Skip to content

Commit 7965d82

Browse files
committed
Add new if helper to make it easier to create if else collections
1 parent 91b3fba commit 7965d82

File tree

6 files changed

+268
-0
lines changed

6 files changed

+268
-0
lines changed

src/CodeHelper/IfHelper/IfCode.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Stefna\PhpCodeBuilder\CodeHelper\IfHelper;
4+
5+
use Stefna\PhpCodeBuilder\CodeHelper\CodeInterface;
6+
7+
final class IfCode implements CodeInterface
8+
{
9+
/**
10+
* @param array<int, mixed> $code
11+
*/
12+
public function __construct(
13+
private string $if,
14+
private array $code,
15+
public IfType $type = IfType::If,
16+
) {}
17+
18+
public function getSourceArray(int $currentIndent = 0): array
19+
{
20+
$ifStmt = $this->type->toStmt();
21+
if ($this->type !== IfType::Else) {
22+
$ifStmt .= sprintf(' (%s)', $this->if);
23+
}
24+
$ifStmt .= ' {';
25+
return [
26+
$ifStmt,
27+
$this->code,
28+
'}',
29+
];
30+
}
31+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Stefna\PhpCodeBuilder\CodeHelper\IfHelper;
4+
5+
use Stefna\PhpCodeBuilder\CodeHelper\CodeInterface;
6+
7+
/**
8+
* @implements \ArrayAccess<int, IfCode>
9+
*/
10+
final class IfCollection implements CodeInterface, \ArrayAccess
11+
{
12+
/** @var list<IfCode> */
13+
private array $checks = [];
14+
15+
private ?IfCode $else = null;
16+
17+
public function getSourceArray(): array
18+
{
19+
$result = [];
20+
foreach ($this->checks as $index => $check) {
21+
$check->type = $index === 0 ? IfType::If : IfType::ElseIf;
22+
$result[] = $check->getSourceArray();
23+
}
24+
if ($this->else) {
25+
$result[] = $this->else->getSourceArray();
26+
}
27+
28+
return array_merge(...$result);
29+
}
30+
31+
/**
32+
* @param array<int, mixed> $code
33+
*/
34+
public function addElse(array $code): void
35+
{
36+
$this->else = new IfCode(
37+
'',
38+
$code,
39+
IfType::Else,
40+
);
41+
}
42+
43+
public function offsetExists(mixed $offset): bool
44+
{
45+
return true;
46+
}
47+
48+
public function offsetGet(mixed $offset): mixed
49+
{
50+
return null;
51+
}
52+
53+
public function offsetSet(mixed $offset, mixed $value): void
54+
{
55+
if (!$value instanceof IfCode) {
56+
throw new \ValueError('Value must be instance of IfCode, got ' . get_debug_type($value));
57+
}
58+
$this->checks[] = $value;
59+
}
60+
61+
public function offsetUnset(mixed $offset): void
62+
{
63+
}
64+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Stefna\PhpCodeBuilder\CodeHelper\IfHelper;
4+
5+
use Stefna\PhpCodeBuilder\CodeHelper\VariableReference;
6+
use Stefna\PhpCodeBuilder\ValueObject\Identifier;
7+
8+
final class IfFactory
9+
{
10+
/**
11+
* @param array<int, mixed> $code
12+
* @param Identifier|class-string $identifier
13+
*/
14+
public static function instanceOf(VariableReference $var, Identifier|string $identifier, array $code): IfCode
15+
{
16+
$identifier = Identifier::fromUnknown($identifier);
17+
return new IfCode(
18+
$var->toString() . ' instanceof ' . $identifier->getName(),
19+
$code
20+
);
21+
}
22+
23+
/**
24+
* @param array<int, mixed> $code
25+
*/
26+
public static function nullCheck(VariableReference $var, array $code): IfCode
27+
{
28+
return new IfCode(
29+
$var->toString() . ' === null',
30+
$code
31+
);
32+
}
33+
34+
/**
35+
* @param array<int, mixed> $code
36+
*/
37+
public static function methodExist(
38+
VariableReference $var,
39+
string $method,
40+
array $code,
41+
): IfCode {
42+
return new IfCode(
43+
sprintf(
44+
'is_object(%1$s) && method_exists(%1$s, \'%2$s\')',
45+
$var->toString(),
46+
$method,
47+
),
48+
$code,
49+
);
50+
}
51+
}

src/CodeHelper/IfHelper/IfType.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Stefna\PhpCodeBuilder\CodeHelper\IfHelper;
4+
5+
enum IfType
6+
{
7+
case If;
8+
case ElseIf;
9+
case Else;
10+
11+
public function toStmt(): string
12+
{
13+
return match ($this) {
14+
self::If => 'if',
15+
self::ElseIf => 'elseif',
16+
self::Else => 'else',
17+
};
18+
}
19+
}

tests/CodeHelper/ForeachCodeTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ function (VariableReference $key, VariableReference $value) {
3737
'}',
3838
], $loop->getSourceArray());
3939
}
40+
4041
public function testLoopThatReturnCodeInterface(): void
4142
{
4243
$loop = new ForeachCode(
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Stefna\PhpCodeBuilder\Tests\CodeHelper;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Stefna\PhpCodeBuilder\CodeHelper\ForeachCode;
7+
use Stefna\PhpCodeBuilder\CodeHelper\IfHelper\IfCollection;
8+
use Stefna\PhpCodeBuilder\CodeHelper\IfHelper\IfFactory;
9+
use Stefna\PhpCodeBuilder\CodeHelper\ReturnCode;
10+
use Stefna\PhpCodeBuilder\CodeHelper\VariableReference;
11+
use Stefna\PhpCodeBuilder\FlattenSource;
12+
use Stefna\PhpCodeBuilder\ValueObject\Identifier;
13+
14+
final class IfCollectionTest extends TestCase
15+
{
16+
public function testIfElseIf(): void
17+
{
18+
$collection = new IfCollection();
19+
$var = new VariableReference('test');
20+
$collection[] = IfFactory::instanceOf(
21+
$var,
22+
Identifier::fromString(WriteableServerConfigurationInterface::class),
23+
[
24+
new ReturnCode($var),
25+
]
26+
);
27+
$collection[] = IfFactory::nullCheck($var, [
28+
new ReturnCode($var),
29+
]);
30+
31+
$this->assertEquals(
32+
'if ($test instanceof WriteableServerConfigurationInterface) {
33+
return $test;
34+
}
35+
elseif ($test === null) {
36+
return $test;
37+
}
38+
',
39+
FlattenSource::source($collection->getSourceArray()),
40+
);
41+
}
42+
43+
public function testElse(): void
44+
{
45+
$collection = new IfCollection();
46+
$var = new VariableReference('test');
47+
$collection[] = IfFactory::methodExist($var, 'toString', [
48+
new ReturnCode($var),
49+
]);
50+
$collection[] = IfFactory::nullCheck($var, [
51+
new ReturnCode($var),
52+
]);
53+
54+
$collection->addElse([
55+
new ReturnCode($var),
56+
]);
57+
58+
$this->assertEquals(
59+
'if (is_object($test) && method_exists($test, \'toString\')) {
60+
return $test;
61+
}
62+
elseif ($test === null) {
63+
return $test;
64+
}
65+
else {
66+
return $test;
67+
}
68+
',
69+
FlattenSource::source($collection->getSourceArray()),
70+
);
71+
}
72+
73+
public function testLoopWithIfCollection(): void
74+
{
75+
$loop = new ForeachCode(new VariableReference('test'), function (VariableReference $key, VariableReference $value) {
76+
$collection = new IfCollection();
77+
$collection[] = IfFactory::instanceOf($value, RequestBody::class, [
78+
'$return[] = ' . $value->toString() . ';',
79+
]);
80+
$collection[] = IfFactory::methodExist($value, 'toString', [
81+
'$return[] = ' . $value->toString() . '->toString();',
82+
]);
83+
84+
return [
85+
$collection,
86+
];
87+
});
88+
89+
$this->assertSame(
90+
'foreach ($test as $key => $value) {
91+
if ($value instanceof RequestBody) {
92+
$return[] = $value;
93+
}
94+
elseif (is_object($value) && method_exists($value, \'toString\')) {
95+
$return[] = $value->toString();
96+
}
97+
}
98+
',
99+
FlattenSource::source($loop->getSourceArray())
100+
);
101+
}
102+
}

0 commit comments

Comments
 (0)