Last active
August 29, 2015 14:05
-
-
Save Chipcius/d3dd4052b07a152870bd to your computer and use it in GitHub Desktop.
hacklang-php-juggler
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
| #!/usr/bin/php | |
| <?php | |
| if(!array_key_exists(1, $argv) || $argv[1] === '--help' || $argv[1] === '-h') | |
| { | |
| printLine("Hacklang php translation tool"); | |
| printLine("Version 1"); | |
| printLine('usage: ./headerModifyer.php <directory> [options]'); | |
| printLine(''); | |
| printLine('Available options:'); | |
| printLine(' php (defult) Makes headers <?php'); | |
| printLine(' hack Makes headers <?hh'); | |
| printLine(' hack decl Makes headers <?hh //decl'); | |
| printLine(' hack partial Makes headers <?hh //partial'); | |
| printLine(' hack strict Makes headers <?hh //strict'); | |
| printLine(''); | |
| exit; | |
| } | |
| $fileCount = 0; | |
| $dir = realpath($argv[1]); | |
| if($dir === false) | |
| throw new Exception('Invalid directory'); | |
| if(array_key_exists(2, $argv) && ($argv[2] === 'hack' ||$argv[2] === 'hhvm')) | |
| { | |
| $output = recursiveDirectoryIterator($dir, 'makeHacklang'); | |
| } | |
| else | |
| { | |
| //Use the hacklang stuff to normalize the files first :D | |
| $output = recursiveDirectoryIterator($dir, 'makeHacklang'); | |
| $fileCount = 0; | |
| $output = recursiveDirectoryIterator($dir, 'makePHP'); | |
| } | |
| print('Updated '. $fileCount . ' files'. PHP_EOL); | |
| function recursiveDirectoryIterator ($directory, $function) | |
| { | |
| if(!file_exists($directory)) | |
| return; | |
| if(!function_exists($function)) | |
| throw new Exception('The function '. $function . ' does not excist'); | |
| if(!is_dir($directory)) | |
| { | |
| $handle = new SplFileInfo($directory); | |
| call_user_func($function, $handle); | |
| return; | |
| } | |
| $iterator = new DirectoryIterator ( $directory ); | |
| foreach ( $iterator as $handle ) | |
| { | |
| if ($handle->isFile() && $handle->getExtension() === 'php') | |
| { | |
| call_user_func($function, $handle); | |
| } | |
| elseif (!$handle->isDot () && !$handle->isFile()) | |
| { | |
| switch ($handle->getFilename()) { | |
| case 'views': | |
| case '.': | |
| case 'i18n': | |
| case 'vendor': | |
| continue 2;//one for the swith and one for the foreach loop | |
| break; | |
| default: | |
| break; | |
| } | |
| //print($directory.DIRECTORY_SEPARATOR.$handle->__toString().PHP_EOL); | |
| recursiveDirectoryIterator( | |
| $directory.DIRECTORY_SEPARATOR.$handle->__toString(), | |
| $function | |
| ); | |
| } | |
| } | |
| } | |
| function makeHacklang(SplFileInfo $fileHandle) | |
| { | |
| global $argv; | |
| static $count = 0; | |
| $thisFile = realpath(__FILE__); | |
| $fullPath = $fileHandle->getPathname(); | |
| if($fullPath === $thisFile) | |
| return; | |
| $hhvm_level = ''; | |
| if(array_key_exists(3, $argv)) | |
| { | |
| switch ($argv[3]) | |
| { | |
| case 'decl': | |
| $hhvm_level = ' //decl'; | |
| break; | |
| case 'partial': | |
| $hhvm_level = ' //partial'; | |
| break; | |
| case 'strict': | |
| $hhvm_level = ' //strict'; | |
| break; | |
| } | |
| } | |
| $fileContent = file_get_contents($fullPath); | |
| $search = [ | |
| '<?php defi', | |
| '<?php', | |
| '<?hh //partial', | |
| '<?hh //decl', | |
| '<?hh //strict', | |
| ]; | |
| $replace = [ | |
| '<?hh'.$hhvm_level. PHP_EOL . 'defi', | |
| '<?hh'.$hhvm_level, | |
| '<?hh'.$hhvm_level, | |
| '<?hh'.$hhvm_level, | |
| '<?hh'.$hhvm_level, | |
| ]; | |
| $newContent = str_replace($search, $replace, $fileContent); | |
| //$newContent = str_replace('<?hh'.PHP_EOL, '<?hh'.$hhvm_level . PHP_EOL,$newContent); | |
| $newContent = splitTranlateHacklang($newContent, $fullPath); | |
| if($fileContent === $newContent) | |
| return; | |
| //print(++$count . PHP_EOL); | |
| //print('Updated: ' .$fullPath . PHP_EOL); | |
| $GLOBALS["fileCount"]++; | |
| $stuff = file_put_contents($fullPath, $newContent); | |
| if($stuff === false) | |
| throw new Exception('Could not write to file'); | |
| } | |
| function makePHP(SplFileInfo $fileHandle) | |
| { | |
| static $count = 0; | |
| $thisFile = realpath(__FILE__); | |
| $fullPath = $fileHandle->getPathname(); | |
| if($fullPath === $thisFile) | |
| return; | |
| $fileContent = file_get_contents($fullPath); | |
| $newContent = str_replace('<?hh', '<?php', $fileContent); | |
| $newContent = splitTranlatePHP($newContent, $fullPath); | |
| if($fileContent === $newContent) | |
| return; | |
| //print(++$count . PHP_EOL); | |
| //print('Updated: ' .$fullPath . PHP_EOL); | |
| $GLOBALS["fileCount"]++; | |
| $stuff = file_put_contents($fullPath, $newContent); | |
| if($stuff === false) | |
| throw new Exception('Could not write to file'); | |
| } | |
| function printLine($text = ''){ | |
| print($text. PHP_EOL); | |
| } | |
| function splitTranlatePHP($fileContents, $filename) | |
| { | |
| $lines = explode(PHP_EOL, $fileContents); | |
| $invalidHints = [ | |
| 'mixed' => true, | |
| 'int' => true, | |
| 'string' => true, | |
| 'bool' => true, | |
| 'float' => true, | |
| ]; | |
| foreach ($lines as $index => $line) | |
| { | |
| $hasKeywordFunction = strpos($line, ' function ') !== false; | |
| $hasKeywordPublic = strpos($line, 'public') !== false; | |
| $hasKeywordProtected = strpos($line, 'protected') !== false; | |
| $hasKeywordPrivate = strpos($line, 'private') !== false; | |
| $hasDollar = strpos($line, '$') !== false; | |
| $hadAccessModifyer = $hasKeywordPublic || $hasKeywordPrivate || $hasKeywordProtected; | |
| if($hasKeywordFunction && $hadAccessModifyer) | |
| { | |
| $lines[$index] = $line = str_replace('):', ')//:', $line); | |
| $argumentsStart = strpos($line, '('); | |
| $argumentsEnd = strpos($line, ')'); | |
| $arguments = substr($line, $argumentsStart+1, $argumentsEnd-$argumentsStart-1); | |
| $argumentArray = explode(',', $arguments); | |
| $newArgumentsArray = []; | |
| foreach ($argumentArray as $key => $argument) | |
| { | |
| $argument = trim($argument); | |
| if(strlen($argument) === 0) | |
| continue; | |
| $argument = str_replace('& ', ' &', $argument); | |
| $dollarPos = strpos($argument, '$'); | |
| if($dollarPos === 0) | |
| { | |
| $newArgumentsArray[$key] = $argument; | |
| continue; | |
| } | |
| if($dollarPos > 0 && $argument[$dollarPos-1] === '&') | |
| $dollarPos--; | |
| if($dollarPos === 0) | |
| { | |
| $newArgumentsArray[$key] = $argument; | |
| continue; | |
| } | |
| $typeHint = trim(substr($argument,0,$dollarPos)); | |
| if(substr($typeHint, 0,2) === '/*') | |
| $typeHint = substr($typeHint, 2); | |
| if(substr($typeHint, -2) === '*/') | |
| $typeHint = substr($typeHint, 0, strlen($typeHint) -2); | |
| if(array_key_exists($typeHint, $invalidHints)) | |
| { | |
| $newArgumentsArray[$key] = '/*' . $typeHint . '*/ ' . substr($argument, $dollarPos); | |
| continue; | |
| } | |
| if(strpos($typeHint, '?') !== false) | |
| { | |
| $newArgumentsArray[$key] = '/*' . $typeHint . '*/ ' . substr($argument, $dollarPos); | |
| continue; | |
| } | |
| if($typeHint === '&') | |
| { | |
| print('WARNING! passing value by reference'.PHP_EOL); | |
| print($line.PHP_EOL); | |
| print($filename.PHP_EOL); | |
| $newArgumentsArray[$key] = $argument; | |
| continue; | |
| } | |
| $newArgumentsArray[$key] = $argument; | |
| } | |
| $newArguments = implode(', ', $newArgumentsArray); | |
| $line = str_replace($arguments, $newArguments, $line); | |
| //Donno if the is needed :/ | |
| $lines[$index] = $line; | |
| } | |
| elseif(!$hasKeywordFunction && $hadAccessModifyer && $hasDollar) | |
| { | |
| $lineEdit = $line; | |
| $startPos = 0; | |
| $reconstructedLine = ''; | |
| $preVariable = substr($line, 0 , strpos($line,'$')); | |
| $postIncludingVariable = substr($line, strpos($line,'$')); | |
| $firstSpaceAfterVariable = strpos($postIncludingVariable, ' '); | |
| $firstTabAfterVariable = strpos($postIncludingVariable, "\t"); | |
| $firstSemicolonAfterVariable = strpos($postIncludingVariable, "\t"); | |
| $endOfVariable = PHP_INT_MAX; | |
| if($firstSpaceAfterVariable !== false && $firstSpaceAfterVariable < $endOfVariable) | |
| $endOfVariable = $firstSpaceAfterVariable; | |
| if($firstTabAfterVariable !== false && $firstTabAfterVariable < $endOfVariable) | |
| $endOfVariable = $firstTabAfterVariable; | |
| if($firstSemicolonAfterVariable !== false && $firstSemicolonAfterVariable < $endOfVariable) | |
| $endOfVariable = $firstSemicolonAfterVariable; | |
| $variable = substr($postIncludingVariable, 0, $endOfVariable); | |
| $oldAssignations = substr($postIncludingVariable, $endOfVariable); | |
| $newAccessor = ''; | |
| if(strpos($preVariable, 'public') !== false) | |
| { | |
| $startPos = strpos($line, 'public'); | |
| $newAccessor .= 'public'; | |
| } | |
| elseif(strpos($preVariable, 'protected') !== false) | |
| { | |
| $startPos = strpos($line, 'protected'); | |
| $newAccessor .= 'protected'; | |
| } | |
| elseif(strpos($preVariable, 'private') !== false) | |
| { | |
| $startPos = strpos($line, 'private'); | |
| $newAccessor .= 'private'; | |
| } | |
| else | |
| continue; | |
| if(strpos($preVariable, 'static') !== false) | |
| { | |
| $pos = strpos($line, 'static'); | |
| if($pos < $startPos) | |
| $startPos = $pos; | |
| $newAccessor .= ' ' . 'static'; | |
| } | |
| $type = str_replace(['public','protected','private','static',], '', $preVariable); | |
| $type = trim($type); | |
| if(strlen($type) > 0) | |
| { | |
| if(substr($type, 0,2) !== '/*') | |
| $type = '/*'. $type; | |
| if(substr($type, -2) !== '*/') | |
| $type .= '*/'; | |
| $type .= ' '; | |
| } | |
| $oldPreSpacing = substr($line, 0, $startPos); | |
| $reconstructedLine = $oldPreSpacing . $newAccessor . ' '. $type . $variable . $oldAssignations; | |
| if(trim($reconstructedLine) != trim($line)) | |
| { | |
| $line = $reconstructedLine; | |
| $lines[$index] = $line; | |
| } | |
| } | |
| } | |
| return implode(PHP_EOL, $lines); | |
| } | |
| function splitTranlateHacklang($fileContents, $filename) | |
| { | |
| $lines = explode(PHP_EOL, $fileContents); | |
| foreach ($lines as $index => $line) | |
| { | |
| $hasKeywordFunction = strpos($line, ' function ') !== false; | |
| $hasKeywordPublic = strpos($line, 'public') !== false; | |
| $hasKeywordProtected = strpos($line, 'protected') !== false; | |
| $hasKeywordPrivate = strpos($line, 'private') !== false; | |
| $hasDollar = strpos($line, '$') !== false; | |
| $hadAccessModifyer = $hasKeywordPublic || $hasKeywordPrivate || $hasKeywordProtected; | |
| if($hasKeywordFunction && $hadAccessModifyer) | |
| { | |
| $lines[$index] = $line = str_replace(')//:' ,'):', $line); | |
| $argumentsStart = strpos($line, '('); | |
| $argumentsEnd = strpos($line, ')'); | |
| //print(PHP_EOL); | |
| //print(PHP_EOL); | |
| $arguments = substr($line, $argumentsStart+1, $argumentsEnd-$argumentsStart-1); | |
| $argumentArray = explode(',', $arguments); | |
| $newArgumentsArray = []; | |
| foreach ($argumentArray as $key => $argument) | |
| { | |
| $argument = trim($argument); | |
| if(strlen($argument) === 0) | |
| continue; | |
| $argument = str_replace('& ', ' &', $argument); | |
| $dollarPos = strpos($argument, '$'); | |
| if($dollarPos === 0) | |
| { | |
| $newArgumentsArray[$key] = $argument; | |
| continue; | |
| } | |
| if($dollarPos > 0 && $argument[$dollarPos-1] === '&') | |
| $dollarPos--; | |
| if($dollarPos === 0) | |
| { | |
| $newArgumentsArray[$key] = $argument; | |
| continue; | |
| } | |
| $typeHint = trim(substr($argument,0,$dollarPos)); | |
| if(substr($typeHint, 0,2) === '/*') | |
| $typeHint = substr($typeHint, 2); | |
| if(substr($typeHint, -2) === '*/') | |
| $typeHint = substr($typeHint, 0, strlen($typeHint) -2); | |
| if($typeHint === 'array' || $typeHint === 'stdClass') | |
| { | |
| $newArgumentsArray[$key] = $argument; | |
| continue; | |
| } | |
| if($typeHint === '&') | |
| { | |
| print('WARNING! passing value by reference'.PHP_EOL); | |
| print($line.PHP_EOL); | |
| print($filename.PHP_EOL); | |
| $newArgumentsArray[$key] = $argument; | |
| continue; | |
| } | |
| $newArgumentsArray[$key] = '' . $typeHint . ' ' . substr($argument, $dollarPos); | |
| } | |
| $newArguments = implode(', ', $newArgumentsArray); | |
| $line = str_replace($arguments, $newArguments, $line); | |
| //Donno if the is needed :/ | |
| $lines[$index] = $line; | |
| } | |
| elseif(!$hasKeywordFunction && $hadAccessModifyer && $hasDollar) | |
| { | |
| $lineEdit = $line; | |
| $startPos = 0; | |
| $reconstructedLine = ''; | |
| $preVariable = substr($line, 0 , strpos($line,'$')); | |
| $postIncludingVariable = substr($line, strpos($line,'$')); | |
| $firstSpaceAfterVariable = strpos($postIncludingVariable, ' '); | |
| $firstTabAfterVariable = strpos($postIncludingVariable, "\t"); | |
| $firstSemicolonAfterVariable = strpos($postIncludingVariable, "\t"); | |
| $endOfVariable = PHP_INT_MAX; | |
| if($firstSpaceAfterVariable !== false && $firstSpaceAfterVariable < $endOfVariable) | |
| $endOfVariable = $firstSpaceAfterVariable; | |
| if($firstTabAfterVariable !== false && $firstTabAfterVariable < $endOfVariable) | |
| $endOfVariable = $firstTabAfterVariable; | |
| if($firstSemicolonAfterVariable !== false && $firstSemicolonAfterVariable < $endOfVariable) | |
| $endOfVariable = $firstSemicolonAfterVariable; | |
| $variable = substr($postIncludingVariable, 0, $endOfVariable); | |
| $oldAssignations = substr($postIncludingVariable, $endOfVariable); | |
| $newAccessor = ''; | |
| if(strpos($preVariable, 'public') !== false) | |
| { | |
| $startPos = strpos($line, 'public'); | |
| $newAccessor .= 'public'; | |
| } | |
| elseif(strpos($preVariable, 'protected') !== false) | |
| { | |
| $startPos = strpos($line, 'protected'); | |
| $newAccessor .= 'protected'; | |
| } | |
| elseif(strpos($preVariable, 'private') !== false) | |
| { | |
| $startPos = strpos($line, 'private'); | |
| $newAccessor .= 'private'; | |
| } | |
| else | |
| continue; | |
| if(strpos($preVariable, 'static') !== false) | |
| { | |
| $pos = strpos($line, 'static'); | |
| if($pos < $startPos) | |
| $startPos = $pos; | |
| $newAccessor .= ' ' . 'static'; | |
| } | |
| $type = str_replace(['public','protected','private','static',], '', $preVariable); | |
| $type = trim($type); | |
| if(strlen($type) > 0) | |
| { | |
| if(substr($type, 0,2) === '/*') | |
| $type = substr($type, 2); | |
| if(substr($type, -2) === '*/') | |
| $type = substr($type,0, strlen($type) -2); | |
| $type .= ' '; | |
| } | |
| $oldPreSpacing = substr($line, 0, $startPos); | |
| $reconstructedLine = $oldPreSpacing . $newAccessor . ' '. $type . $variable . $oldAssignations; | |
| if(trim($reconstructedLine) != trim($line)) | |
| { | |
| $line = $reconstructedLine; | |
| $lines[$index] = $line; | |
| } | |
| } | |
| } | |
| return implode(PHP_EOL, $lines); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment