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