From 3d25ad7de4fdbb3eba2cde2a62422e6be5d79a0a Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Tue, 25 Aug 2026 22:57:22 +0000
Subject: [PATCH] =It's been a minute. I went through the Routes and associated Managers and ensured they played together well. Reworked the Cache.php, and I think I caught all the references. Moving away from JVBase() root class, to individuall classes that are Instanced. Double checked for the ABSPATH check in every file, and added index.php to every directory that didn't already have it. Also still working on the MenuBlock to work with WooCommerce for now for Northeh
---
inc/managers/CustomTable.php | 94 +++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 87 insertions(+), 7 deletions(-)
diff --git a/inc/managers/CustomTable.php b/inc/managers/CustomTable.php
index 1a6719c..c8a9171 100644
--- a/inc/managers/CustomTable.php
+++ b/inc/managers/CustomTable.php
@@ -38,6 +38,8 @@
protected static string $termIDType;
protected static string $postIDType;
protected static string $postTable;
+ protected ?CustomTable $karmaTable = null;
+ protected ?CustomTable $favouritesTable = null;
protected Cache $cache;
@@ -73,6 +75,15 @@
return self::$instances[$tableName];
}
+ public function setKarma(CustomTable $karma):void
+ {
+ $this->karmaTable = $karma;
+ }
+ public function setFavourite(CustomTable $favourites):void
+ {
+ $this->favouritesTable = $favourites;
+ }
+
public function ensureDefined() {
$this->ensureUserTable();
$this->ensureUserIDType();
@@ -143,6 +154,11 @@
return $this;
}
+ public function getColumnKeys():array
+ {
+ return array_keys($this->columns);
+ }
+
/**
* @param array $keys An array of {string} $keys. If a $key is an array, you can define a custom $key => $value, example: 'UNIQUE' => $value, or 'PRIMARY' => $value
* @return $this
@@ -318,6 +334,26 @@
return $this;
}
+ public function orderByKarma(string $metric = 'karmic_score', string $direction = 'DESC'): self
+ {
+ if (!$this->karmaTable || !in_array($metric, ['upvotes', 'downvotes', 'karmic_score'])) {
+ return $this->orderBy('created_at');
+ }
+ $this->builder['orderby'] = $metric;
+ $this->builder['order'] = strtoupper($direction);
+ return $this;
+ }
+
+ public function orderByFavourites(string $direction = 'DESC'): self
+ {
+ if (!$this->favouritesTable) {
+ return $this->orderBy('created_at');
+ }
+ $this->builder['orderby'] = 'favourites_count';
+ $this->builder['order'] = strtoupper($direction);
+ return $this;
+ }
+
/**
* Set pagination
*
@@ -577,7 +613,7 @@
public function get(array $where, string $output = OBJECT): object|array|null
{
return $this->cache->remember(
- $this->cache->generateKey(array_merge(['output' => $output], $where)),
+ array_merge(['output' => $output], $where),
function() use ($where, $output) {
$query = "SELECT * FROM {$this->fullTableName}";
$where = $this->buildWhereClause($where);
@@ -607,7 +643,7 @@
public function getMany(array $args = [], bool $itemsOnly = true, string $output = OBJECT): array
{
$items = $this->cache->remember(
- $this->cache->generateKey(array_merge($args, ['output' => $output])),
+ array_merge($args, ['output' => $output]),
function () use ($args, $output) {
$query = "SELECT * FROM {$this->fullTableName}";
$values = [];
@@ -622,7 +658,7 @@
// ORDER BY
if (!empty($args['orderby'])) {
- $orderby = sanitize_sql_orderby($args['orderby']);
+ $orderby = $this->resolveOrderby($args['orderby']);
$order = (!empty($args['order']) && strtoupper($args['order']) === 'ASC') ? 'ASC' : 'DESC';
$query .= " ORDER BY {$orderby} {$order}";
}
@@ -664,6 +700,26 @@
];
}
+ protected function resolveOrderby(string $orderby):string
+ {
+ $orderby = strtolower($orderby);
+ if (in_array($orderby, ['upvotes', 'downvotes', 'karmic_score']) && $this->karmaTable) {
+ $tableName = $this->karmaTable->getFullTableName();
+ return match ($orderby) {
+ 'upvotes' => "(SELECT COUNT(*) FROM {$tableName} k WHERE k.item_id = {$this->fullTableName}.id AND k.vote = 'up')",
+ 'downvotes' => "(SELECT COUNT(*) FROM {$tableName} k WHERE k.item_id = {$this->fullTableName}.id AND k.vote = 'down')",
+ 'karmic_score' => "(SELECT COALESCE(SUM(CASE WHEN k.vote = 'up' THEN 1 WHEN k.vote = 'down' THEN -1 ELSE 0 END), 0) FROM {$tableName} k WHERE k.item_id = {$this->fullTableName}.id)",
+ };
+ }
+
+ if ($orderby === 'favourites_count' && $this->favouritesTable) {
+ $tableName = $this->favouritesTable->getFullTableName();
+ return "(SELECT COUNT(*) FROM {$tableName} f WHERE f.target_id = {$this->fullTableName}.id)";
+ }
+
+ return sanitize_sql_orderby($orderby);
+ }
+
/**
* Get a specific column value from all matches
@@ -676,7 +732,7 @@
$key = array_merge($where, ['column' => $column, 'orderby' => $orderby, 'order' => $order, 'limit' => $limit]);
return $this->cache->remember(
- $this->cache->generateKey($key),
+ $key,
function() use ($column, $where, $orderby, $order, $limit) {
if (!empty($this->columns) && !array_key_exists($column, $this->columns)) {
$this->logError('pluck', ['reason' => "Column '{$column}' not in definition"]);
@@ -684,7 +740,7 @@
}
$args = ['where' => $where];
if ($orderby) {
- $args['orderby'] = $orderby;
+ $args['orderby'] = $this->resolveOrderby($orderby);
}
if ($order) {
$args['order'] = $order;
@@ -708,7 +764,7 @@
public function count(array $where = []): int
{
return $this->cache->remember(
- $this->cache->generateKey(array_merge(['source' => 'count'], $where)),
+ array_merge(['source' => 'count'], $where),
function() use ($where) {
$query = "SELECT COUNT(*) FROM {$this->fullTableName}";
$values = [];
@@ -1045,16 +1101,34 @@
foreach ($where as $column => $value) {
$column_safe = esc_sql($column);
+ // OR grouping: ['OR' => [ [...cond1], [...cond2] ]]
+ if ($column === 'OR' && is_array($value)) {
+ $orConditions = [];
+ foreach ($value as $orWhere) {
+ $orClause = $this->buildWhereClause($orWhere);
+ $orConditions[] = $orClause['sql'];
+ $values = array_merge($values, $orClause['values']);
+ }
+ $conditions[] = '(' . implode(' OR ', $orConditions) . ')';
+ continue;
+ }
+
if ($value === null) {
$conditions[] = "`{$column_safe}` IS NULL";
} elseif (is_array($value) && count($value) === 2 && is_string($value[0])) {
[$operator, $operand] = $value;
$operator = strtoupper(trim($operator));
- if (in_array($operator, ['IN', 'NOT IN']) && is_array($operand)) {
+ if ($operator === 'IS NOT NULL') {
+ $conditions[] = "`{$column_safe}` IS NOT NULL";
+ } elseif (in_array($operator, ['IN', 'NOT IN']) && is_array($operand)) {
$placeholders = implode(',', array_map([$this, 'getPlaceholder'], $operand));
$conditions[] = "`{$column_safe}` {$operator} ({$placeholders})";
$values = array_merge($values, $operand);
+ } elseif (in_array($operator, ['BETWEEN', 'NOT BETWEEN']) && is_array($operand) && count($operand) === 2) {
+ $conditions[] = "`{$column_safe}` {$operator} " . $this->getPlaceholder($operand[0]) . " AND " . $this->getPlaceholder($operand[1]);
+ $values[] = $operand[0];
+ $values[] = $operand[1];
} else {
// <, >, <=, >=, !=, LIKE, etc.
$conditions[] = "`{$column_safe}` {$operator} " . $this->getPlaceholder($operand);
@@ -1114,4 +1188,10 @@
error_log("[CustomTable:{$this->tableName}] {$operation} failed: " . $this->wpdb->last_error);
}
}
+
+ public function sum(string $column, array $where):float
+ {
+ $rows = $this->pluck($column, $where);
+ return array_sum($rows);
+ }
}
--
Gitblit v1.10.0