/** * Fetch module info from provided path. * * (object) info * ->id * ->path * ->name * ->description * ->version * ->dependencies * ->build * * @param string $path Module path * * @return object|false Module info **/ public static function fetchModuleInfo($path) { /* $id; $path; $name; $description; $version; $dependencies; */ if ($path[0] != '/' && $path[0] != '.') { // 相对路径 $npath = getcwd() . '/modules/' . $path; $path = is_dir($npath) ? $npath : $_SERVER['GINI_MODULE_BASE_PATH'] . '/' . $path; } // $path = realpath($path); $info_script = $path . '/gini.json'; if (!file_exists($info_script)) { return false; } $info = (object) @json_decode(@file_get_contents($info_script), true); if (!is_array($info->dependencies)) { $info->dependencies = []; } if (!$info->id) { $info->id = \Gini\File::relativePath($path, $_SERVER['GINI_MODULE_BASE_PATH']); } if ($info->id != 'gini' && !isset($info->dependencies['gini'])) { $info->dependencies['gini'] = '*'; } $info->path = $path; return $info; }
public function actionModules($args) { foreach (\Gini\Core::$MODULE_INFO as $name => $info) { if (!$info->error) { $rPath = \Gini\File::relativePath($info->path, APP_PATH); if ($rPath[0] == '.') { $rPath = \Gini\File::relativePath($info->path, dirname(SYS_PATH)); if ($rPath[0] == '.') { $rPath = '@/' . \Gini\File::relativePath($info->path, $_SERVER['GINI_MODULE_BASE_PATH']); } else { $rPath = '!/' . $rPath; } } } printf("%s %s %s %s %s[0m\n", $info->error ? "[31m" : '', $this->_strPad($name, 30, ' '), $this->_strPad($info->version, 15, ' '), $this->_strPad($info->name, 30, ' '), $info->error ?: $rPath); } }
public function actionFormat($argv) { if (count($argv) < 1) { exit("usage: [1;34mgini i18n format[0m <locales>\n"); } $appname = APP_ID; foreach ($argv as $locale) { $lodir = I18N_PATH . '/' . $locale . '/LC_MESSAGES'; \Gini\File::ensureDir($lodir); $pofile = $lodir . '/' . $appname . '.po'; $paths = \Gini\Core::filePaths(RAW_DIR . '/l10n/' . $locale . '.po'); echo "merge: {$appname}.po\n"; $cmd = sprintf('msgcat -o %1$s %2$s', escapeshellarg($pofile), implode(' ', array_map('escapeshellarg', $paths))); passthru($cmd); $mofile = $lodir . '/' . $appname . '.mo'; echo "compile: {$appname}.po => {$appname}.mo\n"; $cmd = sprintf('msgfmt -o %s %s', escapeshellarg($mofile), escapeshellarg($pofile)); passthru($cmd); } }
public static function clean() { echo "Cleaning Cache...\n"; \Gini\File::removeDir(APP_PATH . '/cache'); echo " [32mdone.[0m\n"; }
public function actionClean($args) { if (!file_exists(APP_PATH . '/web')) { die("You don't need to clean web dir since it does not exists.\n"); } echo "Removing Web Directory...\n"; \Gini\File::removeDir(APP_PATH . '/web'); echo " [32mdone.[0m\n"; }
public static function exception($e) { $message = $e->getMessage(); $file = $e->getFile(); foreach (\Gini\Core::$MODULE_INFO as $info) { if (0 == strncmp($file, $info->path, strlen($info->path))) { $file = "[{$info->id}] " . \Gini\File::relativePath($file, $info->path); break; } } $line = $e->getLine(); printf("[31m[E] [1m%s[0m\n", $message); error_log(sprintf('[E] %s (%s:%d)', $message, $file, $line)); $trace = array_slice($e->getTrace(), 1, 3); foreach ($trace as $n => $t) { $file = $t['file']; foreach (\Gini\Core::$MODULE_INFO as $info) { if (0 == strncmp($file, $info->path, strlen($info->path))) { $file = "[{$info->id}] " . \Gini\File::relativePath($file, $info->path); break; } } error_log(sprintf('%3d. %s%s() in (%s:%d)', $n + 1, $t['class'] ? $t['class'] . '::' : '', $t['function'], $file, $t['line'])); } }
public function actionInstall($argv) { count($argv) > 0 || APP_ID != 'gini' or die("Usage: gini index install <module> <version>\n\n"); if (!class_exists('\\Sabre\\DAV\\Client')) { self::_loadGiniComposer(); } list($options, $headers) = self::_davOptionsAndHeaders(); $client = new \Sabre\DAV\Client($options); $installedModules = []; $installModule = function ($module, $versionRange, $targetDir, $isApp = false) use(&$installModule, &$installedModules, &$client, &$options, &$headers) { if (isset($installedModules[$module])) { $info = $installedModules[$module]; $v = new \Gini\Version($info->version); // if installed version is incorrect, abort the operation. if (!$v->satisfies($versionRange)) { die("Conflict detected on {$module}! Installed: {$v->fullVersion} Expecting: {$versionRange}\n"); } } else { // try to see if we've already got it somewhere if (isset(\Gini\Core::$MODULE_INFO[$module])) { $info = \Gini\Core::$MODULE_INFO[$module]; $v = new \Gini\Version($info->version); if ($v->satisfies($versionRange)) { $matched = $v; } } // fetch index.json echo "Fetching catalog of {$module}...\n"; while (true) { $response = $client->request('GET', $module . '/index.json', null, $headers); if ($response['statusCode'] == 401 && isset($response['headers']['www-authenticate'])) { // Authentication required // prompt user/password and try again if (!isset($options['userName'])) { list($options, $headers) = self::_davOptionsAndHeaders(true); $client = new \Sabre\DAV\Client($options); continue; } $matched or die("Access denied for fetch catalog of {$module} .\n"); $response = null; } elseif ($response['statusCode'] < 200 || $response['statusCode'] > 206) { $matched or die('Error: ' . $response['statusCode'] . "\n"); $response = null; } break; } if ($response) { $indexInfo = (array) json_decode($response['body'], true); // find latest match version foreach ($indexInfo as $version => $foo) { $v = new \Gini\Version($version); if ($v->satisfies($versionRange)) { if ($matched) { if ($matched->compare($v) > 0) { continue; } } $matched = $v; } } } if (!$matched) { die("Failed to locate required version!\n"); } if (!$info || $matched->fullVersion != $info->version) { $version = $matched->fullVersion; $info = (object) $indexInfo[$version]; $tarPath = "{$module}/{$version}.tgz"; echo "Downloading {$module} from {$tarPath}...\n"; while (true) { $response = $client->request('GET', $tarPath, null, $headers); if ($response['statusCode'] == 401 && isset($response['headers']['www-authenticate'])) { // Authentication required // prompt user/password and try again if (!isset($options['userName'])) { list($options, $headers) = self::_davOptionsAndHeaders(true); $client = new \Sabre\DAV\Client($options); continue; } die("Access denied for fetch catalog of {$module}.\n"); } if ($response['statusCode'] < 200 || $response['statusCode'] > 206) { die('Error: ' . $response['statusCode'] . "\n"); } break; } if ($isApp) { $modulePath = $targetDir; } else { $modulePath = "{$targetDir}/modules/{$module}"; } if (is_dir($modulePath) && file_exists($modulePath)) { \Gini\File::removeDir($modulePath); } \Gini\File::ensureDir($modulePath); echo "Extracting {$module}...\n"; $ph = popen('tar -zx -C ' . escapeshellcmd($modulePath), 'w'); if (is_resource($ph)) { fwrite($ph, $response['body']); pclose($ph); } } else { $version = $info->version; echo "Found local copy of {$module}/{$version}.\n"; } $installedModules[$module] = $info; echo "\n"; } if ($info) { foreach ((array) $info->dependencies as $m => $r) { if ($m == 'gini') { continue; } $installModule($m, $r, $targetDir, false); } } }; if (count($argv) > 0) { // e.g. gini install xxx $module = $argv[0]; if (count($argv) > 1) { $versionRange = $argv[1]; } else { $versionRange = readline('Please provide a version constraint for the ' . $module . ' requirement:'); } $installModule($module, $versionRange, $_SERVER['PWD'] . "/{$module}", true); } else { // run: gini install, then you should be in module directory if (APP_ID != 'gini') { // try to install its dependencies $app = \Gini\Core::moduleInfo(APP_ID); $installedModules[APP_ID] = $app; $installModule(APP_ID, $app->version, APP_PATH, true); } } }
public function actionCreate($args) { count($args) > 0 or die("Usage: gini ci phpunit create <Class\\For\\Test>\n"); $class = $args[0]; preg_match('|^[\\w\\\\]+$|', $class) or die("Usage: gini ci phpunit create <Class\\For\\Test>\n"); echo "Creating {$class}\n"; $pos = strrpos($class, '\\'); if ($pos === false) { $namespace = ''; $name = $class; } else { $namespace = '\\' . trim(substr($class, 0, $pos), '\\'); $name = trim(substr($class, $pos + 1), '\\'); } $content = <<<TEMPL <?php namespace Gini\\PHPUnit{$namespace}; require_once __DIR__ . '/../gini.php'; class {$name} extends \\Gini\\PHPUnit\\CLI { public function testHello() { \$this->assertTrue(false, "PLEASE IMPLEMENT THIS!"); } } TEMPL; $dir = APP_PATH . '/tests/unit'; if ($namespace) { $dir .= strtr($namespace, '\\', '/'); } if (!file_exists($dir . '/' . $name . '.php')) { \Gini\File::ensureDir($dir); file_put_contents($dir . '/' . $name . '.php', $content); echo " [32mdone.[0m\n"; } else { echo " [31mfile exists![0m\n"; } }
public static function exception($e) { $message = $e->getMessage(); if ($message) { $file = $e->getFile(); foreach (\Gini\Core::$MODULE_INFO as $info) { if (0 == strncmp($file, $info->path, strlen($info->path))) { $file = "[{$info->id}] " . \Gini\File::relativePath($file, $info->path); break; } } $line = $e->getLine(); error_log(sprintf('ERROR %s', $message)); $trace = array_slice($e->getTrace(), 1, 5); foreach ($trace as $n => $t) { $file = $t['file']; foreach (\Gini\Core::$MODULE_INFO as $info) { if (0 == strncmp($file, $info->path, strlen($info->path))) { $file = "[{$info->id}] " . \Gini\File::relativePath($file, $info->path); break; } } error_log(sprintf(' %d) %s%s() in %s on line %d', $n + 1, $t['class'] ? $t['class'] . '::' : '', $t['function'], $file, $t['line'])); } } if (PHP_SAPI != 'cli') { while (@ob_end_clean()) { } //清空之前的所有显示 header('HTTP/1.1 500 Internal Server Error'); } }
public function actionUpgradeId() { // ORM required class map. if (!isset($GLOBALS['gini.class_map'])) { echo "[31mYou need to run [1m\"gini cache class\"[0;31m before upgrade ORM id.[0m\n"; return; } // enumerate orms echo "Updating database structures according ORM definition...\n"; $orm_dirs = \Gini\Core::pharFilePaths(CLASS_DIR, 'Gini/ORM'); foreach ($orm_dirs as $orm_dir) { if (!is_dir($orm_dir)) { continue; } \Gini\File::eachFilesIn($orm_dir, function ($file) use($orm_dir) { $oname = preg_replace('|.php$|', '', $file); if ($oname == 'Object') { return; } $class_name = '\\Gini\\ORM\\' . str_replace('/', '\\', $oname); // Check if it is abstract class $rc = new \ReflectionClass($class_name); if ($rc->isAbstract()) { return; } $o = \Gini\IoC::construct($class_name); // some object might not have database backend $db = $o->db(); if (!$db) { return; } printf(" %s\n", $oname); $structure = $o->structure(); foreach ($structure as $field => $option) { if (isset($option['object'])) { $db->query('UPDATE :table SET :field=NULL WHERE :field=0', [':table' => $o->tableName(), ':field' => $field . '_id']); } } }); } echo " [32mdone.[0m\n"; }
public function actionExport($args) { printf("Exporting ORM structures...\n\n"); $orm_dirs = \Gini\Core::pharFilePaths(CLASS_DIR, 'Gini/ORM'); foreach ($orm_dirs as $orm_dir) { if (!is_dir($orm_dir)) { continue; } \Gini\File::eachFilesIn($orm_dir, function ($file) use($orm_dir) { $oname = strtolower(preg_replace('|.php$|', '', $file)); if ($oname == 'object') { return; } $class_name = '\\Gini\\ORM\\' . str_replace('/', '\\', $oname); // Check if it is abstract class $rc = new \ReflectionClass($class_name); if ($rc->isAbstract()) { return; } printf(" %s\n", $oname); $o = \Gini\IoC::construct($class_name); $structure = $o->structure(); // unset system fields unset($structure['id']); unset($structure['_extra']); $i = 1; $max = count($structure); foreach ($structure as $k => $v) { if ($i == $max) { break; } printf(" ├─ %s (%s)\n", $k, implode(',', array_map(function ($k, $v) { return $v ? "{$k}:{$v}" : $k; }, array_keys($v), $v))); ++$i; } printf(" └─ %s (%s)\n\n", $k, implode(',', array_map(function ($k, $v) { return $v ? "{$k}:{$v}" : $k; }, array_keys($v), $v))); }); } }