From a9654f00c8fbc9934289d761843ddd071025013f Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Fri, 28 Aug 2026 17:20:28 +0000
Subject: [PATCH] =PHPStorm Code Inspection: fixed class reference errors (from getting rid of JVB() and replacing with direct class::getInstance; as well as general code sniffing, etc

---
 inc/users/UserSettings.php | 1254 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 628 insertions(+), 626 deletions(-)

diff --git a/inc/users/UserSettings.php b/inc/users/UserSettings.php
index 1ee08e9..a7c8c95 100644
--- a/inc/users/UserSettings.php
+++ b/inc/users/UserSettings.php
@@ -1,633 +1,635 @@
 <?php
 namespace JVBase\users;
 
-use JVBase\JVB;
-use JVBase\registry\ContentRegistry;
+//use JVBase\registry\ContentRegistry;
 
 if (!defined('ABSPATH')) {
     exit; // Exit if accessed directly
 }
-
-class UserSettings extends ContentRegistry
-{
-    protected array $fields;
-    protected array $sections = [
-        'account'   => [
-            'title'         => 'Account',
-            'icon'          => 'settings',
-        ],
-        'notifications' => [
-            'title'         => 'Notifications',
-            'icon'          => 'email'
-        ],
-        'newsletter' => [
-            'title'         => 'Newsletter',
-            'icon'          => 'logo'
-        ],
-        'invitations'    => [
-            'title'        => 'Invite Artists',
-            'icon'        => 'new-user',
-        ]
-    ];
-    protected array $frequency = [
-        'never'     => 'Never',
-        'daily'     => 'Daily',
-        'weekly'    => 'Weekly',
-        'monthly'   => 'Monthly',
-    ];
-
-    public function initType():void
-    {
-        $this->object_type = 'user';
-        $this->userFields();
-    }
-
-    public function getFields():array
-    {
-        return $this->fields;
-    }
-    public function getSections():array
-    {
-        return $this->sections;
-    }
-    public function userFields():void
-    {
-
-        $this->fields = [
-            'display_name'  => [
-                'type'  => 'text',
-                'label' => 'Name',
-                'description'   => 'Optional. Only used if you allow artists to see your info when you favourite them.',
-                'default'   => '',
-                'section'   => 'account',
-                'role'      => ['ei_enthusiast']
-            ],
-            'user_email'    => [
-                'type'  => 'email',
-                'label' => 'Email',
-                'description'   => 'Required for any notifications you subscribe to.',
-                'default'   => '',
-                'section'   => 'account',
-                'role'      => ['ei_enthusiast']
-            ],
-            'city'      => [
-                'type'  => 'text',
-                'label' => 'City',
-                'description'   => 'Optional. Just helps us know where people who use this site are located.',
-                'default'   => '',
-                'section'   => 'account',
-                'role'      => ['ei_enthusiast']
-            ],
-            'notify'    => [
-                'type'  => 'true_false',
-                'label' => 'Notify artists when you favourite their work',
-                'description'   => 'If you select this, artists will see your name when you favourite their work, else they will just get an anonymous notification.',
-                'default'   => false,
-                'section'   => 'account',
-            ],
-            'dark_mode'    => [
-                'type'  => 'true_false',
-                'label' => 'Dark Mode',
-                'default'   => false,
-            ],
-            'email_digest'  => [
-                'type'      => 'radio',
-                'label'     => 'Email Summary Frequency',
-                'options'   => $this->frequency,
-                'default'   => 'never',
-                'section'       => 'notifications'
-            ],
-            'digest_override'   => [
-                'type'  => 'true_false',
-                'label' => 'Apply to all notifications',
-                'description'   => 'Override individual notification settings and apply this frequency to all your notifications',
-                'default'     => false,
-                'section'       => 'notifications'
-            ],
-            'notifications' => [
-                'type'      => 'callback',
-                'callback'  => 'renderNotifications',
-                'label'     => 'Notifications',
-                'section'   => 'notifications',
-                'default'   => '',
-            ],
-            'site_updates'  => [
-                'type'  => 'true_false',
-                'label' => 'Site Updates',
-                'description' => 'Get notified when new features are added to edmonton.ink',
-                'default'   => false,
-                'section'   => 'account',
-            ],
-            'newsletter'    => [
-                'type'  => 'true_false',
-                'label' => 'Newsletter',
-                'description'   => 'Sign up for our monthly-ish newsletter, featuring upcoming events, featured artists, new artists, and their work.',
-                'default'   => false,
-                'section'   => 'newsletter',
-            ],
-            'owner_of'    => [
-                'type' => 'taxonomy',
-                'label'    => __('Owner of', 'jvb'),
-                'taxonomy_type' => 'reference',
-                'taxonomy' => BASE. 'shop',
-                'quickEdit'    => true,
-                'default'    => '',
-            ],
-            'manager_of'    => [
-                'type' => 'taxonomy',
-                'label'    => __('Manager of', 'jvb'),
-                'taxonomy_type' => 'reference',
-                'taxonomy' => BASE. 'shop',
-                'hidden'    => true,
-                'default'    => '',
-            ],
-
-            'invitations'    => [
-                'type'    => 'callback',
-                'callback'    => 'handleInvitationsManagement',
-                'section'    => 'invitations',
-                'label'        => __('Invite Artists', 'jvb'),
-                'role'      => ['ei_artist']
-            ],
-        ];
-    }
-
-    /**
-     * Render custom notification preferences UI
-     * @param int $user_id
-     *
-     * @return string
-     */
-    public function renderNotifications(int $user_id):string
-    {
-        $favourites = $this->getUserFavourites($user_id);
-        $preferences = $this->getUserNotificationPreferences($user_id);
-        global $notify;
-
-        ob_start();
-        ?>
-        <div class="notification-preferences">
-            <?php foreach ($favourites as $type => $items) : ?>
-                <details class="notification-group">
-                    <summary class="notification-group-header row btw">
-                        <span class="type-label"><?=jvbIcon('heart', ['style' => 'fill'])?> <?= $notify[$type] ?></span>
-                        <span class="type-count">( <?= count($items); ?> )</span>
-                    </summary>
-
-                    <?php if (!empty($items)) : ?>
-                        <table class="notification-table">
-                            <thead>
-                            <tr>
-                                <th>Name</th>
-                                <th>Frequency</th>
-                            </tr>
-                            </thead>
-                            <tbody>
-                            <?php foreach ($items as $item) : ?>
-                                <?php
-                                $current = isset($preferences['preferences'][$type][$item['id']])
-                                    ? $preferences['preferences'][$type][$item['id']]
-                                    : $preferences['default_frequency'];
-                                ?>
-                                <tr>
-                                    <td><?= esc_html($item['name']); ?></td>
-                                    <td>
-                                        <div class="radio-options row">
-                                            <?php foreach (['never', 'daily', 'weekly', 'monthly'] as $freq) : ?>
-                                                <input type="radio"
-                                                       name="notification_preferences[<?= esc_attr($type); ?>][<?= esc_attr($item['id']); ?>]"
-                                                       id="<?= esc_attr("{$type}_{$item['id']}_$freq"); ?>"
-                                                       value="<?= esc_attr($freq); ?>"
-                                                    <?php checked($current, $freq); ?>>
-                                                <label for="<?= esc_attr("{$type}_{$item['id']}_$freq"); ?>">
-                                                    <?= ucfirst($freq); ?>
-                                                </label>
-                                            <?php endforeach; ?>
-                                        </div>
-                                    </td>
-                                </tr>
-                            <?php endforeach; ?>
-                            </tbody>
-                            <tfoot>
-                            <tr>
-
-                                <th>Set all <?= $type ?>s to: </th>
-                                <th>
-                                    <div class="radio-options row">
-                                        <?php foreach (['never', 'daily', 'weekly', 'monthly'] as $freq) : ?>
-                                            <input type="radio"
-                                                   name="toggle-all-<?=$type?>"
-                                                   id="toggle-all-<?=$type?>-<?=$freq?>"
-                                                   value="<?= esc_attr($freq); ?>"
-                                                class="toggle-all">
-                                            <label for="toggle-all-<?=$type?>-<?=$freq?>">
-                                                <?= ucfirst($freq); ?>
-                                            </label>
-                                        <?php endforeach; ?>
-                                    </div>
-                                </th>
-
-                            </tr>
-                            </tfoot>
-                        </table>
-                    <?php else : ?>
-                        <p class="no-items">No favourites yet</p>
-                    <?php endif; ?>
-                </details>
-            <?php endforeach; ?>
-        </div>
-        <script>
-            function initGroupOverrides() {
-                document.querySelectorAll('.toggle-all').forEach(toggle => {
-                    toggle.addEventListener('change', e => {
-                        e.preventDefault();
-                        if(toggle.checked){
-                            const table = e.target.closest('table');
-                            console.log(table);
-                            const value = toggle.value;
-
-                            // Enable/disable individual controls
-                            table.querySelectorAll('input[value="'+value+'"]').forEach(radio => {
-                                radio.checked = true;
-                            });
-                        }
-
-                    });
-                });
-
-                // Listen for changes to default frequency
-                document.querySelector('input[name="digest_override"]').addEventListener('change', e=>{
-                    let value = document.querySelector('input[name="email_digest"]:checked').value;
-
-                    console.log(value);
-                    document.querySelectorAll('input[value="'+value+'"]').forEach(toggle => {
-                        toggle.checked = true;
-                    });
-
-                    setTimeout(function () {
-                        e.target.checked = false;
-                    }, 1000)
-
-                });
-
-            }
-            initGroupOverrides();
-        </script>
-        <?php
-        return ob_get_clean();
-    }
-
-    /**
-     * Get user's favourites grouped by type
-     */
-    protected function getUserFavourites(int $user_id):array
-    {
-        global $wpdb;
-        $table = $wpdb->prefix . BASE.'favourites';
-        global $notify;
-        global $types;
-
-
-        $favourites = [];
-        foreach (array_keys($notify) as $type) {
-            $favourites[$type] = [];
-        }
-
-        // Fetch favourites from database
-        $results = $wpdb->get_results($wpdb->prepare(
-            "SELECT * FROM $table WHERE user_id = %d",
-            $user_id
-        ));
-
-        foreach ($results as $result) {
-            $type = str_replace(BASE, '', $result->type);
-
-
-            if (!array_key_exists($type, $favourites)) {
-                continue;
-            }
-            // Get proper name based on type
-            switch ($types[BASE.$type]['table']) {
-                case 'post':
-                    $name = get_the_title($result->target_id);
-                    break;
-                case 'term':
-                    $term = get_term($result->target_id, BASE.$type);
-                    $name = $term ? html_entity_decode($term->name) : '';
-                    break;
-                default:
-                    $name = '';
-            }
-
-            if ($name) {
-                $favourites[$type][] = [
-                    'id' => $result->target_id,
-                    'name' => $name
-                ];
-            }
-        }
-
-        return $favourites;
-    }
-
-    /**
-     * Get current notification preferences
-     */
-    protected function getNotificationPreferences(int $user_id):array
-    {
-        return get_user_meta($user_id, 'notification_preferences', true) ?: [];
-    }
-
-    protected function getUserNotificationPreferences(int $user_id):array
-    {
-        global $wpdb;
-        $table = $wpdb->prefix . BASE.'notification_preferences';
-
-//        error_log('Getting notification preferences for user: ' . $user_id);
-
-        // Get user's preferences from the table
-        $raw_preferences = $wpdb->get_results($wpdb->prepare(
-            "SELECT notification_type, item_id, frequency
-         FROM {$table}
-         WHERE user_id = %d",
-            $user_id
-        ), ARRAY_A);
-
-//        error_log('Raw preferences from database: ' . print_r($raw_preferences, true));
-
-        // Structure the preferences
-        $preferences = [];
-        if (!empty($raw_preferences)) {
-            foreach ($raw_preferences as $pref) {
-                $type = $pref['notification_type'];
-                $item_id = intval($pref['item_id']);
-                $frequency = $pref['frequency'];
-
-                if (!isset($preferences[$type])) {
-                    $preferences[$type] = [];
-                }
-                $preferences[$type][$item_id] = $frequency;
-            }
-        }
-
-        // Get default frequency
-        $default_frequency = get_user_meta($user_id, BASE.'email_digest', true) ?: 'never';
-
-//        error_log('Structured preferences: ' . print_r($preferences, true));
-//        error_log('Default frequency: ' . $default_frequency);
-
-        return [
-            'preferences' => $preferences,
-            'default_frequency' => $default_frequency
-        ];
-    }
-
-    public function handleInvitationsManagement(int $userID):void
-    {
-        $name = 'artist_invite';
-        ?>
-        <div class="field">
-            <script type="text/javascript">
-                function addArtist(button){
-                    let template = window.getTemplate('artistInvite');
-                    let container = button.closest('.field').querySelector('.invite-artists');
-
-                    let nameLabel = template.querySelector('label[for="invited-artist-name"]'),
-                        nameInput = template.querySelector('input#invited-artist-name'),
-                        emailLabel = template.querySelector('label[for="invited-artist-email"]'),
-                        emailInput = template.querySelector('input#invited-artist-email'),
-                        shopLabel = template.querySelector('label[for="invited-add-to-shop"]'),
-                        shopInput = template.querySelector('input#invited-add-to-shop');
-
-
-                    let count = container.childNodes.length;
-                    console.log(container.childNodes);
-                    [
-                        nameLabel.htmlFor,
-                        nameInput.id,
-                        nameInput.name,
-                        emailLabel.htmlFor,
-                        emailInput.id,
-                        emailInput.name,
-                        shopLabel.htmlFor,
-                        shopInput.id,
-                        shopInput.name
-                    ] =
-                    [
-                        `${nameLabel.getAttribute('for')}-${count}`,
-                        `${nameInput.id}-${count}`,
-                        `${nameInput.name}-${count}`,
-                        `${emailLabel.htmlFor}-${count}`,
-                        `${emailInput.id}-${count}`,
-                        `${emailInput.name}-${count}`,
-                        `${shopLabel.htmlFor}-${count}`,
-                        `${shopInput.id}-${count}`,
-                        `${shopInput.name}-${count}`
-                    ];
-                    container.append(template);
-                }
-                function removeArtist(button){
-                    button.closest('.invited-artist').remove();
-                }
-
-                async function revokeInvite(button){
-                    try {
-                        let artist = button.closest('tr');
-                        let id = artist.id;
-
-                        const headers = {
-                            'X-WP-Nonce': eiSettings.nonce,
-                            'action_nonce': eiSettings.dash,
-                            'Content-Type': 'application/json'
-                        };
-
-                        let body = {
-                            user: eiSettings.currentUser,
-                            revoke: id
-                        };
-                        let request = {
-                            method: 'POST',
-                            headers: headers,
-                            body: JSON.stringify(body)
-                        };
-                        console.log(request);
-
-
-                        const response = await fetch(`${eiSettings.api}invitations`, request);
-
-                        console.log(response);
-                        if (!response.ok) {
-                            const errorData = await response.json().catch(() => ({}));
-                        }
-
-                        const data =  await response.json();
-                        if(data.success){
-                            artist.remove();
-                        }
-                    }catch (error) {
-                    }
-                }
-
-                async function resendInvite(button){
-                    try {
-                        let artist = button.closest('tr');
-                        let id = artist.id;
-
-                        const headers = {
-                            'X-WP-Nonce': eiSettings.nonce,
-                            'action_nonce': eiSettings.dash,
-                            'Content-Type': 'application/json'
-                        };
-
-                        let body = {
-                            user: eiSettings.currentUser,
-                            refresh: id
-                        };
-                        let request = {
-                            method: 'POST',
-                            headers: headers,
-                            body: JSON.stringify(body)
-                        };
-                        console.log(request);
-
-
-                        const response = await fetch(`${eiSettings.api}invitations`, request);
-
-                        console.log(response);
-                        if (!response.ok) {
-                            const errorData = await response.json().catch(() => ({}));
-                        }
-
-                        const data =  await response.json();
-
-                    }catch (error) {
-                    }
-                }
-
-                function sendInvites(button){
-                    if(document.querySelector('.invited-artist')){
-                        let newArtists = [];
-                        document.querySelectorAll('.invited-artist').forEach(invited => {
-                            let name = invited.querySelector('input[type="text"]'),
-                                email = invited.querySelector('input[type="email"]'),
-                                toShop = invited.querySelector('input[type="checkbox"]');
-                            if(name.value === '' || email.value === ''){
-                                invited.classList.add('required');
-                                return;
-                            }
-
-                            newArtists.push({
-                                name: name.value,
-                                email: email.value,
-                                toShop: toShop.checked
-                            });
-                            invited.remove();
-                        });
-                        if(newArtists.length > 0){
-                            window.queueManager.addToQueue({
-                                type: 'invite_artist',
-                                data: newArtists
-                            });
-                        }
-                    }
-                }
-            </script>
-
-            <section class="invite-artists">
-                <div class="invited-artist">
-                    <button type="button" onclick="removeArtist(this)" title="Remove Invite"><?=jvbIcon('trash')?></button>
-                    <div>
-                        <label for="invited-artist-name-1">First Name</label>
-                        <input type="text" id="invited-artist-name-1" name="invited-artist-name-1">
-                    </div>
-                    <div>
-                        <label for="invited-artist-email-1">Email</label>
-                        <input type="email" id="invited-artist-email-1" name="invited-artist-email-1">
-                    </div>
-                    <div>
-                        <input type="checkbox" name="invited-add-to-shop-1" id="invited-add-to-shop-1">
-                        <label for="invited-add-to-shop-1">Add to shop?</label>
-                    </div>
-                </div>
-            </section>
-            <div class="actions">
-                <button type="button" onclick="addArtist(this)" class="add-artist"><?= jvbIcon('plus-square')?>Add Artist</button>
-                <button type="button" onclick="sendInvites(this)" class="send-invites"><?=jvbIcon('envelope')?>Send Invites</button>
-            </div>
-
-            <template class="artistInvite">
-                <div class="invited-artist">
-                    <button type="button" onclick="removeArtist(this)" title="Remove Invite"><?=jvbIcon('trash')?></button>
-                    <div>
-                        <label for="invited-artist-name">First Name</label>
-                        <input type="text" id="invited-artist-name" name="invited-artist-name">
-                    </div>
-                    <div>
-                        <label for="invited-artist-email">Email</label>
-                        <input type="email" id="invited-artist-email" name="invited-artist-email">
-                    </div>
-                    <div>
-                        <input type="checkbox" name="invited-add-to-shop" id="invited-add-to-shop">
-                        <label for="invited-add-to-shop">Add to shop?</label>
-                    </div>
-                </div>
-            </template>
-        </div>
-        <?php
-
-        $invites = JVB()->routes('invites')->getUserInvitations($userID);
-
-        ?>
-        <table class="artist-invite">
-            <thead>
-                <tr>
-                    <th scope="col" style="width:100%;">Name</th>
-                    <th scope="col" style="padding:0 .5rem">Email</th>
-                    <th scope="col" style="padding:0 .5rem">Status</th>
-                    <th scope="col" style="padding:0 .5rem">Expires</th>
-                    <th scope="col" style="padding:0 .5rem">Actions</th>
-                </tr>
-            </thead>
-            <tbody>
-            <?php
-            if (!empty($invites->invitations)) {
-                foreach ($invites->invitations as $invite) {
-                    ?>
-                    <tr id="<?=$invite['id']?>">
-                        <td>
-                            <?=$invite['name']?>
-                        </td>
-                        <td>
-                            <?=$invite['email']?>
-                        </td>
-                        <td>
-                            <?=$invite['status']?>
-                        </td>
-                        <td>
-                            <?=$invite['expires_at']?>
-                        </td>
-                        <td class="actions">
-                            <button type="button" data-action="revoke" title="Revoke Invitation" onclick="revokeInvite(this)">
-                                <?=jvbIcon('trash')?>
-                                <span class="screen-reader-text">Revoke invite</span>
-                            </button>
-                            <button type="button" data-action="resend"<?=($invite['status'] === 'exipired') ? '' : ' disabled'?> title="Resend Invitation" onclick="resendInvite(this)">
-                                <?=jvbIcon('arrows-clockwise')?>
-                                <span class="screen-reader-text">Try Again</span>
-                            </button>
-                        </td>
-
-                    </tr>
-                    <?php
-                }
-            } else {
-                ?>
-                <tr><td><i>No invites yet</i></td><td></td><td></td><td></td><td></td></tr>
-                <?php
-            }
-            ?>
-            </tbody>
-        </table>
-        <?php
-    }
-}
+//TODO: Likely replaced with Registrar?
+//
+//class UserSettings extends ContentRegistry
+//{
+//    protected array $fields;
+//    protected array $sections = [
+//        'account'   => [
+//            'title'         => 'Account',
+//            'icon'          => 'settings',
+//        ],
+//        'notifications' => [
+//            'title'         => 'Notifications',
+//            'icon'          => 'email'
+//        ],
+//        'newsletter' => [
+//            'title'         => 'Newsletter',
+//            'icon'          => 'logo'
+//        ],
+//        'invitations'    => [
+//            'title'        => 'Invite Artists',
+//            'icon'        => 'new-user',
+//        ]
+//    ];
+//    protected array $frequency = [
+//        'never'     => 'Never',
+//        'daily'     => 'Daily',
+//        'weekly'    => 'Weekly',
+//        'monthly'   => 'Monthly',
+//    ];
+//
+//    public function initType():void
+//    {
+//        $this->object_type = 'user';
+//        $this->userFields();
+//    }
+//
+//    public function getFields():array
+//    {
+//        return $this->fields;
+//    }
+//    public function getSections():array
+//    {
+//        return $this->sections;
+//    }
+//    public function userFields():void
+//    {
+//
+//        $this->fields = [
+//            'display_name'  => [
+//                'type'  => 'text',
+//                'label' => 'Name',
+//                'description'   => 'Optional. Only used if you allow artists to see your info when you favourite them.',
+//                'default'   => '',
+//                'section'   => 'account',
+//                'role'      => ['ei_enthusiast']
+//            ],
+//            'user_email'    => [
+//                'type'  => 'email',
+//                'label' => 'Email',
+//                'description'   => 'Required for any notifications you subscribe to.',
+//                'default'   => '',
+//                'section'   => 'account',
+//                'role'      => ['ei_enthusiast']
+//            ],
+//            'city'      => [
+//                'type'  => 'text',
+//                'label' => 'City',
+//                'description'   => 'Optional. Just helps us know where people who use this site are located.',
+//                'default'   => '',
+//                'section'   => 'account',
+//                'role'      => ['ei_enthusiast']
+//            ],
+//            'notify'    => [
+//                'type'  => 'true_false',
+//                'label' => 'Notify artists when you favourite their work',
+//                'description'   => 'If you select this, artists will see your name when you favourite their work, else they will just get an anonymous notification.',
+//                'default'   => false,
+//                'section'   => 'account',
+//            ],
+//            'dark_mode'    => [
+//                'type'  => 'true_false',
+//                'label' => 'Dark Mode',
+//                'default'   => false,
+//            ],
+//            'email_digest'  => [
+//                'type'      => 'radio',
+//                'label'     => 'Email Summary Frequency',
+//                'options'   => $this->frequency,
+//                'default'   => 'never',
+//                'section'       => 'notifications'
+//            ],
+//            'digest_override'   => [
+//                'type'  => 'true_false',
+//                'label' => 'Apply to all notifications',
+//                'description'   => 'Override individual notification settings and apply this frequency to all your notifications',
+//                'default'     => false,
+//                'section'       => 'notifications'
+//            ],
+//            'notifications' => [
+//                'type'      => 'callback',
+//                'callback'  => 'renderNotifications',
+//                'label'     => 'Notifications',
+//                'section'   => 'notifications',
+//                'default'   => '',
+//            ],
+//            'site_updates'  => [
+//                'type'  => 'true_false',
+//                'label' => 'Site Updates',
+//                'description' => 'Get notified when new features are added to edmonton.ink',
+//                'default'   => false,
+//                'section'   => 'account',
+//            ],
+//            'newsletter'    => [
+//                'type'  => 'true_false',
+//                'label' => 'Newsletter',
+//                'description'   => 'Sign up for our monthly-ish newsletter, featuring upcoming events, featured artists, new artists, and their work.',
+//                'default'   => false,
+//                'section'   => 'newsletter',
+//            ],
+//            'owner_of'    => [
+//                'type' => 'selector',
+//				'subtype'=> 'taxonomy',
+//                'label'    => __('Owner of', 'jvb'),
+//                'isReference' => true,
+//                'taxonomy' => BASE. 'shop',
+//                'quickEdit'    => true,
+//                'default'    => '',
+//            ],
+//            'manager_of'    => [
+//                'type' => 'selector',
+//                'subtype' => 'taxonomy',
+//                'label'    => __('Manager of', 'jvb'),
+//                'isReference' => true,
+//                'taxonomy' => BASE. 'shop',
+//                'hidden'    => true,
+//                'default'    => '',
+//            ],
+//
+//            'invitations'    => [
+//                'type'    => 'callback',
+//                'callback'    => 'handleInvitationsManagement',
+//                'section'    => 'invitations',
+//                'label'        => __('Invite Artists', 'jvb'),
+//                'role'      => ['ei_artist']
+//            ],
+//        ];
+//    }
+//
+//    /**
+//     * Render custom notification preferences UI
+//     * @param int $user_id
+//     *
+//     * @return string
+//     */
+//    public function renderNotifications(int $user_id):string
+//    {
+//        $favourites = $this->getUserFavourites($user_id);
+//        $preferences = $this->getUserNotificationPreferences($user_id);
+//        global $notify;
+//
+//        ob_start();
+//        ?>
+<!--        <div class="notification-preferences">-->
+<!--            --><?php //foreach ($favourites as $type => $items) : ?>
+<!--                <details class="notification-group">-->
+<!--                    <summary class="notification-group-header row x-btw">-->
+<!--                        <span class="type-label">--><?php //=jvbIcon('heart', ['style' => 'fill'])?><!-- --><?php //= $notify[$type] ?><!--</span>-->
+<!--                        <span class="type-count">( --><?php //= count($items); ?><!-- )</span>-->
+<!--                    </summary>-->
+<!---->
+<!--                    --><?php //if (!empty($items)) : ?>
+<!--                        <table class="notification-table">-->
+<!--                            <thead>-->
+<!--                            <tr>-->
+<!--                                <th>Name</th>-->
+<!--                                <th>Frequency</th>-->
+<!--                            </tr>-->
+<!--                            </thead>-->
+<!--                            <tbody>-->
+<!--                            --><?php //foreach ($items as $item) : ?>
+<!--                                --><?php
+//                                $current = isset($preferences['preferences'][$type][$item['id']])
+//                                    ? $preferences['preferences'][$type][$item['id']]
+//                                    : $preferences['default_frequency'];
+//                                ?>
+<!--                                <tr>-->
+<!--                                    <td>--><?php //= esc_html($item['name']); ?><!--</td>-->
+<!--                                    <td>-->
+<!--                                        <div class="radio-options row">-->
+<!--                                            --><?php //foreach (['never', 'daily', 'weekly', 'monthly'] as $freq) : ?>
+<!--                                                <input type="radio"-->
+<!--                                                       name="notification_preferences[--><?php //= esc_attr($type); ?><!--][--><?php //= esc_attr($item['id']); ?><!--]"-->
+<!--                                                       id="--><?php //= esc_attr("{$type}_{$item['id']}_$freq"); ?><!--"-->
+<!--                                                       value="--><?php //= esc_attr($freq); ?><!--"-->
+<!--                                                    --><?php //checked($current, $freq); ?><!-->-->
+<!--                                                <label for="--><?php //= esc_attr("{$type}_{$item['id']}_$freq"); ?><!--">-->
+<!--                                                    --><?php //= ucfirst($freq); ?>
+<!--                                                </label>-->
+<!--                                            --><?php //endforeach; ?>
+<!--                                        </div>-->
+<!--                                    </td>-->
+<!--                                </tr>-->
+<!--                            --><?php //endforeach; ?>
+<!--                            </tbody>-->
+<!--                            <tfoot>-->
+<!--                            <tr>-->
+<!---->
+<!--                                <th>Set all --><?php //= $type ?><!--s to: </th>-->
+<!--                                <th>-->
+<!--                                    <div class="radio-options row">-->
+<!--                                        --><?php //foreach (['never', 'daily', 'weekly', 'monthly'] as $freq) : ?>
+<!--                                            <input type="radio"-->
+<!--                                                   name="toggle-all---><?php //=$type?><!--"-->
+<!--                                                   id="toggle-all---><?php //=$type?><!-----><?php //=$freq?><!--"-->
+<!--                                                   value="--><?php //= esc_attr($freq); ?><!--"-->
+<!--                                                class="toggle-all">-->
+<!--                                            <label for="toggle-all---><?php //=$type?><!-----><?php //=$freq?><!--">-->
+<!--                                                --><?php //= ucfirst($freq); ?>
+<!--                                            </label>-->
+<!--                                        --><?php //endforeach; ?>
+<!--                                    </div>-->
+<!--                                </th>-->
+<!---->
+<!--                            </tr>-->
+<!--                            </tfoot>-->
+<!--                        </table>-->
+<!--                    --><?php //else : ?>
+<!--                        <p class="no-items">No favourites yet</p>-->
+<!--                    --><?php //endif; ?>
+<!--                </details>-->
+<!--            --><?php //endforeach; ?>
+<!--        </div>-->
+<!--        <script>-->
+<!--            function initGroupOverrides() {-->
+<!--                document.querySelectorAll('.toggle-all').forEach(toggle => {-->
+<!--                    toggle.addEventListener('change', e => {-->
+<!--                        e.preventDefault();-->
+<!--                        if(toggle.checked){-->
+<!--                            const table = e.target.closest('table');-->
+<!--                            console.log(table);-->
+<!--                            const value = toggle.value;-->
+<!---->
+<!--                            // Enable/disable individual controls-->
+<!--                            table.querySelectorAll('input[value="'+value+'"]').forEach(radio => {-->
+<!--                                radio.checked = true;-->
+<!--                            });-->
+<!--                        }-->
+<!---->
+<!--                    });-->
+<!--                });-->
+<!---->
+<!--                // Listen for changes to default frequency-->
+<!--                document.querySelector('input[name="digest_override"]').addEventListener('change', e=>{-->
+<!--                    let value = document.querySelector('input[name="email_digest"]:checked').value;-->
+<!---->
+<!--                    console.log(value);-->
+<!--                    document.querySelectorAll('input[value="'+value+'"]').forEach(toggle => {-->
+<!--                        toggle.checked = true;-->
+<!--                    });-->
+<!---->
+<!--                    setTimeout(function () {-->
+<!--                        e.target.checked = false;-->
+<!--                    }, 1000)-->
+<!---->
+<!--                });-->
+<!---->
+<!--            }-->
+<!--            initGroupOverrides();-->
+<!--        </script>-->
+<!--        --><?php
+//        return ob_get_clean();
+//    }
+//
+//    /**
+//     * Get user's favourites grouped by type
+//     */
+//    protected function getUserFavourites(int $user_id):array
+//    {
+//        global $wpdb;
+//        $table = $wpdb->prefix . BASE.'favourites';
+//        global $notify;
+//        global $types;
+//
+//
+//        $favourites = [];
+//        foreach (array_keys($notify) as $type) {
+//            $favourites[$type] = [];
+//        }
+//
+//        // Fetch favourites from database
+//        $results = $wpdb->get_results($wpdb->prepare(
+//            "SELECT * FROM $table WHERE user_id = %d",
+//            $user_id
+//        ));
+//
+//        foreach ($results as $result) {
+//            $type = str_replace(BASE, '', $result->type);
+//
+//
+//            if (!array_key_exists($type, $favourites)) {
+//                continue;
+//            }
+//            // Get proper name based on type
+//            switch ($types[BASE.$type]['table']) {
+//                case 'post':
+//                    $name = get_the_title($result->target_id);
+//                    break;
+//                case 'term':
+//                    $term = get_term($result->target_id, BASE.$type);
+//                    $name = $term ? html_entity_decode($term->name) : '';
+//                    break;
+//                default:
+//                    $name = '';
+//            }
+//
+//            if ($name) {
+//                $favourites[$type][] = [
+//                    'id' => $result->target_id,
+//                    'name' => $name
+//                ];
+//            }
+//        }
+//
+//        return $favourites;
+//    }
+//
+//    /**
+//     * Get current notification preferences
+//     */
+//    protected function getNotificationPreferences(int $user_id):array
+//    {
+//        return get_user_meta($user_id, 'notification_preferences', true) ?: [];
+//    }
+//
+//    protected function getUserNotificationPreferences(int $user_id):array
+//    {
+//        global $wpdb;
+//        $table = $wpdb->prefix . BASE.'notification_preferences';
+//
+////        error_log('Getting notification preferences for user: ' . $user_id);
+//
+//        // Get user's preferences from the table
+//        $raw_preferences = $wpdb->get_results($wpdb->prepare(
+//            "SELECT notification_type, item_id, frequency
+//         FROM {$table}
+//         WHERE user_id = %d",
+//            $user_id
+//        ), ARRAY_A);
+//
+////        error_log('Raw preferences from database: ' . print_r($raw_preferences, true));
+//
+//        // Structure the preferences
+//        $preferences = [];
+//        if (!empty($raw_preferences)) {
+//            foreach ($raw_preferences as $pref) {
+//                $type = $pref['notification_type'];
+//                $item_id = intval($pref['item_id']);
+//                $frequency = $pref['frequency'];
+//
+//                if (!isset($preferences[$type])) {
+//                    $preferences[$type] = [];
+//                }
+//                $preferences[$type][$item_id] = $frequency;
+//            }
+//        }
+//
+//        // Get default frequency
+//        $default_frequency = get_user_meta($user_id, BASE.'email_digest', true) ?: 'never';
+//
+////        error_log('Structured preferences: ' . print_r($preferences, true));
+////        error_log('Default frequency: ' . $default_frequency);
+//
+//        return [
+//            'preferences' => $preferences,
+//            'default_frequency' => $default_frequency
+//        ];
+//    }
+//
+//    public function handleInvitationsManagement(int $userID):void
+//    {
+//        $name = 'artist_invite';
+//        ?>
+<!--        <div class="field">-->
+<!--            <script type="text/javascript">-->
+<!--                function addArtist(button){-->
+<!--                    let template = window.getTemplate('artistInvite');-->
+<!--                    let container = button.closest('.field').querySelector('.invite-artists');-->
+<!---->
+<!--                    let nameLabel = template.querySelector('label[for="invited-artist-name"]'),-->
+<!--                        nameInput = template.querySelector('input#invited-artist-name'),-->
+<!--                        emailLabel = template.querySelector('label[for="invited-artist-email"]'),-->
+<!--                        emailInput = template.querySelector('input#invited-artist-email'),-->
+<!--                        shopLabel = template.querySelector('label[for="invited-add-to-shop"]'),-->
+<!--                        shopInput = template.querySelector('input#invited-add-to-shop');-->
+<!---->
+<!---->
+<!--                    let count = container.childNodes.length;-->
+<!--                    console.log(container.childNodes);-->
+<!--                    [-->
+<!--                        nameLabel.htmlFor,-->
+<!--                        nameInput.id,-->
+<!--                        nameInput.name,-->
+<!--                        emailLabel.htmlFor,-->
+<!--                        emailInput.id,-->
+<!--                        emailInput.name,-->
+<!--                        shopLabel.htmlFor,-->
+<!--                        shopInput.id,-->
+<!--                        shopInput.name-->
+<!--                    ] =-->
+<!--                    [-->
+<!--                        `${nameLabel.getAttribute('for')}-${count}`,-->
+<!--                        `${nameInput.id}-${count}`,-->
+<!--                        `${nameInput.name}-${count}`,-->
+<!--                        `${emailLabel.htmlFor}-${count}`,-->
+<!--                        `${emailInput.id}-${count}`,-->
+<!--                        `${emailInput.name}-${count}`,-->
+<!--                        `${shopLabel.htmlFor}-${count}`,-->
+<!--                        `${shopInput.id}-${count}`,-->
+<!--                        `${shopInput.name}-${count}`-->
+<!--                    ];-->
+<!--                    container.append(template);-->
+<!--                }-->
+<!--                function removeArtist(button){-->
+<!--                    button.closest('.invited-artist').remove();-->
+<!--                }-->
+<!---->
+<!--                async function revokeInvite(button){-->
+<!--                    try {-->
+<!--                        let artist = button.closest('tr');-->
+<!--                        let id = artist.id;-->
+<!---->
+<!--                        const headers = {-->
+<!--                            'X-WP-Nonce': eiSettings.nonce,-->
+<!--                            'action_nonce': eiSettings.dash,-->
+<!--                            'Content-Type': 'application/json'-->
+<!--                        };-->
+<!---->
+<!--                        let body = {-->
+<!--                            user: eiSettings.currentUser,-->
+<!--                            revoke: id-->
+<!--                        };-->
+<!--                        let request = {-->
+<!--                            method: 'POST',-->
+<!--                            headers: headers,-->
+<!--                            body: JSON.stringify(body)-->
+<!--                        };-->
+<!--                        console.log(request);-->
+<!---->
+<!---->
+<!--                        const response = await fetch(`${eiSettings.api}invitations`, request);-->
+<!---->
+<!--                        console.log(response);-->
+<!--                        if (!response.ok) {-->
+<!--                            const errorData = await response.json().catch(() => ({}));-->
+<!--                        }-->
+<!---->
+<!--                        const data =  await response.json();-->
+<!--                        if(data.success){-->
+<!--                            artist.remove();-->
+<!--                        }-->
+<!--                    }catch (error) {-->
+<!--                    }-->
+<!--                }-->
+<!---->
+<!--                async function resendInvite(button){-->
+<!--                    try {-->
+<!--                        let artist = button.closest('tr');-->
+<!--                        let id = artist.id;-->
+<!---->
+<!--                        const headers = {-->
+<!--                            'X-WP-Nonce': eiSettings.nonce,-->
+<!--                            'action_nonce': eiSettings.dash,-->
+<!--                            'Content-Type': 'application/json'-->
+<!--                        };-->
+<!---->
+<!--                        let body = {-->
+<!--                            user: eiSettings.currentUser,-->
+<!--                            refresh: id-->
+<!--                        };-->
+<!--                        let request = {-->
+<!--                            method: 'POST',-->
+<!--                            headers: headers,-->
+<!--                            body: JSON.stringify(body)-->
+<!--                        };-->
+<!--                        console.log(request);-->
+<!---->
+<!---->
+<!--                        const response = await fetch(`${eiSettings.api}invitations`, request);-->
+<!---->
+<!--                        console.log(response);-->
+<!--                        if (!response.ok) {-->
+<!--                            const errorData = await response.json().catch(() => ({}));-->
+<!--                        }-->
+<!---->
+<!--                        const data =  await response.json();-->
+<!---->
+<!--                    }catch (error) {-->
+<!--                    }-->
+<!--                }-->
+<!---->
+<!--                function sendInvites(button){-->
+<!--                    if(document.querySelector('.invited-artist')){-->
+<!--                        let newArtists = [];-->
+<!--                        document.querySelectorAll('.invited-artist').forEach(invited => {-->
+<!--                            let name = invited.querySelector('input[type="text"]'),-->
+<!--                                email = invited.querySelector('input[type="email"]'),-->
+<!--                                toShop = invited.querySelector('input[type="checkbox"]');-->
+<!--                            if(name.value === '' || email.value === ''){-->
+<!--                                invited.classList.add('required');-->
+<!--                                return;-->
+<!--                            }-->
+<!---->
+<!--                            newArtists.push({-->
+<!--                                name: name.value,-->
+<!--                                email: email.value,-->
+<!--                                toShop: toShop.checked-->
+<!--                            });-->
+<!--                            invited.remove();-->
+<!--                        });-->
+<!--                        if(newArtists.length > 0){-->
+<!--                            window.queueManager.addToQueue({-->
+<!--                                type: 'invite_artist',-->
+<!--                                data: newArtists-->
+<!--                            });-->
+<!--                        }-->
+<!--                    }-->
+<!--                }-->
+<!--            </script>-->
+<!---->
+<!--            <section class="invite-artists">-->
+<!--                <div class="invited-artist">-->
+<!--                    <button type="button" onclick="removeArtist(this)" title="Remove Invite">--><?php //=jvbIcon('trash')?><!--</button>-->
+<!--                    <div>-->
+<!--                        <label for="invited-artist-name-1">First Name</label>-->
+<!--                        <input type="text" id="invited-artist-name-1" name="invited-artist-name-1">-->
+<!--                    </div>-->
+<!--                    <div>-->
+<!--                        <label for="invited-artist-email-1">Email</label>-->
+<!--                        <input type="email" id="invited-artist-email-1" name="invited-artist-email-1">-->
+<!--                    </div>-->
+<!--                    <div>-->
+<!--                        <input type="checkbox" name="invited-add-to-shop-1" id="invited-add-to-shop-1">-->
+<!--                        <label for="invited-add-to-shop-1">Add to shop?</label>-->
+<!--                    </div>-->
+<!--                </div>-->
+<!--            </section>-->
+<!--            <div class="actions">-->
+<!--                <button type="button" onclick="addArtist(this)" class="add-artist">--><?php //= jvbIcon('plus-square')?><!--Add Artist</button>-->
+<!--                <button type="button" onclick="sendInvites(this)" class="send-invites">--><?php //=jvbIcon('envelope')?><!--Send Invites</button>-->
+<!--            </div>-->
+<!---->
+<!--            <template class="artistInvite">-->
+<!--                <div class="invited-artist">-->
+<!--                    <button type="button" onclick="removeArtist(this)" title="Remove Invite">--><?php //=jvbIcon('trash')?><!--</button>-->
+<!--                    <div>-->
+<!--                        <label for="invited-artist-name">First Name</label>-->
+<!--                        <input type="text" id="invited-artist-name" name="invited-artist-name">-->
+<!--                    </div>-->
+<!--                    <div>-->
+<!--                        <label for="invited-artist-email">Email</label>-->
+<!--                        <input type="email" id="invited-artist-email" name="invited-artist-email">-->
+<!--                    </div>-->
+<!--                    <div>-->
+<!--                        <input type="checkbox" name="invited-add-to-shop" id="invited-add-to-shop">-->
+<!--                        <label for="invited-add-to-shop">Add to shop?</label>-->
+<!--                    </div>-->
+<!--                </div>-->
+<!--            </template>-->
+<!--        </div>-->
+<!--        --><?php
+//
+//        $invites = JVB()->routes('invites')->getUserInvitations($userID);
+//
+//        ?>
+<!--        <table class="artist-invite">-->
+<!--            <thead>-->
+<!--                <tr>-->
+<!--                    <th scope="col" style="width:100%;">Name</th>-->
+<!--                    <th scope="col" style="padding:0 .5rem">Email</th>-->
+<!--                    <th scope="col" style="padding:0 .5rem">Status</th>-->
+<!--                    <th scope="col" style="padding:0 .5rem">Expires</th>-->
+<!--                    <th scope="col" style="padding:0 .5rem">Actions</th>-->
+<!--                </tr>-->
+<!--            </thead>-->
+<!--            <tbody>-->
+<!--            --><?php
+//            if (!empty($invites->invitations)) {
+//                foreach ($invites->invitations as $invite) {
+//                    ?>
+<!--                    <tr id="--><?php //=$invite['id']?><!--">-->
+<!--                        <td>-->
+<!--                            --><?php //=$invite['name']?>
+<!--                        </td>-->
+<!--                        <td>-->
+<!--                            --><?php //=$invite['email']?>
+<!--                        </td>-->
+<!--                        <td>-->
+<!--                            --><?php //=$invite['status']?>
+<!--                        </td>-->
+<!--                        <td>-->
+<!--                            --><?php //=$invite['expires_at']?>
+<!--                        </td>-->
+<!--                        <td class="actions">-->
+<!--                            <button type="button" data-action="revoke" title="Revoke Invitation" onclick="revokeInvite(this)">-->
+<!--                                --><?php //=jvbIcon('trash')?>
+<!--                                <span class="screen-reader-text">Revoke invite</span>-->
+<!--                            </button>-->
+<!--                            <button type="button" data-action="resend"--><?php //=($invite['status'] === 'exipired') ? '' : ' disabled'?><!-- title="Resend Invitation" onclick="resendInvite(this)">-->
+<!--                                --><?php //=jvbIcon('arrows-clockwise')?>
+<!--                                <span class="screen-reader-text">Try Again</span>-->
+<!--                            </button>-->
+<!--                        </td>-->
+<!---->
+<!--                    </tr>-->
+<!--                    --><?php
+//                }
+//            } else {
+//                ?>
+<!--                <tr><td><i>No invites yet</i></td><td></td><td></td><td></td><td></td></tr>-->
+<!--                --><?php
+//            }
+//            ?>
+<!--            </tbody>-->
+<!--        </table>-->
+<!--        --><?php
+//    }
+//}

--
Gitblit v1.10.0