LearnPress uses WordPress’s powerful hooks system to allow developers to extend and customize the plugin’s functionality without modifying core files. This approach ensures that your customizations remain intact even after plugin updates.
Introduction to WordPress Hooks
WordPress hooks come in two varieties:
- Actions: Allow you to add or change functionality at specific points in execution
- Filters: Allow you to modify data before it’s used or displayed
LearnPress extends this system with its own set of hooks that are specific to LMS functionality.
How LearnPress Uses Hooks
LearnPress implements hooks throughout its codebase to create a flexible and extensible architecture:
- Template hooks allow customization of the HTML output
- Process hooks enable modification of business logic
- Data hooks permit alteration of data before it’s saved or retrieved
The main hook files in LearnPress are:
- inc/lp-template-hooks.php– Defines template-related hooks
- inc/lp-core-hooks.php– Defines core functionality hooks
- Various class files that define specific hooks for their functionality
Key Action Hooks
Action hooks allow you to execute custom code at specific points in LearnPress’s execution flow.
Course Actions
| Hook | Description | Parameters | Usage Example | 
|---|---|---|---|
| learn-press/before-course-content | Fires before the course content is displayed | None | 
add_action('learn-press/before-course-content', function() {
    echo '<div class="my-custom-banner">Special Offer!</div>';
}); | 
| learn-press/after-course-content | Fires after the course content is displayed | None | 
add_action('learn-press/after-course-content', function() {
    echo '<div class="related-courses">You might also like...</div>';
}); | 
| learn-press/before-single-course | Fires before the single course template | None | 
add_action('learn-press/before-single-course', function() {
    // Add custom content before course
}); | 
| learn-press/after-single-course | Fires after the single course template | None | 
add_action('learn-press/after-single-course', function() {
    // Add custom content after course
}); | 
| learn-press/course-content-summary | Used to build the course content summary | None | 
add_action('learn-press/course-content-summary', function() {
    echo '<div class="custom-course-info">...</div>';
}, 15); | 
Lesson and Quiz Actions
| Hook | Description | Parameters | Usage Example | 
|---|---|---|---|
| learn-press/before-content-item-summary/lp_lesson | Fires before lesson content | None | 
add_action('learn-press/before-content-item-summary/lp_lesson', function() {
    echo '<div class="lesson-prerequisites">Before starting...</div>';
}); | 
| learn-press/before-content-item-summary/lp_quiz | Fires before quiz content | None | 
add_action('learn-press/before-content-item-summary/lp_quiz', function() {
    echo '<div class="quiz-instructions">Quiz instructions...</div>';
}); | 
| learn-press/quiz-started | Fires when a user starts a quiz | $quiz_id, $course_id, $user_id | 
add_action('learn-press/quiz-started', function($quiz_id, $course_id, $user_id) {
    // Log quiz start or perform other actions
}, 10, 3); | 
| learn-press/quiz-completed | Fires when a user completes a quiz | $quiz_id, $course_id, $user_id, $result | 
add_action('learn-press/quiz-completed', function($quiz_id, $course_id, $user_id, $result) {
    // Process quiz completion
}, 10, 4); | 
Checkout and Enrollment Actions
| Hook | Description | Parameters | Usage Example | 
|---|---|---|---|
| learn-press/before-checkout-form | Fires before the checkout form | None | 
add_action('learn-press/before-checkout-form', function() {
    echo '<div class="checkout-notice">Important information...</div>';
}); | 
| learn-press/after-checkout-form | Fires after the checkout form | None | 
add_action('learn-press/after-checkout-form', function() {
    echo '<div class="checkout-support">Need help?</div>';
}); | 
| learn-press/user-enrolled-course | Fires when a user enrolls in a course | $course_id, $user_id, $user_course | 
add_action('learn-press/user-enrolled-course', function($course_id, $user_id, $user_course) {
    // Send welcome email or perform other actions
}, 10, 3); | 
| learn-press/order/status-changed | Fires when an order’s status changes | $order_id, $old_status, $new_status | 
add_action('learn-press/order/status-changed', function($order_id, $old_status, $new_status) {
    if ($new_status === 'completed') {
        // Process completed order
    }
}, 10, 3); | 
Key Filter Hooks
Filter hooks allow you to modify data before it’s used by LearnPress.
Course Filters
| Hook | Description | Parameters | Usage Example | 
|---|---|---|---|
| learn-press/course-price-html | Filters the HTML output of course price | $price_html, $course | 
add_filter('learn-press/course-price-html', function($price_html, $course) {
    // Modify price display
    return '<span class="special-price">' . $price_html . '</span>';
}, 10, 2); | 
| learn-press/single-course/modern/info-meta | Filters the course meta information in modern layout | $data_info_meta, $course, $user | 
add_filter('learn-press/single-course/modern/info-meta', function($data_info_meta, $course, $user) {
    // Add or modify course meta information
    $data_info_meta['custom_field'] = [
        'label' => '<i class="icon"></i>Custom:',
        'value' => 'Custom Value'
    ];
    return $data_info_meta;
}, 10, 3); | 
| learn_press_course_price | Filters the course price value | $price, $course_id | 
add_filter('learn_press_course_price', function($price, $course_id) {
    // Apply discount or modify price
    return $price * 0.9; // 10% discount
}, 10, 2); | 
| learn-press/course-tabs | Filters the tabs displayed on the course page | $tabs, $course | 
add_filter('learn-press/course-tabs', function($tabs, $course) {
    // Add a custom tab
    $tabs['custom_tab'] = [
        'title' => 'Custom Tab',
        'priority' => 40,
        'callback' => function() {
            echo 'Custom tab content';
        }
    ];
    return $tabs;
}, 10, 2); | 
Template and Content Filters
| Hook | Description | Parameters | Usage Example | 
|---|---|---|---|
| learn_press_get_template | Filters the template file path | $template, $template_name, $args | 
add_filter('learn_press_get_template', function($template, $template_name, $args) {
    // Use a different template file
    if ($template_name === 'single-course/price.php') {
        return get_stylesheet_directory() . '/custom-templates/course-price.php';
    }
    return $template;
}, 10, 3); | 
| learn-press/content-item-summary-class | Filters the CSS classes for content item summary | $classes | 
add_filter('learn-press/content-item-summary-class', function($classes) {
    // Add custom classes
    $classes[] = 'my-custom-class';
    return $classes;
}); | 
| learn_press_page_title | Filters the page title in LearnPress pages | $page_title | 
add_filter('learn_press_page_title', function($page_title) {
    // Modify page title
    return 'Learn Online: ' . $page_title;
}); | 
Query and Data Filters
| Hook | Description | Parameters | Usage Example | 
|---|---|---|---|
| learnpress/archive-courses-layouts | Filters the available layouts for course archive | $layouts | 
add_filter('learnpress/archive-courses-layouts', function($layouts) {
    // Add a new layout option
    $layouts['masonry'] = __('Masonry', 'learnpress');
    return $layouts;
}); | 
| lp/is-learning-course | Filters whether a user is learning a course | $is_learning, $course_id | 
add_filter('lp/is-learning-course', function($is_learning, $course_id) {
    // Custom logic to determine if user is learning
    return $is_learning || has_custom_access($course_id);
}, 10, 2); | 
| learn-press/get_template_part | Filters the template part path | $template, $slug, $name | 
add_filter('learn-press/get_template_part', function($template, $slug, $name) {
    // Use custom template part
    if ($slug === 'content' && $name === 'course') {
        return get_stylesheet_directory() . '/custom-parts/content-course.php';
    }
    return $template;
}, 10, 3); | 
Creating Custom Hooks
When developing extensions for LearnPress, it’s good practice to create your own hooks to make your code extensible:
// Adding an action hook
do_action('my_learnpress_extension/before_content', $args);
// Adding a filter hook
$value = apply_filters('my_learnpress_extension/modify_data', $value, $context);
- Use a unique prefix for your hooks to avoid conflicts
- Document your hooks thoroughly
- Be consistent with parameter passing
- Consider backward compatibility when modifying hooks
Using Hooks in Theme Functions
To use LearnPress hooks in your theme, add your code to the theme’s functions.php file or a custom plugin:
// Example of using both action and filter hooks
function my_theme_learnpress_customizations() {
    // Add content before course
    add_action('learn-press/before-course-content', 'my_before_course_content');
    
    // Modify course price display
    add_filter('learn-press/course-price-html', 'my_course_price_html', 10, 2);
}
add_action('after_setup_theme', 'my_theme_learnpress_customizations');
// Action callback
function my_before_course_content() {
    echo '<div class="course-intro">Welcome to this course!</div>';
}
// Filter callback
function my_course_price_html($price_html, $course) {
    if ($course->get_price() > 0) {
        return $price_html . ' <span class="price-guarantee">Best price guarantee!</span>';
    }
    return $price_html;
}
Removing Default Actions
Sometimes you may want to remove LearnPress’s default actions to replace them with your own:
// Remove the default course price display
remove_action('learn-press/course-content-summary', 'learn_press_course_price', 25);
// Add your custom price display
add_action('learn-press/course-content-summary', 'my_custom_course_price', 25);
function my_custom_course_price() {
    // Your custom price display code
    echo '<div class="custom-price-display">...</div>';
}
Debugging Hooks
To see which hooks are firing and in what order, you can use a debugging plugin or add this code:
function debug_learnpress_hooks() {
    // Only show for admins
    if (!current_user_can('administrator')) return;
    
    $current_filter = current_filter();
    if (strpos($current_filter, 'learn') !== false) {
        echo "<div style='padding: 5px; background: #eee; border: 1px solid #ddd; margin: 5px;'>";
        echo "Hook: " . $current_filter;
        echo "</div>";
    }
}
// Add to all LearnPress hooks (this will be very verbose)
add_action('all', 'debug_learnpress_hooks');
