/** * Loads a plugin out of our shared plugins directory. * * Note - This function does not trigger plugin activation / deactivation hooks. * As such, it may not be compatible with all plugins * * @link http://lobby.vip.wordpress.com/plugins/ VIP Shared Plugins * @param string $plugin Optional. Plugin folder name of the plugin, or the folder and * plugin file name (such as wp-api/plugin.php), relative to either the VIP shared-plugins folder, or WP_PLUGIN_DIR * @param string $folder Deprecated. No longer used * @param bool $load_release_candidate Whether to load a release candidate version of this plugin, if available * @return bool True if the include was successful */ function wpcom_vip_load_plugin($plugin = false, $folder_not_used = null, $load_release_candidate = false) { // Make sure there's a plugin to load if (empty($plugin)) { if (!WPCOM_IS_VIP_ENV) { die('wpcom_vip_load_plugin() was called without a first parameter!'); } } // Is it a plugin file with multiple directories? Not supported. _could_ be supported // with some refactoring, but no real need to, just complicates things $exploded = explode(DIRECTORY_SEPARATOR, $plugin); if (count($exploded) > 2) { if (!WPCOM_IS_VIP_ENV) { die('wpcom_vip_load_plugin() was called with multiple subdirectories'); } else { _doing_it_wrong('wpcom_vip_load_plugin', 'Subdirectories not supported in file paths', ''); return false; } } // Is this a valid path? We know it has less than 3 parts, but it could still be // 'plugin/plugin' (need a php file, if specifying a path rather than a slug) if (count($exploded) === 2) { $pathinfo = pathinfo($plugin); if (!isset($pathinfo['extension']) || 'php' !== $pathinfo['extension']) { if (!WPCOM_IS_VIP_ENV) { die('wpcom_vip_load_plugin() was called with a path, but no php file was specified'); } else { _doing_it_wrong('wpcom_vip_load_plugin', 'Must specify php file when loading via path', ''); return false; } } } // Array of files to check for loading the plugin. This is to support // non-standard plugin structures, such as $folder/plugin.php $test_files = array("{$plugin}.php", 'plugin.php'); // Is $plugin a filepath? If so, that's the only file we should test if (basename($plugin) !== $plugin) { $test_files = array(basename($plugin)); // Update the $plugin to the slug, so we store it correctly and build paths correctly $plugin = dirname($plugin); } // Make sure $plugin and $folder are valid $plugin = _wpcom_vip_load_plugin_sanitizer($plugin); // Array of directories to check for the above files in, in priority order $test_directories = array(); if (true === $load_release_candidate) { $test_directories[] = WP_CONTENT_DIR . '/mu-plugins/shared-plugins/release-candidates'; } $test_directories[] = WP_PLUGIN_DIR; $test_directories[] = WP_CONTENT_DIR . '/mu-plugins/shared-plugins'; $includepath = null; $plugin_type = null; foreach ($test_directories as $directory) { foreach ($test_files as $file) { // Prevent any traversal here $plugin = basename($plugin); // Just to be double, extra sure $file = basename($file); $path = "{$directory}/{$plugin}/{$file}"; if (file_exists($path)) { $includepath = $path; // Store where we found it, so we can properly represent that in UI // This is usually the directory above $plugin_type = basename($directory); // release-candidates is a special case, as it's in a nested folder, // so we must look up one level if ('release-candidates' === $plugin_type) { $plugin_type = dirname($directory); } // We found what we were looking for, break from both loops break 2; } } } if ($includepath && file_exists($includepath)) { wpcom_vip_add_loaded_plugin("{$plugin_type}/{$plugin}"); return _wpcom_vip_include_plugin($includepath); } else { if (!WPCOM_IS_VIP_ENV) { die("Unable to load {$plugin} using wpcom_vip_load_plugin()!"); } } }
/** * Loads a plugin out of our shared plugins directory. * * @link http://lobby.vip.wordpress.com/plugins/ VIP Shared Plugins * @param string $plugin Optional. Plugin folder name (and filename) of the plugin * @param string $folder Optional. Folder to include from; defaults to "plugins". Useful for when you have multiple themes and your own shared plugins folder. * @return bool True if the include was successful */ function wpcom_vip_load_plugin($plugin = false, $folder = 'plugins', $load_release_candidate = false) { // Force release candidate loading if the site has the correct sticker if (defined('WPCOM_IS_VIP_ENV') && true === WPCOM_IS_VIP_ENV && has_blog_sticker('vip-plugins-ui-rc-plugins')) { $load_release_candidate = true; } // Make sure there's a plugin to load if (empty($plugin)) { // On WordPress.com, use an internal function to message VIP about a bad call to this function if (function_exists('wpcom_is_vip')) { if (function_exists('send_vip_team_debug_message')) { // Use an expiring cache value to avoid spamming messages if (!wp_cache_get('noplugin', 'wpcom_vip_load_plugin')) { send_vip_team_debug_message('WARNING: wpcom_vip_load_plugin() is being called without a $plugin parameter', 1); wp_cache_set('noplugin', 1, 'wpcom_vip_load_plugin', 3600); } } return false; } else { die('wpcom_vip_load_plugin() was called without a first parameter!'); } } // Make sure $plugin and $folder are valid $plugin = _wpcom_vip_load_plugin_sanitizer($plugin); if ('plugins' !== $folder) { $folder = _wpcom_vip_load_plugin_sanitizer($folder); } // Shared plugins are located at /wp-content/themes/vip/plugins/example-plugin/ // You should keep your local copies of the plugins in the same location $includepath = WP_CONTENT_DIR . "/themes/vip/{$folder}/{$plugin}/{$plugin}.php"; $release_candidate_includepath = WP_CONTENT_DIR . "/themes/vip/{$folder}/release-candidates/{$plugin}/{$plugin}.php"; if (true === $load_release_candidate && file_exists($release_candidate_includepath)) { $includepath = $release_candidate_includepath; } if (file_exists($includepath)) { wpcom_vip_add_loaded_plugin("{$folder}/{$plugin}"); // Since we're going to be include()'ing inside of a function, // we need to do some hackery to get the variable scope we want. // See http://www.php.net/manual/en/language.variables.scope.php#91982 // Start by marking down the currently defined variables (so we can exclude them later) $pre_include_variables = get_defined_vars(); // Now include include_once $includepath; // If there's a wpcom-helper file for the plugin, load that too $helper_path = WP_CONTENT_DIR . "/themes/vip/{$folder}/{$plugin}/wpcom-helper.php"; if (file_exists($helper_path)) { require_once $helper_path; } // Blacklist out some variables $blacklist = array('blacklist' => 0, 'pre_include_variables' => 0, 'new_variables' => 0); // Let's find out what's new by comparing the current variables to the previous ones $new_variables = array_diff_key(get_defined_vars(), $GLOBALS, $blacklist, $pre_include_variables); // global each new variable foreach ($new_variables as $new_variable => $devnull) { global ${$new_variable}; } // Set the values again on those new globals extract($new_variables); return true; } else { // On WordPress.com, use an internal function to message VIP about the bad call to this function if (function_exists('wpcom_is_vip')) { if (function_exists('send_vip_team_debug_message')) { // Use an expiring cache value to avoid spamming messages $cachekey = md5($folder . '|' . $plugin); if (!wp_cache_get("notfound_{$cachekey}", 'wpcom_vip_load_plugin')) { send_vip_team_debug_message("WARNING: wpcom_vip_load_plugin() is trying to load a non-existent file ( /{$folder}/{$plugin}/{$plugin}.php )", 1); wp_cache_set("notfound_{$cachekey}", 1, 'wpcom_vip_load_plugin', 3600); } } return false; // die() in non-WordPress.com environments so you know you made a mistake } else { die("Unable to load {$plugin} ({$folder}) using wpcom_vip_load_plugin()!"); } } }