[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
1 <?php 2 3 function bb_get_plugins_callback( $type = 'normal', $path, $filename ) 4 { 5 if ( '.php' != substr( $filename, -4 ) ) { 6 return false; 7 } 8 9 $data = array( 'autoload' => 0 ); 10 11 if ( $has_underscore = '_' === substr( $filename, 0, 1 ) ) { 12 switch ( $type ) { 13 case 'all': 14 case 'autoload': 15 $data['autoload'] = 1; 16 break; 17 case 'normal': 18 default: 19 return false; 20 break; 21 } 22 } elseif ( 'autoload' === $type ) { 23 return false; 24 } 25 26 if ( $_data = bb_get_plugin_data( $path ) ) { 27 return array_merge( $_data , $data ); 28 } 29 30 return false; 31 } 32 33 function bb_get_plugins( $location = 'all', $type = 'normal', $status = 'all' ) 34 { 35 static $plugin_cache = array(); 36 37 if ( !in_array( $type, array( 'all', 'autoload', 'normal' ) ) ) { 38 $type = 'normal'; 39 } 40 41 if ( 'autoload' === $type || !in_array( $status, array( 'all', 'active', 'inactive' ) ) ) { 42 $status = 'all'; 43 } 44 45 if ( isset( $plugin_cache[$location][$type][$status] ) ) { 46 return $plugin_cache[$location][$type][$status]; 47 } 48 49 global $bb; 50 $directories = array(); 51 if ( 'all' === $location ) { 52 foreach ( $bb->plugin_locations as $_data ) { 53 $directories[] = $_data['dir']; 54 } 55 } elseif ( isset( $bb->plugin_locations[$location]['dir'] ) ) { 56 $directories[] = $bb->plugin_locations[$location]['dir']; 57 } 58 59 require_once( BB_PATH . BB_INC . 'class.bb-dir-map.php' ); 60 61 $plugin_arrays = array(); 62 foreach ( $directories as $directory ) { 63 $dir_map = new BB_Dir_Map( 64 $directory, 65 array( 66 'callback' => 'bb_get_plugins_callback', 67 'callback_args' => array( $type ), 68 'recurse' => 1 69 ) 70 ); 71 $dir_plugins = $dir_map->get_results(); 72 $dir_plugins = is_wp_error( $dir_plugins ) ? array() : $dir_plugins; 73 $plugin_arrays[] = $dir_plugins; 74 unset($dir_map, $dir_plugins); 75 } 76 77 $plugins = array(); 78 foreach ($plugin_arrays as $plugin_array) { 79 $plugins = array_merge($plugins, $plugin_array); 80 } 81 82 $active_plugins = (array) bb_get_option( 'active_plugins' ); 83 84 $adjusted_plugins = array(); 85 foreach ($plugins as $plugin => $plugin_data) { 86 $_id = $plugin_data['location'] . '#' . $plugin; 87 $plugin_data['active'] = 0; 88 if ( 'autoload' === $type || in_array( $_id, $active_plugins ) ) { 89 $plugin_data['active'] = 1; 90 } 91 if ( 92 'active' === $status && $plugin_data['active'] || 93 'inactive' === $status && !$plugin_data['active'] || 94 'all' === $status 95 ) { 96 $adjusted_plugins[$_id] = $plugin_data; 97 } 98 } 99 100 uasort( $adjusted_plugins, 'bb_plugins_sort' ); 101 102 $plugin_cache[$location][$type][$status] = $adjusted_plugins; 103 104 return $adjusted_plugins; 105 } 106 107 function bb_plugins_sort( $a, $b ) 108 { 109 return strnatcasecmp( $a['name'], $b['name'] ); 110 } 111 112 function bb_get_plugin_counts() 113 { 114 $all_plugins = bb_get_plugins( 'all', 'all' ); 115 $active_plugins = (array) bb_get_option( 'active_plugins' ); 116 $counts = array( 117 'plugin_count_all' => count( $all_plugins ), 118 'plugin_count_active' => count( $active_plugins ), 119 'plugin_count_inactive' => 0, 120 'plugin_count_autoload' => 0 121 ); 122 foreach ( $all_plugins as $id => $all_plugin ) { 123 if ( $all_plugin['autoload'] ) { 124 $counts['plugin_count_autoload']++; 125 } elseif ( !in_array( $id, $active_plugins ) ) { 126 $counts['plugin_count_inactive']++; 127 } 128 } 129 return $counts; 130 } 131 132 /** 133 * Parse the plugin contents to retrieve plugin's metadata. 134 * 135 * The metadata of the plugin's data searches for the following in the plugin's 136 * header. All plugin data must be on its own line. For plugin description, it 137 * must not have any newlines or only parts of the description will be displayed 138 * and the same goes for the plugin data. The below is formatted for printing. 139 * 140 * <code> 141 * /* 142 * Plugin Name: Name of Plugin 143 * Plugin URI: Link to plugin information 144 * Description: Plugin Description 145 * Author: Plugin author's name 146 * Author URI: Link to the author's web site 147 * Version: Must be set 148 * Requires at least: Optional. Minimum bbPress version this plugin requires 149 * Tested up to: Optional. Maximum bbPress version this plugin has been tested with 150 * Text Domain: Optional. Unique identifier, should be same as the one used in 151 * bb_load_plugin_textdomain() 152 * Domain Path: Optional. Only useful if the translations are located in a 153 * folder above the plugin's base path. For example, if .mo files are 154 * located in the locale folder then Domain Path will be "/locale/" and 155 * must have the first slash. Defaults to the base folder the plugin is 156 * located in. 157 * * / # You must remove the space to close comment (the space is here only for documentation purposes). 158 * </code> 159 * 160 * Plugin data returned array contains the following: 161 * 'location' - Location of plugin file 162 * 'name' - Name of the plugin, must be unique. 163 * 'uri' - Plugin's web site. 164 * 'plugin_link' - Title of plugin linked to plugin's web site. 165 * 'description' - Description of what the plugin does and/or notes 166 * from the author. 167 * 'author' - The author's name 168 * 'author_uri' - The author's web site address. 169 * 'author_link' - The author's name linked to the author's web site. 170 * 'version' - The plugin version number. 171 * 'requires' - Minimum bbPress version plugin requires 172 * 'tested' - Maximum bbPress version plugin has been tested with 173 * 'text_domain' - Plugin's text domain for localization. 174 * 'domain_path' - Plugin's relative directory path to .mo files. 175 * 176 * Some users have issues with opening large files and manipulating the contents 177 * for want is usually the first 1kiB or 2kiB. This function stops pulling in 178 * the plugin contents when it has all of the required plugin data. 179 * 180 * The first 8kiB of the file will be pulled in and if the plugin data is not 181 * within that first 8kiB, then the plugin author should correct their plugin 182 * and move the plugin data headers to the top. 183 * 184 * The plugin file is assumed to have permissions to allow for scripts to read 185 * the file. This is not checked however and the file is only opened for 186 * reading. 187 * 188 * @link http://trac.wordpress.org/ticket/5651 Previous Optimizations. 189 * @link http://trac.wordpress.org/ticket/7372 Further and better Optimizations. 190 * @since 1.5.0 191 * 192 * @param string $plugin_file Path to the plugin file 193 * @param bool $markup If the returned data should have HTML markup applied 194 * @param bool $translate If the returned data should be translated 195 * @return array See above for description. 196 */ 197 function bb_get_plugin_data( $plugin_file, $markup = true, $translate = true ) { 198 global $bb; 199 200 if ( preg_match( '/^([a-z0-9_-]+)#((?:[a-z0-9\/\\_-]+.)+)(php)$/i', $plugin_file, $_matches ) ) { 201 $plugin_file = $bb->plugin_locations[$_matches[1]]['dir'] . $_matches[2] . $_matches[3]; 202 203 $_directory = $bb->plugin_locations[$_matches[1]]['dir']; 204 $_plugin = $_matches[2] . $_matches[3]; 205 206 if ( !$_plugin ) { 207 // Not likely 208 return false; 209 } 210 211 if ( validate_file( $_plugin ) ) { 212 // $plugin has .., :, etc. 213 return false; 214 } 215 216 $plugin_file = $_directory . $_plugin; 217 unset( $_matches, $_directory, $_plugin ); 218 } 219 220 if ( !file_exists( $plugin_file ) ) { 221 // The plugin isn't there 222 return false; 223 } 224 225 // We don't need to write to the file, so just open for reading. 226 $fp = fopen($plugin_file, 'r'); 227 228 // Pull only the first 8kiB of the file in. 229 $plugin_code = fread( $fp, 8192 ); 230 231 // PHP will close file handle, but we are good citizens. 232 fclose($fp); 233 234 // Grab just the first commented area from the file 235 if ( !preg_match( '|/\*(.*?Plugin Name:.*?)\*/|ims', $plugin_code, $plugin_block ) ) 236 return false; 237 $plugin_data = trim( $plugin_block[1] ); 238 239 preg_match( '|Plugin Name:(.*)$|mi', $plugin_data, $name ); 240 preg_match( '|Plugin URI:(.*)$|mi', $plugin_data, $uri ); 241 preg_match( '|Version:(.*)|i', $plugin_data, $version ); 242 preg_match( '|Description:(.*)$|mi', $plugin_data, $description ); 243 preg_match( '|Author:(.*)$|mi', $plugin_data, $author ); 244 preg_match( '|Author URI:(.*)$|mi', $plugin_data, $author_uri ); 245 preg_match( '|Text Domain:(.*)$|mi', $plugin_data, $text_domain ); 246 preg_match( '|Domain Path:(.*)$|mi', $plugin_data, $domain_path ); 247 preg_match( '|Requires at least:(.*)$|mi', $plugin_data, $requires ); 248 preg_match( '|Tested up to:(.*)$|mi', $plugin_data, $tested ); 249 250 // Normalise the path to the plugin 251 $plugin_file = str_replace( '\\', '/', $plugin_file ); 252 253 foreach ( $bb->plugin_locations as $_name => $_data ) { 254 $_directory = str_replace( '\\', '/', $_data['dir'] ); 255 if ( 0 === strpos( $plugin_file, $_directory ) ) { 256 $location = array( 1 => $_name ); 257 break; 258 } 259 } 260 261 $plugins_allowedtags = array('a' => array('href' => array(),'title' => array()),'abbr' => array('title' => array()),'acronym' => array('title' => array()),'code' => array(),'em' => array(),'strong' => array()); 262 263 $fields = array( 264 'location' => '', 265 'name' => 'html', 266 'uri' => 'url', 267 'version' => 'text', 268 'description' => 'html', 269 'author' => 'html', 270 'author_uri' => 'url', 271 'text_domain' => '', 272 'domain_path' => '', 273 'requires' => 'text', 274 'tested' => 'text', 275 ); 276 foreach ( $fields as $field => $san ) { 277 if ( !empty( ${$field} ) ) { 278 ${$field} = trim(${$field}[1]); 279 switch ( $san ) { 280 case 'html' : 281 ${$field} = bb_filter_kses( ${$field} ); 282 break; 283 case 'text' : 284 ${$field} = esc_html( ${$field} ); 285 break; 286 case 'url' : 287 ${$field} = esc_url( ${$field} ); 288 break; 289 } 290 } else { 291 ${$field} = ''; 292 } 293 } 294 295 $plugin_data = compact( array_keys( $fields ) ); 296 297 if ( $translate ) 298 $plugin_data = _bb_get_plugin_data_translate( $plugin_data, $plugin_file ); 299 300 if ( $markup ) 301 $plugin_data['description'] = bb_autop( preg_replace( '/[\r\n]+/', "\n", trim( $plugin_data['description'] ) ) ); 302 303 $plugin_data['plugin_link'] = ( $plugin_data['uri'] ) ? 304 "<a href='{$plugin_data['uri']}' title='" . esc_attr__( 'Visit plugin site' ) . "'>{$plugin_data['name']}</a>" : 305 $plugin_data['name']; 306 $plugin_data['author_link'] = ( $plugin_data['author'] && $plugin_data['author_uri'] ) ? 307 "<a href='{$plugin_data['author_uri']}' title='" . esc_attr__( 'Visit author homepage' ) . "'>{$plugin_data['author']}</a>" : 308 $plugin_data['author']; 309 310 return $plugin_data; 311 } 312 313 function _bb_get_plugin_data_translate( $plugin_data, $plugin_file ) { 314 //Translate fields 315 if( !empty($plugin_data['text_domain']) ) { 316 if( ! empty( $plugin_data['domain_path'] ) ) 317 bb_load_plugin_textdomain($plugin_data['text_domain'], dirname($plugin_file). $plugin_data['domain_path']); 318 else 319 bb_load_plugin_textdomain($plugin_data['text_domain'], dirname($plugin_file)); 320 321 foreach ( array('name', 'plugin_url', 'description', 'author', 'author_uri', 'version') as $field ) 322 $plugin_data[$field] = translate($plugin_data[$field], $plugin_data['text_domain']); 323 } 324 325 return $plugin_data; 326 } 327 328 /** 329 * Attempts activation of plugin in a "sandbox" and redirects on success. 330 * 331 * A plugin that is already activated will not attempt to be activated again. 332 * 333 * The way it works is by setting the redirection to the error before trying to 334 * include the plugin file. If the plugin fails, then the redirection will not 335 * be overwritten with the success message. Also, the options will not be 336 * updated and the activation hook will not be called on plugin error. 337 * 338 * It should be noted that in no way the below code will actually prevent errors 339 * within the file. The code should not be used elsewhere to replicate the 340 * "sandbox", which uses redirection to work. 341 * 342 * If any errors are found or text is outputted, then it will be captured to 343 * ensure that the success redirection will update the error redirection. 344 * 345 * @since 1.0 346 * 347 * @param string $plugin Plugin path to main plugin file with plugin data. 348 * @param string $redirect Optional. URL to redirect to. 349 * @return WP_Error|null WP_Error on invalid file or null on success. 350 */ 351 function bb_activate_plugin( $plugin, $redirect = '' ) { 352 $active_plugins = (array) bb_get_option( 'active_plugins' ); 353 $plugin = bb_plugin_basename( trim( $plugin ) ); 354 355 $valid_path = bb_validate_plugin( $plugin ); 356 if ( is_wp_error( $valid_path ) ) 357 return $valid_path; 358 359 if ( in_array( $plugin, $active_plugins ) ) { 360 return false; 361 } 362 363 if ( !empty( $redirect ) ) { 364 // We'll override this later if the plugin can be included without fatal error 365 wp_redirect( add_query_arg( '_scrape_nonce', bb_create_nonce( 'scrape-plugin_' . $plugin ), $redirect ) ); 366 } 367 368 ob_start(); 369 @include( $valid_path ); 370 // Add to the active plugins array 371 $active_plugins[] = $plugin; 372 ksort( $active_plugins ); 373 bb_update_option( 'active_plugins', $active_plugins ); 374 do_action( 'bb_activate_plugin_' . $plugin ); 375 ob_end_clean(); 376 377 return $valid_path; 378 } 379 380 /** 381 * Deactivate a single plugin or multiple plugins. 382 * 383 * The deactivation hook is disabled by the plugin upgrader by using the $silent 384 * parameter. 385 * 386 * @since unknown 387 * 388 * @param string|array $plugins Single plugin or list of plugins to deactivate. 389 * @param bool $silent Optional, default is false. Prevent calling deactivate hook. 390 */ 391 function bb_deactivate_plugins( $plugins, $silent = false ) { 392 $active_plugins = (array) bb_get_option( 'active_plugins' ); 393 394 if ( !is_array( $plugins ) ) { 395 $plugins = array( $plugins ); 396 } 397 398 foreach ( $plugins as $plugin ) { 399 $plugin = bb_plugin_basename( trim( $plugin ) ); 400 if ( !in_array( $plugin, $active_plugins ) ) { 401 continue; 402 } 403 // Remove the deactivated plugin 404 array_splice( $active_plugins, array_search( $plugin, $active_plugins ), 1 ); 405 if ( !$silent ) { 406 do_action( 'bb_deactivate_plugin_' . $plugin ); 407 } 408 } 409 410 bb_update_option( 'active_plugins', $active_plugins ); 411 } 412 413 /** 414 * Validate the plugin path. 415 * 416 * Checks that the file exists and is valid file. 417 * 418 * @since 1.0 419 * @uses validate_file() to check the passed plugin identifier isn't malformed 420 * @uses bb_get_plugin_path() to get the full path of the plugin 421 * @uses bb_get_plugins() to get the plugins that actually exist 422 * 423 * @param string $plugin Plugin Path 424 * @param string $location The location of plugin, one of 'user', 'core' or 'all' 425 * @param string $type The type of plugin, one of 'all', 'autoload' or 'normal' 426 * @return WP_Error|int 0 on success, WP_Error on failure. 427 */ 428 function bb_validate_plugin( $plugin, $location = 'all', $type = 'all' ) { 429 if ( validate_file( trim( $plugin ) ) ) { 430 return new WP_Error( 'plugin_invalid', __( 'Invalid plugin path.' ) ); 431 } 432 $path = bb_get_plugin_path( trim( $plugin ) ); 433 if ( !file_exists( $path ) ) { 434 return new WP_Error( 'plugin_not_found', __( 'Plugin file does not exist.' ) ); 435 } 436 if ( !in_array( trim( $plugin ), array_keys( bb_get_plugins( $location, $type ) ) ) ) { 437 return new WP_Error( 'plugin_not_available', __( 'That type of plugin is not available in the specified location.' ) ); 438 } 439 440 return $path; 441 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Dec 7 01:01:35 2017 | Cross-referenced by PHPXref 0.7.1 |