Developer FAQ – Reign WP Job Manager Addon

Get Started

Architecture & Compatibility

Q: What’s the purpose of the new compatibility layer?

A: The compatibility layer (v2.9.0) provides:

  • Middleware between Reign theme and WP Job Manager plugins
  • Custom hooks that won’t break when plugins update
  • Centralized integration point for all three WP Job Manager plugins
  • Future-proof architecture for adding new features

Q: How does the plugin maintain backward compatibility?

A: We ensure backward compatibility by:

  1. Never removing existing hooks/functions
  2. Adding new features through filters
  3. Using deprecation notices before removing features
  4. Maintaining original function signatures
  5. Testing with multiple WP/plugin versions

Q: What’s the hook execution order?

A: Hook priority order:

// Priority 5-9: Early modifications
// Priority 10: Default (most hooks)
// Priority 20-50: Late modifications
// Priority 99-999: Cleanup and final modifications

Hooks & Filters

Q: Should I use WP Job Manager hooks or Reign hooks?

A: Best practice:

  • Use Reign hooks (reign_wpjm_*) for Reign-specific customizations
  • Use WP Job Manager hooks for plugin-agnostic features
  • Reign hooks provide additional data and won’t break with updates

Example:

// Preferred: Use Reign hook
add_filter( 'reign_wpjm_job_query_args', 'my_custom_query', 10, 2 );

// Alternative: Direct WP Job Manager hook
add_filter( 'get_job_listings_query_args', 'my_custom_query', 10, 2 );

Q: How do I add custom job fields?

A: Multiple approaches:

// Method 1: Via form fields filter
add_filter( 'submit_job_form_fields', function( $fields ) {
    $fields['job']['custom_field'] = array(
        'label' => 'Custom Field',
        'type' => 'text',
        'required' => false,
        'priority' => 30
    );
    return $fields;
} );

// Method 2: Via Reign compatibility hook
add_filter( 'reign_wpjm_job_fields', function( $fields ) {
    // Add custom field
    return $fields;
} );

// Save the field
add_action( 'job_manager_update_job_data', function( $job_id, $values ) {
    if ( isset( $values['job']['custom_field'] ) ) {
        update_post_meta( $job_id, '_custom_field', sanitize_text_field( $values['job']['custom_field'] ) );
    }
}, 10, 2 );

Q: How do I modify job queries?

A: Use the query filter:

add_filter( 'reign_wpjm_job_query_args', function( $query_args, $args ) {
    // Only show jobs from last 30 days
    $query_args['date_query'] = array(
        array(
            'after' => '30 days ago'
        )
    );
    
    // Exclude filled positions
    $query_args['meta_query'][] = array(
        'key' => '_filled',
        'value' => '1',
        'compare' => '!='
    );
    
    return $query_args;
}, 10, 2 );

Templates

Q: How do I override templates?

A: Template hierarchy:

1. /yourtheme/job_manager/template-name.php (highest priority)
2. /yourtheme/template-name.php
3. /reign-wp-job-manager-addon/templates/job_manager/template-name.php
4. /wp-job-manager/templates/template-name.php (lowest priority)

Example override:

// Copy from: 
// /plugins/reign-wp-job-manager-addon/templates/job_manager/content-single-job_listing.php

// To:
// /themes/your-theme/job_manager/content-single-job_listing.php

Q: How do I create a custom layout?

A: Create new layout template:

// 1. Create template file
// /yourtheme/job_manager/content-job_listing_custom.php

// 2. Register the layout
add_filter( 'reign_job_layouts', function( $layouts ) {
    $layouts['custom'] = __( 'Custom Layout', 'text-domain' );
    return $layouts;
} );

// 3. Load the template
add_filter( 'reign_job_layout_template', function( $template, $layout ) {
    if ( 'custom' === $layout ) {
        $template = 'content-job_listing_custom.php';
    }
    return $template;
}, 10, 2 );

Q: How do I add content to specific template positions?

A: Use template hooks:

// Add content before job meta
add_action( 'job_listing_meta_start', function() {
    echo '<div class="featured-badge">Featured</div>';
} );

// Add content after single job
add_action( 'single_job_listing_end', function() {
    get_template_part( 'parts/related', 'jobs' );
} );

// Add to resume sidebar
add_action( 'single_resume_sidebar', function() {
    echo '<div class="contact-form">Contact Form Here</div>';
}, 25 ); // Priority 25 to position it correctly

Custom Post Types & Taxonomies

Q: How do I add custom taxonomies?

A: Register and integrate:

// 1. Register taxonomy
add_action( 'init', function() {
    register_taxonomy( 'job_department', array( 'job_listing' ), array(
        'labels' => array(
            'name' => 'Departments',
            'singular_name' => 'Department'
        ),
        'public' => true,
        'hierarchical' => true
    ) );
} );

// 2. Add to submission form
add_filter( 'submit_job_form_fields', function( $fields ) {
    $fields['job']['job_department'] = array(
        'label' => 'Department',
        'type' => 'term-multiselect',
        'taxonomy' => 'job_department',
        'required' => false,
        'priority' => 35
    );
    return $fields;
} );

Q: How do I modify post type arguments?

A: Use the registration filter:

add_filter( 'register_post_type_job_listing', function( $args ) {
    // Add excerpt support
    $args['supports'][] = 'excerpt';
    
    // Change slug
    $args['rewrite']['slug'] = 'careers';
    
    return $args;
} );

Database & Performance

Q: How do I optimize job queries?

A: Performance tips:

// 1. Use transients for expensive queries
function get_featured_jobs( $limit = 5 ) {
    $cache_key = 'featured_jobs_' . $limit;
    $jobs = get_transient( $cache_key );
    
    if ( false === $jobs ) {
        $jobs = get_posts( array(
            'post_type' => 'job_listing',
            'meta_key' => '_featured',
            'meta_value' => '1',
            'posts_per_page' => $limit,
            'fields' => 'ids' // Only get IDs for better performance
        ) );
        set_transient( $cache_key, $jobs, HOUR_IN_SECONDS );
    }
    
    return $jobs;
}

// 2. Add database indexes
function add_custom_indexes() {
    global $wpdb;
    $wpdb->query( "ALTER TABLE {$wpdb->postmeta} ADD INDEX reign_job_featured (_featured)" );
}

// 3. Use specific queries
$job_count = $wpdb->get_var( "
    SELECT COUNT(*) 
    FROM {$wpdb->posts} 
    WHERE post_type = 'job_listing' 
    AND post_status = 'publish'
" );

Q: How do I handle large datasets?

A: Pagination and lazy loading:

// AJAX pagination
add_action( 'wp_ajax_load_more_jobs', 'handle_load_more_jobs' );
add_action( 'wp_ajax_nopriv_load_more_jobs', 'handle_load_more_jobs' );

function handle_load_more_jobs() {
    $page = intval( $_POST['page'] );
    $per_page = 10;
    
    $jobs = get_posts( array(
        'post_type' => 'job_listing',
        'posts_per_page' => $per_page,
        'paged' => $page,
        'post_status' => 'publish'
    ) );
    
    ob_start();
    foreach ( $jobs as $job ) {
        reign_job_mate_get_template( 'content-job_listing.php', array( 'post' => $job ) );
    }
    $html = ob_get_clean();
    
    wp_send_json_success( array( 'html' => $html ) );
}

AJAX & REST API

Q: How do I create custom AJAX endpoints?

A: Register AJAX handlers:

// Register AJAX action
add_action( 'wp_ajax_reign_custom_action', 'handle_custom_action' );
add_action( 'wp_ajax_nopriv_reign_custom_action', 'handle_custom_action' );

function handle_custom_action() {
    // Verify nonce
    if ( ! wp_verify_nonce( $_POST['nonce'], 'reign_ajax_nonce' ) ) {
        wp_die( 'Security check failed' );
    }
    
    // Process request
    $data = array(
        'success' => true,
        'message' => 'Action completed'
    );
    
    wp_send_json( $data );
}

// JavaScript
jQuery.ajax({
    url: reign_ajax.ajax_url,
    type: 'POST',
    data: {
        action: 'reign_custom_action',
        nonce: reign_ajax.nonce
    },
    success: function( response ) {
        console.log( response );
    }
});

Q: How do I add REST API endpoints?

A: Register custom routes:

add_action( 'rest_api_init', function() {
    register_rest_route( 'reign/v1', '/jobs/featured', array(
        'methods' => 'GET',
        'callback' => 'get_featured_jobs_api',
        'permission_callback' => '__return_true'
    ) );
} );

function get_featured_jobs_api( WP_REST_Request $request ) {
    $jobs = get_posts( array(
        'post_type' => 'job_listing',
        'meta_key' => '_featured',
        'meta_value' => '1',
        'posts_per_page' => 10
    ) );
    
    return rest_ensure_response( $jobs );
}

Security

Q: How do I properly sanitize user input?

A: Use appropriate sanitization:

// Text fields
$text = sanitize_text_field( $_POST['text_field'] );

// Email
$email = sanitize_email( $_POST['email'] );

// URL
$url = esc_url_raw( $_POST['url'] );

// HTML content
$html = wp_kses_post( $_POST['description'] );

// Numbers
$number = intval( $_POST['number'] );
$float = floatval( $_POST['price'] );

// File uploads
if ( ! function_exists( 'wp_handle_upload' ) ) {
    require_once( ABSPATH . 'wp-admin/includes/file.php' );
}
$uploaded_file = wp_handle_upload( $_FILES['file'], array( 'test_form' => false ) );

Q: How do I implement proper capability checks?

A: Check user permissions:

// Check capabilities
if ( ! current_user_can( 'edit_job_listings' ) ) {
    wp_die( 'Insufficient permissions' );
}

// Custom capability
add_filter( 'user_has_cap', function( $allcaps, $caps, $args ) {
    if ( isset( $caps[0] ) && 'manage_job_applications' === $caps[0] ) {
        if ( user_can( $args[1], 'edit_others_job_listings' ) ) {
            $allcaps['manage_job_applications'] = true;
        }
    }
    return $allcaps;
}, 10, 3 );

Customization

Q: How do I add custom CSS/JS to specific pages?

A: Conditional enqueuing:

add_action( 'wp_enqueue_scripts', function() {
    // Only on job pages
    if ( is_singular( 'job_listing' ) ) {
        wp_enqueue_style( 
            'reign-job-custom', 
            get_stylesheet_directory_uri() . '/assets/css/job-custom.css' 
        );
        
        wp_enqueue_script( 
            'reign-job-custom', 
            get_stylesheet_directory_uri() . '/assets/js/job-custom.js',
            array( 'jquery' ),
            '1.0.0',
            true
        );
        
        // Localize script
        wp_localize_script( 'reign-job-custom', 'reign_job_vars', array(
            'ajax_url' => admin_url( 'admin-ajax.php' ),
            'job_id' => get_the_ID(),
            'nonce' => wp_create_nonce( 'reign_job_nonce' )
        ) );
    }
} );

Q: How do I create a child theme compatible with the addon?

A: Child theme structure:

// child-theme/functions.php
add_action( 'after_setup_theme', function() {
    // Load parent and child styles
    add_action( 'wp_enqueue_scripts', function() {
        wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
        wp_enqueue_style( 'child-style', get_stylesheet_uri(), array( 'parent-style' ) );
    } );
} );

// Override templates by placing them in:
// child-theme/job_manager/template-name.php
// child-theme/wp-job-manager-resumes/template-name.php

Debugging & Testing

Q: How do I debug hook execution?

A: Debug helpers:

// Log hook execution
add_action( 'all', function( $hook ) {
    if ( strpos( $hook, 'reign' ) !== false || strpos( $hook, 'job' ) !== false ) {
        error_log( "Hook fired: " . $hook );
    }
} );

// Check if hook exists
if ( has_action( 'reign_wpjm_job_submitted' ) ) {
    error_log( 'Hook has callbacks attached' );
}

// List all callbacks for a hook
global $wp_filter;
if ( isset( $wp_filter['reign_wpjm_job_submitted'] ) ) {
    var_dump( $wp_filter['reign_wpjm_job_submitted'] );
}

Q: How do I test compatibility with different plugin versions?

A: Version checking:

// Check plugin versions
if ( defined( 'JOB_MANAGER_VERSION' ) ) {
    if ( version_compare( JOB_MANAGER_VERSION, '2.0.0', '<' ) ) {
        // Use legacy code
    } else {
        // Use modern code
    }
}

// Feature detection
if ( function_exists( 'wpjm_get_the_job_types' ) ) {
    // Function exists, safe to use
}

// Class detection
if ( class_exists( 'WP_Job_Manager_Applications' ) ) {
    // Applications plugin is active
}

Migration & Updates

Q: How do I migrate from direct WP Job Manager integration?

A: Migration steps:

// Old way (direct)
add_action( 'job_listing_meta_start', 'my_function' );

// New way (compatibility layer)
add_action( 'reign_wpjm_job_listing_meta_start', 'my_function' );

// Migration helper
function migrate_to_reign_hooks() {
    // Remove old hook
    remove_action( 'job_listing_meta_start', 'old_function' );
    
    // Add new hook
    add_action( 'reign_wpjm_job_listing_meta_start', 'new_function' );
}
add_action( 'init', 'migrate_to_reign_hooks', 999 );

Q: How do I handle database updates?

A: Version-based updates:

function reign_job_manager_update_check() {
    $current_version = get_option( 'reign_job_manager_version', '1.0.0' );
    
    if ( version_compare( $current_version, '2.9.0', '<' ) ) {
        // Run 2.9.0 updates
        reign_job_manager_update_290();
        update_option( 'reign_job_manager_version', '2.9.0' );
    }
}

function reign_job_manager_update_290() {
    // Update database schema
    // Migrate settings
    // Clear caches
}

Common Issues & Solutions

Q: Templates not overriding properly?

A: Troubleshooting steps:

  1. Check template path is correct
  2. Clear all caches
  3. Check template hierarchy
  4. Verify filter priority
  5. Use template debug mode
// Debug template loading
add_filter( 'reign_job_manager_locate_template', function( $template, $template_name ) {
    error_log( "Loading template: {$template_name} from {$template}" );
    return $template;
}, 10, 2 );

Q: Hooks not firing?

A: Check:

  1. Hook name is correct
  2. Priority conflicts
  3. Conditional loading
  4. Plugin load order
// Force early loading
add_action( 'plugins_loaded', function() {
    // Your hooks here
}, 5 ); // Priority 5 = very early

Q: Performance issues with many jobs?

A: Optimization strategies:

  1. Use pagination
  2. Implement caching
  3. Optimize queries
  4. Use AJAX loading
  5. Add database indexes

Best Practices

Do’s

  • Use Reign compatibility hooks when available
  • Sanitize all user input
  • Use nonces for forms
  • Cache expensive operations
  • Follow WordPress coding standards
  • Test with multiple plugin versions
  • Use child themes for customization

Don’ts

  • Don’t modify plugin files directly
  • Don’t use deprecated functions
  • Don’t bypass security checks
  • Don’t load resources globally
  • Don’t hardcode paths
  • Don’t ignore error messages
  • Don’t skip validation

Resources

Tools

 

  • Query Monitor plugin for debugging
  • Theme Check plugin for validation
  • Debug Bar for development
  • Postman for API testing

Code Examples

// Complete example: Custom job widget
class Reign_Featured_Jobs_Widget extends WP_Widget {
    public function __construct() {
        parent::__construct(
            'reign_featured_jobs',
            'Featured Jobs',
            array( 'description' => 'Display featured job listings' )
        );
    }
    
    public function widget( $args, $instance ) {
        $jobs = get_posts( array(
            'post_type' => 'job_listing',
            'meta_key' => '_featured',
            'meta_value' => '1',
            'posts_per_page' => 5
        ) );
        
        echo $args['before_widget'];
        echo $args['before_title'] . $instance['title'] . $args['after_title'];
        
        echo '<ul>';
        foreach ( $jobs as $job ) {
            printf( 
                '<li><a href="%s">%s</a></li>',
                get_permalink( $job ),
                get_the_title( $job )
            );
        }
        echo '</ul>';
        
        echo $args['after_widget'];
    }
}

add_action( 'widgets_init', function() {
    register_widget( 'Reign_Featured_Jobs_Widget' );
} );
Last updated: September 4, 2025