Completed
Branch FET-4710-paypal-tax-settings (4a99de)
by
unknown
02:21 queued 1424:26
created

EEH_File::get_parent_folder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 7
rs 9.4286
cc 1
eloc 3
nc 1
nop 1
1
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
2
/**
3
 *
4
 * Class EEH_File
5
 *
6
 * Description
7
 *
8
 * @package 			Event Espresso
9
 * @subpackage 	core
10
 * @author 				Brent Christensen
11
 * @since 				$VID:$
12
 *
13
 */
14
class EEH_File extends EEH_Base {
15
16
	/**
17
	 * @var string $_credentials_form
18
	 */
19
	private static $_credentials_form;
20
	
21
	protected static $_wp_filesystem_direct;
22
	
23
	/**
24
	 * @param string|null $filepath the filepath we want to work in. If its in the 
25
	 * wp uploads directory, we'll want to just use the filesystem directly.
26
	 * If not provided, we have to assume its not in the uploads directory
27
	 * @throws EE_Error
28
	 * @return WP_Filesystem_Base
29
	 */
30
	private static function _get_wp_filesystem( $filepath = null) {
31
		if( apply_filters( 
32
				'FHEE__EEH_File___get_wp_filesystem__allow_using_filesystem_direct', 
33
				$filepath && EEH_File::is_in_uploads_folder( $filepath ), 
0 ignored issues
show
Bug Best Practice introduced by
The expression $filepath of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
34
				$filepath ) ) {
35
			if( ! EEH_File::$_wp_filesystem_direct instanceof WP_Filesystem_Direct ) {
0 ignored issues
show
Bug introduced by
The class WP_Filesystem_Direct does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
36
				require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
37
				$method = 'direct';
38
				$wp_filesystem_direct_file = apply_filters( 'filesystem_method_file', ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php', $method );
39
				require_once( $wp_filesystem_direct_file );
40
				EEH_File::$_wp_filesystem_direct = new WP_Filesystem_Direct( array() );
41
			}
42
			return EEH_File::$_wp_filesystem_direct;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \EEH_File::$_wp_filesystem_direct; (WP_Filesystem_Direct) is incompatible with the return type documented by EEH_File::_get_wp_filesystem of type WP_Filesystem_Base.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
43
		}
44
		global $wp_filesystem;
45
		// no filesystem setup ???
46
		if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
0 ignored issues
show
Bug introduced by
The class WP_Filesystem_Base does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
47
			// if some eager beaver's just trying to get in there too early...
48
			// let them do it, because we are one of those eager beavers! :P
49
			/**
50
			 * more explanations are probably merited. http://codex.wordpress.org/Filesystem_API#Initializing_WP_Filesystem_Base
51
			 * says WP_Filesystem should be used after 'wp_loaded', but currently EE's activation process
52
			 * is setup to mostly happen on 'init', and refactoring to have it happen on
53
			 * 'wp_loaded' is too much work on a BETA milestone.
54
			 * So this fix is expected to work if the WP files are owned by the server user,
55
			 * but probably not if the user needs to enter their FTP credentials to modify files
56
			 * and there may be troubles if the WP files are owned by a different user
57
			 * than the server user. But both of these issues should exist in 4.4 and earlier too
58
			 */
59
			if ( FALSE && ! did_action( 'wp_loaded' )) {
60
				$msg = __('An attempt to access and/or write to a file on the server could not be completed due to a lack of sufficient credentials.', 'event_espresso');
61
				if ( WP_DEBUG ) {
62
					$msg .= '<br />' .  __('The WP Filesystem can not be accessed until after the "wp_loaded" hook has run, so it\'s best not to attempt access until the "admin_init" hookpoint.', 'event_espresso');
63
				}
64
				throw new EE_Error( $msg );
65
			} else {
66
				// should be loaded if we are past the wp_loaded hook...
67
				if ( ! function_exists( 'WP_Filesystem' )) {
68
					require_once( ABSPATH . 'wp-admin/includes/file.php' );
69
					require_once( ABSPATH . 'wp-admin/includes/template.php' );
70
				}
71
				// turn on output buffering so that we can capture the credentials form
72
				ob_start();
73
				$credentials = request_filesystem_credentials( '' );
74
				// store credentials form for the time being
75
				EEH_File::$_credentials_form = ob_get_clean();
76
				// basically check for direct or previously configured access
77
				if ( ! WP_Filesystem( $credentials ) ) {
78
					// if credentials do NOT exist
79
					if ( $credentials === FALSE ) {
80
						add_action( 'admin_notices', array( 'EEH_File', 'display_request_filesystem_credentials_form' ), 999 );
81
						throw new EE_Error( __('An attempt to access and/or write to a file on the server could not be completed due to a lack of sufficient credentials.', 'event_espresso'));
82
					} elseif( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {						
83
						add_action( 'admin_notices', array( 'EEH_File', 'display_request_filesystem_credentials_form' ), 999 );
84
						throw new EE_Error( 
85
								sprintf( 
86
										__( 'WP Filesystem Error: $1%s', 'event_espresso' ), 
87
										$wp_filesystem->errors->get_error_message() ) );
88
					}
89
				}
90
			}
91
		}
92
		return $wp_filesystem;
93
	}
94
95
	/**
96
	 * display_request_filesystem_credentials_form
97
	 */
98
	public static function display_request_filesystem_credentials_form() {
99
		if ( ! empty( EEH_File::$_credentials_form )) {
100
			echo '<div class="updated espresso-notices-attention"><p>' . EEH_File::$_credentials_form . '</p></div>';
101
		}
102
	}
103
104
105
106
	/**
107
	 *    verify_filepath_and_permissions
108
	 *    checks that a file is readable and has sufficient file permissions set to access
109
	 *
110
	 * @access public
111
	 * @param string $full_file_path - full server path to the folder or file
112
	 * @param string $file_name      - name of file if checking a file
113
	 * @param string $file_ext       - file extension (ie: "php") if checking a file
114
	 * @param string $type_of_file   - general type of file (ie: "module"), this is only used to improve error messages
115
	 * @throws EE_Error
116
	 * @return bool
117
	 */
118
	public static function verify_filepath_and_permissions( $full_file_path = '', $file_name = '', $file_ext = '', $type_of_file = '' ) {
119
		// load WP_Filesystem and set file permissions
120
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
121
		$full_file_path = EEH_File::standardise_directory_separators( $full_file_path );
122
		if ( ! $wp_filesystem->is_readable( EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ) )) {
123
			$file_name = ! empty( $type_of_file ) ? $file_name . ' ' . $type_of_file : $file_name;
124
			$file_name .= ! empty( $file_ext ) ? ' file' : ' folder';
125
			$msg = sprintf(
126
				__( 'The requested %1$s could not be found or is not readable, possibly due to an incorrect filepath, or incorrect file permissions.%2$s', 'event_espresso' ),
127
				$file_name,
128
				'<br />'
129
			);
130
			if ( EEH_File::exists( $full_file_path )) {
131
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_file_path, $type_of_file );
132
			} else {
133
				// no file permissions means the file was not found
134
				$msg .= sprintf(
135
					__( 'Please ensure the following path is correct: "%s".', 'event_espresso' ),
136
					$full_file_path
137
				);
138
			}
139
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
140
				throw new EE_Error( $msg . '||' . $msg );
141
			}
142
			return FALSE;
143
		}
144
		return TRUE;
145
	}
146
147
148
149
	/**
150
	 * _permissions_error_for_unreadable_filepath - attempts to determine why permissions are set incorrectly for a file or folder
151
	 *
152
	 * @access private
153
	 * @param string $full_file_path - full server path to the folder or file
154
	 * @param string $type_of_file - general type of file (ie: "module"), this is only used to improve error messages
155
	 * @return string
156
	 */
157
	private static function _permissions_error_for_unreadable_filepath( $full_file_path = '', $type_of_file = '' ){
158
		// load WP_Filesystem and set file permissions
159
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
160
		// check file permissions
161
		$perms = $wp_filesystem->getchmod( EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ) );
162
		if ( $perms ) {
163
			// file permissions exist, but way be set incorrectly
164
			$type_of_file = ! empty( $type_of_file ) ? $type_of_file . ' ' : '';
165
			$type_of_file .= ! empty( $type_of_file ) ? 'file' : 'folder';
166
			return sprintf(
167
				__( 'File permissions for the requested %1$s are currently set at "%2$s". The recommended permissions are 644 for files and 755 for folders.', 'event_espresso' ),
168
				$type_of_file,
169
				$perms
170
			);
171
		} else {
172
			// file exists but file permissions could not be read ?!?!
173
			return sprintf(
174
				__( 'Please ensure that the server and/or PHP configuration allows the current process to access the following file: "%s".', 'event_espresso' ),
175
				$full_file_path
176
			);
177
		}
178
	}
179
180
181
182
	/**
183
	 * ensure_folder_exists_and_is_writable
184
	 * ensures that a folder exists and is writable, will attempt to create folder if it does not exist
185
	 * Also ensures all the parent folders exist, and if not tries to create them.
186
	 * Also, if this function creates the folder, adds a .htaccess file and index.html file
187
	 * @param string $folder
188
	 * @throws EE_Error if the folder exists and is writeable, but for some reason we 
189
	 * can't write to it
190
	 * @return bool false if folder isn't writable; true if it exists and is writeable,
191
	 */
192
	public static function ensure_folder_exists_and_is_writable( $folder = '' ){
193
		if ( empty( $folder )) {
194
			return false;
195
		}
196
		// remove ending DS
197
		$folder = EEH_File::standardise_directory_separators( rtrim( $folder, '/\\' ));
198
		$parent_folder = EEH_File::get_parent_folder( $folder );
199
		// add DS to folder
200
		$folder = EEH_File::end_with_directory_separator( $folder );
201
		$wp_filesystem = EEH_File::_get_wp_filesystem( $folder );
202
		if ( ! $wp_filesystem->is_dir( EEH_File::convert_local_filepath_to_remote_filepath( $folder ) ) ) {
203
			//ok so it doesn't exist. Does its parent? Can we write to it?
204
			if(	! EEH_File::ensure_folder_exists_and_is_writable( $parent_folder ) ) {
205
				return false;
206
			}
207 View Code Duplication
			if ( ! EEH_File::verify_is_writable( $parent_folder, 'folder' )) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
208
				return false;
209
			} else {
210
				if ( ! $wp_filesystem->mkdir( EEH_File::convert_local_filepath_to_remote_filepath(  $folder ) ) ) {
211
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
212
						$msg = sprintf( __( '"%s" could not be created.', 'event_espresso' ), $folder );
213
						$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $folder );
214
						throw new EE_Error( $msg );
215
					}
216
					return false;
217
				}
218
				EEH_File::add_htaccess_deny_from_all( $folder );
219
			}
220
		} elseif ( ! EEH_File::verify_is_writable( $folder, 'folder' )) {
221
			return false;
222
		}
223
		return true;
224
	}
225
226
227
228
	/**
229
	 * verify_is_writable - checks if a file or folder is writable
230
	 * @param string $full_path      - full server path to file or folder
231
	 * @param string $file_or_folder - whether checking a file or folder
232
	 * @throws EE_Error
233
	 * @return bool
234
	 */
235
	public static function verify_is_writable( $full_path = '', $file_or_folder = 'folder' ){
236
		// load WP_Filesystem and set file permissions
237
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_path );
238
		$full_path = EEH_File::standardise_directory_separators( $full_path );
239
		if ( ! $wp_filesystem->is_writable( EEH_File::convert_local_filepath_to_remote_filepath( $full_path ) ) ) {
240
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
241
				$msg = sprintf( __( 'The "%1$s" %2$s is not writable.', 'event_espresso' ), $full_path, $file_or_folder );
242
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_path );
243
				throw new EE_Error( $msg );
244
			}
245
			return FALSE;
246
		}
247
		return TRUE;
248
	}
249
250
251
252
	/**
253
	 * ensure_file_exists_and_is_writable
254
	 * ensures that a file exists and is writable, will attempt to create file if it does not exist.
255
	 * Also ensures all the parent folders exist, and if not tries to create them.
256
	 * @param string $full_file_path
257
	 * @throws EE_Error
258
	 * @return bool
259
	 */
260
	public static function ensure_file_exists_and_is_writable( $full_file_path = '' ) {
261
		// load WP_Filesystem and set file permissions
262
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
263
		$full_file_path = EEH_File::standardise_directory_separators( $full_file_path );
264
		$parent_folder = EEH_File::get_parent_folder( $full_file_path );
265 View Code Duplication
		if ( ! EEH_File::exists( $full_file_path )) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
266
			if( ! EEH_File::ensure_folder_exists_and_is_writable( $parent_folder ) ) {
267
				return false;
268
			}
269
			if ( ! $wp_filesystem->touch( EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ) ) ) {
270
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
271
					$msg = sprintf( __( 'The "%s" file could not be created.', 'event_espresso' ), $full_file_path );
272
					$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_file_path );
273
					throw new EE_Error( $msg );
274
				}
275
				return false;
276
			}
277
		}
278
		if ( ! EEH_File::verify_is_writable( $full_file_path, 'file' )) {
279
			return false;
280
		}
281
		return true;
282
	}
283
	
284
	/**
285
	 * Gets the parent folder. If provided with file, gets the folder that contains it.
286
	 * If provided a folder, gets its parent folder.
287
	 * @param string $file_or_folder_path
288
	 * @return string parent folder, ENDING with a directory separator
289
	 */
290
	public static function get_parent_folder( $file_or_folder_path ) {
291
		//find the last DS, ignoring a DS on the very end
292
		//eg if given "/var/something/somewhere/", we want to get "somewhere"'s
293
		//parent folder, "/var/something/"
294
		$ds = strrpos( $file_or_folder_path, DS, -2 );
295
		return substr( $file_or_folder_path, 0, $ds + 1 );
296
	}
297
	
298
	public static function ensure_folder_exists_recursively( $folder ) {
0 ignored issues
show
Unused Code introduced by
The parameter $folder is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
299
		
300
	}
301
302
303
304
	/**
305
	 * get_file_contents
306
	 * @param string $full_file_path
307
	 * @return string
308
	 */
309
	public static function get_file_contents( $full_file_path = '' ){
310
		$full_file_path = EEH_File::standardise_directory_separators( $full_file_path );
311
		if ( EEH_File::verify_filepath_and_permissions( $full_file_path, EEH_File::get_filename_from_filepath( $full_file_path ) , EEH_File::get_file_extension( $full_file_path ))) {
312
			// load WP_Filesystem and set file permissions
313
			$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
314
			return $wp_filesystem->get_contents(EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ) );
315
		}
316
		return '';
317
	}
318
319
320
321
	/**
322
	 * write_file
323
	 * @param string $full_file_path
324
	 * @param string $file_contents - the content to be written to the file
325
	 * @param string $file_type
326
	 * @throws EE_Error
327
	 * @return bool
328
	 */
329
	public static function write_to_file( $full_file_path = '', $file_contents = '', $file_type = '' ){
330
		$full_file_path = EEH_File::standardise_directory_separators( $full_file_path );
331
		$file_type = ! empty( $file_type ) ? rtrim( $file_type, ' ' ) . ' ' : '';
332
		$folder = EEH_File::remove_filename_from_filepath( $full_file_path );
333
		if ( ! EEH_File::verify_is_writable( $folder, 'folder' )) {
334
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
335
				$msg = sprintf( __( 'The %1$sfile located at "%2$s" is not writable.', 'event_espresso' ), $file_type, $full_file_path );
336
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_file_path );
337
				throw new EE_Error( $msg );
338
			}
339
			return FALSE;
340
		}
341
		// load WP_Filesystem and set file permissions
342
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
343
		// write the file
344
		if ( ! $wp_filesystem->put_contents(EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ), $file_contents )) {
345
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
346
				$msg = sprintf( __( 'The %1$sfile located at "%2$s" could not be written to.', 'event_espresso' ), $file_type, $full_file_path );
347
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_file_path, 'f' );
348
				throw new EE_Error( $msg );
349
			}
350
			return FALSE;
351
		}
352
		return TRUE;
353
	}
354
355
356
357
	/**
358
	 * exists
359
	 * checks if a file exists using the WP filesystem
360
	 *
361
	 * @param string $full_file_path
362
	 * @return bool
363
	 */
364
	public static function exists( $full_file_path = '' ) {
365
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
366
		return $wp_filesystem->exists( EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ) ) ? TRUE : FALSE;
367
	}
368
369
370
371
	/**
372
	 * is_readable
373
	 * checks if a file is_readable using the WP filesystem
374
	 *
375
	 * @param string $full_file_path
376
	 * @return bool
377
	 */
378
	public static function is_readable( $full_file_path = '' ) {
379
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
380
		if( $wp_filesystem->is_readable( EEH_File::convert_local_filepath_to_remote_filepath(  $full_file_path ) ) ) {
381
			return true;
382
		} else {
383
			return false;
384
		}
385
	}
386
387
388
389
	/**
390
	 * remove_filename_from_filepath
391
	 * given a full path to a file including the filename itself, this removes  the filename and returns the path, up to, but NOT including the filename OR slash
392
	 *
393
	 * @param string $full_file_path
394
	 * @return string
395
	 */
396
	public static function remove_filename_from_filepath( $full_file_path = '' ) {
397
		return pathinfo( $full_file_path, PATHINFO_DIRNAME );
398
	}
399
400
401
	/**
402
	 * get_filename_from_filepath. Arguably the same as basename()
403
	 *
404
	 * @param string $full_file_path
405
	 * @return string
406
	 */
407
	public static function get_filename_from_filepath( $full_file_path = '' ) {
408
		return pathinfo( $full_file_path, PATHINFO_BASENAME );
409
	}
410
411
412
	/**
413
	 * get_file_extension
414
	 *
415
	 * @param string $full_file_path
416
	 * @return string
417
	 */
418
	public static function get_file_extension( $full_file_path = '' ) {
419
		return pathinfo( $full_file_path, PATHINFO_EXTENSION );
420
	}
421
422
423
424
	/**
425
	 * add_htaccess_deny_from_all and an index.html file
426
	 * in order to prevent folks from exploring filesystem at their leisure
427
	 * @param string $folder
428
	 * @return bool
429
	 */
430
	public static function add_htaccess_deny_from_all( $folder = '' ) {
431
		$folder = EEH_File::standardise_and_end_with_directory_separator( $folder );
432
		if ( ! EEH_File::exists( $folder . '.htaccess' ) ) {
433
			if ( ! EEH_File::write_to_file( $folder . '.htaccess', 'deny from all', '.htaccess' )) {
434
				return FALSE;
435
			}
436
		}
437
		if ( ! EEH_File::exists( $folder . 'index.html' ) ) {
438
			if ( ! EEH_File::write_to_file( $folder . 'index.html', 'cheating huh?', '.html' )) {
439
				return FALSE;
440
			}
441
		}
442
		return TRUE;
443
	}
444
445
446
447
	/**
448
	 * Given that the file in $file_path has the normal name, (ie, CLASSNAME.whatever.php),
449
	 * extract that classname.
450
	 * @param string $file_path
451
	 * @return string
452
	 */
453
	public static function get_classname_from_filepath_with_standard_filename( $file_path ){
454
		//extract file from path
455
		$filename = basename( $file_path );
456
		//now remove the first period and everything after
457
		$pos_of_first_period = strpos( $filename,'.' );
458
		return substr($filename, 0, $pos_of_first_period);
459
	}
460
461
462
463
	/**
464
	 * standardise_directory_separators
465
	 *  convert all directory separators in a file path to whatever is set for DS
466
	 * @param string $file_path
467
	 * @return string
468
	 */
469
	public static function standardise_directory_separators( $file_path ){
470
		return str_replace( array( '\\', '/' ), DS, $file_path );
471
	}
472
473
474
475
	/**
476
	 * end_with_directory_separator
477
	 *  ensures that file path ends with DS
478
	 * @param string $file_path
479
	 * @return string
480
	 */
481
	public static function end_with_directory_separator( $file_path ){
482
		return rtrim( $file_path, '/\\' ) . DS;
483
	}
484
485
486
487
	/**
488
	 * shorthand for both EEH_FIle::end_with_directory_separator AND EEH_File::standardise_directory_separators
489
	 * @param $file_path
490
	 * @return string
491
	 */
492
	public static function standardise_and_end_with_directory_separator( $file_path ){
493
		return self::end_with_directory_separator( self::standardise_directory_separators( $file_path ));
494
	}
495
496
497
498
	/**
499
	 * takes the folder name (with or without trailing slash) and finds the files it in,
500
	 * and what the class's name inside of each should be.
501
	 * @param array $folder_paths
502
	 * @param boolean $index_numerically if TRUE, the returned array will be indexed numerically;
503
	 *		if FALSE (Default), returned array will be indexed by the filenames minus extensions.
504
	 *		Set it TRUE if you know there are files in the directory with the same name but different extensions
505
	 * @throws \EE_Error
506
	 * @return array if $index_numerically == TRUE keys are numeric ,
507
	 *		if $index_numerically == FALSE (Default) keys are what the class names SHOULD be;
508
	 *		 and values are their filepaths
509
	 */
510
	public static function get_contents_of_folders( $folder_paths = array(), $index_numerically = FALSE ){
511
		$class_to_folder_path = array();
512
		foreach( $folder_paths as $folder_path ){
513
			$folder_path = self::standardise_and_end_with_directory_separator( $folder_path );
514
			// load WP_Filesystem and set file permissions
515
			$files_in_folder = glob( $folder_path . '*' );
516
			$class_to_folder_path = array();
517
			if ( $files_in_folder ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $files_in_folder of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
518
				foreach( $files_in_folder as $file_path ){
519
					//only add files, not folders
520
					if ( ! is_dir( $file_path )) {
521
						if ( $index_numerically ) {
522
							$class_to_folder_path[] = $file_path;
523
						} else {
524
							$classname = self::get_classname_from_filepath_with_standard_filename( $file_path );
525
							$class_to_folder_path[$classname] = $file_path;
526
						}
527
					}
528
				}
529
			}
530
		}
531
		return $class_to_folder_path;
532
	}
533
534
535
536
	/**
537
	 * Copies a file. Mostly a wrapper of WP_Filesystem::copy
538
	 * @param string $source_file
539
	 * @param string $destination_file
540
	 * @param boolean $overwrite
541
	 * @return boolean success
542
	 * @throws EE_Error
543
	 */
544
	public static function copy( $source_file, $destination_file, $overwrite = FALSE ){
545
		$full_source_path = EEH_File::standardise_directory_separators( $source_file );
546
		if( ! EEH_File::exists( $full_source_path ) ){
547
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
548
				$msg = sprintf( __( 'The file located at "%2$s" is not readable or doesn\'t exist.', 'event_espresso' ), $full_source_path );
549
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_source_path );
550
				throw new EE_Error( $msg );
551
			}
552
			return FALSE;
553
		}
554
555
		$full_dest_path = EEH_File::standardise_directory_separators( $destination_file );
556
		$folder = EEH_File::remove_filename_from_filepath( $full_dest_path );
557
		if ( ! EEH_File::verify_is_writable( $folder, 'folder' )) {
558
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
559
				$msg = sprintf( __( 'The file located at "%2$s" is not writable.', 'event_espresso' ), $full_dest_path );
560
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_dest_path );
561
				throw new EE_Error( $msg );
562
			}
563
			return FALSE;
564
		}
565
566
		// load WP_Filesystem and set file permissions
567
		$wp_filesystem = EEH_File::_get_wp_filesystem( $destination_file );
568
		// write the file
569
		if ( ! $wp_filesystem->copy( 
570
						EEH_File::convert_local_filepath_to_remote_filepath( $full_source_path ), 
571
						EEH_File::convert_local_filepath_to_remote_filepath( $full_dest_path ), 
572
						$overwrite )) {
573
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
574
				$msg = sprintf( __( 'Attempted writing to file %1$s, but could not, probably because of permissions issues', 'event_espresso' ), $full_source_path );
575
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_source_path, 'f' );
576
				throw new EE_Error( $msg );
577
			}
578
			return FALSE;
579
		}
580
		return TRUE;
581
	}
582
	
583
	/**
584
	 * Reports whether or not the filepath is in the EE uploads folder or not
585
	 * @param string $filepath
586
	 * @return boolean
587
	 */
588
	public static function is_in_uploads_folder( $filepath ) {
589
		$uploads = wp_upload_dir();
590
		return strpos( $filepath, $uploads[ 'basedir' ] ) === 0 ? true : false;
591
	}
592
	
593
	/**
594
	 * Given a "local" filepath (what you probably thought was the only filepath),
595
	 * converts it into a "remote" filepath (the filepath the currently-in-use 
596
	 * $wp_filesystem needs to use access the folder or file).
597
	 * See http://wordpress.stackexchange.com/questions/124900/using-wp-filesystem-in-plugins
598
	 * @param WP_Filesystem_Base $wp_filesystem we aren't initially sure which one
0 ignored issues
show
Bug introduced by
There is no parameter named $wp_filesystem. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
599
	 * is in use, so you need to provide it
600
	 * @param string $local_filepath the filepath to the folder/file locally
601
	 * @return string the remote filepath (eg the filepath the filesystem method, eg 
602
	 * ftp or ssh, will use to access the folder
603
	 */
604
	public static function convert_local_filepath_to_remote_filepath( $local_filepath ) {
605
		$wp_filesystem = EEH_File::_get_wp_filesystem( $local_filepath );
606
		return str_replace( WP_CONTENT_DIR . DS, $wp_filesystem->wp_content_dir(), $local_filepath );
607
	}
608
}
609
// End of file EEH_File.helper.php
610
// Location: /helpers/EEH_File.helper.php