Created
February 27, 2016 18:49
-
-
Save thekid/499e3667a4c7153defdb to your computer and use it in GitHub Desktop.
Convert to PHP 7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| use io\collections\FileCollection; | |
| use io\collections\iterate\FilteredIOCollectionIterator; | |
| use io\collections\iterate\ExtensionEqualsFilter; | |
| use util\cmd\Console; | |
| use io\streams\Streams; | |
| use lang\XPClass; | |
| class Convert { | |
| const IMPORTS = "<?=imports; ?>\n"; | |
| private static function rewrite($file, $version) { | |
| $tokens= token_get_all(Streams::readAll($file->getInputStream())); | |
| $source= ''; | |
| $array= []; | |
| $imports= []; | |
| $namespace= ''; | |
| $replace= [self::IMPORTS => '']; | |
| $type= null; | |
| for ($i= 0, $s= sizeof($tokens); $i < $s; $i++) { | |
| $token= $tokens[$i]; | |
| // Record whether inside type body or outside | |
| if (null === $type && (T_INTERFACE === $token[0] || T_CLASS === $token[0] || T_TRAIT === $token[0])) { | |
| $type= $tokens[$i + 2][1]; | |
| } | |
| // Record namespace | |
| else if (T_NAMESPACE === $token[0]) { | |
| $namespace= ''; | |
| while (++$i < $s && ';' !== $tokens[$i][0]) { | |
| $namespace.= $tokens[$i][1]; | |
| } | |
| $token= 'namespace'.$namespace.';'; | |
| $namespace= trim($namespace).'\\'; | |
| } | |
| // Record imports | |
| else if (T_USE === $token[0] && !$type) { | |
| if (empty($imports)) { | |
| $source.= self::IMPORTS; | |
| } | |
| $import= ''; | |
| while (++$i < $s && ';' !== $tokens[$i][0]) { | |
| $import.= $tokens[$i][1]; | |
| } | |
| $token= 'use'.$import.';'; | |
| $imports[trim($import)]= true; | |
| } | |
| // newinstance('a.b.C') => new class() implements|extends C { ... } | |
| else if (T_STRING === $token[0] && 'newinstance' === $token[1] && T_STRING === $tokens[$i + 2][0]) { | |
| $literal= $tokens[$i + 2][1]; | |
| $braces= 0; | |
| $args= ''; | |
| for ($i+= 6; $i < $s; $i++) { | |
| if ('[' === $tokens[$i]) { | |
| $braces++; | |
| } else if (']' === $tokens[$i]) { | |
| $braces--; | |
| if (0 === $braces) break; | |
| } else { | |
| $args.= is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i]; | |
| } | |
| } | |
| $token= '(new class('.trim($args).') '; | |
| if ('\\' === $literal{0}) { | |
| $class= new XPClass($literal); | |
| } else if ('self' === $literal) { | |
| $version= '7.0' && $literal= $type; // https://bugs.php.net/bug.php?id=71678 | |
| $class= new XPClass($namespace.$type); | |
| } else { | |
| $class= null; | |
| foreach ($imports as $import => $_) { | |
| if (0 === substr_compare($import, $literal, -strlen($literal))) { | |
| $class= new XPClass($import); | |
| break; | |
| } | |
| } | |
| $class || $class= new XPClass($namespace.$literal); | |
| } | |
| if ($class->isInterface()) { | |
| $token.= 'implements '.$literal.' {'; | |
| } else if ($class->isTrait()) { | |
| $token.= ' { use '.$literal.'; '; | |
| } else { | |
| $token.= 'extends '.$literal.' {'; | |
| } | |
| if ('[' === $tokens[$i + 3]) { | |
| for ($i+= 4; $i < $s; $i++) { | |
| // 'list' => [] vs. 'toString' => function() { ... } | |
| if (']' === $tokens[$i]) { | |
| break; | |
| } else if (',' === $tokens[$i]) { | |
| // Skip | |
| } else if (T_CONSTANT_ENCAPSED_STRING === $tokens[$i][0]) { | |
| if ('#' === $tokens[$i][1]{1}) { | |
| $p= strrpos($tokens[$i][1], ' '); | |
| $member= substr($tokens[$i][1], $p + 1, -1); | |
| $token.= substr($tokens[$i][1], 1, $p - 1)."\n "; | |
| } else { | |
| $member= substr($tokens[$i][1], 1, -1); | |
| } | |
| if (T_FUNCTION === $tokens[$i + 4][0]) { | |
| $token.= 'public function '.$member; | |
| $braces= 0; | |
| for ($i+= 5; $i < $s; $i++) { | |
| if ('{' === $tokens[$i]) { | |
| $braces++; | |
| $token.= '{'; | |
| } else if ('}' === $tokens[$i]) { | |
| $braces--; | |
| $token.= '}'; | |
| if (0 === $braces) break; | |
| } else { | |
| $token.= is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i]; | |
| } | |
| } | |
| } else { | |
| $token.= 'public $'.$member.' = '; | |
| $braces= 0; | |
| for ($i+= 4; $i < $s; $i++) { | |
| if ('[' === $tokens[$i]) { | |
| $braces++; | |
| $token.= '['; | |
| } else if (']' === $tokens[$i]) { | |
| $braces--; | |
| if (-1 === $braces) { | |
| $token= trim($token).";\n "; | |
| break 2; | |
| } | |
| $token.= ']'; | |
| } else if (',' === $tokens[$i]) { | |
| if (0 === $braces) break; | |
| } else { | |
| $token.= is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i]; | |
| } | |
| } | |
| $token.= ';'; | |
| } | |
| } else { | |
| $token.= is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i]; | |
| } | |
| } | |
| $token.= '}'; | |
| } else if (T_CONSTANT_ENCAPSED_STRING === $tokens[$i + 3][0]) { | |
| $token.= str_replace('\\\\', '\\', substr($tokens[$i + 3][1], 2, -1)); | |
| $i+= 3; | |
| } else { | |
| $token.= ' }'; | |
| } | |
| } | |
| $source.= is_array($token) ? $token[1] : $token; | |
| } | |
| $source= strtr($source, $replace); | |
| // Console::writeLine($source); | |
| // return; | |
| with ($file->getOutputStream(), function($out) use($source) { | |
| $out->write($source); | |
| }); | |
| return true; | |
| } | |
| public static function main($args) { | |
| $sources= new FilteredIOCollectionIterator( | |
| new FileCollection($args[0]), | |
| new ExtensionEqualsFilter(\xp::CLASS_FILE_EXT), | |
| true | |
| ); | |
| Console::writeLine($sources); | |
| $version= isset($args[1]) ? $args[1] : '7.0'; | |
| Console::write('['); | |
| foreach ($sources as $file) { | |
| Console::write(self::rewrite($file, $version) ? '.' : 'E'); | |
| } | |
| Console::write(']'); | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See also this PHP 5.4/5.5 converter