PluginProbe
Plugins List / 2.5.2
Plugins List v2.5.2
trunk 0.2.1 0.2.2 1.0 2.0 2.1 2.2.7 2.3.2 2.4.4 2.5.2 2.6 2.6.1 2.7
plugins-list / plugins-list.php

plugins-list.php in Plugins List 2.5.2, at plugins-list.php

648 lines 18.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugins List
4 *
5 * @package plugins-list
6 * @author David Artiss
7 * @license GPL-2.0-or-later
8 *
9 * Plugin Name: Plugins List
10 * Plugin URI: https://wordpress.org/plugins/plugins-list/
11 * Description: 🔌 Allows you to insert a list of the WordPress plugins you are using into any post/page.
12 * Version: 2.5.2
13 * Requires at least: 4.6
14 * Requires PHP: 7.4
15 * Author: David Artiss
16 * Author URI: https://artiss.blog
17 * Text Domain: plugins-list
18 * License: GPL v2 or later
19 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
20 *
21 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
22 * General Public License version 2, as published by the Free Software Foundation. You may NOT assume
23 * that you can use any other version of the GPL.
24 *
25 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
26 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
27 */
28
29 define( 'DEFAULT_PLUGIN_LIST_FORMAT', '<li>{{LinkedTitle}} by {{LinkedAuthor}}.</li>' );
30
31 if ( ! function_exists( 'get_plugins' ) ) {
32 require_once ABSPATH . 'wp-admin/includes/plugin.php'; }
33
34 /**
35 * Add meta to plugin details
36 *
37 * Add options to plugin meta line
38 *
39 * @param string $links Current links.
40 * @param string $file File in use.
41 * @return string Links, now with settings added.
42 */
43 function set_plugins_list_meta( $links, $file ) {
44
45 if ( false !== strpos( $file, 'plugins-list.php' ) ) {
46
47 $links = array_merge( $links, array( '<a href="https://github.com/dartiss/plugins-list">' . __( 'Github', 'plugins-list' ) . '</a>' ) );
48
49 $links = array_merge( $links, array( '<a href="http://wordpress.org/support/plugin/plugins-list">' . __( 'Support', 'plugins-list' ) . '</a>' ) );
50
51 $links = array_merge( $links, array( '<a href="https://artiss.blog/donate">' . __( 'Donate', 'plugins-list' ) . '</a>' ) );
52
53 $links = array_merge( $links, array( '<a href="https://wordpress.org/support/plugin/plugins-list/reviews/#new-post">' . __( 'Write a Review', 'plugins-list' ) . '&nbsp;⭐️⭐️⭐️⭐️⭐️</a>' ) );
54 }
55
56 return $links;
57 }
58
59 add_filter( 'plugin_row_meta', 'set_plugins_list_meta', 10, 2 );
60
61 /**
62 * Main Shortcode Function
63 *
64 * Extract shortcode parameters and call main function to output results
65 *
66 * @uses get_plugins_list Get the list of plugins
67 *
68 * @param string $paras Shortcode parameters.
69 * @return stri Output.
70 */
71 function plugins_list_shortcode( $paras ) {
72
73 $atts = shortcode_atts(
74 array(
75 'format' => '',
76 'show_inactive' => '',
77 'show_active' => '',
78 'cache' => '',
79 'nofollow' => '',
80 'target' => '',
81 'by_author' => '',
82 'chars' => '',
83 'words' => '',
84 'emoji' => '',
85 'end' => '',
86 ),
87 $paras
88 );
89
90 // Pass the shortcode parameters onto a function to generate the plugins list.
91
92 $output = get_plugins_list( $atts['format'], $atts['show_inactive'], $atts['show_active'], $atts['cache'], $atts['nofollow'], $atts['target'], $atts['by_author'], $atts['chars'], $atts['words'], $atts['emoji'], $atts['end'] );
93
94 return $output;
95 }
96
97 add_shortcode( 'plugins_list', 'plugins_list_shortcode' );
98
99 /**
100 * Number of plugins shortcode
101 *
102 * Shortcode to return number of plugins
103 *
104 * @uses get_plugin_number Get the number of plugins
105 *
106 * @param string $paras Shortcode parameters.
107 * @return string Output.
108 */
109 function plugin_number_shortcode( $paras ) {
110
111 $atts = shortcode_atts(
112 array(
113 'active' => 'true',
114 'inactive' => 'false',
115 'cache' => 5,
116 ),
117 $paras
118 );
119
120 $output = get_plugin_number( $atts['active'], $atts['inactive'], $atts['cache'] );
121
122 return $output;
123 }
124
125 add_shortcode( 'plugins_number', 'plugin_number_shortcode' );
126
127 /**
128 * Get Plugins List
129 *
130 * Get list of plugins and, optionally, format them
131 *
132 * @uses format_plugin_list Format the plugin list
133 * @uses get_plugin_list_data Get the plugin data
134 *
135 * @param string $format Requires format.
136 * @param string $show_inactive Whether to format or not.
137 * @param string $show_active Whether to show active or not.
138 * @param string $cache Cache time.
139 * @param string $nofollow Whether to add nofollow to link.
140 * @param string $target Link target.
141 * @param string $by_author Which author.
142 * @param string $characters Maximum characters for description.
143 * @param string $words Maximum words for description.
144 * @param string $emoji True or false, whether to strip emoji from description.
145 * @param string $end When the description is truncated, what to place at the end of the string.
146 * @return string Output.
147 */
148 function get_plugins_list( $format, $show_inactive, $show_active, $cache, $nofollow, $target, $by_author, $characters, $words, $emoji, $end ) {
149
150 // Set default values.
151
152 if ( '' === $format ) {
153 $format = DEFAULT_PLUGIN_LIST_FORMAT;
154 }
155 if ( '' === $show_inactive ) {
156 $show_inactive = 'false';
157 }
158 if ( '' === $show_active ) {
159 $show_active = 'true';
160 }
161 if ( '' === $cache ) {
162 $cache = 5;
163 }
164 if ( $nofollow ) {
165 $nofollow = ' rel="nofollow"';
166 } else {
167 $nofollow = '';
168 }
169 if ( '' !== $target ) {
170 $target = ' target="' . $target . '"';
171 } else {
172 $target = '';
173 }
174 if ( '' !== $by_author ) {
175 $by_author = 'true';
176 }
177 if ( 'false' == $emoji ) {
178 $emoji = false;
179 } else {
180 $emoji = true;
181 }
182 if ( '' == $end ) {
183 $end = '&#8230;';
184 }
185
186 // Get plugin data.
187
188 $plugins = get_plugin_list_data( $cache );
189
190 // Sort the plugin array if required in author sequence.
191
192 if ( 'true' === $by_author ) {
193 uasort(
194 $plugins,
195 function( $a, $b ) {
196 return strtoupper( $a['Author'] ) <=> strtoupper( $b['Author'] );
197 }
198 );
199 }
200
201 // Extract each plugin and format the output.
202
203 $output = '';
204
205 foreach ( $plugins as $plugin_file => $plugin_data ) {
206
207 if ( ( is_plugin_active( $plugin_file ) && 'true' === $show_active ) || ( ! is_plugin_active( $plugin_file ) && 'true' === $show_inactive ) ) {
208
209 $output .= format_plugin_list( $plugin_data, $format, $nofollow, $target, $characters, $words, $emoji, $end );
210 }
211 }
212
213 // Return the code, with HTML comments.
214
215 return "\n" . $output . "\n";
216
217 }
218
219 /**
220 * Get Plugin number
221 *
222 * Get number of plugins
223 *
224 * @since 2.2
225 *
226 * @uses get_plugin_list_data Get the plugin data
227 *
228 * @param string $show_active Whether to include active plugins or not.
229 * @param string $show_inactive Whether to include inactive plugins or not.
230 * @param string $cache Cache time.
231 * @return string Plugin number.
232 */
233 function get_plugin_number( $show_active, $show_inactive, $cache ) {
234
235 // Get plugin data.
236
237 $plugins = get_plugin_list_data( $cache );
238
239 // Get count.
240
241 if ( 'true' === $show_inactive && 'true' === $show_active ) {
242 $output = count( $plugins );
243 } else {
244 $output = 0;
245 foreach( $plugins as $plugin_file => $plugin_data ) { // @codingStandardsIgnoreLine -- require $plugin_data for array values but not doing anything with it
246 if ( is_plugin_active( $plugin_file ) ) {
247 $output++;
248 }
249 }
250 if ( 'true' === $show_inactive ) {
251 $output = count( $plugins ) - $output; }
252 }
253
254 return $output;
255 }
256
257 /**
258 * Get Plugins data
259 *
260 * Get plugin data and cache it
261 *
262 * @uses format_plugin_list Format the plugin list.
263 *
264 * @param string $cache Cache time.
265 * @return string Plugin data.
266 */
267 function get_plugin_list_data( $cache ) {
268
269 // Attempt to get plugin list from cache.
270
271 if ( ! $cache ) {
272 $cache = 'no'; }
273
274 $plugins = false;
275 $cache_key = 'plugins_list';
276 if ( is_numeric( $cache ) ) {
277 $plugins = get_transient( $cache_key ); }
278
279 // If not using cache, generate a new list and cache that.
280
281 if ( ! $plugins ) {
282 $plugins = get_plugins();
283 if ( ( '' !== $plugins ) && ( is_numeric( $cache ) ) ) {
284 set_transient( $cache_key, $plugins, MINUTE_IN_SECONDS * $cache ); }
285 }
286
287 return $plugins;
288 }
289
290 /**
291 * Format Plugin List
292 *
293 * Format the plugin list
294 *
295 * @uses replace_plugin_list_tags Replace the tags
296 *
297 * @param string $plugin_data The plugin list.
298 * @param string $format Format to use.
299 * @param string $nofollow Nofollow text.
300 * @param string $target Target text.
301 * @param string $characters Maximum characters for description.
302 * @param string $words Maximum words for description.
303 * @param string $emoji True or false, whether to strip emoji from description.
304 * @param string $end When the description is truncated, what to place at the end of the string.
305 * @return string Output.
306 */
307 function format_plugin_list( $plugin_data, $format, $nofollow, $target, $characters, $words, $emoji, $end ) {
308
309 // Allowed tag.
310
311 $plugins_allowedtags = array(
312 'a' => array(
313 'href' => array(),
314 'title' => array(),
315 ),
316 'abbr' => array( 'title' => array() ),
317 'acronym' => array( 'title' => array() ),
318 'code' => array(),
319 'em' => array(),
320 'strong' => array(),
321 );
322
323 // Sanitize all displayed data.
324
325 $plugin_data['Title'] = wp_kses( $plugin_data['Title'], $plugins_allowedtags );
326 $plugin_data['PluginURI'] = wp_kses( $plugin_data['PluginURI'], $plugins_allowedtags );
327 $plugin_data['AuthorURI'] = wp_kses( $plugin_data['AuthorURI'], $plugins_allowedtags );
328 $plugin_data['Version'] = wp_kses( $plugin_data['Version'], $plugins_allowedtags );
329 $plugin_data['Author'] = wp_kses( $plugin_data['Author'], $plugins_allowedtags );
330
331 // Strip emoji, HTML and unnecessary space from the description.
332 if ( false == $emoji ) {
333 $plugin_data['Description'] = remove_emoji_from_plugin_desc( $plugin_data['Description'] );
334 }
335 $plugin_data['Description'] = strip_spaces_from_plugin_desc( wp_strip_all_tags( $plugin_data['Description'] ) );
336
337 // Truncate the description, if required.
338
339 if ( '' != $characters || '' != $words ) {
340
341 // Use WordPress function to truncate description at a set number of words (ellipsis added automatically).
342
343 if ( '' != $words ) {
344 $word_limited = wp_trim_words( $plugin_data['Description'], $words, $end );
345 $plugin_data['Description'] = $word_limited;
346 }
347
348 // Manually truncate description to a set number of characters. This is done cleanly, however, by doing so to
349 // the previous space. Then an ellipsis is added.
350
351 if ( '' != $characters ) {
352 $character_limited = $plugin_data['Description'];
353 // Make sure the description is greater than the required length.
354 if ( strlen( $character_limited ) > $characters ) {
355 $space = strrpos( substr( $character_limited, 0, $characters + 1 ), ' ' );
356
357 if ( false == $space ) {
358 // If there is no space before the truncation length, just truncate.
359 $character_limited = substr( $character_limited, 0, $characters );
360 } else {
361 // If there is a space within the truncated area, trim to that.
362 $character_limited = substr( $character_limited, 0, $space );
363 }
364 $plugin_data['Description'] = rtrim( $character_limited ) . $end;
365 }
366 }
367
368 // If both words and character limits are used, take whichever results in the shortest result.
369
370 if ( ( '' != $characters && '' != $words ) && ( $word_limited < $character_limited ) ) {
371 $plugin_data['Description'] = $word_limited;
372 }
373 }
374
375 // Replace the tags.
376
377 $format = replace_plugin_list_tags( $plugin_data, $format, $nofollow, $target );
378
379 return $format;
380 }
381
382 /**
383 * Replace tags
384 *
385 * Replace the tags in the provided format
386 *
387 * @param string $plugin_data The plugin list.
388 * @param string $format Format to use.
389 * @param string $nofollow Nofollow text.
390 * @param string $target Target text.
391 * @return string Output.
392 */
393 function replace_plugin_list_tags( $plugin_data, $format, $nofollow, $target ) {
394
395 $format = strtr(
396 $format,
397 array(
398 '{{Title}}' => $plugin_data['Title'],
399 '{{PluginURI}}' => $plugin_data['PluginURI'],
400 '{{AuthorURI}}' => $plugin_data['AuthorURI'],
401 '{{Version}}' => $plugin_data['Version'],
402 '{{Description}}' => $plugin_data['Description'],
403 '{{Author}}' => $plugin_data['Author'],
404 '{{LinkedTitle}}' => "<a href='" . $plugin_data['PluginURI'] . "' title='" . $plugin_data['Title'] . "'" . $nofollow . $target . '>' . $plugin_data['Title'] . '</a>',
405 '{{LinkedAuthor}}' => "<a href='" . $plugin_data['AuthorURI'] . "' title='" . $plugin_data['Author'] . "'" . $nofollow . $target . '>' . $plugin_data['Author'] . '</a>',
406 '#Title#' => $plugin_data['Title'],
407 '#PluginURI#' => $plugin_data['PluginURI'],
408 '#AuthorURI#' => $plugin_data['AuthorURI'],
409 '#Version#' => $plugin_data['Version'],
410 '#Description#' => $plugin_data['Description'],
411 '#Author#' => $plugin_data['Author'],
412 '#LinkedTitle#' => "<a href='" . $plugin_data['PluginURI'] . "' title='" . $plugin_data['Title'] . "'" . $nofollow . $target . '>' . $plugin_data['Title'] . '</a>',
413 '#LinkedAuthor#' => "<a href='" . $plugin_data['AuthorURI'] . "' title='" . $plugin_data['Author'] . "'" . $nofollow . $target . '>' . $plugin_data['Author'] . '</a>',
414 '{{' => '<',
415 '}}' => '>',
416 '{' => '<',
417 '}' => '>',
418 )
419 );
420
421 // Remove all HTML tags other than those used for formatting.
422
423 $allowed_tags = array(
424 'a' => array(
425 'href' => array(),
426 'hreflang' => array(),
427 'rel' => array(),
428 'target' => array(),
429 'type' => array(),
430 'class' => array(),
431 'style' => array(),
432 ),
433 'b' => array(),
434 'big' => array(),
435 'blockquote' => array(
436 'cite' => array(),
437 'class' => array(),
438 'style' => array(),
439 ),
440 'br' => array(),
441 'caption' => array(),
442 'center' => array(),
443 'cite' => array(),
444 'code' => array(
445 'pre' => array(),
446 'class' => array(),
447 'style' => array(),
448 ),
449 'col' => array(
450 'span' => array(),
451 'class' => array(),
452 'style' => array(),
453 ),
454 'colgroup' => array(
455 'span' => array(),
456 'class' => array(),
457 'style' => array(),
458 ),
459 'div' => array(
460 'class' => array(),
461 'style' => array(),
462 ),
463 'em' => array(
464 'class' => array(),
465 'style' => array(),
466 ),
467 'font' => array(
468 'class' => array(),
469 'style' => array(),
470 ),
471 'h1' => array(
472 'class' => array(),
473 'style' => array(),
474 ),
475 'h2' => array(
476 'class' => array(),
477 'style' => array(),
478 ),
479 'h3' => array(
480 'class' => array(),
481 'style' => array(),
482 ),
483 'h4' => array(
484 'class' => array(),
485 'style' => array(),
486 ),
487 'h5' => array(
488 'class' => array(),
489 'style' => array(),
490 ),
491 'h6' => array(
492 'class' => array(),
493 'style' => array(),
494 ),
495 'hr' => array(
496 'class' => array(),
497 'style' => array(),
498 ),
499 'i' => array(
500 'class' => array(),
501 'style' => array(),
502 ),
503 'img' => array(
504 'src' => array(),
505 'alt' => array(),
506 'class' => array(),
507 'style' => array(),
508 ),
509 'li' => array(
510 'class' => array(),
511 'style' => array(),
512 ),
513 'ol' => array(
514 'start' => array(),
515 'type' => array(),
516 'class' => array(),
517 'style' => array(),
518 ),
519 'p' => array(
520 'class' => array(),
521 'style' => array(),
522 ),
523 'pre' => array(
524 'code' => array(),
525 'samp' => array(),
526 'class' => array(),
527 'style' => array(),
528 ),
529 'q' => array(
530 'cite' => array(),
531 'class' => array(),
532 'style' => array(),
533 ),
534 's' => array(
535 'class' => array(),
536 'style' => array(),
537 ),
538 'small' => array(
539 'class' => array(),
540 'style' => array(),
541 ),
542 'span' => array(
543 'class' => array(),
544 'style' => array(),
545 ),
546 'strike' => array(
547 'class' => array(),
548 'style' => array(),
549 ),
550 'strong' => array(
551 'class' => array(),
552 'style' => array(),
553 ),
554 'style' => array(
555 'type' => array(),
556 'class' => array(),
557 'style' => array(),
558 ),
559 'sub' => array(
560 'class' => array(),
561 'style' => array(),
562 ),
563 'sup' => array(
564 'class' => array(),
565 'style' => array(),
566 ),
567 'table' => array(
568 'class' => array(),
569 'style' => array(),
570 ),
571 'td' => array(
572 'colspan' => array(),
573 'headers' => array(),
574 'rowspan' => array(),
575 'class' => array(),
576 'style' => array(),
577 ),
578 'th' => array(
579 'colspan' => array(),
580 'headers' => array(),
581 'rowspan' => array(),
582 'scope' => array(),
583 'class' => array(),
584 'style' => array(),
585 ),
586 'tr' => array(
587 'class' => array(),
588 'style' => array(),
589 ),
590 'u' => array(
591 'class' => array(),
592 'style' => array(),
593 ),
594 'ul' => array(
595 'class' => array(),
596 'style' => array(),
597 ),
598 );
599
600 $format = wp_kses( $format, $allowed_tags );
601
602 return $format;
603 }
604
605 /**
606 * Remove emoji
607 *
608 * Function to strip emoji from the plugin description.
609 *
610 * @param string $description The plugin description.
611 * @return string Stripped description.
612 */
613 function remove_emoji_from_plugin_desc( $description ) {
614
615 $symbols = "\x{1F100}-\x{1F1FF}" // Enclosed Alphanumeric Supplement.
616 . "\x{1F300}-\x{1F5FF}" // Miscellaneous Symbols and Pictographs.
617 . "\x{1F600}-\x{1F64F}" // Emoticons.
618 . "\x{1F680}-\x{1F6FF}" // Transport And Map Symbols.
619 . "\x{1F900}-\x{1F9FF}" // Supplemental Symbols and Pictographs.
620 . "\x{2600}-\x{26FF}" // Miscellaneous Symbols.
621 . "\x{2700}-\x{27BF}"; // Dingbats.
622
623 $description = preg_replace( '/[' . $symbols . ']+/u', '', $description );
624
625 return $description;
626 }
627
628 /**
629 * Strip spaces
630 *
631 * Function to strip extra spaces from the plugin description.
632 *
633 * @param string $description The plugin description.
634 * @return string Stripped description.
635 */
636 function strip_spaces_from_plugin_desc( $description ) {
637
638 $continue = true;
639 while ( true === $continue ) {
640 $replace = str_replace( ' ', ' ', $description );
641 if ( $replace == $description ) {
642 $continue = false;
643 }
644 $description = $replace;
645 }
646 return trim( $description );
647 }
648