Skip to content

Commit 32870ec

Browse files
committed
Add dirty hook
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.
1 parent c76da07 commit 32870ec

File tree

2 files changed

+218
-4
lines changed

2 files changed

+218
-4
lines changed

src/Query.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ final class Query implements ArrayAccess, Iterator
2525

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

28-
private ?Query $parent = null;
29-
30-
private bool $isDirty = false;
31-
3228
private ?string $string = null;
3329

3430
/**
@@ -45,6 +41,12 @@ final class Query implements ArrayAccess, Iterator
4541
*/
4642
private bool $boolToInt = true;
4743

44+
private ?Query $parent = null;
45+
46+
private bool $isDirty = false;
47+
48+
private ?Closure $dirtyHookCallback = null;
49+
4850
/**
4951
* @param string|mixed[] $query
5052
*/
@@ -396,6 +398,13 @@ public function map(Closure $mappingCallback): self
396398
return $this;
397399
}
398400

401+
public function setDirtyHook(Closure $callback): self
402+
{
403+
$this->dirtyHookCallback = $callback;
404+
405+
return $this;
406+
}
407+
399408
/**
400409
* @param int|string $offset
401410
* @throws Exception
@@ -719,6 +728,8 @@ private function setDirty(): void
719728
$this->isDirty = true;
720729

721730
$this->parent?->setDirty();
731+
732+
$this->dirtyHookCallback?->call($this);
722733
}
723734

724735
/**

tests/DirtyHookTest.php

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
<?php
2+
3+
use Crwlr\QueryString\Query;
4+
5+
it('calls the dirty hook when set() was called', function () {
6+
$query = Query::fromArray(['foo' => 'bar']);
7+
8+
$hookWasCalled = false;
9+
10+
$query->setDirtyHook(function () use (& $hookWasCalled) {
11+
$hookWasCalled = true;
12+
});
13+
14+
expect($hookWasCalled)->toBeFalse();
15+
16+
$query->set('baz', 'quz');
17+
18+
expect($hookWasCalled)->toBeTrue();
19+
});
20+
21+
it('calls the dirty hook when appendTo() was called', function () {
22+
$query = Query::fromArray(['foo' => 'bar']);
23+
24+
$hookWasCalled = false;
25+
26+
$query->setDirtyHook(function () use (& $hookWasCalled) {
27+
$hookWasCalled = true;
28+
});
29+
30+
expect($hookWasCalled)->toBeFalse();
31+
32+
$query->appendTo('foo', 'baz');
33+
34+
expect($hookWasCalled)->toBeTrue();
35+
});
36+
37+
it('calls the dirty hook when remove() was called', function () {
38+
$query = Query::fromArray(['foo' => 'bar']);
39+
40+
$hookWasCalled = false;
41+
42+
$query->setDirtyHook(function () use (& $hookWasCalled) {
43+
$hookWasCalled = true;
44+
});
45+
46+
expect($hookWasCalled)->toBeFalse();
47+
48+
$query->remove('foo');
49+
50+
expect($hookWasCalled)->toBeTrue();
51+
});
52+
53+
it('calls the dirty hook when removeValueFrom() was called', function () {
54+
$query = Query::fromArray(['foo' => ['1', '2']]);
55+
56+
$hookWasCalled = false;
57+
58+
$query->setDirtyHook(function () use (& $hookWasCalled) {
59+
$hookWasCalled = true;
60+
});
61+
62+
expect($hookWasCalled)->toBeFalse();
63+
64+
$query->removeValueFrom('foo', '2');
65+
66+
expect($hookWasCalled)->toBeTrue();
67+
});
68+
69+
it('calls the dirty hook when filter() was called', function () {
70+
$query = Query::fromArray(['1', '2', '3', '4', '5']);
71+
72+
$hookWasCalled = false;
73+
74+
$query->setDirtyHook(function () use (& $hookWasCalled) {
75+
$hookWasCalled = true;
76+
});
77+
78+
expect($hookWasCalled)->toBeFalse();
79+
80+
$query->filter(function ($value) {
81+
return (int) $value > 2;
82+
});
83+
84+
expect($hookWasCalled)->toBeTrue();
85+
});
86+
87+
it('calls the dirty hook when map() was called', function () {
88+
$query = Query::fromArray(['1', '2', '3', '4', '5']);
89+
90+
$hookWasCalled = false;
91+
92+
$query->setDirtyHook(function () use (& $hookWasCalled) {
93+
$hookWasCalled = true;
94+
});
95+
96+
expect($hookWasCalled)->toBeFalse();
97+
98+
$query->map(function ($value) {
99+
return (int) $value + 1;
100+
});
101+
102+
expect($hookWasCalled)->toBeTrue();
103+
});
104+
105+
it('calls the dirty hook when boolToString() was called', function () {
106+
$query = Query::fromArray(['foo' => true, 'bar' => false]);
107+
108+
$hookWasCalled = false;
109+
110+
$query->setDirtyHook(function () use (& $hookWasCalled) {
111+
$hookWasCalled = true;
112+
});
113+
114+
expect($hookWasCalled)->toBeFalse();
115+
116+
$query->boolToString();
117+
118+
expect($hookWasCalled)->toBeTrue();
119+
});
120+
121+
it('calls the dirty hook when boolToInt() was called', function () {
122+
$query = Query::fromArray(['foo' => true, 'bar' => false]);
123+
124+
$hookWasCalled = false;
125+
126+
$query->setDirtyHook(function () use (& $hookWasCalled) {
127+
$hookWasCalled = true;
128+
});
129+
130+
expect($hookWasCalled)->toBeFalse();
131+
132+
$query->boolToString();
133+
134+
$query->boolToInt();
135+
136+
expect($hookWasCalled)->toBeTrue();
137+
});
138+
139+
it('calls the dirty hook when spaceCharacterPercentTwenty() was called', function () {
140+
$query = Query::fromArray(['foo' => 'spa ce']);
141+
142+
$hookWasCalled = false;
143+
144+
$query->setDirtyHook(function () use (& $hookWasCalled) {
145+
$hookWasCalled = true;
146+
});
147+
148+
expect($hookWasCalled)->toBeFalse();
149+
150+
$query->spaceCharacterPercentTwenty();
151+
152+
expect($hookWasCalled)->toBeTrue();
153+
});
154+
155+
it('calls the dirty hook when spaceCharacterPlus() was called', function () {
156+
$query = Query::fromArray(['foo' => 'spa ce']);
157+
158+
$hookWasCalled = false;
159+
160+
$query->setDirtyHook(function () use (& $hookWasCalled) {
161+
$hookWasCalled = true;
162+
});
163+
164+
expect($hookWasCalled)->toBeFalse();
165+
166+
$query->spaceCharacterPercentTwenty();
167+
168+
$query->spaceCharacterPlus();
169+
170+
expect($hookWasCalled)->toBeTrue();
171+
});
172+
173+
it('calls the dirty hook when separator() was called', function () {
174+
$query = Query::fromArray(['foo' => '1', 'bar' => '2']);
175+
176+
$hookWasCalled = false;
177+
178+
$query->setDirtyHook(function () use (& $hookWasCalled) {
179+
$hookWasCalled = true;
180+
});
181+
182+
expect($hookWasCalled)->toBeFalse();
183+
184+
$query->separator(';');
185+
186+
expect($hookWasCalled)->toBeTrue();
187+
});
188+
189+
it('calls the dirty hook when something in a child Query instance was changed', function () {
190+
$query = Query::fromArray(['foo' => ['bar' => 'baz']]);
191+
192+
$hookWasCalled = false;
193+
194+
$query->setDirtyHook(function () use (& $hookWasCalled) {
195+
$hookWasCalled = true;
196+
});
197+
198+
expect($hookWasCalled)->toBeFalse();
199+
200+
$query->get('foo')->set('quz', 'test');
201+
202+
expect($hookWasCalled)->toBeTrue();
203+
});

0 commit comments

Comments
 (0)