mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
API Remove deprecated code (#10594)
This commit is contained in:
parent
809bc51661
commit
53c0147f11
41
.upgrade.yml
41
.upgrade.yml
@ -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':
|
||||
|
@ -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']
|
||||
|
@ -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
|
||||
---
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace SilverStripe\Control;
|
||||
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||
use LogicException;
|
||||
|
||||
|
@ -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',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ namespace SilverStripe\Control;
|
||||
|
||||
use BadMethodCallException;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
|
||||
/**
|
||||
* Handles all manipulation of the session.
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace SilverStripe\Control;
|
||||
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
use InvalidArgumentException;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Convert;
|
||||
@ -78,17 +77,8 @@ class SimpleResourceURLGenerator implements ResourceURLGenerator
|
||||
if (strpos($relativePath ?? '', '?') !== false) {
|
||||
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);
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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?
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
@ -182,34 +175,7 @@ class Module implements Serializable
|
||||
$this->composerData = $data['composerData'];
|
||||
$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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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',
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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.
|
||||
|
@ -142,69 +142,6 @@ class DebugView
|
||||
return implode(' → ', $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
|
||||
*
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
$databaseConfig = $config;
|
||||
|
||||
foreach (static::getConfigureDatabasePaths() as $configureDatabasePath) {
|
||||
include_once $configureDatabasePath;
|
||||
}
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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,26 +386,17 @@ 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__);
|
||||
return [
|
||||
'before' => $forTemplate->renderWith($searchTemplates),
|
||||
'buttons-before-right' => sprintf(
|
||||
'<button type="button" name="showFilter" aria-label="%s" title="%s"' .
|
||||
' class="btn btn-secondary font-icon-search btn--no-text btn--icon-large grid-field__filter-open"></button>',
|
||||
_t('SilverStripe\\Forms\\GridField\\GridField.OpenFilter', "Open search and filter"),
|
||||
_t('SilverStripe\\Forms\\GridField\\GridField.OpenFilter', "Open search and filter")
|
||||
)
|
||||
];
|
||||
}
|
||||
$fieldSchema = $this->getSearchFieldSchema($gridField);
|
||||
$forTemplate->SearchFieldSchema = $fieldSchema;
|
||||
$searchTemplates = SSViewer::get_templates_by_class($this, '_Search', __CLASS__);
|
||||
return [
|
||||
'before' => $forTemplate->renderWith($searchTemplates),
|
||||
'buttons-before-right' => sprintf(
|
||||
'<button type="button" name="showFilter" aria-label="%s" title="%s"' .
|
||||
' class="btn btn-secondary font-icon-search btn--no-text btn--icon-large grid-field__filter-open"></button>',
|
||||
_t('SilverStripe\\Forms\\GridField\\GridField.OpenFilter', "Open search and filter"),
|
||||
_t('SilverStripe\\Forms\\GridField\\GridField.OpenFilter', "Open search and filter")
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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 ?? []);
|
||||
}
|
||||
|
||||
|
@ -752,12 +752,11 @@ 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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 = [];
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
namespace SilverStripe\ORM\Connect;
|
||||
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
|
||||
/**
|
||||
* TransactionManager that executes MySQL-compatible transaction control queries
|
||||
*/
|
||||
|
@ -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()
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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');
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
*
|
||||
@ -582,24 +501,12 @@ 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;
|
||||
}
|
||||
$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 -----------------------------------//
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
@ -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,16 +34,8 @@ 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();
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 ?? []);
|
||||
}
|
||||
} elseif ($failUnlessSprintf) {
|
||||
throw new Exception('sprintf style localisation cannot be used in translations - detected in $result');
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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$/
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 [
|
||||
|
@ -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()}
|
||||
*/
|
||||
|
@ -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()
|
||||
|
@ -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 & 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()}
|
||||
*/
|
||||
|
@ -759,7 +759,7 @@ class InjectorTest extends SapphireTest
|
||||
'locator' => SilverStripeServiceConfigurationLocator::class
|
||||
]
|
||||
);
|
||||
Config::modify()->merge(
|
||||
Config::modify()->set(
|
||||
Injector::class,
|
||||
MyChildClass::class,
|
||||
'%$' . MyParentClass::class
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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()
|
||||
|
@ -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');
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace SilverStripe\ORM\Tests;
|
||||
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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, '/');
|
||||
|
@ -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();
|
||||
|
@ -302,7 +302,6 @@ class RequirementsTest extends SapphireTest
|
||||
$backend->clear();
|
||||
$backend->clearCombinedFiles();
|
||||
$backend->setCombinedFilesFolder('_combinedfiles');
|
||||
$backend->setMinifyCombinedFiles(false);
|
||||
$backend->setCombinedFilesEnabled(true);
|
||||
Requirements::flush();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user