fkosmala /
superhive
| 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
Unused Code
introduced
by
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 |