PluginProbe
Plugin Check (PCP) / 1.8.0
Plugin Check (PCP) v1.8.0
2.1.0 trunk 0.1 0.2.0 0.2.1 0.2.2 0.2.3 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.3.0 1.3.1 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 1.9.0 2.0.0 ci-artifacts
plugin-check / includes / Plugin_Context.php

Plugin_Context.php in Plugin Check (PCP) 1.8.0, at includes/Plugin_Context.php

274 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class WordPress\Plugin_Check\Plugin_Context
4 *
5 * @package plugin-check
6 */
7
8 namespace WordPress\Plugin_Check;
9
10 use Exception;
11 use WordPress\Plugin_Check\Lib\Readme\Parser as PCPParser;
12 use WordPress\Plugin_Check\Traits\Readme_Utils;
13 use WordPressdotorg\Plugin_Directory\Readme\Parser as DotorgParser;
14 use function WP_CLI\Utils\normalize_path;
15
16 /**
17 * Class representing the context in which the plugin is running.
18 *
19 * @since 1.0.0
20 */
21 class Plugin_Context {
22
23 use Readme_Utils;
24
25 /**
26 * Absolute path of the plugin main file.
27 *
28 * @since 1.0.0
29 * @var string
30 */
31 protected $main_file;
32
33 /**
34 * Plugin slug.
35 *
36 * @since 1.2.0
37 * @var string
38 */
39 protected $slug;
40
41 /**
42 * The mode to run checks in.
43 *
44 * @since 1.7.0
45 * @var string
46 */
47 protected $mode;
48
49 /**
50 * The minimum supported WordPress version of the plugin.
51 *
52 * @since 1.0.0
53 * @var string
54 */
55 protected $minimum_supported_wp;
56
57 /**
58 * Constructor.
59 *
60 * @since 1.0.0
61 * @since 1.2.0 Second argument $slug was introduced.
62 * @since 1.7.0 Third argument $mode was introduced.
63 *
64 * @param string $main_file The absolute path to the plugin main file.
65 * @param string $slug The plugin slug.
66 * @param string $mode The mode to run checks in.
67 *
68 * @throws Exception Throws exception if not called via regular WP-CLI or WordPress bootstrap order.
69 */
70 public function __construct( $main_file, $slug = '', $mode = 'new' ) {
71 if ( function_exists( 'wp_normalize_path' ) ) {
72 $this->main_file = wp_normalize_path( $main_file );
73 } elseif ( function_exists( '\WP_CLI\Utils\normalize_path' ) ) {
74 $this->main_file = normalize_path( $main_file );
75 } else {
76 throw new Exception(
77 __( 'Unknown environment, normalize_path function not found', 'plugin-check' )
78 );
79 }
80
81 if ( false === strpos( $this->main_file, '.php' ) ) {
82 $files = glob( $this->main_file . '/*.php' );
83 foreach ( $files as $file ) {
84 $plugin_data = get_plugin_data( $file );
85 if ( ! empty( $plugin_data['Name'] ) ) {
86 $this->main_file = $file;
87 break;
88 }
89 }
90 }
91
92 if ( ! empty( $slug ) ) {
93 $this->slug = $slug;
94 } else {
95 $this->slug = basename( dirname( $this->main_file ) );
96 }
97
98 // Validate and set mode.
99 if ( ! empty( $mode ) && in_array( $mode, array( 'new', 'update' ), true ) ) {
100 $this->mode = $mode;
101 } else {
102 $this->mode = 'new';
103 }
104 }
105
106 /**
107 * Returns the plugin basename.
108 *
109 * @since 1.0.0
110 *
111 * @return string Plugin basename.
112 */
113 public function basename() {
114 return plugin_basename( $this->main_file );
115 }
116
117 /**
118 * Returns the plugin main file.
119 *
120 * @since 1.0.2
121 *
122 * @return string Plugin main file.
123 */
124 public function main_file() {
125 return $this->main_file;
126 }
127
128 /**
129 * Returns the plugin slug.
130 *
131 * @since 1.2.0
132 *
133 * @return string Plugin slug.
134 */
135 public function slug() {
136 return $this->slug;
137 }
138
139 /**
140 * Returns the mode to run checks in.
141 *
142 * @since 1.7.0
143 *
144 * @return string The mode to run checks in.
145 */
146 public function get_mode() {
147 return $this->mode;
148 }
149
150 /**
151 * Returns the absolute path for a relative path to the plugin directory.
152 *
153 * @since 1.0.0
154 *
155 * @param string $relative_path Optional. Relative path. Default '/'.
156 * @return string Absolute path.
157 */
158 public function path( $relative_path = '/' ) {
159 if ( is_dir( $this->main_file ) ) {
160 return trailingslashit( $this->main_file ) . ltrim( $relative_path, '/' );
161 } else {
162 return plugin_dir_path( $this->main_file ) . ltrim( $relative_path, '/' );
163 }
164 }
165
166 /**
167 * Returns the full URL for a path relative to the plugin directory.
168 *
169 * @since 1.0.0
170 *
171 * @param string $relative_path Optional. Relative path. Default '/'.
172 * @return string Full URL.
173 */
174 public function url( $relative_path = '/' ) {
175 return plugin_dir_url( $this->main_file ) . ltrim( $relative_path, '/' );
176 }
177
178 /**
179 * Returns the plugin location.
180 *
181 * @since 1.0.0
182 *
183 * @return string The plugin file if single file plugin. Or the plugin folder.
184 */
185 public function location() {
186 $path = $this->path();
187
188 // Return the plugin path and basename if the path matches the plugin directory.
189 if ( WP_PLUGIN_DIR . '/' === $path ) {
190 return $path . $this->basename();
191 }
192
193 return $path;
194 }
195
196 /**
197 * Checks if the plugin is a single file plugin without a dedicated directory.
198 *
199 * This is the case when the single file is directly placed within `wp-content/plugins`.
200 *
201 * @since 1.0.0
202 *
203 * @return bool true if the single file plugin, otherwise false.
204 */
205 public function is_single_file_plugin() {
206 return $this->path() !== $this->location();
207 }
208
209 /**
210 * Determine the minimum supported WordPress version of the plugin.
211 *
212 * @since 1.0.0
213 *
214 * @return string The minimum version supported, or empty string if unknown.
215 */
216 public function minimum_supported_wp() {
217 if ( ! is_null( $this->minimum_supported_wp ) ) {
218 return $this->minimum_supported_wp;
219 }
220
221 $this->minimum_supported_wp = '';
222
223 $headers = get_plugin_data( $this->main_file );
224 if ( ! empty( $headers['RequiresWP'] ) ) {
225 $this->minimum_supported_wp = $headers['RequiresWP'];
226 } elseif ( ! $this->is_single_file_plugin() ) {
227 // Look for the readme.
228 $readme_files = glob( $this->path() . '*' );
229 $readme_files = $this->filter_files_for_readme( $readme_files, $this->path() );
230 $readme_file = reset( $readme_files );
231 if ( $readme_file ) {
232 $parser = class_exists( DotorgParser::class ) ? new DotorgParser( $readme_file ) : new PCPParser( $readme_file );
233
234 if ( ! empty( $parser->requires ) ) {
235 $this->minimum_supported_wp = $parser->requires;
236 }
237 }
238 }
239
240 return $this->minimum_supported_wp;
241 }
242
243 /**
244 * Checks if the file is editable.
245 *
246 * @since 1.1.0
247 *
248 * @param string $file Filename.
249 * @return bool true if the file is editable, otherwise false.
250 */
251 public function is_file_editable( $file ) {
252 $editable = false;
253
254 $editable_extensions = wp_get_plugin_file_editable_extensions( $this->basename() );
255
256 $info = pathinfo( $file );
257
258 $filename = $info['filename'];
259 $dirname = $info['dirname'];
260 $extension = isset( $info['extension'] ) ? strtolower( $info['extension'] ) : '';
261
262 if (
263 in_array( $extension, $editable_extensions, true )
264 && file_exists( dirname( $this->main_file() ) . '/' . $file )
265 && ( ! empty( $filename ) && ( '.' !== $filename[0] ) )
266 && ! ( '.' === $dirname[0] && strlen( $dirname ) > 1 )
267 ) {
268 $editable = true;
269 }
270
271 return $editable;
272 }
273 }
274