Reviewrepository - Source Excerpt 01
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/spiralist-workspace/includes/Domain/ReviewRepository.php so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Domain/ReviewRepository.php
<?php
namespace SpiralistWorkspace\Domain;
use SpiralistWorkspace\Installer;
if (!defined('ABSPATH')) {
exit;
}
/**
* Stores peer reviews and moderation reports for prompt governance.
*/
class ReviewRepository
{
/**
* Returns one review/report row for a prompt, reviewer, and kind.
*
* @return array<string,mixed>
*/
public function find_for_prompt_and_user(int $prompt_id, int $reviewer_user_id, string $kind = 'peer'): array
{
global $wpdb;
if ($prompt_id <= 0 || $reviewer_user_id <= 0) {
return [];
}
$table = Installer::table('prompt_reviews');
$users = $wpdb->users;
$sql = $wpdb->prepare(
"SELECT r.*, u.display_name
FROM {$table} r
LEFT JOIN {$users} u ON u.ID = r.reviewer_user_id
WHERE r.prompt_post_id = %d AND r.reviewer_user_id = %d AND r.review_kind = %s
LIMIT 1",
$prompt_id,
$reviewer_user_id,
sanitize_key($kind)
);
$row = $wpdb->get_row($sql, ARRAY_A);
return is_array($row) ? $this->normalize_row($row) : [];
}
/**
* Upserts one peer review for a prompt and reviewer.
*/
public function submit_peer_review(int $prompt_id, int $reviewer_user_id, string $decision, string $reason = ''): array
{
return $this->upsert($prompt_id, $reviewer_user_id, 'peer', $decision, $reason);
}
/**
* Stores one report for a prompt. Logged-in reporters are deduplicated per prompt.
*/
public function submit_report(int $prompt_id, ?int $reporter_user_id, string $reason = ''): array
{
if (($reporter_user_id ?? 0) > 0) {
return $this->upsert($prompt_id, (int) $reporter_user_id, 'report', 'report', $reason);
}
global $wpdb;
$created_utc = gmdate('Y-m-d H:i:s');
$wpdb->insert(
Installer::table('prompt_reviews'),
[
'prompt_post_id' => $prompt_id,
'reviewer_user_id' => null,
'review_kind' => 'report',
'decision' => 'report',
'reason' => $reason,
'created_utc' => $created_utc,
'updated_utc' => $created_utc,
],
['%d', '%d', '%s', '%s', '%s', '%s', '%s']
);
return $this->get((int) $wpdb->insert_id);
}
/**
* Returns recent review/report rows for a prompt.
*
* @return array<int,array<string,mixed>>
*/
public function list_for_prompt(int $prompt_id, int $limit = 50, string $kind = '', string $since_utc = ''): array
{
global $wpdb;
$limit = max(1, $limit);
$table = Installer::table('prompt_reviews');
$users = $wpdb->users;
$since_utc = sanitize_text_field($since_utc);
if ($kind !== '' && $since_utc !== '') {
$sql = $wpdb->prepare(
"SELECT r.*, u.display_name
FROM {$table} r
LEFT JOIN {$users} u ON u.ID = r.reviewer_user_id
WHERE r.prompt_post_id = %d AND r.review_kind = %s AND r.updated_utc >= %s
ORDER BY r.updated_utc DESC, r.id DESC
LIMIT %d",
$prompt_id,
sanitize_key($kind),
$since_utc,
$limit
);
} elseif ($kind !== '') {
$sql = $wpdb->prepare(
"SELECT r.*, u.display_name
FROM {$table} r
LEFT JOIN {$users} u ON u.ID = r.reviewer_user_id
WHERE r.prompt_post_id = %d AND r.review_kind = %s
ORDER BY r.updated_utc DESC, r.id DESC
LIMIT %d",
$prompt_id,
sanitize_key($kind),
$limit
);
} elseif ($since_utc !== '') {
$sql = $wpdb->prepare(
"SELECT r.*, u.display_name
FROM {$table} r
LEFT JOIN {$users} u ON u.ID = r.reviewer_user_id
WHERE r.prompt_post_id = %d AND r.updated_utc >= %s
ORDER BY r.updated_utc DESC, r.id DESC
LIMIT %d",
$prompt_id,
$since_utc,
$limit
);
} else {
$sql = $wpdb->prepare(
"SELECT r.*, u.display_name
FROM {$table} r
LEFT JOIN {$users} u ON u.ID = r.reviewer_user_id
WHERE r.prompt_post_id = %d
ORDER BY r.updated_utc DESC, r.id DESC
LIMIT %d",
$prompt_id,
$limit
);
}
$rows = $wpdb->get_results($sql, ARRAY_A);
return array_map([$this, 'normalize_row'], is_array($rows) ? $rows : []);
}
/**
* Returns recent review/report rows created by one reviewer or reporter.
*
* @return array<int,array<string,mixed>>
*/
public function list_for_reviewer(int $reviewer_user_id, int $limit = 100, string $kind = ''): array
{
global $wpdb;
if ($reviewer_user_id <= 0) {
return [];
}
$limit = max(1, $limit);
$table = Installer::table('prompt_reviews');
$users = $wpdb->users;
if ($kind !== '') {
$sql = $wpdb->prepare(
"SELECT r.*, u.display_name
FROM {$table} r
LEFT JOIN {$users} u ON u.ID = r.reviewer_user_id
WHERE r.reviewer_user_id = %d AND r.review_kind = %s
ORDER BY r.updated_utc DESC, r.id DESC
LIMIT %d",
$reviewer_user_id,
sanitize_key($kind),
$limit
);
} else {
$sql = $wpdb->prepare(
"SELECT r.*, u.display_name
FROM {$table} r
LEFT JOIN {$users} u ON u.ID = r.reviewer_user_id
WHERE r.reviewer_user_id = %d
ORDER BY r.updated_utc DESC, r.id DESC
LIMIT %d",
$reviewer_user_id,
$limit
);
}
$rows = $wpdb->get_results($sql, ARRAY_A);
return array_map([$this, 'normalize_row'], is_array($rows) ? $rows : []);
}
/**
* Returns summary counts for a prompt's peer reviews and reports.
*
* @return array<string,mixed>
*/
public function summary_for_prompt(int $prompt_id, string $since_utc = ''): array
{
$rows = $this->list_for_prompt($prompt_id, 500, '', $since_utc);
$summary = [
'peer' => [
'endorse' => 0,
'restrict' => 0,
'revert' => 0,
],
'peer_reviews' => 0,
'reports_total' => 0,
'reports_from_accounts' => 0,
'unique_reporters' => 0,
'last_activity_utc' => '',
'since_utc' => $since_utc,
];
$unique_reporters = [];
foreach ($rows as $row) {
if (($row['review_kind'] ?? '') === 'peer') {
$decision = (string) ($row['decision'] ?? '');
if (isset($summary['peer'][$decision])) {
$summary['peer'][$decision]++;
}
$summary['peer_reviews']++;
}
if (($row['review_kind'] ?? '') === 'report') {
$summary['reports_total']++;
if ((int) ($row['reviewer_user_id'] ?? 0) > 0) {
$summary['reports_from_accounts']++;
$unique_reporters[(int) $row['reviewer_user_id']] = true;
}
}
$updated_utc = (string) ($row['updated_utc'] ?? '');
if ($updated_utc !== '' && $updated_utc > (string) $summary['last_activity_utc']) {
$summary['last_activity_utc'] = $updated_utc;
}
}
$summary['unique_reporters'] = count($unique_reporters);
return $summary;
}
/**
* Returns one review row.
*
* @return array<string,mixed>
*/
public function get(int $id): array
{
global $wpdb;
if ($id <= 0) {
return [];
}
$table = Installer::table('prompt_reviews');
$users = $wpdb->users;
$sql = $wpdb->prepare(
"SELECT r.*, u.display_name
FROM {$table} r
LEFT JOIN {$users} u ON u.ID = r.reviewer_user_id
WHERE r.id = %d
LIMIT 1",
$id
);
$row = $wpdb->get_row($sql, ARRAY_A);