Commit 64cd6680e2

64cd6680e21d613609d423e55bd39249d38626f8

parent: 180f43bdcf

Unsigned

cmc <hello@cleberg.net> · 2023-06-15 14:07 UTC

add basic functionality to view items and discussions

Layout: unified · split

README.md +2 −1
@@ -81,7 +81,8 @@ A scratch pad of ideas that may be useful to implement:
81 81
82- [x] Add minimal CSS. 82- [x] Add minimal CSS.
83- [x] Add functionality to view a user's profile. 83- [x] Add functionality to view a user's profile.
84- [ ] Add functionality to view item-specific page with comments (`ConstructStoryDiscussion`). 84- [x] Add functionality to view item-specific page with comments (`ConstructStoryDiscussion`).
85 - [ ] Load recursive descendant threads.
85- [ ] Add functionality to handle polls (`ConstructPoll` & `ConstructPollOpt`). 86- [ ] Add functionality to handle polls (`ConstructPoll` & `ConstructPollOpt`).
86- [ ] Add functionality to load more items or paginate. 87- [ ] Add functionality to load more items or paginate.
87 88
src/Controller/RouteController.php +1 −2
@@ -156,8 +156,7 @@ class RouteController
156 ParseItem( 156 ParseItem(
157 GetApiResults( 157 GetApiResults(
158 'https://hacker-news.firebaseio.com/v0/item/' . $elements[0] . '.json' 158 'https://hacker-news.firebaseio.com/v0/item/' . $elements[0] . '.json'
159 ), 159 )
160 'Item: ' . $elements[0]
161 ) 160 )
162 ); 161 );
163 162
src/Model/ApiService.php +82 −17
@@ -54,9 +54,9 @@ function ParseUser(mixed $api_results, string $inline_title): string
54 if ($api_results == "null") { 54 if ($api_results == "null") {
55 return '<p>ERROR: User not found.</p>'; 55 return '<p>ERROR: User not found.</p>';
56 } else { 56 } else {
57 // TODO: Create function to format $about using the following guidelines 57 // TODO: Create function to format $about using the following guidelines
58 // : https://news.ycombinator.com/formatdoc 58 // : https://news.ycombinator.com/formatdoc
59 // : hint: nl2br() will solve the first formatting requirement 59 // : hint: nl2br() will solve the first formatting requirement
60 $about = $api_results['about']; 60 $about = $api_results['about'];
61 $karma = $api_results['karma']; 61 $karma = $api_results['karma'];
62 $created = date('Y-m-d h:m:s', $api_results['created']); 62 $created = date('Y-m-d h:m:s', $api_results['created']);
@@ -96,11 +96,33 @@ function ParseUser(mixed $api_results, string $inline_title): string
96 * @return string $html_output The formatted HTML result of stories from the API or the error message 96 * @return string $html_output The formatted HTML result of stories from the API or the error message
97 * @author cmc <hello@cleberg.net> 97 * @author cmc <hello@cleberg.net>
98 */ 98 */
99function ParseItem(mixed $api_results, string $inline_title): string 99function ParseItem(mixed $api_results): string
100{ 100{
101 // TODO: Need to create a page specifially for /item/ requests 101 if ($api_results == "null") {
102 // TODO: Use the GetItem() and Construct*() functions below, then output in it's own page - possibly with a single parent and descendat, if exist 102 return '<p>ERROR: User not found.</p>';
103 return 'TODO'; 103 } else {
104 $html_output = '';
105
106 if (in_array($api_results['type'], array("job", "story", "poll", "pollopt"))) {
107 $html_output .= ConstructStoryDiscussion($api_results);
108 } else {
109 if (array_key_exists('parent', $api_results)) {
110 $parent_api_results = GetApiResults('https://hacker-news.firebaseio.com/v0/item/' . $api_results['parent'] . '.json');
111 $html_output .= GetItem($parent_api_results);
112 $html_output .= '<hr>';
113 }
114
115 $html_output .= GetItem($api_results);
116
117 if ($api_results['descendants'] != 0) {
118 $html_output .= '<hr>';
119 $child_api_results = GetApiResults('https://hacker-news.firebaseio.com/v0/item/' . $api_results['kids'][0] . '.json');
120 $html_output .= GetItem($child_api_results);
121 }
122 }
123
124 return $html_output;
125 }
104} 126}
105 127
106 128
@@ -121,7 +143,7 @@ function GetItem(mixed $api_results): string
121 'comment' => ConstructComment($api_results), 143 'comment' => ConstructComment($api_results),
122 'poll' => ConstructPoll($api_results), 144 'poll' => ConstructPoll($api_results),
123 'pollopt' => ConstructPollOpt($api_results), 145 'pollopt' => ConstructPollOpt($api_results),
124 default => 'ERROR: Item type not found.', 146 default => '[ERROR] Item type not found: ' . $type,
125 }; 147 };
126} 148}
127 149
@@ -142,7 +164,11 @@ function ConstructStory(mixed $api_results): string
142 $time = date('Y-m-d h:m:s', $api_results['time']); 164 $time = date('Y-m-d h:m:s', $api_results['time']);
143 $by = $api_results['by']; 165 $by = $api_results['by'];
144 $score = $api_results['score']; 166 $score = $api_results['score'];
145 $descendants = $api_results['descendants']; 167 if (array_key_exists('descendants', $api_results)) {
168 $descendants = $api_results['descendants'];
169 } else {
170 $descendants = 'No';
171 }
146 172
147 return <<<EOT 173 return <<<EOT
148 <div class="story"> 174 <div class="story">
@@ -161,14 +187,52 @@ function ConstructStory(mixed $api_results): string
161 * Creates a story discussion page with comments 187 * Creates a story discussion page with comments
162 * 188 *
163 * @access public 189 * @access public
190 * @param mixed $api_results The decoded API results
164 * @return string The formatted HTML result of stories from the API or the error message 191 * @return string The formatted HTML result of stories from the API or the error message
165 * @author cmc <hello@cleberg.net> 192 * @author cmc <hello@cleberg.net>
166 */ 193 */
167function ConstructStoryDiscussion(): string 194function ConstructStoryDiscussion(mixed $api_results): string
168{ 195{
169 // TODO: Create discussion page, using mostly the same details as ConstructStory - except you need to check for $api_results['text'] to see if the poster left text in addition to the link. 196 $id = $api_results['id'];
170 // : Also need to show comments (at least a list of top level ones to start) 197 $url = $api_results['url'];
171 return 'TODO'; 198 $title = $api_results['title'];
199 $time = date('Y-m-d h:m:s', $api_results['time']);
200 $by = $api_results['by'];
201 $score = $api_results['score'];
202 $descendants = $api_results['descendants'];
203 if (array_key_exists('text', $api_results)) {
204 $text = $api_results['text'];
205 } else {
206 $text = '';
207 }
208
209 $html_output = <<<EOT
210 <div class="story-discussion">
211 <h1><a href="$url" target="_blank" rel="noopener">$title</a></h1>
212 <p>
213 <time datetime="$time">$time</time>
214 by <a href="/user/$by/">$by</a>
215 | $score points
216 | <a href="/item/$id">$descendants comments</a>
217 </p>
218 <p>$text</p>
219 </div>
220 EOT;
221
222 // TODO: Add support for more than just top-level kids (i.e., recursive).
223 if ($api_results['descendants'] != 0) {
224 $html_output .= <<<EOT
225 <div class="story-discussion-comments">
226 <h2>Comments</h2>
227 EOT;
228 for ($i = 0; $i < count($api_results['kids']); $i++) {
229 $child_api_results = GetApiResults('https://hacker-news.firebaseio.com/v0/item/' . $api_results['kids'][$i] . '.json');
230 $html_output .= GetItem($child_api_results);
231 }
232 $html_output .= '</div>';
233 }
234
235 return $html_output;
172} 236}
173 237
174/** 238/**
@@ -179,17 +243,18 @@ function ConstructStoryDiscussion(): string
179 * @return string The formatted HTML result of stories from the API or the error message 243 * @return string The formatted HTML result of stories from the API or the error message
180 * @author cmc <hello@cleberg.net> 244 * @author cmc <hello@cleberg.net>
181 */ 245 */
182function ConstructComment($api_results): string 246function ConstructComment(mixed $api_results): string
183{ 247{
184 $time = date('Y-m-d h:m:s', $api_results['time']); 248 $time = date('Y-m-d h:m:s', $api_results['time']);
185 $text = $api_results['text']; 249 $text = $api_results['text'];
250 $by = $api_results['by'];
186 $parent = $api_results['parent']; 251 $parent = $api_results['parent'];
187 252
188 return <<<EOT 253 return <<<EOT
189 <div class="comment"> 254 <div class="comment">
190 <p>$text</p> 255 <p>$text</p>
191 <p><i>Submitted in response to: <a href="/item/$parent/">$parent</a></i></p> 256 <p><i>Submitted in response to: <a href="/item/$parent/">$parent</a></i></p>
192 <time datetime="$time">$time</time> 257 <p><time datetime="$time">$time</time> by <a href="/user/$by/">$by</a></p>
193 </div> 258 </div>
194 EOT; 259 EOT;
195} 260}
@@ -202,7 +267,7 @@ function ConstructComment($api_results): string
202 * @return string The formatted HTML result of stories from the API or the error message 267 * @return string The formatted HTML result of stories from the API or the error message
203 * @author cmc <hello@cleberg.net> 268 * @author cmc <hello@cleberg.net>
204 */ 269 */
205function ConstructPoll($api_results): string 270function ConstructPoll(mixed $api_results): string
206{ 271{
207 return 'TODO'; 272 return 'TODO';
208} 273}
@@ -215,7 +280,7 @@ function ConstructPoll($api_results): string
215 * @return string The formatted HTML result of stories from the API or the error message 280 * @return string The formatted HTML result of stories from the API or the error message
216 * @author cmc <hello@cleberg.net> 281 * @author cmc <hello@cleberg.net>
217 */ 282 */
218function ConstructPollOpt($api_results): string 283function ConstructPollOpt(mixed $api_results): string
219{ 284{
220 return 'TODO'; 285 return 'TODO';
221} 286}