validateAll(); error_log('Validation result: '.print_r($validation, true)); $checker = JVBase\utility\Checker::getInstance(); error_log('Doing our activation action...'); // Get ContentRegistry instance early $registry = new JVBase\registry\ContentRegistry(); // Initialize content types $registry->onActivation(); $checker->invalidateContentCache(); $checker->invalidateTaxonomyCache(); do_action(BASE.'activation'); error_log('Action done!'); error_log('Checking custom tables...'); (new JVBase\registry\CheckCustomTables())->maybeCreateTables(); error_log('Tables created!'); // Store schema version update_option('jvb_db_version', '1.0.0'); error_log('Starting schedules...'); jvbSchedules(); error_log('Schedules done!'); error_log('checking Admin capabilities...'); jvbAddAdminCaps(); error_log('Admin caps done!'); error_log('Removing unneeded roles...'); remove_role('contributor'); remove_role('author'); remove_role('editor'); error_log('Roles removed!'); error_log('New Roles done!'); jvbRegisterAdminPages(); if (array_key_exists('integrations', JVB_SITE) && array_key_exists('umami', JVB_SITE['integrations']) && JVB_SITE['integrations']['umami']=== true) { error_log('Adding Umami tables'); Umami::createTables(); } if (Features::forSite()->has('is_directory')) { error_log('Activating DirectoryManager'); DirectoryManager::activate(); } error_log('Activation done! Huzzah!'); } function jvbAddAdminCaps() { $roleManager = new \JVBase\managers\RoleManager(); $role = get_role('administrator'); $users = get_users(['role' => 'administrator']); foreach (JVB_CONTENT as $slug => $config) { $plural = strtolower($config['plural']); $capabilities = [ 'edit_' . $plural, 'edit_published_' . $plural, 'publish_' . $plural, 'delete_' . $plural, 'delete_published_' . $plural, 'edit_others_' . $plural, 'delete_others_' . $plural, 'read_private_' . $plural, 'edit_private_' . $plural, 'delete_private_' . $plural, ]; foreach ($capabilities as $cap) { $role->add_cap($cap, true); } foreach ($users as $user) { $roleManager->grantContent($user, $slug); $roleManager->grantOthersContent($user, $slug); } } add_action('init', 'jvbGrantAdminUserCaps', 99); } /** * Grant capabilities to admin users after post types are registered * This runs on init with high priority to ensure post types exist */ function jvbGrantAdminUserCaps() { // Only run once after activation if (get_option('jvb_admin_caps_granted') === '1') { return; } $roleManager = new \JVBase\managers\RoleManager(); $users = get_users(['role' => 'administrator']); foreach (JVB_CONTENT as $slug => $config) { foreach ($users as $user) { // These methods should check if post type exists before adding caps $roleManager->grantContent($user, $slug); $roleManager->grantOthersContent($user, $slug); } } // Mark as complete to prevent running again update_option('jvb_admin_caps_granted', '1'); remove_action('init', 'jvbGrantAdminUserCaps', 99); } function jvbScheduledHooks() { return [ 'jvb_daily_reset' => [ 'time' => '00:01', 'recurrence' => 'daily' ], 'jvb_process_queue' => [ 'recurrence' => 'every-minute', ], 'jvb_queue_maintenance' => [ 'time' => '1:05am', 'recurrence' => 'hourly' ], 'jvbEmailDailyMetricsReport' => [ 'time' => '4:15am tomorrow' ], 'jvb_generate_daily_report' => [ 'time' => '1:20am tomorrow', ], 'jvb_daily_error_summary' => [ 'time' => '7:01am tomorrow', ], 'jvb_cleanup_expired_approvals' => [], 'jvb_cleanupOrphanedFavourites' => [], 'jvb_daily_maintenance' => [ 'time' => '12:03am tomorrow', ], //NotificationManager.php 'jvb_notification_digest_daily' => [ 'time' => '8:08am tomorrow', ], 'jvb_notification_digest_weekly' => [ 'time' => 'monday 6:07am', 'recurrence' => 'weekly', ], 'jvb_notification_digest_monthly' => [ 'time' => '2025-05-05 9:00am', 'recurrence' => 'monthly', ], ]; } function jvbSchedules() { $hooks = jvbScheduledHooks(); //TODO: ensure we actually need these foreach ($hooks as $hook => $options) { $time = (array_key_exists('time', $options)) ? strtotime($options['time']) : time(); $recurrence = (array_key_exists('recurrence', $options)) ? $options['recurrence'] : 'daily'; if (!wp_next_scheduled($hook)) { $result = wp_schedule_event($time, $recurrence, $hook); if (!$result) { error_log('Did not schedule '.$hook.' successfully...'.print_r($result, true)); error_log('Time: '.print_r($time, true)); error_log('Recurrence: '.print_r($recurrence, true)); } } } } function jvbDeactivatePlugin() { jvbClearSchedules(); jvbDeleteOptions(); jvbDeleteDashboard(); jvbDeleteDirectories(); Cache::flushAll(); do_action('jvbDeactivate'); } function jvbDeleteOptions():void { $options = array_filter( wp_load_alloptions(), fn ($key) => str_starts_with($key, BASE) || str_starts_with($key, '_transient_'.BASE) || str_starts_with($key, '_transient_timeout_'.BASE), ARRAY_FILTER_USE_KEY ); foreach ($options as $key => $value) { delete_option($key); } } function jvbDeleteDashboard() { $pages = new WP_Query([ 'post_type' => BASE.'dash', 'posts_per_page' => -1, 'post_status' => 'any', 'fields' => 'ids' ]); if ($pages->have_posts()) { foreach ($pages->posts as $ID) { wp_delete_post($ID, true); } } } function jvbDeleteDirectories() { $pages = new WP_Query([ 'post_type' => BASE.'directory', 'posts_per_page' => -1, 'post_status' => ['publish', 'draft','trash'], 'fields' => 'ids' ]); foreach ($pages->posts as $ID) { wp_delete_post($ID, true); } } function jvbClearSchedules() { $hooks = array_keys(jvbScheduledHooks()); foreach ($hooks as $hook) { wp_clear_scheduled_hook($hook); } } // Optional: Add upgrade routine function jvbMaybeUpgrade():void { $current_version = get_option('jvb_db_version', '0'); if (version_compare($current_version, '1.0.0', '<')) { jvbActivatePlugin(); } } add_action('plugins_loaded', 'jvbMaybeUpgrade'); add_action('jvb_daily_reset', 'jvbDailyResetAction'); function jvbDailyResetAction(): void { do_action('jvbDailyReset'); error_log('Daily options reset completed at ' . current_time('Y-m-d H:i:s')); } function jvbRegisterAdminPages():void { if (Features::forSite()->has('referrals')){ ReferralManager::addSubpage(); } SEOAdminPage::addSubpage(); }