From eb26f31ed6ba7bf8f65cf68df278fe70554d8e76 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Sat, 21 Dec 2024 18:59:55 -0300 Subject: [PATCH] Parsers --- app/src/Parser/Column.php | 108 ++++++++++++++++++++++++++++++++++ app/src/Parser/Constraint.php | 44 ++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 app/src/Parser/Column.php create mode 100644 app/src/Parser/Constraint.php diff --git a/app/src/Parser/Column.php b/app/src/Parser/Column.php new file mode 100644 index 0000000..fb1f91e --- /dev/null +++ b/app/src/Parser/Column.php @@ -0,0 +1,108 @@ +addColumn('{$this->getName()}', '{$this->getType()}'{$this->getOptions()})"; + } + + protected int $ini; + protected int $end; + protected array $parts; + protected array $options; + + protected function getName(): string + { + $ini = $this->getIni(); + $end = $this->getEnd(); + return substr($this->line, $ini, $end - $ini); + } + protected function getType(): string + { + $parts = $this->getParts(); + $type = array_shift($parts); + + if (str_contains($type, '(')) { + list($type, $length) = explode('(', $type); + $this->options []= "'length' => " . rtrim($length, ')'); + } + return match($type) { + 'int' => 'integer', + 'tinyint' => 'boolean', + 'varchar' => 'string', + default => $type + }; + } + protected function getOptions(): string + { + $parts = $this->getParts(); + array_shift($parts); + $validOptions = [ + 'default' => function($parts) { + $i = array_search('default', array_map(function($part) {return strtolower($part);}, $parts)); + return ['default', $parts[$i + 1]]; + }, + 'null' => function($parts) { + $value = true; + $i = array_search('null', array_map(function($part) {return strtolower($part);}, $parts)); + if (key_exists($i - 1, $parts) and strtolower($parts[$i - 1]) === 'not') { + $value = false; + } + return ['null', $value]; + }, + 'unsigned' => function($parts) { + return ['signed', false]; + }, + 'auto_increment' => function($parts) { + return ['auto_increment', true]; + } + ]; + foreach ($validOptions as $validOption => $callable) { + if (str_contains(strtolower($this->line), $validOption)) { + list($option, $value) = $callable($parts); + if (strtolower($value) === 'null') { + $value = 'null'; + } + if ($value !== 'null' and !is_bool($value) and !ctype_digit($value)) { + $value = trim($value, "'"); + $value = "'{$value}'"; + } + if (is_bool($value)) { + $value = $value ? 'true' : 'false'; + } + $this->options []= "'{$option}' => {$value}"; + } + } + if (count($this->options) === 0) { + return ''; + } + return ', [' . implode(', ', $this->options) . ']'; + } + protected function getIni(): int + { + if (!isset($this->ini)) { + $this->ini = strpos($this->line, '`') + 1; + } + return $this->ini; + } + protected function getEnd(): int + { + if (!isset($this->end)) { + $this->end = strpos($this->line, '`', $this->getIni()); + } + return $this->end; + } + protected function getParts(): array + { + if (!isset($this->parts)) { + $this->parts = explode(' ', trim(substr($this->line, $this->getEnd() + 1), ' ,')); + } + return $this->parts; + } +} \ No newline at end of file diff --git a/app/src/Parser/Constraint.php b/app/src/Parser/Constraint.php new file mode 100644 index 0000000..f123518 --- /dev/null +++ b/app/src/Parser/Constraint.php @@ -0,0 +1,44 @@ +addForeignKey({$this->getColumns()}, '{$this->getTable()}', {$this->getReferences()}, ['delete' => 'cascade', 'update' => 'cascade'])"; + } + + protected function getColumns(): string + { + $ini = strpos(strtolower($this->line), 'foreign key') + strlen('FOREIGN KEY '); + $ini = strpos($this->line, '(', $ini) + 1; + $end = strpos(strtolower($this->line), ' references', $ini + 1) - strlen(')'); + return $this->getNames($ini, $end); + } + protected function getTable(): string + { + $ini = strpos(strtolower($this->line), 'references') + strlen('REFERENCES ') + 1; + $end = strpos($this->line, '`', $ini + 1); + return substr($this->line, $ini, $end - $ini); + } + protected function getReferences(): string + { + $ini = strpos($this->line, '(', strpos(strtolower($this->line), 'references')) + 1; + $end = strpos($this->line, ')', $ini); + return $this->getNames($ini, $end); + } + protected function getNames($ini, $end): string + { + $names = substr($this->line, $ini, $end - $ini); + if (!str_contains($names, ',')) { + return str_replace('`', "'", $names); + } + $names = explode(', ', $names); + $columns = array_map(function($name) {return str_replace('`', "'", $name);}, $names); + return '[' . implode(', ', $columns) . ']'; + } +} \ No newline at end of file