Skip to content

Commit

Permalink
Add dirty hook
Browse files Browse the repository at this point in the history
For implementation in the url package we need a way to get informed when
something in the query string was changed, to update the full url.
  • Loading branch information
otsch committed Jun 1, 2022
1 parent c76da07 commit 32870ec
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 4 deletions.
19 changes: 15 additions & 4 deletions src/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ final class Query implements ArrayAccess, Iterator

private const TEMP_SPACE_REPLACEMENT = '<crwlr-space-replacement>';

private ?Query $parent = null;

private bool $isDirty = false;

private ?string $string = null;

/**
Expand All @@ -45,6 +41,12 @@ final class Query implements ArrayAccess, Iterator
*/
private bool $boolToInt = true;

private ?Query $parent = null;

private bool $isDirty = false;

private ?Closure $dirtyHookCallback = null;

/**
* @param string|mixed[] $query
*/
Expand Down Expand Up @@ -396,6 +398,13 @@ public function map(Closure $mappingCallback): self
return $this;
}

public function setDirtyHook(Closure $callback): self
{
$this->dirtyHookCallback = $callback;

return $this;
}

/**
* @param int|string $offset
* @throws Exception
Expand Down Expand Up @@ -719,6 +728,8 @@ private function setDirty(): void
$this->isDirty = true;

$this->parent?->setDirty();

$this->dirtyHookCallback?->call($this);
}

/**
Expand Down
203 changes: 203 additions & 0 deletions tests/DirtyHookTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
<?php

use Crwlr\QueryString\Query;

it('calls the dirty hook when set() was called', function () {
$query = Query::fromArray(['foo' => 'bar']);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->set('baz', 'quz');

expect($hookWasCalled)->toBeTrue();
});

it('calls the dirty hook when appendTo() was called', function () {
$query = Query::fromArray(['foo' => 'bar']);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->appendTo('foo', 'baz');

expect($hookWasCalled)->toBeTrue();
});

it('calls the dirty hook when remove() was called', function () {
$query = Query::fromArray(['foo' => 'bar']);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->remove('foo');

expect($hookWasCalled)->toBeTrue();
});

it('calls the dirty hook when removeValueFrom() was called', function () {
$query = Query::fromArray(['foo' => ['1', '2']]);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->removeValueFrom('foo', '2');

expect($hookWasCalled)->toBeTrue();
});

it('calls the dirty hook when filter() was called', function () {
$query = Query::fromArray(['1', '2', '3', '4', '5']);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->filter(function ($value) {
return (int) $value > 2;
});

expect($hookWasCalled)->toBeTrue();
});

it('calls the dirty hook when map() was called', function () {
$query = Query::fromArray(['1', '2', '3', '4', '5']);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->map(function ($value) {
return (int) $value + 1;
});

expect($hookWasCalled)->toBeTrue();
});

it('calls the dirty hook when boolToString() was called', function () {
$query = Query::fromArray(['foo' => true, 'bar' => false]);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->boolToString();

expect($hookWasCalled)->toBeTrue();
});

it('calls the dirty hook when boolToInt() was called', function () {
$query = Query::fromArray(['foo' => true, 'bar' => false]);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->boolToString();

$query->boolToInt();

expect($hookWasCalled)->toBeTrue();
});

it('calls the dirty hook when spaceCharacterPercentTwenty() was called', function () {
$query = Query::fromArray(['foo' => 'spa ce']);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->spaceCharacterPercentTwenty();

expect($hookWasCalled)->toBeTrue();
});

it('calls the dirty hook when spaceCharacterPlus() was called', function () {
$query = Query::fromArray(['foo' => 'spa ce']);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->spaceCharacterPercentTwenty();

$query->spaceCharacterPlus();

expect($hookWasCalled)->toBeTrue();
});

it('calls the dirty hook when separator() was called', function () {
$query = Query::fromArray(['foo' => '1', 'bar' => '2']);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->separator(';');

expect($hookWasCalled)->toBeTrue();
});

it('calls the dirty hook when something in a child Query instance was changed', function () {
$query = Query::fromArray(['foo' => ['bar' => 'baz']]);

$hookWasCalled = false;

$query->setDirtyHook(function () use (& $hookWasCalled) {
$hookWasCalled = true;
});

expect($hookWasCalled)->toBeFalse();

$query->get('foo')->set('quz', 'test');

expect($hookWasCalled)->toBeTrue();
});

0 comments on commit 32870ec

Please sign in to comment.