Jake Vanderwerf
2026-04-15 c4aa5cdb5e90ad4b420e22772797d16980232a2b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
namespace JVBase\managers\Notifications;
 
use JVBase\managers\CustomTable;
use JVBase\registrar\Registrar;
 
if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}
/**
 * Preferences
 *  Manages preferences for a user's favourites
 **/
class Preferences
{
    protected CustomTable $preferences;
    public function __construct()
    {
        $this->defineTable();
    }
 
    private function defineTable():void
    {
        $table = CustomTable::for('notifications_preferences');
        $table->setColumns([
            'id'                => 'bigint(20) unsigned NOT NULL AUTO_INCREMENT',
            'user_id'           => "{$table->getUserIDType()} NOT NULL",
            'item_id'           => 'bigint(20) NOT NULL',
            'item_type'         => 'varchar(50) NOT NULL',
            'frequency'         => "ENUM('never', 'daily', 'weekly', 'monthly') DEFAULT 'never'",
            'last_sent'         => 'datetime DEFAULT NULL',
            'created_at'        => 'datetime DEFAULT CURRENT_TIMESTAMP',
            'updated_at'        => 'datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'
        ]);
 
        $table->setKeys([
            ['key' => 'PRIMARY', 'value' => '(`id`)'],
            ['key' => 'UNIQUE', 'value' => '`user_type` (`user_id`, `item_id`)'],
            '`user_frequency` (`user_id`, `frequency`)',
            '`frequency_lookup` (`frequency`, `last_sent`)'
        ]);
 
        $base = BASE;
        $table->setConstraints([
            "CONSTRAINT `{$base}notification_pref_user` FOREIGN KEY (`user_id`)
                REFERENCES `{$table->getUserTable()}` (`ID`) ON DELETE CASCADE"
        ]);
 
        $table->defineTable();
        $this->preferences = $table;
    }
 
    public function getUsersByFrequency(string $frequency):array
    {
        if (!in_array($frequency, ['never', 'daily', 'weekly', 'monthly'])) {
            return [];
        }
        return array_unique($this->preferences->pluck('user_id', ['frequency' => $frequency]));
    }
 
    public function getUserSubscriptions(int $userID, string $frequency):array
    {
        if (!in_array($frequency, ['never', 'daily', 'weekly', 'monthly'])) {
            return [];
        }
        return $this->preferences->getMany([
            'user_id'   => $userID,
            'frequency' => $frequency
        ]);
    }
 
    public function addUserPreference(int $userID, int $item_id, string $item_type, string $frequency):bool
    {
        if (!in_array($frequency, ['never', 'daily', 'weekly', 'monthly'])) {
            return false;
        }
        $user = get_userdata($userID);
        if (!$user || is_wp_error($user)) {
            return false;
        }
        $registrar = Registrar::getInstance($item_type);
        if (!$registrar) {
            return false;
        }
        $type = $registrar->getType();
        switch ($type) {
            case 'term':
                $term = get_term($item_id, $registrar->getBased());
                if (!$term || is_wp_error($term)) {
                    return false;
                }
                break;
            case 'user':
                $user = get_userdata($item_id);
                if (!$user || is_wp_error($user)) {
                    return false;
                }
                break;
        }
        return $this->preferences->findOrCreate(
            [
                'user_id'   => $userID,
                'item_id'   => $item_id,
                'item_type' => $item_type
            ],
            [
                'frequency' => $frequency
            ]
        );
    }
 
    public function deleteUserPreference(int $userID, int $item_id, string $item_type):bool
    {
        $hasRecord = $this->preferences->get(['user_id' => $userID, 'item_id' => $item_id, 'item_type' => $item_type]);
        if (!$hasRecord) {
            return false;
        }
        return $this->preferences->delete([
            'user_id'   => $userID,
            'item_id'   => $item_id,
            'item_type' => $item_type
        ]);
    }
}