egroupware/doc/js2ts.php
2021-06-15 13:34:03 +02:00

191 lines
4.6 KiB
PHP
Executable File

#!/usr/bin/env php
<?php
/**
* EGroupware - modify our old JS inheritance to TypeScript
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @author Ralf Becker <rb@egroupware.org>
* @copyright 2020 by Ralf Becker <rb@egroupware.org>
*/
if (PHP_SAPI !== 'cli') // security precaution: forbit calling as web-page
{
die('<h1>fix_api.php must NOT be called as web-page --> exiting !!!</h1>');
}
// raw replacements
$replace = array(
'/^app.classes.([a-z0-9_]+)(\s*=\s*AppJS.extend)\(.*^}\);/misU' =>
function($matches) {
return strtr($matches[0], [
'app.classes.'.$matches[1].$matches[2].'(' => 'class '.ucfirst($matches[1]).'App extends EgwApp',
"\n});" => "\n}\n\napp.classes.$matches[1] = ".ucfirst($matches[1])."App;"
]);
},
"/^\tappname:\s*'([^']+)',/m" => "\treadonly appname = '$1';",
"/^\t([^: ,;(\t]+?):\s*([^()]+?),/m" => "\t\$1 : any = $2;",
"/^\t([^:\n]+):\s*function\s*\(.*this._super.(apply|call)\(/msU" =>
function($matches) {
return str_replace('this._super',
$matches[1] === 'init' ? 'super' : 'super.'.$matches[1], $matches[0]);
},
"/^\t([^:\n]+):\s*function\s*\(/m" => function($matches) {
return "\t".($matches[1] === 'init' ? 'constructor' : $matches[1]).'(';
},
// TS does not like to call parent constructor with super.apply(this, arguments) and we dont have arguments ...
'/\tsuper.apply\(this, *arguments\)/' => "\tsuper()",
"/^\t},$/m" => "\t}",
'/^ \* @version \$Id[^$]*\$\n/m' => '',
'#^ \* @link http://www.egroupware.org#m' => ' * @link: https://www.egroupware.org',
);
/**
* Add boilerplate for app.js files after header
*
* @param $app
* @param $content
* @return string
*/
function app_js_add($app, $content)
{
return preg_replace('#^(/\*\*.*\n\ \*/)#Us', <<<EOF
$1
/*egw:uses
/api/js/jsapi/egw_app.js
*/
import { EgwApp } from '../../api/js/jsapi/egw_app';
EOF
, $content);
}
/**
* Convert JavaScript to TypeScript
*
* @param string $file filename
* @param boolean $dry_run =false true: only echo fixed file, not fix it
* @return boolean false on error
*/
function convert($file, $dry_run=false)
{
global $prog, $replace;
if (basename($file) == $prog) return true; // dont fix ourself ;-)
if (($content = $content_in = file_get_contents($file)) === false) return false;
$replace_callbacks = array_filter($replace, 'is_callable');
$replace_strings = array_filter($replace, 'is_string');
$content = preg_replace(array_keys($replace_strings), array_values($replace_strings),
preg_replace_callback_array($replace_callbacks, $content));
// add app.js spezific boilerplate
if (preg_match('#/([^/]+)/js/app(\.old)?\.js$#', realpath($file), $matches))
{
$content = app_js_add($matches[1], $content);
}
if ($content == $content_in) return true; // nothing changed
if ($dry_run)
{
echo $content;
}
else
{
$ret = file_put_contents($new_file=preg_replace('/\.js$/', '.ts', $file), $content) === false ? -1 : 0;
//system('/usr/bin/php -l '.$file.'.new', $ret);
system('/usr/bin/diff -u '.$file.' '.$new_file);
return !$ret;
}
return true;
}
/**
* Loop recursive through directory and call fix_api for each php file
*
* @param string $dir
* @param boolean $dry_run =false true: only echo fixed file, not fix it
* @return boolean false on error
*/
function convert_recursive($dir, $dry_run=false)
{
if (!is_dir($dir)) return false;
foreach(scandir($dir) as $file)
{
if ($file == '.' || $file == '..') continue;
if (is_dir($dir.'/'.$file))
{
convert_recursive($dir.'/'.$file, $dry_run);
}
elseif(substr($file,-3) == '.js')
{
echo "\r".str_repeat(' ',100)."\r".$dir.'/'.$file.': ';
convert($dir.'/'.$file, $dry_run);
}
}
echo "\r".str_repeat(' ',100)."\r";
return true;
}
/**
* Give usage
*
* @param string $error =null
*/
function usage($error=null)
{
global $prog;
echo "Usage: $prog [-h|--help] [-d|--dry-run] file(s) or dir(s)\n\n";
if ($error) echo $error."\n\n";
exit($error ? 1 : 0);
}
$args = $_SERVER['argv'];
$prog = basename(array_shift($args));
if (!$args) usage();
$dry_run = false;
while(($arg = array_shift($args)) && $arg[0] == '-')
{
switch($arg)
{
case '-h':
case '--help':
usage();
break;
case '-d':
case '--dry-run':
$dry_run = true;
break;
default:
if ($args) // not last argument
{
usage("Unknown argument '$arg'!");
}
break 2;
}
}
do {
if (!file_exists($arg)) usage("Error: $arg not found!");
if (!is_dir($arg))
{
convert($arg, $dry_run);
}
else
{
convert_recursive($arg, $dry_run);
}
}
while(($arg = array_shift($args)));