├── README.md ├── convert.php └── revert.php /README.md: -------------------------------------------------------------------------------- 1 | PHP 5.4 Short Array Syntax Converter 2 | ================================ 3 | 4 | Command-line script to convert and revert PHP's `array()` syntax to PHP 5.4's short array syntax`[]` using PHP's built-in tokenizer. 5 | 6 | By relying on the PHP tokenizer, nothing but the array syntax itself will be altered. The script was successfully tested against code bases with more than 5.000 PHP files. 7 | 8 | 9 | Usage 10 | ================================ 11 | 12 | Usage: php convert.php [-w] 13 | 14 | 15 | Run the script with the path of the PHP file you wish to convert as argument. This will print the converted source code to STDOUT. 16 | 17 | You can add the `-w` switch if you want to override the original file with the converted code. 18 | 19 | If you want the script to process PHP files with short open tags (` -name "*.php" -exec php "convert.php" -w "{}" \; 26 | 27 | Or on Windows (thanks to John Jablonski for suggesting): 28 | 29 | FOR /f "tokens=*" %a in ('dir *.php /S/B') DO php convert.php %a -w 30 | 31 | In case you don't trust the script yet, you can even perform a syntax check after conversion: 32 | 33 | find -name "*.php" -exec php -l "{}" \; | grep "error:" 34 | 35 | 36 | Revert 37 | ================================ 38 | 39 | Usage: php revert.php [-w] 40 | 41 | **Reverting has not yet been thoroughly tested, so use with extreme percaution!** 42 | 43 | Since there is no specific token for the short array syntax, it assumes every "[" is an aray and relies on checking the previous token for a variable, object property, function return ")", nested array "]" and variable reference "}". 44 | 45 | 46 | Thanks to 47 | ================================ 48 | Thanks to [Lebenslauf.com](https://lebenslauf.com) (German CV editor) for sponsoring the development. 49 | -------------------------------------------------------------------------------- /convert.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 30 | */ 31 | 32 | 33 | // - - - - - HANDLE COMMAND LINE ARGUMENTS - - - - - 34 | 35 | $filePath = null; 36 | $saveFile = false; 37 | 38 | if ($argc > 3) { 39 | file_put_contents('php://stderr', 'Usage: php convert.php [-w] ' . "\n"); 40 | exit(1); 41 | } 42 | for ($i = 1; $i < $argc; ++$i) { 43 | if ($argv[$i] && $argv[$i][0] == '-') { 44 | $saveFile = ($argv[$i] == '-w'); 45 | } else { 46 | $filePath = $argv[$i]; 47 | } 48 | } 49 | 50 | if (!$filePath) { 51 | file_put_contents('php://stderr', 'Usage: php convert.php [-w] ' . "\n"); 52 | exit(1); 53 | } elseif (!file_exists($filePath)) { 54 | file_put_contents('php://stderr', 'File "' . $filePath . '" not found.' . "\n"); 55 | exit(1); 56 | } 57 | 58 | 59 | // - - - - - READ ORIGINAL CODE - - - - - 60 | 61 | $code = file_get_contents($filePath); 62 | $tokens = token_get_all($code); 63 | 64 | 65 | // - - - - - PARSE CODE - - - - - 66 | 67 | $replacements = array(); 68 | $offset = 0; 69 | for ($i = 0; $i < count($tokens); ++$i) { 70 | // Keep track of the current byte offset in the source code 71 | $offset += strlen(is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i]); 72 | 73 | // T_ARRAY could either mean the "array(...)" syntax we're looking for 74 | // or a type hinting statement ("function(array $foo) { ... }") 75 | if (is_array($tokens[$i]) && $tokens[$i][0] === T_ARRAY) { 76 | // Look for a subsequent opening bracket ("(") to be sure we're actually 77 | // looking at an "array(...)" statement 78 | $isArraySyntax = false; 79 | $subOffset = $offset; 80 | for ($j = $i + 1; $j < count($tokens); ++$j) { 81 | $subOffset += strlen(is_array($tokens[$j]) ? $tokens[$j][1] : $tokens[$j]); 82 | 83 | if (is_string($tokens[$j]) && $tokens[$j] == '(') { 84 | $isArraySyntax = true; 85 | break; 86 | } elseif (!is_array($tokens[$j]) || $tokens[$j][0] !== T_WHITESPACE) { 87 | $isArraySyntax = false; 88 | break; 89 | } 90 | } 91 | 92 | if ($isArraySyntax) { 93 | // Replace "array" and the opening bracket (including preceeding whitespace) with "[" 94 | $replacements[] = array( 95 | 'start' => $offset - strlen($tokens[$i][1]), 96 | 'end' => $subOffset, 97 | 'string' => '[', 98 | ); 99 | 100 | // Look for matching closing bracket (")") 101 | $subOffset = $offset; 102 | $openBracketsCount = 0; 103 | for ($j = $i + 1; $j < count($tokens); ++$j) { 104 | $subOffset += strlen(is_array($tokens[$j]) ? $tokens[$j][1] : $tokens[$j]); 105 | 106 | if (is_string($tokens[$j]) && $tokens[$j] == '(') { 107 | ++$openBracketsCount; 108 | } elseif (is_string($tokens[$j]) && $tokens[$j] == ')') { 109 | --$openBracketsCount; 110 | 111 | if ($openBracketsCount == 0) { 112 | // Replace ")" with "]" 113 | $replacements[] = array( 114 | 'start' => $subOffset - 1, 115 | 'end' => $subOffset, 116 | 'string' => ']', 117 | ); 118 | break; 119 | } 120 | } 121 | } 122 | } 123 | } 124 | } 125 | 126 | 127 | // - - - - - UPDATE CODE - - - - - 128 | 129 | // Apply the replacements to the source code 130 | $offsetChange = 0; 131 | foreach ($replacements as $replacement) { 132 | $code = substr_replace( 133 | $code, 134 | $replacement['string'], 135 | $replacement['start'] + $offsetChange, 136 | $replacement['end'] - $replacement['start'] 137 | ); 138 | $offsetChange += strlen($replacement['string']) - ($replacement['end'] - $replacement['start']); 139 | } 140 | 141 | 142 | // - - - - - OUTPUT/WRITE NEW CODE - - - - - 143 | 144 | if ($saveFile) { 145 | if ($replacements) { 146 | file_put_contents($filePath, $code); 147 | print count($replacements) . ' replacements.' . "\n"; 148 | } else { 149 | print 'No replacements.' . "\n"; 150 | } 151 | } else { 152 | print $code; 153 | } -------------------------------------------------------------------------------- /revert.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 30 | */ 31 | 32 | 33 | // - - - - - HANDLE COMMAND LINE ARGUMENTS - - - - - 34 | 35 | $filePath = null; 36 | $saveFile = false; 37 | 38 | if ($argc > 3) { 39 | file_put_contents('php://stderr', 'Usage: php revert.php [-w] ' . "\n"); 40 | exit(1); 41 | } 42 | for ($i = 1; $i < $argc; ++$i) { 43 | if ($argv[$i] && $argv[$i][0] == '-') { 44 | $saveFile = ($argv[$i] == '-w'); 45 | } else { 46 | $filePath = $argv[$i]; 47 | } 48 | } 49 | 50 | if (!$filePath) { 51 | file_put_contents('php://stderr', 'Usage: php revert.php [-w] ' . "\n"); 52 | exit(1); 53 | } elseif (!file_exists($filePath)) { 54 | file_put_contents('php://stderr', 'File "' . $filePath . '" not found.' . "\n"); 55 | exit(1); 56 | } 57 | 58 | 59 | // - - - - - READ ORIGINAL CODE - - - - - 60 | 61 | $code = file_get_contents($filePath); 62 | $tokens = token_get_all($code); 63 | 64 | 65 | // - - - - - PARSE CODE - - - - - 66 | 67 | $replacements = array(); 68 | $offset = 0; 69 | for ($i = 0; $i < count($tokens); ++$i) { 70 | // Keep track of the current byte offset in the source code 71 | $offset += strlen(is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i]); 72 | 73 | // "[" literal could either be an array index pointer 74 | // or an array definition 75 | if (is_string($tokens[$i]) && $tokens[$i] === '[') { 76 | // Assume we're looking at an array definition by default 77 | $isArraySyntax = true; 78 | $subOffset = $offset; 79 | for ($j = $i - 1; $j > 0; --$j) { 80 | $subOffset -= strlen(is_array($tokens[$j]) ? $tokens[$j][1] : $tokens[$j]); 81 | 82 | if (is_array($tokens[$j]) && $tokens[$j][0] === T_WHITESPACE) { 83 | $subOffset += strlen($tokens[$j][1]); 84 | continue; 85 | // Look for a previous variable or function return 86 | // to make sure we're not looking at an array pointer 87 | } elseif ( 88 | (is_array($tokens[$j]) && ($tokens[$j][0] === T_VARIABLE || $tokens[$j][0] === T_STRING)) 89 | || in_array($tokens[$j], array(')', ']', '}'), true) 90 | ) { 91 | $isArraySyntax = false; 92 | break; 93 | } else { 94 | break; 95 | } 96 | } 97 | 98 | if ($isArraySyntax) { 99 | // Replace "[" with "array(" 100 | $replacements[] = array( 101 | 'start' => $offset - strlen($tokens[$i]), 102 | 'end' => $offset, 103 | 'string' => 'array(', 104 | ); 105 | 106 | // Look for matching closing bracket ("]") 107 | $subOffset = $offset; 108 | $openBracketsCount = 1; 109 | for ($j = $i + 1; $j < count($tokens); ++$j) { 110 | $subOffset += strlen(is_array($tokens[$j]) ? $tokens[$j][1] : $tokens[$j]); 111 | 112 | if (is_string($tokens[$j]) && $tokens[$j] == '[') { 113 | ++$openBracketsCount; 114 | } elseif (is_string($tokens[$j]) && $tokens[$j] == ']') { 115 | --$openBracketsCount; 116 | if($openBracketsCount == 0) { 117 | // Replace "]" with ")" 118 | $replacements[] = array( 119 | 'start' => $subOffset - 1, 120 | 'end' => $subOffset, 121 | 'string' => ')', 122 | ); 123 | break; 124 | } 125 | } 126 | } 127 | } 128 | } 129 | } 130 | 131 | 132 | // - - - - - UPDATE CODE - - - - - 133 | 134 | // Apply the replacements to the source code 135 | $offsetChange = 0; 136 | foreach ($replacements as $replacement) { 137 | $code = substr_replace($code, $replacement['string'], $replacement['start'] + $offsetChange, $replacement['end'] - $replacement['start']); 138 | $offsetChange += strlen($replacement['string']) - ($replacement['end'] - $replacement['start']); 139 | } 140 | 141 | 142 | // - - - - - OUTPUT/WRITE NEW CODE - - - - - 143 | 144 | if ($saveFile) { 145 | if ($replacements) { 146 | file_put_contents($filePath, $code); 147 | print count($replacements) . ' replacements.' . "\n"; 148 | } else { 149 | print 'No replacements.' . "\n"; 150 | } 151 | } else { 152 | print $code; 153 | } --------------------------------------------------------------------------------