API Remove deprecated code (#10594)

This commit is contained in:
Sabina Talipova 2022-12-08 10:44:47 +13:00 committed by GitHub
parent 809bc51661
commit 53c0147f11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
110 changed files with 90 additions and 5558 deletions

View File

@ -176,8 +176,6 @@ mappings:
SS_ClassManifest: SilverStripe\Core\Manifest\ClassManifest
SilverStripe\Core\Manifest\SS_ClassManifest: SilverStripe\Core\Manifest\ClassManifest
ManifestFileFinder: SilverStripe\Core\Manifest\ManifestFileFinder
ErrorControlChain: SilverStripe\Core\Startup\ErrorControlChain
ParameterConfirmationToken: SilverStripe\Core\Startup\ParameterConfirmationToken
DatabaseAdapterRegistry: SilverStripe\Dev\Install\DatabaseAdapterRegistry
DatabaseConfigurationHelper: SilverStripe\Dev\Install\DatabaseConfigurationHelper
MySQLDatabaseConfigurationHelper: SilverStripe\Dev\Install\MySQLDatabaseConfigurationHelper
@ -192,7 +190,6 @@ mappings:
CliDebugView: SilverStripe\Dev\CliDebugView
CSSContentParser: SilverStripe\Dev\CSSContentParser
CsvBulkLoader: SilverStripe\Dev\CsvBulkLoader
CSVParser: SilverStripe\Dev\CSVParser
Debug: SilverStripe\Dev\Debug
DebugView: SilverStripe\Dev\DebugView
Deprecation: SilverStripe\Dev\Deprecation
@ -201,7 +198,6 @@ mappings:
FixtureBlueprint: SilverStripe\Dev\FixtureBlueprint
FixtureFactory: SilverStripe\Dev\FixtureFactory
FunctionalTest: SilverStripe\Dev\FunctionalTest
InstallerTest: SilverStripe\Dev\InstallerTest
MigrationTask: SilverStripe\Dev\MigrationTask
SapphireTest: SilverStripe\Dev\SapphireTest
TaskRunner: SilverStripe\Dev\TaskRunner
@ -229,17 +225,13 @@ mappings:
NestedController: SilverStripe\Control\NestedController
NullHTTPRequest: SilverStripe\Control\NullHTTPRequest
PjaxResponseNegotiator: SilverStripe\Control\PjaxResponseNegotiator
RequestFilter: SilverStripe\Control\RequestFilter
RequestHandler: SilverStripe\Control\RequestHandler
RequestProcessor: SilverStripe\Control\RequestProcessor
Session: SilverStripe\Control\Session
Email: SilverStripe\Control\Email\Email
Mailer: SilverStripe\Control\Email\Mailer
RSSFeed: SilverStripe\Control\RSS\RSSFeed
RSSFeed_Entry: SilverStripe\Control\RSS\RSSFeed_Entry
CleanupTestDatabasesTask: SilverStripe\Dev\Tasks\CleanupTestDatabasesTask
i18nTextCollectorTask: SilverStripe\Dev\Tasks\i18nTextCollectorTask
MigrateFileTask: SilverStripe\Dev\Tasks\MigrateFileTask
CheckboxField: SilverStripe\Forms\CheckboxField
CheckboxField_Readonly: SilverStripe\Forms\CheckboxField_Readonly
CheckboxSetField: SilverStripe\Forms\CheckboxSetField
@ -372,7 +364,6 @@ mappings:
GenericTemplateGlobalProvider: SilverStripe\View\GenericTemplateGlobalProvider
Requirements: SilverStripe\View\Requirements
Requirements_Backend: SilverStripe\View\Requirements_Backend
Requirements_Minifier: SilverStripe\View\Requirements_Minifier
SSTemplateParseException: SilverStripe\View\SSTemplateParseException
SSTemplateParser: SilverStripe\View\SSTemplateParser
SSViewer_Scope: SilverStripe\View\SSViewer_Scope
@ -487,7 +478,6 @@ mappings:
CsvBulkLoaderTest_Team: SilverStripe\Dev\Tests\CsvBulkLoaderTest\Team
CsvBulkLoaderTest_Player: SilverStripe\Dev\Tests\CsvBulkLoaderTest\Player
CsvBulkLoaderTest_PlayerContract: SilverStripe\Dev\Tests\CsvBulkLoaderTest\PlayerContract
CSVParserTest: SilverStripe\Dev\Tests\CSVParserTest
DeprecationTest_Deprecation: SilverStripe\Dev\Tests\DeprecationTest\TestDeprecation
DeprecationTest: SilverStripe\Dev\Tests\DeprecationTest
DevAdminControllerTest: SilverStripe\Dev\Tests\DevAdminControllerTest
@ -847,11 +837,6 @@ mappings:
ThemeResourceLoaderTest: SilverStripe\Core\Tests\Manifest\ThemeResourceLoaderTest
EmailTest: SilverStripe\Control\Tests\Email\EmailTest
MailerTest: SilverStripe\Control\Tests\Email\SwiftMailerTest
ErrorControlChainTest_Chain: SilverStripe\Core\Tests\Startup\ErrorControlChainTest\ErrorControlChainTest_Chain
ErrorControlChainTest: SilverStripe\Core\Tests\Startup\ErrorControlChainTest
ParameterConfirmationTokenTest_Token: SilverStripe\Core\Tests\Startup\ParameterConfirmationTokenTest\ParameterConfirmationTokenTest_Token
ParameterConfirmationTokenTest_ValidToken: SilverStripe\Core\Tests\Startup\ParameterConfirmationTokenTest\ParameterConfirmationTokenTest_ValidToken
ParameterConfirmationTokenTest: SilverStripe\Core\Tests\Startup\ParameterConfirmationTokenTest
ConfigTest_DefinesFoo: SilverStripe\Core\Tests\Config\ConfigTest\DefinesFoo
ConfigTest_DefinesBar: SilverStripe\Core\Tests\Config\ConfigTest\DefinesBar
ConfigTest_DefinesFooAndBar: SilverStripe\Core\Tests\Config\ConfigTest\DefinesFooAndBar
@ -981,8 +966,6 @@ warnings:
message: 'Renamed to CMSMain_TreeNode'
'HTMLEditorField_Toolbar':
message: 'replaced With SilverStripe\Admin\ModalController'
'HTMLEditorField_Embed':
message: 'replaced with SilverStripe\View\Embed\EmbedResource'
'HTMLEditorField_File':
message: 'Removed'
'HTMLEditorField_Flash':
@ -1009,14 +992,8 @@ warnings:
message: 'Use SilverStripe\CMS\BatchActions\CMSBatchAction_Archive instead'
'EncryptAllPasswordsTask':
message: 'Removed'
'SapphireInfo':
message: 'Removed'
'SilverStripe\Dev\SapphireREPL':
message: 'Removed'
'SilverStripe\Dev\SapphireInfo':
message: 'Deprecated'
'SilverStripe\Dev\InstallerTest':
message: 'Deprecated'
methods:
'SilverStripe\Security\Authenticator::register()':
message: 'Custom authenticators work differently now'
@ -1309,12 +1286,6 @@ warnings:
message: 'Removed SilverStripe\ORM\FieldType\DBDate->day_before()'
'days_between()':
message: 'Removed SilverStripe\ORM\FieldType\DBDate->days_between()'
'SilverStripe\Security\Permission::get_declared_permissions_list()':
message: 'Deprecated'
'SilverStripe\Security\Permission::get_label_for_permission()':
message: 'Deprecated'
'SilverStripe\Security\Permission::traverse_declared_permissions()':
message: 'Deprecated'
'SilverStripe\Control\Session::get_all()':
message: 'Session can not be accessed statically and `get_all()` is now called `getAll()'
'SilverStripe\Control\Session::clear_all()':
@ -1336,10 +1307,6 @@ warnings:
message: 'Renamed to combineFiles'
replacement: 'combineFiles'
url: 'https://docs.silverstripe.org/en/4/changelogs/4.0.0#requirements'
'SilverStripe\View\Requirements_Backend->combine_js_with_min':
message: 'Renamed to $minifyCombinedFiles'
url: 'https://docs.silverstripe.org/en/4/changelogs/4.0.0#requirements'
replacement: 'minifyCombinedFiles'
'SilverStripe\View\Requirements_Backend->write_header_comments':
message: 'Renamed to writeHeaderComment'
url: 'https://docs.silverstripe.org/en/4/changelogs/4.0.0#requirements'
@ -1350,12 +1317,6 @@ warnings:
replacement: 'writeJavascriptToBody'
'SilverStripe\Forms\Formfield->dontEscape':
message: 'FormField::$dontEscape has been removed. Escaping is now managed on a class by class basis.'
'SilverStripe\Security\LoginForm->authenticator_class':
message: 'authenticator_class is deprecated. Use getAuthenticatorClass/setAuthenticatorClass.'
'SilverStripe\Security\Permission->declared_permissions':
message: 'Deprecated'
'SilverStripe\Security\Permission->declared_permissions_list':
message: 'Deprecated'
functions:
'file_get_contents()':
message: 'Use new asset abstraction'
@ -1428,8 +1389,6 @@ visibilities:
visibility: private
'SilverStripe\ORM\DataObject::default_classname':
visibility: private
'SilverStripe\ORM\DataObject->destroyed':
visibility: public
'SilverStripe\ORM\DataObject->record':
visibility: protected
'SilverStripe\ORM\DataObject->joinRecord':

View File

@ -12,9 +12,6 @@ SilverStripe\Dev\Backtrace:
- ['SilverStripe\Control\Middleware\ConfirmationMiddleware\GetParameter', buildConfirmationItem]
- ['SilverStripe\Control\Middleware\ConfirmationMiddleware\Url', buildConfirmationItem]
- ['SilverStripe\Control\Middleware\ConfirmationMiddleware\UrlPathStartswith', buildConfirmationItem]
- ['SilverStripe\Core\Startup\AbstractConfirmationToken', 'checkToken']
- ['SilverStripe\Core\Startup\AbstractConfirmationToken', 'pathForToken']
- ['SilverStripe\Core\Startup\AbstractConfirmationToken', 'prepare_tokens']
- ['SilverStripe\ORM\DB', 'connect']
- ['SilverStripe\ORM\DB', 'createDatabase']
- ['SilverStripe\Security\Confirmation\Item', '__construct']
@ -33,9 +30,7 @@ SilverStripe\Dev\Backtrace:
- ['SilverStripe\Security\PasswordEncryptor_Blowfish', 'encryptY']
- ['SilverStripe\Security\PasswordValidator', 'validate']
- ['SilverStripe\Security\RememberLoginHash', 'setToken']
- ['SilverStripe\Security\Security', 'check_default_admin']
- ['SilverStripe\Security\Security', 'encrypt_password']
- ['SilverStripe\Security\Security', 'setDefaultAdmin']
- ['*', 'checkPassword']
- ['*', 'onAfterChangePassword']
- ['*', 'onBeforeChangePassword']

View File

@ -3,13 +3,12 @@ Name: requestprocessors
---
SilverStripe\Core\Injector\Injector:
SilverStripe\Control\Director:
# Note: Don't add 'class' config here, as it will affect ErrorDirector as well
# Note: Don't add 'class' config here
properties:
Middlewares:
TrustedProxyMiddleware: '%$SilverStripe\Control\Middleware\TrustedProxyMiddleware'
AllowedHostsMiddleware: '%$SilverStripe\Control\Middleware\AllowedHostsMiddleware'
SessionMiddleware: '%$SilverStripe\Control\Middleware\SessionMiddleware'
RequestProcessorMiddleware: '%$SilverStripe\Control\RequestProcessor'
FlushMiddleware: '%$SilverStripe\Control\Middleware\FlushMiddleware'
ChangeDetectionMiddleware: '%$SilverStripe\Control\Middleware\ChangeDetectionMiddleware'
HTTPCacheControleMiddleware: '%$SilverStripe\Control\Middleware\HTTPCacheControlMiddleware'
@ -33,16 +32,6 @@ SilverStripe\Core\Injector\Injector:
Middlewares:
- '%$SecurityRateLimitMiddleware'
---
Name: errorrequestprocessors
After:
- '#requestprocessors'
---
SilverStripe\Core\Injector\Injector:
# Note: If Director config changes, take note it will affect this config too
SilverStripe\Core\Startup\ErrorDirector: '%$SilverStripe\Control\Director'
---
Name: canonicalurls
---

View File

@ -4,10 +4,7 @@ namespace SilverStripe\Control;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\Security\BasicAuth;
use SilverStripe\Security\BasicAuthMiddleware;
use SilverStripe\Security\Member;
use SilverStripe\Security\Security;
use SilverStripe\View\SSViewer;
@ -62,13 +59,6 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
*/
protected $templates = [];
/**
* @deprecated 4.1.0:5.0.0 Add this controller's url to
* SilverStripe\Security\BasicAuthMiddleware.URLPatterns injected property instead of setting false
* @var bool
*/
protected $basicAuthEnabled = true;
/**
* The response object that the controller returns.
*
@ -106,11 +96,6 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
*/
protected function init()
{
// @todo This will be removed in 5.0 and will be controlled by middleware instead
if ($this->basicAuthEnabled) {
BasicAuth::protect_site_if_necessary();
}
// This is used to test that subordinate controllers are actually calling parent::init() - a common bug
$this->baseInitCalled = true;
}
@ -523,19 +508,6 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
return $template->process($obj);
}
/**
* Call this to disable site-wide basic authentication for a specific controller. This must be
* called before Controller::init(). That is, you must call it in your controller's init method
* before it calls parent::init().
*
* @deprecated 4.1.0 Add this controller's url to SilverStripe\Security\BasicAuthMiddleware.URLPatterns injected property instead
*/
public function disableBasicAuth()
{
Deprecation::notice('4.1.0', 'Add this controller\'s url to SilverStripe\Security\BasicAuthMiddleware.URLPatterns injected property instead');
$this->basicAuthEnabled = false;
}
/**
* Returns the current controller.
*

View File

@ -2,7 +2,6 @@
namespace SilverStripe\Control;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\FieldType\DBDatetime;
use LogicException;

View File

@ -12,7 +12,6 @@ use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Kernel;
use SilverStripe\Core\Path;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Versioned\Versioned;
use SilverStripe\View\Requirements;
use SilverStripe\View\Requirements_Backend;
@ -375,34 +374,6 @@ class Director implements TemplateGlobalProvider
return $response;
}
/**
* Returns indication whether the manifest cache has been flushed
* in the beginning of the current request.
*
* That could mean the current active request has `?flush` parameter.
* Another possibility is a race condition when the current request
* hits the server in between another request `?flush` authorisation
* and a redirect to the actual flush.
*
* @return bool
*
* @deprecated 4.12.0 Use Kernel::isFlushed instead
*/
public static function isManifestFlushed()
{
Deprecation::notice('4.12.0', 'Use Kernel::isFlushed instead');
$kernel = Injector::inst()->get(Kernel::class);
// Only CoreKernel implements this method at the moment
// Introducing it to the Kernel interface is a breaking change
if (method_exists($kernel, 'isFlushed')) {
return $kernel->isFlushed();
}
$classManifest = $kernel->getClassLoader()->getManifest();
return $classManifest->isFlushed();
}
/**
* Return the {@link SiteTree} object that is currently being viewed. If there is no SiteTree
* object to return, then this will return the current controller.
@ -433,19 +404,9 @@ class Director implements TemplateGlobalProvider
* - BASE - Append this path to the base url (i.e. behaves as though `<base>` tag is provided in a html document). This is the default.
* - REQUEST - Resolve this path to the current url (i.e. behaves as though no `<base>` tag is provided in a html document)
* - ROOT - Treat this as though it was an absolute path, and append it to the protocol and hostname.
*
* @param string $url The url or path to resolve to absolute url.
* @param string $relativeParent Disambiguation method to use for evaluating relative paths
* @return string The absolute url
*/
public static function absoluteURL($url, $relativeParent = self::BASE)
public static function absoluteURL(string $url, string $relativeParent = self::BASE): string|bool
{
if (is_bool($relativeParent)) {
// Deprecate old boolean second parameter
Deprecation::notice('5.0', 'Director::absoluteURL takes an explicit parent for relative url');
$relativeParent = $relativeParent ? self::BASE : self::REQUEST;
}
// Check if there is already a protocol given
if (preg_match('/^http(s?):\/\//', $url ?? '')) {
return $url;
@ -1151,7 +1112,7 @@ class Director implements TemplateGlobalProvider
'isLive',
'is_ajax',
'isAjax' => 'is_ajax',
'BaseHref' => 'absoluteBaseURL', //@deprecated 3.0
'BaseHref' => 'absoluteBaseURL',
];
}

View File

@ -1,16 +0,0 @@
<?php
namespace SilverStripe\Control\Email;
/**
* @deprecated 4.12.0 Will be replaced with symfony/mailer
*/
interface Mailer
{
/**
* @param Email $email
* @return bool
*/
public function send($email);
}

View File

@ -3,15 +3,11 @@
namespace SilverStripe\Control;
use SilverStripe\Assets\File;
use SilverStripe\Control\Middleware\ChangeDetectionMiddleware;
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Convert;
use InvalidArgumentException;
use finfo;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation;
/**
* A class with HTTP-related helpers. Like Debug, this is more a bundle of methods than a class.
@ -20,39 +16,6 @@ class HTTP
{
use Configurable;
/**
* @deprecated 4.2.0:5.0.0 Use HTTPCacheControlMiddleware::singleton()->setMaxAge($age) instead
* @var int
*/
protected static $cache_age = 0;
/**
* @deprecated 4.2.0:5.0.0 Handled by HTTPCacheControlMiddleware
* @var int
*/
protected static $modification_date = null;
/**
* @deprecated 4.2.0:5.0.0 Handled by ChangeDetectionMiddleware
* @var string
*/
protected static $etag = null;
/**
* @config
* @var bool
* @deprecated 4.2.0:5.0.0 'HTTP.cache_ajax_requests config is deprecated.
* Use HTTPCacheControlMiddleware::disableCache() instead'
*/
private static $cache_ajax_requests = false;
/**
* @config
* @var bool
* @deprecated 4.2.0:5.0.0 Use HTTPCacheControlMiddleware.defaultState/.defaultForcingLevel instead
*/
private static $disable_http_cache = false;
/**
* Set to true to disable all deprecated HTTP Cache settings
*
@ -68,25 +31,6 @@ class HTTP
*/
private static $MimeTypes = [];
/**
* List of names to add to the Cache-Control header.
*
* @deprecated 4.2.0:5.0.0 Handled by HTTPCacheControlMiddleware instead
* @see HTTPCacheControlMiddleware::__construct()
* @config
* @var array Keys are cache control names, values are boolean flags
*/
private static $cache_control = [];
/**
* Vary string; A comma separated list of var header names
*
* @deprecated 4.2.0:5.0.0 Handled by HTTPCacheControlMiddleware instead
* @config
* @var string|null
*/
private static $vary = null;
/**
* Turns a local system filename into a URL by comparing it to the script filename.
*
@ -368,217 +312,4 @@ class HTTP
return $mimeTypes[$ext];
}
/**
* Set the maximum age of this page in web caches, in seconds.
*
* @deprecated 4.2.0 Use HTTPCacheControlMiddleware::singleton()->setMaxAge($age) instead
* @param int $age
*/
public static function set_cache_age($age)
{
Deprecation::notice('4.2.0', 'Use HTTPCacheControlMiddleware::singleton()->setMaxAge($age) instead');
self::$cache_age = $age;
HTTPCacheControlMiddleware::singleton()->setMaxAge($age);
}
/**
* @param string $dateString
* @deprecated 4.2.0 Use HTTPCacheControlMiddleware::registerModificationDate() instead
*/
public static function register_modification_date($dateString)
{
Deprecation::notice('4.2.0', 'Use HTTPCacheControlMiddleware::registerModificationDate() instead');
HTTPCacheControlMiddleware::singleton()->registerModificationDate($dateString);
}
/**
* @param int $timestamp
* @deprecated 4.2.0 Use HTTPCacheControlMiddleware::registerModificationDate() instead
*/
public static function register_modification_timestamp($timestamp)
{
Deprecation::notice('4.2.0', 'Use HTTPCacheControlMiddleware::registerModificationDate() instead');
HTTPCacheControlMiddleware::singleton()->registerModificationDate($timestamp);
}
/**
* @deprecated 4.2.0 Use ChangeDetectionMiddleware instead
* @param string $etag
*/
public static function register_etag($etag)
{
Deprecation::notice('4.2.0', 'Use ChangeDetectionMiddleware instead');
if (strpos($etag ?? '', '"') !== 0) {
$etag = "\"{$etag}\"";
}
self::$etag = $etag;
}
/**
* Add the appropriate caching headers to the response, including If-Modified-Since / 304 handling.
* Note that setting HTTP::$cache_age will overrule any cache headers set by PHP's
* session_cache_limiter functionality. It is your responsibility to ensure only cacheable data
* is in fact cached, and HTTP::$cache_age isn't set when the HTTP body contains session-specific
* content.
*
* Omitting the $body argument or passing a string is deprecated; in these cases, the headers are
* output directly.
*
* @param HTTPResponse $response
* @deprecated 4.2.0 Headers are added automatically by HTTPCacheControlMiddleware instead.
*/
public static function add_cache_headers($response = null)
{
Deprecation::notice('4.2.0', 'Headers are added automatically by HTTPCacheControlMiddleware instead.');
// Skip if deprecated API is disabled
if (Config::inst()->get(HTTP::class, 'ignoreDeprecatedCaching')) {
return;
}
// Ensure a valid response object is provided
if (!$response instanceof HTTPResponse) {
user_error("HTTP::add_cache_headers() must be passed an HTTPResponse object", E_USER_WARNING);
return;
}
// Warn if already assigned cache-control headers
if ($response->getHeader('Cache-Control')) {
trigger_error(
'Cache-Control header has already been set. '
. 'Please use HTTPCacheControlMiddleware API to set caching options instead.',
E_USER_WARNING
);
return;
}
// Ensure a valid request object exists in the current context
if (!Injector::inst()->has(HTTPRequest::class)) {
user_error("HTTP::add_cache_headers() cannot work without a current HTTPRequest object", E_USER_WARNING);
return;
}
/** @var HTTPRequest $request */
$request = Injector::inst()->get(HTTPRequest::class);
// Run middleware
ChangeDetectionMiddleware::singleton()->process($request, function (HTTPRequest $request) use ($response) {
return HTTPCacheControlMiddleware::singleton()->process($request, function (HTTPRequest $request) use ($response) {
return $response;
});
});
}
/**
* 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
*/
public static function augmentState(HTTPRequest $request, HTTPResponse $response)
{
Deprecation::notice('4.2.0', 'Use HTTPCacheControlMiddleware instead');
// Skip if deprecated API is disabled
$config = Config::forClass(HTTP::class);
if ($config->get('ignoreDeprecatedCaching')) {
return;
}
$cacheControlMiddleware = HTTPCacheControlMiddleware::singleton();
// 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
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
Deprecation::withNoReplacement(function () use ($config, $cacheControlMiddleware) {
if (!$config->get('cache_ajax_requests') && Director::is_ajax()) {
$cacheControlMiddleware->disableCache();
}
});
// Pass vary to middleware
$configVary = Deprecation::withNoReplacement(function () use ($config) {
return $config->get('vary');
});
if ($configVary) {
$cacheControlMiddleware->addVary($configVary);
}
// Pass cache_control to middleware
$configCacheControl = Deprecation::withNoReplacement(function () use ($config) {
return $config->get('cache_control');
});
if ($configCacheControl) {
$supportedDirectives = ['max-age', 'no-cache', 'no-store', 'must-revalidate'];
if ($foundUnsupported = array_diff(array_keys($configCacheControl ?? []), $supportedDirectives)) {
throw new \LogicException(
'Found unsupported legacy directives in HTTP.cache_control: ' .
implode(', ', $foundUnsupported) .
'. Please use HTTPCacheControlMiddleware API instead'
);
}
if (isset($configCacheControl['max-age'])) {
$cacheControlMiddleware->setMaxAge($configCacheControl['max-age']);
}
if (isset($configCacheControl['no-cache'])) {
$cacheControlMiddleware->setNoCache((bool)$configCacheControl['no-cache']);
}
if (isset($configCacheControl['no-store'])) {
$cacheControlMiddleware->setNoStore((bool)$configCacheControl['no-store']);
}
if (isset($configCacheControl['must-revalidate'])) {
$cacheControlMiddleware->setMustRevalidate((bool)$configCacheControl['must-revalidate']);
}
}
// Set modification date
if (self::$modification_date) {
Deprecation::notice('5.0', 'Use HTTPCacheControlMiddleware::registerModificationDate() instead');
$cacheControlMiddleware->registerModificationDate(self::$modification_date);
}
// Ensure deprecated $etag property is assigned
if (self::$etag && !$cacheControlMiddleware->hasDirective('no-store') && !$response->getHeader('ETag')) {
Deprecation::notice('5.0', 'Etag should not be set explicitly');
$response->addHeader('ETag', self::$etag);
}
}
/**
* Return an {@link http://www.faqs.org/rfcs/rfc2822 RFC 2822} date in the GMT timezone (a timestamp
* is always in GMT: the number of seconds since January 1 1970 00:00:00 GMT)
*
* @param int $timestamp
* @deprecated 4.2.0 Use native php function gmdate() instead
* @return string
*/
public static function gmt_date($timestamp)
{
Deprecation::notice('4.2.0', 'Use native php function gmdate() instead');
return gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
}
/**
* Return static variable cache_age in second
*
* @return int
*/
public static function get_cache_age()
{
return self::$cache_age;
}
}

View File

@ -13,9 +13,6 @@ use SilverStripe\Core\Startup\RequestFlushDiscoverer;
use SilverStripe\Core\Startup\ScheduledFlushDiscoverer;
use SilverStripe\Core\Startup\DeployFlushDiscoverer;
/**
* Invokes the HTTP application within an ErrorControlChain
*/
class HTTPApplication implements Application
{
use HTTPMiddlewareAware;

View File

@ -2,7 +2,6 @@
namespace SilverStripe\Control;
use SilverStripe\Dev\Deprecation;
use ArrayAccess;
use BadMethodCallException;
use InvalidArgumentException;
@ -903,28 +902,6 @@ class HTTPRequest implements ArrayAccess
return in_array(strtoupper($method ?? ''), ['GET','POST','PUT','DELETE','HEAD']);
}
/**
* Gets the "real" HTTP method for a request. This method is no longer used to mitigate the risk of web cache
* poisoning.
*
* @see https://www.silverstripe.org/download/security-releases/CVE-2019-19326
* @param string $origMethod Original HTTP method from the browser request
* @param array $postVars
* @return string HTTP method (all uppercase)
* @deprecated 4.4.7 Will be removed without equivalent functionality
*/
public static function detect_method($origMethod, $postVars)
{
Deprecation::notice('4.4.7', 'Will be removed without equivalent functionality');
if (isset($postVars['_method'])) {
if (!self::isValidHttpMethod($postVars['_method'])) {
throw new InvalidArgumentException('HTTPRequest::detect_method(): Invalid "_method" parameter');
}
return strtoupper($postVars['_method'] ?? '');
}
return $origMethod;
}
/**
* Determines whether the request has a session
*

View File

@ -3,7 +3,6 @@
namespace SilverStripe\Control\Middleware;
use InvalidArgumentException;
use SilverStripe\Control\HTTP;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPResponse_Exception;
@ -12,7 +11,6 @@ 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,11 +49,6 @@ class HTTPCacheControlMiddleware implements HTTPMiddleware, Resettable
// Update state based on current request and response objects
$this->augmentState($request, $response);
// Update state based on deprecated HTTP settings
Deprecation::withNoReplacement(function () use ($request, $response) {
HTTP::augmentState($request, $response);
});
// Add all headers to this response object
$this->applyToResponse($response);

View File

@ -1,32 +0,0 @@
<?php
namespace SilverStripe\Control;
/**
* A request filter is an object that's executed before and after a
* request occurs. By returning 'false' from the preRequest method,
* request execution will be stopped from continuing
*
* @author marcus@silverstripe.com.au
* @license BSD License http://silverstripe.org/bsd-license/
* @deprecated 4.0.0:5.0.0 Use HTTPMiddleware instead
*/
interface RequestFilter
{
/**
* Filter executed before a request processes
*
* @param HTTPRequest $request Request container object
* @return boolean Whether to continue processing other filters. Null or true will continue processing (optional)
*/
public function preRequest(HTTPRequest $request);
/**
* Filter executed AFTER a request
*
* @param HTTPRequest $request Request container object
* @param HTTPResponse $response
* @return bool Whether to continue processing other filters. Null or true will continue processing (optional)
*/
public function postRequest(HTTPRequest $request, HTTPResponse $response);
}

View File

@ -1,80 +0,0 @@
<?php
namespace SilverStripe\Control;
use SilverStripe\Control\Middleware\HTTPMiddleware;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Dev\Deprecation;
/**
* Middleware that provides back-support for the deprecated RequestFilter API.
*
* @deprecated 4.0.1 Use HTTPMiddleware directly instead.
*/
class RequestProcessor implements HTTPMiddleware
{
use Injectable;
/**
* List of currently assigned request filters
*
* @var RequestFilter[]
*/
private $filters = [];
/**
* Construct new RequestFilter with a list of filter objects
*
* @param RequestFilter[] $filters
*/
public function __construct($filters = [])
{
Deprecation::withNoReplacement(function () {
Deprecation::notice('4.0.1', 'Use HTTPMiddleware directly instead.', Deprecation::SCOPE_CLASS);
});
$this->filters = $filters;
}
/**
* Assign a list of request filters
*
* @param RequestFilter[] $filters
* @return $this
*/
public function setFilters($filters)
{
$this->filters = $filters;
return $this;
}
/**
* @inheritdoc
*/
public function process(HTTPRequest $request, callable $delegate)
{
if ($this->filters) {
Deprecation::notice(
'5.0',
'Deprecated RequestFilters are in use. Apply HTTPMiddleware to Director.middlewares instead.'
);
}
foreach ($this->filters as $filter) {
$res = $filter->preRequest($request);
if ($res === false) {
return new HTTPResponse(_t(__CLASS__ . '.INVALID_REQUEST', 'Invalid request'), 400);
}
}
$response = $delegate($request);
foreach ($this->filters as $filter) {
$res = $filter->postRequest($request, $response);
if ($res === false) {
return new HTTPResponse(_t(__CLASS__ . '.REQUEST_ABORTED', 'Request aborted'), 500);
}
}
return $response;
}
}

View File

@ -4,7 +4,6 @@ namespace SilverStripe\Control;
use BadMethodCallException;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Dev\Deprecation;
/**
* Handles all manipulation of the session.

View File

@ -2,7 +2,6 @@
namespace SilverStripe\Control;
use SilverStripe\Dev\Deprecation;
use InvalidArgumentException;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Convert;
@ -79,17 +78,8 @@ class SimpleResourceURLGenerator implements ResourceURLGenerator
list($relativePath, $query) = explode('?', $relativePath ?? '');
}
// Determine lookup mechanism based on existence of public/ folder.
// From 5.0 onwards only resolvePublicResource() will be used.
if (!Director::publicDir()) {
$ret = Deprecation::withNoReplacement(function () use ($relativePath) {
return $this->resolveUnsecuredResource($relativePath);
});
list($exists, $absolutePath, $relativePath) = $ret;
} else {
list($exists, $absolutePath, $relativePath) = $this->resolvePublicResource($relativePath);
}
}
if (!$exists) {
trigger_error("File {$relativePath} does not exist", E_USER_NOTICE);
}
@ -160,36 +150,6 @@ class SimpleResourceURLGenerator implements ResourceURLGenerator
return [$exists, $absolutePath, $relativePath];
}
/**
* Resolve resource in the absence of a public/ folder
*
* @deprecated 4.1.0 Will be removed without equivalent functionality when public/ folder becomes mandatory
* @param string $relativePath
* @return array List of [$exists, $absolutePath, $relativePath]
*/
protected function resolveUnsecuredResource($relativePath)
{
Deprecation::notice('4.1.0', 'Will be removed without equivalent functionality when public/ folder becomes mandatory');
// Check if the path requested is public-only, but we have no public folder
$publicOnly = $this->inferPublicResourceRequired($relativePath);
if ($publicOnly) {
trigger_error('Requesting a public resource without a public folder has no effect', E_USER_WARNING);
}
// Resolve path to base
$absolutePath = Path::join(Director::baseFolder(), $relativePath);
$exists = file_exists($absolutePath ?? '');
// Rewrite vendor/ to _resources/ folder
if (stripos($relativePath ?? '', ManifestFileFinder::VENDOR_DIR . DIRECTORY_SEPARATOR) === 0) {
$relativePath = Path::join(
RESOURCES_DIR,
substr($relativePath ?? '', strlen(ManifestFileFinder::VENDOR_DIR ?? ''))
);
}
return [$exists, $absolutePath, $relativePath];
}
/**
* Determine if the requested $relativePath requires a public-only resource.
* An error will occur if this file isn't immediately available in the public/ assets folder.

View File

@ -7,7 +7,6 @@ use ReflectionClass;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Control\Director;
use SilverStripe\Core\Manifest\ClassLoader;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DB;
use SilverStripe\View\ViewableData;
@ -155,17 +154,6 @@ class ClassInfo
});
}
/**
* @deprecated 4.0.1 Use DataObject::getSchema()->baseDataClass()
* @param string $class
* @return string
*/
public static function baseDataClass($class)
{
Deprecation::notice('4.0.1', 'Use DataObject::getSchema()->baseDataClass()');
return DataObject::getSchema()->baseDataClass($class);
}
/**
* Returns a list of classes that inherit from the given class.
* The resulting array includes the base class passed
@ -370,15 +358,6 @@ class ClassInfo
return strtolower(self::$_cache_methods[$lClass][$lMethod] ?? '') === $lCompclass;
}
/**
* @deprecated 4.0.1 Use DataObject::getSchema()->tableForField()
*/
public static function table_for_object_field($candidateClass, $fieldName)
{
Deprecation::notice('4.0.1', 'Use DataObject::getSchema()->tableForField()');
return DataObject::getSchema()->tableForField($candidateClass, $fieldName);
}
/**
* Strip namespace from class
*

View File

@ -2,8 +2,6 @@
namespace SilverStripe\Core\Config;
use SilverStripe\Dev\Deprecation;
class Config_ForClass
{
/**
@ -37,20 +35,6 @@ class Config_ForClass
$this->set($name, $val);
}
/**
* Explicit pass-through to Config::update()
*
* @param string $name
* @param mixed $value
* @return $this
* @deprecated 4.12.0 Use merge() instead
*/
public function update($name, $value)
{
Deprecation::notice('4.12.0', 'Use merge() instead');
return $this->merge($name, $value);
}
/**
* Merge a given config
*

View File

@ -2,8 +2,6 @@
namespace SilverStripe\Core\Config;
use SilverStripe\Dev\Deprecation;
/**
* Provides extensions to this object to integrate it with standard config API methods.
*
@ -22,19 +20,6 @@ trait Configurable
return Config::forClass(get_called_class());
}
/**
* Get inherited config value
*
* @deprecated 5.0 Use ->config()->get() instead
* @param string $name
* @return mixed
*/
public function stat($name)
{
Deprecation::notice('5.0', 'Use ->get');
return $this->config()->get($name);
}
/**
* Gets the uninherited value for the given config option
*
@ -45,19 +30,4 @@ trait Configurable
{
return $this->config()->uninherited($name);
}
/**
* Update the config value for a given property
*
* @deprecated 5.0 Use ->config()->set() instead
* @param string $name
* @param mixed $value
* @return $this
*/
public function set_stat($name, $value)
{
Deprecation::notice('5.0', 'Use ->config()->set()');
$this->config()->set($name, $value);
return $this;
}
}

View File

@ -2,9 +2,7 @@
namespace SilverStripe\Core;
use InvalidArgumentException;
use SimpleXMLElement;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\DB;
use SilverStripe\View\Parsers\URLSegmentFilter;
@ -157,37 +155,6 @@ class Convert
);
}
/**
* Encode a value as a JSON encoded string. You can optionally pass a bitmask of
* JSON constants as options through to the encode function.
*
* @deprecated 4.4.0 Use json_encode() instead
* @param mixed $val Value to be encoded
* @param int $options Optional bitmask of JSON constants
* @return string JSON encoded string
*/
public static function raw2json($val, $options = 0)
{
Deprecation::notice('4.4.0', 'Use json_encode() instead');
return json_encode($val, $options ?? 0);
}
/**
* Encode an array as a JSON encoded string.
*
* @deprecated 4.4.0 Use json_encode() instead
* @param array $val Array to convert
* @param int $options Optional bitmask of JSON constants
* @return string JSON encoded string
*/
public static function array2json($val, $options = 0)
{
Deprecation::notice('4.4.0', 'Use json_encode() instead');
return json_encode($val, $options ?? 0);
}
/**
* Safely encodes a value (or list of values) using the current database's
* safe string encoding method
@ -258,75 +225,9 @@ class Convert
return html_entity_decode($val ?? '', ENT_QUOTES, 'UTF-8');
}
/**
* Convert a JSON encoded string into an object.
*
* @deprecated 4.4.0 Use json_decode() instead
* @param string $val
* @return object|boolean
*/
public static function json2obj($val)
{
Deprecation::notice('4.4.0', 'Use json_decode() instead');
return json_decode($val ?? '');
}
/**
* Convert a JSON string into an array.
*
* @deprecated 4.4.0 Use json_decode($val, true) instead
* @param string $val JSON string to convert
* @return array|boolean
*/
public static function json2array($val)
{
Deprecation::notice('4.4.0', 'Use json_decode() instead');
return json_decode($val ?? '', true);
}
/**
* Converts an XML string to a PHP array
* See http://phpsecurity.readthedocs.org/en/latest/Injection-Attacks.html#xml-external-entity-injection
*
* @uses recursiveXMLToArray()
* @param string $val
* @param boolean $disableDoctypes Disables the use of DOCTYPE, and will trigger an error if encountered.
* false by default.
* @param boolean $disableExternals Does nothing because xml entities are removed
* @deprecated 4.11.0 Use a dedicated XML library instead
* @return array
* @throws Exception
*/
public static function xml2array($val, $disableDoctypes = false, $disableExternals = false)
{
Deprecation::notice('4.11.0', 'Use a dedicated XML library instead');
// Check doctype
if ($disableDoctypes && strpos($val ?? '', '<!DOCTYPE') !== false) {
throw new InvalidArgumentException('XML Doctype parsing disabled');
}
// CVE-2021-41559 Ensure entities are removed due to their inherent security risk via
// XXE attacks and quadratic blowup attacks, and also lack of consistent support
$val = preg_replace('/(?s)<!ENTITY.*?>/', '', $val ?? '');
// If there's still an <!ENTITY> present, then it would be the result of a maliciously
// crafted XML document e.g. <!ENTITY><!<!ENTITY>ENTITY ext SYSTEM "http://evil.com">
if (strpos($val ?? '', '<!ENTITY') !== false) {
throw new InvalidArgumentException('Malicious XML entity detected');
}
// This will throw an exception if the XML contains references to any internal entities
// that were defined in an <!ENTITY /> before it was removed
$xml = new SimpleXMLElement($val ?? '');
return self::recursiveXMLToArray($xml);
}
/**
* Convert a XML string to a PHP array recursively. Do not
* call this function directly, Please use {@link Convert::xml2array()}
* call this function directly.
*
* @param SimpleXMLElement $xml
*

View File

@ -5,7 +5,6 @@ namespace SilverStripe\Core;
use InvalidArgumentException;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation;
use SilverStripe\View\ViewableData;
/**

View File

@ -8,11 +8,9 @@ use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use ReflectionMethod;
use ReflectionObject;
use ReflectionProperty;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Environment;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\DataObject;
/**
@ -853,18 +851,6 @@ class Injector implements ContainerInterface
}
}
/**
* @deprecated 4.0.1 Use Injector::has() instead
* @param $name
* @return string
*/
public function hasService($name)
{
Deprecation::notice('4.0.1', 'Use Injector::has() instead');
return $this->has($name);
}
/**
* Does the given service exist?
*

View File

@ -4,21 +4,14 @@ namespace SilverStripe\Core\Manifest;
use Exception;
use InvalidArgumentException;
use Serializable;
use SilverStripe\Core\Path;
use SilverStripe\Dev\Deprecation;
/**
* Abstraction of a PHP Package. Can be used to retrieve information about Silverstripe CMS modules, and other packages
* managed via composer, by reading their `composer.json` file.
*/
class Module implements Serializable
class Module
{
/**
* @deprecated 4.1.0:5.0.0 Use Path::normalise() instead
*/
const TRIM_CHARS = ' /\\';
/**
* Full directory path to this module with no trailing slash
*
@ -183,33 +176,6 @@ class Module implements Serializable
$this->resources = [];
}
/**
* The __serialize() magic method will be automatically used instead of this
*
* @return string
* @deprecated 4.12.0 Use __serialize() instead
*/
public function serialize()
{
Deprecation::notice('4.12.0', 'Use __serialize() instead');
return json_encode([$this->path, $this->basePath, $this->composerData]);
}
/**
* The __unserialize() magic method will be automatically used instead of this almost all the time
* This method will be automatically used if existing serialized data was not saved as an associative array
* and the PHP version used in less than PHP 9.0
*
* @param string $serialized
* @deprecated 4.12.0 Use __unserialize() instead
*/
public function unserialize($serialized)
{
Deprecation::notice('4.12.0', 'Use __unserialize() instead');
list($this->path, $this->basePath, $this->composerData) = json_decode($serialized ?? '', true);
$this->resources = [];
}
/**
* Activate _config.php for this module, if one exists
*/
@ -256,58 +222,6 @@ class Module implements Serializable
}
return $this->resources[$path] = new ModuleResource($this, $path);
}
/**
* @deprecated 4.0.1 Use getResource($path)->getRelativePath() instead
* @param string $path
* @return string
*/
public function getRelativeResourcePath($path)
{
Deprecation::notice('4.0.1', 'Use getResource($path)->getRelativePath() instead');
return $this
->getResource($path)
->getRelativePath();
}
/**
* @deprecated 4.0.1 Use getResource($path)->getPath() instead
* @param string $path
* @return string
*/
public function getResourcePath($path)
{
Deprecation::notice('4.0.1', 'Use getResource($path)->getPath() instead');
return $this
->getResource($path)
->getPath();
}
/**
* @deprecated 4.0.1 Use getResource($path)->getURL() instead
* @param string $path
* @return string
*/
public function getResourceURL($path)
{
Deprecation::notice('4.0.1', 'Use getResource($path)->getURL() instead');
return $this
->getResource($path)
->getURL();
}
/**
* @deprecated 4.0.1 Use getResource($path)->exists() instead
* @param string $path
* @return string
*/
public function hasResource($path)
{
Deprecation::notice('4.0.1', 'Use getResource($path)->exists() instead');
return $this
->getResource($path)
->exists();
}
}
/**

View File

@ -1,200 +0,0 @@
<?php
namespace SilverStripe\Core\Startup;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Convert;
use SilverStripe\Security\RandomGenerator;
/**
* Shared functionality for token-based authentication of potentially dangerous URLs or query
* string parameters
*
* @internal This class is designed specifically for use pre-startup and may change without warning
*
* @deprecated 4.12.0 Will be removed without equivalent functionality
*/
abstract class AbstractConfirmationToken
{
/**
* @var HTTPRequest
*/
protected $request = null;
/**
* The validated and checked token for this parameter
*
* @var string|null A string value, or null if either not provided or invalid
*/
protected $token = null;
/**
* Given a list of token names, suppress all tokens that have not been validated, and
* return the non-validated token with the highest priority
*
* @param array $keys List of token keys in ascending priority (low to high)
* @param HTTPRequest $request
* @return static The token container for the unvalidated $key given with the highest priority
*/
public function __construct()
{
Deprecation::notice('4.12.0', 'Will be removed without equivalent functionality', Deprecation::SCOPE_CLASS);
}
public static function prepare_tokens($keys, HTTPRequest $request)
{
$target = null;
foreach ($keys as $key) {
$token = new static($key, $request);
// Validate this token
if ($token->reloadRequired() || $token->reloadRequiredIfError()) {
$token->suppress();
$target = $token;
}
}
return $target;
}
/**
* Generate a local filesystem path to store a token
*
* @param $token
* @return string
*/
protected function pathForToken($token)
{
return TEMP_PATH . DIRECTORY_SEPARATOR . 'token_' . preg_replace('/[^a-z0-9]+/', '', $token ?? '');
}
/**
* Generate a new random token and store it
*
* @return string Token name
*/
protected function genToken()
{
// Generate a new random token (as random as possible)
$rg = new RandomGenerator();
$token = $rg->randomToken('md5');
// Store a file in the session save path (safer than /tmp, as open_basedir might limit that)
file_put_contents($this->pathForToken($token) ?? '', $token);
return $token;
}
/**
* Is the necessary token provided for this parameter?
* A value must be provided for the token
*
* @return bool
*/
public function tokenProvided()
{
return !empty($this->token);
}
/**
* Validate a token
*
* @param string $token
* @return boolean True if the token is valid
*/
protected function checkToken($token)
{
if (!$token) {
return false;
}
$file = $this->pathForToken($token);
$content = null;
if (file_exists($file ?? '')) {
$content = file_get_contents($file ?? '');
unlink($file ?? '');
}
return $content === $token;
}
/**
* Get redirect url, excluding querystring
*
* @return string
*/
public function currentURL()
{
return Controller::join_links(Director::baseURL(), $this->request->getURL(false));
}
/**
* Forces a reload of the request with the token included
*
* @return HTTPResponse
*/
public function reloadWithToken()
{
$location = $this->redirectURL();
$locationJS = Convert::raw2js($location);
$locationATT = Convert::raw2att($location);
$body = <<<HTML
<script>location.href='$locationJS';</script>
<noscript><meta http-equiv="refresh" content="0; url=$locationATT"></noscript>
You are being redirected. If you are not redirected soon, <a href="$locationATT">click here to continue</a>
HTML;
// Build response
$result = new HTTPResponse($body);
$result->redirect($location);
return $result;
}
/**
* Is this parameter requested without a valid token?
*
* @return bool True if the parameter is given without a valid token
*/
abstract public function reloadRequired();
/**
* Check if this token is provided either in the backurl, or directly,
* but without a token
*
* @return bool
*/
abstract public function reloadRequiredIfError();
/**
* Suppress the current parameter for the duration of this request
*/
abstract public function suppress();
/**
* Determine the querystring parameters to include
*
* @param bool $includeToken Include the token value?
* @return array List of querystring parameters, possibly including token parameter
*/
abstract public function params($includeToken = true);
/**
* @return string
*/
abstract public function getRedirectUrlBase();
/**
* @return array
*/
abstract public function getRedirectUrlParams();
/**
* Get redirection URL
*
* @return string
*/
abstract protected function redirectURL();
}

View File

@ -1,187 +0,0 @@
<?php
namespace SilverStripe\Core\Startup;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Convert;
/**
* A chain of confirmation tokens to be validated on each request. This allows the application to
* check multiple tokens at once without having to potentially redirect the user for each of them
*
* @internal This class is designed specifically for use pre-startup and may change without warning
*
* @deprecated 4.12.0 Will be removed without equivalent functionality
*/
class ConfirmationTokenChain
{
/**
* @var array
*/
protected $tokens = [];
/**
* @param AbstractConfirmationToken $token
*/
public function __construct()
{
Deprecation::notice('4.12.0', 'Will be removed without equivalent functionality', Deprecation::SCOPE_CLASS);
}
public function pushToken(AbstractConfirmationToken $token)
{
$this->tokens[] = $token;
}
/**
* Collect all tokens that require a redirect
*
* @return \Generator
*/
protected function filteredTokens()
{
foreach ($this->tokens as $token) {
if ($token->reloadRequired() || $token->reloadRequiredIfError()) {
yield $token;
}
}
}
/**
* @return bool
*/
public function suppressionRequired()
{
foreach ($this->tokens as $token) {
if ($token->reloadRequired()) {
return true;
}
}
return false;
}
/**
* Suppress URLs & GET vars from tokens that require a redirect
*/
public function suppressTokens()
{
foreach ($this->filteredTokens() as $token) {
$token->suppress();
}
}
/**
* @return bool
*/
public function reloadRequired()
{
foreach ($this->tokens as $token) {
if ($token->reloadRequired()) {
return true;
}
}
return false;
}
/**
* @return bool
*/
public function reloadRequiredIfError()
{
foreach ($this->tokens as $token) {
if ($token->reloadRequiredIfError()) {
return true;
}
}
return false;
}
/**
* @param bool $includeToken
* @return array
*/
public function params($includeToken = true)
{
$params = [];
foreach ($this->tokens as $token) {
$params = array_merge($params, $token->params($includeToken));
}
return $params;
}
/**
* Fetch the URL we want to redirect to, excluding query string parameters. This may
* be the same URL (with a token to be added outside this method), or to a different
* URL if the current one has been suppressed
*
* @return string
*/
public function getRedirectUrlBase()
{
// URLConfirmationTokens may alter the URL to suppress the URL they're protecting,
// so we need to ensure they're inspected last and therefore take priority
$tokens = iterator_to_array($this->filteredTokens(), false);
usort($tokens, function ($a, $b) {
return ($a instanceof URLConfirmationToken) ? 1 : 0;
});
$urlBase = Director::baseURL();
foreach ($tokens as $token) {
$urlBase = $token->getRedirectUrlBase();
}
return $urlBase;
}
/**
* Collate GET vars from all token providers that need to apply a token
*
* @return array
*/
public function getRedirectUrlParams()
{
$params = $_GET;
unset($params['url']); // CLIRequestBuilder may add this
foreach ($this->filteredTokens() as $token) {
$params = array_merge($params, $token->params());
}
return $params;
}
/**
* @return string
*/
protected function redirectURL()
{
$params = http_build_query($this->getRedirectUrlParams() ?? []);
return Controller::join_links($this->getRedirectUrlBase(), '?' . $params);
}
/**
* @return HTTPResponse
*/
public function reloadWithTokens()
{
$location = $this->redirectURL();
$locationJS = Convert::raw2js($location);
$locationATT = Convert::raw2att($location);
$body = <<<HTML
<script>location.href='$locationJS';</script>
<noscript><meta http-equiv="refresh" content="0; url=$locationATT"></noscript>
You are being redirected. If you are not redirected soon, <a href="$locationATT">click here to continue</a>
HTML;
// Build response
$result = new HTTPResponse($body);
$result->redirect($location);
return $result;
}
}

View File

@ -1,262 +0,0 @@
<?php
namespace SilverStripe\Core\Startup;
use SilverStripe\Dev\Deprecation;
use Exception;
/**
* Class ErrorControlChain
*
* Runs a set of steps, optionally suppressing uncaught errors or exceptions which would otherwise be fatal that
* occur in each step. If an error does occur, subsequent steps are normally skipped, but can optionally be run anyway.
*
* Usage:
*
* $chain = new ErrorControlChain();
* $chain->then($callback1)->then($callback2)->thenIfErrored($callback3)->execute();
*
* @internal This class is designed specifically for use pre-startup and may change without warning
*
* @deprecated 4.12.0 Will be removed without equivalent functionality
*/
class ErrorControlChain
{
public static $fatal_errors = null; // Initialised after class definition
/**
* Is there an error?
*
* @var bool
*/
protected $error = false;
/**
* List of steps
*
* @var array
*/
protected $steps = [];
/**
* True if errors should be hidden
*
* @var bool
*/
protected $suppression = true;
/** We can't unregister_shutdown_function, so this acts as a flag to enable handling */
protected $handleFatalErrors = false;
/** We overload display_errors to hide errors during execution, so we need to remember the original to restore to */
protected $originalDisplayErrors = null;
/**
* Any exceptions passed through the chain
*
* @var Exception
*/
protected $lastException = null;
/**
* Determine if an error has been found
*
* @return bool
*/
public function __construct()
{
Deprecation::notice('4.12.0', 'Will be removed without equivalent functionality', Deprecation::SCOPE_CLASS);
}
public function hasErrored()
{
return $this->error;
}
public function setErrored($error)
{
$this->error = (bool)$error;
}
/**
* Sets whether errors are suppressed or not
* Notes:
* - Errors cannot be suppressed if not handling errors.
* - Errors cannot be un-suppressed if original mode dis-allowed visible errors
*
* @param bool $suppression
*/
public function setSuppression($suppression)
{
$this->suppression = (bool)$suppression;
// If handling fatal errors, conditionally disable, or restore error display
// Note: original value of display_errors could also evaluate to "off"
if ($this->handleFatalErrors) {
if ($suppression) {
$this->setDisplayErrors(0);
} else {
$this->setDisplayErrors($this->originalDisplayErrors);
}
}
}
/**
* Set display_errors
*
* @param mixed $errors
*/
protected function setDisplayErrors($errors)
{
ini_set('display_errors', $errors);
}
/**
* Get value of display_errors ini value
*
* @return mixed
*/
protected function getDisplayErrors()
{
return ini_get('display_errors');
}
/**
* Add this callback to the chain of callbacks to call along with the state
* that $error must be in this point in the chain for the callback to be called
*
* @param $callback - The callback to call
* @param $onErrorState - false if only call if no errors yet, true if only call if already errors, null for either
* @return $this
*/
public function then($callback, $onErrorState = false)
{
$this->steps[] = [
'callback' => $callback,
'onErrorState' => $onErrorState
];
return $this;
}
/**
* Request that the callback is invoked if not errored
*
* @param callable $callback
* @return $this
*/
public function thenWhileGood($callback)
{
return $this->then($callback, false);
}
/**
* Request that the callback is invoked on error
*
* @param callable $callback
* @return $this
*/
public function thenIfErrored($callback)
{
return $this->then($callback, true);
}
/**
* Request that the callback is invoked always
*
* @param callable $callback
* @return $this
*/
public function thenAlways($callback)
{
return $this->then($callback, null);
}
/**
* Return true if the last error was fatal
*
* @return boolean
*/
protected function lastErrorWasFatal()
{
if ($this->lastException) {
return true;
}
$error = error_get_last();
return $error && ($error['type'] & self::$fatal_errors) != 0;
}
protected function lastErrorWasMemoryExhaustion()
{
$error = error_get_last();
$message = $error ? $error['message'] : '';
return stripos($message ?? '', 'memory') !== false && stripos($message ?? '', 'exhausted') !== false;
}
static $transtable = [
'k' => 1024,
'm' => 1048576,
'g' => 1073741824
];
protected function translateMemstring($memString)
{
$char = strtolower(substr($memString ?? '', -1));
$fact = isset(self::$transtable[$char]) ? self::$transtable[$char] : 1;
return ((int)$memString) * $fact;
}
public function handleFatalError()
{
if ($this->handleFatalErrors && $this->suppression) {
if ($this->lastErrorWasFatal()) {
if ($this->lastErrorWasMemoryExhaustion()) {
// Bump up memory limit by an arbitrary 10% / 10MB (whichever is bigger) since we've run out
$cur = $this->translateMemstring(ini_get('memory_limit'));
if ($cur != -1) {
ini_set('memory_limit', $cur + max(round($cur*0.1), 10000000));
}
}
$this->error = true;
$this->step();
}
}
}
public function execute()
{
register_shutdown_function([$this, 'handleFatalError']);
$this->handleFatalErrors = true;
$this->originalDisplayErrors = $this->getDisplayErrors();
$this->setSuppression($this->suppression);
$this->step();
}
protected function step()
{
if ($this->steps) {
$step = array_shift($this->steps);
if ($step['onErrorState'] === null || $step['onErrorState'] === $this->error) {
try {
call_user_func($step['callback'], $this);
} catch (Exception $ex) {
$this->lastException = $ex;
throw $ex;
}
}
$this->step();
} else {
// Now clean up
$this->handleFatalErrors = false;
$this->setDisplayErrors($this->originalDisplayErrors);
}
}
}
ErrorControlChain::$fatal_errors = E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR;
if (defined('E_RECOVERABLE_ERROR')) {
ErrorControlChain::$fatal_errors |= E_RECOVERABLE_ERROR;
}

View File

@ -1,163 +0,0 @@
<?php
namespace SilverStripe\Core\Startup;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Control\Middleware\HTTPMiddleware;
use SilverStripe\Core\Application;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Security\Security;
/**
* Decorates application bootstrapping with errorcontrolchain
*
* @internal This class is designed specifically for use pre-startup and may change without warning
*
* @deprecated 4.12.0 Will be removed without equivalent functionality
*/
class ErrorControlChainMiddleware implements HTTPMiddleware
{
/**
* @var Application
*/
protected $application = null;
/**
* Whether to keep working (legacy mode)
*
* @var bool
*/
private $legacy;
/**
* Build error control chain for an application
*
* @param Application $application
* @param bool $legacy Keep working (legacy mode)
*/
public function __construct(Application $application, $legacy = false)
{
Deprecation::notice('4.12.0', 'Will be removed without equivalent functionality', Deprecation::SCOPE_CLASS);
$this->application = $application;
$this->legacy = $legacy;
}
/**
* @param HTTPRequest $request
* @return ConfirmationTokenChain
*/
protected function prepareConfirmationTokenChain(HTTPRequest $request)
{
$chain = new ConfirmationTokenChain();
$chain->pushToken(new URLConfirmationToken('dev/build', $request));
$chain->pushToken(new ParameterConfirmationToken('flush', $request));
return $chain;
}
public function process(HTTPRequest $request, callable $next)
{
if (!$this->legacy) {
return call_user_func($next, $request);
}
$result = null;
// Prepare tokens and execute chain
$confirmationTokenChain = $this->prepareConfirmationTokenChain($request);
$errorControlChain = new ErrorControlChain();
$errorControlChain
->then(function () use ($request, $errorControlChain, $confirmationTokenChain, $next, &$result) {
if ($confirmationTokenChain->suppressionRequired()) {
$confirmationTokenChain->suppressTokens();
} else {
// If no redirection is necessary then we can disable error suppression
$errorControlChain->setSuppression(false);
}
try {
// Check if a token is requesting a redirect
if ($confirmationTokenChain && $confirmationTokenChain->reloadRequired()) {
$result = $this->safeReloadWithTokens($request, $confirmationTokenChain);
} else {
// If no reload necessary, process application
$result = call_user_func($next, $request);
}
} catch (HTTPResponse_Exception $exception) {
$result = $exception->getResponse();
}
})
// Finally if a token was requested but there was an error while figuring out if it's allowed, do it anyway
->thenIfErrored(function () use ($confirmationTokenChain) {
if ($confirmationTokenChain && $confirmationTokenChain->reloadRequiredIfError()) {
try {
// Reload requires manual boot
$this->getApplication()->getKernel()->boot(false);
} finally {
// Given we're in an error state here, try to continue even if the kernel boot fails
$result = $confirmationTokenChain->reloadWithTokens();
$result->output();
}
}
})
->execute();
return $result;
}
/**
* Reload application with the given token, but only if either the user is authenticated,
* or authentication is impossible.
*
* @param HTTPRequest $request
* @param ConfirmationTokenChain $confirmationTokenChain
* @return HTTPResponse
*/
protected function safeReloadWithTokens(HTTPRequest $request, ConfirmationTokenChain $confirmationTokenChain)
{
// Safe reload requires manual boot
$this->getApplication()->getKernel()->boot(false);
// Ensure session is started
$request->getSession()->init($request);
// Request with ErrorDirector
$result = ErrorDirector::singleton()->handleRequestWithTokenChain(
$request,
$confirmationTokenChain,
$this->getApplication()->getKernel()
);
if ($result) {
return $result;
}
// Fail and redirect the user to the login page
$params = array_merge($request->getVars(), $confirmationTokenChain->params(false));
$backURL = $confirmationTokenChain->getRedirectUrlBase() . '?' . http_build_query($params ?? []);
$loginPage = Director::absoluteURL(Security::config()->get('login_url'));
$loginPage .= "?BackURL=" . urlencode($backURL ?? '');
$result = new HTTPResponse();
$result->redirect($loginPage);
return $result;
}
/**
* @return Application
*/
public function getApplication()
{
return $this->application;
}
/**
* @param Application $application
* @return $this
*/
public function setApplication(Application $application)
{
$this->application = $application;
return $this;
}
}

View File

@ -1,58 +0,0 @@
<?php
namespace SilverStripe\Core\Startup;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Kernel;
use SilverStripe\Security\Permission;
use SilverStripe\Security\Security;
/**
* Specialised Director class used by ErrorControlChain to handle error and redirect conditions
*
* @internal This class is experimental API and may change without warning
*
* @deprecated 4.12.0 Will be removed without equivalent functionality
*/
class ErrorDirector extends Director
{
/**
* Redirect with token if allowed, or null if not allowed
*
* @param HTTPRequest $request
* @param ConfirmationTokenChain $confirmationTokenChain
* @param Kernel $kernel
* @return null|HTTPResponse Redirection response, or null if not able to redirect
*/
public function __construct()
{
Deprecation::notice('4.12.0', 'Will be removed without equivalent functionality', Deprecation::SCOPE_CLASS);
}
public function handleRequestWithTokenChain(
HTTPRequest $request,
ConfirmationTokenChain $confirmationTokenChain,
Kernel $kernel
) {
Injector::inst()->registerService($request, HTTPRequest::class);
// Next, check if we're in dev mode, or the database doesn't have any security data, or we are admin
$reload = function (HTTPRequest $request) use ($confirmationTokenChain, $kernel) {
if ($kernel->getEnvironment() === Kernel::DEV || !Security::database_is_ready() || Permission::check('ADMIN')) {
return $confirmationTokenChain->reloadWithTokens();
}
return null;
};
try {
return $this->callMiddleware($request, $reload);
} finally {
// Ensure registered request is un-registered
Injector::inst()->unregisterNamedObject(HTTPRequest::class);
}
}
}

View File

@ -1,165 +0,0 @@
<?php
namespace SilverStripe\Core\Startup;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Convert;
use SilverStripe\Security\RandomGenerator;
/**
* This is used to protect dangerous GET parameters that need to be detected early in the request
* lifecycle by generating a one-time-use token & redirecting with that token included in the
* redirected URL
*
* @internal This class is designed specifically for use pre-startup and may change without warning
*
* @deprecated 4.12.0 Will be removed without equivalent functionality
*/
class ParameterConfirmationToken extends AbstractConfirmationToken
{
/**
* The name of the parameter
*
* @var string
*/
protected $parameterName = null;
/**
* The parameter given in the main request
*
* @var string|null The string value, or null if not provided
*/
protected $parameter = null;
/**
* The parameter given in the backURL
*
* @var string|null
*/
protected $parameterBackURL = null;
/**
* @param string $parameterName Name of the querystring parameter to check
* @param HTTPRequest $request
*/
public function __construct($parameterName, HTTPRequest $request)
{
Deprecation::notice('4.12.0', 'Will be removed without equivalent functionality', Deprecation::SCOPE_CLASS);
// Store the parameter name
$this->parameterName = $parameterName;
$this->request = $request;
// Store the parameter value
$this->parameter = $request->getVar($parameterName);
$this->parameterBackURL = $this->backURLToken($request);
// If the token provided is valid, mark it as such
$token = $request->getVar($parameterName . 'token');
if ($this->checkToken($token)) {
$this->token = $token;
}
}
/**
* Check if this token exists in the BackURL
*
* @param HTTPRequest $request
* @return string Value of token in backurl, or null if not in backurl
*/
protected function backURLToken(HTTPRequest $request)
{
$backURL = $request->getVar('BackURL');
if (!strstr($backURL ?? '', '?')) {
return null;
}
// Filter backURL if it contains the given request parameter
list(,$query) = explode('?', $backURL ?? '');
parse_str($query ?? '', $queryArgs);
$name = $this->getName();
if (isset($queryArgs[$name])) {
return $queryArgs[$name];
}
return null;
}
/**
* Get the name of this token
*
* @return string
*/
public function getName()
{
return $this->parameterName;
}
/**
* Is the parameter requested?
* ?parameter and ?parameter=1 are both considered requested
*
* @return bool
*/
public function parameterProvided()
{
return $this->parameter !== null;
}
/**
* Is the parameter requested in a BackURL param?
*
* @return bool
*/
public function existsInReferer()
{
return $this->parameterBackURL !== null;
}
public function reloadRequired()
{
return $this->parameterProvided() && !$this->tokenProvided();
}
public function reloadRequiredIfError()
{
// Don't reload if token exists
return $this->reloadRequired() || $this->existsInReferer();
}
public function suppress()
{
$this->request->offsetUnset($this->parameterName);
}
public function params($includeToken = true)
{
$params = [
$this->parameterName => $this->parameter,
];
if ($includeToken) {
$params[$this->parameterName . 'token'] = $this->genToken();
}
return $params;
}
public function getRedirectUrlBase()
{
return ($this->existsInReferer() && !$this->parameterProvided()) ? Director::baseURL() : $this->currentURL();
}
public function getRedirectUrlParams()
{
return ($this->existsInReferer() && !$this->parameterProvided())
? $this->params()
: array_merge($this->request->getVars(), $this->params());
}
protected function redirectURL()
{
$query = http_build_query($this->getRedirectUrlParams() ?? []);
return Controller::join_links($this->getRedirectUrlBase(), '?' . $query);
}
}

View File

@ -1,143 +0,0 @@
<?php
namespace SilverStripe\Core\Startup;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
/**
* This is used to protect dangerous URLs that need to be detected early in the request lifecycle
* by generating a one-time-use token & redirecting with that token included in the redirected URL
*
* @internal This class is designed specifically for use pre-startup and may change without warning
*
* @deprecated 4.12.0 Will be removed without equivalent functionality
*/
class URLConfirmationToken extends AbstractConfirmationToken
{
/**
* @var string
*/
protected $urlToCheck;
/**
* @var string
*/
protected $currentURL;
/**
* @var string
*/
protected $tokenParameterName;
/**
* @var bool
*/
protected $urlExistsInBackURL;
/**
* @param string $urlToCheck URL to check
* @param HTTPRequest $request
*/
public function __construct($urlToCheck, HTTPRequest $request)
{
Deprecation::notice('4.12.0', 'Will be removed without equivalent functionality', Deprecation::SCOPE_CLASS);
$this->urlToCheck = $urlToCheck;
$this->request = $request;
$this->currentURL = $request->getURL(false);
$this->tokenParameterName = preg_replace('/[^a-z0-9]/i', '', $urlToCheck ?? '') . 'token';
$this->urlExistsInBackURL = $this->getURLExistsInBackURL($request);
// If the token provided is valid, mark it as such
$token = $request->getVar($this->tokenParameterName);
if ($this->checkToken($token)) {
$this->token = $token;
}
}
/**
* @param HTTPRequest $request
* @return bool
*/
protected function getURLExistsInBackURL(HTTPRequest $request)
{
$backURL = ltrim($request->getVar('BackURL') ?? '', '/');
return (strpos($backURL ?? '', $this->urlToCheck ?? '') === 0);
}
/**
* @return bool
*/
protected function urlMatches()
{
return ($this->currentURL === $this->urlToCheck);
}
/**
* @return string
*/
public function getURLToCheck()
{
return $this->urlToCheck;
}
/**
* @return bool
*/
public function urlExistsInBackURL()
{
return $this->urlExistsInBackURL;
}
public function reloadRequired()
{
return $this->urlMatches() && !$this->tokenProvided();
}
public function reloadRequiredIfError()
{
return $this->reloadRequired() || $this->urlExistsInBackURL();
}
public function suppress()
{
$_SERVER['REQUEST_URI'] = '/';
$this->request->setURL('/');
}
public function params($includeToken = true)
{
$params = [];
if ($includeToken) {
$params[$this->tokenParameterName] = $this->genToken();
}
return $params;
}
public function currentURL()
{
return Controller::join_links(Director::baseURL(), $this->currentURL);
}
public function getRedirectUrlBase()
{
return ($this->urlExistsInBackURL && !$this->urlMatches()) ? Director::baseURL() : $this->currentURL();
}
public function getRedirectUrlParams()
{
return ($this->urlExistsInBackURL && !$this->urlMatches())
? $this->params()
: array_merge($this->request->getVars(), $this->params());
}
protected function redirectURL()
{
$query = http_build_query($this->getRedirectUrlParams() ?? []);
return Controller::join_links($this->getRedirectUrlBase(), '?' . $query);
}
}

View File

@ -52,8 +52,8 @@ class Backtrace
'Zend_Log->log',
'Zend_Log->__call',
'Zend_Log->err',
'SilverStripe\\Dev\\DebugView->writeTrace',
'SilverStripe\\Dev\\CliDebugView->writeTrace',
'SilverStripe\\Dev\\DebugView->renderTrace',
'SilverStripe\\Dev\\CliDebugView->renderTrace',
'SilverStripe\\Dev\\Debug::emailError',
'SilverStripe\\Dev\\Debug::warningHandler',
'SilverStripe\\Dev\\Debug::noticeHandler',

View File

@ -1,341 +0,0 @@
<?php
namespace SilverStripe\Dev;
use League\Csv\Reader;
use SilverStripe\Core\Injector\Injectable;
use Iterator;
use SilverStripe\Control\Director;
/**
* Class to handle parsing of CSV files, where the column headers are in the
* first row.
*
* The idea is that you pass it another object to handle the actual processing
* of the data in the CSV file.
*
* Usage:
*
* <code>
* $parser = new CSVParser('myfile.csv');
* $parser->mapColumns(array(
* 'first name' => 'FirstName',
* 'lastname' => 'Surname',
* 'last name' => 'Surname',
* ));
* foreach($parser as $row) {
* // $row is a map of column name => column value
* $obj = new MyDataObject();
* $obj->update($row);
* $obj->write();
* }
* </code>
*/
class CSVParser implements Iterator
{
use Injectable;
/**
* @var string $filename
*/
protected $filename;
/**
* @var resource $fileHandle
*/
protected $fileHandle;
/**
* Map of source columns to output columns.
*
* Once they get into this variable, all of the source columns are in
* lowercase.
*
* @var array
*/
protected $columnMap = [];
/**
* The header row used to map data in the CSV file.
*
* To begin with, this is null. Once it has been set, data will get
* returned from the CSV file.
*
* @var array
*/
protected $headerRow = null;
/**
* A custom header row provided by the caller.
*
* @var array
*/
protected $providedHeaderRow = null;
/**
* The data of the current row.
*
* @var array
*/
protected $currentRow = null;
/**
* The current row number.
*
* 1 is the first data row in the CSV file; the header row, if it exists,
* is ignored.
*
* @var int
*/
protected $rowNum = 0;
/**
* The character for separating columns.
*
* @var string
*/
protected $delimiter = ",";
/**
* The character for quoting columns.
*
* @var string
*/
protected $enclosure = '"';
/**
* Open a CSV file for parsing.
*
* You can use the object returned in a foreach loop to extract the data.
*
* @param string $filename The name of the file. If relative, it will be relative to the site's base dir
* @param string $delimiter The character for separating columns
* @param string $enclosure The character for quoting or enclosing columns
*/
public function __construct($filename, $delimiter = ",", $enclosure = '"')
{
Deprecation::notice('5.0', __CLASS__ . ' is deprecated, use ' . Reader::class . ' instead');
$filename = Director::getAbsFile($filename);
$this->filename = $filename;
$this->delimiter = $delimiter;
$this->enclosure = $enclosure;
}
/**
* Re-map columns in the CSV file.
*
* This can be useful for identifying synonyms in the file. For example:
*
* <code>
* $csv->mapColumns(array(
* 'firstname' => 'FirstName',
* 'last name' => 'Surname',
* ));
* </code>
*
* @param array $columnMap
*/
public function mapColumns($columnMap)
{
if ($columnMap) {
$lowerColumnMap = [];
foreach ($columnMap as $k => $v) {
$lowerColumnMap[strtolower($k)] = $v;
}
$this->columnMap = array_merge($this->columnMap, $lowerColumnMap);
}
}
/**
* If your CSV file doesn't have a header row, then you can call this
* function to provide one.
*
* If you call this function, then the first row of the CSV will be
* included in the data returned.
*
* @param array $headerRow
*/
public function provideHeaderRow($headerRow)
{
$this->providedHeaderRow = $headerRow;
}
/**
* Open the CSV file for reading.
*/
protected function openFile()
{
$this->fileHandle = fopen($this->filename ?? '', 'r');
if ($this->providedHeaderRow) {
$this->headerRow = $this->remapHeader($this->providedHeaderRow);
}
}
/**
* Close the CSV file and re-set all of the internal variables.
*/
protected function closeFile()
{
if ($this->fileHandle) {
fclose($this->fileHandle);
}
$this->fileHandle = null;
$this->rowNum = 0;
$this->currentRow = null;
$this->headerRow = null;
}
/**
* Get a header row from the CSV file.
*/
protected function fetchCSVHeader()
{
$srcRow = fgetcsv(
$this->fileHandle,
0,
$this->delimiter ?? '',
$this->enclosure ?? ''
);
$this->headerRow = $this->remapHeader($srcRow);
}
/**
* Map the contents of a header array using $this->mappedColumns.
*
* @param array $header
*
* @return array
*/
protected function remapHeader($header)
{
$mappedHeader = [];
foreach ($header as $item) {
if (isset($this->columnMap[strtolower($item)])) {
$item = $this->columnMap[strtolower($item)];
}
$mappedHeader[] = $item;
}
return $mappedHeader;
}
/**
* Get a row from the CSV file and update $this->currentRow;
*
* @return array
*/
protected function fetchCSVRow()
{
if (!$this->fileHandle) {
$this->openFile();
}
if (!$this->headerRow) {
$this->fetchCSVHeader();
}
$this->rowNum++;
$srcRow = fgetcsv(
$this->fileHandle,
0,
$this->delimiter ?? '',
$this->enclosure ?? ''
);
if ($srcRow) {
$row = [];
foreach ($srcRow as $i => $value) {
// Allow escaping of quotes and commas in the data
$value = str_replace(
['\\' . $this->enclosure,'\\' . $this->delimiter],
[$this->enclosure, $this->delimiter],
$value ?? ''
);
// Trim leading tab
// [SS-2017-007] Ensure all cells with leading [@=+] have a leading tab
$value = ltrim($value ?? '', "\t");
if (array_key_exists($i, $this->headerRow ?? [])) {
if ($this->headerRow[$i]) {
$row[$this->headerRow[$i]] = $value;
}
} else {
user_error("No heading for column $i on row $this->rowNum", E_USER_WARNING);
}
}
$this->currentRow = $row;
} else {
$this->closeFile();
}
return $this->currentRow;
}
/**
* @ignore
*/
public function __destruct()
{
$this->closeFile();
}
//// ITERATOR FUNCTIONS
/**
* @ignore
*/
#[\ReturnTypeWillChange]
public function rewind()
{
$this->closeFile();
$this->fetchCSVRow();
}
/**
* @ignore
*/
#[\ReturnTypeWillChange]
public function current()
{
return $this->currentRow;
}
/**
* @ignore
*/
#[\ReturnTypeWillChange]
public function key()
{
return $this->rowNum;
}
/**
* @ignore
*/
#[\ReturnTypeWillChange]
public function next()
{
$this->fetchCSVRow();
return $this->currentRow;
}
/**
* @ignore
*/
#[\ReturnTypeWillChange]
public function valid()
{
return $this->currentRow ? true : false;
}
}

View File

@ -159,124 +159,6 @@ class CsvBulkLoader extends BulkLoader
return $map;
}
/**
* Splits a large file up into many smaller files.
*
* @param string $path Path to large file to split
* @param int $lines Number of lines per file
*
* @return array List of file paths
* @deprecated 4.12.0 Process files using a stream instead
*/
protected function splitFile($path, $lines = null)
{
Deprecation::notice('4.12.0', 'Process files using a stream instead');
if (!is_int($lines)) {
$lines = $this->config()->get("lines");
}
$new = $this->getNewSplitFileName();
$to = fopen($new ?? '', 'w+');
$from = fopen($path ?? '', 'r');
$header = null;
if ($this->hasHeaderRow) {
$header = fgets($from);
fwrite($to, $header ?? '');
}
$files = [];
$files[] = $new;
$count = 0;
while (!feof($from)) {
fwrite($to, fgets($from) ?? '');
$count++;
if ($count >= $lines) {
fclose($to);
// get a new temporary file name, to write the next lines to
$new = $this->getNewSplitFileName();
$to = fopen($new ?? '', 'w+');
if ($this->hasHeaderRow) {
// add the headers to the new file
fwrite($to, $header ?? '');
}
$files[] = $new;
$count = 0;
}
}
fclose($to);
return $files;
}
/**
* @return string
* @deprecated 4.12.0 Name files yourself instead
*/
protected function getNewSplitFileName()
{
Deprecation::notice('4.12.0', 'Name files yourself instead');
return TEMP_PATH . DIRECTORY_SEPARATOR . uniqid(str_replace('\\', '_', static::class) ?? '', true) . '.csv';
}
/**
* @param string $filepath
* @param boolean $preview
*
* @return BulkLoader_Result
* @deprecated 4.12.0 Process rows individually instead
*/
protected function processChunk($filepath, $preview = false)
{
Deprecation::notice('4.12.0', 'Process rows individually instead');
$results = BulkLoader_Result::create();
$csv = new CSVParser(
$filepath,
$this->delimiter,
$this->enclosure
);
// ColumnMap has two uses, depending on whether hasHeaderRow is set
if ($this->columnMap) {
// if the map goes to a callback, use the same key value as the map
// value, rather than function name as multiple keys may use the
// same callback
$map = [];
foreach ($this->columnMap as $k => $v) {
if (strpos($v ?? '', "->") === 0) {
$map[$k] = $k;
} else {
$map[$k] = $v;
}
}
if ($this->hasHeaderRow) {
$csv->mapColumns($map);
} else {
$csv->provideHeaderRow($map);
}
}
foreach ($csv as $row) {
$this->processRecord($row, $this->columnMap, $results, $preview);
}
return $results;
}
/**
* @todo Better messages for relation checks and duplicate detection
* Note that columnMap isn't used.

View File

@ -142,69 +142,6 @@ class DebugView
return implode('&nbsp;&rarr;&nbsp;', $pathLinks);
}
/**
* @deprecated 4.0.1 Use renderHeader() instead
*/
public function writeHeader()
{
Deprecation::notice('4.0.1', 'Use renderHeader() instead');
echo $this->renderHeader();
}
/**
* @deprecated 4.0.1 Use renderInfo() instead
*/
public function writeInfo($title, $subtitle, $description = false)
{
Deprecation::notice('4.0.1', 'Use renderInfo() instead');
echo $this->renderInfo($title, $subtitle, $description);
}
/**
* @deprecated 4.0.1 Use renderFooter() instead
*/
public function writeFooter()
{
Deprecation::notice('4.0.1', 'Use renderFooter() instead');
echo $this->renderFooter();
}
/**
* @deprecated 4.0.1 Use renderError() instead
*/
public function writeError($httpRequest, $errno, $errstr, $errfile, $errline)
{
Deprecation::notice('4.0.1', 'Use renderError() instead');
echo $this->renderError($httpRequest, $errno, $errstr, $errfile, $errline);
}
/**
* @deprecated 4.0.1 Use renderSourceFragment() instead
*/
public function writeSourceFragment($lines, $errline)
{
Deprecation::notice('4.0.1', 'Use renderSourceFragment() instead');
echo $this->renderSourceFragment($lines, $errline);
}
/**
* @deprecated 4.0.1 Use renderTrace() instead
*/
public function writeTrace($trace)
{
Deprecation::notice('4.0.1', 'Use renderTrace() instead');
echo $this->renderTrace($trace);
}
/**
* @deprecated 4.0.1 Use renderVariable() instead
*/
public function writeVariable($val, $caller)
{
Deprecation::notice('4.0.1', 'Use renderVariable() instead');
echo $this->renderVariable($val, $caller);
}
/**
* Render HTML header for development views
*

View File

@ -31,38 +31,6 @@ class Deprecation
const SCOPE_GLOBAL = 4;
const SCOPE_CONFIG = 8;
/**
* @var string
* @deprecated 4.12.0 Will be removed without equivalent functionality to replace it
*/
protected static $version;
/**
* Override whether deprecation is enabled. If null, then fallback to
* SS_DEPRECATION_ENABLED, and then true if not defined.
*
* Deprecation is only available on dev.
*
* Must be configured outside of the config API, as deprecation API
* must be available before this to avoid infinite loops.
*
* @var boolean|null
* @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.
@ -131,37 +99,6 @@ class Deprecation
}
}
/**
* This method is no longer used
*
* @static
* @param $ver string -
* A php standard version string, see http://php.net/manual/en/function.version-compare.php for details.
* @param null $forModule string -
* The name of a module. The passed version will be used as the check value for
* calls directly from this module rather than the global value
* @return void
* @deprecated 4.12.0 Use enable() instead
*/
public static function notification_version($ver, $forModule = null)
{
static::notice('4.12.0', 'Use enable() instead');
// noop
}
/**
* This method is no longer used
*
* @param array $backtrace A backtrace as returned from debug_backtrace
* @return Module The module being called
* @deprecated 4.12.0 Will be removed without equivalent functionality to replace it
*/
protected static function get_calling_module_from_trace($backtrace)
{
static::notice('4.12.0', 'Will be removed without equivalent functionality to replace it');
// noop
}
/**
* Given a backtrace, get the method name from the immediate parent caller (the caller of #notice)
*
@ -191,18 +128,6 @@ class Deprecation
return ($called['class'] ?? '') . ($called['type'] ?? '') . ($called['function'] ?? '');
}
/**
* This method is no longer used
*
* @return bool
* @deprecated 4.12.0 Will be removed without equivalent functionality to replace it
*/
public static function get_enabled()
{
static::notice('4.12.0', 'Will be removed without equivalent functionality to replace it');
// noop
}
public static function isEnabled(): bool
{
if (!Director::isDev()) {
@ -211,18 +136,6 @@ class Deprecation
return static::$currentlyEnabled || Environment::getEnv('SS_DEPRECATION_ENABLED');
}
/**
* This method is no longer used
*
* @param bool $enabled
* @deprecated 4.12.0 Use enable() instead
*/
public static function set_enabled($enabled)
{
static::notice('4.12.0', 'Use enable() instead');
// noop
}
public static function outputNotices(): void
{
if (!self::isEnabled()) {
@ -322,28 +235,4 @@ class Deprecation
static::$insideNotice = false;
}
}
/**
* This method is no longer used
*
* @return array Opaque array that should only be used to pass to {@see Deprecation::restore_settings()}
* @deprecated 4.12.0 Will be removed without equivalent functionality to replace it
*/
public static function dump_settings()
{
static::notice('4.12.0', 'Will be removed without equivalent functionality to replace it');
// noop
}
/**
* This method is no longer used
*
* @param $settings array An array as returned by {@see Deprecation::dump_settings()}
* @deprecated 4.12.0 Will be removed without equivalent functionality to replace it
*/
public static function restore_settings($settings)
{
static::notice('4.12.0', 'Will be removed without equivalent functionality to replace it');
// noop
}
}

View File

@ -11,7 +11,6 @@ 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
@ -43,14 +42,6 @@ abstract class FunctionalTest extends SapphireTest implements TestOnly
*/
protected static $disable_themes = false;
/**
* Set this to true on your sub-class to use the draft site by default for every test in this class.
*
* @deprecated 4.2.0 Use ?stage=Stage in your request's querystring instead
* @var bool
*/
protected static $use_draft_site = false;
/**
* @var TestSession
*/
@ -101,14 +92,6 @@ abstract class FunctionalTest extends SapphireTest implements TestOnly
// Flush user
$this->logOut();
// Switch to draft site, if necessary
// If you rely on this you should be crafting stage-specific urls instead though.
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.
BasicAuth::protect_entire_site(false);
@ -402,26 +385,6 @@ abstract class FunctionalTest extends SapphireTest implements TestOnly
$this->assertTrue($expectedMatches == $actuals, $message);
}
/**
* Use the draft (stage) site for testing.
* This is helpful if you're not testing publication functionality and don't want "stage management" cluttering
* your test.
*
* @deprecated 4.2.0 Use ?stage=Stage in your request's querystring instead
* @param bool $enabled toggle the use of the draft site
*/
public function useDraftSite($enabled = true)
{
Deprecation::notice('4.2.0', 'Use ?stage=Stage in your request\'s querystring instead');
if ($enabled) {
$this->session()->set('readingMode', 'Stage.Stage');
$this->session()->set('unsecuredDraftSite', true);
} else {
$this->session()->clear('readingMode');
$this->session()->clear('unsecuredDraftSite');
}
}
/**
* @return bool
*/
@ -429,14 +392,4 @@ abstract class FunctionalTest extends SapphireTest implements TestOnly
{
return static::$disable_themes;
}
/**
* @deprecated 4.2.0 Use ?stage=Stage in your request's querystring instead
* @return bool
*/
public static function get_use_draft_site()
{
Deprecation::notice('4.2.0', 'Use ?stage=Stage in your request\'s querystring instead');
return static::$use_draft_site;
}
}

View File

@ -5,7 +5,6 @@ namespace SilverStripe\Dev\Install;
use InvalidArgumentException;
use Psr\SimpleCache\CacheInterface;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Core\Flushable;
/**
@ -141,12 +140,8 @@ class DatabaseAdapterRegistry implements Flushable
*/
public static function autoconfigure(&$config = null)
{
if (!isset($config)) {
Deprecation::notice('5.0', 'Configuration via global is deprecated');
global $databaseConfig;
} else {
$databaseConfig = $config;
}
foreach (static::getConfigureDatabasePaths() as $configureDatabasePath) {
include_once $configureDatabasePath;
}

View File

@ -1,28 +0,0 @@
<?php
namespace SilverStripe\Dev;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Control\Controller;
/**
* Simple controller that the installer uses to test that URL rewriting is working.
* @deprecated 4.4.7 Will be removed without equivalent functionality
*/
class InstallerTest extends Controller
{
private static $allowed_actions = [
'testrewrite'
];
public function __construct()
{
Deprecation::notice('4.4.7', 'Will be removed without equivalent functionality', Deprecation::SCOPE_CLASS);
}
public function testrewrite()
{
echo "OK";
}
}

View File

@ -1,60 +0,0 @@
<?php
namespace SilverStripe\Dev;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Security\Permission;
use SilverStripe\Security\Security;
/**
* Returns information about the current site instance.
* @deprecated 4.4.7 Will be removed without equivalent functionality
*/
class SapphireInfo extends Controller
{
private static $allowed_actions = [
'baseurl',
'version',
'environmenttype',
];
public function __construct()
{
Deprecation::notice('4.4.7', 'Will be removed without equivalent functionality', Deprecation::SCOPE_CLASS);
}
protected function init()
{
parent::init();
if (!Director::is_cli() && !Permission::check('ADMIN')) {
Security::permissionFailure();
}
}
public function Version()
{
$sapphireVersion = file_get_contents(FRAMEWORK_PATH . '/silverstripe_version');
if (!$sapphireVersion) {
$sapphireVersion = _t('SilverStripe\\Admin\\LeftAndMain.VersionUnknown', 'unknown');
}
return $sapphireVersion;
}
public function EnvironmentType()
{
if (Director::isLive()) {
return "live";
} elseif (Director::isTest()) {
return "test";
} else {
return "dev";
}
}
public function BaseURL()
{
return Director::absoluteBaseURL();
}
}

View File

@ -62,12 +62,6 @@ abstract class SapphireTest extends TestCase implements TestOnly
*/
protected static $fixture_file = null;
/**
* @deprecated 4.0.1 Use FixtureTestState instead
* @var FixtureFactory
*/
protected $fixtureFactory;
/**
* @var Boolean If set to TRUE, this will force a test database to be generated
* in {@link setUp()}. Note that this flag is overruled by the presence of a
@ -427,34 +421,6 @@ abstract class SapphireTest extends TestCase implements TestOnly
static::resetDBSchema();
}
/**
* @return FixtureFactory|false
* @deprecated 4.0.1 Use FixtureTestState instead
*/
public function getFixtureFactory()
{
Deprecation::notice('4.0.1', 'Use FixtureTestState instead');
/** @var FixtureTestState $state */
$state = static::$state->getStateByName('fixtures');
return $state->getFixtureFactory(static::class);
}
/**
* Sets a new fixture factory
* @param FixtureFactory $factory
* @return $this
* @deprecated 4.0.1 Use FixtureTestState instead
*/
public function setFixtureFactory(FixtureFactory $factory)
{
Deprecation::notice('4.0.1', 'Use FixtureTestState instead');
/** @var FixtureTestState $state */
$state = static::$state->getStateByName('fixtures');
$state->setFixtureFactory($factory, static::class);
$this->fixtureFactory = $factory;
return $this;
}
/**
* Get the ID of an object from the fixture.
*
@ -518,21 +484,6 @@ abstract class SapphireTest extends TestCase implements TestOnly
return $obj;
}
/**
* Load a YAML fixture file into the database.
* Once loaded, you can use idFromFixture() and objFromFixture() to get items from the fixture.
* Doesn't clear existing fixtures.
* @param string $fixtureFile The location of the .yml fixture file, relative to the site base dir
* @deprecated 4.0.1 Use FixtureTestState instead
*
*/
public function loadFixture($fixtureFile)
{
Deprecation::notice('4.0.1', 'Use FixtureTestState instead');
$fixture = Injector::inst()->create(YamlFixture::class, $fixtureFile);
$fixture->writeInto($this->getFixtureFactory());
}
/**
* Clear all fixtures which were previously loaded through
* {@link loadFixture()}
@ -716,18 +667,6 @@ abstract class SapphireTest extends TestCase implements TestOnly
);
}
/**
* @param $matches
* @param $dataObjectSet
* @deprecated 4.0.1 Use assertListContains() instead
*
*/
public function assertDOSContains($matches, $dataObjectSet)
{
Deprecation::notice('4.0.1', 'Use assertListContains() instead');
static::assertListContains($matches, $dataObjectSet);
}
/**
* Asserts that no items in a given list appear in the given dataobject list
*
@ -770,18 +709,6 @@ abstract class SapphireTest extends TestCase implements TestOnly
);
}
/**
* @param $matches
* @param $dataObjectSet
* @deprecated 4.0.1 Use assertListNotContains() instead
*
*/
public static function assertNotDOSContains($matches, $dataObjectSet)
{
Deprecation::notice('4.0.1', 'Use assertListNotContains() instead');
static::assertListNotContains($matches, $dataObjectSet);
}
/**
* Assert that the given {@link SS_List} includes only DataObjects matching the given
* key-value pairs. Each match must correspond to 1 distinct record.
@ -818,19 +745,6 @@ abstract class SapphireTest extends TestCase implements TestOnly
);
}
/**
* @param $matches
* @param SS_List $dataObjectSet
* @deprecated 4.0.1 Use assertListEquals() instead
*
*/
public function assertDOSEquals($matches, $dataObjectSet)
{
Deprecation::notice('4.0.1', 'Use assertListEquals() instead');
static::assertListEquals($matches, $dataObjectSet);
}
/**
* Assert that the every record in the given {@link SS_List} matches the given key-value
* pairs.
@ -862,18 +776,6 @@ abstract class SapphireTest extends TestCase implements TestOnly
);
}
/**
* @param $match
* @param SS_List $dataObjectSet
* @deprecated 4.0.1 Use assertListAllMatch() instead
*
*/
public function assertDOSAllMatch($match, SS_List $dataObjectSet)
{
Deprecation::notice('4.0.1', 'Use assertListAllMatch() instead');
static::assertListAllMatch($match, $dataObjectSet);
}
/**
* Removes sequences of repeated whitespace characters from SQL queries
* making them suitable for string comparison

View File

@ -1,350 +0,0 @@
<?php
namespace SilverStripe\Dev\Tasks;
use Monolog\Handler\FilterHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Psr\Log\LoggerInterface;
use SilverStripe\AssetAdmin\Helper\ImageThumbnailHelper;
use SilverStripe\Assets\Dev\Tasks\LegacyThumbnailMigrationHelper;
use SilverStripe\Assets\Dev\Tasks\FileMigrationHelper;
use SilverStripe\Assets\Dev\Tasks\FolderMigrationHelper;
use SilverStripe\Assets\Dev\Tasks\NormaliseAccessMigrationHelper;
use SilverStripe\Assets\Storage\AssetStore;
use SilverStripe\Assets\Storage\FileHashingService;
use SilverStripe\Control\Director;
use SilverStripe\Core\Environment;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Logging\PreformattedEchoHandler;
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
{
private static $segment = 'MigrateFileTask';
protected $title = 'Migrate File dataobjects from 3.x and successive iterations in 4.x';
protected $defaultSubtasks = [
'move-files',
'migrate-folders',
'move-thumbnails',
'generate-cms-thumbnails',
'fix-folder-permissions',
'fix-secureassets',
];
protected $optInSubtasks = [
'normalise-access',
'relocate-userform-uploads-2020-9280'
];
private static $dependencies = [
'logger' => '%$' . LoggerInterface::class,
];
/** @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();
$args = $request->getVars();
$this->validateArgs($args);
Injector::inst()->get(FileHashingService::class)->enableCache();
// Set max time and memory limit
Environment::increaseTimeLimitTo();
Environment::setMemoryLimitMax(-1);
Environment::increaseMemoryLimitTo(-1);
$this->extend('preFileMigration');
$this->logger->warn(
'Please read https://docs.silverstripe.org/en/4/developer_guides/files/file_migration/ ' .
'before running this task.'
);
$subtasks = !empty($args['only']) ? explode(',', $args['only']) : $this->defaultSubtasks;
$subtask = 'move-files';
if (in_array($subtask, $subtasks ?? [])) {
if (!class_exists(FileMigrationHelper::class)) {
$this->logger->error("No file migration helper detected");
} else {
$this->extend('preFileMigrationSubtask', $subtask);
$this->logger->notice("######################################################");
$this->logger->notice("Migrating filesystem and database records ({$subtask})");
$this->logger->notice("######################################################");
FileMigrationHelper::singleton()
->setLogger($this->logger)
->run();
$this->extend('postFileMigrationSubtask', $subtask);
}
}
$subtask = 'migrate-folders';
if (in_array($subtask, $subtasks ?? [])) {
if (!class_exists(FolderMigrationHelper::class)) {
$this->logger->error("No folder migration helper detected");
} else {
$this->extend('preFileMigrationSubtask', $subtask);
$this->logger->notice("######################################################");
$this->logger->notice("Migrating folder database records ({$subtask})");
$this->logger->notice("######################################################");
FolderMigrationHelper::singleton()
->setLogger($this->logger)
->run();
$this->extend('postFileMigrationSubtask', $subtask);
}
}
$subtask = 'move-thumbnails';
if (in_array($subtask, $subtasks ?? [])) {
if (!class_exists(LegacyThumbnailMigrationHelper::class)) {
$this->logger->error("LegacyThumbnailMigrationHelper not found");
} else {
$this->extend('preFileMigrationSubtask', $subtask);
$this->logger->notice("#############################################################");
$this->logger->notice("Migrating existing thumbnails to new file format ({$subtask})");
$this->logger->notice("#############################################################");
$paths = LegacyThumbnailMigrationHelper::singleton()
->setLogger($this->logger)
->run($this->getStore());
if ($paths) {
$this->logger->info(sprintf("%d thumbnails moved", count($paths ?? [])));
} else {
$this->logger->info("No thumbnails needed to be moved");
}
$this->extend('postFileMigrationSubtask', $subtask);
}
}
$subtask = 'generate-cms-thumbnails';
if (in_array($subtask, $subtasks ?? [])) {
if (!class_exists(ImageThumbnailHelper::class)) {
$this->logger->error("ImageThumbnailHelper not found");
} else {
$this->extend('preFileMigrationSubtask', $subtask);
$this->logger->notice("#############################################");
$this->logger->notice("Generating new CMS UI thumbnails ({$subtask})");
$this->logger->notice("#############################################");
$count = ImageThumbnailHelper::singleton()
->setLogger($this->logger)
->run();
if ($count > 0) {
$this->logger->info("Created {$count} CMS UI thumbnails");
} else {
$this->logger->info("No CMS UI thumbnails needed to be created");
}
$this->extend('postFileMigrationSubtask', $subtask);
}
}
$subtask = 'fix-folder-permissions';
if (in_array($subtask, $subtasks ?? [])) {
if (!class_exists(FixFolderPermissionsHelper::class)) {
$this->logger->error("FixFolderPermissionsHelper not found");
} else {
$this->extend('preFileMigrationSubtask', $subtask);
$this->logger->notice("####################################################");
$this->logger->notice("Fixing secure-assets folder permissions ({$subtask})");
$this->logger->notice("####################################################");
$this->logger->debug('Only required if the 3.x project included silverstripe/secure-assets');
$count = FixFolderPermissionsHelper::singleton()
->setLogger($this->logger)
->run();
if ($count > 0) {
$this->logger->info("Repaired {$count} folders with broken CanViewType settings");
} else {
$this->logger->info("No folders required fixes");
}
$this->extend('postFileMigrationSubtask', $subtask);
}
}
$subtask = 'fix-secureassets';
if (in_array($subtask, $subtasks ?? [])) {
if (!class_exists(SecureAssetsMigrationHelper::class)) {
$this->logger->error("SecureAssetsMigrationHelper not found");
} else {
$this->extend('preFileMigrationSubtask', $subtask);
$this->logger->notice("#####################################################");
$this->logger->notice("Fixing secure-assets folder restrictions ({$subtask})");
$this->logger->notice("#####################################################");
$this->logger->debug('Only required if the 3.x project included silverstripe/secure-assets');
$paths = SecureAssetsMigrationHelper::singleton()
->setLogger($this->logger)
->run($this->getStore());
if (count($paths ?? []) > 0) {
$this->logger->info(sprintf("Repaired %d folders broken folder restrictions", count($paths ?? [])));
} else {
$this->logger->info("No folders required fixes");
}
$this->extend('postFileMigrationSubtask', $subtask);
}
}
$subtask = 'normalise-access';
if (in_array($subtask, $subtasks ?? [])) {
if (!class_exists(NormaliseAccessMigrationHelper::class)) {
$this->logger->error("No normalise access migration helper detected");
} else {
$this->extend('preFileMigrationSubtask', $subtask);
$this->logger->notice("######################################################");
$this->logger->notice("Migrating filesystem and database records ({$subtask})");
$this->logger->notice("######################################################");
NormaliseAccessMigrationHelper::singleton()
->setLogger($this->logger)
->run();
$this->extend('postFileMigrationSubtask', $subtask);
}
}
$subtask = 'relocate-userform-uploads-2020-9280';
if (in_array($subtask, $subtasks ?? [])) {
if (!class_exists(RecoverUploadLocationsHelper::class)) {
$this->logger->error("No UserForms helper detected");
} else {
$this->extend('preFileMigrationSubtask', $subtask);
$this->logger->notice("######################################################");
$this->logger->notice("Recovering UserForm uploaded file locations ({$subtask})");
$this->logger->notice("######################################################");
RecoverUploadLocationsHelper::singleton()
->setLogger($this->logger)
->run();
$this->extend('postFileMigrationSubtask', $subtask);
}
}
$this->extend('postFileMigration');
$this->logger->info("Done!");
}
public function getDescription()
{
return <<<TXT
Imports all files referenced by File dataobjects into the new Asset Persistence Layer introduced in 4.0.
Moves existing thumbnails, and generates new thumbnail sizes for the CMS UI. Fixes file permissions.
If the task fails or times out, run it again and if possible the tasks will start where they left off.
You need to flush your cache after running this task via CLI.
See https://docs.silverstripe.org/en/4/developer_guides/files/file_migration/.
TXT;
}
/**
* @param LoggerInterface $logger
*/
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
return $this;
}
/**
* @return AssetStore
*/
protected function getStore()
{
return singleton(AssetStore::class);
}
/**
* @param array $args
* @throws \InvalidArgumentException
*/
protected function validateArgs($args)
{
if (!empty($args['only'])) {
$only = explode(',', $args['only'] ?? '');
$diff = array_diff($only ?? [], $this->defaultSubtasks);
$diff = array_diff($diff ?? [], $this->optInSubtasks);
if ($diff) {
throw new \InvalidArgumentException('Invalid subtasks detected: ' . implode(', ', $diff));
}
}
}
/**
* TODO Refactor this whole mess into Symfony Console on a TaskRunner level,
* with a thin wrapper to show coloured console output via a browser:
* https://github.com/silverstripe/silverstripe-framework/issues/5542
* @throws \Exception
*/
protected function addLogHandlers()
{
// Using a global service here so other systems can control and redirect log output,
// for example when this task is run as part of a queuedjob
$logger = Injector::inst()->get(LoggerInterface::class)->withName('log');
$formatter = new ColoredLineFormatter();
$formatter->ignoreEmptyContextAndExtra();
$errorHandler = new StreamHandler('php://stderr', Logger::ERROR);
$errorHandler->setFormatter($formatter);
$standardHandler = new StreamHandler('php://stdout');
$standardHandler->setFormatter($formatter);
// Avoid double logging of errors
$standardFilterHandler = new FilterHandler(
$standardHandler,
Logger::DEBUG,
Logger::WARNING
);
$logger->pushHandler($standardFilterHandler);
$logger->pushHandler($errorHandler);
$this->logger = $logger;
}
}

View File

@ -2,7 +2,6 @@
namespace SilverStripe\Forms;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\ArrayList;
/**
@ -17,7 +16,6 @@ class FieldList extends ArrayList
* Cached flat representation of all fields in this set,
* including fields nested in {@link CompositeFields}.
*
* @uses self::collateDataFields()
* @var FormField[]
*/
protected $sequentialSet;
@ -179,46 +177,6 @@ class FieldList extends ArrayList
$this->sequentialSaveableSet = null;
}
/**
* @deprecated 4.1.0 Please use dataFields or saveableFields instead
* @param $list
* @param bool $saveableOnly
*/
protected function collateDataFields(&$list, $saveableOnly = false)
{
Deprecation::notice('4.1.0', 'Please use dataFields or saveableFields instead');
if (!isset($list)) {
$list = [];
}
/** @var FormField $field */
foreach ($this as $field) {
if ($field instanceof CompositeField) {
$field->collateDataFields($list, $saveableOnly);
}
if ($saveableOnly) {
$isIncluded = $field->canSubmitValue();
} else {
$isIncluded = $field->hasData();
}
if ($isIncluded) {
$name = $field->getName();
if (isset($list[$name])) {
if ($this->form) {
$formClass = get_class($this->form);
$errSuffix = " in your '{$formClass}' form called '" . $this->form->Name() . "'";
} else {
$errSuffix = '';
}
throw new \RuntimeException(
"collateDataFields() I noticed that a field called '$name' appears twice$errSuffix."
);
}
$list[$name] = $field;
}
}
}
/**
* Add an extra field to a tab within this FieldList.
* This is most commonly used when overloading getCMSFields()
@ -563,19 +521,9 @@ class FieldList extends ArrayList
/**
* Inserts a field before a particular field in a FieldList.
* Will traverse CompositeFields depth-first to find the matching $name, and insert before the first match
*
* @param string $name Name of the field to insert before
* @param FormField $item The form field to insert
* @param bool $appendIfMissing Append to the end of the list if $name isn't found
* @return FormField|false Field if it was successfully inserted, false if not inserted
*/
public function insertBefore($name, $item, $appendIfMissing = true)
public function insertBefore(string $name, FormField $item, bool $appendIfMissing = true): FormField|bool
{
// Backwards compatibility for order of arguments
if ($name instanceof FormField) {
Deprecation::notice('5.0', 'Incorrect order of arguments for insertBefore');
list($item, $name) = [$name, $item];
}
$this->onBeforeInsert($item);
$item->setContainerFieldList($this);
@ -605,19 +553,9 @@ class FieldList extends ArrayList
/**
* Inserts a field after a particular field in a FieldList.
* Will traverse CompositeFields depth-first to find the matching $name, and insert after the first match
*
* @param string $name Name of the field to insert after
* @param FormField $item The form field to insert
* @param bool $appendIfMissing Append to the end of the list if $name isn't found
* @return FormField|false Field if it was successfully inserted, false if not inserted
*/
public function insertAfter($name, $item, $appendIfMissing = true)
public function insertAfter(string $name, FormField $item, bool $appendIfMissing = true): FormField|bool
{
// Backwards compatibility for order of arguments
if ($name instanceof FormField) {
Deprecation::notice('5.0', 'Incorrect order of arguments for insertAfter');
list($item, $name) = [$name, $item];
}
$this->onBeforeInsert($item);
$item->setContainerFieldList($this);

View File

@ -11,9 +11,7 @@ use SilverStripe\Control\NullHTTPRequest;
use SilverStripe\Control\RequestHandler;
use SilverStripe\Control\Session;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\ORM\FieldType\DBHTMLText;
@ -85,7 +83,7 @@ class Form extends ViewableData implements HasRequestHandler
const ENC_TYPE_MULTIPART = 'multipart/form-data';
/**
* Accessed by Form.ss; modified by {@link formHtmlContent()}.
* Accessed by Form.ss.
* A performance enhancement over the generate-the-form-tag-and-then-remove-it code that was there previously
*
* @var bool
@ -1583,32 +1581,6 @@ class Form extends ViewableData implements HasRequestHandler
return $return;
}
/**
* Returns an HTML rendition of this form, without the <form> tag itself.
*
* Attaches 3 extra hidden files, _form_action, _form_name, _form_method,
* and _form_enctype. These are the attributes of the form. These fields
* can be used to send the form to Ajax.
*
* @deprecated 4.12.0 Will be removed without equivalent functionality
* @return string
*/
public function formHtmlContent()
{
Deprecation::notice('4.12.0', 'Will be removed without equivalent functionality');
$this->IncludeFormTag = false;
$content = $this->forTemplate();
$this->IncludeFormTag = true;
$content .= "<input type=\"hidden\" name=\"_form_action\" id=\"" . $this->FormName() . "_form_action\""
. " value=\"" . $this->FormAction() . "\" />\n";
$content .= "<input type=\"hidden\" name=\"_form_name\" value=\"" . $this->FormName() . "\" />\n";
$content .= "<input type=\"hidden\" name=\"_form_method\" value=\"" . $this->FormMethod() . "\" />\n";
$content .= "<input type=\"hidden\" name=\"_form_enctype\" value=\"" . $this->getEncType() . "\" />\n";
return $content;
}
/**
* Render this form using the given template, and return the result as a string
* You can pass either an SSViewer or a template name

View File

@ -1058,7 +1058,6 @@ class FormField extends RequestHandler
* make sense for data-focused methods to look at them. By overloading hasData() to return
* false, you can prevent any data-focused methods from looking at it.
*
* @see FieldList::collateDataFields()
*
* @return bool
*/

View File

@ -6,15 +6,9 @@ use LogicException;
use SilverStripe\Admin\LeftAndMain;
use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Convert;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Forms\FieldGroup;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\Schema\FormSchema;
use SilverStripe\Forms\TextField;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\Filterable;
use SilverStripe\ORM\SS_List;
use SilverStripe\View\ArrayData;
@ -35,25 +29,6 @@ class GridFieldFilterHeader extends AbstractGridFieldComponent implements GridFi
*/
protected $throwExceptionOnBadDataType = true;
/**
* Indicates that this component should revert to displaying it's legacy
* table header style rather than the react driven search box
*
* @deprecated 4.3.0:5.0.0 Will be removed in 5.0
* @var bool
*/
public $useLegacyFilterHeader = false;
/**
* Forces all filter components to revert to displaying the legacy
* table header style rather than the react driven search box
*
* @deprecated 4.3.0:5.0.0 Will be removed in 5.0
* @config
* @var bool
*/
private static $force_legacy = false;
/**
* @var \SilverStripe\ORM\Search\SearchContext
*/
@ -64,18 +39,6 @@ class GridFieldFilterHeader extends AbstractGridFieldComponent implements GridFi
*/
protected $searchForm = null;
/**
* @var callable
* @deprecated 4.3.0:5.0.0 Will be removed in 5.0
*/
protected $updateSearchContextCallback = null;
/**
* @var callable
* @deprecated 4.3.0:5.0.0 Will be removed in 5.0
*/
protected $updateSearchFormCallback = null;
/**
* The name of the default search field
* @var string|null
@ -92,24 +55,6 @@ class GridFieldFilterHeader extends AbstractGridFieldComponent implements GridFi
];
}
/**
* @param bool $useLegacy This will be removed in 5.0
* @param callable|null $updateSearchContext This will be removed in 5.0
* @param callable|null $updateSearchForm This will be removed in 5.0
*/
public function __construct(
$useLegacy = false,
callable $updateSearchContext = null,
callable $updateSearchForm = null
) {
$forceLegacy = Deprecation::withNoReplacement(function () {
return Config::inst()->get(self::class, 'force_legacy');
});
$this->useLegacyFilterHeader = $forceLegacy || $useLegacy;
$this->updateSearchContextCallback = $updateSearchContext;
$this->updateSearchFormCallback = $updateSearchForm;
}
/**
* Determine what happens when this component is used with a list that isn't {@link SS_Filterable}.
*
@ -283,10 +228,6 @@ class GridFieldFilterHeader extends AbstractGridFieldComponent implements GridFi
{
if (!$this->searchContext) {
$this->searchContext = singleton($gridField->getModelClass())->getDefaultSearchContext();
if ($this->updateSearchContextCallback) {
call_user_func($this->updateSearchContextCallback, $this->searchContext);
}
}
return $this->searchContext;
@ -322,7 +263,7 @@ class GridFieldFilterHeader extends AbstractGridFieldComponent implements GridFi
// Prefix "Search__" onto the filters for the React component
$filters = $context->getSearchParams();
if (!$this->useLegacyFilterHeader && !empty($filters)) {
if (!empty($filters)) {
$filters = array_combine(array_map(function ($key) {
return 'Search__' . $key;
}, array_keys($filters ?? [])), $filters ?? []);
@ -403,10 +344,6 @@ class GridFieldFilterHeader extends AbstractGridFieldComponent implements GridFi
$form->disableSecurityToken(); // This form is not tied to session so we disable this
$form->loadDataFrom($searchContext->getSearchParams());
if ($this->updateSearchFormCallback) {
call_user_func($this->updateSearchFormCallback, $form);
}
return $this->searchForm;
}
@ -435,82 +372,6 @@ class GridFieldFilterHeader extends AbstractGridFieldComponent implements GridFi
return $response;
}
/**
* Generate fields for the legacy filter header row
*
* @deprecated 4.12.0 Use search field instead
* @param GridField $gridfield
* @return ArrayList|null
*/
public function getLegacyFilterHeader(GridField $gridField)
{
Deprecation::notice('4.12.0', 'Use search field instead');
$list = $gridField->getList();
if (!$this->checkDataType($list)) {
return null;
}
$columns = $gridField->getColumns();
$filterArguments = $this->getState($gridField)->Columns->toArray();
$currentColumn = 0;
$canFilter = false;
$fieldsList = new ArrayList();
foreach ($columns as $columnField) {
$currentColumn++;
$metadata = $gridField->getColumnMetadata($columnField);
$title = $metadata['title'];
$fields = new FieldGroup();
if ($title && $list->canFilterBy($columnField)) {
$canFilter = true;
$value = '';
if (isset($filterArguments[$columnField])) {
$value = $filterArguments[$columnField];
}
$field = new TextField('filter[' . $gridField->getName() . '][' . $columnField . ']', '', $value);
$field->addExtraClass('grid-field__sort-field');
$field->addExtraClass('no-change-track');
$field->setAttribute(
'placeholder',
_t('SilverStripe\\Forms\\GridField\\GridField.FilterBy', "Filter by ") . _t('SilverStripe\\Forms\\GridField\\GridField.' . $metadata['title'], $metadata['title'])
);
$fields->push($field);
$fields->push(
GridField_FormAction::create($gridField, 'reset', false, 'reset', null)
->addExtraClass('btn font-icon-cancel btn-secondary btn--no-text ss-gridfield-button-reset')
->setAttribute('title', _t('SilverStripe\\Forms\\GridField\\GridField.ResetFilter', "Reset"))
->setAttribute('id', 'action_reset_' . $gridField->getModelClass() . '_' . $columnField)
);
}
if ($currentColumn == count($columns ?? [])) {
$fields->push(
GridField_FormAction::create($gridField, 'filter', false, 'filter', null)
->addExtraClass('btn font-icon-search btn--no-text btn--icon-large grid-field__filter-submit ss-gridfield-button-filter')
->setAttribute('title', _t('SilverStripe\\Forms\\GridField\\GridField.Filter', 'Filter'))
->setAttribute('id', 'action_filter_' . $gridField->getModelClass() . '_' . $columnField)
);
$fields->push(
GridField_FormAction::create($gridField, 'reset', false, 'reset', null)
->addExtraClass('btn font-icon-cancel btn--no-text grid-field__filter-clear btn--icon-md ss-gridfield-button-close')
->setAttribute('title', _t('SilverStripe\\Forms\\GridField\\GridField.ResetFilter', "Reset"))
->setAttribute('id', 'action_reset_' . $gridField->getModelClass() . '_' . $columnField)
);
$fields->addExtraClass('grid-field__filter-buttons');
$fields->addExtraClass('no-change-track');
}
$fieldsList->push($fields);
}
return $canFilter ? $fieldsList : null;
}
/**
* Either returns the legacy filter header or the search button and field
*
@ -525,14 +386,6 @@ class GridFieldFilterHeader extends AbstractGridFieldComponent implements GridFi
return null;
}
if ($this->useLegacyFilterHeader) {
$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)];
} else {
$fieldSchema = $this->getSearchFieldSchema($gridField);
$forTemplate->SearchFieldSchema = $fieldSchema;
$searchTemplates = SSViewer::get_templates_by_class($this, '_Search', __CLASS__);
@ -546,5 +399,4 @@ class GridFieldFilterHeader extends AbstractGridFieldComponent implements GridFi
)
];
}
}
}

View File

@ -190,7 +190,7 @@ class GridFieldSortableHeader extends AbstractGridFieldComponent implements Grid
if ($currentColumn == count($columns ?? [])) {
$filter = $gridField->getConfig()->getComponentByType(GridFieldFilterHeader::class);
if ($filter && $filter->useLegacyFilterHeader && $filter->canFilterAnyColumns($gridField)) {
if ($filter && $filter->canFilterAnyColumns($gridField)) {
$field = new LiteralField(
$fieldName,
sprintf(

View File

@ -1,23 +0,0 @@
<?php
namespace SilverStripe\Forms\GridField;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Versioned\VersionedGridFieldState\VersionedGridFieldState;
if (!class_exists(VersionedGridFieldState::class)) {
return;
}
/**
* @deprecated 4.1.0 Use VersionedGridFieldState instead
*/
class GridFieldVersionedState extends VersionedGridFieldState
{
public function __construct(array $versionedLabelFields = ['Name', 'Title'])
{
Deprecation::notice('4.1.0', 'Use VersionedGridFieldState instead', Deprecation::SCOPE_CLASS);
parent::__construct($versionedLabelFields);
}
}

View File

@ -7,11 +7,8 @@ use SilverStripe\Assets\Folder;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Manifest\Module;
use SilverStripe\Core\Manifest\ModuleLoader;
use SilverStripe\Core\Manifest\ModuleResource;
use SilverStripe\Core\Manifest\ModuleResourceLoader;
use SilverStripe\Dev\Deprecation;
use SilverStripe\i18n\i18n;
use SilverStripe\i18n\i18nEntityProvider;
use SilverStripe\View\Requirements;
@ -924,25 +921,6 @@ class TinyMCEConfig extends HTMLEditorConfig implements i18nEntityProvider
));
}
/**
* @deprecated 4.0.1 Use getTinyMCEResourcePath() instead
*/
public function getTinyMCEPath()
{
Deprecation::notice('4.0.1', 'Use getTinyMCEResourcePath() instead');
return $this->getTinyMCEResourcePath();
}
/**
* @return Module
* @deprecated 4.0.1 Set base_dir or editor_css config instead
*/
protected function getAdminModule()
{
Deprecation::notice('4.0.1', 'Set base_dir or editor_css config instead');
return ModuleLoader::getModule('silverstripe/admin');
}
/**
* Sets the upload folder name used by the insert media dialog
*

View File

@ -2,8 +2,6 @@
namespace SilverStripe\Forms;
use SilverStripe\Dev\Deprecation;
/**
* Password input field.
*/
@ -34,14 +32,6 @@ class PasswordField extends TextField
*/
public function __construct($name, $title = null, $value = '')
{
if (count(func_get_args()) > 3) {
Deprecation::notice(
'3.0',
'Use setMaxLength() instead of constructor arguments',
Deprecation::SCOPE_GLOBAL
);
}
parent::__construct($name, $title, $value);
}

View File

@ -2,8 +2,6 @@
namespace SilverStripe\Forms;
use SilverStripe\Dev\Deprecation;
/**
* Text input field.
*/
@ -119,21 +117,6 @@ class TextField extends FormField implements TippableFieldInterface
return $data;
}
/**
* @return string
* @deprecated 4.0.1 Use setValue() instead
*/
public function InternallyLabelledField()
{
Deprecation::notice('4.0.1', 'Use setValue() instead');
if (!$this->value) {
$this->value = $this->Title();
}
return $this->Field();
}
/**
* Validate this field
*

View File

@ -5,7 +5,6 @@ namespace SilverStripe\Logging;
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Monolog\ErrorHandler as MonologHandler;
use SilverStripe\Dev\Deprecation;
class MonologErrorHandler implements ErrorHandler
{
@ -14,35 +13,6 @@ class MonologErrorHandler implements ErrorHandler
*/
private $loggers = [];
/**
* Set the PSR-3 logger to send errors & exceptions to. Will overwrite any previously configured
* loggers
*
* @deprecated 4.4.0 Use pushLogger() instead
* @param LoggerInterface $logger
* @return $this
*/
public function setLogger(LoggerInterface $logger)
{
Deprecation::notice('4.4.0', 'Use pushLogger() instead');
$this->loggers = [$logger];
return $this;
}
/**
* Get the first registered PSR-3 logger to send errors & exceptions to
*
* @deprecated 4.4.0 Use getLoggers() instead
* @return LoggerInterface
*/
public function getLogger()
{
Deprecation::notice('4.4.0', 'Use getLoggers() instead');
return reset($this->loggers);
}
/**
* Adds a PSR-3 logger to send messages to, to the end of the stack
*

View File

@ -6,7 +6,6 @@ use ArrayIterator;
use InvalidArgumentException;
use LogicException;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\Deprecation;
use SilverStripe\View\ArrayData;
use SilverStripe\View\ViewableData;
@ -187,29 +186,7 @@ class ArrayList extends ViewableData implements SS_List, Filterable, Sortable, L
*/
public function limit($length, $offset = 0)
{
// Type checking: designed for consistency with DataList::limit()
if ((!is_numeric($length) || !is_numeric($offset)) && !is_null($length)) {
Deprecation::notice(
'4.3',
'Arguments to ArrayList::limit() should be numeric or null'
);
}
if ($length < 0 || $offset < 0) {
Deprecation::notice(
'4.3',
'Arguments to ArrayList::limit() should be positive'
);
}
if (!$length) {
if ($length === 0) {
Deprecation::notice(
'4.3',
"limit(0) is deprecated in SS4. In SS5 a limit of 0 will instead return no records."
);
}
$length = count($this->items ?? []);
}

View File

@ -753,11 +753,10 @@ abstract class Database
/**
* Commit everything inside this transaction so far
*
* @param bool $chain
* @return bool|null Boolean is returned if success state is known, or null if
* Boolean is returned if success state is known, or null if
* unknown. Note: For error checking purposes null should not be treated as error.
*/
abstract public function transactionEnd($chain = false);
abstract public function transactionEnd(): bool|null;
/**
* Return depth of current transaction

View File

@ -6,7 +6,6 @@ use SilverStripe\Assets\File;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Convert;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\PaginatedList;
use SilverStripe\ORM\DataList;
use SilverStripe\ORM\ArrayList;
@ -353,15 +352,10 @@ class MySQLDatabase extends Database implements TransactionManager
return $this->getTransactionManager()->transactionDepth();
}
public function transactionEnd($chain = false)
public function transactionEnd():bool|null
{
$result = $this->getTransactionManager()->transactionEnd();
if ($chain) {
Deprecation::notice('4.4', '$chain argument is deprecated');
return $this->getTransactionManager()->transactionStart();
}
return $result;
}

View File

@ -373,7 +373,7 @@ class MySQLSchemaManager extends DBSchemaManager
public function enumValuesForField($tableName, $fieldName)
{
// Get the enum of all page types from the SiteTree table
$classnameinfo = $this->query("DESCRIBE \"$tableName\" \"$fieldName\"")->first();
$classnameinfo = $this->query("DESCRIBE \"$tableName\" \"$fieldName\"")->record();
preg_match_all("/'[^,]+'/", $classnameinfo["Type"] ?? '', $matches);
$classes = [];

View File

@ -2,8 +2,6 @@
namespace SilverStripe\ORM\Connect;
use SilverStripe\Dev\Deprecation;
/**
* TransactionManager that executes MySQL-compatible transaction control queries
*/

View File

@ -264,9 +264,9 @@ class NullDatabase extends Database
// no-op
}
public function transactionEnd($chain = false)
public function transactionEnd(): bool|null
{
// no-op
return false;
}
public function transactionDepth()

View File

@ -95,15 +95,6 @@ abstract class Query implements \IteratorAggregate
return $this->getIterator()->current();
}
/**
* @deprecated Use record() instead
* @return array
*/
public function first()
{
return $this->record();
}
/**
* Returns the first column of the first record.
*

View File

@ -2,7 +2,6 @@
namespace SilverStripe\ORM;
use BadMethodCallException;
use InvalidArgumentException;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
@ -10,7 +9,6 @@ use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Environment;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\Connect\Database;
use SilverStripe\ORM\Connect\DBConnector;
use SilverStripe\ORM\Connect\DBSchemaManager;
@ -111,16 +109,6 @@ class DB
return null;
}
/**
* @deprecated 4.0.1 Use DB::get_conn() instead
* @todo PSR-2 standardisation will probably un-deprecate this
*/
public static function getConn($name = 'default')
{
Deprecation::notice('4.0.1', 'Use DB::get_conn() instead');
return self::get_conn($name);
}
/**
* Retrieves the schema manager for the current database
*

View File

@ -2,7 +2,6 @@
namespace SilverStripe\ORM;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Extension;
use SilverStripe\Forms\FieldList;
@ -19,15 +18,6 @@ use Exception;
abstract class DataExtension extends Extension
{
/**
* @deprecated 4.7.0 Will be removed without equivalent functionality
*/
public static function unload_extra_statics($class, $extension)
{
Deprecation::notice('4.7.0', 'Will be removed without equivalent functionality');
throw new Exception('unload_extra_statics gone');
}
/**
* Hook for extension-specific validation.
*

View File

@ -11,7 +11,6 @@ use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Resettable;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FormField;
use SilverStripe\Forms\FormScaffolder;
@ -30,7 +29,6 @@ use SilverStripe\ORM\Queries\SQLDelete;
use SilverStripe\ORM\Search\SearchContext;
use SilverStripe\ORM\RelatedData\RelatedDataService;
use SilverStripe\ORM\UniqueKey\UniqueKeyInterface;
use SilverStripe\ORM\UniqueKey\UniqueKeyService;
use SilverStripe\Security\Member;
use SilverStripe\Security\Permission;
use SilverStripe\Security\Security;
@ -143,12 +141,6 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
*/
private static $default_classname = null;
/**
* @deprecated 4.0.0:5.0.0
* @var bool
*/
public $destroyed = false;
/**
* Data stored in this objects database record. An array indexed by fieldname.
*
@ -504,26 +496,13 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
/**
* Create a duplicate of this node. Can duplicate many_many relations
*
* @param bool $doWrite Perform a write() operation before returning the object.
* If this is true, it will create the duplicate in the database.
* @param array|null|false $relations List of relations to duplicate.
* Will default to `cascade_duplicates` if null.
* Set to 'false' to force none.
* Set to specific array of names to duplicate to override these.
* Note: If using versioned, this will additionally failover to `owns` config.
* @return static A duplicate of this node. The exact type will be the type of this node.
*/
public function duplicate($doWrite = true, $relations = null)
public function duplicate(bool $doWrite = true, array|null $relations = null): static
{
// Handle legacy behaviour
if (is_string($relations) || $relations === true) {
if ($relations === true) {
$relations = 'many_many';
}
Deprecation::notice('5.0', 'Use cascade_duplicates config instead of providing a string to duplicate()');
$relations = array_keys($this->config()->get($relations) ?? []) ?: [];
}
// Get duplicates
if ($relations === null) {
$relations = $this->config()->get('cascade_duplicates');
@ -597,31 +576,6 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
}
}
/**
* Copies the many_many and belongs_many_many relations from one object to another instance of the name of object.
*
* @deprecated 4.1.0 Use duplicateRelations() instead
* @param DataObject $sourceObject the source object to duplicate from
* @param DataObject $destinationObject the destination object to populate with the duplicated relations
* @param bool|string $filter
*/
protected function duplicateManyManyRelations($sourceObject, $destinationObject, $filter)
{
Deprecation::notice('4.1.0', 'Use duplicateRelations() instead');
// Get list of relations to duplicate
if ($filter === 'many_many' || $filter === 'belongs_many_many') {
$relations = $sourceObject->config()->get($filter);
} elseif ($filter === true) {
$relations = $sourceObject->manyMany();
} else {
throw new InvalidArgumentException("Invalid many_many duplication filter");
}
foreach ($relations as $manyManyName => $type) {
$this->duplicateManyManyRelation($sourceObject, $destinationObject, $manyManyName);
}
}
/**
* Duplicates a single many_many relation from one object to another.
*
@ -1262,18 +1216,6 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
return $result;
}
/**
* Public accessor for {@see DataObject::validate()}
*
* @return ValidationResult
* @deprecated 4.12.0 Use validate() instead
*/
public function doValidate()
{
Deprecation::notice('4.12.0', 'Use validate() instead');
return $this->validate();
}
/**
* Event handler called before writing to the database.
* You can overload this to clean up or otherwise process data before writing it to the

View File

@ -485,7 +485,7 @@ class DataQuery
// Wrap the whole thing in an "EXISTS"
$sql = 'SELECT CASE WHEN EXISTS(' . $statement->sql($params) . ') THEN 1 ELSE 0 END';
$result = DB::prepared_query($sql, $params);
$row = $result->first();
$row = $result->record();
$result = reset($row);
// Checking for 't' supports PostgreSQL before silverstripe/postgresql@2.2

View File

@ -10,7 +10,6 @@ use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Environment;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Manifest\ClassLoader;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\DevelopmentAdmin;
use SilverStripe\ORM\Connect\DatabaseException;
use SilverStripe\ORM\Connect\TableBuilder;
@ -368,22 +367,6 @@ class DatabaseAdmin extends Controller
$this->extend('onAfterBuild', $quiet, $populate, $testMode);
}
/**
* Given a base data class, a field name and an old and new class name (value), look for obsolete ($oldClassName)
* values in the $dataClass's $fieldName column and replace it with $newClassName.
*
* @param string $dataClass The data class to look up
* @param string $fieldName The field name to look in for obsolete class names
* @param string $oldClassName The old class name
* @param string $newClassName The new class name
* @deprecated 4.12.0 Use updateLegacyClassNameField() instead
*/
protected function updateLegacyClassNames($dataClass, $fieldName, $oldClassName, $newClassName)
{
Deprecation::notice('4.12.0', 'Use updateLegacyClassNameField() instead');
$this->updateLegacyClassNameField($dataClass, $fieldName, [$oldClassName => $newClassName]);
}
/**
* Given a base data class, a field name and a mapping of class replacements, look for obsolete
* values in the $dataClass's $fieldName column and replace it with $mapping

View File

@ -4,7 +4,6 @@ namespace SilverStripe\ORM\FieldType;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DB;
@ -32,17 +31,6 @@ class DBClassName extends DBEnum
private static $index = true;
/**
* Clear all cached classname specs. It's necessary to clear all cached subclassed names
* for any classes if a new class manifest is generated.
* @deprecated 4.3.0 Use DBEnum::flushCache() instead
*/
public static function clear_classname_cache()
{
Deprecation::notice('4.3.0', 'Use DBEnum::flushCache() instead');
DBEnum::flushCache();
}
/**
* Create a new DBClassName field
*

View File

@ -5,7 +5,6 @@ namespace SilverStripe\ORM;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\Queries\SQLSelect;
/**
@ -54,27 +53,17 @@ class ManyManyThroughQueryManipulator implements DataQueryManipulator
/**
* Build query manipulator for a given join table. Additional parameters (foreign key, etc)
* will be inferred at evaluation from query parameters set via the ManyManyThroughList
*
* @param string $joinClass Class name of the joined dataobject record
* @param string $localKey The key in the join table that maps to the dataClass' PK.
* @param string $foreignKey The key in the join table that maps to joined class' PK.
* @param string $foreignClass the 'from' class name
* @param string $parentClass Name of parent class. Subclass of $foreignClass
*/
public function __construct($joinClass, $localKey, $foreignKey, $foreignClass = null, $parentClass = null)
public function __construct(string $joinClass, string $localKey, string $foreignKey, string $foreignClass, string $parentClass)
{
$this->setJoinClass($joinClass);
$this->setLocalKey($localKey);
$this->setForeignKey($foreignKey);
if ($foreignClass) {
$this->setForeignClass($foreignClass);
} else {
Deprecation::notice('5.0', 'Arg $foreignClass will be mandatory in 5.x');
}
if ($parentClass) {
$this->setParentClass($parentClass);
} else {
Deprecation::notice('5.0', 'Arg $parentClass will be mandatory in 5.x');
}
}

View File

@ -2,8 +2,6 @@
namespace SilverStripe\ORM\Queries;
use SilverStripe\Dev\Deprecation;
/**
* Represents a SQL query for an expression which interacts with existing rows
* (SELECT / DELETE / UPDATE) with a WHERE clause
@ -265,14 +263,6 @@ abstract class SQLConditionalExpression extends SQLExpression
*/
public function getJoins(&$parameters = [])
{
if (func_num_args() == 0) {
Deprecation::notice(
'4.0',
'SQLConditionalExpression::getJoins() now may produce parameters which are necessary to
execute this query'
);
}
// Sort the joins
$parameters = [];
$joins = $this->getOrderedJoins($this->from);

View File

@ -3,7 +3,6 @@
namespace SilverStripe\ORM\Queries;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\DB;
use InvalidArgumentException;
@ -250,14 +249,6 @@ class SQLSelect extends SQLConditionalExpression
throw new InvalidArgumentException("SQLSelect::setLimit() only takes positive values");
}
if ($limit === 0) {
Deprecation::notice(
'4.3',
"setLimit(0) is deprecated in SS4. To clear limit, call setLimit(null). " .
"In SS5 a limit of 0 will instead return no records."
);
}
if (is_numeric($limit) && ($limit || $offset)) {
$this->limit = [
'start' => (int)$offset,

View File

@ -75,13 +75,6 @@ class SearchContext
*/
protected $searchParams = [];
/**
* The logical connective used to join WHERE clauses. Must be "AND".
* @deprecated 5.0
* @var string
*/
public $connective = 'AND';
/**
* A key value pair of values that should be searched for.
* The keys should match the field names specified in {@link self::$fields}.
@ -147,9 +140,6 @@ class SearchContext
*/
public function getQuery($searchParams, $sort = false, $limit = false, $existingQuery = null)
{
if ($this->connective != "AND") {
throw new Exception("SearchContext connective '$this->connective' not supported after ORM-rewrite.");
}
$this->setSearchParams($searchParams);
$query = $this->prepareQuery($sort, $limit, $existingQuery);
return $this->search($query);

View File

@ -3,10 +3,7 @@
namespace SilverStripe\ORM;
use InvalidArgumentException;
use Serializable;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Dev\Deprecation;
/**
* A class that combined as a boolean result with an optional list of error messages.
@ -15,7 +12,7 @@ use SilverStripe\Dev\Deprecation;
* Each message can have a code or field which will uniquely identify that message. However,
* messages can be stored without a field or message as an "overall" message.
*/
class ValidationResult implements Serializable
class ValidationResult
{
use Injectable;
@ -64,22 +61,6 @@ class ValidationResult implements Serializable
*/
protected $messages = [];
/**
* Create a new ValidationResult.
* By default, it is a successful result. Call $this->error() to record errors.
*/
public function __construct()
{
if (func_num_args() > 0) {
Deprecation::notice('3.2', '$valid parameter is deprecated please addError to mark the result as invalid', false);
$this->isValid = func_get_arg(0);
}
if (func_num_args() > 1) {
Deprecation::notice('3.2', '$message parameter is deprecated please use addMessage or addError instead', false);
$this->addError(func_get_arg(1));
}
}
/**
* Record an error against this validation result,
*
@ -227,30 +208,4 @@ class ValidationResult implements Serializable
$this->messages = $data['messages'];
$this->isValid = $data['isValid'];
}
/**
* The __serialize() magic method will be automatically used instead of this
*
* @return string
* @deprecated 4.12.0 Use __serialize() instead
*/
public function serialize()
{
Deprecation::notice('4.12.0', 'Use __serialize() instead');
return json_encode([$this->messages, $this->isValid]);
}
/**
* The __unserialize() magic method will be automatically used instead of this almost all the time
* This method will be automatically used if existing serialized data was not saved as an associative array
* and the PHP version used in less than PHP 9.0
*
* @param string $serialized
* @deprecated 4.12.0 Use __unserialize() instead
*/
public function unserialize($serialized)
{
Deprecation::notice('4.12.0', 'Use __unserialize() instead');
list($this->messages, $this->isValid) = json_decode($serialized ?? '', true);
}
}

View File

@ -15,13 +15,12 @@ use SilverStripe\ORM\DataObject;
* complies with your privacy standards. We're logging
* username and IP.
*
* @property string $Email Email address used for login attempt. @deprecated 3.0.0:5.0.0
* @property string $EmailHashed sha1 hashed Email address used for login attempt
* @property string $Status Status of the login attempt, either 'Success' or 'Failure'
* @property string $IP IP address of user attempting to login
* @property int $MemberID ID of the Member, only if Member with Email exists
* @property int $MemberID ID of the Member
*
* @method Member Member() Member object of the user trying to log in, only if Member with Email exists
* @method Member Member() Member object of the user trying to log in
*/
class LoginAttempt extends DataObject
{
@ -36,7 +35,6 @@ class LoginAttempt extends DataObject
const FAILURE = 'Failure';
private static $db = [
'Email' => 'Varchar(255)', // Remove in 5.0
'EmailHashed' => 'Varchar(255)',
'Status' => "Enum('Success,Failure')",
'IP' => 'Varchar(255)',
@ -60,7 +58,6 @@ class LoginAttempt extends DataObject
public function fieldLabels($includerelations = true)
{
$labels = parent::fieldLabels($includerelations);
$labels['Email'] = _t(__CLASS__ . '.Email', 'Email Address');
$labels['EmailHashed'] = _t(__CLASS__ . '.EmailHashed', 'Email Address (hashed)');
$labels['Status'] = _t(__CLASS__ . '.Status', 'Status');
$labels['IP'] = _t(__CLASS__ . '.IP', 'IP Address');

View File

@ -15,12 +15,6 @@ use SilverStripe\Forms\Form;
*/
abstract class LoginForm extends Form
{
/**
* @deprecated 4.4.0:5.0.0 Use getAuthenticatorClass() or setAuthenticatorClass() instead
* @var string
*/
protected $authenticator_class;
/**
* Authenticator class to use with this login form
*
@ -61,8 +55,7 @@ abstract class LoginForm extends Form
*/
public function getAuthenticatorClass()
{
// B/C for deprecated authenticator_class property
return $this->authenticator_class ?: $this->authenticatorClass;
return $this->authenticatorClass;
}
/**

View File

@ -6,14 +6,12 @@ use IntlDateFormatter;
use InvalidArgumentException;
use SilverStripe\Admin\LeftAndMain;
use SilverStripe\CMS\Controllers\CMSMain;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Control\Email\Email;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\TestMailer;
use SilverStripe\Forms\ConfirmedPasswordField;
use SilverStripe\Forms\DropdownField;
@ -162,7 +160,7 @@ class Member extends DataObject
/**
* @config
* @var array See {@link set_title_columns()}
* @var array
*/
private static $title_format = null;
@ -279,42 +277,6 @@ class Member extends DataObject
$service->findOrCreateDefaultAdmin();
}
/**
* Get the default admin record if it exists, or creates it otherwise if enabled
*
* @deprecated 4.0.1 Use DefaultAdminService::findOrCreateDefaultAdmin() instead
* @return Member
*/
public static function default_admin()
{
Deprecation::notice('4.0.1', 'Use DefaultAdminService::findOrCreateDefaultAdmin() instead');
return DefaultAdminService::singleton()->findOrCreateDefaultAdmin();
}
/**
* Check if the passed password matches the stored one (if the member is not locked out).
*
* @deprecated 4.0.1 Use Authenticator::checkPassword() instead
*
* @param string $password
* @return ValidationResult
*/
public function checkPassword($password)
{
Deprecation::notice('4.0.1', 'Use Authenticator::checkPassword() instead');
// With a valid user and password, check the password is correct
$result = ValidationResult::create();
$authenticators = Security::singleton()->getApplicableAuthenticators(Authenticator::CHECK_PASSWORD);
foreach ($authenticators as $authenticator) {
$authenticator->checkPassword($this, $password, $result);
if (!$result->isValid()) {
break;
}
}
return $result;
}
/**
* Check if this user is the currently configured default admin
*
@ -447,16 +409,6 @@ class Member extends DataObject
return strtotime(date('Y-m-d')) >= strtotime($this->PasswordExpiry ?? '');
}
/**
* @deprecated 4.12.0 Use Security::setCurrentUser() or IdentityStore::logIn() instead
*
*/
public function logIn()
{
Deprecation::notice('4.12.0', 'Use Security::setCurrentUser() or IdentityStore::logIn() instead');
Security::setCurrentUser($this);
}
/**
* Called before a member is logged in via session/cookie/etc
*/
@ -501,39 +453,6 @@ class Member extends DataObject
$this->write();
}
/**
* Check if the member ID logged in session actually
* has a database record of the same ID. If there is
* no logged in user, FALSE is returned anyway.
*
* @deprecated 4.12.0 Use Security::getCurrentUser() instead
*
* @return boolean TRUE record found FALSE no record found
*/
public static function logged_in_session_exists()
{
Deprecation::notice('4.12.0', 'Use Security::getCurrentUser() instead');
$member = Security::getCurrentUser();
if ($member && $member->exists()) {
return true;
}
return false;
}
/**
* Logs this member out.
*
* @deprecated 4.12.0 Use Security::setCurrentUser(null) or an IdentityStore instead
*/
public function logOut()
{
Deprecation::notice('4.12.0', 'Use Security::setCurrentUser(null) or an IdentityStore instead');
Injector::inst()->get(IdentityStore::class)->logOut(Controller::curr()->getRequest());
}
/**
* Audit logging hook, called before a member is logged out
*
@ -583,23 +502,11 @@ class Member extends DataObject
* Generate an auto login token which can be used to reset the password,
* at the same time hashing it and storing in the database.
*
* @param int|null $lifetime DEPRECATED: The lifetime of the auto login hash in days. Overrides
* the Member.auto_login_token_lifetime config value
* @return string Token that should be passed to the client (but NOT persisted).
*/
public function generateAutologinTokenAndStoreHash($lifetime = null)
public function generateAutologinTokenAndStoreHash()
{
if ($lifetime !== null) {
Deprecation::notice(
'5.0',
'Passing a $lifetime to Member::generateAutologinTokenAndStoreHash() is deprecated,
use the Member.auto_login_token_lifetime config setting instead',
Deprecation::SCOPE_GLOBAL
);
$lifetime = (86400 * $lifetime); // Method argument is days, convert to seconds
} else {
$lifetime = $this->config()->auto_login_token_lifetime;
}
do {
$generator = new RandomGenerator();
@ -758,27 +665,13 @@ class Member extends DataObject
}
/**
* Returns the current logged in user
*
* @deprecated 4.12.0 Use Security::getCurrentUser() instead
*
* @return Member
*/
public static function currentUser()
{
Deprecation::notice('4.12.0', 'Use Security::getCurrentUser() instead');
return Security::getCurrentUser();
}
/**
* Temporarily act as the specified user, limited to a $callback, but
* without logging in as that user.
*
* E.g.
* <code>
* Member::actAs(Security::findAnAdministrator(), function() {
* Member::actAs(DefaultAdminService::findOrCreateDefaultAdmin(), function() {
* $record->write();
* });
* </code>
@ -805,56 +698,6 @@ class Member extends DataObject
}
}
/**
* Get the ID of the current logged in user
*
* @deprecated 4.12.0 Use Security::getCurrentUser() instead
*
* @return int Returns the ID of the current logged in user or 0.
*/
public static function currentUserID()
{
Deprecation::notice('4.12.0', 'Use Security::getCurrentUser() instead');
$member = Security::getCurrentUser();
if ($member) {
return $member->ID;
}
return 0;
}
/**
* Generate a random password, with randomiser to kick in if there's no words file on the
* filesystem.
*
* @return string Returns a random password.
*
* @deprecated 4.12.0 Will be removed without equivalent functionality to replace it
*/
public static function create_new_password()
{
Deprecation::notice('4.12.0', 'Will be removed without equivalent functionality to replace it');
$words = Security::config()->uninherited('word_list');
if ($words && file_exists($words ?? '')) {
$words = file($words ?? '');
list($usec, $sec) = explode(' ', microtime() ?? '');
mt_srand($sec + ((float)$usec * 100000));
$word = trim($words[random_int(0, count($words) - 1)] ?? '');
$number = random_int(10, 999);
return $word . $number;
} else {
$random = mt_rand();
$string = md5($random ?? '');
$output = substr($string ?? '', 0, 8);
return $output;
}
}
/**
* Event handler called before writing to the database.
*/
@ -1103,26 +946,6 @@ class Member extends DataObject
}
}
/**
* @param array $columns Column names on the Member record to show in {@link getTitle()}.
* @param string $sep Separator
* @deprecated 4.12.0 Use Member.title_format config instead
*/
public static function set_title_columns($columns, $sep = ' ')
{
Deprecation::notice('4.12.0', 'Use Member.title_format config instead');
if (!is_array($columns)) {
$columns = [$columns];
}
self::config()->set(
'title_format',
[
'columns' => $columns,
'sep' => $sep
]
);
}
//------------------- HELPER METHODS -----------------------------------//
/**

View File

@ -68,7 +68,7 @@ class MemberAuthenticator implements Authenticator
$email = !empty($data['Email']) ? $data['Email'] : null;
$result = $result ?: ValidationResult::create();
// Check default login (see Security::setDefaultAdmin())
// Check default login
$asDefaultAdmin = DefaultAdminService::isDefaultAdmin($email);
if ($asDefaultAdmin) {
// If logging is as default admin, ensure record is setup correctly

View File

@ -45,7 +45,6 @@ class MemberPassword extends DataObject
/**
* Check if the given password is the same as the one stored in this record.
* See {@link Member->checkPassword()}.
*
* @param string $password Cleartext password
* @return bool

View File

@ -5,7 +5,6 @@ namespace SilverStripe\Security;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Extensible;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\ValidationResult;
/**
@ -13,9 +12,10 @@ use SilverStripe\ORM\ValidationResult;
*
* <code>
* $pwdVal = new PasswordValidator();
* $pwdValidator->minLength(7);
* $pwdValidator->setMinLength(7);
* $pwdValidator->checkHistoricalPasswords(6);
* $pwdValidator->characterStrength(3, array("lowercase", "uppercase", "digits", "punctuation"));
* $pwdValidator->setMinTestScore(3);
* $pwdValidator->setTestNames(array("lowercase", "uppercase", "digits", "punctuation"));
*
* Member::set_password_validator($pwdValidator);
* </code>
@ -75,52 +75,6 @@ class PasswordValidator
*/
protected $historicalPasswordCount = null;
/**
* Minimum password length
*
* @param int $minLength
* @return $this
* @deprecated 4.5.0 Use setMinLength() instead
*/
public function minLength($minLength)
{
Deprecation::notice('4.5.0', 'Use setMinLength() instead');
return $this->setMinLength($minLength);
}
/**
* Check the character strength of the password.
*
* Eg: $this->characterStrength(3, array("lowercase", "uppercase", "digits", "punctuation"))
*
* @param int $minScore The minimum number of character tests that must pass
* @param string[] $testNames The names of the tests to perform
* @return $this
* @deprecated 4.5.0 Use setMinTestScore($score) and setTestNames($names) instead
*/
public function characterStrength($minScore, $testNames = null)
{
Deprecation::notice('4.5.0', 'Use setMinTestScore($score) and setTestNames($names) instead');
$this->setMinTestScore($minScore);
if ($testNames) {
$this->setTestNames($testNames);
}
return $this;
}
/**
* Check a number of previous passwords that the user has used, and don't let them change to that.
*
* @param int $count
* @return $this
* @deprecated 4.5.0 Use setHistoricCount($value) instead
*/
public function checkHistoricalPasswords($count)
{
Deprecation::notice('4.5.0', 'Use setHistoricCount($value) instead');
return $this->setHistoricCount($count);
}
/**
* @return int
*/

View File

@ -2,7 +2,6 @@
namespace SilverStripe\Security;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Resettable;
use SilverStripe\Dev\TestOnly;
@ -66,23 +65,6 @@ class Permission extends DataObject implements TemplateGlobalProvider, Resettabl
const INHERIT_PERMISSION = 0;
/**
* Method to globally disable "strict" checking, which means a permission
* will be granted if the key does not exist at all.
*
* @deprecated 4.4.0
* @var array
*/
private static $declared_permissions = null;
/**
* Linear list of declared permissions in the system.
*
* @deprecated 4.4.0
* @var array
*/
private static $declared_permissions_list = null;
/**
* @config
* @var $strict_checking Boolean Method to globally disable "strict" checking,
@ -657,73 +639,6 @@ class Permission extends DataObject implements TemplateGlobalProvider, Resettabl
}
}
/**
* Get a linear list of the permissions in the system.
*
* @return array Linear list of declared permissions in the system.
* @deprecated 4.4.0 Will be removed without equivalent functionality
*/
public static function get_declared_permissions_list()
{
Deprecation::notice('4.4.0', 'Will be removed without equivalent functionality');
if (!self::$declared_permissions) {
return null;
}
if (self::$declared_permissions_list) {
return self::$declared_permissions_list;
}
self::$declared_permissions_list = [];
self::traverse_declared_permissions(self::$declared_permissions, self::$declared_permissions_list);
return self::$declared_permissions_list;
}
/**
* Look up the human-readable title for the permission as defined by <code>Permission::declare_permissions</code>
*
* @param string $perm Permission code
* @return string Label for the given permission, or the permission itself if the label doesn't exist
* @deprecated 4.4.0 Will be removed without equivalent functionality
*/
public static function get_label_for_permission($perm)
{
Deprecation::notice('4.4.0', 'Will be removed without equivalent functionality');
$list = self::get_declared_permissions_list();
if (array_key_exists($perm, $list ?? [])) {
return $list[$perm];
}
return $perm;
}
/**
* Recursively traverse the nested list of declared permissions and create
* a linear list.
*
* @param array $declared Nested structure of permissions.
* @param array $list List of permissions in the structure. The result will be
* written to this array.
* @deprecated 4.4.0 Will be removed without equivalent functionality
*/
protected static function traverse_declared_permissions($declared, &$list)
{
Deprecation::notice('4.4.0', 'Will be removed without equivalent functionality');
if (!is_array($declared)) {
return;
}
foreach ($declared as $perm => $value) {
if ($value instanceof Permission_Group) {
$list[] = $value->getName();
self::traverse_declared_permissions($value->getPermissions(), $list);
} else {
$list[$perm] = $value;
}
}
}
public function onBeforeWrite()
{
parent::onBeforeWrite();

View File

@ -2,37 +2,12 @@
namespace SilverStripe\Security;
use Error;
use Exception;
use SilverStripe\Dev\Deprecation;
/**
* Convenience class for generating cryptographically secure pseudo-random strings/tokens
*/
class RandomGenerator
{
/**
* @return string A 128-character, randomly generated ASCII string
* @throws Exception If no suitable CSPRNG is installed
* @deprecated 4.4.0 Use native php function random_bytes() instead
*/
public function generateEntropy()
{
Deprecation::notice('4.4.0', 'Use native php function random_bytes() instead');
try {
return bin2hex(random_bytes(64));
} catch (Error $e) {
throw $e; // This is required so that Error exceptions in PHP 5 aren't caught below
} catch (Exception $e) {
throw new Exception(
'It appears there is no suitable CSPRNG (random number generator) installed. '
. 'Please review the server requirements documentation: '
. 'https://docs.silverstripe.org/en/getting_started/server_requirements/'
);
}
}
/**
* Generates a random token that can be used for session IDs, CSRF tokens etc., based on
* hash algorithms.

View File

@ -16,7 +16,6 @@ use SilverStripe\Control\RequestHandler;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\Form;
use SilverStripe\ORM\ArrayList;
@ -83,16 +82,6 @@ class Security extends Controller implements TemplateGlobalProvider
*/
private static $remember_username = true;
/**
* Location of word list to use for generating passwords
*
* @config
* @var string
*
* @deprecated 4.12 Will be removed without equivalent functionality to replace it
*/
private static $word_list = './wordlist.txt';
/**
* @config
* @var string
@ -462,30 +451,6 @@ class Security extends Controller implements TemplateGlobalProvider
return self::$currentUser;
}
/**
* Get the login forms for all available authentication methods
*
* @deprecated 4.12.0 Use delegateToMultipleHandlers() instead
*
* @return array Returns an array of available login forms (array of Form
* objects).
*
*/
public function getLoginForms()
{
Deprecation::notice('4.12.0', 'Use delegateToMultipleHandlers() instead');
return array_map(
function (Authenticator $authenticator) {
return [
$authenticator->getLoginHandler($this->Link())->loginForm()
];
},
$this->getApplicableAuthenticators() ?? []
);
}
/**
* Get a link to a security action
*
@ -1061,119 +1026,6 @@ class Security extends Controller implements TemplateGlobalProvider
);
}
/**
* Return an existing member with administrator privileges, or create one of necessary.
*
* Will create a default 'Administrators' group if no group is found
* with an ADMIN permission. Will create a new 'Admin' member with administrative permissions
* if no existing Member with these permissions is found.
*
* Important: Any newly created administrator accounts will NOT have valid
* login credentials (Email/Password properties), which means they can't be used for login
* purposes outside of any default credentials set through {@link Security::setDefaultAdmin()}.
*
* @return Member
*
* @deprecated 4.0.1 Use DefaultAdminService::findOrCreateDefaultAdmin()
*/
public static function findAnAdministrator()
{
Deprecation::notice('4.0.1', 'Use DefaultAdminService::findOrCreateDefaultAdmin()');
$service = DefaultAdminService::singleton();
return $service->findOrCreateDefaultAdmin();
}
/**
* Flush the default admin credentials
*
* @deprecated 4.0.1 Use DefaultAdminService::clearDefaultAdmin()
*/
public static function clear_default_admin()
{
Deprecation::notice('4.0.1', 'Use DefaultAdminService::clearDefaultAdmin()');
DefaultAdminService::clearDefaultAdmin();
}
/**
* Set a default admin in dev-mode
*
* This will set a static default-admin which is not existing
* as a database-record. By this workaround we can test pages in dev-mode
* with a unified login. Submitted login-credentials are first checked
* against this static information in {@link Security::authenticate()}.
*
* @param string $username The user name
* @param string $password The password (in cleartext)
* @return bool True if successfully set
*
* @deprecated 4.0.1 Use DefaultAdminService::setDefaultAdmin($username, $password)
*/
public static function setDefaultAdmin($username, $password)
{
Deprecation::notice('4.0.1', 'Use DefaultAdminService::setDefaultAdmin($username, $password)');
DefaultAdminService::setDefaultAdmin($username, $password);
return true;
}
/**
* Checks if the passed credentials are matching the default-admin.
* Compares cleartext-password set through Security::setDefaultAdmin().
*
* @param string $username
* @param string $password
* @return bool
*
* @deprecated 4.0.1 Use DefaultAdminService::isDefaultAdminCredentials() instead
*/
public static function check_default_admin($username, $password)
{
Deprecation::notice('4.0.1', 'Use DefaultAdminService::isDefaultAdminCredentials() instead');
/** @var DefaultAdminService $service */
return DefaultAdminService::isDefaultAdminCredentials($username, $password);
}
/**
* Check that the default admin account has been set.
*
* @deprecated 4.0.1 Use DefaultAdminService::hasDefaultAdmin() instead
*/
public static function has_default_admin()
{
Deprecation::notice('4.0.1', 'Use DefaultAdminService::hasDefaultAdmin() instead');
return DefaultAdminService::hasDefaultAdmin();
}
/**
* Get default admin username
*
* @deprecated 4.0.1 Use DefaultAdminService::getDefaultAdminUsername() instead
* @return string
*/
public static function default_admin_username()
{
Deprecation::notice('4.0.1', 'Use DefaultAdminService::getDefaultAdminUsername() instead');
return DefaultAdminService::getDefaultAdminUsername();
}
/**
* Get default admin password
*
* @deprecated 4.0.1 Use DefaultAdminService::getDefaultAdminPassword() instead
* @return string
*/
public static function default_admin_password()
{
Deprecation::notice('4.0.1', 'Use DefaultAdminService::getDefaultAdminPassword() instead');
return DefaultAdminService::getDefaultAdminPassword();
}
/**
* Encrypt a password according to the current password encryption settings.
* If the settings are so that passwords shouldn't be encrypted, the

View File

@ -1,153 +0,0 @@
<?php
namespace SilverStripe\View\Embed;
use Embed\Adapters\Adapter;
use Embed\Embed;
use Embed\Http\DispatcherInterface;
use SilverStripe\Core\Manifest\ModuleResourceLoader;
use SilverStripe\Dev\Deprecation;
/**
* This is a deprecated class that was compatible with embed/embed v3
* This has been replaced with EmbedContainer which is embed/embed v4 compatible
*
* Encapsulation of an embed tag, linking to an external media source.
*
* @see Embed
* @deprecated 4.11.0 Use EmbedContainer instead
*/
class EmbedResource implements Embeddable
{
/**
* Embed result
*
* @var Adapter
*/
protected $embed;
/**
* @var string
*/
protected $url;
/**
* @var array
*/
protected $options = [];
/**
* @var DispatcherInterface
*/
protected $dispatcher;
/**
* @param string $url
*/
public function __construct($url)
{
Deprecation::notice('4.11.0', 'Use EmbedContainer instead', Deprecation::SCOPE_CLASS);
$this->url = $url;
}
public function getWidth()
{
return $this->getEmbed()->getWidth() ?: 100;
}
public function getHeight()
{
return $this->getEmbed()->getHeight() ?: 100;
}
public function getPreviewURL()
{
// Use thumbnail url
if ($this->getEmbed()->image) {
return $this->getEmbed()->image;
}
// Use direct image type
if ($this->getType() === 'photo' && !empty($this->getEmbed()->url)) {
return $this->getEmbed()->url;
}
// Default media
return ModuleResourceLoader::resourceURL(
'silverstripe/asset-admin:client/dist/images/icon_file.png'
);
}
/**
* Get human readable name for this resource
*
* @return string
*/
public function getName()
{
if ($this->getEmbed()->title) {
return $this->getEmbed()->title;
}
return preg_replace('/\?.*/', '', basename($this->getEmbed()->getUrl() ?? ''));
}
public function getType()
{
return $this->getEmbed()->type;
}
public function validate()
{
return !empty($this->getEmbed()->code);
}
/**
* @param array $options
* @return $this
*/
public function setOptions(array $options)
{
$this->options = $options;
return $this;
}
/**
* @return array
*/
public function getOptions()
{
return $this->options;
}
/**
* @param DispatcherInterface $dispatcher
* @return $this
*/
public function setDispatcher(DispatcherInterface $dispatcher)
{
$this->dispatcher = $dispatcher;
return $this;
}
/**
* @return DispatcherInterface
*/
public function getDispatcher()
{
return $this->dispatcher;
}
/**
* Returns a bootstrapped Embed object
*
* @return Adapter
*/
public function getEmbed()
{
if (!$this->embed) {
$this->embed = Embed::create($this->url, $this->getOptions(), $this->getDispatcher());
}
return $this->embed;
}
}

View File

@ -6,7 +6,6 @@ use InvalidArgumentException;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Flushable;
use SilverStripe\Dev\Deprecation;
/**
* Requirements tracker for JavaScript and CSS.
@ -303,14 +302,6 @@ class Requirements implements Flushable
*/
public static function includeInHTML($content)
{
if (func_num_args() > 1) {
Deprecation::notice(
'5.0',
'$templateFile argument is deprecated. includeInHTML takes a sole $content parameter now.'
);
$content = func_get_arg(1);
}
return self::backend()->includeInHTML($content);
}
@ -334,11 +325,10 @@ class Requirements implements Flushable
* 'framework/javascript/lang'
* @param bool $return Return all relative file paths rather than including them in
* requirements
* @param bool $langOnly @deprecated 4.1.0:5.0.0 as i18n.js should be included manually in your project
*
* @return array
*/
public static function add_i18n_javascript($langDir, $return = false, $langOnly = false)
public static function add_i18n_javascript($langDir, $return = false)
{
return self::backend()->add_i18n_javascript($langDir, $return);
}

View File

@ -16,7 +16,6 @@ use SilverStripe\Core\Manifest\ModuleResourceLoader;
use SilverStripe\Core\Manifest\ResourceURLGenerator;
use SilverStripe\Core\Path;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\Deprecation;
use SilverStripe\i18n\i18n;
use SilverStripe\ORM\FieldType\DBField;
use Symfony\Component\Filesystem\Path as FilesystemPath;
@ -139,13 +138,6 @@ class Requirements_Backend
*/
protected $combinedFiles = [];
/**
* Use the injected minification service to minify any javascript file passed to {@link combine_files()}.
*
* @var bool
*/
protected $minifyCombinedFiles = false;
/**
* Whether or not file headers should be written when combining files
*
@ -210,11 +202,6 @@ class Requirements_Backend
*/
protected $assetHandler = null;
/**
* @var Requirements_Minifier
*/
protected $minifier = null;
/**
* Gets the backend storage for generated files
*
@ -235,28 +222,6 @@ class Requirements_Backend
$this->assetHandler = $handler;
}
/**
* Gets the minification service for this backend
*
* @return Requirements_Minifier
* @deprecated 4.0.1 Will be removed without equivalent functionality
*/
public function getMinifier()
{
Deprecation::notice('4.0.1', 'Will be removed without equivalent functionality');
return $this->minifier;
}
/**
* Set a new minification service for this backend
*
* @param Requirements_Minifier $minifier
*/
public function setMinifier(Requirements_Minifier $minifier = null)
{
$this->minifier = $minifier;
}
/**
* Enable or disable the combination of CSS and JavaScript files
*
@ -385,28 +350,6 @@ class Requirements_Backend
return $this->forceJSToBottom;
}
/**
* Check if minify files should be combined
*
* @return bool
*/
public function getMinifyCombinedFiles()
{
return $this->minifyCombinedFiles;
}
/**
* Set if combined files should be minified
*
* @param bool $minify
* @return $this
*/
public function setMinifyCombinedFiles($minify)
{
$this->minifyCombinedFiles = $minify;
return $this;
}
/**
* Register the given JavaScript file as required.
*
@ -812,14 +755,6 @@ class Requirements_Backend
*/
public function includeInHTML($content)
{
if (func_num_args() > 1) {
Deprecation::notice(
'5.0',
'$templateFile argument is deprecated. includeInHTML takes a sole $content parameter now.'
);
$content = func_get_arg(1);
}
// Skip if content isn't injectable, or there is nothing to inject
$tagsAvailable = preg_match('#</head\b#', $content ?? '');
$hasFiles = $this->css || $this->javascript || $this->customCSS || $this->customScript || $this->customHeadTags;
@ -1154,10 +1089,6 @@ class Requirements_Backend
*/
public function combineFiles($combinedFileName, $files, $options = [])
{
if (is_string($options)) {
Deprecation::notice('4.0', 'Parameter media is deprecated. Use options array instead.');
$options = ['media' => $options];
}
// Skip this combined files if already included
if (isset($this->combinedFiles[$combinedFileName])) {
return;
@ -1381,28 +1312,11 @@ class Requirements_Backend
$combinedFileID = File::join_paths($this->getCombinedFilesFolder(), $combinedFile);
// Send file combination request to the backend, with an optional callback to perform regeneration
$minify = $this->getMinifyCombinedFiles();
if ($minify && !$this->minifier) {
throw new Exception(
sprintf(
<<<MESSAGE
Cannot minify files without a minification service defined.
Set %s::minifyCombinedFiles to false, or inject a %s service on
%s.properties.minifier
MESSAGE
,
__CLASS__,
Requirements_Minifier::class,
__CLASS__
)
);
}
$combinedURL = $this
->getAssetHandler()
->getContentURL(
$combinedFileID,
function () use ($fileList, $minify, $type) {
function () use ($fileList, $type) {
// Physically combine all file content
$combinedData = '';
foreach ($fileList as $file) {
@ -1415,11 +1329,6 @@ MESSAGE
// resolve relative paths for css files
$fileContent = $this->resolveCSSReferences($fileContent, $file);
}
// Use configured minifier
if ($minify) {
$fileContent = $this->minifier->minify($fileContent, $type, $file);
}
if ($this->writeHeaderComment) {
// Write a header comment for each file for easier identification and debugging.
$combinedData .= "/****** FILE: $file *****/\n";

View File

@ -1,22 +0,0 @@
<?php
namespace SilverStripe\View;
/**
* Provides an abstract interface for minifying content
*
* @deprecated 4.0.0:5.0.0
*/
interface Requirements_Minifier
{
/**
* Minify the given content
*
* @param string $content
* @param string $type Either js or css
* @param string $filename Name of file to display in case of error
* @return string minified content
*/
public function minify($content, $type, $filename);
}

View File

@ -11,7 +11,6 @@ use SilverStripe\Core\Flushable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Control\Director;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\Security\Permission;
@ -70,16 +69,6 @@ class SSViewer implements Flushable
*/
protected static $current_themes = null;
/**
* The used "theme", which usually consists of templates, images and stylesheets.
* Only used when {@link $theme_enabled} is set to TRUE, and $themes is empty
*
* @deprecated 4.0.0:5.0.0
* @config
* @var string
*/
private static $theme = null;
/**
* Use the theme. Set to FALSE in order to disable themes,
* which can be useful for scenarios where theme overrides are temporarily undesired,
@ -287,27 +276,9 @@ class SSViewer implements Flushable
return $themes;
}
// Support @deprecated legacy behaviour
$theme = Deprecation::withNoReplacement(function () {
return SSViewer::config()->uninherited('theme');
});
if ($theme) {
return [self::PUBLIC_THEME, $theme, self::DEFAULT_THEME];
}
return $default;
}
/**
* @param string $theme The "base theme" name (without underscores).
* @deprecated 4.0.1 Use SSViewer::set_themes() instead
*/
public static function set_theme($theme)
{
Deprecation::notice('4.0.1', 'Use SSViewer::set_themes() instead');
self::set_themes([$theme, self::DEFAULT_THEME]);
}
/**
* Traverses the given the given class context looking for candidate template names
* which match each item in the class hierarchy. The resulting list of template candidates

View File

@ -2,8 +2,6 @@
namespace SilverStripe\View;
use SilverStripe\Dev\Deprecation;
/**
* Defines an extra set of basic methods that can be used in templates
* that are not defined on sub-classes of {@link ViewableData}.
@ -66,16 +64,6 @@ class SSViewer_BasicIteratorSupport implements TemplateIteratorProvider
return $this->iteratorPos == 0;
}
/**
* @deprecated 4.12.0 Use IsFirst() instead
* @return bool
*/
public function First()
{
Deprecation::notice('4.12.0', 'Use IsFirst() instead');
return $this->IsFirst();
}
/**
* Returns true if this object is the last in a set.
*
@ -86,16 +74,6 @@ class SSViewer_BasicIteratorSupport implements TemplateIteratorProvider
return $this->iteratorPos == $this->iteratorTotalItems - 1;
}
/**
* @deprecated 4.12.0 Use IsLast() instead
* @return bool
*/
public function Last()
{
Deprecation::notice('4.12.0', 'Use IsLast() instead');
return $this->IsLast();
}
/**
* Returns 'first' or 'last' if this is the first or last object in the set.
*

View File

@ -16,7 +16,6 @@ use SilverStripe\View\HTML;
use SilverStripe\View\Parsers\ShortcodeHandler;
use SilverStripe\View\Parsers\ShortcodeParser;
use SilverStripe\Control\Director;
use SilverStripe\Dev\Deprecation;
use SilverStripe\View\Embed\EmbedContainer;
/**
@ -156,32 +155,6 @@ class EmbedShortcodeProvider implements ShortcodeHandler
return '';
}
/**
* @param Adapter $embed
* @param array $arguments Additional shortcode params
* @return string
* @deprecated 4.11.0 Use embeddableToHtml() instead
*/
public static function embedForTemplate($embed, $arguments)
{
Deprecation::notice('4.11.0', 'Use embeddableToHtml() instead');
switch ($embed->getType()) {
case 'video':
case 'rich':
// Attempt to inherit width (but leave height auto)
if (empty($arguments['width']) && $embed->getWidth()) {
$arguments['width'] = $embed->getWidth();
}
return static::videoEmbed($arguments, $embed->getCode());
case 'link':
return static::linkEmbed($arguments, $embed->getUrl(), $embed->getTitle());
case 'photo':
return static::photoEmbed($arguments, $embed->getUrl());
default:
return null;
}
}
/**
* Build video embed tag
*

View File

@ -14,9 +14,7 @@ use SilverStripe\Core\Convert;
use SilverStripe\Core\Extensible;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Manifest\ModuleResourceLoader;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\ArrayLib;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBHTMLText;
@ -609,35 +607,6 @@ 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.1 Use ModuleResourceLoader::resourcePath() or ModuleResourceLoader::resourceURL() instead
*/
public function ThemeDir()
{
Deprecation::notice('4.0.1', 'Use ModuleResourceLoader::resourcePath() or ModuleResourceLoader::resourceURL() 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

@ -1,10 +0,0 @@
<?php
/**
* @deprecated 4.0.0:5.0.0
*
* Placeholder empty file
*/
use SilverStripe\Dev\Deprecation;
Deprecation::notice('5.0', 'ConfigureFromEnv.php is deprecated', Deprecation::SCOPE_GLOBAL);

View File

@ -5,12 +5,10 @@ namespace SilverStripe\i18n\Data;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Manifest\ModuleLoader;
use SilverStripe\Core\Manifest\ModuleManifest;
use SilverStripe\Core\Resettable;
use SilverStripe\i18n\i18n;
use SilverStripe\View\SSViewer;
use SilverStripe\View\ThemeResourceLoader;
use SilverStripe\Dev\Deprecation;
/**
* Data sources for localisation strings. I.e. yml files stored
@ -36,15 +34,7 @@ class Sources implements Resettable
*/
public function getSortedModules()
{
$i18nOrder = Sources::config()->uninherited('module_priority');
$sortedModules = [];
if ($i18nOrder) {
Deprecation::notice('5.0', sprintf(
'%s.module_priority is deprecated. Use %s.module_priority instead.',
__CLASS__,
ModuleManifest::class
));
}
foreach (ModuleLoader::inst()->getManifest()->getModules() as $module) {
$sortedModules[$module->getName()] = $module->getPath();

View File

@ -2,9 +2,7 @@
namespace SilverStripe\i18n\Messages\Symfony;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Core\Flushable;
use Symfony\Component\Config\Resource\DirectoryResource;
use Symfony\Component\Config\Resource\SelfCheckingResourceInterface;
/**
@ -14,7 +12,7 @@ use Symfony\Component\Config\Resource\SelfCheckingResourceInterface;
* @link https://media.giphy.com/media/fRRD3T37DeY6Y/giphy.gif for use case
* @see DirectoryResource
*/
class FlushInvalidatedResource implements SelfCheckingResourceInterface, \Serializable, Flushable
class FlushInvalidatedResource implements SelfCheckingResourceInterface, Flushable
{
public function __toString()
@ -51,32 +49,6 @@ class FlushInvalidatedResource implements SelfCheckingResourceInterface, \Serial
// no-op
}
/**
* The __serialize() magic method will be automatically used instead of this
*
* @return string
* @deprecated 4.12.0 Use __serialize() instead
*/
public function serialize()
{
Deprecation::notice('4.12.0', 'Use __serialize() instead');
return '';
}
/**
* The __unserialize() magic method will be automatically used instead of this almost all the time
* This method will be automatically used if existing serialized data was not saved as an associative array
* and the PHP version used in less than PHP 9.0
*
* @param string $serialized
* @deprecated 4.12.0 Use __unserialize() instead
*/
public function unserialize($serialized)
{
Deprecation::notice('4.12.0', 'Use __unserialize() instead');
// no-op
}
public static function flush()
{
// Mark canary as dirty

View File

@ -2,6 +2,7 @@
namespace SilverStripe\i18n\TextCollection;
use Exception;
use LogicException;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Injector\Injectable;
@ -11,7 +12,6 @@ use SilverStripe\Core\Manifest\ModuleLoader;
use SilverStripe\Dev\Debug;
use SilverStripe\Control\Director;
use ReflectionClass;
use SilverStripe\Dev\Deprecation;
use SilverStripe\i18n\i18n;
use SilverStripe\i18n\i18nEntityProvider;
use SilverStripe\i18n\Messages\Reader;
@ -828,23 +828,10 @@ class i18nTextCollector
/** @var i18nEntityProvider $obj */
$obj = singleton($class);
$provided = $obj->provideI18nEntities();
// Handle deprecated return syntax
foreach ($provided as $key => $value) {
// Detect non-associative result for any key
if (is_array($value) && $value === array_values($value ?? [])) {
Deprecation::notice('5.0', 'Non-associative translations from providei18nEntities is deprecated');
$entity = array_filter([
'default' => $value[0],
'comment' => isset($value[1]) ? $value[1] : null,
'module' => isset($value[2]) ? $value[2] : null,
]);
if (count($entity ?? []) === 1) {
$provided[$key] = $value[0];
} elseif ($entity) {
$provided[$key] = $entity;
} else {
unset($provided[$key]);
}
if (is_array($value) && $value === array_values($value)) {
throw new Exception('Translations from provideI18nEntities() must be an associative array for key $key');
}
}
$entities = array_merge($entities, $provided);

View File

@ -2,9 +2,9 @@
namespace SilverStripe\i18n;
use Exception;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation;
use SilverStripe\i18n\Data\Locales;
use SilverStripe\i18n\Data\Sources;
use SilverStripe\i18n\Messages\MessageProvider;
@ -205,23 +205,16 @@ class i18n implements TemplateGlobalProvider
$result = static::getMessageProvider()->translate($entity, $default, $injection);
}
// Sometimes default is omitted, so we don't know we have %s injection format until after translation
if (!$default && !preg_match('/\{[\w\d]*\}/i', $result ?? '') && preg_match('/%[s,d]/', $result ?? '')) {
Deprecation::notice('5.0', 'sprintf style localisation is deprecated');
if ($injection) {
$sprintfArgs = array_values($injection ?? []);
throw new Exception('sprintf style localisation cannot be used in translations - detected in $result');
}
} elseif ($failUnlessSprintf) {
if ($failUnlessSprintf) {
// Note: After removing deprecated code, you can move this error up into the is-associative check
// Neither default nor translated strings were %s substituted, and our array isn't associative
throw new InvalidArgumentException('Injection must be an associative array');
}
// @deprecated (see above)
if ($sprintfArgs) {
return vsprintf($result ?? '', $sprintfArgs ?? []);
}
return $result;
}

View File

@ -76,15 +76,6 @@ class CmsUiContext implements Context
Assert::assertNotNull($cms_element, 'CMS not found');
}
/**
* @Then /^I should see a "([^"]*)" notice$/
* @deprecated 4.7.0 Use `iShouldSeeAToast` instead
*/
public function iShouldSeeANotice($notice)
{
$this->getMainContext()->assertElementContains('.toast, .notice-wrap', $notice);
}
/**
* @Then /^I should see a "(.+)" (\w+) toast$/
*/

View File

@ -10,13 +10,11 @@ use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Control\Middleware\CanonicalURLMiddleware;
use SilverStripe\Control\Middleware\RequestHandlerMiddlewareAdapter;
use SilverStripe\Control\Middleware\TrustedProxyMiddleware;
use SilverStripe\Control\RequestProcessor;
use SilverStripe\Control\Tests\DirectorTest\TestController;
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;
/**
@ -855,46 +853,6 @@ class DirectorTest extends SapphireTest
$this->assertEquals($request->getURL(true), $url);
}
public function testRequestFilterInDirectorTest()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$filter = new DirectorTest\TestRequestFilter;
$processor = new RequestProcessor([$filter]);
$middlewares = Director::singleton()->getMiddlewares();
$middlewares['RequestProcessorMiddleware'] = $processor;
Director::singleton()->setMiddlewares($middlewares);
$response = Director::test('some-dummy-url');
$this->assertEquals(404, $response->getStatusCode());
$this->assertEquals(1, $filter->preCalls);
$this->assertEquals(1, $filter->postCalls);
$filter->failPost = true;
$response = Director::test('some-dummy-url');
$this->assertEquals(500, $response->getStatusCode());
$this->assertEquals(_t(Director::class . '.REQUEST_ABORTED', 'Request aborted'), $response->getBody());
$this->assertEquals(2, $filter->preCalls);
$this->assertEquals(2, $filter->postCalls);
$filter->failPre = true;
$response = Director::test('some-dummy-url');
$this->assertEquals(400, $response->getStatusCode());
$this->assertEquals(_t(Director::class . '.INVALID_REQUEST', 'Invalid request'), $response->getBody());
$this->assertEquals(3, $filter->preCalls);
// preCall 'true' will trigger an exception and prevent post call execution
$this->assertEquals(2, $filter->postCalls);
}
public function testGlobalMiddleware()
{
$middleware = new DirectorTest\TestMiddleware;

View File

@ -4,10 +4,9 @@ namespace SilverStripe\Control\Tests\DirectorTest;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\RequestFilter;
use SilverStripe\Dev\TestOnly;
class TestRequestFilter implements RequestFilter, TestOnly
class TestRequestFilter implements TestOnly
{
public $preCalls = 0;
public $postCalls = 0;

View File

@ -44,7 +44,7 @@ class MailerSubscriberTest extends SapphireTest
public function testSendAllEmailsTo(): void
{
Email::config()->update('send_all_emails_to', 'to@example.com');
Email::config()->merge('send_all_emails_to', ['to@example.com']);
$email = $this->getEmail();
$email->send();
@ -61,7 +61,7 @@ class MailerSubscriberTest extends SapphireTest
public function testSendAllEmailsFrom(): void
{
Email::config()->update('send_all_emails_from', 'from@example.com');
Email::config()->merge('send_all_emails_from', ['from@example.com']);
$email = $this->getEmail();
$email->send();
@ -78,7 +78,7 @@ class MailerSubscriberTest extends SapphireTest
public function testCCAllEmailsTo(): void
{
Email::config()->update('cc_all_emails_to', 'cc@example.com');
Email::config()->merge('cc_all_emails_to', ['cc@example.com']);
$email = $this->getEmail();
$email->send();
@ -89,7 +89,7 @@ class MailerSubscriberTest extends SapphireTest
public function testBCCAllEmailsTo(): void
{
Email::config()->update('bcc_all_emails_to', 'bcc@example.com');
Email::config()->merge('bcc_all_emails_to', ['bcc@example.com']);
$email = $this->getEmail();
$email->send();

View File

@ -6,7 +6,6 @@ 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
@ -151,27 +150,6 @@ class HTTPRequestTest extends SapphireTest
];
}
/**
* @dataProvider detectMethodDataProvider
*/
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']);
}
public function setHttpMethodDataProvider()
{
return [

View File

@ -11,7 +11,6 @@ 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
@ -114,89 +113,6 @@ class HTTPTest extends FunctionalTest
$this->assertEmpty($v);
}
public function testDeprecatedVaryHandling()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
/** @var Config */
Config::modify()->set(
HTTP::class,
'vary',
'X-Foo'
);
$response = new HTTPResponse('', 200);
$this->addCacheHeaders($response);
$header = $response->getHeader('Vary');
$this->assertStringContainsString('X-Foo', $header);
}
public function testDeprecatedCacheControlHandling()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
HTTPCacheControlMiddleware::singleton()->publicCache();
/** @var Config */
Config::modify()->set(
HTTP::class,
'cache_control',
[
'no-store' => true,
'no-cache' => true,
]
);
$response = new HTTPResponse('', 200);
$this->addCacheHeaders($response);
$header = $response->getHeader('Cache-Control');
$this->assertStringContainsString('no-store', $header);
$this->assertStringContainsString('no-cache', $header);
}
public function testDeprecatedCacheControlHandlingOnMaxAge()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
HTTPCacheControlMiddleware::singleton()->publicCache();
/** @var Config */
Config::modify()->set(
HTTP::class,
'cache_control',
[
// Needs to be separate from no-cache and no-store,
// since that would unset max-age
'max-age' => 99,
]
);
$response = new HTTPResponse('', 200);
$this->addCacheHeaders($response);
$header = $response->getHeader('Cache-Control');
$this->assertStringContainsString('max-age=99', $header);
}
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 */
Config::modify()->set(
HTTP::class,
'cache_control',
[
'no-store' => true,
'unknown' => true,
]
);
$response = new HTTPResponse('', 200);
$this->addCacheHeaders($response);
}
/**
* Tests {@link HTTP::getLinksIn()}
*/

View File

@ -22,8 +22,8 @@ class ConfigTest extends SapphireTest
$this->assertEquals(5, Config::inst()->get(ConfigTest\TestNest::class, 'bar'));
// Test nested data can be updated
Config::modify()->merge(ConfigTest\TestNest::class, 'foo', 4);
$this->assertEquals(4, Config::inst()->get(ConfigTest\TestNest::class, 'foo'));
Config::modify()->merge(ConfigTest\TestNest::class, 'foo', [4]);
$this->assertEquals(4, Config::inst()->get(ConfigTest\TestNest::class, 'foo')[0]);
$this->assertEquals(5, Config::inst()->get(ConfigTest\TestNest::class, 'bar'));
// Test unnest restores data
@ -171,31 +171,31 @@ class ConfigTest extends SapphireTest
{
// Booleans
$this->assertTrue(Config::inst()->get(ConfigTest\First::class, 'bool'));
Config::modify()->merge(ConfigTest\First::class, 'bool', false);
$this->assertFalse(Config::inst()->get(ConfigTest\First::class, 'bool'));
Config::modify()->merge(ConfigTest\First::class, 'bool', true);
$this->assertTrue(Config::inst()->get(ConfigTest\First::class, 'bool'));
Config::modify()->merge(ConfigTest\First::class, 'bool', [false]);
$this->assertFalse(Config::inst()->get(ConfigTest\First::class, 'bool')[0]);
Config::modify()->merge(ConfigTest\First::class, 'bool', [true]);
$this->assertTrue(Config::inst()->get(ConfigTest\First::class, 'bool')[1]);
// Integers
$this->assertEquals(42, Config::inst()->get(ConfigTest\First::class, 'int'));
Config::modify()->merge(ConfigTest\First::class, 'int', 0);
$this->assertEquals(0, Config::inst()->get(ConfigTest\First::class, 'int'));
Config::modify()->merge(ConfigTest\First::class, 'int', 42);
$this->assertEquals(42, Config::inst()->get(ConfigTest\First::class, 'int'));
Config::modify()->merge(ConfigTest\First::class, 'int', [0]);
$this->assertEquals(0, Config::inst()->get(ConfigTest\First::class, 'int')[0]);
Config::modify()->merge(ConfigTest\First::class, 'int', [42]);
$this->assertEquals(42, Config::inst()->get(ConfigTest\First::class, 'int')[1]);
// Strings
$this->assertEquals('value', Config::inst()->get(ConfigTest\First::class, 'string'));
Config::modify()->merge(ConfigTest\First::class, 'string', '');
$this->assertEquals('', Config::inst()->get(ConfigTest\First::class, 'string'));
Config::modify()->merge(ConfigTest\First::class, 'string', 'value');
$this->assertEquals('value', Config::inst()->get(ConfigTest\First::class, 'string'));
Config::modify()->merge(ConfigTest\First::class, 'string', ['']);
$this->assertEquals('', Config::inst()->get(ConfigTest\First::class, 'string')[0]);
Config::modify()->merge(ConfigTest\First::class, 'string', ['value']);
$this->assertEquals('value', Config::inst()->get(ConfigTest\First::class, 'string')[1]);
// Nulls
$this->assertEquals('value', Config::inst()->get(ConfigTest\First::class, 'nullable'));
Config::modify()->merge(ConfigTest\First::class, 'nullable', null);
$this->assertNull(Config::inst()->get(ConfigTest\First::class, 'nullable'));
Config::modify()->merge(ConfigTest\First::class, 'nullable', 'value');
$this->assertEquals('value', Config::inst()->get(ConfigTest\First::class, 'nullable'));
Config::modify()->merge(ConfigTest\First::class, 'nullable', [null]);
$this->assertNull(Config::inst()->get(ConfigTest\First::class, 'nullable')[0]);
Config::modify()->merge(ConfigTest\First::class, 'nullable', ['value']);
$this->assertEquals('value', Config::inst()->get(ConfigTest\First::class, 'nullable')[1]);
}
public function testSetsFalsyDefaults()

View File

@ -5,7 +5,6 @@ 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;
@ -213,60 +212,6 @@ PHP
$this->assertEquals('This is some normal text.', Convert::xml2raw($val2), 'Normal text is not escaped');
}
/**
* Tests {@link Convert::xml2raw()}
*/
public function testArray2JSON()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$val = [
'Joe' => 'Bloggs',
'Tom' => 'Jones',
'My' => [
'Complicated' => 'Structure'
]
];
$encoded = Convert::array2json($val);
$this->assertEquals(
'{"Joe":"Bloggs","Tom":"Jones","My":{"Complicated":"Structure"}}',
$encoded,
'Array is encoded in JSON'
);
}
/**
* Tests {@link Convert::json2array()}
*/
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');
$this->assertContains('Bloggs', $decoded, 'Contains "Bloggs" value in decoded array');
$this->assertContains('Jones', $decoded, 'Contains "Jones" value in decoded array');
$this->assertStringContainsString('Structure', $decoded['My']['Complicated']);
}
/**
* Tests {@link Convert::testJSON2Obj()}
*/
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);
$this->assertEquals('Jones', $obj->Tom);
$this->assertEquals('Structure', $obj->My->Complicated);
}
/**
* Tests {@link Convert::testRaw2URL()}
*
@ -364,143 +309,6 @@ PHP
);
}
/**
* Tests {@link Convert::raw2json()}
*/
public function testRaw2JSON()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
// Test object
$input = new stdClass();
$input->Title = 'My Object';
$input->Content = '<p>Data</p>';
$this->assertEquals(
'{"Title":"My Object","Content":"<p>Data<\/p>"}',
Convert::raw2json($input)
);
// Array
$array = ['One' => 'Apple', 'Two' => 'Banana'];
$this->assertEquals(
'{"One":"Apple","Two":"Banana"}',
Convert::raw2json($array)
);
// String value with already encoded data. Result should be quoted.
$value = '{"Left": "Value"}';
$this->assertEquals(
'"{\\"Left\\": \\"Value\\"}"',
Convert::raw2json($value)
);
}
/**
* Test that a context bitmask can be passed through to the json_encode method in {@link Convert::raw2json()}
* and in {@link Convert::array2json()}
*/
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);
$this->assertSame($expected, $result);
$wrapperResult = Convert::array2json($data, JSON_HEX_QUOT);
$this->assertSame($expected, $wrapperResult);
}
/**
* Tests {@link Convert::xml2array()}
*/
public function testXML2Array()
{
$inputXML = <<<XML
<?xml version="1.0"?>
<!DOCTYPE results [
<!ENTITY long "SOME_SUPER_LONG_STRING">
]>
<results>
<result>My para</result>
<result>Ampersand &amp; is retained and not double encoded</result>
</results>
XML
;
$expected = [
'result' => [
'My para',
'Ampersand & is retained and not double encoded'
]
];
$actual = Convert::xml2array($inputXML, false);
$this->assertEquals($expected, $actual);
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('XML Doctype parsing disabled');
Convert::xml2array($inputXML, true);
}
/**
* Tests {@link Convert::xml2array()} if an exception the contains a reference to a removed <!ENTITY />
*/
public function testXML2ArrayEntityException()
{
$inputXML = <<<XML
<?xml version="1.0"?>
<!DOCTYPE results [
<!ENTITY long "SOME_SUPER_LONG_STRING">
]>
<results>
<result>Now include &long; lots of times to expand the in-memory size of this XML structure</result>
<result>&long;&long;&long;</result>
</results>
XML;
$this->expectException(Exception::class);
$this->expectExceptionMessage('String could not be parsed as XML');
Convert::xml2array($inputXML);
}
/**
* Tests {@link Convert::xml2array()} if an exception the contains a reference to a multiple removed <!ENTITY />
*/
public function testXML2ArrayMultipleEntitiesException()
{
$inputXML = <<<XML
<?xml version="1.0"?>
<!DOCTYPE results [<!ENTITY long "SOME_SUPER_LONG_STRING"><!ENTITY short "SHORT_STRING">]>
<results>
<result>Now include &long; and &short; lots of times</result>
<result>&long;&long;&long;&short;&short;&short;</result>
</results>
XML;
$this->expectException(Exception::class);
$this->expectExceptionMessage('String could not be parsed as XML');
Convert::xml2array($inputXML);
}
/**
* Tests {@link Convert::xml2array()} if there is a malicious <!ENTITY /> present
*/
public function testXML2ArrayMaliciousEntityException()
{
$inputXML = <<<XML
<?xml version="1.0"?>
<!DOCTYPE results [
<!ENTITY><!<!ENTITY>ENTITY ext SYSTEM "http://evil.com">
]>
<results>
<result>Evil document</result>
</results>
XML;
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Malicious XML entity detected');
Convert::xml2array($inputXML);
}
/**
* Tests {@link Convert::base64url_encode()} and {@link Convert::base64url_decode()}
*/

View File

@ -759,7 +759,7 @@ class InjectorTest extends SapphireTest
'locator' => SilverStripeServiceConfigurationLocator::class
]
);
Config::modify()->merge(
Config::modify()->set(
Injector::class,
MyChildClass::class,
'%$' . MyParentClass::class

View File

@ -19,7 +19,6 @@ 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;
@ -109,62 +108,6 @@ class ObjectTest extends SapphireTest
);
}
public function testStaticGetterMethod()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$obj = singleton(MyObject::class);
$this->assertEquals(
'MyObject',
$obj->stat('mystaticProperty'),
'Uninherited statics through stat() on a singleton behave the same as built-in PHP statics'
);
}
public function testStaticInheritanceGetters()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$subObj = singleton(MyObject::class);
$this->assertEquals(
$subObj->stat('mystaticProperty'),
'MyObject',
'Statics defined on a parent class are available through stat() on a subclass'
);
}
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');
$this->assertEquals(
$singleton2->stat('mystaticProperty'),
'changed',
'Statics setting is populated throughout singletons without explicitly clearing cache'
);
}
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');
$this->assertEquals(
$instance2->stat('mystaticProperty'),
'changed',
'Statics setting through set_stat() is populated throughout instances without explicitly clearing cache'
);
}
/**
* Tests that {@link Object::create()} correctly passes all arguments to the new object
*/

View File

@ -1,159 +0,0 @@
<?php
namespace SilverStripe\Dev\Tests;
use SilverStripe\Dev\CSVParser;
use SilverStripe\Dev\SapphireTest;
class CSVParserTest extends SapphireTest
{
/**
* Name of csv test dir
*
* @var string
*/
protected $csvPath = null;
protected function setUp(): void
{
parent::setUp();
$this->csvPath = __DIR__ . '/CsvBulkLoaderTest/csv/';
}
public function testParsingWithHeaders()
{
/* By default, a CSV file will be interpreted as having headers */
$csv = new CSVParser($this->csvPath . 'PlayersWithHeader.csv');
$firstNames = $birthdays = $biographies = $registered = [];
foreach ($csv as $record) {
/* Each row in the CSV file will be keyed with the header row */
$this->assertEquals(
['FirstName','Biography','Birthday','IsRegistered'],
array_keys($record ?? [])
);
$firstNames[] = $record['FirstName'];
$biographies[] = $record['Biography'];
$birthdays[] = $record['Birthday'];
$registered[] = $record['IsRegistered'];
}
$this->assertEquals(
['John','Jane','Jamie','Järg','Jacob'],
$firstNames
);
$this->assertEquals(
[
"He's a good guy",
"She is awesome."
. PHP_EOL
. "So awesome that she gets multiple rows and \"escaped\" strings in her biography",
"Pretty old, with an escaped comma",
"Unicode FTW",
"Likes leading tabs in his biography",
],
$biographies
);
$this->assertEquals([
"1988-01-31",
"1982-01-31",
"1882-01-31",
"1982-06-30",
"2000-04-30",
], $birthdays);
$this->assertEquals(
['1', '0', '1', '1', '0'],
$registered
);
}
public function testParsingWithHeadersAndColumnMap()
{
/* By default, a CSV file will be interpreted as having headers */
$csv = new CSVParser($this->csvPath . 'PlayersWithHeader.csv');
/* We can set up column remapping. The keys are case-insensitive. */
$csv->mapColumns([
'FirstName' => '__fn',
'bIoGrApHy' => '__BG',
]);
$firstNames = $birthdays = $biographies = $registered = [];
foreach ($csv as $record) {
/* Each row in the CSV file will be keyed with the renamed columns. Any unmapped column names will be
* left as-is. */
$this->assertEquals(['__fn','__BG','Birthday','IsRegistered'], array_keys($record ?? []));
$firstNames[] = $record['__fn'];
$biographies[] = $record['__BG'];
$birthdays[] = $record['Birthday'];
$registered[] = $record['IsRegistered'];
}
$this->assertEquals(['John','Jane','Jamie','Järg','Jacob'], $firstNames);
$this->assertEquals(
[
"He's a good guy",
"She is awesome."
. PHP_EOL
. "So awesome that she gets multiple rows and \"escaped\" strings in her biography",
"Pretty old, with an escaped comma",
"Unicode FTW",
"Likes leading tabs in his biography",
],
$biographies
);
$this->assertEquals([
"1988-01-31",
"1982-01-31",
"1882-01-31",
"1982-06-30",
"2000-04-30",
], $birthdays);
$this->assertEquals(['1', '0', '1', '1', '0'], $registered);
}
public function testParsingWithExplicitHeaderRow()
{
/* If your CSV file doesn't have a header row */
$csv = new CSVParser($this->csvPath . 'PlayersWithHeader.csv');
$csv->provideHeaderRow(['__fn','__bio','__bd','__reg']);
$firstNames = $birthdays = $biographies = $registered = [];
foreach ($csv as $record) {
/* Each row in the CSV file will be keyed with the header row that you gave */
$this->assertEquals(['__fn','__bio','__bd','__reg'], array_keys($record ?? []));
$firstNames[] = $record['__fn'];
$biographies[] = $record['__bio'];
$birthdays[] = $record['__bd'];
$registered[] = $record['__reg'];
}
/* And the first row will be returned in the data */
$this->assertEquals(['FirstName','John','Jane','Jamie','Järg','Jacob'], $firstNames);
$this->assertEquals(
[
'Biography',
"He's a good guy",
"She is awesome."
. PHP_EOL
. "So awesome that she gets multiple rows and \"escaped\" strings in her biography",
"Pretty old, with an escaped comma",
"Unicode FTW",
"Likes leading tabs in his biography"
],
$biographies
);
$this->assertEquals([
"Birthday",
"1988-01-31",
"1982-01-31",
"1882-01-31",
"1982-06-30",
"2000-04-30",
], $birthdays);
$this->assertEquals(['IsRegistered', '1', '0', '1', '1', '0'], $registered);
}
}

View File

@ -73,18 +73,6 @@ class GridFieldFilterHeaderTest extends SapphireTest
// Check that the output is the new search field
$this->assertStringContainsString('<div class="search-holder grid-field__search-holder grid-field__search-holder--hidden"', $htmlFragment['before']);
$this->assertStringContainsString('Open search and filter', $htmlFragment['buttons-before-right']);
$this->gridField->getConfig()->removeComponentsByType(GridFieldFilterHeader::class);
$this->gridField->getConfig()->addComponent(new GridFieldFilterHeader(true));
$this->component = $this->gridField->getConfig()->getComponentByType(GridFieldFilterHeader::class);
$htmlFragment = $this->component->getHTMLFragments($this->gridField);
// Check that the output is the legacy filter header
$this->assertStringContainsString(
'<tr class="grid-field__filter-header grid-field__search-holder--hidden">',
$htmlFragment['header']
);
$this->assertFalse(array_key_exists('buttons-before-right', $htmlFragment ?? []));
}
public function testSearchFieldSchema()

View File

@ -4,7 +4,6 @@ namespace SilverStripe\Logging\Tests;
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Logging\MonologErrorHandler;
@ -27,11 +26,6 @@ class MonologErrorHandlerTest extends SapphireTest
$handler->pushLogger($logger)->pushLogger($logger);
$this->assertCount(2, $handler->getLoggers(), 'Loggers are pushed to the stack');
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

@ -2,7 +2,6 @@
namespace SilverStripe\ORM\Tests;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject;

View File

@ -270,7 +270,7 @@ class DatabaseTest extends SapphireTest
$this->assertIsString($record['Created'], 'DBDatetime fields should be string (non-prepared)');
// Booleans selected directly are ints
$result = DB::query('SELECT TRUE')->first();
$result = DB::query('SELECT TRUE')->record();
$this->assertIsInt(reset($result));
}

View File

@ -12,14 +12,6 @@ class ControllerNotSecured extends Controller implements TestOnly
{
protected $template = 'BlankPage';
/**
* Disable legacy global-enable
*
* @deprecated 4.0.0:5.0.0
* @var bool
*/
protected $basicAuthEnabled = false;
public function Link($action = null)
{
return Controller::join_links('BasicAuthTest_ControllerNotSecured', $action, '/');

View File

@ -3,7 +3,6 @@
namespace SilverStripe\Security\Tests;
use SilverStripe\Security\RandomGenerator;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
/**
@ -12,16 +11,6 @@ use SilverStripe\Dev\SapphireTest;
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());
}
public function testGenerateHash()
{
$r = new RandomGenerator();

View File

@ -302,7 +302,6 @@ class RequirementsTest extends SapphireTest
$backend->clear();
$backend->clearCombinedFiles();
$backend->setCombinedFilesFolder('_combinedfiles');
$backend->setMinifyCombinedFiles(false);
$backend->setCombinedFilesEnabled(true);
Requirements::flush();
}

View File

@ -25,7 +25,6 @@ use SilverStripe\Security\SecurityToken;
use SilverStripe\View\ArrayData;
use SilverStripe\View\Requirements;
use SilverStripe\View\Requirements_Backend;
use SilverStripe\View\Requirements_Minifier;
use SilverStripe\View\SSTemplateParseException;
use SilverStripe\View\SSTemplateParser;
use SilverStripe\View\SSViewer;
@ -34,7 +33,6 @@ 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
@ -69,24 +67,6 @@ class SSViewerTest extends SapphireTest
parent::tearDown();
}
/**
* Tests for {@link Config::inst()->get('SSViewer', 'theme')} for different behaviour
* of user defined themes via {@link SiteConfig} and default theme
* when no user themes are defined.
*/
public function testCurrentTheme()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
SSViewer::config()->set('theme', 'mytheme');
$this->assertEquals(
'mytheme',
SSViewer::config()->uninherited('theme'),
'Current theme is the default - user has not defined one'
);
}
/**
* Tests for themes helper functions, ensuring they behave as defined in the RFC at
* https://github.com/silverstripe/silverstripe-framework/issues/5604
@ -277,47 +257,6 @@ class SSViewerTest extends SapphireTest
$this->assertStringContainsString($jsFileContents, $combinedTestFileContents);
}
public function testRequirementsMinification()
{
/** @var Requirements_Backend $testBackend */
$testBackend = Injector::inst()->create(Requirements_Backend::class);
$testBackend->setSuffixRequirements(false);
$testBackend->setMinifyCombinedFiles(true);
$testBackend->setCombinedFilesEnabled(true);
$testFile = $this->getCurrentRelativePath() . '/SSViewerTest/javascript/RequirementsTest_a.js';
$testFileContent = file_get_contents($testFile ?? '');
$mockMinifier = $this->getMockBuilder(Requirements_Minifier::class)
->setMethods(['minify'])
->getMock();
$mockMinifier->expects($this->once())
->method('minify')
->with(
$testFileContent,
'js',
$testFile
);
$testBackend->setMinifier($mockMinifier);
$testBackend->combineFiles('testRequirementsMinified.js', [$testFile]);
$testBackend->processCombinedFiles();
$testBackend->setMinifyCombinedFiles(false);
$mockMinifier->expects($this->never())
->method('minify');
$testBackend->processCombinedFiles();
$this->expectException(Exception::class);
$this->expectExceptionMessageMatches('/^Cannot minify files without a minification service defined./');
$testBackend->setMinifyCombinedFiles(true);
$testBackend->setMinifier(null);
$testBackend->processCombinedFiles();
}
public function testComments()
{
$input = <<<SS

View File

@ -7,7 +7,6 @@ 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,
@ -206,22 +205,4 @@ 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()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$themes = [
"silverstripe/framework:/tests/php/View/ViewableDataTest/testtheme",
SSViewer::DEFAULT_THEME
];
SSViewer::set_themes($themes);
$data = new ViewableData();
$this->assertStringContainsString(
'tests/php/View/ViewableDataTest/testtheme',
$data->ThemeDir()
);
}
}