#!/usr/bin/env php <?php use Symfony\Component\Yaml\Yaml; define('ROOT', dirname(__DIR__)); require ROOT . '/vendor/autoload.php'; const types = [ 'blob' => '', 'bool' => 'bool', 'char' => 'string', 'datetime' => '\DateTimeInterface', 'timestamp' => '\DateTimeInterface', 'html' => 'string', 'int' => 'int', 'numeric' => 'float', 'serial' => 'int', 'text' => 'string', 'varchar' => 'string', 'phone_number' => 'PhoneNumber', ]; $files = array_merge(glob(ROOT . '/src/Entity/*.php'), array_merge(glob(ROOT . '/components/*/Entity/*.php'), glob(ROOT . '/plugins/*/Entity/*.php'))); $classes = []; $nullable_no_defaults_warning = []; foreach ($files as $file) { require_once $file; $declared = get_declared_classes(); foreach ($declared as $dc) { if (preg_match('/(App|(Component|Plugin)\\\\[^\\\\]+)\\\\Entity/', $dc) && !in_array($dc, $classes)) { $class = $dc; $classes[] = $class; break; } } $no_ns_class = preg_replace('/.*?\\\\/', '', $class); $schema = $class::schemaDef(); $fields = array_keys($schema['fields']); $fields_code = []; $methods_code = []; foreach ($fields as $field) { $field_schema = $schema['fields'][$field]; $nullable = ($field_schema['not null'] ?? false) ? '' : '?'; $type = types[$field_schema['type']]; $type = $type !== '' ? $nullable . $type : $type; $method_name = str_replace([' ', 'actor'], ['', 'Actor'], ucwords(str_replace('_', ' ', $field))); $length = $field_schema['length'] ?? null; $field_setter = "\${$field}"; if (\is_int($length)) { if ($nullable === '?') { $field_setter = "\is_null(\${$field}) ? null : \mb_substr(\${$field}, 0, $length)"; } else { $field_setter = "\mb_substr(\${$field}, 0, $length)"; } } if (($nullable === '?' || \array_key_exists('default', $field_schema)) && $type != '\DateTimeInterface') { if (!\array_key_exists('default', $field_schema)) { $nullable_no_defaults_warning[] = "{$class}::{$field}"; } $default = $field_schema['default'] ?? null; if (\is_string($default)) { $default = "'{$default}'"; } elseif (\is_null($default)) { $default = "null"; } elseif ($type === 'bool' || $type === '?bool') { $default = $default ? 'true' : 'false'; } $fields_code[] = " private {$type} \${$field} = {$default};"; } else { $fields_code[] = " private {$type} \${$field};"; } $methods_code[] = " public function set{$method_name}({$type} \${$field}): self" . "\n {\n \$this->{$field} = {$field_setter};\n return \$this;\n }" . "\n\n" . " public function get{$method_name}()" . ($type !== '' ? ": {$type}" : '') . "\n {\n return \$this->{$field};\n }" . "\n"; } $fields_code = implode("\n", $fields_code); $methods_code = implode("\n", $methods_code); $begin = '// {{{ Autocode'; $end = '// }}} Autocode'; $code = " {$begin} // @codeCoverageIgnoreStart {$fields_code} {$methods_code} // @codeCoverageIgnoreEnd {$end}"; foreach (['/\\//' => '\\/', '/ /' => '\\ '] as $from => $to) { $begin = preg_replace($from, $to, $begin); $end = preg_replace($from, $to, $end); } $in_file = file_get_contents($file); $out_file = preg_replace("%\\s*{$begin}.*{$end}%smu", $code, $in_file); file_put_contents($file, $out_file); } if (!empty($nullable_no_defaults_warning)) { echo "Warning: The following don't have a default value, but we're assigning it `null`. Doctrine might not like this, so update it\n"; foreach ($nullable_no_defaults_warning as $n) { echo " {$n}\n"; } }