diff --git a/src/Dev/BulkLoader.php b/src/Dev/BulkLoader.php index 7e9a920c5cb..4f26a3fe201 100644 --- a/src/Dev/BulkLoader.php +++ b/src/Dev/BulkLoader.php @@ -172,7 +172,7 @@ public function load($filepath) if (!$record->canDelete()) { $type = $record->i18n_singular_name(); throw new HTTPResponse_Exception( - _t(__CLASS__ . '.CANNOT_DELETE', "Not allowed to delete '$type' records"), + _t(__CLASS__ . '.CANNOT_DELETE', "Not allowed to delete '{type}' records", ["type" => $type]), 403 ); } diff --git a/src/Dev/CsvBulkLoader.php b/src/Dev/CsvBulkLoader.php index edcfa25b293..1d00492cfd8 100644 --- a/src/Dev/CsvBulkLoader.php +++ b/src/Dev/CsvBulkLoader.php @@ -185,7 +185,7 @@ protected function processRecord($record, $columnMap, &$results, $preview = fals if ($this->getCheckPermissions() && !$preview && $alreadyExists && !$existingObj->canEdit()) { $type = $existingObj->i18n_singular_name(); throw new HTTPResponse_Exception( - _t(BulkLoader::class . '.CANNOT_EDIT', "Not allowed to edit '$type' records"), + _t(BulkLoader::class . '.CANNOT_EDIT', "Not allowed to edit '{type}' records", ["type" => $type]), 403 ); } @@ -197,7 +197,7 @@ protected function processRecord($record, $columnMap, &$results, $preview = fals if ($this->getCheckPermissions() && !$preview && !$alreadyExists && !$obj->canCreate()) { $type = $obj->i18n_singular_name(); throw new HTTPResponse_Exception( - _t(BulkLoader::class . '.CANNOT_CREATE', "Not allowed to create '$type' records"), + _t(BulkLoader::class . '.CANNOT_CREATE', "Not allowed to create '{type}' records", ["type" => $type]), 403 ); } @@ -233,7 +233,7 @@ protected function processRecord($record, $columnMap, &$results, $preview = fals if ($this->getCheckPermissions() && !$relationObj->canCreate()) { $type = $relationObj->i18n_singular_name(); throw new HTTPResponse_Exception( - _t(BulkLoader::class . '.CANNOT_CREATE', "Not allowed to create '$type' records"), + _t(BulkLoader::class . '.CANNOT_CREATE', "Not allowed to create '{type}' records", ["type" => $type]), 403 ); } @@ -255,7 +255,7 @@ protected function processRecord($record, $columnMap, &$results, $preview = fals if ($this->getCheckPermissions() && !$relationObj->canEdit()) { $type = $relationObj->i18n_singular_name(); throw new HTTPResponse_Exception( - _t(BulkLoader::class . '.CANNOT_EDIT', "Not allowed to edit '$type' records"), + _t(BulkLoader::class . '.CANNOT_EDIT', "Not allowed to edit '{type}' records", ["type" => $type]), 403 ); } diff --git a/src/Forms/Form.php b/src/Forms/Form.php index 440ba4b5224..07c4fc9eda2 100644 --- a/src/Forms/Form.php +++ b/src/Forms/Form.php @@ -1334,9 +1334,6 @@ public function validate(): ValidationResult * do not want them parsed as submitted data. MERGE_AS_SUBMITTED_VALUE does the opposite and forces the data to be * parsed as it would be submitted from a form. * - * For backwards compatibility reasons, this parameter can also be set to === true, which is the same as passing - * MERGE_CLEAR_MISSING - * * @param array $fieldList An optional list of fields to process. This can be useful when you have a * form that has some fields that save to one object, and some that save to another. * @return $this @@ -1350,8 +1347,20 @@ public function loadDataFrom($data, $mergeStrategy = 0, $fieldList = null) // Handle the backwards compatible case of passing "true" as the second argument if ($mergeStrategy === true) { + Deprecation::notice( + '5.4.0', + 'Passing `true` to the $mergeStrategy argument in ' . Form::class . '::loadDataFrom() is deprecated.' + . ' Pass ' . Form::class . '::MERGE_CLEAR_MISSING instead.', + Deprecation::SCOPE_GLOBAL + ); $mergeStrategy = Form::MERGE_CLEAR_MISSING; } elseif ($mergeStrategy === false) { + Deprecation::notice( + '5.4.0', + 'Passing `false` to the $mergeStrategy argument in ' . Form::class . '::loadDataFrom() is deprecated.' + . ' Pass 0 instead.', + Deprecation::SCOPE_GLOBAL + ); $mergeStrategy = 0; } diff --git a/src/Forms/FormRequestHandler.php b/src/Forms/FormRequestHandler.php index b72df564d7e..8d7bec85d44 100644 --- a/src/Forms/FormRequestHandler.php +++ b/src/Forms/FormRequestHandler.php @@ -133,7 +133,7 @@ public function httpSubmission($request) $allowedFields = array_keys($this->form->Fields()->saveableFields() ?? []); // Populate the form - $this->form->loadDataFrom($vars, true, $allowedFields); + $this->form->loadDataFrom($vars, Form::MERGE_CLEAR_MISSING, $allowedFields); // Protection against CSRF attacks $token = $this->form->getSecurityToken(); diff --git a/src/ORM/Connect/TransactionManager.php b/src/ORM/Connect/TransactionManager.php index feb29da1b28..cf8b4d1490b 100644 --- a/src/ORM/Connect/TransactionManager.php +++ b/src/ORM/Connect/TransactionManager.php @@ -16,8 +16,8 @@ interface TransactionManager /** * Start a prepared transaction * - * @param string|boolean $transactionMode Transaction mode, or false to ignore. Deprecated and will be removed in SS5. - * @param string|boolean $sessionCharacteristics Session characteristics, or false to ignore. Deprecated and will be removed in SS5. + * @param string|boolean $transactionMode Transaction mode, or false to ignore. + * @param string|boolean $sessionCharacteristics Session characteristics, or false to ignore. * @throws DatabaseException on failure * @return bool True on success */ diff --git a/src/ORM/DataObject.php b/src/ORM/DataObject.php index 65b00fe9ed9..28da655b35b 100644 --- a/src/ORM/DataObject.php +++ b/src/ORM/DataObject.php @@ -2685,6 +2685,12 @@ public function getCMSCompositeValidator(): CompositeValidator // Support for the old method during the deprecation period if ($this->hasMethod('getCMSValidator')) { + Deprecation::notice( + '5.4.0', + 'The getCMSValidator() method is deprecated and won\'t be supported in a future major release.' + . ' Override getCMSCompositeValidator() instead.', + Deprecation::SCOPE_GLOBAL + ); $compositeValidator->addValidator($this->getCMSValidator()); } @@ -3419,7 +3425,6 @@ public function getReverseAssociation($className) * Supports parameterised queries. See SQLSelect::addWhere() for syntax examples. * @param string|array|null $sort Passed to DataList::sort() * BY clause. If omitted, DataObject::$default_sort will be used. - * @param string $join Deprecated 3.0 Join clause. Use leftJoin($table, $joinClause) instead. * @param string|array $limit A limit expression to be inserted into the LIMIT clause. * @param string $containerClass The container class to return the results in. * @@ -3429,7 +3434,6 @@ public static function get( $callerClass = null, $filter = "", $sort = "", - $join = "", $limit = null, $containerClass = DataList::class ) { @@ -3439,18 +3443,13 @@ public static function get( if ($callerClass === DataObject::class) { throw new InvalidArgumentException('Call ::get() instead of DataObject::get()'); } - if ($filter || $sort || $join || $limit || ($containerClass !== DataList::class)) { + if ($filter || $sort || $limit || ($containerClass !== DataList::class)) { throw new InvalidArgumentException('If calling ::get() then you shouldn\'t pass any other' . ' arguments'); } } elseif ($callerClass === DataObject::class) { throw new InvalidArgumentException('DataObject::get() cannot query non-subclass DataObject directly'); } - if ($join) { - throw new InvalidArgumentException( - 'The $join argument has been removed. Use leftJoin($table, $joinClause) instead.' - ); - } // Build and decorate with args $result = DataList::create($callerClass); diff --git a/src/ORM/Search/BasicSearchContext.php b/src/ORM/Search/BasicSearchContext.php index d128829c185..34fd9ecc1d0 100644 --- a/src/ORM/Search/BasicSearchContext.php +++ b/src/ORM/Search/BasicSearchContext.php @@ -33,28 +33,16 @@ class BasicSearchContext extends SearchContext * If a filter is applied to a relationship in dot notation, * the parameter name should have the dots replaced with double underscores, * for example "Comments__Name" instead of the filter name "Comments.Name". - * @param array|bool|string $sort Field to sort on. + * @param array|false|string $sort Field to sort on. * @param int|array|null $limit * @param SS_List $existingQuery */ - public function getQuery($searchParams, $sort = false, $limit = false, $existingQuery = null): SS_List + public function getQuery($searchParams, $sort = false, int|array|null $limit = null, $existingQuery = null): SS_List { if (!$existingQuery || !is_a($existingQuery, SS_List::class)) { throw new InvalidArgumentException('getQuery requires a pre-existing SS_List list to be passed as $existingQuery.'); } - if ((count(func_get_args()) >= 3) && (!in_array(gettype($limit), ['array', 'NULL', 'integer']))) { - Deprecation::notice( - '5.1.0', - '$limit should be type of int|array|null' - ); - if (is_string($limit) && is_numeric($limit)) { - $limit = (int) $limit; - } else { - $limit = null; - } - } - $searchParams = $this->applySearchFilters($this->normaliseSearchParams($searchParams)); $result = $this->applyGeneralSearchField($searchParams, $existingQuery); diff --git a/src/ORM/Search/SearchContext.php b/src/ORM/Search/SearchContext.php index 90fe2b4d0b9..6b6195cfca5 100644 --- a/src/ORM/Search/SearchContext.php +++ b/src/ORM/Search/SearchContext.php @@ -142,22 +142,15 @@ protected function applyBaseTableFields() * If a filter is applied to a relationship in dot notation, * the parameter name should have the dots replaced with double underscores, * for example "Comments__Name" instead of the filter name "Comments.Name". - * @param array|bool|string $sort Database column to sort on. + * @param array|false|string $sort Database column to sort on. * Falls back to {@link DataObject::$default_sort} if not provided. * @param int|array|null $limit * @param DataList $existingQuery * @return DataList * @throws Exception */ - public function getQuery($searchParams, $sort = false, $limit = false, $existingQuery = null) + public function getQuery($searchParams, $sort = false, int|array|null $limit = null, $existingQuery = null) { - if ((count(func_get_args()) >= 3) && (!in_array(gettype($limit), ['integer', 'array', 'NULL']))) { - Deprecation::notice( - '5.1.0', - '$limit should be type of int|array|null' - ); - $limit = null; - } $this->setSearchParams($searchParams); $query = $this->prepareQuery($sort, $limit, $existingQuery); return $this->search($query); @@ -197,9 +190,6 @@ private function prepareQuery($sort, $limit, ?DataList $existingQuery): DataList } $query = null; if ($existingQuery) { - if (!($existingQuery instanceof DataList)) { - throw new InvalidArgumentException("existingQuery must be DataList"); - } if ($existingQuery->dataClass() != $this->modelClass) { throw new InvalidArgumentException("existingQuery's dataClass is " . $existingQuery->dataClass() . ", $this->modelClass expected."); diff --git a/src/Security/MemberAuthenticator/CookieAuthenticationHandler.php b/src/Security/MemberAuthenticator/CookieAuthenticationHandler.php index 8f71d503d45..b18d29a4597 100644 --- a/src/Security/MemberAuthenticator/CookieAuthenticationHandler.php +++ b/src/Security/MemberAuthenticator/CookieAuthenticationHandler.php @@ -175,22 +175,8 @@ public function authenticateRequest(HTTPRequest $request) $this->cascadeInTo->logIn($member, false, $request); } - // Renew the token - Deprecation::withSuppressedNotice(fn() => $rememberLoginHash->renew()); - - // Send the new token to the client if it was changed - if ($rememberLoginHash->getToken()) { - $tokenExpiryDays = RememberLoginHash::config()->uninherited('token_expiry_days'); - Cookie::set( - $this->getTokenCookieName(), - $member->ID . ':' . $rememberLoginHash->getToken(), - $tokenExpiryDays, - null, - null, - false, - true - ); - } + // Session renewal hook + $rememberLoginHash->extend('onAfterRenewSession'); // Audit logging hook $member->extend('memberAutoLoggedIn'); diff --git a/src/Security/RememberLoginHash.php b/src/Security/RememberLoginHash.php index 1895445b226..e2f82c7f9dd 100644 --- a/src/Security/RememberLoginHash.php +++ b/src/Security/RememberLoginHash.php @@ -82,15 +82,6 @@ class RememberLoginHash extends DataObject */ private static $force_single_token = false; - /** - * If true, the token will be replaced during session renewal. This can cause unexpected - * logouts if the new token does not reach the client (e.g. due to a network error). - * - * This can be disabled as of CMS 5.3, and renewal will be removed entirely in CMS 6. - * @deprecated 5.3.0 Will be removed without equivalent functionality - */ - private static bool $replace_token_during_session_renewal = true; - /** * The token used for the hash. Only present during the lifetime of the request * that generates it, as the hash representation is stored in the database and @@ -201,28 +192,6 @@ public static function generate(Member $member) return $rememberLoginHash; } - /** - * Generates a new hash for this member but keeps the device ID intact - * - * @deprecated 5.3.0 Will be removed without equivalent functionality - * @return RememberLoginHash - */ - public function renew() - { - // Only regenerate token if configured to do so - Deprecation::notice('5.3.0', 'Will be removed without equivalent functionality'); - $replaceToken = RememberLoginHash::config()->get('replace_token_during_session_renewal'); - if ($replaceToken) { - $hash = $this->getNewHash($this->Member()); - $this->Hash = $hash; - } - - $this->extend('onAfterRenewToken', $replaceToken); - $this->write(); - - return $this; - } - /** * Deletes existing tokens for this member * if logout_across_devices is true, all tokens are deleted, otherwise diff --git a/tests/php/ORM/DataObjectTest.php b/tests/php/ORM/DataObjectTest.php index a5996a5aa24..92add5bfec8 100644 --- a/tests/php/ORM/DataObjectTest.php +++ b/tests/php/ORM/DataObjectTest.php @@ -377,7 +377,7 @@ public function testGet() $this->assertEquals('Phil', $comments->first()->Name); // Test limit - $comments = DataObject::get(DataObjectTest\TeamComment::class, '', "\"Name\" ASC", '', '1,2'); + $comments = DataObject::get(DataObjectTest\TeamComment::class, '', "\"Name\" ASC", '1,2'); $this->assertEquals(2, $comments->count()); $this->assertEquals('Joe', $comments->first()->Name); $this->assertEquals('Phil', $comments->last()->Name); diff --git a/tests/php/ORM/Search/BasicSearchContextTest.php b/tests/php/ORM/Search/BasicSearchContextTest.php index e0a6966430e..9d0157de118 100644 --- a/tests/php/ORM/Search/BasicSearchContextTest.php +++ b/tests/php/ORM/Search/BasicSearchContextTest.php @@ -266,26 +266,6 @@ public static function provideGetQueryLimit(): array 'Sara', ], ], - 'limit numeric string' => [ - 'limit' => '4', - 'expected' => [ - 'James', - 'John', - 'Jane', - 'Hemi', - ], - ], - 'limit invalid string' => [ - 'limit' => 'blah', - 'expected' => [ - 'James', - 'John', - 'Jane', - 'Hemi', - 'Sara', - 'MatchNothing', - ], - ], ]; }