whoami7 - Manager
:
/
home
/
kckglobal
/
www
/
portal
/
vendor
/
phpmyadmin
/
sql-parser
/
src
/
Tools
/
Upload File:
files >> //home/kckglobal/www/portal/vendor/phpmyadmin/sql-parser/src/Tools/ContextGenerator.php
<?php declare(strict_types=1); namespace PhpMyAdmin\SqlParser\Tools; use PhpMyAdmin\SqlParser\Token; use function array_filter; use function array_map; use function array_merge; use function array_slice; use function basename; use function count; use function dirname; use function file; use function file_put_contents; use function implode; use function ksort; use function preg_match; use function scandir; use function sort; use function sprintf; use function str_replace; use function str_split; use function strlen; use function strstr; use function strtoupper; use function substr; use function trim; use const ARRAY_FILTER_USE_KEY; use const SORT_STRING; /** * Used for context generation. */ class ContextGenerator { /** * Labels and flags that may be used when defining keywords. * * @var array<string, int> */ public static $LABELS_FLAGS = [ '(R)' => Token::FLAG_KEYWORD_RESERVED, '(D)' => Token::FLAG_KEYWORD_DATA_TYPE, '(K)' => Token::FLAG_KEYWORD_KEY, '(F)' => Token::FLAG_KEYWORD_FUNCTION, ]; /** * Documentation links for each context. * * @var array<string, string> */ public static $LINKS = [ 'MySql50000' => 'https://dev.mysql.com/doc/refman/5.0/en/keywords.html', 'MySql50100' => 'https://dev.mysql.com/doc/refman/5.1/en/keywords.html', 'MySql50500' => 'https://dev.mysql.com/doc/refman/5.5/en/keywords.html', 'MySql50600' => 'https://dev.mysql.com/doc/refman/5.6/en/keywords.html', 'MySql50700' => 'https://dev.mysql.com/doc/refman/5.7/en/keywords.html', 'MySql80000' => 'https://dev.mysql.com/doc/refman/8.0/en/keywords.html', 'MySql80100' => 'https://dev.mysql.com/doc/refman/8.1/en/keywords.html', 'MySql80200' => 'https://dev.mysql.com/doc/refman/8.2/en/keywords.html', 'MySql80300' => 'https://dev.mysql.com/doc/refman/8.3/en/keywords.html', 'MySql80400' => 'https://dev.mysql.com/doc/refman/8.4/en/keywords.html', 'MySql90000' => 'https://dev.mysql.com/doc/refman/9.0/en/keywords.html', 'MySql90100' => 'https://dev.mysql.com/doc/refman/9.1/en/keywords.html', 'MariaDb100000' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb100100' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb100200' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb100300' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb100400' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb100500' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb100600' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb100700' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb100800' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb100900' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb101000' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb101100' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb110000' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb110100' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb110200' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb110300' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb110400' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb110500' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb110600' => 'https://mariadb.com/kb/en/reserved-words/', 'MariaDb110700' => 'https://mariadb.com/kb/en/reserved-words/', ]; /** * Reversed const <=> int from {@see Token} class to write the constant name instead of its value. * * @var array<int, string> */ private static $typesNumToConst = [ 1 => 'Token::FLAG_KEYWORD', 2 => 'Token::FLAG_KEYWORD_RESERVED', 4 => 'Token::FLAG_KEYWORD_COMPOSED', 8 => 'Token::FLAG_KEYWORD_DATA_TYPE', 16 => 'Token::FLAG_KEYWORD_KEY', 32 => 'Token::FLAG_KEYWORD_FUNCTION', ]; /** * The template of a context. * * Parameters: * 1 - name * 2 - class * 3 - link * 4 - keywords array */ public const TEMPLATE = <<<'PHP' <?php declare(strict_types=1); namespace PhpMyAdmin\SqlParser\Contexts; use PhpMyAdmin\SqlParser\Context; use PhpMyAdmin\SqlParser\Token; /** * Context for %1$s. * * This class was auto-generated from tools/contexts/*.txt. * Use tools/run_generators.sh for update. * * @see %3$s */ class %2$s extends Context { /** * List of keywords. * * The value associated to each keyword represents its flags. * * @see Token * * @var array<string,int> * @phpstan-var non-empty-array<non-empty-string,Token::FLAG_KEYWORD_*|int> */ public static $KEYWORDS = [ %4$s ]; } PHP; /** * Sorts an array of words. * * @param array<int, list<string>> $arr * * @return array<int, list<string>> */ public static function sortWords(array &$arr) { ksort($arr); foreach ($arr as &$words) { sort($words, SORT_STRING); } return $arr; } /** * Reads a list of words and sorts it by type, length and keyword. * * @param list<string> $files * * @return array<int, list<string>> */ public static function readWords(array $files) { /** @psalm-var list<string> $words */ $words = []; foreach ($files as $file) { $words = array_merge($words, file($file)); } /** @var array<string, int> $types */ $types = []; for ($i = 0, $count = count($words); $i !== $count; ++$i) { $value = trim($words[$i]); if ($value === '') { continue; } $type = Token::FLAG_KEYWORD; // Reserved, data types, keys, functions, etc. keywords. foreach (static::$LABELS_FLAGS as $label => $flags) { if (strstr($value, $label) === false) { continue; } $type |= $flags; $value = trim(str_replace($label, '', $value)); } // Composed keyword. if (strstr($value, ' ') !== false) { $type |= Token::FLAG_KEYWORD_RESERVED; $type |= Token::FLAG_KEYWORD_COMPOSED; } $value = strtoupper($value); if (! isset($types[$value])) { $types[$value] = $type; } else { $types[$value] |= $type; } } // Prepare an array in a way to sort by type, then by word. $ret = []; foreach ($types as $word => $type) { $ret[$type][] = $word; } return static::sortWords($ret); } /** * Prints an array of a words in PHP format. * * @param array<int, list<string>> $words the list of words to be formatted */ public static function printWords(array $words): string { $ret = ''; foreach ($words as $type => $wordsByType) { foreach ($wordsByType as $word) { $ret .= sprintf(" '%s' => %s,\n", $word, self::translateIntTypeToTextConstant($type)); } } return $ret; } private static function translateIntTypeToTextConstant(int $type): string { $matchingFlags = array_filter( self::$typesNumToConst, static function (int $num) use ($type): bool { return ($type & $num) !== 0; }, ARRAY_FILTER_USE_KEY ); return implode(' | ', $matchingFlags); } /** * Generates a context's class. * * @param array<string, string|array<int, list<string>>> $options the options for this context * @psalm-param array{ * name: string, * class: string, * link: string, * keywords: array<int, list<string>> * } $options * * @return string */ public static function generate($options) { $options['keywords'] = static::printWords($options['keywords']); return sprintf(self::TEMPLATE, $options['name'], $options['class'], $options['link'], $options['keywords']); } /** * Formats context name. * * @param string $name name to format * * @return string */ public static function formatName($name) { /* Split name and version */ $parts = []; if (preg_match('/^(\D+)(\d+)$/', $name, $parts) === 0) { return $name; } /* Format name */ $base = $parts[1]; switch ($base) { case 'MySql': $base = 'MySQL'; break; case 'MariaDb': $base = 'MariaDB'; break; } /* Parse version to array */ $versionString = $parts[2]; if (strlen($versionString) % 2 === 1) { $versionString = '0' . $versionString; } $version = array_map('intval', str_split($versionString, 2)); /* Remove trailing zero */ if ($version[count($version) - 1] === 0) { $version = array_slice($version, 0, -1); } /* Create name */ return $base . ' ' . implode('.', $version); } /** * Builds a test. * * Reads the input file, generates the data and writes it back. * * @param string $input the input file * @param string $output the output directory * * @return void */ public static function build($input, $output) { /** * The directory that contains the input file. * * Used to include common files. * * @var string */ $directory = dirname($input) . '/'; /** * The name of the file that contains the context. */ $file = basename($input); /** * The name of the context. * * @var string */ $name = substr($file, 0, -4); /** * The name of the class that defines this context. * * @var string */ $class = 'Context' . $name; /** * The formatted name of this context. */ $formattedName = static::formatName($name); file_put_contents( $output . '/' . $class . '.php', static::generate( [ 'name' => $formattedName, 'class' => $class, 'link' => static::$LINKS[$name], 'keywords' => static::readWords( [ $directory . '_common.txt', $directory . '_functions' . $file, $directory . $file, ] ), ] ) ); } /** * Generates recursively all tests preserving the directory structure. * * @param string $input the input directory * @param string $output the output directory * * @return void */ public static function buildAll($input, $output) { $files = scandir($input); foreach ($files as $file) { // Skipping current and parent directories. // Skipping _functions* and _common.txt files if (($file[0] === '.') || ($file[0] === '_')) { continue; } // Skipping README.md if ($file === 'README.md') { continue; } // Building the context. echo sprintf("Building context for %s...\n", $file); static::build($input . '/' . $file, $output); } } }
Copyright ©2021 || Defacer Indonesia