|
1 | 1 | <?php |
2 | 2 |
|
| 3 | +use WP_CLI\Utils; |
| 4 | + |
3 | 5 | class EvalFile_Command extends WP_CLI_Command { |
4 | 6 |
|
| 7 | + /** |
| 8 | + * Regular expression pattern to match the shell shebang. |
| 9 | + * |
| 10 | + * @var string |
| 11 | + */ |
| 12 | + const SHEBANG_PATTERN = '/^(#!.*)$/m'; |
| 13 | + |
| 14 | + /** |
| 15 | + * Regular expression pattern to match __FILE__ and __DIR__ constants. |
| 16 | + * |
| 17 | + * We try to be smart and only replace the constants when they are not within quotes. |
| 18 | + * Regular expressions being stateless, this is probably not 100% correct for edge cases. |
| 19 | + * |
| 20 | + * @see https://regex101.com/r/9hXp5d/4/ |
| 21 | + * |
| 22 | + * @var string |
| 23 | + */ |
| 24 | + const FILE_DIR_PATTERN = '/(?>\'[^\']*?\')|(?>"[^"]*?")|(?<file>\b__FILE__\b)|(?<dir>\b__DIR__\b)/m'; |
| 25 | + |
5 | 26 | /** |
6 | 27 | * Loads and executes a PHP file. |
7 | 28 | * |
@@ -32,34 +53,37 @@ public function __invoke( $args, $assoc_args ) { |
32 | 53 | WP_CLI::error( "'$file' does not exist." ); |
33 | 54 | } |
34 | 55 |
|
35 | | - if ( null === \WP_CLI\Utils\get_flag_value( $assoc_args, 'skip-wordpress' ) ) { |
| 56 | + if ( null === Utils\get_flag_value( $assoc_args, 'skip-wordpress' ) ) { |
36 | 57 | WP_CLI::get_runner()->load_wordpress(); |
37 | 58 | } |
38 | 59 |
|
39 | 60 | self::execute_eval( $file, $args ); |
40 | 61 | } |
41 | 62 |
|
| 63 | + /** |
| 64 | + * Evaluate a provided file. |
| 65 | + * |
| 66 | + * @param string $file Filepath to execute, or - for STDIN. |
| 67 | + * @param mixed $args Array of positional arguments to pass to the file. |
| 68 | + */ |
42 | 69 | private static function execute_eval( $file, $args ) { |
43 | 70 | if ( '-' === $file ) { |
44 | 71 | eval( '?>' . file_get_contents( 'php://stdin' ) ); |
45 | 72 | } else { |
46 | 73 | $file_contents = file_get_contents( $file ); |
47 | 74 |
|
48 | 75 | // Check for and remove she-bang. |
49 | | - if ( 0 === strpos( $file_contents, '#!' ) ) { |
50 | | - $file_contents = preg_replace( '/^(#!.*)$/im', '', $file_contents ); |
| 76 | + if ( 0 === strncmp( $file_contents, '#!', 2 ) ) { |
| 77 | + $file_contents = preg_replace( static::SHEBANG_PATTERN, '', $file_contents ); |
51 | 78 | } |
52 | 79 |
|
53 | 80 | $file = realpath( $file ); |
54 | 81 | $dir = dirname( $file ); |
55 | 82 |
|
56 | 83 | // Replace __FILE__ and __DIR__ constants with value of $file or $dir. |
57 | | - // We try to be smart and only replace the constants when they are not within quotes. |
58 | | - // Regular expressions being stateless, this is probably not 100% correct for edge cases. |
59 | | - // See https://regex101.com/r/9hXp5d/2/ |
60 | 84 | $file_contents = preg_replace_callback( |
61 | | - '/(?>\'[^\']*?\')|(?>"[^"]*?")|(?<file>__FILE__)|(?<dir>__DIR__)/m', |
62 | | - function ( $matches ) use ( $file, $dir ) { |
| 85 | + static::FILE_DIR_PATTERN, |
| 86 | + static function ( $matches ) use ( $file, $dir ) { |
63 | 87 | if ( ! empty( $matches['file'] ) ) { |
64 | 88 | return "'{$file}'"; |
65 | 89 | } |
|
0 commit comments