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');
//}
//if (JVB_TESTING) {
// error_log('In testing mode...');
//} else {
// error_log('Not in testing mode...');
//}
const JVB_DIR = WP_PLUGIN_DIR . '/jvb';
define('JVB_URL', plugin_dir_url(__FILE__));
// Session Security
define('JVB_SESSION_FINGERPRINT', true);
// Login Security
define('JVB_MAX_LOGIN_ATTEMPTS', 5);
define('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)) {
?>