-
-
Save SalvatoreNoschese/5607cc118c70ec9940ecc0e439420c06 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Plugin Name: Tiny GoToTop | |
Description: A simple plugin to add a "go to top" button to your site. | |
Version: 1.0 | |
Author: Salvatore Noschese | |
Author URI: https://salvatorenoschese.it | |
Text Domain: tiny-gototop | |
Domain Path: /languages | |
*/ | |
class Tiny_GoToTop { | |
// Default settings for the plugin | |
const DEFAULTS = [ | |
'main_color' => '#023e47', | |
'secondary_color' => '#8b6b36', | |
'opacity' => 0.5, | |
'position_right' => 20, | |
'position_bottom' => 20, | |
'padding' => 10, | |
'width' => 20, | |
'height' => 20, | |
'border_radius' => 50, // % for border-radius | |
]; | |
// Hold plugin data | |
private $plugin_data; | |
// Constructor to initialize the plugin, load data, and add hooks | |
public function __construct() { | |
// Load plugin data | |
if (!function_exists('get_plugin_data')) { | |
require_once(ABSPATH . 'wp-admin/includes/plugin.php'); | |
} | |
$this->plugin_data = get_plugin_data(__FILE__); | |
// Load the plugin's text domain for translations | |
add_action('plugins_loaded', [$this, 'load_textdomain']); | |
// Add a settings page to the WordPress admin menu | |
add_action('admin_menu', [$this, 'add_settings_page']); | |
// Enqueue scripts and styles for the admin area | |
add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']); | |
// Enqueue scripts and styles for the frontend | |
add_action('wp_enqueue_scripts', [$this, 'enqueue_frontend_scripts']); | |
// Print the "go to top" button in the footer | |
add_action('wp_footer', [$this, 'print_button']); | |
// add settings link | |
add_filter('plugin_action_links_' . plugin_basename(__FILE__), [$this, 'add_plugin_page_settings_link']); | |
// add donate link | |
add_filter('plugin_row_meta', [$this, 'plugin_row_meta'], 10, 2); | |
// Add the custom footer | |
add_filter('admin_footer_text', [$this, 'custom_footer_text']); | |
} | |
// Load text domain for internationalization | |
public function load_textdomain() { | |
load_plugin_textdomain('tiny-gototop', false, dirname(plugin_basename(__FILE__)) . '/languages'); | |
} | |
// custom footer | |
public function custom_footer_text($footer_text) { | |
$screen = get_current_screen(); | |
if ($screen && strpos($screen->id, 'tiny-gototop') !== false) { | |
$plugin_name = $this->plugin_data['Name']; | |
$plugin_version = $this->plugin_data['Version']; | |
$author = $this->plugin_data['Author']; | |
return "<strong><em>$plugin_name v$plugin_version | by $author</em></strong>"; | |
} | |
return $footer_text; | |
} | |
// Get a plugin option, returning the default if the option is not set | |
public function get_option($name) { | |
return get_option('tiny_gototop_' . $name, self::DEFAULTS[$name]); | |
} | |
// Remove options if deactivated | |
public static function deactivate() { | |
$option_names = [ | |
'main_color', 'secondary_color', 'opacity', 'position_right', | |
'position_bottom', 'padding', 'width', 'height', 'border_radius' | |
]; | |
foreach ($option_names as $option) { | |
delete_option('tiny_gototop_' . $option); | |
} | |
// Rimuovi il file CSS generato | |
$css_file = plugin_dir_path(__FILE__) . 'assets/tiny-gototop.css'; | |
if (file_exists($css_file)) { | |
unlink($css_file); | |
} | |
// Rimuovi il transient | |
delete_transient('tiny_gototop_css'); | |
} | |
// add settings link | |
public function add_plugin_page_settings_link($actions) { | |
$mylinks = [ | |
'<a href="https://salvatorenoschese.it" title="' . __('Support') . '" target="_blank">' . __('Support') . ' 🔗</a>', | |
'<a href="' . admin_url("options-general.php?page=tiny-gototop") . '" title="' . __('Settings') . '">' . __('Settings') . ' ⚙️</a>', | |
]; | |
return array_merge($actions, $mylinks); | |
} | |
// add donate link | |
public function plugin_row_meta($links, $file) { | |
if (plugin_basename(__FILE__) === $file) { | |
$new_links = [ | |
'<a href="https://paypal.me/SalvatoreN" target="_blank">' . __('Donate', 'tiny-gototop') . ' 🎁</a>' | |
]; | |
$links = array_merge($links, $new_links); | |
} | |
return $links; | |
} | |
// Generate the CSS for the "go to top" button | |
public function generate_css($css = null) { | |
// If no custom CSS is passed, generate it based on settings | |
if ($css === null) { | |
$main_color = $this->get_option('main_color'); | |
$secondary_color = $this->get_option('secondary_color'); | |
$opacity = $this->get_option('opacity'); | |
$position_right = $this->get_option('position_right'); | |
$position_bottom = $this->get_option('position_bottom'); | |
$padding = $this->get_option('padding'); | |
$width = $this->get_option('width'); | |
$height = $this->get_option('height'); | |
$border_radius = $this->get_option('border_radius'); | |
// CSS rules for the button | |
$css = "#go-to-top {\n"; | |
$css .= " display: none;\n"; | |
$css .= " position: fixed;\n"; | |
$css .= " bottom: {$position_bottom}px;\n"; | |
$css .= " right: {$position_right}px;\n"; | |
$css .= " cursor: pointer;\n"; | |
$css .= " padding: {$padding}px;\n"; | |
$css .= " width: {$width}px;\n"; | |
$css .= " height: {$height}px;\n"; | |
$css .= " border-radius: {$border_radius}%;\n"; | |
$css .= " z-index: 1000;\n"; | |
$css .= " opacity: {$opacity};\n"; | |
$css .= " box-shadow: 0 2px 5px rgba(0,0,0,0.3);\n"; | |
$css .= " background-color: {$main_color};\n"; | |
$css .= " transition: background-color 0.3s ease;\n"; | |
$css .= "}\n"; | |
// CSS rules for hover state | |
$css .= "@media (hover: hover) {\n"; | |
$css .= " #go-to-top:hover {\n"; | |
$css .= " background-color: {$secondary_color};\n"; | |
$css .= " }\n"; | |
$css .= "}\n"; | |
// CSS rules for active background | |
$css .= "#go-to-top.active-background {\n"; | |
$css .= " background-color: {$secondary_color};\n"; | |
$css .= "}"; | |
} | |
// Save the generated CSS to a file | |
$css_file = plugin_dir_path(__FILE__) . 'assets/tiny-gototop.css'; | |
file_put_contents($css_file, $css); | |
// Store the CSS in a transient for faster access | |
set_transient('tiny_gototop_css', $css, 12 * HOUR_IN_SECONDS); | |
} | |
// Save the plugin settings, resetting to defaults if necessary | |
public function save_settings($reset = false) { | |
// Check the nonce for security | |
check_admin_referer('tiny_gototop_update_options'); | |
// Loop through each setting | |
foreach (self::DEFAULTS as $key => $default) { | |
if ($reset) { | |
// Reset to default if reset is true | |
update_option('tiny_gototop_' . $key, $default); | |
} else { | |
// Otherwise, save the value from the form, or default if not set | |
$value = isset($_POST['tiny_gototop_' . $key]) ? $this->sanitize_option($key, $_POST['tiny_gototop_' . $key]) : $default; | |
update_option('tiny_gototop_' . $key, $value); | |
} | |
} | |
// Generate the updated CSS | |
$this->generate_css(); | |
} | |
// Sanitize options based on their expected data type | |
public function sanitize_option($key, $value) { | |
switch ($key) { | |
case 'main_color': | |
case 'secondary_color': | |
return sanitize_hex_color($value); // Sanitize colors | |
case 'opacity': | |
return floatval($value); // Convert opacity to float | |
default: | |
return intval($value); // Convert other values to integers | |
} | |
} | |
// Add the settings page to the WordPress admin menu | |
public function add_settings_page() { | |
add_options_page( | |
sprintf(__('Tiny GoToTop: %s', 'tiny-gototop'), __('Settings')), // Page title | |
__('Tiny GoToTop', 'tiny-gototop'), | |
'manage_options', | |
'tiny-gototop', | |
[$this, 'render_settings_page'] | |
); | |
} | |
// Render the settings page in the admin area | |
public function render_settings_page() { | |
// Ensure the CSS file exists | |
$this->check_css_file(); | |
?> | |
<div class="wrap"> | |
<h1>Tiny GoToTop: <?php _e('Settings'); ?> ⚙️</h1> | |
<?php | |
// Handle form submission for saving settings | |
if (isset($_POST['submit']) && check_admin_referer('tiny_gototop_update_options')) { | |
$this->save_settings(); | |
echo '<div class="notice notice-success is-dismissible"><p>' . __('Settings Saved ✅', 'tiny-gototop') . '</p></div>'; | |
} | |
// Handle form submission for resetting settings | |
if (isset($_POST['reset']) && check_admin_referer('tiny_gototop_update_options')) { | |
$this->save_settings(true); | |
echo '<div class="notice notice-warning is-dismissible"><p>' . __('Settings Restored 🗑️', 'tiny-gototop') . '</p></div>'; | |
} | |
?> | |
<hr /> | |
<form method="post" action=""> | |
<?php wp_nonce_field('tiny_gototop_update_options'); ?> | |
<table class="form-table"> | |
<?php $this->render_settings_fields(); ?> | |
</table> | |
<hr /> | |
<code><small><?php _e('ℹ️ Live preview always present here in the backend!', 'tiny-gototop'); ?></small></code> | |
<div class="submit"> | |
<input type="submit" name="submit" class="button-primary" value="<?php _e('Save Changes', 'tiny-gototop'); ?>" /> | |
<input type="submit" name="reset" class="button-secondary" value="<?php _e('Restore Default', 'tiny-gototop'); ?>" /> | |
</div> | |
</form> | |
</div> | |
<?php | |
// Display the preview of the "go to top" button | |
$this->print_button(); | |
} | |
// Render the fields for the settings page | |
private function render_settings_fields() { | |
// Define the fields to be rendered | |
$fields = [ | |
'main_color' => __('Main Color', 'tiny-gototop'), | |
'secondary_color' => __('Secondary Color', 'tiny-gototop'), | |
'opacity' => __('Opacity', 'tiny-gototop'), | |
'position_right' => __('Right (px)', 'tiny-gototop'), | |
'position_bottom' => __('Bottom (px)', 'tiny-gototop'), | |
'padding' => __('Padding (px)', 'tiny-gototop'), | |
'width' => __('Width (px)', 'tiny-gototop'), | |
'height' => __('Height (px)', 'tiny-gototop'), | |
'border_radius' => __('Border Radius (%)', 'tiny-gototop'), | |
]; | |
// Loop through each field to render its label and input | |
foreach ($fields as $key => $label) { | |
echo '<tr>'; | |
echo '<th scope="row"><label for="tiny_gototop_' . $key . '">' . $label . '</label></th>'; | |
echo '<td>'; | |
// Render different input types based on the setting type | |
if ($key === 'opacity') { | |
$this->render_opacity_select($key); // Opacity uses a select dropdown | |
} elseif (in_array($key, ['main_color', 'secondary_color'])) { | |
$this->render_color_input($key); // Colors use a color picker | |
} else { | |
$this->render_number_input($key); // Others use a number input | |
} | |
echo '</td>'; | |
echo '</tr>'; | |
} | |
} | |
// Render the select dropdown for the opacity setting | |
private function render_opacity_select($key) { | |
$current_opacity = esc_attr($this->get_option($key)); | |
echo '<select class="go-to-top-select" name="tiny_gototop_' . $key . '" style="width:60px">'; | |
// Generate options from 0 to 1 in increments of 0.1 | |
for ($i = 0; $i <= 10; $i++) { | |
$value = $i / 10; | |
echo '<option value="' . $value . '" ' . selected($current_opacity, $value, false) . '>' . $value . '</option>'; | |
} | |
echo '</select>'; | |
} | |
// Render the color picker input | |
private function render_color_input($key) { | |
echo '<input type="text" class="tiny-color-picker" id="tiny_gototop_' . $key . '" name="tiny_gototop_' . $key . '" value="' . esc_attr($this->get_option($key)) . '" />'; | |
} | |
// Render the number input for various settings | |
private function render_number_input($key) { | |
echo '<input type="number" id="tiny_gototop_' . $key . '" name="tiny_gototop_' . $key . '" value="' . esc_attr($this->get_option($key)) . '" />'; | |
} | |
// Ensure the CSS file exists, generate it if it doesn't | |
public function check_css_file() { | |
$css_file = plugin_dir_path(__FILE__) . 'assets/tiny-gototop.css'; | |
if (!file_exists($css_file)) { | |
$this->generate_css(); | |
} | |
} | |
// Print the "go to top" button in the frontend or admin preview | |
public function print_button() { | |
$width = $this->get_option('width'); | |
$height = $this->get_option('height'); | |
// Attributes for the admin preview | |
$attrib = is_admin() ? 'title="' . __('Just a preview', 'tiny-gototop') . '" style="display:block" ' : ''; | |
echo ' | |
<!-- Go to top --> | |
<img id="go-to-top" src="' . plugin_dir_url(__FILE__) . 'assets/tiny-gototop.svg" alt="' . __('go to top (svg)', 'tiny-gototop') . '" width="' . esc_attr($width) . '" height="' . esc_attr($height) . '" ' . $attrib . '/> | |
<!-- Go to top -->'; | |
} | |
// Enqueue admin scripts and styles, including color picker and custom CSS | |
public function enqueue_admin_scripts($hook_suffix) { | |
if ($hook_suffix === 'settings_page_tiny-gototop') { | |
$css_version = time(); // Use current timestamp to avoid cache issues | |
wp_enqueue_style('wp-color-picker'); | |
wp_enqueue_script('tiny-gototop-backend-script', plugin_dir_url(__FILE__) . 'assets/tiny-gototop-backend.js', array('wp-color-picker'), false, true); | |
wp_enqueue_style('tiny-gototop-backend-style', plugin_dir_url(__FILE__) . 'assets/tiny-gototop-backend.css'); | |
wp_enqueue_style('tiny-gototop-style', plugin_dir_url(__FILE__) . 'assets/tiny-gototop.css', array(), $css_version); | |
} | |
} | |
// Enqueue frontend scripts and styles | |
public function enqueue_frontend_scripts() { | |
$this->check_css_file(); // Ensure the CSS file exists | |
$css_file = plugin_dir_path(__FILE__) . 'assets/tiny-gototop.css'; | |
$css_version = filemtime($css_file); // Use file modification time for cache busting | |
wp_enqueue_style('tiny-gototop-style', plugin_dir_url(__FILE__) . 'assets/tiny-gototop.css', array(), $css_version); | |
wp_enqueue_script('tiny-gototop-script', plugin_dir_url(__FILE__) . 'assets/tiny-gototop.js', array(), null, true); | |
} | |
} | |
// Instantiate the Tiny_GoToTop class to initialize the plugin | |
$tiny_gototop = new Tiny_GoToTop(); | |
// Clean if deactivated | |
register_deactivation_hook(__FILE__, ['Tiny_GoToTop', 'deactivate']); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment