Skip to content

Commit ac6cac9

Browse files
committed
wip
1 parent 32ff29c commit ac6cac9

File tree

6 files changed

+134
-6
lines changed

6 files changed

+134
-6
lines changed

src/Web/Blog/BlogPostTag.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
enum BlogPostTag: string
66
{
7-
case RELEASE = 'Release';
8-
case THOUGHTS = 'Thoughts';
9-
case TUTORIAL = 'Tutorial';
7+
case RELEASE = 'release';
8+
case THOUGHTS = 'thoughts';
9+
case TUTORIAL = 'tutorial';
1010

1111
public function getStyle(): string
1212
{

src/Web/Blog/BlogRepository.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ public function all(bool $loadContent = false): ImmutableArray
3636
...YamlFrontMatter::parse(file_get_contents($path))->matter(),
3737
];
3838

39+
if (isset($data['tag'])) {
40+
$data['tag'] = strtolower($data['tag']);
41+
}
42+
43+
if (isset($data['author'])) {
44+
$data['author'] = strtolower($data['author']);
45+
}
46+
3947
if ($loadContent) {
4048
$data['content'] = $this->parseContent($path)->getContent();
4149
}
@@ -63,6 +71,14 @@ public function find(string $slug): ?BlogPost
6371
...$content->getFrontMatter(),
6472
];
6573

74+
if (isset($data['tag'])) {
75+
$data['tag'] = strtolower($data['tag']);
76+
}
77+
78+
if (isset($data['author'])) {
79+
$data['author'] = strtolower($data['author']);
80+
}
81+
6682
return map($data)->to(BlogPost::class);
6783
}
6884

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
title: Tempest 1.5
3+
description: This release brings a new markdown view component, CSRF support, installable view components, and more.
4+
tag: release
5+
author: brent
6+
---
7+
8+
## Installable view components
9+
10+
We made some pretty significant changes to view component's discovery. These changes now make it possible to ship view components from the framework or via third-party packages and publish them when needed:
11+
12+
```console
13+
./tempest install view-components
14+
15+
<dim>│</dim> <em>Select which view components you want to install</em>
16+
<dim>│</dim> / <dim>Filter...</dim>
17+
<dim>│</dim> → ⋅ x-csrf-token
18+
<dim>│</dim> ⋅ x-markdown
19+
<dim>│</dim> ⋅ x-input
20+
<dim>│</dim> ⋅ x-icon
21+
22+
<comment>…</comment>
23+
```
24+
25+
This refactor came with some breaking changes though. Tempest View is still an experimental component of the framework, so occasional breaking changes might happen. We documented the how and why of these changes in [a separate blog post](/blog/tempest-view-updates). In the end, these changes made a lot of sense, and it's great to see how [Discovery](/blog/discovery-explained) made the installer part with vendor- and project-based view components trivial to add.
26+
27+
Apart from the view component installer, we also made a bunch of fixes to how view components deal with local and global variable scope, and we added a bunch more built-in view components that ship with the framework:
28+
29+
- `{html}<x-base />`: a barebone base layout with Tailwind CDN included
30+
- `{html}<x-form />`: a form component which posts by default and includes the csrf token out of the box
31+
- `{html}<x-input />`: a flexible component to render form inputs
32+
- `{html}<x-submit />`: renders a submit button
33+
- `{html}<x-markdown />`: a component to render markdown, either inline or from a variable
34+
35+
You can read more about built-in view components in [the docs](/docs/essentials/views#built-in-components).
36+
37+
## CSRF support
38+
39+
Any form request will now have CSRF protection. Because CSRF protection is enabled by default, you will need to add the new `{html}<x-csrf-token />` element to your forms (it is included by default when you use `{html}<x-form />`).
40+
41+
```html
42+
<form action="">
43+
<x-csrf-token />
44+
</form>
45+
```
46+
47+
## Database pagination
48+
49+
The select query builder now has pagination support:
50+
51+
```php
52+
$chapters = query(Chapter::class)
53+
->select()
54+
->whereField('book_id', $book->id)
55+
->paginate();
56+
```
57+
58+
## New `Json` response
59+
60+
We've added a new `Json` response class that can be returned from controllers and will include the necessary JSON headers:
61+
62+
```php
63+
use Tempest\Http\Responses\Json;
64+
65+
#[Get('/books')]
66+
public function books(): Response
67+
{
68+
// …
69+
return new Json($books);
70+
}
71+
```
72+
73+
## View data testers
74+
75+
We added some additional assertion methods to our HTTP tester, so that you can make assertions on view data directly:
76+
77+
```php
78+
public function test_can_assert_view_data(): void
79+
{
80+
$this->http
81+
->get(uri([TestController::class, 'withView']))
82+
->assertViewData('name')
83+
->assertViewData('name', function (array $data, string $value): void {
84+
$this->assertEquals(['name' => 'Brent'], $data);
85+
$this->assertEquals('Brent', $value);
86+
})
87+
->assertViewDataMissing('email');
88+
}
89+
```
90+
91+
That's all the notable new features in Tempest 1.5. Of course, there are a bunch of bug fixes as well. Click here to read [the full changelog](https://github.com/tempestphp/tempest-framework/releases/tag/v1.5.0).

src/Web/Blog/index.view.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

33
/** @var \App\Web\Blog\BlogPost[] $posts */
4+
use function Tempest\Support\str;
45
?>
56

67
<x-base title="Blog">
@@ -35,7 +36,7 @@
3536
:class="$post->tag->getStyle()"
3637
class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded ring ring-inset"
3738
>
38-
{{ $post->tag->value }}
39+
{{ str($post->tag->value)->title() }}
3940
</span>
4041
<span :if="$post->author" class="text-(--ui-text-muted) text-sm">
4142
by <span class="font-medium">{{ $post->author->getName() }}</span> on <span class="font-medium">{{ $post->createdAt->format('F d, Y') }}</span>

src/Web/Documentation/content/1.x/1-essentials/02-views.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ A base template you can install into your own project as a starting point. This
485485

486486
### `x-form`
487487

488-
This component provides a form element that will post by default instead of get:
488+
This component provides a form element that will post by default and includes the csrf token out of the box:
489489

490490
```html
491491
<?php
@@ -516,6 +516,16 @@ A submit button component that prefills with a "Submit" label:
516516
<x-submit label="Send" />
517517
```
518518

519+
### `x-csrf-token`
520+
521+
Includes the CSRF token in a form
522+
523+
```html
524+
<form action="">
525+
<x-csrf-token />
526+
</form>
527+
```
528+
519529
### `x-icon`
520530

521531
This component provides the ability to inject any icon from the [Iconify](https://iconify.design/) project in your templates.

src/Web/Documentation/content/1.x/4-internals/03-view-spec.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ A base template you can install into your own project as a starting point. This
470470

471471
### `x-form`
472472

473-
This component provides a form element that will post by default instead of get:
473+
This component provides a form element that will post by default and includes the csrf token out of the box:
474474

475475
```html
476476
<?php
@@ -501,6 +501,16 @@ A submit button component that prefills with a "Submit" label:
501501
<x-submit label="Send" />
502502
```
503503

504+
### `x-csrf-token`
505+
506+
Includes the CSRF token in a form
507+
508+
```html
509+
<form action="">
510+
<x-csrf-token />
511+
</form>
512+
```
513+
504514
### `x-icon`
505515

506516
This component provides the ability to inject any icon from the [Iconify](https://iconify.design/) project in your templates.

0 commit comments

Comments
 (0)