Skip to content

Commit

Permalink
feat: Add option to disable previous URL storage (#82)
Browse files Browse the repository at this point in the history
* fix: Disable save previous URL

* docs: Update configuration.md

* feat: Add in config parameter `storePreviousURL`
  • Loading branch information
neznaika0 authored Nov 6, 2024
1 parent 463a474 commit 221fc70
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 0 deletions.
10 changes: 10 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,13 @@ Since these decorators are used automatically in the `development` mode (or to b
We can add the defined string as an `id` or `class` to the html tag.

In the `production` environment these decorators are ignored by design. So this is useful only for the `development` mode.

### $storePreviousURL

Specifies whether the HTMX request URL should be stored in the session, for use with the `previous_url()` helper function.
For more information, see the [user guide](https://codeigniter.com/user_guide/helpers/url_helper.html#previous_url).

Basically, if you use HTMX extensively, including for navigating your site, you will probably want to leave it as `true`,
and in cases where storing the request is not desirable, even if it uses HTMX, you can use custom header, to indicate the
AJAX call or [ajax-header](https://github.com/bigskysoftware/htmx-extensions/blob/main/src/ajax-header/README.md) extension,
which will add the necessary headers automatically. URLs from AJAX requests are always excluded from session storage.
79 changes: 79 additions & 0 deletions src/CodeIgniter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

namespace Michalsn\CodeIgniterHtmx;

use CodeIgniter\CodeIgniter as BaseCodeIgniter;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\URI;
use Michalsn\CodeIgniterHtmx\HTTP\IncomingRequest;

/**
* @property CLIRequest|IncomingRequest|null $request
*/
class CodeIgniter extends BaseCodeIgniter
{
/**
* Web access?
*/
private function isWeb(): bool
{
return $this->context === 'web';
}

/**
* If we have a session object to use, store the current URI
* as the previous URI. This is called just prior to sending the
* response to the client, and will make it available next request.
*
* This helps provider safer, more reliable previous_url() detection.
*
* @param string|URI $uri
*
* @return void
*/
public function storePreviousURL($uri)
{
// Ignore CLI requests
if (! $this->isWeb()) {
return;
}

// Ignore AJAX requests
if (method_exists($this->request, 'isAJAX') && $this->request->isAJAX()) {
return;
}

// Ignore HTMX requests
if (config('Htmx')->storePreviousURL === false
&& method_exists($this->request, 'isHTMX') && $this->request->isHTMX()) {
return;
}

// Ignore unroutable responses
if ($this->response instanceof DownloadResponse || $this->response instanceof RedirectResponse) {
return;
}

// Ignore non-HTML responses
if (! str_contains($this->response->getHeaderLine('Content-Type'), 'text/html')) {
return;
}

// This is mainly needed during testing...
if (is_string($uri)) {
$uri = service('uri', $uri, false);
}

if (isset($_SESSION)) {
session()->set('_ci_previous_url', URI::createURIString(
$uri->getScheme(),
$uri->getAuthority(),
$uri->getPath(),
$uri->getQuery(),
$uri->getFragment()
));
}
}
}
5 changes: 5 additions & 0 deletions src/Config/Htmx.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ class Htmx extends BaseConfig
* when they are enabled.
*/
public string $skipViewDecoratorsString = 'htmxSkipViewDecorators';

/**
* Enable / disable storing previous URLs for HTMX requests.
*/
public bool $storePreviousURL = true;
}
17 changes: 17 additions & 0 deletions src/Config/Services.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Config\Services as AppServices;
use Config\Toolbar as ToolbarConfig;
use Config\View as ViewConfig;
use Michalsn\CodeIgniterHtmx\CodeIgniter;
use Michalsn\CodeIgniterHtmx\Debug\Toolbar;
use Michalsn\CodeIgniterHtmx\HTTP\IncomingRequest;
use Michalsn\CodeIgniterHtmx\HTTP\RedirectResponse;
Expand All @@ -19,6 +20,22 @@

class Services extends BaseService
{
/**
* CodeIgniter, the core of the framework.
*
* @return CodeIgniter
*/
public static function codeigniter(?App $config = null, bool $getShared = true)
{
if ($getShared) {
return static::getSharedInstance('codeigniter', $config);
}

$config ??= config(App::class);

return new CodeIgniter($config);
}

/**
* The Renderer class is the class that actually displays a file to the user.
* The default View class within CodeIgniter is intentionally simple, but this
Expand Down
65 changes: 65 additions & 0 deletions tests/CodeIgniterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

namespace Tests;

use CodeIgniter\Test\CIUnitTestCase;

/**
* @internal
*/
final class CodeIgniterTest extends CIUnitTestCase
{
protected function setUp(): void
{
parent::setUp();

$this->resetServices();
}

protected function tearDown(): void
{
parent::tearDown();

$this->resetServices();
}

public function testStorePreviousURLIsHTMX(): void
{
$_SESSION['_ci_previous_url'] = 'https://example.com/index.php/?previous=original';

config('Htmx')->storePreviousURL = true;

service('uri')->setPath('/')->setQuery('previous=saved_from_htmx');
service('request')->appendHeader('HX-Request', 'true');

ob_start();
service('codeigniter', null, false)->setContext('web')->run();
ob_get_clean();

$this->assertTrue(service('request')->isHTMX());
$this->assertArrayHasKey('_ci_previous_url', $_SESSION);
$this->assertSame('https://example.com/index.php/?previous=saved_from_htmx', $_SESSION['_ci_previous_url']);
}

public function testDontStorePreviousURLIsHTMX(): void
{
$_SESSION['_ci_previous_url'] = 'https://example.com/index.php/?previous=original';

service('uri')->setPath('/')->setQuery('previous=original');

config('Htmx')->storePreviousURL = false;

service('uri')->setPath('/')->setQuery('previous=not_saved_from_htmx');
service('request')->appendHeader('HX-Request', 'true');

ob_start();
service('codeigniter', null, false)->setContext('web')->run();
ob_get_clean();

$this->assertTrue(service('request')->isHTMX());
$this->assertArrayHasKey('_ci_previous_url', $_SESSION);
$this->assertSame('https://example.com/index.php/?previous=original', $_SESSION['_ci_previous_url']);
}
}

0 comments on commit 221fc70

Please sign in to comment.