Skip to content

Commit 4b66675

Browse files
committed
Add BlockReplacer helper utility
1 parent 002b84e commit 4b66675

File tree

5 files changed

+158
-2
lines changed

5 files changed

+158
-2
lines changed

src/BlockReplacer.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
namespace Recoded\WordPressBlockParser;
4+
5+
use Recoded\WordPressBlockParser\Blocks\AbstractBlock;
6+
use Stringable;
7+
8+
final class BlockReplacer implements Stringable
9+
{
10+
private string $replacedContent;
11+
private int $offsetDifference = 0;
12+
13+
/**
14+
* Create a new BlockReplacer instance.
15+
*
16+
* @param string $content
17+
* @return void
18+
*/
19+
public function __construct(
20+
public readonly string $content,
21+
) {
22+
$this->replacedContent = $content;
23+
}
24+
25+
/**
26+
* Create a new replacer from content string.
27+
*
28+
* @param string $content
29+
* @return self
30+
*/
31+
public static function create(string $content): self
32+
{
33+
return new self($content);
34+
}
35+
36+
/**
37+
* Replace the given block in the content.
38+
*
39+
* @param \Recoded\WordPressBlockParser\Blocks\AbstractBlock $block
40+
* @param string $replacement
41+
* @return $this
42+
*/
43+
public function replace(AbstractBlock $block, string $replacement): self
44+
{
45+
$from = $block->getStart() + $this->offsetDifference;
46+
$to = $block->getEnd() + $this->offsetDifference;
47+
48+
$this->replacedContent = substr($this->replacedContent, 0, $from)
49+
. $replacement
50+
. substr($this->replacedContent, $to);
51+
52+
$this->offsetDifference += strlen($replacement) - ($to - $from);
53+
54+
return $this;
55+
}
56+
57+
/**
58+
* Get the replaced content.
59+
*
60+
* @return string
61+
*/
62+
public function __toString(): string
63+
{
64+
return $this->replacedContent;
65+
}
66+
}

src/Blocks/AbstractBlock.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Recoded\WordPressBlockParser\Blocks;
4+
5+
abstract class AbstractBlock
6+
{
7+
/**
8+
* Get the offset on which the block starts.
9+
*
10+
* @return int
11+
*/
12+
abstract public function getStart(): int;
13+
14+
/**
15+
* Get the offset on which the block ends.
16+
*
17+
* @return int
18+
*/
19+
abstract public function getEnd(): int;
20+
}

src/Blocks/Block.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use Recoded\WordPressBlockParser\Tokens\BlockClosing;
66
use Recoded\WordPressBlockParser\Tokens\BlockOpening;
77

8-
final class Block
8+
final class Block extends AbstractBlock
99
{
1010
/**
1111
* Create new Block instance.
@@ -28,4 +28,24 @@ public function __construct(
2828
) {
2929
//
3030
}
31+
32+
/**
33+
* Get the offset on which the block starts.
34+
*
35+
* @return int
36+
*/
37+
public function getStart(): int
38+
{
39+
return $this->opening->startsAt;
40+
}
41+
42+
/**
43+
* Get the offset on which the block ends.
44+
*
45+
* @return int
46+
*/
47+
public function getEnd(): int
48+
{
49+
return $this->closing->startsAt + $this->closing->length;
50+
}
3151
}

src/Blocks/SelfClosingBlock.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use Recoded\WordPressBlockParser\Tokens\SelfClosingBlock as SelfClosingBlockToken;
66

7-
final class SelfClosingBlock
7+
final class SelfClosingBlock extends AbstractBlock
88
{
99
/**
1010
* Create new SelfClosingBlock instance.
@@ -23,4 +23,24 @@ public function __construct(
2323
) {
2424
//
2525
}
26+
27+
/**
28+
* Get the offset on which the block starts.
29+
*
30+
* @return int
31+
*/
32+
public function getStart(): int
33+
{
34+
return $this->token->startsAt;
35+
}
36+
37+
/**
38+
* Get the offset on which the block ends.
39+
*
40+
* @return int
41+
*/
42+
public function getEnd(): int
43+
{
44+
return $this->token->startsAt + $this->token->length;
45+
}
2646
}

tests/BlockReplacerTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Tests;
4+
5+
use Recoded\WordPressBlockParser\BlockParser;
6+
use Recoded\WordPressBlockParser\BlockReplacer;
7+
8+
final class BlockReplacerTest extends TestCase
9+
{
10+
public function test_it_replaces_blocks(): void
11+
{
12+
$parser = BlockParser::create($content = <<<HTML
13+
<!-- wp:paragraph -->
14+
<!-- wp:paragraph -->
15+
Test
16+
<!-- /wp:paragraph -->
17+
<!-- /wp:paragraph -->
18+
<!-- wp:paragraph /-->
19+
HTML);
20+
21+
$blocks = iterator_to_array($parser);
22+
23+
$replaced = (string) BlockReplacer::create($content)
24+
->replace($blocks[0], 'foo')
25+
->replace($blocks[1], 'bar');
26+
27+
self::assertEquals('foo
28+
bar', $replaced);
29+
}
30+
}

0 commit comments

Comments
 (0)