added additional plugins

This commit is contained in:
Rodolfo Martinez 2025-12-12 19:05:48 -05:00
parent c85895d306
commit 00e60ec1b7
132 changed files with 27514 additions and 0 deletions

View file

@ -0,0 +1,677 @@
<?php
/**
* Plugin Name: LearnDash Start Course Button
* Plugin URI: https://sspmedia.ca/wordpress/
* Description: Adds prominent "Start Course" and "Start Group Work" buttons for LearnDash with shortcode and Gutenberg block support
* Version: 1.0.0
* Author: SSP Media
* License: GPL v2 or later
* Text Domain: learndash-start-button
* Domain Path: /languages
* Requires at least: 5.0
* Requires PHP: 7.2
* WC requires at least: 7.0
* WC tested up to: 9.0
*
* @package LearnDashStartCourseButton
*/
// Prevent direct access - Wordfence compatible
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
// Define plugin constants
if (!defined('LDSB_VERSION')) {
define('LDSB_VERSION', '1.0.0');
}
if (!defined('LDSB_PLUGIN_URL')) {
define('LDSB_PLUGIN_URL', plugin_dir_url(__FILE__));
}
if (!defined('LDSB_PLUGIN_PATH')) {
define('LDSB_PLUGIN_PATH', plugin_dir_path(__FILE__));
}
if (!defined('LDSB_PLUGIN_BASENAME')) {
define('LDSB_PLUGIN_BASENAME', plugin_basename(__FILE__));
}
/**
* Check plugin dependencies
*
* @since 1.0.0
* @return bool True if dependencies are met, false otherwise
*/
function ldsb_check_dependencies() {
$deps_met = true;
$notices = array();
// Check for LearnDash
if (!defined('LEARNDASH_VERSION')) {
$deps_met = false;
$notices[] = __('LearnDash Start Course Button requires LearnDash LMS to be installed and activated.', 'learndash-start-button');
} elseif (version_compare(LEARNDASH_VERSION, '3.0', '<')) {
$deps_met = false;
$notices[] = __('LearnDash Start Course Button requires LearnDash version 3.0 or higher.', 'learndash-start-button');
}
// Display admin notices if dependencies not met
if (!$deps_met && is_admin() && !empty($notices)) {
add_action('admin_notices', function() use ($notices) {
foreach ($notices as $notice) {
echo '<div class="notice notice-error"><p>' . esc_html($notice) . '</p></div>';
}
});
return false;
}
return true;
}
add_action('plugins_loaded', 'ldsb_check_dependencies');
/**
* Declare WooCommerce HPOS compatibility
*
* @since 1.0.0
* @return void
*/
add_action('before_woocommerce_init', function() {
if (class_exists('\Automattic\WooCommerce\Utilities\FeaturesUtil')) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('custom_order_tables', __FILE__, true);
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('cart_checkout_blocks', __FILE__, true);
}
});
/**
* Enqueue plugin styles - Only on LearnDash pages
*
* @since 1.0.0
* @return void
*/
function ldsb_enqueue_styles() {
// Only load on singular pages or LearnDash archives
if (!is_singular() && !is_post_type_archive('sfwd-courses') && !is_post_type_archive('groups') && !is_tax('ld_course_category') && !is_tax('ld_course_tag') && !is_tax('ld_group_category') && !is_tax('ld_group_tag')) {
return;
}
// Check if current post is LearnDash content or has our shortcode
if (is_singular()) {
global $post;
// Validate post object exists
if (!$post || !is_object($post) || !isset($post->post_content)) {
return;
}
// Check post type
$ld_post_types = array('sfwd-courses', 'sfwd-lessons', 'sfwd-topic', 'sfwd-quiz', 'groups');
$is_ld_content = in_array(get_post_type(), $ld_post_types);
// Check for shortcodes
$has_course_shortcode = has_shortcode($post->post_content, 'learndash_start_button');
$has_group_shortcode = has_shortcode($post->post_content, 'learndash_start_group');
// Check for blocks
$has_course_block = has_block('ldsb/start-button', $post);
$has_group_block = has_block('ldsb/start-group', $post);
if (!$is_ld_content && !$has_course_shortcode && !$has_group_shortcode && !$has_course_block && !$has_group_block) {
return;
}
}
wp_enqueue_style(
'ldsb-button-styles',
LDSB_PLUGIN_URL . 'assets/css/style.css',
array(),
LDSB_VERSION,
'all'
);
}
add_action('wp_enqueue_scripts', 'ldsb_enqueue_styles');
/**
* Get first lesson URL with compatibility checks
*
* @since 1.0.0
* @param int $course_id The course ID
* @return string|false The first lesson URL or course URL, false on failure
*/
function ldsb_get_first_lesson_url($course_id) {
$course_url = get_permalink($course_id);
// If we can't get the course URL, return false
if (!$course_url) {
return false;
}
// Try new LearnDash 4.0+ method first
if (function_exists('learndash_course_get_children_of_step')) {
$lessons = learndash_course_get_children_of_step($course_id, $course_id, 'sfwd-lessons');
if (!empty($lessons)) {
$lesson_url = get_permalink($lessons[0]);
return $lesson_url ? $lesson_url : $course_url;
}
}
// Fallback to older method
if (function_exists('learndash_get_course_lessons_list')) {
$lessons = learndash_get_course_lessons_list($course_id);
if (!empty($lessons) && is_array($lessons)) {
$first_lesson = reset($lessons);
if (isset($first_lesson['post']->ID)) {
$lesson_url = get_permalink($first_lesson['post']->ID);
return $lesson_url ? $lesson_url : $course_url;
}
}
}
return $course_url;
}
/**
* Sanitize multiple HTML classes
*
* @since 1.0.0
* @param string $classes Space-separated list of class names
* @return string Sanitized space-separated list of class names
*/
function ldsb_sanitize_html_classes($classes) {
if (empty($classes)) {
return '';
}
// Split by spaces and sanitize each class individually
$classes_array = explode(' ', $classes);
$sanitized_classes = array();
foreach ($classes_array as $class) {
$class = trim($class);
if (!empty($class)) {
$sanitized = sanitize_html_class($class);
if (!empty($sanitized)) {
$sanitized_classes[] = $sanitized;
}
}
}
return implode(' ', $sanitized_classes);
}
/**
* Check user access with compatibility
*
* @since 1.0.0
* @param int $course_id The course ID to check access for
* @param int|null $user_id The user ID to check, defaults to current user
* @return bool True if user has access, false otherwise
*/
function ldsb_check_user_access($course_id, $user_id = null) {
if (null === $user_id) {
$user_id = get_current_user_id();
}
// Try newer method first (LearnDash 3.0+)
if (function_exists('sfwd_lms_has_access')) {
return sfwd_lms_has_access($course_id, $user_id);
}
// Fallback for older versions
if (function_exists('ld_course_check_user_access')) {
return ld_course_check_user_access($course_id, $user_id);
}
// Last resort - check if user is logged in
return is_user_logged_in();
}
/**
* Get first course URL from a group
*
* @since 1.0.0
* @param int $group_id The group ID
* @return string|false The first course/lesson URL or group URL, false on failure
*/
function ldsb_get_first_group_course_url($group_id) {
// Get group courses
$group_courses = array();
// Try LearnDash 3.2+ method
if (function_exists('learndash_group_enrolled_courses')) {
$group_courses = learndash_group_enrolled_courses($group_id);
} elseif (function_exists('learndash_get_group_enrolled_courses')) {
$group_courses = learndash_get_group_enrolled_courses($group_id);
} else {
// Fallback to direct meta query
$group_courses = get_post_meta($group_id, 'learndash_group_enrolled_courses', true);
if (!is_array($group_courses)) {
$group_courses = array();
}
}
// If we have courses, get the first one
if (!empty($group_courses)) {
$first_course_id = is_array($group_courses) ? reset($group_courses) : $group_courses;
// Check if it's a valid course
if (get_post_type($first_course_id) === 'sfwd-courses') {
// Try to get first lesson of this course
$course_url = ldsb_get_first_lesson_url($first_course_id);
if ($course_url) {
return $course_url;
}
}
}
// Fallback to group URL
$group_url = get_permalink($group_id);
return $group_url ? $group_url : false;
}
/**
* Register shortcode for the Start Group Work button
*
* @since 1.0.0
* @param array $atts Shortcode attributes
* @return string Button HTML or empty comment
*/
function ldsb_start_group_shortcode($atts) {
// Verify LearnDash is active
if (!defined('LEARNDASH_VERSION')) {
return '<!-- LearnDash not active -->';
}
// Parse and sanitize attributes
$atts = shortcode_atts(array(
'group_id' => '',
'text' => __('Start First Course', 'learndash-start-button'),
'new_tab' => 'no',
'class' => '',
'alignment' => ''
), $atts, 'learndash_start_group');
// Sanitize inputs
$group_id = !empty($atts['group_id']) ? absint($atts['group_id']) : get_the_ID();
$button_text = sanitize_text_field($atts['text']);
$new_tab = in_array($atts['new_tab'], array('yes', 'true', '1'), true);
$custom_class = ldsb_sanitize_html_classes($atts['class']);
$alignment = !empty($atts['alignment']) ? sanitize_key($atts['alignment']) : '';
// Validate group exists and is correct post type
$group_post = get_post($group_id);
if (!$group_post || get_post_type($group_post) !== 'groups') {
return '<!-- Invalid group ID or not a group page -->';
}
// Get the first course URL from the group
$course_url = ldsb_get_first_group_course_url($group_id);
// If we can't get a valid URL, return empty
if (!$course_url) {
return '<!-- Could not generate valid URL for group -->';
}
// Determine button text - SIMPLIFIED VERSION
$access_text = esc_html($button_text); // Default text for everyone
// ONLY override for logged-out users
if (!is_user_logged_in()) {
$access_text = __('Login to Start', 'learndash-start-button');
$course_url = wp_login_url($course_url);
}
// Admins and all logged-in users see the default button text
// No "Join Group to Start" text anywhere!
// Build wrapper classes
$wrapper_classes = array('ldsb-button-wrapper');
if ($alignment) {
$wrapper_classes[] = 'align-' . $alignment;
}
if ($custom_class) {
$wrapper_classes[] = $custom_class;
}
$wrapper_class_string = implode(' ', $wrapper_classes);
// Build link attributes
$link_attrs = array(
'href' => esc_url($course_url),
'class' => 'ldsb-start-button ldsb-group-button',
'role' => 'button',
'data-group-id' => $group_id
);
if ($new_tab) {
$link_attrs['target'] = '_blank';
$link_attrs['rel'] = 'noopener noreferrer';
}
// Build attributes string
$attrs_string = '';
foreach ($link_attrs as $key => $value) {
$attrs_string .= sprintf(' %s="%s"', $key, esc_attr($value));
}
// Build the button HTML
$button_html = sprintf(
'<div class="%s">
<a%s>
<span class="ldsb-button-text">%s</span>
<svg class="ldsb-button-arrow" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
</div>',
esc_attr($wrapper_class_string),
$attrs_string,
$access_text
);
// Allow filtering of output
return apply_filters('ldsb_group_button_html', $button_html, $atts);
}
add_shortcode('learndash_start_group', 'ldsb_start_group_shortcode');
/**
* Register shortcode for the Start Now button
*
* @since 1.0.0
* @param array $atts Shortcode attributes
* @return string Button HTML or empty comment
*/
function ldsb_start_button_shortcode($atts) {
// Verify LearnDash is active
if (!defined('LEARNDASH_VERSION')) {
return '<!-- LearnDash not active -->';
}
// Parse and sanitize attributes
$atts = shortcode_atts(array(
'course_id' => '',
'text' => __('Start Course', 'learndash-start-button'),
'new_tab' => 'no',
'class' => '',
'alignment' => ''
), $atts, 'learndash_start_button');
// Sanitize inputs
$course_id = !empty($atts['course_id']) ? absint($atts['course_id']) : get_the_ID();
$button_text = sanitize_text_field($atts['text']);
$new_tab = in_array($atts['new_tab'], array('yes', 'true', '1'), true);
$custom_class = ldsb_sanitize_html_classes($atts['class']);
$alignment = !empty($atts['alignment']) ? sanitize_key($atts['alignment']) : '';
// Validate course exists and get post type
$course_post = get_post($course_id);
if (!$course_post) {
return '<!-- Invalid course ID -->';
}
// Get proper course ID if we're on a lesson/topic
$course_post_type = get_post_type($course_post);
if ($course_post_type !== 'sfwd-courses') {
if (function_exists('learndash_get_course_id')) {
$course_id = learndash_get_course_id($course_id);
if (!$course_id) {
return '<!-- No associated course found -->';
}
}
}
// Get the course URL
$course_url = ldsb_get_first_lesson_url($course_id);
// If we can't get a valid URL, return empty
if (!$course_url) {
return '<!-- Could not generate valid URL for course -->';
}
// Check user access
$user_id = get_current_user_id();
$has_access = ldsb_check_user_access($course_id, $user_id);
$access_text = esc_html($button_text);
if (!$has_access && !is_user_logged_in()) {
$access_text = __('Login to Start', 'learndash-start-button');
$course_url = wp_login_url($course_url);
} elseif (!$has_access) {
$access_text = __('Enroll to Start', 'learndash-start-button');
}
// Build wrapper classes
$wrapper_classes = array('ldsb-button-wrapper');
if ($alignment) {
$wrapper_classes[] = 'align-' . $alignment;
}
if ($custom_class) {
$wrapper_classes[] = $custom_class;
}
$wrapper_class_string = implode(' ', $wrapper_classes);
// Build link attributes
$link_attrs = array(
'href' => esc_url($course_url),
'class' => 'ldsb-start-button',
'role' => 'button',
'data-course-id' => $course_id
);
if ($new_tab) {
$link_attrs['target'] = '_blank';
$link_attrs['rel'] = 'noopener noreferrer';
}
// Build attributes string
$attrs_string = '';
foreach ($link_attrs as $key => $value) {
$attrs_string .= sprintf(' %s="%s"', $key, esc_attr($value));
}
// Build the button HTML
$button_html = sprintf(
'<div class="%s">
<a%s>
<span class="ldsb-button-text">%s</span>
<svg class="ldsb-button-arrow" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
</div>',
esc_attr($wrapper_class_string),
$attrs_string,
$access_text
);
// Allow filtering of output
return apply_filters('ldsb_button_html', $button_html, $atts);
}
add_shortcode('learndash_start_button', 'ldsb_start_button_shortcode');
/**
* Register Gutenberg blocks
*
* @since 1.0.0
* @return void
*/
function ldsb_register_blocks() {
// Check if Gutenberg is available
if (!function_exists('register_block_type')) {
return;
}
// Register block editor script
wp_register_script(
'ldsb-block-editor',
LDSB_PLUGIN_URL . 'assets/js/block.js',
array('wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-data', 'wp-i18n'),
LDSB_VERSION,
true
);
// Add translation support
wp_set_script_translations('ldsb-block-editor', 'learndash-start-button');
// Register block editor styles
wp_register_style(
'ldsb-block-editor-style',
LDSB_PLUGIN_URL . 'assets/css/editor.css',
array('wp-edit-blocks'),
LDSB_VERSION
);
// Register the Course Start button block
register_block_type('ldsb/start-button', array(
'editor_script' => 'ldsb-block-editor',
'editor_style' => 'ldsb-block-editor-style',
'render_callback' => 'ldsb_render_block',
'attributes' => array(
'courseId' => array(
'type' => 'number',
'default' => 0
),
'buttonText' => array(
'type' => 'string',
'default' => __('Start Course', 'learndash-start-button')
),
'newTab' => array(
'type' => 'boolean',
'default' => false
),
'alignment' => array(
'type' => 'string',
'default' => 'left',
'enum' => array('left', 'center', 'right')
)
),
'supports' => array(
'align' => false, // We handle alignment internally
'className' => true,
'html' => false
)
));
// Register the Group Start button block
register_block_type('ldsb/start-group', array(
'editor_script' => 'ldsb-block-editor',
'editor_style' => 'ldsb-block-editor-style',
'render_callback' => 'ldsb_render_group_block',
'attributes' => array(
'groupId' => array(
'type' => 'number',
'default' => 0
),
'buttonText' => array(
'type' => 'string',
'default' => __('Start First Course', 'learndash-start-button')
),
'newTab' => array(
'type' => 'boolean',
'default' => false
),
'alignment' => array(
'type' => 'string',
'default' => 'left',
'enum' => array('left', 'center', 'right')
)
),
'supports' => array(
'align' => false,
'className' => true,
'html' => false
)
));
}
add_action('init', 'ldsb_register_blocks');
/**
* Render block callback
*
* @since 1.0.0
* @param array $attributes Block attributes
* @return string Block HTML output
*/
function ldsb_render_block($attributes) {
// Sanitize attributes
$course_id = isset($attributes['courseId']) ? absint($attributes['courseId']) : 0;
$button_text = isset($attributes['buttonText']) ? sanitize_text_field($attributes['buttonText']) : __('Start Course', 'learndash-start-button');
$new_tab = isset($attributes['newTab']) && $attributes['newTab'] ? 'yes' : 'no';
$alignment = isset($attributes['alignment']) ? sanitize_key($attributes['alignment']) : 'left';
// Pass alignment to shortcode
return ldsb_start_button_shortcode(array(
'course_id' => $course_id,
'text' => $button_text,
'new_tab' => $new_tab,
'alignment' => $alignment
));
}
/**
* Render group block callback
*
* @since 1.0.0
* @param array $attributes Block attributes
* @return string Block HTML output
*/
function ldsb_render_group_block($attributes) {
// Sanitize attributes
$group_id = isset($attributes['groupId']) ? absint($attributes['groupId']) : 0;
$button_text = isset($attributes['buttonText']) ? sanitize_text_field($attributes['buttonText']) : __('Start First Course', 'learndash-start-button');
$new_tab = isset($attributes['newTab']) && $attributes['newTab'] ? 'yes' : 'no';
$alignment = isset($attributes['alignment']) ? sanitize_key($attributes['alignment']) : 'left';
// Pass to group shortcode
return ldsb_start_group_shortcode(array(
'group_id' => $group_id,
'text' => $button_text,
'new_tab' => $new_tab,
'alignment' => $alignment
));
}
/**
* Plugin activation hook
*
* @since 1.0.0
* @return void
*/
function ldsb_activate() {
// Check minimum requirements
if (version_compare(PHP_VERSION, '7.2', '<')) {
deactivate_plugins(LDSB_PLUGIN_BASENAME);
wp_die(__('This plugin requires PHP 7.2 or higher.', 'learndash-start-button'));
}
// Set default options
add_option('ldsb_version', LDSB_VERSION);
// Note: flush_rewrite_rules() removed - this plugin doesn't register custom post types or rewrite rules
}
register_activation_hook(__FILE__, 'ldsb_activate');
/**
* Plugin deactivation hook
*
* @since 1.0.0
* @return void
*/
function ldsb_deactivate() {
// Note: No cleanup needed on deactivation
// flush_rewrite_rules() should NOT be called on deactivation per WordPress best practices
}
register_deactivation_hook(__FILE__, 'ldsb_deactivate');
/**
* Load plugin textdomain
*
* @since 1.0.0
* @return void
*/
function ldsb_load_textdomain() {
load_plugin_textdomain(
'learndash-start-button',
false,
dirname(LDSB_PLUGIN_BASENAME) . '/languages'
);
}
add_action('plugins_loaded', 'ldsb_load_textdomain');
// End of file - no closing PHP tag to prevent whitespace issues