Skip to content

Commit e2ceee9

Browse files
Merge pull request #10 from FranklinEkemezie/dev
From Termux Dev Env - View functionality update
2 parents 21cc73c + fe7cb6f commit e2ceee9

File tree

7 files changed

+175
-14
lines changed

7 files changed

+175
-14
lines changed

app/Views/View.php

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class View
2222
*/
2323
public function __construct(string $viewName)
2424
{
25+
$viewFile = ("$defaultDir/" ?? "/app/views/") . static::DEFAULT_DIR . "/$viewName.view.php";
2526
try { $defaultViewDir = Config::get('DEFAULT_VIEW_DIR'); }
2627
catch (ConfigNotFoundException) {
2728
throw new ViewException("Default view directory not found in app configuration");
@@ -38,19 +39,77 @@ public function __construct(string $viewName)
3839
$this->viewFile = $viewFile;
3940
}
4041

42+
protected static function parseVariables(string $template, array $props): string
43+
{
44+
45+
// Matches
46+
$abc = "[a-zA-Z]";
47+
$abc_ = "[a-zA-Z_]";
48+
$abc123_ = "[a-zA-Z0-9_]";
49+
$varName = "({$abc}{$abc123_}+)";
50+
51+
$regex = "/\{\{ *$varName(\.$varName)? *\}\}/";
52+
$replace_callback = function (array $match) use ($props) {
53+
if (count($match) === 4) {
54+
[ , $propName, , $propProperty] = $match;
55+
$value = $props[$propName][$propProperty] ?? null;
56+
} else {
57+
[ , $propName] = $match;
58+
$value = $props[$propName] ?? null;
59+
}
60+
61+
if ($value === null && false) {
62+
throw new ViewException("Undefined prop: {$match[1]}");
63+
}
64+
65+
return $value;
66+
return "<?php echo '$value'; ?>";
67+
};
68+
69+
return preg_replace_callback($regex, $replace_callback, $template);
70+
}
71+
72+
protected static function parseForLoops(string $template, array $props): string
73+
{
74+
75+
// Matches
76+
$abc = "[a-zA-Z]";
77+
$abc_ = "[a-zA-Z_]";
78+
$abc123_ = "[a-zA-Z0-9_]";
79+
$varName = "({$abc}{$abc123_}*)";
80+
81+
$regex = "/@for *\(($varName:)? $varName of $varName*\) \{.+\}/";
82+
$regex = "/@for *\(($varName\:)?/";
83+
$replace_callback = function (array $match) use ($props) {
84+
var_dump($match);
85+
if (count($match) === 4) {
86+
[ , $propName, , $propProperty] = $match;
87+
$value = $props[$propName][$propProperty] ?? null ;
88+
} else {
89+
[ , $propName] = $match;
90+
$value = $props[$propName] ?? null;
91+
}
92+
93+
if ($value === null && false) {
94+
throw new ViewException("Undefined prop: {$match[1]}");
95+
}
96+
97+
return $value;
98+
return "<?php echo '$value'; ?>";
99+
};
100+
101+
return preg_replace_callback($regex, $replace_callback, $template);
102+
103+
}
104+
41105
public function render(array $props=[]): string
42106
{
43107
// Get the content of the file
44108
$view = file_get_contents($this->viewFile);
45109

46110
// Extract props
47-
$view = preg_replace_callback(
48-
"/\{ *([a-zA-Z_][a-zA-Z0-9_]+) *\}/",
49-
fn(array $match) => $props[$match[1]] ?? throw new ViewException(
50-
"Undefined prop: {$match[1]}"
51-
),
52-
$view
53-
);
111+
$view = static::parseForLoops($view, $props);
112+
// $view = static::parseVariables($view, $props);
54113

55114
return $view;
56115
}

tests/Unit/Views/ViewTest.php

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,60 @@ class ViewTest extends BaseTestCase
1313
{
1414

1515
#[Test]
16-
public function it_gets_view(): void
16+
public function it_parses_variable(): void
1717
{
18+
$address = [
19+
'city' => "Diao City",
20+
'zip' => "456123"
21+
];
22+
$props = [
23+
'name' => "John",
24+
'email' => "john@doe.com",
25+
'user' => [
26+
'id' => "23abc"
27+
],
28+
'address' => $address
29+
];
30+
31+
$viewTestDir = TESTS_DIR . "/views";
32+
$view = new View('variables', $viewTestDir);
33+
$expectedView = new View('variables_expected', $viewTestDir);
34+
35+
$this->assertSame(
36+
$expectedView->render(),
37+
$view->render($props)
38+
);
39+
40+
}
41+
42+
#[Test]
43+
public function it_parses_for_loops(): void
44+
{
45+
$address = [
46+
'city' => "Diao City",
47+
'zip' => "456123"
48+
];
1849
$props = [
19-
"name" => "John",
20-
"email" => "john@doe.com"
50+
'name' => "John",
51+
'email' => "john@doe.com",
52+
'user' => [
53+
'id' => "23abc"
54+
],
55+
'address' => $address
2156
];
2257

23-
$view = new View('dashboard', TESTS_DIR . "/views/");
58+
$viewTestDir = TESTS_DIR . "/views";
59+
$view = new View('loop', $viewTestDir);
60+
$expectedView = new View('loop_', $viewTestDir);
2461

25-
$expected = "Welcome, John (john@doe.com)!";
2662
$this->assertSame(
27-
$expected,
63+
$expectedView->render(),
2864
$view->render($props)
2965
);
3066

3167
}
3268

69+
70+
3371
}
3472

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,15 @@
1-
Welcome, { name } ({ email })!
1+
Welcome, {{ name }}!
2+
Email: {{ email }}
3+
ID: USER_{{ user.id }}
4+
5+
@{
6+
for(invoice of invoices) {
7+
<p>Invoice ID: {{ invoice.id }}</p>
8+
}
9+
}}
10+
11+
@{
12+
for(key: value of bio_info) {
13+
{{ key }}: {{
14+
}
15+
}}

tests/views/pages/loop.view.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
@for(index: invoice of invoices) {
2+
Invoice No: {{ index }}
3+
Invoice ID: {{ invoice.id }}
4+
Amount: {{ invoice.amount }}
5+
}
6+
7+
@for(key: value of invoices[0]) {
8+
9+
<p><b>{{ field }}</b>: {{ value }}</p>
10+
}
11+
12+
<br/>

tests/views/pages/loop_.view.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Invoice No: 0
2+
Invoice ID: 23abc
3+
Amount: $10.08
4+
5+
Invoice No: 1
6+
Invoice ID: 24abc
7+
Amount: $15.24
8+
9+
Invoice No: 2
10+
Invoice ID: 25abc
11+
Amount: $5.31
12+
13+
<p><b>id</b>: 23</p>
14+
<p><b>amount</b>: $10.08</p>
15+
16+
<br/>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!-- Primitive variable -->
2+
Welcome, <b>{{ name }}</b>
3+
4+
<!-- Associative array -->
5+
Email: {{ email }}
6+
User ID: {{ user.id }}
7+
8+
<!-- Object instance -->
9+
City: {{ address.city }}
10+
Zip Code: {{ address.zip }}
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!-- Primitive variable -->
2+
Welcome, <b>John</b>
3+
4+
<!-- Associative array -->
5+
Email: john@doe.com
6+
User ID: 23abc
7+
8+
<!-- Object instance -->
9+
City: Diao City
10+
Zip Code: 456123
11+

0 commit comments

Comments
 (0)