|
6 | 6 | * @subpackage Administration |
7 | 7 | */ |
8 | 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 have |
13 | | - * 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 in |
24 | | - * load_plugin_textdomain(). |
25 | | - * Domain Path: Optional. Only useful if the translations are located in a |
26 | | - * folder above the plugin's base path. For example, if .mo files are |
27 | | - * located in the locale folder then Domain Path will be "/locale/" and |
28 | | - * must have the first slash. Defaults to the base folder the plugin is |
29 | | - * located in. |
30 | | - * Network: Optional. Specify "Network: true" to require that a plugin is activated |
31 | | - * across all sites in an installation. This will prevent a plugin from being |
32 | | - * 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 not |
38 | | - * within that first 8 KB, then the plugin author should correct their plugin |
39 | | - * and move the plugin data headers to the top. |
40 | | - * |
41 | | - * The plugin file is assumed to have permissions to allow for scripts to read |
42 | | - * the file. This is not checked however and the file is only opened for |
43 | | - * reading. |
44 | | - * |
45 | | - * @since 1.5.0 |
46 | | - * @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.0 |
127 | | - * |
128 | | - * @see get_plugin_data() |
129 | | - * |
130 | | - * @access private |
131 | | - * |
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.NonSingularStringLiteralDomain |
163 | | - $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 | | - |
224 | 9 | /** |
225 | 10 | * Gets a list of a plugin's files. |
226 | 11 | * |
|
0 commit comments