Completed
Branch BETA-4.9-messages-queue-fixed (941081)
by
unknown
17:38 queued 10s
created

EEH_File::exists()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 2
eloc 3
nc 2
nop 1
1
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
2
/**
3
 * Event Espresso
4
 *
5
 * Event Registration and Management Plugin for WordPress
6
 *
7
 * @ package			Event Espresso
8
 * @ author			Seth Shoultes
9
 * @ copyright		(c) 2008-2011 Event Espresso  All Rights Reserved.
10
 * @ license			http://eventespresso.com/support/terms-conditions/   * see Plugin Licensing *
11
 * @ link					http://www.eventespresso.com
12
 * @ version		 	4.0
13
 *
14
 */
15
require_once( EE_HELPERS . 'EEH_Base.helper.php' );
16
require_once( EE_INTERFACES . 'EEI_Interfaces.php' );
17
/**
18
 *
19
 * Class EEH_File
20
 *
21
 * Description
22
 *
23
 * @package 			Event Espresso
24
 * @subpackage 	core
25
 * @author 				Brent Christensen
26
 * @since 				$VID:$
27
 *
28
 */
29
class EEH_File extends EEH_Base implements EEHI_File {
30
31
	/**
32
	 * @var string $_credentials_form
33
	 */
34
	private static $_credentials_form;
35
	
36
	protected static $_wp_filesystem_direct;
37
	
38
	/**
39
	 * @param string|null $filepath the filepath we want to work in. If its in the 
40
	 * wp uploads directory, we'll want to just use the filesystem directly.
41
	 * If not provided, we have to assume its not in the uploads directory
42
	 * @throws EE_Error
43
	 * @return WP_Filesystem_Base
44
	 */
45
	private static function _get_wp_filesystem( $filepath = null) {
46
		if( apply_filters( 
47
				'FHEE__EEH_File___get_wp_filesystem__allow_using_filesystem_direct', 
48
				$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...
49
				$filepath ) ) {
50
			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...
51
				require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
52
				$method = 'direct';
53
				$wp_filesystem_direct_file = apply_filters( 'filesystem_method_file', ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php', $method );
54
				//check constants defined, just like in wp-admin/includes/file.php's WP_Filesystem()
55
				if ( ! defined('FS_CHMOD_DIR') ) {
56
					define('FS_CHMOD_DIR', ( fileperms( ABSPATH ) & 0777 | 0755 ) );
57
				}
58
				if ( ! defined('FS_CHMOD_FILE') ) {
59
					define('FS_CHMOD_FILE', ( fileperms( ABSPATH . 'index.php' ) & 0777 | 0644 ) );
60
				}
61
				require_once( $wp_filesystem_direct_file );
62
				EEH_File::$_wp_filesystem_direct = new WP_Filesystem_Direct( array() );
63
			}
64
			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...
65
		}
66
		global $wp_filesystem;
67
		// no filesystem setup ???
68
		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...
69
			// if some eager beaver's just trying to get in there too early...
70
			// let them do it, because we are one of those eager beavers! :P
71
			/**
72
			 * more explanations are probably merited. http://codex.wordpress.org/Filesystem_API#Initializing_WP_Filesystem_Base
73
			 * says WP_Filesystem should be used after 'wp_loaded', but currently EE's activation process
74
			 * is setup to mostly happen on 'init', and refactoring to have it happen on
75
			 * 'wp_loaded' is too much work on a BETA milestone.
76
			 * So this fix is expected to work if the WP files are owned by the server user,
77
			 * but probably not if the user needs to enter their FTP credentials to modify files
78
			 * and there may be troubles if the WP files are owned by a different user
79
			 * than the server user. But both of these issues should exist in 4.4 and earlier too
80
			 */
81
			if ( FALSE && ! did_action( 'wp_loaded' )) {
82
				$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');
83
				if ( WP_DEBUG ) {
84
					$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');
85
				}
86
				throw new EE_Error( $msg );
87
			} else {
88
				// should be loaded if we are past the wp_loaded hook...
89
				if ( ! function_exists( 'WP_Filesystem' )) {
90
					require_once( ABSPATH . 'wp-admin/includes/file.php' );
91
					require_once( ABSPATH . 'wp-admin/includes/template.php' );
92
				}
93
				// turn on output buffering so that we can capture the credentials form
94
				ob_start();
95
				$credentials = request_filesystem_credentials( '' );
96
				// store credentials form for the time being
97
				EEH_File::$_credentials_form = ob_get_clean();
98
				// basically check for direct or previously configured access
99
				if ( ! WP_Filesystem( $credentials ) ) {
100
					// if credentials do NOT exist
101
					if ( $credentials === FALSE ) {
102
						add_action( 'admin_notices', array( 'EEH_File', 'display_request_filesystem_credentials_form' ), 999 );
103
						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'));
104
					} elseif( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
105
						add_action( 'admin_notices', array( 'EEH_File', 'display_request_filesystem_credentials_form' ), 999 );
106
						throw new EE_Error(
107
								sprintf(
108
										__( 'WP Filesystem Error: $1%s', 'event_espresso' ),
109
										$wp_filesystem->errors->get_error_message() ) );
110
					}
111
				}
112
			}
113
		}
114
		return $wp_filesystem;
115
	}
116
117
	/**
118
	 * display_request_filesystem_credentials_form
119
	 */
120
	public static function display_request_filesystem_credentials_form() {
121
		if ( ! empty( EEH_File::$_credentials_form )) {
122
			echo '<div class="updated espresso-notices-attention"><p>' . EEH_File::$_credentials_form . '</p></div>';
123
		}
124
	}
125
126
127
128
	/**
129
	 *    verify_filepath_and_permissions
130
	 *    checks that a file is readable and has sufficient file permissions set to access
131
	 *
132
	 * @access public
133
	 * @param string $full_file_path - full server path to the folder or file
134
	 * @param string $file_name      - name of file if checking a file
135
	 * @param string $file_ext       - file extension (ie: "php") if checking a file
136
	 * @param string $type_of_file   - general type of file (ie: "module"), this is only used to improve error messages
137
	 * @throws EE_Error
138
	 * @return bool
139
	 */
140
	public static function verify_filepath_and_permissions( $full_file_path = '', $file_name = '', $file_ext = '', $type_of_file = '' ) {
141
		// load WP_Filesystem and set file permissions
142
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
143
		$full_file_path = EEH_File::standardise_directory_separators( $full_file_path );
144
		if ( ! $wp_filesystem->is_readable( EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ) )) {
145
			$file_name = ! empty( $type_of_file ) ? $file_name . ' ' . $type_of_file : $file_name;
146
			$file_name .= ! empty( $file_ext ) ? ' file' : ' folder';
147
			$msg = sprintf(
148
				__( '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' ),
149
				$file_name,
150
				'<br />'
151
			);
152
			if ( EEH_File::exists( $full_file_path )) {
153
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_file_path, $type_of_file );
154
			} else {
155
				// no file permissions means the file was not found
156
				$msg .= sprintf(
157
					__( 'Please ensure the following path is correct: "%s".', 'event_espresso' ),
158
					$full_file_path
159
				);
160
			}
161
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
162
				throw new EE_Error( $msg . '||' . $msg );
163
			}
164
			return FALSE;
165
		}
166
		return TRUE;
167
	}
168
169
170
171
	/**
172
	 * _permissions_error_for_unreadable_filepath - attempts to determine why permissions are set incorrectly for a file or folder
173
	 *
174
	 * @access private
175
	 * @param string $full_file_path - full server path to the folder or file
176
	 * @param string $type_of_file - general type of file (ie: "module"), this is only used to improve error messages
177
	 * @return string
178
	 */
179
	private static function _permissions_error_for_unreadable_filepath( $full_file_path = '', $type_of_file = '' ){
180
		// load WP_Filesystem and set file permissions
181
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
182
		// check file permissions
183
		$perms = $wp_filesystem->getchmod( EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ) );
184
		if ( $perms ) {
185
			// file permissions exist, but way be set incorrectly
186
			$type_of_file = ! empty( $type_of_file ) ? $type_of_file . ' ' : '';
187
			$type_of_file .= ! empty( $type_of_file ) ? 'file' : 'folder';
188
			return sprintf(
189
				__( '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' ),
190
				$type_of_file,
191
				$perms
192
			);
193
		} else {
194
			// file exists but file permissions could not be read ?!?!
195
			return sprintf(
196
				__( 'Please ensure that the server and/or PHP configuration allows the current process to access the following file: "%s".', 'event_espresso' ),
197
				$full_file_path
198
			);
199
		}
200
	}
201
202
203
204
	/**
205
	 * ensure_folder_exists_and_is_writable
206
	 * ensures that a folder exists and is writable, will attempt to create folder if it does not exist
207
	 * Also ensures all the parent folders exist, and if not tries to create them.
208
	 * Also, if this function creates the folder, adds a .htaccess file and index.html file
209
	 * @param string $folder
210
	 * @throws EE_Error if the folder exists and is writeable, but for some reason we 
211
	 * can't write to it
212
	 * @return bool false if folder isn't writable; true if it exists and is writeable,
213
	 */
214
	public static function ensure_folder_exists_and_is_writable( $folder = '' ){
215
		if ( empty( $folder )) {
216
			return false;
217
		}
218
		// remove ending DS
219
		$folder = EEH_File::standardise_directory_separators( rtrim( $folder, '/\\' ));
220
		$parent_folder = EEH_File::get_parent_folder( $folder );
221
		// add DS to folder
222
		$folder = EEH_File::end_with_directory_separator( $folder );
223
		$wp_filesystem = EEH_File::_get_wp_filesystem( $folder );
224
		if ( ! $wp_filesystem->is_dir( EEH_File::convert_local_filepath_to_remote_filepath( $folder ) ) ) {
225
			//ok so it doesn't exist. Does its parent? Can we write to it?
226
			if(	! EEH_File::ensure_folder_exists_and_is_writable( $parent_folder ) ) {
227
				return false;
228
			}
229 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...
230
				return false;
231
			} else {
232
				if ( ! $wp_filesystem->mkdir( EEH_File::convert_local_filepath_to_remote_filepath(  $folder ) ) ) {
233
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
234
						$msg = sprintf( __( '"%s" could not be created.', 'event_espresso' ), $folder );
235
						$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $folder );
236
						throw new EE_Error( $msg );
237
					}
238
					return false;
239
				}
240
				EEH_File::add_index_file( $folder );
241
			}
242
		} elseif ( ! EEH_File::verify_is_writable( $folder, 'folder' )) {
243
			return false;
244
		}
245
		return true;
246
	}
247
248
249
250
	/**
251
	 * verify_is_writable - checks if a file or folder is writable
252
	 * @param string $full_path      - full server path to file or folder
253
	 * @param string $file_or_folder - whether checking a file or folder
254
	 * @throws EE_Error
255
	 * @return bool
256
	 */
257
	public static function verify_is_writable( $full_path = '', $file_or_folder = 'folder' ){
258
		// load WP_Filesystem and set file permissions
259
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_path );
260
		$full_path = EEH_File::standardise_directory_separators( $full_path );
261
		if ( ! $wp_filesystem->is_writable( EEH_File::convert_local_filepath_to_remote_filepath( $full_path ) ) ) {
262
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
263
				$msg = sprintf( __( 'The "%1$s" %2$s is not writable.', 'event_espresso' ), $full_path, $file_or_folder );
264
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_path );
265
				throw new EE_Error( $msg );
266
			}
267
			return FALSE;
268
		}
269
		return TRUE;
270
	}
271
272
273
274
	/**
275
	 * ensure_file_exists_and_is_writable
276
	 * ensures that a file exists and is writable, will attempt to create file if it does not exist.
277
	 * Also ensures all the parent folders exist, and if not tries to create them.
278
	 * @param string $full_file_path
279
	 * @throws EE_Error
280
	 * @return bool
281
	 */
282
	public static function ensure_file_exists_and_is_writable( $full_file_path = '' ) {
283
		// load WP_Filesystem and set file permissions
284
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
285
		$full_file_path = EEH_File::standardise_directory_separators( $full_file_path );
286
		$parent_folder = EEH_File::get_parent_folder( $full_file_path );
287 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...
288
			if( ! EEH_File::ensure_folder_exists_and_is_writable( $parent_folder ) ) {
289
				return false;
290
			}
291
			if ( ! $wp_filesystem->touch( EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ) ) ) {
292
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
293
					$msg = sprintf( __( 'The "%s" file could not be created.', 'event_espresso' ), $full_file_path );
294
					$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_file_path );
295
					throw new EE_Error( $msg );
296
				}
297
				return false;
298
			}
299
		}
300
		if ( ! EEH_File::verify_is_writable( $full_file_path, 'file' )) {
301
			return false;
302
		}
303
		return true;
304
	}
305
	
306
	/**
307
	 * Gets the parent folder. If provided with file, gets the folder that contains it.
308
	 * If provided a folder, gets its parent folder.
309
	 * @param string $file_or_folder_path
310
	 * @return string parent folder, ENDING with a directory separator
311
	 */
312
	public static function get_parent_folder( $file_or_folder_path ) {
313
		//find the last DS, ignoring a DS on the very end
314
		//eg if given "/var/something/somewhere/", we want to get "somewhere"'s
315
		//parent folder, "/var/something/"
316
		$ds = strrpos( $file_or_folder_path, DS, -2 );
317
		return substr( $file_or_folder_path, 0, $ds + 1 );
318
	}
319
	
320
	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...
321
		
322
	}
323
324
325
326
	/**
327
	 * get_file_contents
328
	 * @param string $full_file_path
329
	 * @return string
330
	 */
331
	public static function get_file_contents( $full_file_path = '' ){
332
		$full_file_path = EEH_File::standardise_directory_separators( $full_file_path );
333
		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 ))) {
334
			// load WP_Filesystem and set file permissions
335
			$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
336
			return $wp_filesystem->get_contents(EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ) );
337
		}
338
		return '';
339
	}
340
341
342
343
	/**
344
	 * write_file
345
	 * @param string $full_file_path
346
	 * @param string $file_contents - the content to be written to the file
347
	 * @param string $file_type
348
	 * @throws EE_Error
349
	 * @return bool
350
	 */
351
	public static function write_to_file( $full_file_path = '', $file_contents = '', $file_type = '' ){
352
		$full_file_path = EEH_File::standardise_directory_separators( $full_file_path );
353
		$file_type = ! empty( $file_type ) ? rtrim( $file_type, ' ' ) . ' ' : '';
354
		$folder = EEH_File::remove_filename_from_filepath( $full_file_path );
355
		if ( ! EEH_File::verify_is_writable( $folder, 'folder' )) {
356
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
357
				$msg = sprintf( __( 'The %1$sfile located at "%2$s" is not writable.', 'event_espresso' ), $file_type, $full_file_path );
358
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_file_path );
359
				throw new EE_Error( $msg );
360
			}
361
			return FALSE;
362
		}
363
		// load WP_Filesystem and set file permissions
364
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
365
		// write the file
366
		if ( ! $wp_filesystem->put_contents(EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ), $file_contents )) {
367
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
368
				$msg = sprintf( __( 'The %1$sfile located at "%2$s" could not be written to.', 'event_espresso' ), $file_type, $full_file_path );
369
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_file_path, 'f' );
370
				throw new EE_Error( $msg );
371
			}
372
			return FALSE;
373
		}
374
		return TRUE;
375
	}
376
377
	/**
378
	 * Wrapper for WP_Filesystem_Base::delete
379
	 *
380
	 * @param string $filepath
381
	 * @param boolean $recursive
382
	 * @param boolean|string $type 'd' for directory, 'f' for file
383
	 * @return boolean
384
	 */
385
	public static function delete( $filepath, $recursive = false, $type = false ) {
386
		$wp_filesystem = EEH_File::_get_wp_filesystem();
387
		return $wp_filesystem->delete( $filepath, $recursive, $type ) ? TRUE : FALSE;
388
	}
389
390
391
392
	/**
393
	 * exists
394
	 * checks if a file exists using the WP filesystem
395
	 *
396
	 * @param string $full_file_path
397
	 * @return bool
398
	 */
399
	public static function exists( $full_file_path = '' ) {
400
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
401
		return $wp_filesystem->exists( EEH_File::convert_local_filepath_to_remote_filepath( $full_file_path ) ) ? TRUE : FALSE;
402
	}
403
404
405
406
	/**
407
	 * is_readable
408
	 * checks if a file is_readable using the WP filesystem
409
	 *
410
	 * @param string $full_file_path
411
	 * @return bool
412
	 */
413
	public static function is_readable( $full_file_path = '' ) {
414
		$wp_filesystem = EEH_File::_get_wp_filesystem( $full_file_path );
415
		if( $wp_filesystem->is_readable( EEH_File::convert_local_filepath_to_remote_filepath(  $full_file_path ) ) ) {
416
			return true;
417
		} else {
418
			return false;
419
		}
420
	}
421
422
423
424
	/**
425
	 * remove_filename_from_filepath
426
	 * 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
427
	 *
428
	 * @param string $full_file_path
429
	 * @return string
430
	 */
431
	public static function remove_filename_from_filepath( $full_file_path = '' ) {
432
		return pathinfo( $full_file_path, PATHINFO_DIRNAME );
433
	}
434
435
436
	/**
437
	 * get_filename_from_filepath. Arguably the same as basename()
438
	 *
439
	 * @param string $full_file_path
440
	 * @return string
441
	 */
442
	public static function get_filename_from_filepath( $full_file_path = '' ) {
443
		return pathinfo( $full_file_path, PATHINFO_BASENAME );
444
	}
445
446
447
	/**
448
	 * get_file_extension
449
	 *
450
	 * @param string $full_file_path
451
	 * @return string
452
	 */
453
	public static function get_file_extension( $full_file_path = '' ) {
454
		return pathinfo( $full_file_path, PATHINFO_EXTENSION );
455
	}
456
457
458
459
	/**
460
	 * add_htaccess_deny_from_all so the webserver cannot access this folder
461
	 * @param string $folder
462
	 * @return bool
463
	 */
464 View Code Duplication
	public static function add_htaccess_deny_from_all( $folder = '' ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
465
		$folder = EEH_File::standardise_and_end_with_directory_separator( $folder );
466
		if ( ! EEH_File::exists( $folder . '.htaccess' ) ) {
467
			if ( ! EEH_File::write_to_file( $folder . '.htaccess', 'deny from all', '.htaccess' )) {
468
				return FALSE;
469
			}
470
		}
471
		
472
		return TRUE;
473
	}
474
	
475
	/**
476
	 * Adds an index file to this folder, so folks can't list all the file's contents
477
	 * @param string $folder
478
	 * @return boolean
479
	 */
480 View Code Duplication
	public static function add_index_file( $folder ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
481
		$folder = EEH_File::standardise_and_end_with_directory_separator( $folder );
482
		if ( ! EEH_File::exists( $folder . 'index.php' ) ) {
483
			if ( ! EEH_File::write_to_file( $folder . 'index.php', 'You are not permitted to read from this folder', '.php' )) {
484
				return false;
485
			}
486
		}
487
		return true;
488
	}
489
490
491
492
	/**
493
	 * Given that the file in $file_path has the normal name, (ie, CLASSNAME.whatever.php),
494
	 * extract that classname.
495
	 * @param string $file_path
496
	 * @return string
497
	 */
498
	public static function get_classname_from_filepath_with_standard_filename( $file_path ){
499
		//extract file from path
500
		$filename = basename( $file_path );
501
		//now remove the first period and everything after
502
		$pos_of_first_period = strpos( $filename,'.' );
503
		return substr($filename, 0, $pos_of_first_period);
504
	}
505
506
507
508
	/**
509
	 * standardise_directory_separators
510
	 *  convert all directory separators in a file path to whatever is set for DS
511
	 * @param string $file_path
512
	 * @return string
513
	 */
514
	public static function standardise_directory_separators( $file_path ){
515
		return str_replace( array( '\\', '/' ), DS, $file_path );
516
	}
517
518
519
520
	/**
521
	 * end_with_directory_separator
522
	 *  ensures that file path ends with DS
523
	 * @param string $file_path
524
	 * @return string
525
	 */
526
	public static function end_with_directory_separator( $file_path ){
527
		return rtrim( $file_path, '/\\' ) . DS;
528
	}
529
530
531
532
	/**
533
	 * shorthand for both EEH_FIle::end_with_directory_separator AND EEH_File::standardise_directory_separators
534
	 * @param $file_path
535
	 * @return string
536
	 */
537
	public static function standardise_and_end_with_directory_separator( $file_path ){
538
		return self::end_with_directory_separator( self::standardise_directory_separators( $file_path ));
539
	}
540
541
542
543
	/**
544
	 * takes the folder name (with or without trailing slash) and finds the files it in,
545
	 * and what the class's name inside of each should be.
546
	 * @param array $folder_paths
547
	 * @param boolean $index_numerically if TRUE, the returned array will be indexed numerically;
548
	 *		if FALSE (Default), returned array will be indexed by the filenames minus extensions.
549
	 *		Set it TRUE if you know there are files in the directory with the same name but different extensions
550
	 * @throws \EE_Error
551
	 * @return array if $index_numerically == TRUE keys are numeric ,
552
	 *		if $index_numerically == FALSE (Default) keys are what the class names SHOULD be;
553
	 *		 and values are their filepaths
554
	 */
555
	public static function get_contents_of_folders( $folder_paths = array(), $index_numerically = FALSE ){
556
		$class_to_folder_path = array();
557
		foreach( $folder_paths as $folder_path ){
558
			$folder_path = self::standardise_and_end_with_directory_separator( $folder_path );
559
			// load WP_Filesystem and set file permissions
560
			$files_in_folder = glob( $folder_path . '*' );
561
			$class_to_folder_path = array();
562
			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...
563
				foreach( $files_in_folder as $file_path ){
564
					//only add files, not folders
565
					if ( ! is_dir( $file_path )) {
566
						if ( $index_numerically ) {
567
							$class_to_folder_path[] = $file_path;
568
						} else {
569
							$classname = self::get_classname_from_filepath_with_standard_filename( $file_path );
570
							$class_to_folder_path[$classname] = $file_path;
571
						}
572
					}
573
				}
574
			}
575
		}
576
		return $class_to_folder_path;
577
	}
578
579
580
581
	/**
582
	 * Copies a file. Mostly a wrapper of WP_Filesystem::copy
583
	 * @param string $source_file
584
	 * @param string $destination_file
585
	 * @param boolean $overwrite
586
	 * @return boolean success
587
	 * @throws EE_Error
588
	 */
589
	public static function copy( $source_file, $destination_file, $overwrite = FALSE ){
590
		$full_source_path = EEH_File::standardise_directory_separators( $source_file );
591
		if( ! EEH_File::exists( $full_source_path ) ){
592
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
593
				$msg = sprintf( __( 'The file located at "%2$s" is not readable or doesn\'t exist.', 'event_espresso' ), $full_source_path );
594
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_source_path );
595
				throw new EE_Error( $msg );
596
			}
597
			return FALSE;
598
		}
599
600
		$full_dest_path = EEH_File::standardise_directory_separators( $destination_file );
601
		$folder = EEH_File::remove_filename_from_filepath( $full_dest_path );
602
		if ( ! EEH_File::verify_is_writable( $folder, 'folder' )) {
603
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
604
				$msg = sprintf( __( 'The file located at "%2$s" is not writable.', 'event_espresso' ), $full_dest_path );
605
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_dest_path );
606
				throw new EE_Error( $msg );
607
			}
608
			return FALSE;
609
		}
610
611
		// load WP_Filesystem and set file permissions
612
		$wp_filesystem = EEH_File::_get_wp_filesystem( $destination_file );
613
		// write the file
614
		if ( ! $wp_filesystem->copy( 
615
						EEH_File::convert_local_filepath_to_remote_filepath( $full_source_path ), 
616
						EEH_File::convert_local_filepath_to_remote_filepath( $full_dest_path ), 
617
						$overwrite )) {
618
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
619
				$msg = sprintf( __( 'Attempted writing to file %1$s, but could not, probably because of permissions issues', 'event_espresso' ), $full_source_path );
620
				$msg .= EEH_File::_permissions_error_for_unreadable_filepath( $full_source_path, 'f' );
621
				throw new EE_Error( $msg );
622
			}
623
			return FALSE;
624
		}
625
		return TRUE;
626
	}
627
	
628
	/**
629
	 * Reports whether or not the filepath is in the EE uploads folder or not
630
	 * @param string $filepath
631
	 * @return boolean
632
	 */
633
	public static function is_in_uploads_folder( $filepath ) {
634
		$uploads = wp_upload_dir();
635
		return strpos( $filepath, $uploads[ 'basedir' ] ) === 0 ? true : false;
636
	}
637
	
638
	/**
639
	 * Given a "local" filepath (what you probably thought was the only filepath),
640
	 * converts it into a "remote" filepath (the filepath the currently-in-use 
641
	 * $wp_filesystem needs to use access the folder or file).
642
	 * See http://wordpress.stackexchange.com/questions/124900/using-wp-filesystem-in-plugins
643
	 * @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...
644
	 * is in use, so you need to provide it
645
	 * @param string $local_filepath the filepath to the folder/file locally
646
	 * @return string the remote filepath (eg the filepath the filesystem method, eg 
647
	 * ftp or ssh, will use to access the folder
648
	 */
649
	public static function convert_local_filepath_to_remote_filepath( $local_filepath ) {
650
		$wp_filesystem = EEH_File::_get_wp_filesystem( $local_filepath );
651
		return str_replace( WP_CONTENT_DIR . DS, $wp_filesystem->wp_content_dir(), $local_filepath );
652
	}
653
}
654
// End of file EEH_File.helper.php
655
// Location: /helpers/EEH_File.helper.php