/
guide.txt
151 lines (110 loc) · 4.79 KB
/
guide.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
Title: Content from an RSS feed
----
Description: Load data from an RSS feed and create virtual pages for each item.
----
Intro: Fetch your Medium blog into your own site. In this example we will create pages from an RSS feed.
----
Text:
For this example, we use (link: https://help.medium.com/hc/en-us/articles/214874118-RSS-feeds text: Medium's RSS feeds) to integrate articles as virtual pages into our own site.
To start, we create a parent page, e.g. `rssfeed` in the `/content` folder and inside it an `rssfeed.txt` text file.
Let's give our parent page a title and maybe a short intro.
```kirbycontent "/content/rssfeed/rssfeed.txt"
Title: My virtual feed
\----
Intro: This page lists articles from an RSS feed.
```
## Creating the virtual subpages
To fetch the virtual children, we create a new `Rssfeed` page model which will read the RSS feed and create a virtual child page for each entry on the fly. The (link: docs/reference/@/http/remote text: `Remote`) class is our friend and helps us with handling this remote request.
```php "/site/models/rssfeed.php"
<?php
use Kirby\Uuid\Uuid;
class RssfeedPage extends Page {
public function children()
{
if ($this->children instanceof Pages) {
return $this->children;
}
$results = [];
$pages = [];
// use the URL of the feed you want to fetch
$request = Remote::get('https://open.nytimes.com/feed');
// if the request was sucessfully, parse feed as $results
if ($request->code() === 200) {
$results = Xml::parse($request->content());
}
// if we have any results, create the child page props for each result
if (count($results) > 0) {
foreach ($results['channel']['item'] as $item) {
$pages[] = [
'slug' => Str::slug($item['title']),
'template' => 'feeditem',
'model' => 'feeditem',
'content' => [
'title' => $item['title'],
'date' => $item['pubDate'] ?? '',
'description' => $item['description'] ?? '',
'link' => $item['link'] ?? '',
'text' => $item['contentencoded'] ?? '',
'categories' => isset($item['category']) ? implode(',', $item['category']) : '',
'author' => $item['dccreator'] ?? '',
'uuid' => Uuid::generate(),
]
];
}
}
// create a Pages collection for the child pages
return $this->children = Pages::factory($pages, $this);
}
}
```
<warning>
Unless you have disabled UUIDs in your config, you have to pass a `uuid` field in the content array to prevent Kirby from generating the page in the file system when the `$page->uuid()` method is called.
If you generate the UUIDs automatically like in the example above, they will change at every load. However, if you want to reference your virtual pages anywhere with their UUID, make sure to use a unique string that does not change.
</warning>
## The template
With this new page model in place, we can now render all feed articles in our `rssfeed.php` template as if they were regular Kirby children pages.
```php "/site/templates/rssfeed.php"
<?php snippet('header') ?>
<main>
<header>
<h1><?= $page->title() ?></h1>
</header>
<div class="feed">
<?php foreach ($page->children()->sortBy('date', 'desc') as $item): ?>
<article>
<header class="article-header">
<a href="<?= $item->url() ?>">
<h2><?= $item->title() ?></h2>
<time><?= $item->date()->toDate('d F Y') ?></time>
</a>
</header>
</article>
<?php endforeach ?>
</div>
</main>
<?php snippet('footer') ?>
```
## Subpages
Each article will automatically get its own subpage. Routing will work out of the box and you can create an `feeditem.php` template (as we defined above when setting the child page props) to render each individual article.
```php "/site/templates/feeditem.php"
<?php snippet('header') ?>
<main>
<article class="feedarticle">
<header class="article-header">
<h1><?= $page->title() ?></h1>
<time><?= $page->date()->toDate('d F Y') ?></time>
<?php if ($page->categories()->isNotEmpty()) : ?>
<p class="tags"><?= $page->categories() ?></p>
<?php endif ?>
</header>
<div class="article-body">
<?php if ($page->author()->isNotEmpty()): ?>
<p>by <?= $page->author() ?></p>
<?php endif ?>
<?= $page->text()->excerpt(500) ?>
<a href="<?= $page->link() ?>">Continue reading on Medium</a>
</div>
</article>
</main>
<?php snippet('footer') ?>
```