queue ?? []; // foreach ($queue as $handle) { // $src = $wp_scripts->registered[$handle]->src ?? 'unknown'; // error_log("Enqueued: $handle => $src"); // } // }, 999); //}, 999); /** * Track REST API errors by wrapping request execution */ //add_filter('rest_pre_dispatch', function($result, $server, $request) { // // Store request details globally for error logging // $GLOBALS['jvb_rest_request'] = [ // 'route' => $request->get_route(), // 'method' => $request->get_method(), // 'params' => $request->get_params(), // 'time' => microtime(true), // ]; // // // Set up error handler for this request // set_error_handler(function($errno, $errstr, $errfile, $errline) { // if (!(error_reporting() & $errno)) { // return false; // } // // $context = array_merge($GLOBALS['jvb_rest_request'] ?? [], [ // 'error_type' => $errno, // 'error_message' => $errstr, // 'file' => $errfile, // 'line' => $errline, // 'user_id' => get_current_user_id(), // ]); // // error_log('JVB REST Error: ' . json_encode($context)); // // return false; // Let PHP handle it normally too // }); // // return $result; //}, 10, 3); // //add_filter('rest_post_dispatch', function($result, $server, $request) { // // Restore default error handler // restore_error_handler(); // // // Check for fatal errors that occurred during request // $error = error_get_last(); // if ($error && in_array($error['type'], [E_ERROR, E_USER_ERROR, E_PARSE, E_COMPILE_ERROR])) { // $context = array_merge($GLOBALS['jvb_rest_request'] ?? [], [ // 'fatal_error' => $error, // 'user_id' => get_current_user_id(), // ]); // // error_log('JVB REST Fatal: ' . json_encode($context)); // } // // // Clean up // unset($GLOBALS['jvb_rest_request']); // // return $result; //}, 10, 3); function jvbIgnoredPostTypes():array { return [BASE.'directory', BASE.'dash', 'attachment', 'revision', 'nav_menu_item']; } define('JVB_TESTING', str_contains(get_home_url(),'.test')); //const JVB_TESTING = false; //if (!JVB_TESTING) { // add_filter('show_admin_bar', '__return_false'); //} const JVB_DIR = WP_PLUGIN_DIR . '/jvb'; define('JVB_URL', plugin_dir_url(__FILE__)); // Session Security const JVB_SESSION_FINGERPRINT = true; // Login Security const JVB_MAX_LOGIN_ATTEMPTS = 5; const JVB_LOCKOUT_DURATION = 15 * MINUTE_IN_SECONDS; require(JVB_DIR.'/inc/Instance.php'); require(JVB_DIR.'/base/_setup.php'); require(JVB_DIR.'/inc/utility/setup.php'); require(JVB_DIR.'/checks.php'); require(JVB_DIR . '/inc/integrations/ServiceMap.php'); require(JVB_DIR . '/inc/registrar/_setup.php'); require(JVB_DIR . '/activate.php'); require(JVB_DIR . '/inc/helpers/all.php'); require(JVB_DIR . '/inc/ui/_setup.php'); require(JVB_DIR . '/inc/meta/_setup.php'); require(JVB_DIR . '/inc/importers/_setup.php'); require(JVB_DIR . '/inc/managers/_setup.php'); /** * Get an icon element * * @param string $name Icon name * @param array $options Options array: * - 'source' => 'icons'|'dash'|'forms'|etc. (default: 'icons') * - 'style' => 'regular'|'bold'|'fill'|etc. * - 'label' => 'Accessible label' * - 'decorative' => true * - 'class' => 'additional classes' * - 'size' => 24 * @return string HTML icon element */ function jvbIcon(string $name, array $options = []): string { $source = $options['source'] ?? 'icons'; // Remove source from options before passing to IconsManager unset($options['source']); return IconsManager::for($source)->get($name, $options); } function jvbFullIcon(string $name, array $options = []):string { $source = $options['source'] ?? 'icons'; unset($options['source']); return IconsManager::for($source)->getRawSvg($name, $options['style']??null); } /** * Get a CSS data URI for an icon * * @param string $name Icon name * @param array $options Options array: * - 'style' => 'regular'|'bold'|'fill'|etc. * - 'source' => 'icons'|'dash'|'forms'|etc. (for tracking purposes) * @return string data:image/svg+xml;base64,... URL */ function jvbCSSIcon(string $name, array $options = []): string { $style = $options['style'] ?? null; $source = $options['source'] ?? 'icons'; return IconsManager::for($source)->getCSSIcon($name, $style); } /** * Get a dashboard icon */ function jvbDashIcon(string $name, array $options = []): string { $options['source'] = 'dash'; return jvbIcon($name, $options); } /** * Get a form editor icon */ function jvbFormIcon(string $name, array $options = []): string { $options['source'] = 'forms'; return jvbIcon($name, $options); } require(JVB_DIR . '/inc/integrations/_setup.php'); require(JVB_DIR . '/inc/rest/_setup.php'); add_filter( 'cron_schedules', 'jvbCronSchedules'); function jvbCronSchedules($schedules) { $schedules[ 'every-5-minutes' ] = [ 'interval' => 5 * 60, 'display' => __('Every 5 minutes', 'jvb') ]; $schedules[ 'every-minute' ] = [ 'interval' => 60, 'display' => __('Every minute', 'jvb') ]; $schedules[ 'monthly' ] = [ 'interval' => MONTH_IN_SECONDS, 'display' => __('Once Monthly', 'jvb') ]; return $schedules; } register_activation_hook(JVB_DIR.'/jvb.php', 'jvbActivatePlugin'); register_deactivation_hook(JVB_DIR.'/jvb.php', 'jvbDeactivatePlugin'); //require(JVB_DIR . '/inc/users/UserSettings.php'); require(JVB_DIR . '/inc/templates.php'); /** * Utilities */ //require(JVB_DIR . '/cleanup.php'); require(JVB_DIR . '/inc/admin/_setup.php'); require(JVB_DIR . '/JVBase.php'); /** * After moving to the Registrar::based registration, we need to carefully time * when Site gets defined, as well as Registrar initial definitions, field definitions, * and integration config * These custom actions should simplify the timing for us. */ add_action('plugins_loaded', 'jvb_site_definitions',1); add_action('plugins_loaded', 'jvb_registrar_definitions',2); add_action('plugins_loaded', 'jvb_field_definitions', 3); add_action('plugins_loaded', 'jvb_options_definitions',3); add_action('init', 'jvbLoadBase', 2); add_action('init', 'jvb_integration_definitions',3); add_action('init', 'jvb_field_section_definitions', 5); /** * Can define the Site settings * @return void */ function jvb_site_definitions():void { do_action('jvb_define_site'); } function jvb_registrar_definitions():void { do_action('jvb_define_registrar'); } function jvb_field_definitions():void { do_action('jvb_define_fields'); } function jvb_options_definitions():void { do_action('jvb_define_options'); } function jvbLoadBase():void { do_action('jvbloaded'); Emails::getInstance(); Queue::getInstance(); Roles::getInstance(); Login::getInstance(); SEOAdmin::getInstance(); SchemaOutput::getInstance(); SchemaHelper::getInstance(); CustomBlocks::getInstance(); AdminPages::getInstance(); if (Site::has('magic_link')) { MagicLinks::getInstance(); } if (Site::has('dashboard')) { Dashboard::getInstance(); } if (Site::has('referrals')) { Referrals::getInstance(); } if (Site::has('is_directory')) { DirectoryManager::getInstance(); } if (Site::has('feed_block')) { TaxonomyRelationships::getInstance(); } if (Site::hasAll(['dashboard', 'membership', 'feed_block'])) { UserTermsManager::getInstance(); } if (Site::has('favourites')) { Favourites::getInstance(); } if (!empty(Registrar::withFeature('has_responses'))) { Responses::getInstance(); } $membership = Site::membership(); if ($membership && $membership->has('notifications')) { NotificationManager::getInstance(); } if ($membership && $membership->has('invitable')) { InvitationsManager::getInstance(); } if (!empty(Registrar::withFeature('approve_new'))) { Approvals::getInstance(); } jvbLoadRoutes(); } function jvb_integration_definitions():void { do_action('jvb_define_integrations'); } function jvb_field_section_definitions():void { do_action('jvb_define_field_sections'); Registrar::maybeBuildSections(); } add_action('wp_footer', 'jvbAdditionalActions'); function jvbAdditionalActions():void { if (Login::isLogin()) { return; } $extras = apply_filters('jvbAdditionalActions', []); $extras = array_filter($extras, function ($extra) { return is_array($extra) && array_key_exists('button', $extra) && array_key_exists('content', $extra); }); if (empty ($extras)) { return; } $buttons = array_map(function ($extra) { return $extra['button']; }, $extras); $contents = array_map(function($extra) { return $extra['content']; }, $extras); if (!empty ($buttons)) { ?>
has('forum')) { NewsRoutes::getInstance(); } } require(JVB_DIR . '/inc/blocks/_setup.php'); add_filter('upload_mimes', function ($mimes) { $mimes['webp'] = 'image/webp'; $mimes['avif'] = 'image/avif'; return $mimes; }); // And this to ensure WebP is treated as an image add_filter('file_is_displayable_image', function ($result, $path) { if (preg_match('/\.webp$/i', $path)) { return true; } return $result; }, 10, 2); function jvbDump(mixed $array, string $name = 'var'):void { highlight_string(""); } function jvbAdminMap():void { // wp_enqueue_script( // 'google-maps', // 'https://maps.googleapis.com/maps/api/js?key=' . GOOGLE_API . '&libraries=places&callback=googleMapsLoaded', // [], // null, // [ // 'strategy' => 'async', // 'in_footer' => true // ] // ); // // // Add the callback function // wp_add_inline_script('google-maps', ' // function googleMapsLoaded() { // if (window.googleMapsCallbacks && window.googleMapsCallbacks.length) { // window.googleMapsCallbacks.forEach(callback => callback()); // } // } // '); } add_action('wp_body_open', 'jvbAccessibility'); function jvbAccessibility():void { echo '
'; } /* add_action('wp_head', 'jvbFrontendBase',1); function jvbFrontendBase():void { roles, true)); //}); // //add_filter('rest_pre_dispatch', function($result, $server, $request) { // if (strpos($request->get_route(), '/wp/v2/pages') !== false) { // error_log('Pages request - User: ' . get_current_user_id()); // error_log('Can edit pages: ' . (current_user_can('edit_pages') ? 'yes' : 'no')); // error_log('Nonce: ' . $request->get_header('X-WP-Nonce')); // } // return $result; //}, 10, 3); add_action('wp_footer', 'jvb_back_to_top'); function jvb_back_to_top():void { echo sprintf( '%sBack to Top', jvbIcon('caret-double-up') ); } add_action( 'doing_it_wrong_run', function ( $function_name ) { if ( '_load_textdomain_just_in_time' === $function_name ) { // This will print the full execution path to your screen or log debug_print_backtrace(); } } ); add_filter('the_seo_framework_sitemap_exclude_ids', 'jvb_maybe_exclude_singles', 8, 1); function jvb_maybe_exclude_singles(array $IDs):array { return Registrar::maybeExcludeSingles($IDs); }