Issues (13)

src/Controllers/HomeController.php (1 issue)

1
<?php
2
3
/**
4
 *  * Home controller
5
 *  *
6
 * The file contains every necessary functions for Home display.
7
 *
8
 *  * @category   Controllers
9
 *  * @package    SuperHive
10
 *  * @author     Florent Kosmala <[email protected]>
11
 *  * @license    https://www.gnu.org/licenses/gpl-3.0.txt GPL-3.0
12
 *  */
13
14
declare(strict_types=1);
15
16
namespace App\Controllers;
17
18
use App\Controllers\CommonController as Common;
19
use League\CommonMark\CommonMarkConverter;
20
use Psr\Container\ContainerInterface;
21
use Psr\Http\Message\ResponseInterface as Response;
22
use Psr\Http\Message\ServerRequestInterface as Request;
23
24
final class HomeController
25
{
26
    /** @var array<int|string, int|string> $settings */
27
    private array $settings;
28
29
    private ContainerInterface $app;
30
31
    public function __construct(ContainerInterface $app)
32
    {
33
        $this->app = $app;
34
        $this->settings = $app->get('settings');
35
36
        $common = new Common($this->app);
37
        $common->genPostsFile();
38
    }
39
40
    /**
41
     *  * Index function
42
     *  *
43
     * This function display the index page with the list of posts.
44
     * It ocntians also the function to generate the blog.json file with all posts informations.
45
     * All the posts must be converted from MarkDown to HTML before display.
46
     *
47
     * @param Response $response
48
     */
49
    public function index(Response $response): Response
50
    {
51
        $settings = $this->settings;
52
53
        // The file with the latest posts.
54
        $file = $this->app->get('blogfile');
55
56
        // Get the JSON
57
        $articles = json_decode(file_get_contents($file), true);
58
59
        //Get ready to parse the mardown
60
        $converter = new CommonMarkConverter();
61
        $parsedPosts = [];
62
63
        foreach ($articles as &$article) {
64
            // Create HTML from Markdown
65
            $article['body'] = $converter->convert($article['body']);
66
67
            //Get featured image
68
            $meta = json_decode($article['json_metadata'], true);
69
70
            if (
71
                array_key_exists('image', $meta)
72
                && is_array($meta['image'])
73
                && array_key_exists(0, $meta['image'])
74
            ) {
75
                $featured = $meta['image'][0];
76
            } else {
77
                $featured = '/themes/' . $settings['theme'] . '/no-img.png';
78
            }
79
80
            $article['featured'] = $featured;
81
82
            $parsedPosts[] = $article;
83
        }
84
85
        $common = new Common($this->app);
86
        $mostUsedTags = $common->getMostUsedTags();
87
        $popular = $common->getPopularPosts();
88
        $lastPosts = $common->getLastPosts();
89
90
        // Return view with articles
91
        return $this->app->get('view')->render($response, $settings['theme'] . '/index.html', [
92
            'articles' => $parsedPosts,
93
            'tags' => $mostUsedTags,
94
            'popular' => $popular,
95
            'last' => $lastPosts,
96
            'settings' => $settings,
97
        ]);
98
    }
99
100
    /**
101
     *  * Search function
102
     *  *
103
     * This function was called when search form is not empty and the form was send.
104
     * It displays the posts which contains the selected string.
105
     *
106
     * @param Request $request
107
     * @param Response $response
108
     *
109
     * @return Response $response
110
     */
111
    public function search(Request $request, Response $response): Response
112
    {
113
        $settings = $this->settings;
114
        $data = $request->getParsedBody();
115
        $posts = [];
116
        $result = [];
0 ignored issues
show
The assignment to $result is dead and can be removed.
Loading history...
117
118
        if (isset($data['term'])) {
119
            $term = $data['term'];
120
        } else {
121
            $term = 'nerd';
122
        }
123
124
        $file = $this->app->get('blogfile');
125
        $articles = json_decode(file_get_contents($file), true);
126
127
        $matches = [];
128
129
        foreach ($articles as $article) {
130
            // Check in Title
131
            if (preg_match("/\b{$term}\b/i", $article['title'])) {
132
                $matches[] = $article['title'];
133
            }
134
135
            // Check in Body
136
            if (preg_match("/\b{$term}\b/i", $article['body'])) {
137
                $matches[] = $article['title'];
138
            }
139
140
            //Check in Tags
141
            $metadata = json_decode($article['json_metadata'], true);
142
            $tags = implode(',', $metadata['tags']);
143
            if (preg_match("/\b{$term}\b/i", $tags)) {
144
                $matches[] = $article['title'];
145
            }
146
        }
147
        $result = array_unique($matches);
148
149
        foreach ($articles as $article) {
150
            if (in_array($article['title'], $result)) {
151
                //Get featured image
152
                $meta = json_decode($article['json_metadata'], true);
153
                if (
154
                    array_key_exists('image', $meta)
155
                    && is_array($meta['image'])
156
                    && array_key_exists(0, $meta['image'])
157
                ) {
158
                    $featured = $meta['image'][0];
159
                } else {
160
                    $featured = '/themes/' . $settings['theme'] . '/no-img.png';
161
                }
162
                $article['featured'] = $featured;
163
164
                $posts[] = $article;
165
            }
166
        }
167
168
        return $this->app->get('view')->render($response, $settings['theme'] . '/search.html', [
169
            'term' => $term,
170
            'posts' => $posts,
171
            'settings' => $settings,
172
        ]);
173
    }
174
175
    /**
176
     *  * Login function
177
     *  *
178
     * This function displays the login form.
179
     * It was called everytime an admin page is called without good session.
180
     *
181
     * @param Response $response
182
     *
183
     * @return Response $response
184
     */
185
    public function login(Response $response): Response
186
    {
187
        $settings = $this->settings;
188
189
        return $this->app->get('view')->render($response, 'login.html', [
190
            'settings' => $settings,
191
        ]);
192
    }
193
194
    /**
195
     *  * Login post function
196
     *  *
197
     * Called when the login form is send.
198
     * just compare the entered login and the encrypted key (generated by HiveKeychain)
199
     * with the credentials in passwod file.
200
     *
201
     * @param Request  $request
202
     * @param Response $response
203
     *
204
     * @return Response $response
205
     */
206
    public function loginPost(Request $request, Response $response): Response
207
    {
208
        $settings = $this->settings;
209
        $session = $this->app->get('session');
210
        $author = $settings['author'];
211
        $data = $request->getParsedBody();
212
213
        if (isset($data['username'])) {
214
            if (preg_match('/(hive-\d{6})/i', $author) == 1) {
215
                $session['sh_author'] = $data['username'];
216
                $session['sh_sign'] = $data['passwd'];
217
                $msg = 'OK';
218
            } else {
219
                $passFile = file_get_contents($this->app->get('password'));
220
                $cred = unserialize($passFile);
221
                $passwd = $cred[$author];
222
                if (($data['username'] === $author) && ($data['passwd'] === $passwd)) {
223
                    $session['sh_author'] = $data['username'];
224
                    $session['sh_sign'] = $data['passwd'];
225
                    $msg = 'OK';
226
                } else {
227
                    $session::destroy();
228
                    $msg = 'Not Ok';
229
                }
230
            }
231
        } else {
232
            $session::destroy();
233
            $msg = 'Not Ok';
234
        }
235
236
        $response->getBody()->write($msg);
237
        return $response;
238
    }
239
240
    /**
241
     * Feed function
242
     *
243
     * Generate the RSS feed of account's posts
244
     *
245
     * @param Request  $request
246
     * @param Response $response
247
     *
248
     * @return Response $response
249
     */
250
    public function feed(Request $request, Response $response): Response
251
    {
252
        $settings = $this->settings;
253
        $data = $request->getQueryParams();
254
        $tag = $data['tag'] ?? null;
255
        $matches = [];
256
257
        $file = $this->app->get('blogfile');
258
        $articles = json_decode(file_get_contents($file), true);
259
260
        if ($tag !== null) {
261
            foreach ($articles as $article) {
262
                $metadata = json_decode($article['json_metadata'], true);
263
                $tags = implode(',', $metadata['tags']);
264
                if (preg_match("/\b{$tag}\b/i", $tags)) {
265
                    $matches[] = $article['title'];
266
                }
267
            }
268
        }
269
270
        $result = array_unique($matches);
271
272
        if (!empty($result)) {
273
            $posts = array();
274
            foreach ($articles as $article) {
275
                if (in_array($article['title'], $result)) {
276
                    $posts[] = $article;
277
                }
278
            }
279
        }
280
        if (!empty($posts)) {
281
            $articles = $posts;
282
        }
283
284
        header('Content-Type: text/xml');
285
        return $this->app->get('view')->render($response, '/feed.xml', [
286
            'articles' => $articles,
287
            'settings' => $settings,
288
        ]);
289
    }
290
291
    /**
292
     *  * Sitemap function
293
     *  *
294
     * Generate the Sitemap with all posts links.
295
     *
296
     * @param Response $response
297
     *
298
     * @return Response $response
299
     */
300
    public function sitemap(Response $response): Response
301
    {
302
        $settings = $this->settings;
303
304
        $pages = [];
305
306
        $file = $this->app->get('blogfile');
307
        $articles = json_decode(file_get_contents($file), true);
308
309
        $pagesDir = $this->app->get('pagesdir');
310
        $files = preg_grep('~\.(html)$~', scandir($pagesDir));
311
        foreach ($files as $file) {
312
            $page = [];
313
            $page['created'] = filemtime($pagesDir . $file);
314
            $page['name'] = mb_substr($file, 0, -5);
315
            $pages[] = $page;
316
        }
317
318
        header('Content-Type: text/xml');
319
        return $this->app->get('view')->render($response, '/sitemap.xml', [
320
            'articles' => $articles,
321
            'pages' => $pages,
322
            'settings' => $settings,
323
        ]);
324
    }
325
326
    /**
327
     *  * About function
328
     *  *
329
     * Generate the about page with account information.
330
     *
331
     * @param Response $response
332
     *
333
     * @return Response $response
334
     */
335
    public function about(Response $response): Response
336
    {
337
        $settings = $this->settings;
338
        $accountFile = $this->app->get('accountfile');
339
        $account = json_decode(file_get_contents($accountFile), true);
340
341
        $accountBio = json_decode($account[0]['posting_json_metadata'], true);
342
343
        return $this->app->get('view')->render($response, $settings['theme'] . '/about.html', [
344
            'settings' => $settings,
345
            'data' => $account[0],
346
            'account' => $accountBio['profile'],
347
        ]);
348
    }
349
}
350