PluginProbe
Extend Link / 2.0.0
Extend Link v2.0.0
trunk 2.0.0 2.0.1 2.0.2
extend-link / extend-link.php

extend-link.php in Extend Link 2.0.0, at extend-link.php

242 lines 12.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Extend Link
4 * Plugin URI: https://wp-time.com/how-to-add-link-attributes-in-wordpress/
5 * Description: Allows you to add classes, IDs, titles, rel attributes, and file download options to links directly from the "Extend Link" dialog in the Classic Editor and Classic Block in Gutenberg. It also provides H1–H6 support, so you can, for example, add an ID or classes to a heading. A lightweight, professional plugin, free and always will remain free!
6 * Version: 2.0.0
7 * Author: Alobaidi
8 * Author URI: https://wp-time.com/how-to-add-link-attributes-in-wordpress/
9 * Text Domain: extend-link
10 * Requires at least: 5.8
11 * Requires PHP: 7.4
12 * License: GPLv2 or later
13 * License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
14 *
15 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
16 * General Public License version 2, as published by the Free Software Foundation. You may NOT assume
17 * that you can use any other version of the GPL.
18 *
19 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
20 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 */
22
23 // Prevent direct access
24 if ( !defined('ABSPATH') ) {
25 exit;
26 }
27
28 if ( !class_exists('Extend_Link_TinyMCE') ) {
29
30 class Extend_Link_TinyMCE {
31 private static $instance = null;
32
33 /**
34 * Retrieves the singleton instance of this class
35 * Creates a new instance if one doesn't exist yet
36 *
37 * @return Extend_Link_TinyMCE The single instance of this class
38 */
39 public static function get_instance() {
40 if (null === self::$instance) {
41 self::$instance = new self();
42 }
43 return self::$instance;
44 }
45
46 /**
47 * constructor - intentionally empty
48 * Initialization happens in the init() method instead for better control
49 */
50 public function __construct() {
51 // No initialization here.
52 }
53
54 /**
55 * Initialize plugin
56 */
57 public function init() {
58 add_filter('plugin_row_meta', array($this, 'plugin_row_meta_custom'), 10, 2);
59 add_action('admin_enqueue_scripts', array($this, 'enqueue_translations'));
60 add_filter('mce_buttons', array($this, 'add_tinymce_button'));
61 add_filter('mce_external_plugins', array($this, 'add_tinymce_plugin'));
62 add_action('wp_ajax_extend_link_plu_check_link', array($this, 'check_link_status'));
63 }
64
65 /**
66 * Adds custom links to plugin's meta information row
67 */
68 public function plugin_row_meta_custom($links, $file) {
69 $plugin_file = plugin_basename(__FILE__);
70
71 if ( $file == $plugin_file ) {
72
73 $custom_links = array(
74 '<a style="font-weight:bold;" href="https://wp-time.com/how-to-add-link-attributes-in-wordpress/" target="_blank">' . esc_html__('Plugin Reference', 'extend-link') . '</a>',
75 '<a style="font-weight:bold;color:#4f9915;" href="https://wp-time.com/video-popup-plugin-for-wordpress/#live-demo" target="_blank">' . esc_html__('Video Popup Plugin', 'extend-link') . '</a>',
76 '<a style="font-weight:bold;color:#ce7825;" href="https://wp-time.com/wordpress-preloader/#preloader-for-wp" target="_blank">' . esc_html__('Preloader Plugin', 'extend-link') . '</a>'
77 );
78
79 $links = array_merge($links, $custom_links);
80 }
81 return $links;
82 }
83
84 /**
85 * Add TinyMCE plugin script
86 */
87 public function add_tinymce_button($buttons) {
88 array_push($buttons, 'extend_link');
89 return $buttons;
90 }
91
92 public function add_tinymce_plugin($plugin_array) {
93 $version = '2.0.0';
94 $plugin_array['extend_link'] = plugins_url('/js/tinymce-button.js?ver='.$version, __FILE__);
95 return $plugin_array;
96 }
97
98 /**
99 * Enqueue translations for JavaScript
100 */
101 public function enqueue_translations($hook) {
102 // Only load on post/page editor screens
103 if ( !in_array($hook, array('post.php', 'post-new.php')) ) {
104 return;
105 }
106
107 wp_enqueue_style(
108 'extend_link_tinymce-button-style',
109 plugins_url('/css/tinymce-button-style.css', __FILE__),
110 array(),
111 '2.0.0'
112 );
113
114 // Prepare translations array
115 $translations = array(
116 'plugin_name' => __('Extend Link', 'extend-link'),
117 'dialog_btn_tooltip' => __('Allows you to add classes, IDs, titles, rel attributes, and file download options to links. It also allows adding an ID or classes to a heading.', 'extend-link'),
118 'dialog_title' => __('Insert/Edit Link or Add an ID or Classes to a Heading', 'extend-link'),
119 'link' => __('Link', 'extend-link'),
120 'url' => __('URL', 'extend-link'),
121 'link_text' => __('Link Text', 'extend-link'),
122 'link_text_placeholder' => __('Click here', 'extend-link'),
123 'title' => __('Title (tooltip)', 'extend-link'),
124 'title_placeholder' => __('Link description', 'extend-link'),
125 'id' => __('ID', 'extend-link'),
126 'id_placeholder' => __('link-id', 'extend-link'),
127 'classes' => __('Class(es)', 'extend-link'),
128 'classes_placeholder' => __('class-1 class-2', 'extend-link'),
129 'open_new_tab' => __('Open in new tab', 'extend-link'),
130 'add_nofollow' => __('Add rel="nofollow"', 'extend-link'),
131 'add_noreferrer' => __('Add rel="noreferrer"', 'extend-link'),
132 'add_noopener' => __('Add rel="noopener"', 'extend-link'),
133 'download_file' => __('Download file (instead of opening)', 'extend-link'),
134 'cancel' => __('Cancel', 'extend-link'),
135 'save' => __('Save', 'extend-link'),
136 'error_text_required' => __('Please enter link text', 'extend-link'),
137
138 'url_tooltip' => __('Enter a link.', 'extend-link'),
139 'link_text_tooltip' => __('Enter the text that will appear for the link.', 'extend-link'),
140 'title_tooltip' => __('Optional tooltip text shown on hover.', 'extend-link'),
141 'id_tooltip' => __('A single unique ID for the link (only one allowed).', 'extend-link'),
142 'classes_tooltip' => __('Add one or more CSS classes separated by spaces.', 'extend-link'),
143
144 'open_new_tab_tooltip' => __('Open the link in a new browser tab.', 'extend-link'),
145 'add_nofollow_tooltip' => __('Prevent search engines from following this link.', 'extend-link'),
146 'add_noreferrer_tooltip' => __('Hide the referrer information when the link is clicked.', 'extend-link'),
147 'add_noopener_tooltip' => __('Improve security by preventing the new page from accessing the opener.', 'extend-link'),
148 'download_file_tooltip' => __('Force the browser to download the file instead of opening it. Use this only with a direct file URL (e.g., https://example.com/video.mp4). Note: This option may not work in some browsers.', 'extend-link'),
149
150 'check_btn_text' => __('Check', 'extend-link'),
151 'check_btn_label' => __('Check Link Status', 'extend-link'),
152 'check_btn_tooltip' => __('Check whether the link is working or broken. Useful for SEO.', 'extend-link'),
153 'check_btn_no_url' => __('Please enter a URL first to check its status.', 'extend-link'),
154 'check_btn_disabled' => __('Please wait...', 'extend-link'),
155 'check_btn_working_link' => __('Link is working!', 'extend-link'),
156 'check_btn_broken_link' => __('Link is broken!', 'extend-link'),
157 'check_btn_error' => __('Error checking link. Please try again after a few seconds.', 'extend-link'),
158
159 'plugin_ref_btn_text' => __('Plugin Reference', 'extend-link'),
160 'plugin_ref_btn_tooltip' => __('Everything related to the plugin can be found on this page.', 'extend-link'),
161 'plugin_support_btn_text' => __('Support', 'extend-link'),
162 'plugin_support_btn_tooltip' => __('The Extend Link plugin is free and will always remain free. Contact us if you have any questions or feature suggestions to help improve the plugin.', 'extend-link'),
163 'plugin_rate_btn_text' => __('Rate Plugin', 'extend-link'),
164 'plugin_rate_btn_tooltip' => __('Rate this plugin to support its development.', 'extend-link'),
165 'plugin_label_note' => __('This plugin is completely free and will remain free, even as we add more features. So, suggestions for our other plugins, like Preloader and Video Popup, help us continue development.', 'extend-link'),
166
167 'vp_plugin_btn_text' => __('Video Popup Plugin', 'extend-link'),
168 'vp_plugin_btn_tooltip' => __('From our plugins: The ultimate Video Popup plugin for WordPress. Smart, flexible, and made for easy control. Create unlimited, on-brand, and elegant responsive popups for YouTube, Vimeo, MP4 & WebM videos on click or On-Page Load.', 'extend-link'),
169 'preloader_plugin_btn_text' => __('Preloader Plugin', 'extend-link'),
170 'preloader_plugin_btn_tooltip' => __('From our plugins: The ultimate Preloader plugin for WordPress. Add a preloader to your website easily in only 3 steps. Simple, fast, and compatible with all major browsers.', 'extend-link')
171 );
172
173 // Add translations to page as inline script
174 wp_add_inline_script(
175 'wp-tinymce',
176 'window.extendLinkI18n = ' . wp_json_encode($translations) . ';',
177 'before'
178 );
179
180 wp_add_inline_script(
181 'wp-tinymce',
182 'var extendLinkAjax = ' . json_encode(array(
183 'ajaxurl' => admin_url('admin-ajax.php'),
184 'nonce' => wp_create_nonce('extend_link_check_status_nonce')
185 )) . ';',
186 'before'
187 );
188 }
189
190 public function check_link_status() {
191
192 if ( !isset($_POST['nonce']) || empty($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'extend_link_check_status_nonce') ) {
193 wp_send_json_error(['message' => __('Security check failed. Please refresh the page and try again.', 'extend-link')]);
194 }
195
196 $url = isset($_POST['url']) ? sanitize_url(wp_unslash($_POST['url'])) : '';
197
198 $url = !empty(trim($url)) ? esc_url_raw($url) : '';
199
200 if (empty($url)) {
201 wp_send_json_error(['message' => __('Please enter a URL first to check its status.', 'extend-link')]);
202 }
203
204 if ( !filter_var($url, FILTER_VALIDATE_URL) ) {
205 wp_send_json_error(['message' => __('Please enter a valid URL.', 'extend-link')]);
206 }
207
208 $response = wp_remote_head($url, array(
209 'timeout' => 10,
210 'sslverify' => false
211 ));
212
213 if (is_wp_error($response)) {
214 wp_send_json_error(__('There is an error. Please try again after a few seconds.', 'extend-link'));
215 }
216
217 $status = wp_remote_retrieve_response_code($response);
218
219 if ($status >= 200 && $status < 400) {
220 wp_send_json_success([
221 'message' => sprintf(
222 // translators: %s will be replaced with the HTTP status code of the working link.
223 __('Link is working (Status: %s)', 'extend-link'),
224 $status
225 )
226 ]);
227 } else {
228 wp_send_json_error([
229 'message' => sprintf(
230 // translators: %s will be replaced with the HTTP status code of the broken link.
231 __('Link is broken (Status: %s)', 'extend-link'),
232 $status
233 )
234 ]);
235 }
236 }
237 }
238
239 // Initialize plugin
240 $Extend_Link_TinyMCE = Extend_Link_TinyMCE::get_instance();
241 $Extend_Link_TinyMCE->init();
242 }