PluginProbe
Easy Footnotes / 1.1.11
Easy Footnotes v1.1.11
trunk 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.2 All 32 releases
easy-footnotes / easy-footnotes.php

easy-footnotes.php in Easy Footnotes 1.1.11, at easy-footnotes.php

324 lines 11.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Easy Footnotes
4 * Plugin URI: https://jasonyingling.me/easy-footnotes-wordpress/
5 * Description: Easily add footnotes to your posts with a simple shortcode.
6 * Text Domain: easy-footnotes
7 * Version: 1.1.11
8 * Author: Jason Yingling
9 * Author URI: https://jasonyingling.me
10 * License: GPL2
11 *
12 * @package easy-footnotes
13 */
14
15 /*
16 Copyright 2018 Jason Yingling (email : yingling017@gmail.com)
17
18 This program is free software; you can redistribute it and/or modify
19 it under the terms of the GNU General Public License, version 2, as
20 published by the Free Software Foundation.
21
22 This program is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
26
27 You should have received a copy of the GNU General Public License
28 along with this program; if not, write to the Free Software
29 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 */
31 /**
32 * The Easy Footnotes class. In camel case. Because I didn't follow WPCS way back when.
33 */
34 class easyFootnotes {
35
36 /**
37 * Add label option using add_option if it does not already exist.
38 *
39 * @var array $footnotes An array for the footnotes to be stored.
40 */
41 public $footnotes = array();
42 public $footnoteCount = 0;
43 public $prevPost;
44 public $footnoteOptions;
45 public $footnoteLookup = array();
46 public $usedFootnoteNumbers = array();
47
48 private $footnoteSettings;
49
50 private $version = '1.1.11';
51
52 /**
53 * Constructing the initial plugin options, shortcodes, and hooks.
54 */
55 public function __construct() {
56 $this->footnoteSettings = array(
57 'footnoteLabel' => __( 'Footnotes', 'easy-footnotes' ),
58 'useLabel' => false,
59 'hide_easy_footnote_after_posts' => false,
60 'show_easy_footnote_on_front' => false,
61 'reset_footnotes' => false,
62 'combine_duplicate_footnotes' => false,
63 );
64
65 add_option( 'easy_footnotes_options', $this->footnoteSettings );
66 add_shortcode( 'note', array( $this, 'easy_footnote_shortcode' ) );
67 add_shortcode( 'efn_note', array( $this, 'easy_footnote_shortcode' ) );
68 add_shortcode( 'efn_reset', array( $this, 'short_code_reset' ) );
69 add_filter( 'the_content', array( $this, 'easy_footnote_after_content' ), 20 );
70
71 $this->footnoteOptions = get_option( 'easy_footnotes_options' );
72 if ( isset( $this->footnoteOptions['reset_footnotes'] ) && $this->footnoteOptions['reset_footnotes'] || ( ! isset( $this->footnoteOptions[ 'combine_duplicate_footnotes' ] ) || $this->footnoteOptions[ 'combine_duplicate_footnotes' ] === false ) ) {
73 add_filter( 'the_content', array( $this, 'easy_footnote_reset' ), 999 );
74 }
75
76 add_action( 'wp_enqueue_scripts', array( $this, 'register_qtip_scripts' ) );
77 add_action( 'admin_menu', array( $this, 'easy_footnotes_admin_actions' ) );
78 add_action( 'admin_enqueue_scripts', array( $this, 'easy_footnotes_admin_scripts' ) );
79 add_action( 'init', array($this, 'efn_load_textdomain') );
80
81 $this->footnoteOptions = get_option( 'easy_footnotes_options' );
82 }
83
84 /**
85 * Registering the scripts and styles used by jQuery qTip.
86 */
87 public function register_qtip_scripts() {
88 wp_register_script( 'imagesloaded', plugins_url( '/assets/qtip/imagesloaded.pkgd.min.js', __FILE__ ), array(), $this->version, true );
89 wp_register_script( 'qtip', plugins_url( '/assets/qtip/jquery.qtip.min.js', __FILE__ ), array( 'jquery', 'imagesloaded' ), $this->version, true );
90 wp_register_script( 'qtipcall', plugins_url( '/assets/qtip/jquery.qtipcall.js', __FILE__ ), array( 'jquery', 'qtip' ), $this->version, true );
91 wp_register_style( 'qtipstyles', plugins_url( '/assets/qtip/jquery.qtip.min.css', __FILE__ ), array(), $this->version, false );
92 wp_register_style( 'easyfootnotescss', plugins_url( '/assets/easy-footnotes.css', __FILE__ ), array(), $this->version, false );
93 }
94
95 /**
96 * Create the Easy Footnotes shortcode.
97 *
98 * @param array $atts Shortcode attributes.
99 * @param string $content Content within the shortcode.
100 */
101 public function easy_footnote_shortcode( $atts, $content = null ) {
102 if ( isset( $this->footnoteOptions['show_easy_footnote_on_front'] ) && $this->footnoteOptions['show_easy_footnote_on_front'] ) {
103 $efn_show_on_front = is_front_page();
104 } else {
105 $efn_show_on_front = false;
106 }
107
108 wp_enqueue_style( 'qtipstyles' );
109 wp_enqueue_style( 'easyfootnotescss' );
110 wp_enqueue_script( 'imagesloaded' );
111 wp_enqueue_script( 'qtip' );
112 wp_enqueue_script( 'qtipcall' );
113 wp_enqueue_style( 'dashicons' );
114
115 // Accept optional custom number attribute
116 $atts = shortcode_atts(
117 array(
118 'num' => null
119 ),
120 $atts
121 );
122
123 $post_id = get_the_ID();
124
125 $content = do_shortcode( $content );
126
127 $content_id = md5( preg_replace("/[^A-Za-z0-9 ]/", '', wp_strip_all_tags( html_entity_decode( $content ) ) ) );
128
129 /**
130 * Search for existing footnote for removing duplicate
131 * Also add the same numbers to duplicate footnotes
132 */
133 if (!isset($this->usedFootnoteNumbers)) {
134 $this->usedFootnoteNumbers = array();
135 }
136 if (!isset($this->footnoteLookup)) {
137 $this->footnoteLookup = array();
138 }
139
140 // If a custom number is provided, use that number and mark it as used
141 if ( ! empty( $atts['num'] ) ) {
142 $footnote_number = intval( $atts['num'] );
143 $this->usedFootnoteNumbers[] = $footnote_number; // Track custom number
144 $this->footnoteLookup[$content_id] = $footnote_number;
145 $this->footnotes[$footnote_number] = $content;
146 } elseif ( isset( $this->footnoteLookup[$content_id] ) && isset( $this->footnoteOptions[ 'combine_duplicate_footnotes' ] ) && $this->footnoteOptions[ 'combine_duplicate_footnotes' ] === true ) {
147 // Use existing footnote number for duplicate content
148 $footnote_number = $this->footnoteLookup[$content_id];
149 } else {
150 // Auto-increment for new footnotes, skipping used numbers
151 do {
152 $this->footnoteCount++;
153 } while ( in_array( $this->footnoteCount, $this->usedFootnoteNumbers ) );
154
155 $footnote_number = $this->footnoteCount;
156 $this->footnoteLookup[$content_id] = $footnote_number;
157 $this->usedFootnoteNumbers[] = $footnote_number; // Mark as used
158 $this->footnotes[$footnote_number] = $content;
159 }
160
161 // Generate the correct footnote link with the correct number
162 $footnoteLink = (is_singular() || $efn_show_on_front) && is_main_query()
163 ? '#easy-footnote-bottom-' . $footnote_number . '-' . $post_id
164 : get_permalink($post_id) . '#easy-footnote-bottom-' . $footnote_number . '-' . $post_id;
165
166 // Now generate the footnote markup with the correct number and link
167 $footnoteContent = "<span id='easy-footnote-" . esc_attr($footnote_number) . '-' . $post_id
168 . "' class='easy-footnote-margin-adjust'></span><span class='easy-footnote'>"
169 . "<a href='" . esc_url($footnoteLink) . "' title='" . htmlspecialchars($content, ENT_QUOTES)
170 . "'><sup>" . esc_html($footnote_number) . "</sup></a></span>";
171
172 return $footnoteContent;
173 }
174
175 /**
176 * The content of a particular footnote.
177 *
178 * @param string $content The content from a particular call of the shortcode.
179 */
180 public function easy_footnote_content( $content ) {
181 $this->footnotes[ $this->footnoteCount ] = $content;
182
183 return $this->footnotes;
184 }
185
186 /**
187 * Display the list of footnotes after the post content.
188 *
189 * @param string $content The content of the current post.
190 */
191 public function easy_footnote_after_content( $content ) {
192 if ( isset( $this->footnoteOptions['hide_easy_footnote_after_posts'] ) && $this->footnoteOptions['hide_easy_footnote_after_posts'] ) {
193 return $content;
194 }
195
196 if ( isset( $this->footnoteOptions['show_easy_footnote_on_front'] ) && $this->footnoteOptions['show_easy_footnote_on_front'] ) {
197 $efn_show_on_front = is_front_page() || is_home();
198 } else {
199 $efn_show_on_front = false;
200 }
201
202 if ( ( is_singular() || $efn_show_on_front ) && is_main_query() ) {
203 $footnotesInsert = $this->footnotes;
204
205 $footnoteCopy = '';
206 $efn_output = '';
207
208 $useLabel = isset( $this->footnoteOptions['useLabel'] ) ? $this->footnoteOptions['useLabel'] : false;
209 $efLabel = isset($this->footnoteOptions['footnoteLabel'] ) ? $this->footnoteOptions['footnoteLabel'] : __( 'Footnotes', 'easy-footnotes' );
210
211 $post_id = get_the_ID();
212
213 // Create a new array to track used footnotes and their numbers
214 $footnote_number = 1;
215
216 // sort footnotes according to numbers
217 ksort($footnotesInsert);
218
219 foreach ( $footnotesInsert as $count => $footnote ) {
220
221 if ( isset( $this->footnoteOptions[ 'combine_duplicate_footnotes' ] ) && $this->footnoteOptions[ 'combine_duplicate_footnotes' ] === true ) {
222 // If the footnote is already in the lookup, use its number
223 if ( isset( $this->footnoteLookup[$footnote] ) ) {
224 $count = $this->footnoteLookup[$footnote];
225 } else {
226 // Skip custom numbers that were already used
227 while ( in_array( $footnote_number, $this->usedFootnoteNumbers ) ) {
228 $footnote_number++;
229 }
230 }
231 }
232 // Generate back-to-top link and the footnote item
233 $footnoteCopy .= '<li class="easy-footnote-single"><span id="easy-footnote-bottom-' . esc_attr( $count ) . '-' . $post_id . '" class="easy-footnote-margin-adjust"></span>' . wp_kses_post( $footnote ) . '<a class="easy-footnote-to-top" href="' . esc_url( '#easy-footnote-' . $count . '-' . $post_id ) . '"></a></li>';
234 }
235 if ( ! empty( $footnotesInsert ) ) {
236 if ( true === $useLabel ) {
237 $footnote_label = '<div class="easy-footnote-title"><h4>' . esc_html( $efLabel ) . '</h4></div>';
238 // Filter for editing footnote label markup and output.
239 $footnote_label = apply_filters( 'efn_footnote_label', $footnote_label, $efLabel );
240
241 $efn_output .= $footnote_label;
242 }
243
244 $footnote_content = '';
245
246 // Add filter before footnote list.
247 $footnote_content = apply_filters( 'before_footnote', $footnote_content );
248 $footnote_content .= '<ol class="easy-footnotes-wrapper">' . $footnoteCopy . '</ol>';
249
250 // Add filter after footnote list.
251 $footnote_content = apply_filters( 'after_footnote', $footnote_content );
252
253 $efn_output .= $footnote_content;
254
255 // Add filters for the entire footnote list output.
256 $efn_output = apply_filters( 'efn_footnote_list_output', $efn_output );
257
258 $content .= do_shortcode( $efn_output );
259 }
260 }
261
262 return $content;
263 }
264
265 /**
266 * Reset the footnote count and footnote array each time the_content has been run.
267 *
268 * @param string $content The content of the post from the_content filter.
269 */
270 public function easy_footnote_reset( $content ) {
271 $this->footnoteCount = 0;
272
273 $this->footnotes = array();
274
275 return $content;
276 }
277
278 /**
279 * Include the easy-footnotes-admin.php file.
280 */
281 public function easy_footnotes_admin() {
282 include 'easy-footnotes-admin.php';
283 }
284
285 /**
286 * Function to add options page for Easy Footnote Settings.
287 */
288 public function easy_footnotes_admin_actions() {
289 add_options_page(
290 __( 'Easy Footnotes Settings', 'easy-footnotes' ),
291 __( 'Easy Footnotes', 'easy-footnotes' ),
292 'manage_options',
293 'easy-footnotes-settings',
294 array( $this, 'easy_footnotes_admin' )
295 );
296 }
297
298 /**
299 * Function for enqueuring EAsy Footnotes admin scripts.
300 */
301 public function easy_footnotes_admin_scripts() {
302 wp_enqueue_style( 'easy-footnotes-admin-styles', plugins_url( '/assets/easy-footnotes-admin.css', __FILE__ ), '', $this->version );
303 wp_enqueue_script( 'easy-footnotes-admin-scripts', plugins_url( '/assets/js/easy-footnotes-admin.js', __FILE__ ), array( 'jquery' ), $this->version, true );
304 }
305
306 /**
307 * Load plugin textdomain easy-footnotes
308 */
309 public function efn_load_textdomain() {
310 load_plugin_textdomain( 'easy-footnotes', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
311 }
312
313 /**
314 * Manually reset footnotes and counter
315 */
316 public function short_code_reset() {
317 $this->footnoteCount = 0;
318 $this->footnotes = array();
319 return "";
320 }
321 }
322
323 $easyFootnotes = new easyFootnotes();
324