Commit d0138b92ae

d0138b92ae002002d520b9871764039e678930b7

parent: 7f0d14fe6f

Unsigned

cmc <hello@cleberg.net> · 2023-06-14 19:37 UTC

fix: code quality and formatting

Layout: unified · split

.idea/.gitignore added +8
@@ -0,0 +1,8 @@
1# Default ignored files
2/shelf/
3/workspace.xml
4# Editor-based HTTP Client requests
5/httpRequests/
6# Datasource local storage ignored files
7/dataSources/
8/dataSources.local.xml
.idea/hn.iml added +8
@@ -0,0 +1,8 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<module type="WEB_MODULE" version="4">
3 <component name="NewModuleRootManager">
4 <content url="file://$MODULE_DIR$" />
5 <orderEntry type="inheritedJdk" />
6 <orderEntry type="sourceFolder" forTests="false" />
7 </component>
8</module>
\ No newline at end of file
.idea/modules.xml added +8
@@ -0,0 +1,8 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<project version="4">
3 <component name="ProjectModuleManager">
4 <modules>
5 <module fileurl="file://$PROJECT_DIR$/.idea/hn.iml" filepath="$PROJECT_DIR$/.idea/hn.iml" />
6 </modules>
7 </component>
8</project>
\ No newline at end of file
.idea/php.xml added +22
@@ -0,0 +1,22 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<project version="4">
3 <component name="MessDetectorOptionsConfiguration">
4 <option name="transferred" value="true" />
5 </component>
6 <component name="PHPCSFixerOptionsConfiguration">
7 <option name="transferred" value="true" />
8 </component>
9 <component name="PHPCodeSnifferOptionsConfiguration">
10 <option name="highlightLevel" value="WARNING" />
11 <option name="transferred" value="true" />
12 </component>
13 <component name="PhpProjectSharedConfiguration" php_language_level="7.0">
14 <option name="suggestChangeDefaultLanguageLevel" value="false" />
15 </component>
16 <component name="PhpStanOptionsConfiguration">
17 <option name="transferred" value="true" />
18 </component>
19 <component name="PsalmOptionsConfiguration">
20 <option name="transferred" value="true" />
21 </component>
22</project>
\ No newline at end of file
.idea/vcs.xml added +6
@@ -0,0 +1,6 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<project version="4">
3 <component name="VcsDirectoryMappings">
4 <mapping directory="" vcs="Git" />
5 </component>
6</project>
\ No newline at end of file
index.php +215 −214
@@ -5,231 +5,232 @@ $path = ltrim($_SERVER['REQUEST_URI'], '/');
55$elements = explode('/', $path);
66
77if (empty($elements[0])) {
8 $html_output = get_stories(
9 'https://hacker-news.firebaseio.com/v0/topstories.json?limitToFirst=10&orderBy="$key"',
10 'Top'
11 );
12 echo_html(
13 $GLOBALS['full_domain'],
14 'The top stories from Hacker News, proxied by hn.',
15 'hn',
16 $html_output
17 );
8 $html_output = get_stories(
9 'https://hacker-news.firebaseio.com/v0/topstories.json?limitToFirst=10&orderBy="$key"',
10 'Top'
11 );
12 echo_html(
13 $GLOBALS['full_domain'],
14 'The top stories from Hacker News, proxied by hn.',
15 'hn',
16 $html_output
17 );
1818} else {
19 switch (array_shift($elements)) {
20 case 'top':
21 $html_output = get_stories(
22 'https://hacker-news.firebaseio.com/v0/topstories.json?limitToFirst=10&orderBy="$key"',
23 'Top'
24 );
25 echo_html(
26 $GLOBALS['full_domain'],
27 'The top stories from Hacker News, proxied by hn.',
28 'hn',
29 $html_output
30 );
31 break;
32
33 case 'best':
34 $html_output = get_stories(
35 'https://hacker-news.firebaseio.com/v0/beststories.json?limitToFirst=10&orderBy="$key"',
36 'Best'
37 );
38 echo_html(
39 $GLOBALS['full_domain'] . '/best/',
40 'The best 30 stories from Hacker News, proxied by hn.',
41 'hn ~ best',
42 $html_output
43 );
44 break;
45
46 case 'new':
47 $html_output = get_stories(
48 'https://hacker-news.firebaseio.com/v0/newstories.json?limitToFirst=10&orderBy="$key"',
49 'New'
50 );
51 echo_html(
52 $GLOBALS['full_domain'] . '/new/',
53 'The newest 30 stories from Hacker News, proxied by hn.',
54 'hn ~ new',
55 $html_output
56 );
57 break;
58
59 case 'ask':
60 $html_output = get_stories(
61 'https://hacker-news.firebaseio.com/v0/askstories.json?limitToFirst=10&orderBy="$key"',
62 'Ask'
63 );
64 echo_html(
65 $GLOBALS['full_domain'] . '/ask/',
66 'The latest 30 asks from Hacker News, proxied by hn.',
67 'hn ~ ask',
68 $html_output
69 );
70 break;
71
72 case 'show':
73 $html_output = get_stories(
74 'https://hacker-news.firebaseio.com/v0/showstories.json?limitToFirst=10&orderBy="$key"',
75 'Show'
76 );
77 echo_html(
78 $GLOBALS['full_domain'] . '/show/',
79 'The latest 30 show stories from Hacker News, proxied by hn.',
80 'hn ~ show',
81 $html_output
82 );
83 break;
84
85 case 'job':
86 $html_output = get_stories(
87 'https://hacker-news.firebaseio.com/v0/jobstories.json?limitToFirst=10&orderBy="$key"',
88 'Job'
89 );
90 echo_html(
91 $GLOBALS['full_domain'] . '/job/',
92 'The latest 30 job posts from Hacker News, proxied by hn.',
93 'hn ~ job',
94 $html_output
95 );
96 break;
97
98 case 'user':
99 $html_output = get_user(
100 'https://hacker-news.firebaseio.com/v0/user/' . $elements[0] . '.json',
101 'User Profile: ' . $elements[0]
102 );
103 echo_html(
104 $GLOBALS['full_domain'] . '/user/' . $elements[0],
105 'The Hacker News profile for ' . $elements[0] . ', proxied by hn.',
106 'hn',
107 $html_output
108 );
109 break;
110
111 default:
112 header('HTTP/1.1 404 Not Found');
113 }
19 switch (array_shift($elements)) {
20 case 'top':
21 $html_output = get_stories(
22 'https://hacker-news.firebaseio.com/v0/topstories.json?limitToFirst=10&orderBy="$key"',
23 'Top'
24 );
25 echo_html(
26 $GLOBALS['full_domain'],
27 'The top stories from Hacker News, proxied by hn.',
28 'hn',
29 $html_output
30 );
31 break;
32
33 case 'best':
34 $html_output = get_stories(
35 'https://hacker-news.firebaseio.com/v0/beststories.json?limitToFirst=10&orderBy="$key"',
36 'Best'
37 );
38 echo_html(
39 $GLOBALS['full_domain'] . '/best/',
40 'The best 30 stories from Hacker News, proxied by hn.',
41 'hn ~ best',
42 $html_output
43 );
44 break;
45
46 case 'new':
47 $html_output = get_stories(
48 'https://hacker-news.firebaseio.com/v0/newstories.json?limitToFirst=10&orderBy="$key"',
49 'New'
50 );
51 echo_html(
52 $GLOBALS['full_domain'] . '/new/',
53 'The newest 30 stories from Hacker News, proxied by hn.',
54 'hn ~ new',
55 $html_output
56 );
57 break;
58
59 case 'ask':
60 $html_output = get_stories(
61 'https://hacker-news.firebaseio.com/v0/askstories.json?limitToFirst=10&orderBy="$key"',
62 'Ask'
63 );
64 echo_html(
65 $GLOBALS['full_domain'] . '/ask/',
66 'The latest 30 asks from Hacker News, proxied by hn.',
67 'hn ~ ask',
68 $html_output
69 );
70 break;
71
72 case 'show':
73 $html_output = get_stories(
74 'https://hacker-news.firebaseio.com/v0/showstories.json?limitToFirst=10&orderBy="$key"',
75 'Show'
76 );
77 echo_html(
78 $GLOBALS['full_domain'] . '/show/',
79 'The latest 30 show stories from Hacker News, proxied by hn.',
80 'hn ~ show',
81 $html_output
82 );
83 break;
84
85 case 'job':
86 $html_output = get_stories(
87 'https://hacker-news.firebaseio.com/v0/jobstories.json?limitToFirst=10&orderBy="$key"',
88 'Job'
89 );
90 echo_html(
91 $GLOBALS['full_domain'] . '/job/',
92 'The latest 30 job posts from Hacker News, proxied by hn.',
93 'hn ~ job',
94 $html_output
95 );
96 break;
97
98 case 'user':
99 $html_output = get_user(
100 'https://hacker-news.firebaseio.com/v0/user/' . $elements[0] . '.json',
101 'User Profile: ' . $elements[0]
102 );
103 echo_html(
104 $GLOBALS['full_domain'] . '/user/' . $elements[0],
105 'The Hacker News profile for ' . $elements[0] . ', proxied by hn.',
106 'hn',
107 $html_output
108 );
109 break;
110
111 default:
112 header('HTTP/1.1 404 Not Found');
113 }
114114}
115115
116116/**
117* Extract a set of stories from Hacker News API and format in HTML
118*
119* @access public
120* @author cmc <hello@cleberg.net>
121* @param string $api_url The API endpoint to use for extraction
122* @param string $inline_title The <h1> title to use in the HTML
123* @return string $html_output The formatted HTML result of stories from the API
124*/
125function get_stories($api_url, $inline_title) {
126 $response_raw = file_get_contents($api_url);
127 if (is_null($response_raw) || $response_raw == "null") {
128 $html_output .= '<p>ERROR: Stories not found. API returned `null`.</p>';
129 return $html_output;
130 } else {
131 $response = json_decode($response_raw, true);
132 }
133
134 $html_output = '<h1>' . $inline_title . '</h1>';
135
136 for ($i = 0; $i < count($response); $i++) {
137 $sub_url = 'https://hacker-news.firebaseio.com/v0/item/' . $response[$i] . '.json';
138 $sub_response_raw = file_get_contents($sub_url);
139 $sub_response = json_decode($sub_response_raw, true);
140
141 // TODO: Can this be converted to a heredoc string with variables?
142 $html = '<div><a href="' . $sub_response['url'] . '">' . $sub_response['title'] . '</a>';
143 $html .= '<p><time datetime="' . date('Y-m-d h:m:s', $sub_response['time']) . '">';
144 $html .= date('Y-m-d h:m:s', $sub_response['time']) . '</time> by <a';
145 $html .= ' href="/user/'. $sub_response['by'] . '">';
146 $html .= $sub_response['by'] . '</a> | ' . $sub_response['score'];
147 $html .= ' points</p></div>';
148 $html_output .= $html;
149 }
150
151 return $html_output;
117 * Extract a set of stories from Hacker News API and format in HTML
118 *
119 * @access public
120 * @param string $api_url The API endpoint to use for extraction
121 * @param string $inline_title The <h1> title to use in the HTML
122 * @return string $html_output The formatted HTML result of stories from the API
123 * @author cmc <hello@cleberg.net>
124 */
125function get_stories(string $api_url, string $inline_title): string
126{
127 $response_raw = file_get_contents($api_url);
128 if ($response_raw == "null") {
129 return '<p>ERROR: Stories not found. API returned `null`.</p>';
130 } else {
131 $response = json_decode($response_raw, true);
132 }
133
134 $html_output = '<h1>' . $inline_title . '</h1>';
135
136 for ($i = 0; $i < count($response); $i++) {
137 $sub_url = 'https://hacker-news.firebaseio.com/v0/item/' . $response[$i] . '.json';
138 $sub_response_raw = file_get_contents($sub_url);
139 $sub_response = json_decode($sub_response_raw, true);
140
141 // TODO: Can this be converted to a heredoc string with variables?
142 $html = '<div><a href="' . $sub_response['url'] . '">' . $sub_response['title'] . '</a>';
143 $html .= '<p><time datetime="' . date('Y-m-d h:m:s', $sub_response['time']) . '">';
144 $html .= date('Y-m-d h:m:s', $sub_response['time']) . '</time> by <a';
145 $html .= ' href="/user/' . $sub_response['by'] . '">';
146 $html .= $sub_response['by'] . '</a> | ' . $sub_response['score'];
147 $html .= ' points</p></div>';
148 $html_output .= $html;
149 }
150
151 return $html_output;
152152}
153153
154154/**
155*Extract a user's profile from Hacker News API and format in HTML
156*
157* @access public
158* @author cmc <hello@cleberg.net>
159* @param string $api_url The API endpoint to use for extraction
160* @param string $inline_title The <h1> title to use in the HTML
161* @return string $html_output The formatted HTML result of stories from the API
162*/
163function get_user(string $api_url, string $inline_title) {
164 $response_raw = file_get_contents($api_url);
165 if (is_null($response_raw) || $response_raw == "null") {
166 $html_output .= '<p>ERROR: User not found.</p>';
167 return $html_output;
168 } else {
169 $response = json_decode($response_raw, true);
170 }
171
172 // TODO: Can this be converted to a heredoc string with variables?
173 $html_output = '<h1>' . $inline_title . '</h1>';
174 $html_output .= '<p>About: ' . $response['about'] . '</p>';
175 $html_output .= '<p>Karma: ' . $response['karma'] . '</p>';
176 $html_output .= '<p>Created: <time datetime="' . date('Y-m-d h:m:s', $response['created']) . '>' . date('Y-m-d h:m:s', $response['created']) . '</time></p>';
177 $html_output .= '<p>Recently Submitted Posts:</p>';
178
179 $limit = count($response['submitted']) > 10 ? 10 : count($response['submitted']);
180 if (count($response['submitted']) > 0) {
181 for ($i = 0; $i < $limit; $i++) {
182 $sub_url = 'https://hacker-news.firebaseio.com/v0/item/' . $response['submitted'][$i] . '.json';
183 $sub_response_raw = file_get_contents($sub_url);
184 $sub_response = json_decode($sub_response_raw, true);
185
186 if ($sub_response['type'] == 'story' || $sub_response['type'] == 'job') {
187 $html = '<div><a href="' . $sub_response['url'] . '">' . $sub_response['title'] . '</a>';
188 $html .= '<p><time datetime="' . date('Y-m-d h:m:s', $sub_response['time']) . '">';
189 $html .= date('Y-m-d h:m:s', $sub_response['time']) . '</time> by <a';
190 $html .= ' href="/user/'. $sub_response['by'] . '">';
191 $html .= $sub_response['by'] . '</a> | ' . $sub_response['score'];
192 $html .= ' points</p></div>';
193 } elseif ($sub_response['type'] == 'poll') {
194 // TODO: Handle polls
195 $html = 'TODO: Add logic to handle polls here.';
196 } else {
197 // TODO: Add link to parent with $sub_response['parent']
198 $html = '<div><time datetime="' . date('Y-m-d h:m:s', $sub_response['time']);
199 $html .= '">' . date('Y-m-d h:m:s', $sub_response['time']);
200 $html .= '</time><br><p>' . $sub_response['text'] . '</p></div>';
201 }
202 $html_output .= $html;
203 }
204 } else {
205 $html_output .= '<p>User has no subsmissions.</p>';
206 }
207
208 return $html_output;
155 *Extract a user's profile from Hacker News API and format in HTML
156 *
157 * @access public
158 * @param string $api_url The API endpoint to use for extraction
159 * @param string $inline_title The <h1> title to use in the HTML
160 * @return string $html_output The formatted HTML result of stories from the API
161 * @author cmc <hello@cleberg.net>
162 */
163function get_user(string $api_url, string $inline_title): string
164{
165 $response_raw = file_get_contents($api_url);
166 if ($response_raw == "null") {
167 return '<p>ERROR: User not found.</p>';
168 } else {
169 $response = json_decode($response_raw, true);
170 }
171
172 // TODO: Can this be converted to a heredoc string with variables?
173 $html_output = '<h1>' . $inline_title . '</h1>';
174 $html_output .= '<p>About: ' . $response['about'] . '</p>';
175 $html_output .= '<p>Karma: ' . $response['karma'] . '</p>';
176 $html_output .= '<p>Created: <time datetime="' . date('Y-m-d h:m:s', $response['created']) . '>' . date('Y-m-d h:m:s', $response['created']) . '</time></p>';
177 $html_output .= '<p>Recently Submitted Posts:</p>';
178
179 $limit = count($response['submitted']) > 10 ? 10 : count($response['submitted']);
180 if (count($response['submitted']) > 0) {
181 for ($i = 0; $i < $limit; $i++) {
182 $sub_url = 'https://hacker-news.firebaseio.com/v0/item/' . $response['submitted'][$i] . '.json';
183 $sub_response_raw = file_get_contents($sub_url);
184 $sub_response = json_decode($sub_response_raw, true);
185
186 if ($sub_response['type'] == 'story' || $sub_response['type'] == 'job') {
187 $html = '<div><a href="' . $sub_response['url'] . '">' . $sub_response['title'] . '</a>';
188 $html .= '<p><time datetime="' . date('Y-m-d h:m:s', $sub_response['time']) . '">';
189 $html .= date('Y-m-d h:m:s', $sub_response['time']) . '</time> by <a';
190 $html .= ' href="/user/' . $sub_response['by'] . '">';
191 $html .= $sub_response['by'] . '</a> | ' . $sub_response['score'];
192 $html .= ' points</p></div>';
193 } elseif ($sub_response['type'] == 'poll') {
194 // TODO: Handle polls
195 $html = 'TODO: Add logic to handle polls here.';
196 } else {
197 // TODO: Add link to parent with $sub_response['parent']
198 $html = '<div><time datetime="' . date('Y-m-d h:m:s', $sub_response['time']);
199 $html .= '">' . date('Y-m-d h:m:s', $sub_response['time']);
200 $html .= '</time><br><p>' . $sub_response['text'] . '</p></div>';
201 }
202 $html_output .= $html;
203 }
204 } else {
205 $html_output .= '<p>User has no submissions.</p>';
206 }
207
208 return $html_output;
209209}
210210
211211
212212/**
213* Send formatted HTML results to the user via a template
214*
215* @access public
216* @author cmc <hello@cleberg.net>
217* @param string $page_url Canoncial URL for HTML header
218* @param string $page_description Page description for HTML header
219* @param string $page_title Page title for HTML header
220* @param string $page_content Page content to display in <main>
221*/
222function echo_html(string $page_url, string $page_description, string $page_title, string $page_content) {
223 include_once 'src/View/class-template.php';
224
225 $template = new HN\View\Template(
226 $page_url,
227 $page_description,
228 $page_title,
229 $page_content
230 );
231
232 $template->echo_template();
213 * Send formatted HTML results to the user via a template
214 *
215 * @access public
216 * @param string $page_url Canonical URL for HTML header
217 * @param string $page_description Page description for HTML header
218 * @param string $page_title Page title for HTML header
219 * @param string $page_content Page content to display in <main>
220 * @author cmc <hello@cleberg.net>
221 */
222function echo_html(string $page_url, string $page_description, string $page_title, string $page_content)
223{
224 include_once 'src/View/class-template.php';
225
226 $template = new HN\View\Template(
227 $page_url,
228 $page_description,
229 $page_title,
230 $page_content
231 );
232
233 $template->echo_template();
233234}
234235
235236// EOF