Changeset 59461
- Timestamp:
- 11/26/2024 10:14:07 AM (3 months ago)
- Location:
- trunk/src
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/includes/plugin.php
r58975 r59461 6 6 * @subpackage Administration 7 7 */ 8 9 /**10 * Parses the plugin contents to retrieve plugin's metadata.11 *12 * All plugin headers must be on their own line. Plugin description must not have13 * any newlines, otherwise only parts of the description will be displayed.14 * The below is formatted for printing.15 *16 * /*17 * Plugin Name: Name of the plugin.18 * Plugin URI: The home page of the plugin.19 * Description: Plugin description.20 * Author: Plugin author's name.21 * Author URI: Link to the author's website.22 * Version: Plugin version.23 * Text Domain: Optional. Unique identifier, should be same as the one used in24 * load_plugin_textdomain().25 * Domain Path: Optional. Only useful if the translations are located in a26 * folder above the plugin's base path. For example, if .mo files are27 * located in the locale folder then Domain Path will be "/locale/" and28 * must have the first slash. Defaults to the base folder the plugin is29 * located in.30 * Network: Optional. Specify "Network: true" to require that a plugin is activated31 * across all sites in an installation. This will prevent a plugin from being32 * activated on a single site when Multisite is enabled.33 * Requires at least: Optional. Specify the minimum required WordPress version.34 * Requires PHP: Optional. Specify the minimum required PHP version.35 * * / # Remove the space to close comment.36 *37 * The first 8 KB of the file will be pulled in and if the plugin data is not38 * within that first 8 KB, then the plugin author should correct their plugin39 * and move the plugin data headers to the top.40 *41 * The plugin file is assumed to have permissions to allow for scripts to read42 * the file. This is not checked however and the file is only opened for43 * reading.44 *45 * @since 1.5.046 * @since 5.3.0 Added support for `Requires at least` and `Requires PHP` headers.47 * @since 5.8.0 Added support for `Update URI` header.48 * @since 6.5.0 Added support for `Requires Plugins` header.49 *50 * @param string $plugin_file Absolute path to the main plugin file.51 * @param bool $markup Optional. If the returned data should have HTML markup applied.52 * Default true.53 * @param bool $translate Optional. If the returned data should be translated. Default true.54 * @return array {55 * Plugin data. Values will be empty if not supplied by the plugin.56 *57 * @type string $Name Name of the plugin. Should be unique.58 * @type string $PluginURI Plugin URI.59 * @type string $Version Plugin version.60 * @type string $Description Plugin description.61 * @type string $Author Plugin author's name.62 * @type string $AuthorURI Plugin author's website address (if set).63 * @type string $TextDomain Plugin textdomain.64 * @type string $DomainPath Plugin's relative directory path to .mo files.65 * @type bool $Network Whether the plugin can only be activated network-wide.66 * @type string $RequiresWP Minimum required version of WordPress.67 * @type string $RequiresPHP Minimum required version of PHP.68 * @type string $UpdateURI ID of the plugin for update purposes, should be a URI.69 * @type string $RequiresPlugins Comma separated list of dot org plugin slugs.70 * @type string $Title Title of the plugin and link to the plugin's site (if set).71 * @type string $AuthorName Plugin author's name.72 * }73 */74 function get_plugin_data( $plugin_file, $markup = true, $translate = true ) {75 76 $default_headers = array(77 'Name' => 'Plugin Name',78 'PluginURI' => 'Plugin URI',79 'Version' => 'Version',80 'Description' => 'Description',81 'Author' => 'Author',82 'AuthorURI' => 'Author URI',83 'TextDomain' => 'Text Domain',84 'DomainPath' => 'Domain Path',85 'Network' => 'Network',86 'RequiresWP' => 'Requires at least',87 'RequiresPHP' => 'Requires PHP',88 'UpdateURI' => 'Update URI',89 'RequiresPlugins' => 'Requires Plugins',90 // Site Wide Only is deprecated in favor of Network.91 '_sitewide' => 'Site Wide Only',92 );93 94 $plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' );95 96 // Site Wide Only is the old header for Network.97 if ( ! $plugin_data['Network'] && $plugin_data['_sitewide'] ) {98 /* translators: 1: Site Wide Only: true, 2: Network: true */99 _deprecated_argument( __FUNCTION__, '3.0.0', sprintf( __( 'The %1$s plugin header is deprecated. Use %2$s instead.' ), '<code>Site Wide Only: true</code>', '<code>Network: true</code>' ) );100 $plugin_data['Network'] = $plugin_data['_sitewide'];101 }102 $plugin_data['Network'] = ( 'true' === strtolower( $plugin_data['Network'] ) );103 unset( $plugin_data['_sitewide'] );104 105 // If no text domain is defined fall back to the plugin slug.106 if ( ! $plugin_data['TextDomain'] ) {107 $plugin_slug = dirname( plugin_basename( $plugin_file ) );108 if ( '.' !== $plugin_slug && ! str_contains( $plugin_slug, '/' ) ) {109 $plugin_data['TextDomain'] = $plugin_slug;110 }111 }112 113 if ( $markup || $translate ) {114 $plugin_data = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup, $translate );115 } else {116 $plugin_data['Title'] = $plugin_data['Name'];117 $plugin_data['AuthorName'] = $plugin_data['Author'];118 }119 120 return $plugin_data;121 }122 123 /**124 * Sanitizes plugin data, optionally adds markup, optionally translates.125 *126 * @since 2.7.0127 *128 * @see get_plugin_data()129 *130 * @access private131 *132 * @param string $plugin_file Path to the main plugin file.133 * @param array $plugin_data An array of plugin data. See get_plugin_data().134 * @param bool $markup Optional. If the returned data should have HTML markup applied.135 * Default true.136 * @param bool $translate Optional. If the returned data should be translated. Default true.137 * @return array Plugin data. Values will be empty if not supplied by the plugin.138 * See get_plugin_data() for the list of possible values.139 */140 function _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup = true, $translate = true ) {141 142 // Sanitize the plugin filename to a WP_PLUGIN_DIR relative path.143 $plugin_file = plugin_basename( $plugin_file );144 145 // Translate fields.146 if ( $translate ) {147 $textdomain = $plugin_data['TextDomain'];148 if ( $textdomain ) {149 if ( ! is_textdomain_loaded( $textdomain ) ) {150 if ( $plugin_data['DomainPath'] ) {151 load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) . $plugin_data['DomainPath'] );152 } else {153 load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) );154 }155 }156 } elseif ( 'hello.php' === basename( $plugin_file ) ) {157 $textdomain = 'default';158 }159 if ( $textdomain ) {160 foreach ( array( 'Name', 'PluginURI', 'Description', 'Author', 'AuthorURI', 'Version' ) as $field ) {161 if ( ! empty( $plugin_data[ $field ] ) ) {162 // phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain163 $plugin_data[ $field ] = translate( $plugin_data[ $field ], $textdomain );164 }165 }166 }167 }168 169 // Sanitize fields.170 $allowed_tags_in_links = array(171 'abbr' => array( 'title' => true ),172 'acronym' => array( 'title' => true ),173 'code' => true,174 'em' => true,175 'strong' => true,176 );177 178 $allowed_tags = $allowed_tags_in_links;179 $allowed_tags['a'] = array(180 'href' => true,181 'title' => true,182 );183 184 /*185 * Name is marked up inside <a> tags. Don't allow these.186 * Author is too, but some plugins have used <a> here (omitting Author URI).187 */188 $plugin_data['Name'] = wp_kses( $plugin_data['Name'], $allowed_tags_in_links );189 $plugin_data['Author'] = wp_kses( $plugin_data['Author'], $allowed_tags );190 191 $plugin_data['Description'] = wp_kses( $plugin_data['Description'], $allowed_tags );192 $plugin_data['Version'] = wp_kses( $plugin_data['Version'], $allowed_tags );193 194 $plugin_data['PluginURI'] = esc_url( $plugin_data['PluginURI'] );195 $plugin_data['AuthorURI'] = esc_url( $plugin_data['AuthorURI'] );196 197 $plugin_data['Title'] = $plugin_data['Name'];198 $plugin_data['AuthorName'] = $plugin_data['Author'];199 200 // Apply markup.201 if ( $markup ) {202 if ( $plugin_data['PluginURI'] && $plugin_data['Name'] ) {203 $plugin_data['Title'] = '<a href="' . $plugin_data['PluginURI'] . '">' . $plugin_data['Name'] . '</a>';204 }205 206 if ( $plugin_data['AuthorURI'] && $plugin_data['Author'] ) {207 $plugin_data['Author'] = '<a href="' . $plugin_data['AuthorURI'] . '">' . $plugin_data['Author'] . '</a>';208 }209 210 $plugin_data['Description'] = wptexturize( $plugin_data['Description'] );211 212 if ( $plugin_data['Author'] ) {213 $plugin_data['Description'] .= sprintf(214 /* translators: %s: Plugin author. */215 ' <cite>' . __( 'By %s.' ) . '</cite>',216 $plugin_data['Author']217 );218 }219 }220 221 return $plugin_data;222 }223 8 224 9 /** -
trunk/src/wp-includes/functions.php
r59389 r59461 6931 6931 6932 6932 /** 6933 * Parses the plugin contents to retrieve plugin's metadata. 6934 * 6935 * All plugin headers must be on their own line. Plugin description must not have 6936 * any newlines, otherwise only parts of the description will be displayed. 6937 * The below is formatted for printing. 6938 * 6939 * /* 6940 * Plugin Name: Name of the plugin. 6941 * Plugin URI: The home page of the plugin. 6942 * Description: Plugin description. 6943 * Author: Plugin author's name. 6944 * Author URI: Link to the author's website. 6945 * Version: Plugin version. 6946 * Text Domain: Optional. Unique identifier, should be same as the one used in 6947 * load_plugin_textdomain(). 6948 * Domain Path: Optional. Only useful if the translations are located in a 6949 * folder above the plugin's base path. For example, if .mo files are 6950 * located in the locale folder then Domain Path will be "/locale/" and 6951 * must have the first slash. Defaults to the base folder the plugin is 6952 * located in. 6953 * Network: Optional. Specify "Network: true" to require that a plugin is activated 6954 * across all sites in an installation. This will prevent a plugin from being 6955 * activated on a single site when Multisite is enabled. 6956 * Requires at least: Optional. Specify the minimum required WordPress version. 6957 * Requires PHP: Optional. Specify the minimum required PHP version. 6958 * * / # Remove the space to close comment. 6959 * 6960 * The first 8 KB of the file will be pulled in and if the plugin data is not 6961 * within that first 8 KB, then the plugin author should correct their plugin 6962 * and move the plugin data headers to the top. 6963 * 6964 * The plugin file is assumed to have permissions to allow for scripts to read 6965 * the file. This is not checked however and the file is only opened for 6966 * reading. 6967 * 6968 * @since 1.5.0 6969 * @since 5.3.0 Added support for `Requires at least` and `Requires PHP` headers. 6970 * @since 5.8.0 Added support for `Update URI` header. 6971 * @since 6.5.0 Added support for `Requires Plugins` header. 6972 * 6973 * @param string $plugin_file Absolute path to the main plugin file. 6974 * @param bool $markup Optional. If the returned data should have HTML markup applied. 6975 * Default true. 6976 * @param bool $translate Optional. If the returned data should be translated. Default true. 6977 * @return array { 6978 * Plugin data. Values will be empty if not supplied by the plugin. 6979 * 6980 * @type string $Name Name of the plugin. Should be unique. 6981 * @type string $PluginURI Plugin URI. 6982 * @type string $Version Plugin version. 6983 * @type string $Description Plugin description. 6984 * @type string $Author Plugin author's name. 6985 * @type string $AuthorURI Plugin author's website address (if set). 6986 * @type string $TextDomain Plugin textdomain. 6987 * @type string $DomainPath Plugin's relative directory path to .mo files. 6988 * @type bool $Network Whether the plugin can only be activated network-wide. 6989 * @type string $RequiresWP Minimum required version of WordPress. 6990 * @type string $RequiresPHP Minimum required version of PHP. 6991 * @type string $UpdateURI ID of the plugin for update purposes, should be a URI. 6992 * @type string $RequiresPlugins Comma separated list of dot org plugin slugs. 6993 * @type string $Title Title of the plugin and link to the plugin's site (if set). 6994 * @type string $AuthorName Plugin author's name. 6995 * } 6996 */ 6997 function get_plugin_data( $plugin_file, $markup = true, $translate = true ) { 6998 6999 $default_headers = array( 7000 'Name' => 'Plugin Name', 7001 'PluginURI' => 'Plugin URI', 7002 'Version' => 'Version', 7003 'Description' => 'Description', 7004 'Author' => 'Author', 7005 'AuthorURI' => 'Author URI', 7006 'TextDomain' => 'Text Domain', 7007 'DomainPath' => 'Domain Path', 7008 'Network' => 'Network', 7009 'RequiresWP' => 'Requires at least', 7010 'RequiresPHP' => 'Requires PHP', 7011 'UpdateURI' => 'Update URI', 7012 'RequiresPlugins' => 'Requires Plugins', 7013 // Site Wide Only is deprecated in favor of Network. 7014 '_sitewide' => 'Site Wide Only', 7015 ); 7016 7017 $plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' ); 7018 7019 // Site Wide Only is the old header for Network. 7020 if ( ! $plugin_data['Network'] && $plugin_data['_sitewide'] ) { 7021 /* translators: 1: Site Wide Only: true, 2: Network: true */ 7022 _deprecated_argument( __FUNCTION__, '3.0.0', sprintf( __( 'The %1$s plugin header is deprecated. Use %2$s instead.' ), '<code>Site Wide Only: true</code>', '<code>Network: true</code>' ) ); 7023 $plugin_data['Network'] = $plugin_data['_sitewide']; 7024 } 7025 $plugin_data['Network'] = ( 'true' === strtolower( $plugin_data['Network'] ) ); 7026 unset( $plugin_data['_sitewide'] ); 7027 7028 // If no text domain is defined fall back to the plugin slug. 7029 if ( ! $plugin_data['TextDomain'] ) { 7030 $plugin_slug = dirname( plugin_basename( $plugin_file ) ); 7031 if ( '.' !== $plugin_slug && ! str_contains( $plugin_slug, '/' ) ) { 7032 $plugin_data['TextDomain'] = $plugin_slug; 7033 } 7034 } 7035 7036 if ( $markup || $translate ) { 7037 $plugin_data = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup, $translate ); 7038 } else { 7039 $plugin_data['Title'] = $plugin_data['Name']; 7040 $plugin_data['AuthorName'] = $plugin_data['Author']; 7041 } 7042 7043 return $plugin_data; 7044 } 7045 7046 /** 7047 * Sanitizes plugin data, optionally adds markup, optionally translates. 7048 * 7049 * @since 2.7.0 7050 * 7051 * @see get_plugin_data() 7052 * 7053 * @access private 7054 * 7055 * @param string $plugin_file Path to the main plugin file. 7056 * @param array $plugin_data An array of plugin data. See get_plugin_data(). 7057 * @param bool $markup Optional. If the returned data should have HTML markup applied. 7058 * Default true. 7059 * @param bool $translate Optional. If the returned data should be translated. Default true. 7060 * @return array Plugin data. Values will be empty if not supplied by the plugin. 7061 * See get_plugin_data() for the list of possible values. 7062 */ 7063 function _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup = true, $translate = true ) { 7064 7065 // Sanitize the plugin filename to a WP_PLUGIN_DIR relative path. 7066 $plugin_file = plugin_basename( $plugin_file ); 7067 7068 // Translate fields. 7069 if ( $translate ) { 7070 $textdomain = $plugin_data['TextDomain']; 7071 if ( $textdomain ) { 7072 if ( ! is_textdomain_loaded( $textdomain ) ) { 7073 if ( $plugin_data['DomainPath'] ) { 7074 load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) . $plugin_data['DomainPath'] ); 7075 } else { 7076 load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) ); 7077 } 7078 } 7079 } elseif ( 'hello.php' === basename( $plugin_file ) ) { 7080 $textdomain = 'default'; 7081 } 7082 if ( $textdomain ) { 7083 foreach ( array( 'Name', 'PluginURI', 'Description', 'Author', 'AuthorURI', 'Version' ) as $field ) { 7084 if ( ! empty( $plugin_data[ $field ] ) ) { 7085 // phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain 7086 $plugin_data[ $field ] = translate( $plugin_data[ $field ], $textdomain ); 7087 } 7088 } 7089 } 7090 } 7091 7092 // Sanitize fields. 7093 $allowed_tags_in_links = array( 7094 'abbr' => array( 'title' => true ), 7095 'acronym' => array( 'title' => true ), 7096 'code' => true, 7097 'em' => true, 7098 'strong' => true, 7099 ); 7100 7101 $allowed_tags = $allowed_tags_in_links; 7102 $allowed_tags['a'] = array( 7103 'href' => true, 7104 'title' => true, 7105 ); 7106 7107 /* 7108 * Name is marked up inside <a> tags. Don't allow these. 7109 * Author is too, but some plugins have used <a> here (omitting Author URI). 7110 */ 7111 $plugin_data['Name'] = wp_kses( $plugin_data['Name'], $allowed_tags_in_links ); 7112 $plugin_data['Author'] = wp_kses( $plugin_data['Author'], $allowed_tags ); 7113 7114 $plugin_data['Description'] = wp_kses( $plugin_data['Description'], $allowed_tags ); 7115 $plugin_data['Version'] = wp_kses( $plugin_data['Version'], $allowed_tags ); 7116 7117 $plugin_data['PluginURI'] = esc_url( $plugin_data['PluginURI'] ); 7118 $plugin_data['AuthorURI'] = esc_url( $plugin_data['AuthorURI'] ); 7119 7120 $plugin_data['Title'] = $plugin_data['Name']; 7121 $plugin_data['AuthorName'] = $plugin_data['Author']; 7122 7123 // Apply markup. 7124 if ( $markup ) { 7125 if ( $plugin_data['PluginURI'] && $plugin_data['Name'] ) { 7126 $plugin_data['Title'] = '<a href="' . $plugin_data['PluginURI'] . '">' . $plugin_data['Name'] . '</a>'; 7127 } 7128 7129 if ( $plugin_data['AuthorURI'] && $plugin_data['Author'] ) { 7130 $plugin_data['Author'] = '<a href="' . $plugin_data['AuthorURI'] . '">' . $plugin_data['Author'] . '</a>'; 7131 } 7132 7133 $plugin_data['Description'] = wptexturize( $plugin_data['Description'] ); 7134 7135 if ( $plugin_data['Author'] ) { 7136 $plugin_data['Description'] .= sprintf( 7137 /* translators: %s: Plugin author. */ 7138 ' <cite>' . __( 'By %s.' ) . '</cite>', 7139 $plugin_data['Author'] 7140 ); 7141 } 7142 } 7143 7144 return $plugin_data; 7145 } 7146 7147 /** 6933 7148 * Returns true. 6934 7149 * -
trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php
r59073 r59461 873 873 return empty( $theme_name ) ? $template_object->theme : $theme_name; 874 874 case 'plugin': 875 if ( ! function_exists( 'get_plugins' ) || ! function_exists( 'get_plugin_data' )) {875 if ( ! function_exists( 'get_plugins' ) ) { 876 876 require_once ABSPATH . 'wp-admin/includes/plugin.php'; 877 877 } -
trunk/src/wp-settings.php
r59132 r59461 535 535 */ 536 536 do_action( 'plugin_loaded', $plugin ); 537 } 538 unset( $plugin, $_wp_plugin_file ); 537 538 $plugin_data = get_plugin_data( $plugin, false, false ); 539 540 $textdomain = $plugin_data['TextDomain']; 541 if ( $textdomain ) { 542 if ( $plugin_data['DomainPath'] ) { 543 $GLOBALS['wp_textdomain_registry']->set_custom_path( $textdomain, dirname( $plugin ) . $plugin_data['DomainPath'] ); 544 } else { 545 $GLOBALS['wp_textdomain_registry']->set_custom_path( $textdomain, dirname( $plugin ) ); 546 } 547 } 548 } 549 unset( $plugin, $_wp_plugin_file, $plugin_data, $textdomain ); 539 550 540 551 // Load pluggable functions. … … 672 683 include $theme . '/functions.php'; 673 684 } 685 686 $theme = wp_get_theme( basename( $theme ) ); 687 $theme->load_textdomain(); 674 688 } 675 689 unset( $theme );
Note: See TracChangeset
for help on using the changeset viewer.