Skip to content

Commit

Permalink
Allow hooks to be updated when active
Browse files Browse the repository at this point in the history
  • Loading branch information
mvorisek committed Apr 1, 2024
1 parent 5c9ff31 commit b3026a9
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 15 deletions.
38 changes: 34 additions & 4 deletions src/HookTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,18 +304,48 @@ public function hook(string $spot, array $args = [], &$brokenBy = null)
if (isset($this->hooks[$spot])) {
krsort($this->hooks[$spot]); // lower priority is called sooner
$hooksBackup = $this->hooks[$spot];
$priorities = array_keys($hooksBackup);

try {
while ($hooks = array_pop($this->hooks[$spot])) {
foreach ($hooks as $index => [$hookFx, $hookArgs]) {
while (($priority = array_pop($priorities)) !== null) {
$hooks2Backup = $this->hooks[$spot][$priority];
$indexes = array_reverse(array_keys($hooks2Backup));

while (($index = array_pop($indexes)) !== null) {
[$hookFx, $hookArgs] = $this->hooks[$spot][$priority][$index];

$return[$index] = $hookFx($this, ...$args, ...$hookArgs);

if (!isset($this->hooks[$spot][$priority])) {
break;
} elseif ($hooks2Backup !== $this->hooks[$spot][$priority]) {
$hooks2Backup = $this->hooks[$spot][$priority];
$indexes = array_reverse(array_keys($hooks2Backup));
foreach ($indexes as $k => $i) {
if ($i <= $index) {
unset($indexes[$k]);
}
}
}
}

if (!isset($this->hooks[$spot])) {
break;
} elseif ($hooksBackup !== $this->hooks[$spot]) {
krsort($this->hooks[$spot]);
$hooksBackup = $this->hooks[$spot];
$priorities = array_keys($hooksBackup);
foreach ($priorities as $k => $p) {
if ($p <= $priority) {
unset($priorities[$k]);
}
}
}
}
} catch (HookBreaker $e) {
$brokenBy = $e;

return $e->getReturnValue();
} finally {
$this->hooks[$spot] = $hooksBackup;
}
}

Expand Down
66 changes: 55 additions & 11 deletions tests/HookTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ public function testHookException1(): void
public function testOrder(): void
{
$m = new HookMock();
$ind = $m->onHook('spot', static function () {

$m->onHook('spot', static function () {
return 3;
}, [], -1);
$m->onHook('spot', static function () {
Expand Down Expand Up @@ -100,16 +101,16 @@ public function testOrder(): void
$ret = $m->hook('spot');

self::assertSame([
$ind + 2 => 1,
$ind + 1 => 2,
$ind => 3,
$ind + 3 => 4,
$ind + 4 => 5,
$ind + 6 => 6,
$ind + 7 => 7,
$ind + 8 => 8,
$ind + 9 => 9,
$ind + 5 => 10,
2 => 1,
1 => 2,
0 => 3,
3 => 4,
4 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
5 => 10,
], $ret);
}

Expand All @@ -134,6 +135,49 @@ public function testMulti(): void
self::assertSame([9, 6], $res2);
}

public function testUpdateWhenActive(): void
{
$m = new HookMock();

$addHooksFx = static function (int $priority, string $res) use ($m) {
$m->onHook('spot', static function () use ($m, $priority, $res) {
$m->onHook('spot', static function () use ($res) {
return $res . 'a';
}, [], $priority);
$m->onHook('spot', static function () use ($m, $priority, $res) {
$m->removeHook('spot', $priority);

return $res . 'b';
}, [], $priority);

return $res;
}, [], $priority);
};

$addHooksFx(-2, '1');
$addHooksFx(-1, '2');
$addHooksFx(-1, '3');
$addHooksFx(0, '4');
$addHooksFx(1, '5');
$addHooksFx(1, '6');

$ret = $m->hook('spot');

self::assertSame([
0 => '1',
7 => '1b',
2 => '3',
9 => '3b',
3 => '4',
10 => '4a',
11 => '4b',
4 => '5',
5 => '6',
12 => '5a',
13 => '5b',
], $ret);
}

public function testArgs(): void
{
$obj = new HookMock();
Expand Down

0 comments on commit b3026a9

Please sign in to comment.