summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Controller/FeedController.php47
-rw-r--r--src/Controller/RouteController.php170
-rw-r--r--src/Model/ApiService.php286
-rw-r--r--src/Model/CacheService.php10
-rw-r--r--src/View/BaseTemplate.php35
5 files changed, 0 insertions, 548 deletions
diff --git a/src/Controller/FeedController.php b/src/Controller/FeedController.php
deleted file mode 100644
index 8bba37f..0000000
--- a/src/Controller/FeedController.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-namespace HN\Controllers;
-
-class FeedController
-{
- /**
- * @var string
- */
- private string $canonical_url;
- /**
- * @var string
- */
- private string $description;
- /**
- * @var string
- */
- private string $title;
- /**
- * @var string
- */
- private string $content;
- /**
- * @var false|string
- */
- private mixed $current_year;
-
- public function __construct(string $canonical_url, string $description, string $title, string $content)
- {
- $this->canonical_url = $canonical_url;
- $this->description = $description;
- $this->title = $title;
- $this->content = $content;
- $this->current_year = date("Y");
- }
-
- /**
- * Request template to be presented to the user
- *
- * @access public
- * @author Christian Cleberg <[email protected]>
- */
- public function render(): void
- {
- include_once 'src/View/BaseTemplate.php';
- }
-}
diff --git a/src/Controller/RouteController.php b/src/Controller/RouteController.php
deleted file mode 100644
index e3b2236..0000000
--- a/src/Controller/RouteController.php
+++ /dev/null
@@ -1,170 +0,0 @@
-<?php
-
-namespace HN\Controllers;
-
-require_once 'src/Controller/FeedController.php';
-
-use function HN\Models\GetApiResults;
-use function HN\Models\ParseItem;
-use function HN\Models\ParseStories;
-use function HN\Models\ParseUser;
-
-class RouteController
-{
- /**
- * @var string
- */
- private string $request;
-
- public function __construct(string $request)
- {
- $this->request = $request;
- }
-
- /**
- * Route the user to the appropriate function, based on the URL
- *
- * @access public
- * @return void No return type; send user to FeedController->render() or a 404 error
- * @author Christian Cleberg <[email protected]>
- */
- public function routeUser(): void
- {
- include_once 'src/Model/ApiService.php';
- $path = ltrim($this->request, '/');
- $elements = explode('/', $path);
-
- switch (array_shift($elements)) {
- case '':
- case 'top':
- $feed = new FeedController(
- $GLOBALS['full_domain'],
- 'The top stories from Hacker News, proxied by hn.',
- 'hn',
- ParseStories(
- GetApiResults(
- 'https://hacker-news.firebaseio.com/v0/topstories.json?limitToFirst=10&orderBy="$key"'
- ),
- 'Top'
- )
- );
-
- $feed->render();
- break;
-
- case 'best':
- $feed = new FeedController(
- $GLOBALS['full_domain'] . '/Best/',
- 'The best stories from Hacker News, proxied by hn.',
- 'hn ~ best',
- ParseStories(
- GetApiResults(
- 'https://hacker-news.firebaseio.com/v0/beststories.json?limitToFirst=10&orderBy="$key"'
- ),
- 'Best'
- )
- );
-
- $feed->render();
- break;
-
- case 'new':
- $feed = new FeedController(
- $GLOBALS['full_domain'] . '/new/',
- 'The newest stories from Hacker News, proxied by hn.',
- 'hn ~ new',
- ParseStories(
- GetApiResults(
- 'https://hacker-news.firebaseio.com/v0/newstories.json?limitToFirst=10&orderBy="$key"'
- ),
- 'New'
- )
- );
-
- $feed->render();
- break;
-
- case 'ask':
- $feed = new FeedController(
- $GLOBALS['full_domain'] . '/ask/',
- 'The top asks from Hacker News, proxied by hn.',
- 'hn ~ ask',
- ParseStories(
- GetApiResults(
- 'https://hacker-news.firebaseio.com/v0/askstories.json?limitToFirst=10&orderBy="$key"'
- ),
- 'Ask'
- )
- );
-
- $feed->render();
- break;
-
- case 'show':
- $feed = new FeedController(
- $GLOBALS['full_domain'] . '/show/',
- 'The latest showcases from Hacker News, proxied by hn.',
- 'hn ~ show',
- ParseStories(
- GetApiResults(
- 'https://hacker-news.firebaseio.com/v0/showstories.json?limitToFirst=10&orderBy="$key"'
- ),
- 'Show'
- )
- );
-
- $feed->render();
- break;
-
- case 'job':
- $feed = new FeedController(
- $GLOBALS['full_domain'] . '/job/',
- 'The latest jobs from Hacker News, proxied by hn.',
- 'hn ~ jobs',
- ParseStories(
- GetApiResults(
- 'https://hacker-news.firebaseio.com/v0/jobstories.json?limitToFirst=10&orderBy="$key"'
- ),
- 'Job'
- )
- );
-
- $feed->render();
- break;
-
- case 'user':
- $feed = new FeedController(
- $GLOBALS['full_domain'] . '/user/' . $elements[0],
- 'The Hacker News profile for ' . $elements[0] . ', proxied by hn.',
- 'hn ~ ' . $elements[0],
- ParseUser(
- GetApiResults(
- 'https://hacker-news.firebaseio.com/v0/user/' . $elements[0] . '.json'
- ),
- 'User: ' . $elements[0]
- )
- );
-
- $feed->render();
- break;
-
- case 'item':
- $feed = new FeedController(
- $GLOBALS['full_domain'] . '/item/' . $elements[0],
- 'Hacker News story ' . $elements[0] . ', proxied by hn.',
- 'hn ~ ' . $elements[0],
- ParseItem(
- GetApiResults(
- 'https://hacker-news.firebaseio.com/v0/item/' . $elements[0] . '.json'
- )
- )
- );
-
- $feed->render();
- break;
-
- default:
- header('HTTP/1.1 404 Not Found');
- }
- }
-} \ No newline at end of file
diff --git a/src/Model/ApiService.php b/src/Model/ApiService.php
deleted file mode 100644
index dce65e5..0000000
--- a/src/Model/ApiService.php
+++ /dev/null
@@ -1,286 +0,0 @@
-<?php
-
-namespace HN\Models;
-
-/**
- * Extract a set of stories from the Hacker News API
- *
- * @access public
- * @param string $api_url The API endpoint to use for extraction
- * @return mixed The API results formatted into an HTML section
- * @author Christian Cleberg <[email protected]>
- */
-function GetApiResults(string $api_url): mixed
-{
- $response = file_get_contents($api_url);
- return json_decode($response, true);
-}
-
-/**
- * Formats a given set of API results into an HTML section
- *
- * @access public
- * @param mixed $api_results The decoded API results
- * @param string $inline_title The <h1> title to use in the HTML
- * @return string $html_output The formatted HTML result of stories from the API or the error message
- * @author Christian Cleberg <[email protected]>
- */
-function ParseStories(mixed $api_results, string $inline_title): string
-{
- if ($api_results == "null") {
- return '<p>ERROR: Stories not found. API returned `null`.</p>';
- } else {
- $html_output = '<h1>' . $inline_title . '</h1>';
- for ($i = 0; $i < count($api_results); $i++) {
- $story_api_results = GetApiResults('https://hacker-news.firebaseio.com/v0/item/' . $api_results[$i] . '.json');
- $html_output .= ConstructStory($story_api_results);
- }
-
- return $html_output;
- }
-}
-
-/**
- *Extract a user's profile from Hacker News API and format in HTML
- *
- * @access public
- * @param mixed $api_results The decoded API results
- * @param string $inline_title The <h1> title to use in the HTML
- * @return string $html_output The formatted HTML result of stories from the API
- * @author Christian Cleberg <[email protected]>
- */
-function ParseUser(mixed $api_results, string $inline_title): string
-{
- if ($api_results == "null") {
- return '<p>ERROR: User not found.</p>';
- } else {
- // TODO: Create function to format $about using the following guidelines
- // : https://news.ycombinator.com/formatdoc
- // : hint: nl2br() will solve the first formatting requirement
- $about = $api_results['about'];
- $karma = $api_results['karma'];
- $created = date('Y-m-d h:m:s', $api_results['created']);
-
- $html_output = <<<EOT
- <div class="user-details">
- <h1>$inline_title</h1>
- <p>About: $about</p>
- <p>Karma: $karma</p>
- <p>Created: <time datetime="$created">$created</time></p>
- <br>
- <h2>Recently Submitted</h2>
- </div>
- EOT;
-
- $limit = (count($api_results['submitted']) > 10) ? 10 : count($api_results['submitted']);
- if (count($api_results['submitted']) > 0) {
- for ($i = 0; $i < $limit; $i++) {
- $user_api_results = GetApiResults('https://hacker-news.firebaseio.com/v0/item/' . $api_results['submitted'][$i] . '.json');
- $html_output .= GetItem($user_api_results);
- }
- } else {
- $html_output .= '<p>User has no submissions.</p>';
- }
-
- return $html_output;
- }
-}
-
-
-/**
- * Formats one specific item requested by the user
- *
- * @access public
- * @param mixed $api_results The decoded API results
- * @param string $inline_title The <h1> title to use in the HTML
- * @return string $html_output The formatted HTML result of stories from the API or the error message
- * @author Christian Cleberg <[email protected]>
- */
-function ParseItem(mixed $api_results): string
-{
- if ($api_results == "null") {
- return '<p>ERROR: User not found.</p>';
- } else {
- $html_output = '';
-
- if (in_array($api_results['type'], array("job", "story", "poll", "pollopt"))) {
- $html_output .= ConstructStoryDiscussion($api_results);
- } else {
- if (array_key_exists('parent', $api_results)) {
- $parent_api_results = GetApiResults('https://hacker-news.firebaseio.com/v0/item/' . $api_results['parent'] . '.json');
- $html_output .= GetItem($parent_api_results);
- $html_output .= '<hr>';
- }
-
- $html_output .= GetItem($api_results);
-
- if ($api_results['descendants'] != 0) {
- $html_output .= '<hr>';
- $child_api_results = GetApiResults('https://hacker-news.firebaseio.com/v0/item/' . $api_results['kids'][0] . '.json');
- $html_output .= GetItem($child_api_results);
- }
- }
-
- return $html_output;
- }
-}
-
-
-/**
- * Formats one item from the API to HTML
- *
- * @access public
- * @param mixed $api_results The decoded API results
- * @return string The formatted HTML result of stories from the API or the error message
- * @author Christian Cleberg <[email protected]>
- */
-function GetItem(mixed $api_results): string
-{
- $type = $api_results['type'];
-
- return match ($type) {
- 'story', 'job' => ConstructStory($api_results),
- 'comment' => ConstructComment($api_results),
- 'poll' => ConstructPoll($api_results),
- 'pollopt' => ConstructPollOpt($api_results),
- default => '[ERROR] Item type not found: ' . $type,
- };
-}
-
-
-/**
- * Creates a story HTML element
- *
- * @access public
- * @param mixed $api_results The decoded API results
- * @return string The formatted HTML result of stories from the API or the error message
- * @author Christian Cleberg <[email protected]>
- */
-function ConstructStory(mixed $api_results): string
-{
- $id = $api_results['id'];
- $url = $api_results['url'];
- $title = $api_results['title'];
- $time = date('Y-m-d h:m:s', $api_results['time']);
- $by = $api_results['by'];
- $score = $api_results['score'];
- if (array_key_exists('descendants', $api_results)) {
- $descendants = $api_results['descendants'];
- } else {
- $descendants = 'No';
- }
-
- return <<<EOT
- <div class="story">
- <a href="$url">$title</a>
- <p>
- <time datetime="$time">$time</time>
- by <a href="/user/$by/">$by</a>
- | $score points
- | <a href="/item/$id">$descendants comments</a>
- </p>
- </div>
- EOT;
-}
-
-/**
- * Creates a story discussion page with comments
- *
- * @access public
- * @param mixed $api_results The decoded API results
- * @return string The formatted HTML result of stories from the API or the error message
- * @author Christian Cleberg <[email protected]>
- */
-function ConstructStoryDiscussion(mixed $api_results): string
-{
- $id = $api_results['id'];
- $url = $api_results['url'];
- $title = $api_results['title'];
- $time = date('Y-m-d h:m:s', $api_results['time']);
- $by = $api_results['by'];
- $score = $api_results['score'];
- $descendants = $api_results['descendants'];
- if (array_key_exists('text', $api_results)) {
- $text = $api_results['text'];
- } else {
- $text = '';
- }
-
- $html_output = <<<EOT
- <div class="story-discussion">
- <h1><a href="$url" target="_blank" rel="noopener">$title</a></h1>
- <p>
- <time datetime="$time">$time</time>
- by <a href="/user/$by/">$by</a>
- | $score points
- | <a href="/item/$id">$descendants comments</a>
- </p>
- <p>$text</p>
- </div>
- EOT;
-
- // TODO: Add support for more than just top-level kids (i.e., recursive).
- if ($api_results['descendants'] != 0) {
- $html_output .= <<<EOT
- <div class="story-discussion-comments">
- <h2>Comments</h2>
- EOT;
- for ($i = 0; $i < count($api_results['kids']); $i++) {
- $child_api_results = GetApiResults('https://hacker-news.firebaseio.com/v0/item/' . $api_results['kids'][$i] . '.json');
- $html_output .= GetItem($child_api_results);
- }
- $html_output .= '</div>';
- }
-
- return $html_output;
-}
-
-/**
- * Creates a comment HTML element
- *
- * @access public
- * @param mixed $api_results The decoded API results
- * @return string The formatted HTML result of stories from the API or the error message
- * @author Christian Cleberg <[email protected]>
- */
-function ConstructComment(mixed $api_results): string
-{
- $time = date('Y-m-d h:m:s', $api_results['time']);
- $text = $api_results['text'];
- $by = $api_results['by'];
- $parent = $api_results['parent'];
-
- return <<<EOT
- <div class="comment">
- <p>$text</p>
- <p><i>Submitted in response to: <a href="/item/$parent/">$parent</a></i></p>
- <p><time datetime="$time">$time</time> by <a href="/user/$by/">$by</a></p>
- </div>
- EOT;
-}
-
-/**
- * Creates a poll HTML element
- *
- * @access public
- * @param mixed $api_results The decoded API results
- * @return string The formatted HTML result of stories from the API or the error message
- * @author Christian Cleberg <[email protected]>
- */
-function ConstructPoll(mixed $api_results): string
-{
- return 'TODO';
-}
-
-/**
- * Creates a poll-option HTML element
- *
- * @access public
- * @param mixed $api_results The decoded API results
- * @return string The formatted HTML result of stories from the API or the error message
- * @author Christian Cleberg <[email protected]>
- */
-function ConstructPollOpt(mixed $api_results): string
-{
- return 'TODO';
-}
diff --git a/src/Model/CacheService.php b/src/Model/CacheService.php
deleted file mode 100644
index ccb0db4..0000000
--- a/src/Model/CacheService.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-
-/**
- * TODO: Implement a way to cache certain content in SQLite or something similarly performative
- *
- * @access public
- * @return void
- * @author Christian Cleberg <[email protected]>
- */
-function CacheService() {} \ No newline at end of file
diff --git a/src/View/BaseTemplate.php b/src/View/BaseTemplate.php
deleted file mode 100644
index 1aa25ab..0000000
--- a/src/View/BaseTemplate.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<!doctype html>
-<html lang="en">
-
-<head>
- <title><?php echo $this->title; ?></title>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
- <meta http-equiv="x-ua-compatible" content="ie=edge">
- <meta name="author" content="<?php echo $GLOBALS['author_name']; ?>">
- <meta name="description" content="<?php echo $this->description; ?>">
- <link rel="canonical" href="<?php echo $this->canonical_url; ?>">
- <link rel="stylesheet" href="/static/styles.min.css">
-</head>
-
-<body>
-<main id="main">
- <nav class="links">
- <span><a href="/">Top</a> &middot; </span>
- <span><a href="/best/">Best</a> &middot;</span>
- <span><a href="/new/">New</a> &middot;</span>
- <span><a href="/ask/">Ask</a> &middot;</span>
- <span><a href="/show/">Show</a> &middot;</span>
- <span><a href="/job/">Job</a></span>
- </nav>
- <?php echo $this->content; ?>
-</main>
-
-<footer>
- <p><a href="https://git.cleberg.net/hn.git">Source Code</a></p>
- <p>Copyright &copy; 2023 - <?php echo $this->current_year; ?></p>
-</footer>
-
-</body>
-
-</html>