Convert @ to : in parameter names
- Still more to do; possible connection exhaustion
This commit is contained in:
parent
7231a95fca
commit
3a31aca467
4
src/composer.lock
generated
4
src/composer.lock
generated
|
@ -12,7 +12,7 @@
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.bitbadger.solutions/bit-badger/pdo-document",
|
"url": "https://git.bitbadger.solutions/bit-badger/pdo-document",
|
||||||
"reference": "afc5d8009507a297c8169be93aee1085e652eedc"
|
"reference": "bcca9f5ace2ba32c24412e284ff4789480d9619d"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
"Test\\Integration\\": "./tests/integration"
|
"Test\\Integration\\": "./tests/integration"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"time": "2024-06-04T12:10:57+00:00"
|
"time": "2024-06-05T02:36:58+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "netresearch/jsonmapper",
|
"name": "netresearch/jsonmapper",
|
||||||
|
|
|
@ -83,12 +83,13 @@ class Data
|
||||||
/**
|
/**
|
||||||
* Create a JSON field comparison to find bookmarked items
|
* Create a JSON field comparison to find bookmarked items
|
||||||
*
|
*
|
||||||
|
* @param bool $value The flag to set (optional; defaults to true)
|
||||||
* @param string $qualifier The table qualifier to include (optional; defaults to no qualifier)
|
* @param string $qualifier The table qualifier to include (optional; defaults to no qualifier)
|
||||||
* @return Field A field that will find bookmarked items
|
* @return Field A field that will find bookmarked items
|
||||||
*/
|
*/
|
||||||
public static function bookmarkField(string $qualifier = ''): Field
|
public static function bookmarkField(bool $value = true, string $qualifier = ''): Field
|
||||||
{
|
{
|
||||||
$bookField = Field::EQ('is_bookmarked', 1, '@book');
|
$bookField = Field::EQ('is_bookmarked', ($value ? 1 : 0), ':book');
|
||||||
$bookField->qualifier = $qualifier;
|
$bookField->qualifier = $qualifier;
|
||||||
return $bookField;
|
return $bookField;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +103,7 @@ class Data
|
||||||
*/
|
*/
|
||||||
public static function feedField(int $feedId, string $qualifier = ''): Field
|
public static function feedField(int $feedId, string $qualifier = ''): Field
|
||||||
{
|
{
|
||||||
$feedField = Field::EQ(Configuration::$idField, $feedId, '@feed');
|
$feedField = Field::EQ(Configuration::$idField, $feedId, ':feed');
|
||||||
$feedField->qualifier = $qualifier;
|
$feedField->qualifier = $qualifier;
|
||||||
return $feedField;
|
return $feedField;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +116,7 @@ class Data
|
||||||
*/
|
*/
|
||||||
public static function unreadField(string $qualifier = ''): Field
|
public static function unreadField(string $qualifier = ''): Field
|
||||||
{
|
{
|
||||||
$readField = Field::EQ('is_read', 0, '@read');
|
$readField = Field::EQ('is_read', 0, ':read');
|
||||||
$readField->qualifier = $qualifier;
|
$readField->qualifier = $qualifier;
|
||||||
return $readField;
|
return $readField;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +129,7 @@ class Data
|
||||||
*/
|
*/
|
||||||
public static function userIdField(string $qualifier = ''): Field
|
public static function userIdField(string $qualifier = ''): Field
|
||||||
{
|
{
|
||||||
$userField = Field::EQ('user_id', $_SESSION[Key::USER_ID], '@user');
|
$userField = Field::EQ('user_id', $_SESSION[Key::USER_ID], ':user');
|
||||||
$userField->qualifier = $qualifier;
|
$userField->qualifier = $qualifier;
|
||||||
return $userField;
|
return $userField;
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,25 +116,25 @@ class Feed
|
||||||
return ['error' => 'Unrecognized purge type ' . PURGE_TYPE];
|
return ['error' => 'Unrecognized purge type ' . PURGE_TYPE];
|
||||||
}
|
}
|
||||||
|
|
||||||
$fields = [Field::EQ('feed_id', $feedId, '@feed'), Field::EQ('is_bookmarked', 0, '@book')];
|
$fields = [Field::EQ('feed_id', $feedId, ':feed'), Data::bookmarkField(false)];
|
||||||
$sql = Query\Delete::byFields(Table::ITEM, $fields);
|
$sql = Query\Delete::byFields(Table::ITEM, $fields);
|
||||||
if (PURGE_TYPE == self::PURGE_READ) {
|
if (PURGE_TYPE == self::PURGE_READ) {
|
||||||
$readField = Field::EQ('is_read', 1, '@read');
|
$readField = Field::EQ('is_read', 1, ':read');
|
||||||
$fields[] = $readField;
|
$fields[] = $readField;
|
||||||
$sql .= ' AND ' . Query::whereByFields([$readField]);
|
$sql .= ' AND ' . Query::whereByFields([$readField]);
|
||||||
} elseif (PURGE_TYPE == self::PURGE_BY_DAYS) {
|
} elseif (PURGE_TYPE == self::PURGE_BY_DAYS) {
|
||||||
$fields[] = Field::EQ('', Data::formatDate('-' . PURGE_NUMBER . ' day'), '@oldest');
|
$fields[] = Field::EQ('', Data::formatDate('-' . PURGE_NUMBER . ' day'), ':oldest');
|
||||||
$sql .= " AND date(coalesce(data->>'updated_on', data->>'published_on)) < date(@oldest)";
|
$sql .= " AND date(coalesce(data->>'updated_on', data->>'published_on)) < date(:oldest)";
|
||||||
} elseif (PURGE_TYPE == self::PURGE_BY_COUNT) {
|
} elseif (PURGE_TYPE == self::PURGE_BY_COUNT) {
|
||||||
$fields[] = Field::EQ('', PURGE_NUMBER, '@keep');
|
$fields[] = Field::EQ('', PURGE_NUMBER, ':keep');
|
||||||
$id = Configuration::$idField;
|
$id = Configuration::$idField;
|
||||||
$table = Table::ITEM;
|
$table = Table::ITEM;
|
||||||
$sql .= ' ' . <<<SQL
|
$sql .= ' ' . <<<SQL
|
||||||
AND data->>'$id' IN (
|
AND data->>'$id' IN (
|
||||||
SELECT data->>'$id' FROM $table
|
SELECT data->>'$id' FROM $table
|
||||||
WHERE data->>'feed_id' = @feed
|
WHERE data->>'feed_id' = :feed
|
||||||
ORDER BY date(coalesce(data->>'updated_on', data->>'published_on')) DESC
|
ORDER BY date(coalesce(data->>'updated_on', data->>'published_on')) DESC
|
||||||
LIMIT -1 OFFSET @keep
|
LIMIT -1 OFFSET :keep
|
||||||
)
|
)
|
||||||
SQL;
|
SQL;
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,7 @@ class Feed
|
||||||
|
|
||||||
Document::insert(Table::FEED, self::fromParsed($feed), $pdo);
|
Document::insert(Table::FEED, self::fromParsed($feed), $pdo);
|
||||||
|
|
||||||
$doc = Find::firstByFields(Table::FEED, $fields, self::class);
|
$doc = Find::firstByFields(Table::FEED, $fields, static::class);
|
||||||
if (!$doc) return ['error' => 'Could not retrieve inserted feed'];
|
if (!$doc) return ['error' => 'Could not retrieve inserted feed'];
|
||||||
|
|
||||||
$result = self::updateItems($doc->id, $feed, date_create_immutable(WWW_EPOCH), $pdo);
|
$result = self::updateItems($doc->id, $feed, date_create_immutable(WWW_EPOCH), $pdo);
|
||||||
|
|
|
@ -58,7 +58,7 @@ class ItemList
|
||||||
try {
|
try {
|
||||||
$this->dbList = Custom::list(
|
$this->dbList = Custom::list(
|
||||||
ItemWithFeed::SELECT_WITH_FEED . ' WHERE '
|
ItemWithFeed::SELECT_WITH_FEED . ' WHERE '
|
||||||
. Query::whereByFields(array_filter($allFields, fn($it) => $it->paramName <> '@search'))
|
. Query::whereByFields(array_filter($allFields, fn($it) => $it->paramName <> ':search'))
|
||||||
. $searchWhere,
|
. $searchWhere,
|
||||||
Parameters::addFields($allFields, []), new DocumentMapper(ItemWithFeed::class));
|
Parameters::addFields($allFields, []), new DocumentMapper(ItemWithFeed::class));
|
||||||
} catch (DocumentException $ex) {
|
} catch (DocumentException $ex) {
|
||||||
|
@ -73,7 +73,7 @@ class ItemList
|
||||||
*/
|
*/
|
||||||
public static function allBookmarked(): static
|
public static function allBookmarked(): static
|
||||||
{
|
{
|
||||||
$list = new static('Bookmarked', '/?bookmarked', [Data::bookmarkField(Table::ITEM)]);
|
$list = new static('Bookmarked', '/?bookmarked', [Data::bookmarkField(qualifier: Table::ITEM)]);
|
||||||
$list->linkFeed = true;
|
$list->linkFeed = true;
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ class ItemList
|
||||||
public static function bookmarkedForFeed(int $feedId): static
|
public static function bookmarkedForFeed(int $feedId): static
|
||||||
{
|
{
|
||||||
return new static('Bookmarked', "/feed/items?id=$feedId&bookmarked",
|
return new static('Bookmarked', "/feed/items?id=$feedId&bookmarked",
|
||||||
[Data::feedField($feedId, Table::FEED), Data::bookmarkField(Table::ITEM)]);
|
[Data::feedField($feedId, Table::FEED), Data::bookmarkField(qualifier: Table::ITEM)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -136,12 +136,12 @@ class ItemList
|
||||||
*/
|
*/
|
||||||
public static function matchingSearch(string $search, bool $isBookmarked): static
|
public static function matchingSearch(string $search, bool $isBookmarked): static
|
||||||
{
|
{
|
||||||
$fields = [Field::EQ('content', $search, '@search')];
|
$fields = [Field::EQ('content', $search, ':search')];
|
||||||
if ($isBookmarked) $fields[] = Data::bookmarkField(Table::ITEM);
|
if ($isBookmarked) $fields[] = Data::bookmarkField(qualifier: Table::ITEM);
|
||||||
$list = new static('Matching' . ($isBookmarked ? ' Bookmarked' : ''),
|
$list = new static('Matching' . ($isBookmarked ? ' Bookmarked' : ''),
|
||||||
"/search?search=$search&items=" . ($isBookmarked ? 'bookmarked' : 'all'), $fields,
|
"/search?search=$search&items=" . ($isBookmarked ? 'bookmarked' : 'all'), $fields,
|
||||||
' AND ' . Table::ITEM . ".data->>'" . Configuration::$idField . "' IN "
|
' AND ' . Table::ITEM . ".data->>'" . Configuration::$idField . "' IN "
|
||||||
. '(SELECT ROWID FROM item_search WHERE content MATCH @search)');
|
. '(SELECT ROWID FROM item_search WHERE content MATCH :search)');
|
||||||
$list->showIndicators = true;
|
$list->showIndicators = true;
|
||||||
$list->displayFeed = true;
|
$list->displayFeed = true;
|
||||||
return $list;
|
return $list;
|
||||||
|
|
|
@ -36,9 +36,9 @@ class ItemWithFeed extends Item
|
||||||
*/
|
*/
|
||||||
private static function idAndUserFields(int $id): array
|
private static function idAndUserFields(int $id): array
|
||||||
{
|
{
|
||||||
$idField = Field::EQ(Configuration::$idField, $id, '@id');
|
$idField = Field::EQ(Configuration::$idField, $id, ':id');
|
||||||
$idField->qualifier = Table::ITEM;
|
$idField->qualifier = Table::ITEM;
|
||||||
$userField = Field::EQ('user_id', $_SESSION[Key::USER_ID], '@user');
|
$userField = Field::EQ('user_id', $_SESSION[Key::USER_ID], ':user');
|
||||||
$userField->qualifier = Table::FEED;
|
$userField->qualifier = Table::FEED;
|
||||||
return [$idField, $userField];
|
return [$idField, $userField];
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ class User
|
||||||
*/
|
*/
|
||||||
public static function hasBookmarks(): bool
|
public static function hasBookmarks(): bool
|
||||||
{
|
{
|
||||||
$fields = [Data::userIdField(Table::FEED), Data::bookmarkField(Table::ITEM)];
|
$fields = [Data::userIdField(Table::FEED), Data::bookmarkField(true, Table::ITEM)];
|
||||||
return Custom::scalar(Query\Exists::query(ItemWithFeed::FROM_WITH_JOIN, Query::whereByFields($fields)),
|
return Custom::scalar(Query\Exists::query(ItemWithFeed::FROM_WITH_JOIN, Query::whereByFields($fields)),
|
||||||
Parameters::addFields($fields, []), new ExistsMapper());
|
Parameters::addFields($fields, []), new ExistsMapper());
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,33 +19,31 @@ include '../start.php';
|
||||||
|
|
||||||
FeedReaderCentral\Security::verifyUser();
|
FeedReaderCentral\Security::verifyUser();
|
||||||
|
|
||||||
$field = Field::EQ('user_id', $_SESSION[Key::USER_ID], '@user');
|
$field = Field::EQ('user_id', $_SESSION[Key::USER_ID], ':user');
|
||||||
$feeds = Custom::list(Query\Find::byFields(Table::FEED, [$field]) . " ORDER BY lower(data->>'title')",
|
$feeds = Custom::list(Query\Find::byFields(Table::FEED, [$field]) . " ORDER BY lower(data->>'title')",
|
||||||
$field->appendParameter([]), new DocumentMapper(Feed::class));
|
$field->appendParameter([]), new DocumentMapper(Feed::class));
|
||||||
|
|
||||||
page_head('Your Feeds'); ?>
|
page_head('Your Feeds');
|
||||||
<h1>Your Feeds</h1>
|
echo '<h1>Your Feeds</h1><article><p class=action_buttons>' . hx_get('/feed/?id=new', 'Add Feed') . '</p>';
|
||||||
<article>
|
foreach ($feeds->items() as /** @var Feed $feed */ $feed) {
|
||||||
<p class=action_buttons><?=hx_get('/feed/?id=new', 'Add Feed')?></p><?php
|
|
||||||
foreach ($feeds->items() as /** @var Feed $feed */ $feed) {
|
|
||||||
$item = Table::ITEM;
|
$item = Table::ITEM;
|
||||||
$counts = Custom::single(<<<SQL
|
$counts = Custom::single(<<<SQL
|
||||||
SELECT (SELECT COUNT(*) FROM $item WHERE data->>'feed_id' = @feed) AS total,
|
SELECT (SELECT COUNT(*) FROM $item WHERE data->>'feed_id' = :feed) AS total,
|
||||||
(SELECT COUNT(*) FROM $item WHERE data->>'feed_id' = @feed AND data->>'is_read' = '0') AS unread,
|
(SELECT COUNT(*) FROM $item WHERE data->>'feed_id' = :feed AND data->>'is_read' = 0) AS unread,
|
||||||
(SELECT COUNT(*) FROM $item WHERE data->>'feed_id' = @feed AND data->>'is_bookmarked' = '1') AS marked
|
(SELECT COUNT(*) FROM $item WHERE data->>'feed_id' = :feed AND data->>'is_bookmarked' = 1) AS marked
|
||||||
SQL, ['@feed' => $feed->id], new ArrayMapper()) ?? ['total' => 0, 'unread' => 0, 'marked' => 0]; ?>
|
SQL, [':feed' => $feed->id], new ArrayMapper()) ?? ['total' => 0, 'unread' => 0, 'marked' => 0];
|
||||||
<p><strong><?=htmlentities($feed->title)?></strong><br>
|
echo '<p><strong>' . htmlentities($feed->title) . '</strong><br>'
|
||||||
<span class=meta><em>Last Updated <?=date_time($feed->updated_on)?> •
|
. '<span class=meta><em>Last Updated ' . date_time($feed->updated_on) . ' • '
|
||||||
As of <?=date_time($feed->checked_on)?></em><br>
|
. 'As of ' . date_time($feed->checked_on) . '</em><br>' . hx_get("/feed/?id=$feed->id", 'Edit') . ' • '
|
||||||
<?=hx_get("/feed/?id=$feed->id", 'Edit')?> • Read
|
. 'Read ' . ($counts['unread'] > 0 ? hx_get("/feed/items?id=$feed->id&unread", 'Unread') : 'Unread')
|
||||||
<?=$counts['unread'] > 0 ? hx_get("/feed/items?id=$feed->id&unread", 'Unread') : 'Unread'?>
|
. " ({$counts['unread']}) | "
|
||||||
(<?=$counts['unread']?>) |
|
. ($counts['total'] > 0 ? hx_get("/feed/items?id=$feed->id", 'All') : 'All') . " ({$counts['total']}) | "
|
||||||
<?=$counts['total'] > 0 ? hx_get("/feed/items?id=$feed->id", 'All') : 'All'?> (<?=$counts['total']?>) |
|
. ($counts['marked'] > 0 ? hx_get("/feed/items?id=$feed->id&bookmarked", 'Bookmarked') : 'Bookmarked')
|
||||||
<?=$counts['marked'] > 0 ? hx_get("/feed/items?id=$feed->id&bookmarked", 'Bookmarked') : 'Bookmarked'?>
|
. " ({$counts['marked']}) • "
|
||||||
(<?=$counts['marked']?>) •
|
. "<a href=/feed/?id=$feed->id hx-delete=/feed/?id=$feed->id "
|
||||||
<a href=/feed/?id=<?=$feed->id?> hx-delete=/feed/?id=<?=$feed->id?>
|
. ' hx-confirm="Are you sure you want to delete “' . htmlspecialchars($feed->title)
|
||||||
hx-confirm="Are you sure you want to delete “<?=htmlspecialchars($feed->title)?>”? This will remove the feed and all its items, including unread and bookmarked.">Delete</a>
|
. '”? This will remove the feed and all its items, including unread and bookmarked.">Delete</a>'
|
||||||
</span><?php
|
. '</span>';
|
||||||
} ?>
|
}
|
||||||
</article><?php
|
echo '</article>';
|
||||||
page_foot();
|
page_foot();
|
||||||
|
|
|
@ -21,6 +21,7 @@ if (key_exists('refresh', $_GET)) {
|
||||||
add_error(nl2br($refreshResult['error']));
|
add_error(nl2br($refreshResult['error']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//const PDO_DOC_DEBUG_SQL = true;
|
||||||
|
|
||||||
$list = match (true) {
|
$list = match (true) {
|
||||||
key_exists('bookmarked', $_GET) => ItemList::allBookmarked(),
|
key_exists('bookmarked', $_GET) => ItemList::allBookmarked(),
|
||||||
|
|
|
@ -12,7 +12,7 @@ session_start([
|
||||||
'cookie_httponly' => true,
|
'cookie_httponly' => true,
|
||||||
'cookie_samesite' => 'Strict']);
|
'cookie_samesite' => 'Strict']);
|
||||||
|
|
||||||
//const DOC_DEBUG_SQL = true;
|
//const PDO_DOC_DEBUG_SQL = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a message to be displayed at the top of the page
|
* Add a message to be displayed at the top of the page
|
||||||
|
|
|
@ -16,6 +16,8 @@ require __DIR__ . '/../cli-start.php';
|
||||||
|
|
||||||
cli_title('DATABASE UPDATE');
|
cli_title('DATABASE UPDATE');
|
||||||
|
|
||||||
|
//const PDO_DOC_DEBUG_SQL = true;
|
||||||
|
|
||||||
if ($argc < 2) display_help();
|
if ($argc < 2) display_help();
|
||||||
|
|
||||||
switch ($argv[1]) {
|
switch ($argv[1]) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user