' . esc_html($notice) . '
'; } }); 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 ''; } // 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 ''; } // 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 ''; } // 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( '', 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 ''; } // 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 ''; } // 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 ''; } } } // 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 ''; } // 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( '', 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