Preview: tutor-lms-custom-button.php
Size: 16.61 KB
/home/certprox/template.certproxywizard.com/wp-content/plugins/tutor-lms-custom-button/tutor-lms-custom-button.php
<?php
/**
* Plugin Name: Tutor LMS Custom Dashboard Button
* Plugin URI: https://sacre-savoir.com
* Description: Adds a customizable button to the Tutor LMS dashboard for ALL users (students, instructors, admins). Configure text, color and link from WP Admin > Settings > Tutor Dashboard Button.
* Version: 2.0.0
* Author: Sabbir
* License: GPL2
* Text Domain: tutor-custom-btn
*/
if ( ! defined( 'ABSPATH' ) ) exit;
// ═══════════════════════════════════════════════════════
// 1. ADMIN SETTINGS PAGE
// ═══════════════════════════════════════════════════════
add_action( 'admin_menu', 'tcb_add_admin_menu' );
function tcb_add_admin_menu() {
add_options_page(
'Tutor Dashboard Button',
'Tutor Dashboard Button',
'manage_options',
'tutor-custom-button',
'tcb_settings_page_html'
);
}
add_action( 'admin_init', 'tcb_register_settings' );
function tcb_register_settings() {
register_setting( 'tcb_group', 'tcb_text', [ 'sanitize_callback' => 'sanitize_text_field', 'default' => 'Click Here' ] );
register_setting( 'tcb_group', 'tcb_url', [ 'sanitize_callback' => 'esc_url_raw', 'default' => '' ] );
register_setting( 'tcb_group', 'tcb_text_color', [ 'sanitize_callback' => 'sanitize_hex_color', 'default' => '#ffffff' ] );
register_setting( 'tcb_group', 'tcb_bg_color', [ 'sanitize_callback' => 'sanitize_hex_color', 'default' => '#1d2a7a' ] );
register_setting( 'tcb_group', 'tcb_enabled', [ 'sanitize_callback' => 'absint', 'default' => 1 ] );
register_setting( 'tcb_group', 'tcb_position', [ 'sanitize_callback' => 'sanitize_text_field', 'default' => 'before_profile' ] );
}
function tcb_settings_page_html() {
if ( ! current_user_can( 'manage_options' ) ) return;
$text = get_option( 'tcb_text', 'Click Here' );
$url = get_option( 'tcb_url', '' );
$tc = get_option( 'tcb_text_color', '#ffffff' );
$bg = get_option( 'tcb_bg_color', '#1d2a7a' );
$enabled = get_option( 'tcb_enabled', 1 );
$position = get_option( 'tcb_position', 'before_profile' );
?>
<div class="wrap">
<h1>🎓 Tutor LMS — Dashboard Button Settings</h1>
<p style="color:#555">The button will appear automatically on the Tutor LMS dashboard for every user (student, instructor, admin).</p>
<?php if ( isset( $_GET['settings-updated'] ) ) : ?>
<div class="notice notice-success is-dismissible"><p><strong>✅ Settings saved!</strong></p></div>
<?php endif; ?>
<div style="display:grid;grid-template-columns:1fr 300px;gap:30px;max-width:900px">
<div>
<form method="post" action="options.php">
<?php settings_fields( 'tcb_group' ); ?>
<table class="form-table">
<tr>
<th>Enable Button</th>
<td>
<label class="tcb-toggle">
<input type="checkbox" name="tcb_enabled" value="1" <?php checked(1,$enabled); ?>>
<span class="tcb-slider"></span>
</label>
</td>
</tr>
<tr>
<th><label for="tcb_text">Button Text</label></th>
<td>
<input type="text" id="tcb_text" name="tcb_text" value="<?php echo esc_attr($text); ?>" class="regular-text" placeholder="e.g. Visit Our Site">
</td>
</tr>
<tr>
<th><label for="tcb_url">Button URL</label></th>
<td>
<input type="url" id="tcb_url" name="tcb_url" value="<?php echo esc_attr($url); ?>" class="regular-text" placeholder="https://example.com">
<p class="description">Opens in a new tab automatically.</p>
</td>
</tr>
<tr>
<th><label for="tcb_text_color">Text Color</label></th>
<td style="display:flex;align-items:center;gap:10px;padding-top:12px">
<input type="color" id="tcb_text_color" name="tcb_text_color" value="<?php echo esc_attr($tc); ?>" class="tcb-cp">
<input type="text" id="tcb_text_color_hex" class="tcb-hex" value="<?php echo esc_attr($tc); ?>" maxlength="7">
</td>
</tr>
<tr>
<th><label for="tcb_bg_color">Background Color</label></th>
<td style="display:flex;align-items:center;gap:10px;padding-top:12px">
<input type="color" id="tcb_bg_color" name="tcb_bg_color" value="<?php echo esc_attr($bg); ?>" class="tcb-cp">
<input type="text" id="tcb_bg_color_hex" class="tcb-hex" value="<?php echo esc_attr($bg); ?>" maxlength="7">
</td>
</tr>
<tr>
<th><label for="tcb_position">Button Position</label></th>
<td>
<select id="tcb_position" name="tcb_position">
<option value="before_profile" <?php selected($position,'before_profile'); ?>>Above "Complete Your Profile"</option>
<option value="after_profile" <?php selected($position,'after_profile'); ?>>Below "Complete Your Profile"</option>
<option value="before_stats" <?php selected($position,'before_stats'); ?>>Above Stats Cards (Enrolled / Active …)</option>
<option value="after_stats" <?php selected($position,'after_stats'); ?>>Below Stats Cards</option>
</select>
</td>
</tr>
</table>
<?php submit_button('Save Settings'); ?>
</form>
</div>
<!-- Live Preview -->
<div>
<div style="position:sticky;top:32px;background:#f6f7f8;border:1px solid #ddd;border-radius:8px;padding:24px;text-align:center">
<p style="margin:0 0 14px;font-size:12px;text-transform:uppercase;color:#888;letter-spacing:.5px">Live Preview</p>
<a id="tcb-preview" href="#"
style="display:inline-block;padding:11px 26px;border-radius:6px;font-weight:700;font-size:15px;text-decoration:none;box-shadow:0 2px 8px rgba(0,0,0,.15);transition:opacity .2s;
color:<?php echo esc_attr($tc); ?>;background:<?php echo esc_attr($bg); ?>">
<?php echo esc_html($text); ?>
</a>
<p style="font-size:11px;color:#aaa;margin:12px 0 0">Updates as you type</p>
</div>
</div>
</div>
</div>
<style>
.tcb-toggle{position:relative;display:inline-block;width:52px;height:28px}
.tcb-toggle input{opacity:0;width:0;height:0}
.tcb-slider{position:absolute;cursor:pointer;inset:0;background:#ccc;border-radius:28px;transition:.3s}
.tcb-slider:before{content:"";position:absolute;height:20px;width:20px;left:4px;bottom:4px;background:#fff;border-radius:50%;transition:.3s}
.tcb-toggle input:checked+.tcb-slider{background:#1d72b8}
.tcb-toggle input:checked+.tcb-slider:before{transform:translateX(24px)}
.tcb-cp{width:46px;height:36px;border:1px solid #ddd;border-radius:4px;cursor:pointer;padding:2px}
.tcb-hex{width:80px;font-family:monospace}
</style>
<script>
(function(){
var prev = document.getElementById('tcb-preview');
function pair(cpId, hexId, prop){
var cp = document.getElementById(cpId);
var hex = document.getElementById(hexId);
cp.addEventListener('input',function(){ hex.value=cp.value; prev.style[prop]=cp.value; });
hex.addEventListener('input',function(){
if(/^#[0-9a-fA-F]{6}$/.test(hex.value)){ cp.value=hex.value; prev.style[prop]=hex.value; }
});
}
pair('tcb_text_color','tcb_text_color_hex','color');
pair('tcb_bg_color','tcb_bg_color_hex','backgroundColor');
document.getElementById('tcb_text').addEventListener('input',function(){ prev.textContent=this.value||'Button'; });
document.getElementById('tcb_url').addEventListener('input',function(){ prev.href=this.value; });
})();
</script>
<?php
}
// ═══════════════════════════════════════════════════════
// 2. OUTPUT THE BUTTON ON THE FRONTEND
// Strategy: Try every known Tutor LMS action hook.
// If none fires, JavaScript DOM injection is the
// guaranteed fallback – it runs on every page load.
// ═══════════════════════════════════════════════════════
// ── 2a. All known Tutor LMS PHP action hooks ──────────
$tcb_hooks = [
'tutor_dashboard/before_dashboard_content',
'tutor_after_dashboard_top_banner',
'tutor_dashboard_content_before',
'tutor_dashboard_before',
'tutor/dashboard/before',
'tutor_student_dashboard_before',
];
foreach ( $tcb_hooks as $hook ) {
add_action( $hook, 'tcb_render_button_php', 5 );
}
function tcb_render_button_php() {
static $done = false;
if ( $done ) return;
$done = true;
echo tcb_button_html();
}
// ── 2b. Shortcode [tutor_dashboard_button] ────────────
add_shortcode( 'tutor_dashboard_button', 'tcb_button_html' );
// ── 2c. HTML helper ───────────────────────────────────
function tcb_button_html() {
if ( ! get_option('tcb_enabled', 1) ) return '';
$text = get_option('tcb_text', 'Click Here');
$url = get_option('tcb_url', '');
$tc = get_option('tcb_text_color', '#ffffff');
$bg = get_option('tcb_bg_color', '#1d2a7a');
if ( empty($url) ) return '';
return sprintf(
'<div class="tcb-wrap"><a href="%s" target="_blank" rel="noopener noreferrer" class="tcb-btn" style="color:%s;background:%s">%s</a></div>',
esc_url($url), esc_attr($tc), esc_attr($bg), esc_html($text)
);
}
// ═══════════════════════════════════════════════════════
// 3. JAVASCRIPT DOM INJECTION — GUARANTEED FALLBACK
// Runs on every page that contains the Tutor dashboard.
// Reads button config via wp_localize_script so no
// inline PHP is needed in the JS.
// ═══════════════════════════════════════════════════════
add_action( 'wp_enqueue_scripts', 'tcb_enqueue' );
function tcb_enqueue() {
if ( ! get_option('tcb_enabled', 1) ) return;
if ( ! function_exists('tutor') ) return;
$url = get_option('tcb_url', '');
if ( empty($url) ) return;
// Inline script — no external file needed
$config = [
'text' => get_option('tcb_text', 'Click Here'),
'url' => $url,
'textColor' => get_option('tcb_text_color', '#ffffff'),
'bgColor' => get_option('tcb_bg_color', '#1d2a7a'),
'position' => get_option('tcb_position', 'before_profile'),
];
wp_register_script( 'tcb-inject', false, [], false, true );
wp_enqueue_script( 'tcb-inject' );
wp_add_inline_script( 'tcb-inject', 'var TCB = ' . wp_json_encode($config) . ';' );
wp_add_inline_script( 'tcb-inject', "
(function(){
function tcbInject(){
/* Already injected? Skip. */
if(document.getElementById('tcb-dashboard-btn')) return;
/* ── Selectors that wrap the Tutor dashboard content ── */
var anchors = [
'.tutor-dashboard-content-wrap',
'.tutor-dashboard-content',
'.tutor-dashboard .tutor-col-8',
'.tutor-dashboard .tutor-col-9',
'[class*=\"tutor-dashboard\"] .tutor-col',
'.dashboard-content-area',
'.tutor-student-dashboard',
'#tutor-dashboard-content'
];
var container = null;
for(var i=0;i<anchors.length;i++){
container = document.querySelector(anchors[i]);
if(container) break;
}
if(!container) return; /* Not a dashboard page */
/* ── Build the button ── */
var wrap = document.createElement('div');
wrap.id = 'tcb-dashboard-btn';
wrap.className = 'tcb-wrap';
var a = document.createElement('a');
a.href = TCB.url;
a.target = '_blank';
a.rel = 'noopener noreferrer';
a.className = 'tcb-btn';
a.style.color = TCB.textColor;
a.style.background = TCB.bgColor;
a.textContent = TCB.text;
wrap.appendChild(a);
/* ── Choose insertion point based on position setting ── */
var pos = TCB.position;
var profileBox = container.querySelector('.tutor-dashboard-permalink, .complete-profile-box, [class*=\"complete\"][class*=\"profile\"], .tutor-card');
var statsRow = container.querySelector('.tutor-dashboard-group, .tutor-row:has(.tutor-dashboard-permalinks), .tutor-stats-wrap, .tutor-dashboard-stats');
if(pos === 'before_profile' || pos === 'before_stats'){
/* Insert as very first child of dashboard content */
container.insertBefore(wrap, container.firstChild);
} else if(pos === 'after_profile' && profileBox){
profileBox.parentNode.insertBefore(wrap, profileBox.nextSibling);
} else if(pos === 'after_stats' && statsRow){
statsRow.parentNode.insertBefore(wrap, statsRow.nextSibling);
} else {
/* Default: prepend */
container.insertBefore(wrap, container.firstChild);
}
}
/* Run after DOM ready */
if(document.readyState === 'loading'){
document.addEventListener('DOMContentLoaded', tcbInject);
} else {
tcbInject();
}
/* Also try after full page load (handles lazy-rendered dashboards) */
window.addEventListener('load', tcbInject);
})();
" );
}
// ═══════════════════════════════════════════════════════
// 4. FRONT-END CSS
// ═══════════════════════════════════════════════════════
add_action( 'wp_head', 'tcb_styles' );
function tcb_styles(){
if ( ! get_option('tcb_enabled',1) ) return;
if ( ! function_exists('tutor') ) return;
?>
<style id="tcb-css">
.tcb-wrap{
display:flex;
justify-content:flex-end;
margin-bottom:18px;
}
a.tcb-btn{
display:inline-block;
padding:11px 28px;
border-radius:6px;
font-size:15px;
font-weight:700;
text-decoration:none !important;
cursor:pointer;
box-shadow:0 2px 10px rgba(0,0,0,.15);
transition:opacity .2s, transform .15s;
}
a.tcb-btn:hover{
opacity:.85;
transform:translateY(-1px);
}
</style>
<?php
}
// ═══════════════════════════════════════════════════════
// 5. QUICK SETTINGS LINK IN PLUGINS LIST
// ═══════════════════════════════════════════════════════
add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), function($links){
$links[] = '<a href="'.admin_url('options-general.php?page=tutor-custom-button').'">Settings</a>';
return $links;
});
Directory Contents
Dirs: 1 × Files: 2