diff --git a/src/Control/Controller.php b/src/Control/Controller.php index 017d69af0..3666289e9 100644 --- a/src/Control/Controller.php +++ b/src/Control/Controller.php @@ -73,10 +73,8 @@ class Controller extends RequestHandler implements TemplateGlobalProvider * The response object that the controller returns. * * Set in {@link handleRequest()}. - * - * @var HTTPResponse */ - protected $response; + protected HTTPResponse $response; /** * Default URL handlers. @@ -95,6 +93,12 @@ class Controller extends RequestHandler implements TemplateGlobalProvider 'handleIndex', ]; + public function __construct() + { + parent::__construct(); + $this->setResponse(HTTPResponse::create()); + } + /** * Initialisation function that is run before any action on the controller is called. * @@ -142,12 +146,11 @@ class Controller extends RequestHandler implements TemplateGlobalProvider * * Also set the URLParams */ - public function setRequest($request) + public function setRequest(HTTPRequest $request): static { - $return = parent::setRequest($request); + parent::setRequest($request); $this->setURLParams($this->getRequest()->allParams()); - - return $return; + return $this; } /** @@ -192,11 +195,8 @@ class Controller extends RequestHandler implements TemplateGlobalProvider * Important: If you are going to overload handleRequest, * make sure that you start the method with $this->beforeHandleRequest() * and end the method with $this->afterHandleRequest() - * - * @param HTTPRequest $request - * @return HTTPResponse */ - public function handleRequest(HTTPRequest $request) + public function handleRequest(HTTPRequest $request): HTTPResponse { if (!$request) { throw new \RuntimeException('Controller::handleRequest() not passed a request!'); @@ -332,14 +332,9 @@ class Controller extends RequestHandler implements TemplateGlobalProvider /** * Returns the HTTPResponse object that this controller is building up. Can be used to set the * status code and headers. - * - * @return HTTPResponse */ - public function getResponse() + public function getResponse(): HTTPResponse { - if (!$this->response) { - $this->setResponse(new HTTPResponse()); - } return $this->response; } @@ -628,17 +623,14 @@ class Controller extends RequestHandler implements TemplateGlobalProvider /** * Redirect to the given URL. - * - * @param string $url - * @param int $code - * @return HTTPResponse */ - public function redirect($url, $code = 302) + public function redirect(string $url, int $code = 302): HTTPResponse { - if ($this->getResponse()->getHeader('Location') && $this->getResponse()->getHeader('Location') != $url) { + $response = $this->getResponse(); + if ($response->getHeader('Location') && $response->getHeader('Location') != $url) { user_error("Already directed to " . $this->getResponse()->getHeader('Location') . "; now trying to direct to $url", E_USER_WARNING); - return null; + return $response; } $response = parent::redirect($url, $code); $this->setResponse($response); diff --git a/src/Control/HTTPResponse.php b/src/Control/HTTPResponse.php index 15eb80520..502d5fbaf 100644 --- a/src/Control/HTTPResponse.php +++ b/src/Control/HTTPResponse.php @@ -310,13 +310,7 @@ class HTTPResponse return $this; } - /** - * @param string $dest - * @param int $code - * - * @return $this - */ - public function redirect($dest, $code = 302) + public function redirect(string $dest, int $code = 302): static { if (!in_array($code, self::$redirect_codes)) { trigger_error("Invalid HTTP redirect code {$code}", E_USER_WARNING); diff --git a/src/Control/HTTPResponse_Exception.php b/src/Control/HTTPResponse_Exception.php index 355e28000..252cc7cbb 100644 --- a/src/Control/HTTPResponse_Exception.php +++ b/src/Control/HTTPResponse_Exception.php @@ -17,7 +17,7 @@ use Exception; class HTTPResponse_Exception extends Exception { - protected $response; + protected HTTPResponse $response; /** * @param HTTPResponse|string $body Either the plaintext content of the error @@ -52,17 +52,11 @@ class HTTPResponse_Exception extends Exception parent::__construct((string) $this->getResponse()->getBody(), $this->getResponse()->getStatusCode()); } - /** - * @return HTTPResponse - */ - public function getResponse() + public function getResponse(): HTTPResponse { return $this->response; } - /** - * @param HTTPResponse $response - */ public function setResponse(HTTPResponse $response) { $this->response = $response; diff --git a/src/Control/PjaxResponseNegotiator.php b/src/Control/PjaxResponseNegotiator.php index 08c114ccd..70d3b7657 100644 --- a/src/Control/PjaxResponseNegotiator.php +++ b/src/Control/PjaxResponseNegotiator.php @@ -30,7 +30,7 @@ class PjaxResponseNegotiator */ protected $callbacks = []; - protected $response = null; + protected HTTPResponse $response; /** * Overridden fragments (if any). Otherwise uses fragments from the request. @@ -41,21 +41,18 @@ class PjaxResponseNegotiator * @param array $callbacks * @param HTTPResponse $response An existing response to reuse (optional) */ - public function __construct($callbacks = [], $response = null) + public function __construct($callbacks = [], HTTPResponse $response = null) { $this->callbacks = $callbacks; - $this->response = $response; + $this->response = $response ?: HTTPResponse::create(); } - public function getResponse() + public function getResponse(): HTTPResponse { - if (!$this->response) { - $this->response = new HTTPResponse(); - } return $this->response; } - public function setResponse($response) + public function setResponse(HTTPResponse $response) { $this->response = $response; } @@ -68,10 +65,9 @@ class PjaxResponseNegotiator * @param array $extraCallbacks List of anonymous functions or callables returning either a string * or HTTPResponse, keyed by their fragment identifier. The 'default' key can * be used as a fallback for non-ajax responses. - * @return HTTPResponse * @throws HTTPResponse_Exception */ - public function respond(HTTPRequest $request, $extraCallbacks = []) + public function respond(HTTPRequest $request, $extraCallbacks = []): HTTPResponse { // Prepare the default options and combine with the others $callbacks = array_merge($this->callbacks, $extraCallbacks); diff --git a/src/Control/RequestHandler.php b/src/Control/RequestHandler.php index f5d1fbbcf..76e3580ae 100644 --- a/src/Control/RequestHandler.php +++ b/src/Control/RequestHandler.php @@ -60,7 +60,7 @@ class RequestHandler extends ViewableData * @var HTTPRequest $request The request object that the controller was called with. * Set in {@link handleRequest()}. Useful to generate the {} */ - protected $request = null; + protected HTTPRequest $request; /** * The DataModel for this request @@ -543,11 +543,8 @@ class RequestHandler extends ViewableData /** * Typically the request is set through {@link handleAction()} * or {@link handleRequest()}, but in some based we want to set it manually. - * - * @param HTTPRequest $request - * @return $this */ - public function setRequest($request) + public function setRequest(HTTPRequest $request): static { $this->request = $request; return $this; @@ -581,12 +578,8 @@ class RequestHandler extends ViewableData /** * Redirect to the given URL. - * - * @param string $url - * @param int $code - * @return HTTPResponse */ - public function redirect($url, $code = 302) + public function redirect(string $url, int $code = 302): HTTPResponse { $url = Director::absoluteURL($url); $response = new HTTPResponse(); @@ -655,10 +648,8 @@ class RequestHandler extends ViewableData * URL (see {@link Director::baseURL()}). * * @uses redirect() - * - * @return HTTPResponse */ - public function redirectBack() + public function redirectBack(): HTTPResponse { // Prefer to redirect to ?BackURL, but fall back to Referer header // As a last resort redirect to base url diff --git a/src/Dev/DevBuildController.php b/src/Dev/DevBuildController.php index 30a5b9d84..5f7a949fd 100644 --- a/src/Dev/DevBuildController.php +++ b/src/Dev/DevBuildController.php @@ -4,6 +4,8 @@ namespace SilverStripe\Dev; use SilverStripe\Control\Controller; use SilverStripe\Control\Director; +use SilverStripe\Control\HTTPRequest; +use SilverStripe\Control\HTTPResponse; use SilverStripe\ORM\DatabaseAdmin; class DevBuildController extends Controller @@ -17,7 +19,7 @@ class DevBuildController extends Controller 'build' ]; - public function build($request) + public function build(HTTPRequest $request): HTTPResponse { if (Director::is_cli()) { $da = DatabaseAdmin::create(); diff --git a/src/Forms/FileField.php b/src/Forms/FileField.php index fbe309c8d..7d087c67f 100644 --- a/src/Forms/FileField.php +++ b/src/Forms/FileField.php @@ -23,7 +23,8 @@ use SilverStripe\ORM\DataObjectInterface; * * class ExampleFormController extends PageController { * - * function Form() { + * public function Form(): Form + * { * $fields = new FieldList( * new TextField('MyName'), * new FileField('MyFile') @@ -31,12 +32,13 @@ use SilverStripe\ORM\DataObjectInterface; * $actions = new FieldList( * new FormAction('doUpload', 'Upload file') * ); - * $validator = new RequiredFields(['MyName', 'MyFile']); + * $validator = new RequiredFields(['MyName', 'MyFile']); * * return new Form($this, 'Form', $fields, $actions, $validator); * } * - * function doUpload($data, $form) { + * public function doUpload((array $data, Form $form): HTTPResponse + * { * $file = $data['MyFile']; * $content = file_get_contents($file['tmp_name']); * // ... process content diff --git a/src/Forms/FormRequestHandler.php b/src/Forms/FormRequestHandler.php index 9c2113724..8b22adbc8 100644 --- a/src/Forms/FormRequestHandler.php +++ b/src/Forms/FormRequestHandler.php @@ -103,7 +103,7 @@ class FormRequestHandler extends RequestHandler * if the form is valid. * * @param HTTPRequest $request - * @return HTTPResponse + * @return mixed * @throws HTTPResponse_Exception */ public function httpSubmission($request) @@ -200,7 +200,7 @@ class FormRequestHandler extends RequestHandler // buttonClicked() validates that the action set above is valid && !$this->buttonClicked() ) { - return $this->httpError( + $this->httpError( 403, sprintf('Action "%s" not allowed on controller (Class: %s)', $funcName, get_class($controller)) ); @@ -209,7 +209,7 @@ class FormRequestHandler extends RequestHandler $this->hasMethod($funcName) && !$this->checkAccessAction($funcName) ) { - return $this->httpError( + $this->httpError( 403, sprintf('Action "%s" not allowed on form request handler (Class: "%s")', $funcName, static::class) ); @@ -261,7 +261,7 @@ class FormRequestHandler extends RequestHandler ); } - return $this->httpError(404, "Could not find a suitable form-action callback function"); + $this->httpError(404, "Could not find a suitable form-action callback function"); } /** @@ -299,11 +299,8 @@ class FormRequestHandler extends RequestHandler * handles 'application/json' requests with a JSON object containing the error messages. * Behaviour can be influenced by setting {@link $redirectToFormOnValidationError}, * and can be overruled by setting {@link $validationResponseCallback}. - * - * @param ValidationResult $result - * @return HTTPResponse */ - protected function getValidationErrorResponse(ValidationResult $result) + protected function getValidationErrorResponse(ValidationResult $result): HTTPResponse { // Check for custom handling mechanism $callback = $this->form->getValidationResponseCallback(); @@ -329,10 +326,8 @@ class FormRequestHandler extends RequestHandler /** * Redirect back to this form with an added #anchor link - * - * @return HTTPResponse */ - public function redirectBackToForm() + public function redirectBackToForm(): HTTPResponse { $pageURL = $this->getReturnReferer(); if (!$pageURL) { @@ -369,9 +364,8 @@ class FormRequestHandler extends RequestHandler * * @internal called from {@see Form::getValidationErrorResponse} * @param ValidationResult $result - * @return HTTPResponse */ - protected function getAjaxErrorResponse(ValidationResult $result) + protected function getAjaxErrorResponse(ValidationResult $result): HTTPResponse { // Ajax form submissions accept json encoded errors by default $acceptType = $this->getRequest()->getHeader('Accept'); diff --git a/src/Security/MemberAuthenticator/LostPasswordHandler.php b/src/Security/MemberAuthenticator/LostPasswordHandler.php index 6fcac0f15..37e8b896b 100644 --- a/src/Security/MemberAuthenticator/LostPasswordHandler.php +++ b/src/Security/MemberAuthenticator/LostPasswordHandler.php @@ -153,13 +153,8 @@ class LostPasswordHandler extends RequestHandler * the logic, by returning FALSE. In this case, the user will be redirected back * to the form without further action. It is recommended to set a message * in the form detailing why the action was denied. - * - * @skipUpgrade - * @param array $data Submitted data - * @param LostPasswordForm $form - * @return HTTPResponse */ - public function forgotPassword($data, $form) + public function forgotPassword(array $data, Form $form): HTTPResponse { // Run a first pass validation check on the data $dataValidation = $this->validateForgotPasswordData($data, $form); diff --git a/src/Security/Security.php b/src/Security/Security.php index 5f82d8202..283af0fc9 100644 --- a/src/Security/Security.php +++ b/src/Security/Security.php @@ -314,9 +314,8 @@ class Security extends Controller implements TemplateGlobalProvider * * The alreadyLoggedIn value can contain a '%s' placeholder that will be replaced with a link * to log in. - * @return HTTPResponse */ - public static function permissionFailure($controller = null, $messageSet = null) + public static function permissionFailure($controller = null, $messageSet = null): HTTPResponse { self::set_ignore_disallowed_actions(true); diff --git a/tests/php/Control/Middleware/Control/TestController.php b/tests/php/Control/Middleware/Control/TestController.php index d906dc0df..08f093a5a 100644 --- a/tests/php/Control/Middleware/Control/TestController.php +++ b/tests/php/Control/Middleware/Control/TestController.php @@ -3,12 +3,14 @@ namespace SilverStripe\Control\Tests\Middleware\Control; use SilverStripe\Control\Controller; +use SilverStripe\Control\HTTPRequest; +use SilverStripe\Control\HTTPResponse; class TestController extends Controller { - public function index($request) + public function index(HTTPRequest $request): HTTPResponse { - return "Success"; + return HTTPResponse::create()->setBody("Success"); } public function Link($action = null) diff --git a/tests/php/Control/RequestHandlingTest/TestFormHandler.php b/tests/php/Control/RequestHandlingTest/TestFormHandler.php index c05d245e2..62f62d4f1 100644 --- a/tests/php/Control/RequestHandlingTest/TestFormHandler.php +++ b/tests/php/Control/RequestHandlingTest/TestFormHandler.php @@ -3,6 +3,8 @@ namespace SilverStripe\Control\Tests\RequestHandlingTest; +use SilverStripe\Control\HTTPRequest; +use SilverStripe\Control\HTTPResponse; use SilverStripe\Forms\FormRequestHandler; /** @@ -29,13 +31,13 @@ class TestFormHandler extends FormRequestHandler return $this->form->Fields()->dataFieldByName($request->param('FieldName')); } - public function handleSubmission($request) + public function handleSubmission(HTTPRequest $request): HTTPResponse { - return "Form posted"; + return HTTPResponse::create()->setBody("Form posted"); } - public function handleGet($request) + public function handleGet(HTTPRequest $request): HTTPResponse { - return "Get request on form"; + return HTTPResponse::create()->setBody("Get request on form"); } } diff --git a/tests/php/Forms/FormFactoryTest/ControllerExtension.php b/tests/php/Forms/FormFactoryTest/ControllerExtension.php index 49ba30dfe..ba2be1798 100644 --- a/tests/php/Forms/FormFactoryTest/ControllerExtension.php +++ b/tests/php/Forms/FormFactoryTest/ControllerExtension.php @@ -3,9 +3,12 @@ namespace SilverStripe\Forms\Tests\FormFactoryTest; use SilverStripe\Control\Controller; +use SilverStripe\Control\HTTPRequest; +use SilverStripe\Control\HTTPResponse; use SilverStripe\Core\Convert; use SilverStripe\Core\Extension; use SilverStripe\Forms\FieldList; +use SilverStripe\Forms\Form; use SilverStripe\Forms\FormAction; use SilverStripe\Forms\LiteralField; use SilverStripe\ORM\DataObject; @@ -75,13 +78,15 @@ class ControllerExtension extends Extension } } - public function publish($data, $form) + public function publish(array $data, Form $form): HTTPResponse { // noop + return HTTPResponse::create(); } - public function preview() + public function preview(HTTPRequest $request): HTTPResponse { // noop + return HTTPResponse::create(); } } diff --git a/tests/php/Forms/FormTest/ControllerWithSecurityToken.php b/tests/php/Forms/FormTest/ControllerWithSecurityToken.php index 4c01aaec5..23597f65e 100644 --- a/tests/php/Forms/FormTest/ControllerWithSecurityToken.php +++ b/tests/php/Forms/FormTest/ControllerWithSecurityToken.php @@ -3,6 +3,7 @@ namespace SilverStripe\Forms\Tests\FormTest; use SilverStripe\Control\Controller; +use SilverStripe\Control\HTTPResponse; use SilverStripe\Dev\TestOnly; use SilverStripe\Forms\EmailField; use SilverStripe\Forms\FieldList; @@ -49,7 +50,7 @@ class ControllerWithSecurityToken extends Controller implements TestOnly return $form; } - public function doSubmit($data, $form, $request) + public function doSubmit(array $data, Form $form): HTTPResponse { $form->sessionMessage('Test save was successful', 'good'); return $this->redirectBack(); diff --git a/tests/php/Forms/FormTest/ControllerWithSpecialSubmittedValueFields.php b/tests/php/Forms/FormTest/ControllerWithSpecialSubmittedValueFields.php index 18b500d4e..250924b6f 100644 --- a/tests/php/Forms/FormTest/ControllerWithSpecialSubmittedValueFields.php +++ b/tests/php/Forms/FormTest/ControllerWithSpecialSubmittedValueFields.php @@ -82,13 +82,13 @@ class ControllerWithSpecialSubmittedValueFields extends Controller implements Te return $form; } - public function doSubmit($data, $form, $request) + public function doSubmit(array $data, Form $form): HTTPResponse { $form->sessionMessage('Test save was successful', 'good'); return $this->redirectBack(); } - public function doTriggerException($data, $form, $request) + public function doTriggerException(array $data, Form $form): HTTPResponse { $result = new ValidationResult(); $result->addFieldError('Email', 'Error on Email field'); diff --git a/tests/php/Forms/FormTest/ControllerWithStrictPostCheck.php b/tests/php/Forms/FormTest/ControllerWithStrictPostCheck.php index 687414f50..4b77e4264 100644 --- a/tests/php/Forms/FormTest/ControllerWithStrictPostCheck.php +++ b/tests/php/Forms/FormTest/ControllerWithStrictPostCheck.php @@ -3,6 +3,7 @@ namespace SilverStripe\Forms\Tests\FormTest; use SilverStripe\Control\Controller; +use SilverStripe\Control\HTTPResponse; use SilverStripe\Dev\TestOnly; use SilverStripe\Forms\EmailField; use SilverStripe\Forms\FieldList; @@ -48,7 +49,7 @@ class ControllerWithStrictPostCheck extends Controller implements TestOnly return $form; } - public function doSubmit($data, $form, $request) + public function doSubmit(array $data, Form $form): HTTPResponse { $form->sessionMessage('Test save was successful', 'good'); return $this->redirectBack(); diff --git a/tests/php/Forms/FormTest/TestController.php b/tests/php/Forms/FormTest/TestController.php index 3f49eeac1..fc75a9136 100644 --- a/tests/php/Forms/FormTest/TestController.php +++ b/tests/php/Forms/FormTest/TestController.php @@ -3,6 +3,7 @@ namespace SilverStripe\Forms\Tests\FormTest; use SilverStripe\Control\Controller; +use SilverStripe\Control\HTTPResponse; use SilverStripe\Dev\TestOnly; use SilverStripe\Forms\CheckboxSetField; use SilverStripe\Forms\EmailField; @@ -79,13 +80,13 @@ class TestController extends Controller implements TestOnly return $form; } - public function doSubmit($data, $form, $request) + public function doSubmit(array $data, Form $form): HTTPResponse { $form->sessionMessage('Test save was successful', 'good'); return $this->redirectBack(); } - public function doTriggerException($data, $form, $request) + public function doTriggerException(array $data, Form $form): HTTPResponse { $result = new ValidationResult(); $result->addFieldError('Email', 'Error on Email field'); @@ -93,13 +94,13 @@ class TestController extends Controller implements TestOnly throw new ValidationException($result); } - public function doSubmitValidationExempt($data, $form, $request) + public function doSubmitValidationExempt(array $data, Form $form): HTTPResponse { $form->sessionMessage('Validation skipped', 'good'); return $this->redirectBack(); } - public function doSubmitActionExempt($data, $form, $request) + public function doSubmitActionExempt(array $data, Form $form): HTTPResponse { $form->sessionMessage('Validation bypassed!', 'good'); return $this->redirectBack(); diff --git a/tests/php/Forms/GridField/GridField_URLHandlerTest/TestComponent.php b/tests/php/Forms/GridField/GridField_URLHandlerTest/TestComponent.php index 1df1f7eb1..b3346e065 100644 --- a/tests/php/Forms/GridField/GridField_URLHandlerTest/TestComponent.php +++ b/tests/php/Forms/GridField/GridField_URLHandlerTest/TestComponent.php @@ -4,6 +4,7 @@ namespace SilverStripe\Forms\Tests\GridField\GridField_URLHandlerTest; use SilverStripe\Control\Controller; use SilverStripe\Control\HTTPRequest; +use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\RequestHandler; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\Form; @@ -83,9 +84,9 @@ class TestComponent extends RequestHandler implements GridField_URLHandler ); } - public function doAction($data, $form) + public function doAction(array $data, Form $form): HTTPResponse { - return "Submitted " . $data['Test'] . " to component"; + return HTTPResponse::create()->setBody("Submitted " . $data['Test'] . " to component"); } public function testpage(GridField $gridField, HTTPRequest $request) diff --git a/tests/php/Forms/GridField/GridField_URLHandlerTest/TestComponent_ItemRequest.php b/tests/php/Forms/GridField/GridField_URLHandlerTest/TestComponent_ItemRequest.php index 3a2bf24c7..0a000512c 100644 --- a/tests/php/Forms/GridField/GridField_URLHandlerTest/TestComponent_ItemRequest.php +++ b/tests/php/Forms/GridField/GridField_URLHandlerTest/TestComponent_ItemRequest.php @@ -2,6 +2,7 @@ namespace SilverStripe\Forms\Tests\GridField\GridField_URLHandlerTest; +use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\RequestHandler; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\Form; @@ -53,9 +54,9 @@ class TestComponent_ItemRequest extends RequestHandler ); } - public function doAction($data, $form) + public function doAction(array $data, Form $form): HTTPResponse { - return "Submitted " . $data['Test'] . " to item #" . $this->id; + return HTTPResponse::create()->setBody("Submitted " . $data['Test'] . " to item #" . $this->id); } public function testpage() diff --git a/tests/php/Security/SecurityTest/NullController.php b/tests/php/Security/SecurityTest/NullController.php index 503a9fe73..f6387944e 100644 --- a/tests/php/Security/SecurityTest/NullController.php +++ b/tests/php/Security/SecurityTest/NullController.php @@ -3,6 +3,7 @@ namespace SilverStripe\Security\Tests\SecurityTest; use SilverStripe\Control\Controller; +use SilverStripe\Control\HTTPResponse; use SilverStripe\Dev\TestOnly; /** @@ -11,9 +12,10 @@ use SilverStripe\Dev\TestOnly; class NullController extends Controller implements TestOnly { - public function redirect($url, $code = 302) + public function redirect(string $url, int $code = 302): HTTPResponse { // NOOP + return HTTPResponse::create(); } public function Link($action = null)