Compare commits

...

5 Commits

Author SHA1 Message Date
Pavel Shevaev b7725936e6 Fixing check for required fields without @default
Publish PHP Package / docker (push) Successful in 6s Details
2025-04-08 18:31:28 +03:00
Pavel Shevaev 3275b0b724 Making junk check more efficient
Publish PHP Package / docker (push) Successful in 6s Details
2025-02-27 20:26:05 +03:00
Pavel Shevaev bd5a403d37 Adding support for assoc import/export
Publish PHP Package / docker (push) Successful in 6s Details
2025-02-27 19:59:39 +03:00
Pavel Shevaev c923ad53c5 Simplifying codegen for fields initialization
Publish PHP Package / docker (push) Successful in 6s Details
2025-02-25 17:04:27 +03:00
Pavel Shevaev c38e315e68 Adding check_junk optional support during normalization
Publish PHP Package / docker (push) Successful in 8s Details
2025-02-25 15:40:56 +03:00
3 changed files with 58 additions and 25 deletions

View File

@ -90,9 +90,9 @@ function _add_twig_support(\Twig\Environment $twig)
}
));
$twig->addFunction(new \Twig\TwigFunction('value2data',
function($val, \mtgType $type, $data, $tokens = array())
function($val, $name, \mtgType $type, $data, $tokens = array())
{
return value2data($val, $type, $data, $tokens);
return value2data($val, $name, $type, $data, $tokens);
}
));
$twig->addFunction(new \Twig\TwigFunction('data_normalize',
@ -261,24 +261,24 @@ function data2value(string $val, \mtgType $type, string $data, array $tokens, bo
}
//TODO: move it to template
function value2data(string $val, \mtgType $type, string $data, $tokens = array())
function value2data(string $val, string $name, \mtgType $type, string $data, $tokens = array(), $assoc = '$assoc')
{
$str = '';
if($type instanceof \mtgBuiltinType)
{
$str .= "{$data}[] = $val;\n";
$str .= "\metagen_php\array_set_value({$data}, {$assoc}, '$name', $val);\n";
}
else if($type instanceof \mtgMetaStruct)
{
if(array_key_exists('virtual', $tokens))
$str .= "{$data}[] = {$val}->export(true/*virtual*/);\n";
$str .= "\metagen_php\array_set_value({$data}, {$assoc}, '$name', {$val}->export(\$assoc, true/*virtual*/));\n";
else
$str .= "{$data}[] = {$val}->export();\n";
$str .= "\metagen_php\array_set_value({$data}, {$assoc}, '$name', {$val}->export(\$assoc));\n";
}
else if($type instanceof \mtgMetaEnum)
{
$str .= "{$data}[] = $val;\n";
$str .= "\metagen_php\array_set_value({$data}, {$assoc}, '$name', $val);\n";
}
else if($type instanceof \mtgArrType)
{
@ -289,9 +289,9 @@ function value2data(string $val, \mtgType $type, string $data, $tokens = array()
$str .= "else\n";
$str .= " foreach({$val} as \$arr_tmp_item__)\n";
$str .= " {\n";
$str .= value2data("\$arr_tmp_item__", $type->getValue(), "\$arr_tmp__", $tokens) . "\n";
$str .= value2data("\$arr_tmp_item__", '', $type->getValue(), "\$arr_tmp__", $tokens, 'false') . "\n";
$str .= " }\n";
$str .= "{$data}[] = \$arr_tmp__;\n";
$str .= "\metagen_php\array_set_value({$data}, \$assoc, '$name', \$arr_tmp__);\n";
}
else
throw new Exception("Unknown type '{$type->getName()}'");
@ -304,11 +304,10 @@ function is_null_str($default)
return is_string($default) && json_decode($default, true) === null;
}
function data_normalize($name, \mtgType $type, $buf, $dst, $tokens = array(), $tmp_val = '$tmp_val__')
function get_default_value_arg(\mtgType $type, array $tokens, bool &$has_default = true) : string
{
$str = '';
$default_value_arg = array_key_exists('default', $tokens) ? default_value($tokens['default']) : "null";
$has_default = array_key_exists('default', $tokens);
$default_value_arg = $has_default ? default_value($tokens['default']) : "null";
if($type instanceof \mtgMetaStruct)
{
@ -330,10 +329,25 @@ function data_normalize($name, \mtgType $type, $buf, $dst, $tokens = array(), $t
}
}
return $default_value_arg;
}
function data_normalize($name, \mtgType $type, $buf, $dst, $tokens = array(), $tmp_val = '$tmp_val__')
{
$str = '';
$has_default = false;
$default_value_arg = get_default_value_arg($type, $tokens, $has_default);
$str .= "\n";
if($name !== null)
{
$str .= "{$tmp_val} = {$buf}['{$name}'] ?? {$default_value_arg};\n";
if(!$has_default)
$str .= "if({$tmp_val} === null) throw new Exception(\"'{$name}' is missing\");\n";
$str .= "if(\$check_junk) unset({$buf}['{$name}']);\n";
}
if($type instanceof \mtgBuiltinType)
{
@ -350,16 +364,17 @@ function data_normalize($name, \mtgType $type, $buf, $dst, $tokens = array(), $t
if(array_key_exists('virtual', $tokens))
{
$str .= "\$vclass_id__ = \metagen_php\\val_uint32(\$tmp_sub_arr__['\$id'] ?? {$type->getClassId()});\n";
$str .= "if(\$check_junk) unset(\$tmp_sub_arr__['\$id']);\n";
$str .= "\$vclass__ = AutogenBundle::getClassName(\$vclass_id__);\n";
$str .= "if(!is_a(\$vclass__, '{$type->getName()}', true)) throw new Exception(\"'\$vclass__' is not subclass of '{$type->getName()}'\");\n";
$str .= "\$tmp_sub_mapped__ = array(\$vclass_id__);\n";
$str .= "call_user_func_array([\$vclass__, 'normalize'], array(&\$tmp_sub_arr__, &\$tmp_sub_mapped__));\n";
$str .= "call_user_func_array([\$vclass__, 'normalize'], array(&\$tmp_sub_arr__, &\$tmp_sub_mapped__, true, \$check_junk));\n";
$str .= "{$dst}[] = \$tmp_sub_mapped__;\n";
}
else
{
$str .= "\$tmp_sub_mapped__ = array();\n";
$str .= "{$type}::normalize(\$tmp_sub_arr__, \$tmp_sub_mapped__);\n";
$str .= "{$type}::normalize(\$tmp_sub_arr__, \$tmp_sub_mapped__, true, \$check_junk);\n";
$str .= "{$dst}[] = \$tmp_sub_mapped__;\n";
}
$str .= "}";

View File

@ -222,3 +222,11 @@ function val_blob($val)
return $val;
}
function check_junk_fields(array $data, array $FIELDS)
{
unset($data['$id']);
$diff = array_diff(array_keys($data), $FIELDS);
if($diff)
throw new Exception("Junk fields: " . json_encode(array_values($diff)));
}

View File

@ -58,9 +58,15 @@ class {{o.name}} {{o.parent ? 'extends ' ~ o.parent.name}}
return self::CLASS_ID;
}
function import(array &$data)
function import(array &$data, bool $assoc = false)
{
$this->_import($data, true);
if($assoc)
{
self::normalize($data, $normalized);
$this->_import($normalized, true);
}
else
$this->_import($data, true);
}
function _import(array &$data, $root = true) : int
@ -82,17 +88,18 @@ class {{o.name}} {{o.parent ? 'extends ' ~ o.parent.name}}
$FIELDS = self::CLASS_FIELDS();
throw new Exception($e->getMessage() . " < {$FIELDS[$IDX]} < ({{o.name}})");
}
return $IDX;
}
function export($virtual = false) : array
function export(bool $assoc = false, bool $virtual = false) : array
{
$data = array();
$this->_export($data, $virtual);
$this->_export($data, $assoc, $virtual);
return $data;
}
function _export(array &$data, $virtual = false)
function _export(array &$data, bool $assoc = false, $virtual = false)
{
if($virtual)
$data[] = $this->getClassId();
@ -100,7 +107,7 @@ class {{o.name}} {{o.parent ? 'extends ' ~ o.parent.name}}
{{_self.export_fields(o)}}
}
static function normalize(array &$data, array &$mapped, bool $root = true) : int
static function normalize(array &$data, array &$mapped, bool $check_junk = true, bool $root = true) : int
{
$IDX = -1;
@ -108,7 +115,7 @@ class {{o.name}} {{o.parent ? 'extends ' ~ o.parent.name}}
{
$IDX = 0;
{%- if o.parent ~%}
$IDX = parent::normalize($data, $mapped, false);
$IDX = parent::normalize($data, $mapped, $check_junk, false);
{%- endif ~%}
{%- for f in o.fields ~%}
@ -122,6 +129,9 @@ class {{o.name}} {{o.parent ? 'extends ' ~ o.parent.name}}
throw new Exception($e->getMessage() . " < {$FIELDS[$IDX]} < ({{o.name}})");
}
if($root && $check_junk && sizeof($data) > 0)
throw new Exception("Junk fields: " . implode(',', array_keys($data)));
return $IDX;
}
}
@ -217,7 +227,7 @@ array_merge(parent::CLASS_FIELDS_PROPS(),
[]
{%- elseif f.type is instanceof('\\mtgBuiltinType') ~%}
{%- if has_token(f, 'default') -%}
\metagen_php\val_{{f.type}}({{apply_value_filters(f.name, f.tokens, token(f, 'default')|default_value, false)}})
{{token(f, 'default')|default_value}}
{%- elseif f.type.isstring -%}
''
{%- else -%}
@ -253,10 +263,10 @@ array_merge(parent::CLASS_FIELDS_PROPS(),
{% macro export_fields(o) %}
{%- if o.parent -%}
parent::_export($data, false);
parent::_export($data, $assoc, false);
{%- endif -%}
{%- for f in o.fields ~%}
{{value2data('$this->'~f.name, f.type, '$data', f.tokens)}}
{{value2data('$this->'~f.name, f.name, f.type, '$data', f.tokens)}}
{%- endfor -%}
{% endmacro %}