alpha1 #8
|
@ -36,10 +36,26 @@ header {
|
|||
}
|
||||
main {
|
||||
padding: 0 .5rem;
|
||||
|
||||
.item_heading {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.item_published {
|
||||
margin-bottom: 1rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
}
|
||||
article {
|
||||
max-width: 60rem;
|
||||
margin: auto;
|
||||
|
||||
.item_content {
|
||||
border: solid 1px navy;
|
||||
border-radius: .5rem;
|
||||
background-color: white;
|
||||
padding: .5rem;
|
||||
}
|
||||
}
|
||||
input[type=url], input[type=text] {
|
||||
width: 50%;
|
||||
|
@ -47,11 +63,27 @@ input[type=url], input[type=text] {
|
|||
padding: .25rem;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
button {
|
||||
button,
|
||||
.action_buttons a:link,
|
||||
.action_buttons a:visited {
|
||||
font-size: 1rem;
|
||||
font-weight: normal;
|
||||
background-color: navy;
|
||||
color: white;
|
||||
padding: .25rem 1rem;
|
||||
padding: .5rem 1rem;
|
||||
border-radius: .25rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
border: none;
|
||||
}
|
||||
button:hover,
|
||||
.action_buttons a:hover {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(navy, #000032);
|
||||
}
|
||||
.action_buttons {
|
||||
margin: 1rem 0;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
|
|
@ -24,14 +24,9 @@ page_head('Welcome'); ?>
|
|||
<h1>Your Unread Items</h1>
|
||||
<article><?php
|
||||
if ($item) {
|
||||
while ($item) {
|
||||
try {
|
||||
$asOf = (new DateTimeImmutable($item['as_of']))->format(DATE_TIME_FORMAT);
|
||||
} catch (Exception) {
|
||||
$asOf = '(invalid date)';
|
||||
} ?>
|
||||
<p><a href=/item/view?id=<?=$item['id']?>><?=htmlentities($item['item_title'])?></a><br>
|
||||
<?=htmlentities($item['feed_title'])?><br><small><em><?=$asOf?></em></small><?php
|
||||
while ($item) { ?>
|
||||
<p><a href=/item?id=<?=$item['id']?>><?=htmlentities($item['item_title'])?></a><br>
|
||||
<?=htmlentities($item['feed_title'])?><br><small><em><?=date_time($item['as_of'])?></em></small><?php
|
||||
$item = $result->fetchArray(SQLITE3_ASSOC);
|
||||
}
|
||||
} else { ?>
|
||||
|
|
79
src/public/item.php
Normal file
79
src/public/item.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Item View Page
|
||||
*
|
||||
* Retrieves and displays an item from a feed belonging to the current user
|
||||
*/
|
||||
|
||||
include '../start.php';
|
||||
|
||||
Security::verifyUser();
|
||||
|
||||
$db = Data::getConnection();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
// "Keep as New" button sends a POST request to reset the is_read flag before going back to the list of unread items
|
||||
$isValidQuery = $db->prepare(<<<'SQL'
|
||||
SELECT COUNT(*)
|
||||
FROM item INNER JOIN feed ON feed.id = item.feed_id
|
||||
WHERE item.id = :id AND feed.user_id = :user
|
||||
SQL);
|
||||
$isValidQuery->bindValue(':id', $_POST['id']);
|
||||
$isValidQuery->bindValue(':user', $_REQUEST[Key::USER_ID]);
|
||||
$isValidResult = $isValidQuery->execute();
|
||||
if ($isValidResult && $isValidResult->fetchArray(SQLITE3_NUM)[0] == 1) {
|
||||
$keepUnread = $db->prepare('UPDATE item SET is_read = 0 WHERE id = :id');
|
||||
$keepUnread->bindValue(':id', $_POST['id']);
|
||||
$keepUnread->execute();
|
||||
}
|
||||
$db->close();
|
||||
frc_redirect('/');
|
||||
}
|
||||
|
||||
$query = $db->prepare(<<<'SQL'
|
||||
SELECT item.title AS item_title, item.item_link, item.published_on, item.updated_on, item.content, item.is_encoded,
|
||||
feed.title AS feed_title
|
||||
FROM item INNER JOIN feed ON feed.id = item.feed_id
|
||||
WHERE item.id = :id
|
||||
AND feed.user_id = :user
|
||||
SQL);
|
||||
$query->bindValue(':id', $_GET['id']);
|
||||
$query->bindValue(':user', $_REQUEST[Key::USER_ID]);
|
||||
$result = $query->execute();
|
||||
$item = $result ? $result->fetchArray(SQLITE3_ASSOC) : false;
|
||||
|
||||
if ($item) {
|
||||
$markRead = $db->prepare('UPDATE item SET is_read = 1 WHERE id = :id');
|
||||
$markRead->bindValue(':id', $_GET['id']);
|
||||
$markRead->execute();
|
||||
}
|
||||
|
||||
$published = date_time($item['published_on']);
|
||||
$updated = isset($item['updated_on']) ? date_time($item['updated_on']) : null;
|
||||
$isEncoded = (bool) $item['is_encoded'];
|
||||
|
||||
page_head(htmlentities("{$item['item_title']} | {$item['feed_title']}")); ?>
|
||||
<h1 class=item_heading>
|
||||
<a href="<?=$item['item_link']?>" target=_blank rel=noopener><?=$item['item_title']?></a><br>
|
||||
</h1>
|
||||
<div class=item_published>
|
||||
From <strong><?=htmlentities($item['feed_title'])?></strong><br>
|
||||
Published <?=date_time($item['published_on'])?><?=$updated && $updated != $published ? " (Updated $updated)" : ''?>
|
||||
</div>
|
||||
<article>
|
||||
<div class=item_content><?php
|
||||
if ($isEncoded) {
|
||||
echo str_replace('<a ', '<a target=_blank rel=noopener ', $item['content']);
|
||||
} else {
|
||||
echo htmlentities($item['content']);
|
||||
} ?>
|
||||
</div>
|
||||
<form class=action_buttons action=/item method=POST>
|
||||
<input type=hidden name=id value=<?=$_GET['id']?>>
|
||||
<a href="/">Done</a>
|
||||
<button type=submit>Keep as New</button>
|
||||
</form>
|
||||
</article><?php
|
||||
page_foot();
|
||||
$db->close();
|
|
@ -49,6 +49,7 @@ function page_head(string $title): void {
|
|||
?><!DOCTYPE html>
|
||||
<html lang=en>
|
||||
<head>
|
||||
<meta name=viewport content="width=device-width, initial-scale=1">
|
||||
<title><?=$title?> | Feed Reader Central</title>
|
||||
<link href=/assets/style.css rel=stylesheet>
|
||||
</head>
|
||||
|
@ -79,3 +80,32 @@ function page_head(string $title): void {
|
|||
function page_foot(): void {
|
||||
?></main></body></html><?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect the user to the given URL
|
||||
*
|
||||
* @param string $value A local URL to which the user should be redirected
|
||||
*/
|
||||
function frc_redirect(string $value) {
|
||||
if (str_starts_with($value, 'http')) {
|
||||
http_response_code(400);
|
||||
die();
|
||||
}
|
||||
header("Location: $value");
|
||||
http_response_code(303);
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date/time string to a date/time in the configured format
|
||||
*
|
||||
* @param string $value The date/time string
|
||||
* @return string The standard format of a date/time, or '(invalid date)' if the date could not be parsed
|
||||
*/
|
||||
function date_time(string $value): string {
|
||||
try {
|
||||
return (new DateTimeImmutable($value))->format(DATE_TIME_FORMAT);
|
||||
} catch (Exception) {
|
||||
return '(invalid date)';
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user