Repository: codeigniter4/CodeIgniter4 (PHP)

Issue:
Bug: TypeError in form_open('') function
### PHP Version

8.2

### CodeIgniter4 Version

4.5.0

### CodeIgniter4 Installation Method

Composer (as dependency to an existing project)

### Which operating systems have you tested for this bug?

Windows

### Which server did you use?

cli

### Database

MariaDB 10.4

### What happened?

When CSRF Filter is On.
I encountered a TypeError when using the form_open(''). 
The error message is as follows:

```
TypeError
str_contains(): Argument #1 ($haystack) must be of type string, CodeIgniter\HTTP\SiteURI given
SYSTEMPATH\Helpers\form_helper.php at line 65

58         }
59 
60         $form = '<form action="' . $action . '"' . $attributes . ">\n";
61 
62         // Add CSRF field if enabled, but leave it out for GET requests and requests to external websites
63         $before = service('filters')->getFilters()['before'];
64 
65         if ((in_array('csrf', $before, true) || array_key_exists('csrf', $before)) && str_contains($action, base_url()) && ! stripos($form, 'method="get"')) {
66             $form .= csrf_field($csrfId ?? null);
67         }
68 
69         foreach ($hidden as $name => $value) {
70             $form .= form_hidden($name, $value);
71         }
72 
```

#### Debug

```vendor\codeigniter4\framework\system\Helpers\form_helper.php
// vendor\codeigniter4\framework\system\Helpers\form_helper.php line 65

var_dump(in_array('csrf', $before, true));       // true
var_dump(array_key_exists('csrf', $before));  // false
var_dump(str_contains($action, base_url()));  // error

if ((in_array('csrf', $before, true) || array_key_exists('csrf', $before)) && str_contains($action, base_url()) && !stripos($form, 'method="get"')) {
  $form .= csrf_field($csrfId ?? null);
}
```

### Steps to Reproduce

1. Upgrade CodeIgniter to 4.5.0 from 4.4.7.
2. Use the form_open('') function in View.

### Expected Output

`<form action="current_url" method="post">`

### Anything else?

This issue did not occur when using CodeIgniter version 4.4.7.
Any help on this issue would be greatly appreciated.


Discussion:
I could not reproduce.
Cannot reproduce.
@datamweb @kenjis 

I was able to confirm the reproducibility. 
An error occurs when using CSRF filter.

```app\Config\Filters.php
// app\Config\Filters.php line 70
    public array $globals = [
        'before' => [
            // 'honeypot',
            'csrf',
            // 'invalidchars',
        ],
        'after' => [
            'toolbar',
            // 'honeypot',
            // 'secureheaders',
        ],
    ];
```

Debug

```vendor\codeigniter4\framework\system\Helpers\form_helper.php
// vendor\codeigniter4\framework\system\Helpers\form_helper.php line 65

var_dump(in_array('csrf', $before, true));       // true
var_dump(array_key_exists('csrf', $before));  // false
var_dump(str_contains($action, base_url()));  // error

if ((in_array('csrf', $before, true) || array_key_exists('csrf', $before)) && str_contains($action, base_url()) && !stripos($form, 'method="get"')) {
  $form .= csrf_field($csrfId ?? null);
}
```
It works when change it to

```
str_contains((string)$action, base_url())
```
Check #8736

Resolved!
thank you.
No, not yet merged.
This issue will be closed automatically when merged.



Patch:
diff --git a/system/Helpers/form_helper.php b/system/Helpers/form_helper.php
index 1e3ea4a9152a..2e5b9f7ca576 100644
--- a/system/Helpers/form_helper.php
+++ b/system/Helpers/form_helper.php
@@ -31,7 +31,7 @@ function form_open(string $action = '', $attributes = [], array $hidden = []): s
     {
         // If no action is provided then set to the current url
         if ($action === '') {
-            $action = current_url(true);
+            $action = (string) current_url(true);
         } // If an action is not a full URL then turn it into one
         elseif (! str_contains($action, '://')) {
             // If an action has {locale}


Test patch:
diff --git a/tests/system/Helpers/FormHelperTest.php b/tests/system/Helpers/FormHelperTest.php
index 2ee32da768fc..cfb58c338932 100644
--- a/tests/system/Helpers/FormHelperTest.php
+++ b/tests/system/Helpers/FormHelperTest.php
@@ -101,21 +101,33 @@ public function testFormOpenWithoutAction(): void
     {
         $this->setRequest();
 
-        $before = (new Filters())->globals['before'];
-        if (in_array('csrf', $before, true) || array_key_exists('csrf', $before)) {
-            $Value    = csrf_hash();
-            $Name     = csrf_token();
-            $expected = <<<EOH
-                <form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8">
-                <input type="hidden" name="{$Name}" value="{$Value}" style="display:none;">
+        $expected = <<<'EOH'
+            <form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8">
 
-                EOH;
-        } else {
-            $expected = <<<'EOH'
-                <form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8">
+            EOH;
+        $attributes = [
+            'name'   => 'form',
+            'id'     => 'form',
+            'method' => 'POST',
+        ];
+        $this->assertSame($expected, form_open('', $attributes));
+    }
 
-                EOH;
-        }
+    public function testFormOpenWithoutActionWithCSRF(): void
+    {
+        $this->setRequest();
+
+        // Sets csrf filter.
+        $filters                      = config(Filters::class);
+        $filters->globals['before'][] = 'csrf';
+        service('filters')->initialize();
+
+        $Value    = csrf_hash();
+        $Name     = csrf_token();
+        $expected = <<<EOH
+            <form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8">
+            <input type="hidden" name="{$Name}" value="{$Value}">
+            EOH;
         $attributes = [
             'name'   => 'form',
             'id'     => 'form',