From f407c56118216881dab85d5007df4cb1f42c2f09 Mon Sep 17 00:00:00 2001
From: kenjis <kenji.uui@gmail.com>
Date: Tue, 20 Sep 2022 17:10:21 +0900
Subject: [PATCH 1/8] fix: add missing methods in MessageInterface

These are missing for ResponseInterface.
---
 system/HTTP/MessageInterface.php | 33 ++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/system/HTTP/MessageInterface.php b/system/HTTP/MessageInterface.php
index c9a65d4db372..284b876babde 100644
--- a/system/HTTP/MessageInterface.php
+++ b/system/HTTP/MessageInterface.php
@@ -27,6 +27,15 @@ interface MessageInterface
      */
     public function setBody($data);
 
+    /**
+     * Gets the body of the message.
+     *
+     * @return string|null
+     *
+     * @TODO Incompatible return type with PSR-7
+     */
+    public function getBody();
+
     /**
      * Appends data to the body of the current message.
      *
@@ -48,6 +57,17 @@ public function populateHeaders(): void;
      */
     public function headers(): array;
 
+    /**
+     * Checks if a header exists by the given case-insensitive name.
+     *
+     * @param string $name Case-insensitive header field name.
+     *
+     * @return bool Returns true if any header names match the given header
+     *              name using a case-insensitive string comparison. Returns false if
+     *              no matching header name is found in the message.
+     */
+    public function hasHeader(string $name): bool;
+
     /**
      * Returns a single Header object. If multiple headers with the same
      * name exist, then will return an array of header objects.
@@ -58,6 +78,19 @@ public function headers(): array;
      */
     public function header($name);
 
+    /**
+     * Retrieves a comma-separated string of the values for a single header.
+     *
+     * This method returns all of the header values of the given
+     * case-insensitive header name as a string concatenated together using
+     * a comma.
+     *
+     * NOTE: Not all header values may be appropriately represented using
+     * comma concatenation. For such headers, use getHeader() instead
+     * and supply your own delimiter when concatenating.
+     */
+    public function getHeaderLine(string $name): string;
+
     /**
      * Sets a header and it's value.
      *

From df20d3bf886c45695977aa86f77405b1fb121409 Mon Sep 17 00:00:00 2001
From: kenjis <kenji.uui@gmail.com>
Date: Tue, 20 Sep 2022 17:10:59 +0900
Subject: [PATCH 2/8] fix: ResponseInterface

---
 system/HTTP/ResponseInterface.php | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/system/HTTP/ResponseInterface.php b/system/HTTP/ResponseInterface.php
index e8f9fd3fcf3b..aaf548635a56 100644
--- a/system/HTTP/ResponseInterface.php
+++ b/system/HTTP/ResponseInterface.php
@@ -28,10 +28,8 @@
  * - Status code and reason phrase
  * - Headers
  * - Message body
- *
- * @mixin RedirectResponse
  */
-interface ResponseInterface
+interface ResponseInterface extends MessageInterface
 {
     /**
      * Constants for status codes.

From 331f76f21a325f9232b558ca51ce848b5678896e Mon Sep 17 00:00:00 2001
From: kenjis <kenji.uui@gmail.com>
Date: Tue, 20 Sep 2022 17:11:22 +0900
Subject: [PATCH 3/8] docs: add empty line

---
 system/HTTP/Response.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/system/HTTP/Response.php b/system/HTTP/Response.php
index c0f3a2e8120a..e733b3ee336d 100644
--- a/system/HTTP/Response.php
+++ b/system/HTTP/Response.php
@@ -188,6 +188,7 @@ public function __construct($config)
 
     /**
      * Turns "pretend" mode on or off to aid in testing.
+     *
      * Note that this is not a part of the interface so
      * should not be relied on outside of internal testing.
      *

From 03ea7ad5ff6c92be8400bbde18c8008345352b06 Mon Sep 17 00:00:00 2001
From: kenjis <kenji.uui@gmail.com>
Date: Tue, 20 Sep 2022 17:12:18 +0900
Subject: [PATCH 4/8] refactor: make useSafeOutput() deprecated

CodeIgniter should not depend on Response::pretend().
---
 system/CodeIgniter.php                        | 10 +++-
 tests/system/CodeIgniterTest.php              | 57 ++++++++++---------
 .../system/RESTful/ResourceControllerTest.php | 19 ++++---
 .../system/RESTful/ResourcePresenterTest.php  | 16 +++---
 4 files changed, 56 insertions(+), 46 deletions(-)

diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php
index 79bc192c094e..0c955556685e 100644
--- a/system/CodeIgniter.php
+++ b/system/CodeIgniter.php
@@ -138,6 +138,8 @@ class CodeIgniter
      * to keep from setting headers/cookies/etc
      *
      * @var bool
+     *
+     * @deprecated No longer used.
      */
     protected $useSafeOutput = false;
 
@@ -340,7 +342,7 @@ public function run(?RouteCollectionInterface $routes = null, bool $returnRespon
                 return $response;
             }
 
-            $this->response->pretend($this->useSafeOutput)->send();
+            $this->response->send();
             $this->callExit(EXIT_SUCCESS);
 
             return;
@@ -371,6 +373,8 @@ public function run(?RouteCollectionInterface $routes = null, bool $returnRespon
      * not complain when ini_set() function is used.
      *
      * @return $this
+     *
+     * @deprecated No longer used.
      */
     public function useSafeOutput(bool $safe = true)
     {
@@ -433,7 +437,7 @@ protected function handleRequest(?RouteCollectionInterface $routes, Cache $cache
 
         // If a ResponseInterface instance is returned then send it back to the client and stop
         if ($possibleResponse instanceof ResponseInterface) {
-            return $returnResponse ? $possibleResponse : $possibleResponse->pretend($this->useSafeOutput)->send();
+            return $returnResponse ? $possibleResponse : $possibleResponse->send();
         }
 
         if ($possibleResponse instanceof Request) {
@@ -1057,7 +1061,7 @@ public function spoofRequestMethod()
      */
     protected function sendResponse()
     {
-        $this->response->pretend($this->useSafeOutput)->send();
+        $this->response->send();
     }
 
     /**
diff --git a/tests/system/CodeIgniterTest.php b/tests/system/CodeIgniterTest.php
index 4b1938aa0293..eb685eeedb16 100644
--- a/tests/system/CodeIgniterTest.php
+++ b/tests/system/CodeIgniterTest.php
@@ -41,6 +41,9 @@ protected function setUp(): void
         $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
 
         $this->codeigniter = new MockCodeIgniter(new App());
+
+        $response = Services::response();
+        $response->pretend();
     }
 
     protected function tearDown(): void
@@ -60,7 +63,7 @@ public function testRunEmptyDefaultRoute()
         $_SERVER['argc'] = 1;
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertStringContainsString('Welcome to CodeIgniter', $output);
@@ -82,7 +85,7 @@ public function testRunClosureRoute()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertStringContainsString('You want to see "about" page.', $output);
@@ -101,7 +104,7 @@ public function testRun404Override()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($routes);
+        $this->codeigniter->run($routes);
         $output = ob_get_clean();
 
         $this->assertStringContainsString('Hello', $output);
@@ -120,7 +123,7 @@ public function testRun404OverrideControllerReturnsResponse()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($routes);
+        $this->codeigniter->run($routes);
         $output = ob_get_clean();
 
         $this->assertStringContainsString('Oops', $output);
@@ -141,7 +144,7 @@ public function testRun404OverrideByClosure()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($routes);
+        $this->codeigniter->run($routes);
         $output = ob_get_clean();
 
         $this->assertStringContainsString('404 Override by Closure.', $output);
@@ -161,7 +164,7 @@ public function testControllersCanReturnString()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertStringContainsString('You want to see "about" page.', $output);
@@ -186,7 +189,7 @@ public function testControllersCanReturnResponseObject()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertStringContainsString("You want to see 'about' page.", $output);
@@ -213,7 +216,7 @@ public function testControllersCanReturnDownloadResponseObject()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertSame('some text', $output);
@@ -234,7 +237,7 @@ public function testControllersRunFilterByClassName()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertStringContainsString('http://hellowworld.com', $output);
@@ -262,7 +265,7 @@ public function testRoutesIsEmpty()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertStringContainsString('Welcome to CodeIgniter', $output);
@@ -276,7 +279,7 @@ public function testTransfersCorrectHTTPVersion()
         $_SERVER['SERVER_PROTOCOL'] = 'HTTP/2.0';
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         ob_get_clean();
 
         $response = $this->getPrivateProperty($this->codeigniter, 'response');
@@ -291,7 +294,7 @@ public function testIgnoringErrorSuppressedByAt()
 
         ob_start();
         @unlink('inexistent-file');
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertStringContainsString('Welcome to CodeIgniter', $output);
@@ -316,7 +319,7 @@ public function testRunForceSecure()
         $this->assertNull($response->header('Location'));
 
         ob_start();
-        $codeigniter->useSafeOutput(true)->run();
+        $codeigniter->run();
         ob_get_clean();
 
         $this->assertSame('https://example.com/', $response->header('Location')->getValue());
@@ -339,7 +342,7 @@ public function testRunRedirectionWithNamed()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         ob_get_clean();
         $response = $this->getPrivateProperty($this->codeigniter, 'response');
         $this->assertSame('http://example.com/pages/named', $response->header('Location')->getValue());
@@ -362,7 +365,7 @@ public function testRunRedirectionWithURI()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         ob_get_clean();
         $response = $this->getPrivateProperty($this->codeigniter, 'response');
         $this->assertSame('http://example.com/pages/uri', $response->header('Location')->getValue());
@@ -386,7 +389,7 @@ public function testRunRedirectionWithURINotSet()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         ob_get_clean();
         $response = $this->getPrivateProperty($this->codeigniter, 'response');
         $this->assertSame('http://example.com/pages/notset', $response->header('Location')->getValue());
@@ -409,7 +412,7 @@ public function testRunRedirectionWithHTTPCode303()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         ob_get_clean();
 
         $response = $this->getPrivateProperty($this->codeigniter, 'response');
@@ -426,7 +429,7 @@ public function testStoresPreviousURL()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         ob_get_clean();
 
         $this->assertArrayHasKey('_ci_previous_url', $_SESSION);
@@ -450,7 +453,7 @@ public function testNotStoresPreviousURL()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         ob_get_clean();
 
         $this->assertArrayNotHasKey('_ci_previous_url', $_SESSION);
@@ -474,7 +477,7 @@ public function testNotStoresPreviousURLByCheckingContentType()
         Services::injectMock('router', $router);
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         ob_get_clean();
 
         $this->assertArrayNotHasKey('_ci_previous_url', $_SESSION);
@@ -491,7 +494,7 @@ public function testRunDefaultRoute()
         $_SERVER['argc'] = 2;
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertStringContainsString('Welcome to CodeIgniter', $output);
@@ -510,7 +513,7 @@ public function testRunCLIRoute()
         $routes->cli('cli', '\Tests\Support\Controllers\Popcorn::index');
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertStringContainsString('Method Not Allowed', $output);
@@ -534,7 +537,7 @@ public function testSpoofRequestMethodCanUsePUT()
         $routes->put('/', 'Home::index');
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         ob_get_clean();
 
         $this->assertSame('put', Services::request()->getMethod());
@@ -558,7 +561,7 @@ public function testSpoofRequestMethodCannotUseGET()
         $routes->get('/', 'Home::index');
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         ob_get_clean();
 
         $this->assertSame('post', Services::request()->getMethod());
@@ -598,7 +601,7 @@ public function testPageCacheSendSecureHeaders()
 
         // The first response to be cached.
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertStringContainsString('This is a test page', $output);
@@ -608,7 +611,7 @@ public function testPageCacheSendSecureHeaders()
 
         // The second response from the Page cache.
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run();
+        $this->codeigniter->run();
         $output = ob_get_clean();
 
         $this->assertStringContainsString('This is a test page', $output);
@@ -666,7 +669,7 @@ public function testPageCacheWithCacheQueryString($cacheQueryStringValue, int $e
             Services::injectMock('router', $router);
 
             // Cache the page output using default caching function and $cacheConfig with value from the data provider
-            $this->codeigniter->useSafeOutput(true)->run();
+            $this->codeigniter->run();
             $this->codeigniter->cachePage($cacheConfig); // Cache the page using our own $cacheConfig confugration
         }
 
diff --git a/tests/system/RESTful/ResourceControllerTest.php b/tests/system/RESTful/ResourceControllerTest.php
index b65a7ddf38c4..fe1d0ac6f781 100644
--- a/tests/system/RESTful/ResourceControllerTest.php
+++ b/tests/system/RESTful/ResourceControllerTest.php
@@ -71,6 +71,9 @@ private function createCodeigniter(): void
 
         $config            = new App();
         $this->codeigniter = new MockCodeIgniter($config);
+
+        $response = Services::response();
+        $response->pretend();
     }
 
     protected function tearDown(): void
@@ -96,7 +99,7 @@ public function testResourceGet()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $error = json_decode($output)->messages->error;
@@ -118,7 +121,7 @@ public function testResourceGetNew()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $error = json_decode($output)->messages->error;
@@ -141,7 +144,7 @@ public function testResourceGetEdit()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $error = json_decode($output)->messages->error;
@@ -163,7 +166,7 @@ public function testResourceGetOne()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $error = json_decode($output)->messages->error;
@@ -184,7 +187,7 @@ public function testResourcePost()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $error = json_decode($output)->messages->error;
@@ -206,7 +209,7 @@ public function testResourcePatch()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $error = json_decode($output)->messages->error;
@@ -228,7 +231,7 @@ public function testResourcePut()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $error = json_decode($output)->messages->error;
@@ -250,7 +253,7 @@ public function testResourceDelete()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $error = json_decode($output)->messages->error;
diff --git a/tests/system/RESTful/ResourcePresenterTest.php b/tests/system/RESTful/ResourcePresenterTest.php
index c36f6340c861..a430b527a580 100644
--- a/tests/system/RESTful/ResourcePresenterTest.php
+++ b/tests/system/RESTful/ResourcePresenterTest.php
@@ -90,7 +90,7 @@ public function testResourceGet()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $this->assertSame(lang('RESTful.notImplemented', ['index']), $output);
@@ -112,7 +112,7 @@ public function testResourceShow()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $this->assertStringContainsString(lang('RESTful.notImplemented', ['show']), $output);
@@ -133,7 +133,7 @@ public function testResourceNew()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $this->assertStringContainsString(lang('RESTful.notImplemented', ['new']), $output);
@@ -154,7 +154,7 @@ public function testResourceCreate()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $this->assertStringContainsString(lang('RESTful.notImplemented', ['create']), $output);
@@ -176,7 +176,7 @@ public function testResourceRemove()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $this->assertStringContainsString(lang('RESTful.notImplemented', ['remove']), $output);
@@ -198,7 +198,7 @@ public function testResourceDelete()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $this->assertStringContainsString(lang('RESTful.notImplemented', ['delete']), $output);
@@ -221,7 +221,7 @@ public function testResourceEdit()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $this->assertStringContainsString(lang('RESTful.notImplemented', ['edit']), $output);
@@ -243,7 +243,7 @@ public function testResourceUpdate()
         $this->createCodeigniter();
 
         ob_start();
-        $this->codeigniter->useSafeOutput(true)->run($this->routes);
+        $this->codeigniter->run($this->routes);
         $output = ob_get_clean();
 
         $this->assertStringContainsString(lang('RESTful.notImplemented', ['update']), $output);

From 4cff965ffb18aa2d73002fb2c9d1238b6d9c84ef Mon Sep 17 00:00:00 2001
From: kenjis <kenji.uui@gmail.com>
Date: Thu, 22 Sep 2022 15:38:55 +0900
Subject: [PATCH 5/8] docs: add @testTag

See https://github.com/DaveLiddament/php-language-extensions#testtag
---
 system/HTTP/Response.php | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/system/HTTP/Response.php b/system/HTTP/Response.php
index e733b3ee336d..56ccce087e67 100644
--- a/system/HTTP/Response.php
+++ b/system/HTTP/Response.php
@@ -193,6 +193,8 @@ public function __construct($config)
      * should not be relied on outside of internal testing.
      *
      * @return $this
+     *
+     * @testTag only available to test code
      */
     public function pretend(bool $pretend = true)
     {

From 386800afe82990b4e68c193eee5c36e0ff509925 Mon Sep 17 00:00:00 2001
From: kenjis <kenji.uui@gmail.com>
Date: Fri, 23 Sep 2022 08:32:59 +0900
Subject: [PATCH 6/8] docs: fix @return

---
 system/HTTP/ResponseInterface.php | 24 ++++++++++++++----------
 system/HTTP/ResponseTrait.php     |  6 +++---
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/system/HTTP/ResponseInterface.php b/system/HTTP/ResponseInterface.php
index aaf548635a56..f6b00a5044db 100644
--- a/system/HTTP/ResponseInterface.php
+++ b/system/HTTP/ResponseInterface.php
@@ -128,7 +128,7 @@ public function getStatusCode(): int;
      *                       provided status code; if none is provided, will
      *                       default to the IANA name.
      *
-     * @return self
+     * @return $this
      *
      * @throws InvalidArgumentException For invalid status code arguments.
      */
@@ -151,7 +151,7 @@ public function getReason(): string;
     /**
      * Sets the date header
      *
-     * @return ResponseInterface
+     * @return $this
      */
     public function setDate(DateTime $date);
 
@@ -162,6 +162,8 @@ public function setDate(DateTime $date);
      * preferably, an instance of DateTime.
      *
      * @param DateTime|string $date
+     *
+     * @return $this
      */
     public function setLastModified($date);
 
@@ -170,7 +172,7 @@ public function setLastModified($date);
      *
      * @see http://tools.ietf.org/html/rfc5988
      *
-     * @return Response
+     * @return $this
      *
      * @todo Recommend moving to Pager
      */
@@ -180,7 +182,7 @@ public function setLink(PagerInterface $pager);
      * Sets the Content Type header for this response with the mime type
      * and, optionally, the charset.
      *
-     * @return ResponseInterface
+     * @return $this
      */
     public function setContentType(string $mime, string $charset = 'UTF-8');
 
@@ -200,7 +202,7 @@ public function setJSON($body, bool $unencoded = false);
     /**
      * Returns the current body, converted to JSON is it isn't already.
      *
-     * @return mixed|string
+     * @return bool|string|null
      *
      * @throws InvalidArgumentException If the body property is not array.
      */
@@ -218,7 +220,7 @@ public function setXML($body);
     /**
      * Retrieves the current body into XML and returns it.
      *
-     * @return mixed|string
+     * @return bool|string|null
      *
      * @throws InvalidArgumentException If the body property is not array.
      */
@@ -233,6 +235,8 @@ public function getXML();
     /**
      * Sets the appropriate headers to ensure this response
      * is not cached by the browsers.
+     *
+     * @return $this
      */
     public function noCache();
 
@@ -260,7 +264,7 @@ public function noCache();
      *  - proxy-revalidate
      *  - no-transform
      *
-     * @return ResponseInterface
+     * @return $this
      */
     public function setCache(array $options = []);
 
@@ -271,21 +275,21 @@ public function setCache(array $options = []);
     /**
      * Sends the output to the browser.
      *
-     * @return ResponseInterface
+     * @return $this
      */
     public function send();
 
     /**
      * Sends the headers of this HTTP request to the browser.
      *
-     * @return Response
+     * @return $this
      */
     public function sendHeaders();
 
     /**
      * Sends the Body of the message to the browser.
      *
-     * @return Response
+     * @return $this
      */
     public function sendBody();
 
diff --git a/system/HTTP/ResponseTrait.php b/system/HTTP/ResponseTrait.php
index 10a10f817bb4..b58fcdae8e53 100644
--- a/system/HTTP/ResponseTrait.php
+++ b/system/HTTP/ResponseTrait.php
@@ -252,7 +252,7 @@ public function setJSON($body, bool $unencoded = false)
     /**
      * Returns the current body, converted to JSON is it isn't already.
      *
-     * @return mixed|string
+     * @return bool|string|null
      *
      * @throws InvalidArgumentException If the body property is not array.
      */
@@ -284,7 +284,7 @@ public function setXML($body)
     /**
      * Retrieves the current body into XML and returns it.
      *
-     * @return mixed|string
+     * @return bool|string|null
      *
      * @throws InvalidArgumentException If the body property is not array.
      */
@@ -430,7 +430,7 @@ public function setLastModified($date)
     /**
      * Sends the output to the browser.
      *
-     * @return Response
+     * @return $this
      */
     public function send()
     {

From 3dab2dec620aa41532d9bb4c893da5f9512e0193 Mon Sep 17 00:00:00 2001
From: kenjis <kenji.uui@gmail.com>
Date: Fri, 23 Sep 2022 09:29:31 +0900
Subject: [PATCH 7/8] docs: add changelog and upgrade

---
 user_guide_src/source/changelogs/v4.3.0.rst        | 8 ++++++++
 user_guide_src/source/installation/upgrade_430.rst | 5 +++++
 2 files changed, 13 insertions(+)

diff --git a/user_guide_src/source/changelogs/v4.3.0.rst b/user_guide_src/source/changelogs/v4.3.0.rst
index 85bf1f421083..03d3ff8068ff 100644
--- a/user_guide_src/source/changelogs/v4.3.0.rst
+++ b/user_guide_src/source/changelogs/v4.3.0.rst
@@ -46,6 +46,14 @@ Others
 - ``CITestStreamFilter::$buffer = ''`` no longer causes the filter to be registered to listen for streams. Now there
   is a ``CITestStreamFilter::registration()`` method for this. See :ref:`upgrade-430-stream-filter` for details.
 
+.. _v430-interface-changes:
+
+Interface Changes
+=================
+
+- Added missing ``getBody()``, ``hasHeader()`` and ``getHeaderLine()`` method in ``MessageInterface``.
+- Now ``ResponseInterface`` extends ``MessageInterface``.
+
 Method Signature Changes
 ========================
 
diff --git a/user_guide_src/source/installation/upgrade_430.rst b/user_guide_src/source/installation/upgrade_430.rst
index a304001cf896..8e843272d715 100644
--- a/user_guide_src/source/installation/upgrade_430.rst
+++ b/user_guide_src/source/installation/upgrade_430.rst
@@ -117,6 +117,11 @@ need to use::
 
 Or use the trait ``CodeIgniter\Test\StreamFilterTrait``. See :ref:`testing-cli-output`.
 
+Interface Changes
+=================
+
+Some interfaces has been fixed. See :ref:`v430-interface-changes` for details.
+
 Others
 ======
 

From 9fbd5f8b6558cbc571220df5cb3e3c5639de9601 Mon Sep 17 00:00:00 2001
From: kenjis <kenji.uui@gmail.com>
Date: Fri, 23 Sep 2022 09:30:50 +0900
Subject: [PATCH 8/8] docs: fix reference name

We use a dash as a separator, not a underscore.
---
 user_guide_src/source/changelogs/v4.3.0.rst        | 2 +-
 user_guide_src/source/installation/upgrade_430.rst | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/user_guide_src/source/changelogs/v4.3.0.rst b/user_guide_src/source/changelogs/v4.3.0.rst
index 03d3ff8068ff..2740501b625d 100644
--- a/user_guide_src/source/changelogs/v4.3.0.rst
+++ b/user_guide_src/source/changelogs/v4.3.0.rst
@@ -57,7 +57,7 @@ Interface Changes
 Method Signature Changes
 ========================
 
-.. _v430_validation_changes:
+.. _v430-validation-changes:
 
 Validation Changes
 ------------------
diff --git a/user_guide_src/source/installation/upgrade_430.rst b/user_guide_src/source/installation/upgrade_430.rst
index 8e843272d715..5d9aac504cdb 100644
--- a/user_guide_src/source/installation/upgrade_430.rst
+++ b/user_guide_src/source/installation/upgrade_430.rst
@@ -77,7 +77,7 @@ instead of the Validation object.
 Validation Changes
 ==================
 
-- ``ValidationInterface`` has been changed. Implemented classes should likewise add the methods and the parameters so as not to break LSP. See :ref:`v430_validation_changes` for details.
+- ``ValidationInterface`` has been changed. Implemented classes should likewise add the methods and the parameters so as not to break LSP. See :ref:`v430-validation-changes` for details.
 - The return value of  ``Validation::loadRuleGroup()`` has been changed ``null`` to ``[]`` when the ``$group`` is empty. Update the code if you depend on the behavior.
 
 .. _upgrade-430-stream-filter: