Skip to content

Instantly share code, notes, and snippets.

@johnorourke
Last active April 16, 2020 11:41
Show Gist options
  • Save johnorourke/d1f86c7484d0601ae8db9ad806e090df to your computer and use it in GitHub Desktop.
Save johnorourke/d1f86c7484d0601ae8db9ad806e090df to your computer and use it in GitHub Desktop.
<?php
// namespace should be just the module eg. GetJohn\\PunchoutHub
const API_NS = 'Api\Data'; // path to api data models
const MODEL_NS = 'Model'; // path to models
if(!file_exists('composer.json'))
{
throw new \Exception('must be run from the root of your module');
}
$composerJson = json_decode(file_get_contents('composer.json'), true);
$namespaces = array_keys($composerJson['autoload']['psr-4']);
$moduleNs = array_shift($namespaces);
if(!$moduleNs)
{
throw new \Exception('namespace must be first in composer.json / autoload / psr-4');
}
$json = file_get_contents($argv[1]);
$object = json_decode($json, false);
if(gettype($object) != 'object')
{
throw new \Exception("Input file must be an object");
}
$baseName = preg_replace('/\..*/', '', basename($argv[1]));
const TYPE_MAP = [
'double' => 'float',
'boolean' => 'bool',
'integer' => 'int',
];
function writeInterface($object, $name)
{
global $namespace, $moduleNs;
$modelName = str_replace('_', '', ucwords($name, "_"));
$interfaceName = str_replace('_', '', ucwords($name, "_")) . 'Interface';
$interfacePrefix = '\\' . $moduleNs . API_NS . '\\';
$magicMethods = [];
$modelBody = '';
$interfaceBody = '';
foreach(get_object_vars($object) as $key => $value)
{
$type = gettype($value);
$type = isset(TYPE_MAP[$type]) ? TYPE_MAP[$type] : $type;
$phpType = $type;
switch($type)
{
case 'float':
case 'string':
case 'bool':
case 'int':
break;
case 'array':
if(count($value))
{
$type = gettype($value[0]);
$type = isset(TYPE_MAP[$type]) ? TYPE_MAP[$type] : $type;
if($type == 'object')
{
$singular = $name . '_' . preg_replace('/s$/', '', $key); // hack.. English only!
$type = $interfacePrefix . writeInterface($value[0], $singular);
}
} else {
$type = 'mixed';
}
$type .= '[]';
$phpType = 'array';
break;
case 'object':
$type = $interfacePrefix . writeInterface($value, $name . '_' . $key);
$phpType = $type;
break;
default:
throw new \Exception('invalid property type "'.$key.'": '.$type);
}
$interfaceType = $interfacePrefix .
$ucKey = str_replace('_', '', ucwords($key, "_"));
$interfaceBody .= "\t/**\n\t * @param $type $key\n\t * @return $interfaceName\n\t */\n\tpublic function set$ucKey($phpType \$value): $interfaceName;\n\n";
$modelBody .= "\t/**\n\t * @param $type $key\n\t * @return $interfacePrefix$interfaceName\n\t */\n\tpublic function set$ucKey($phpType \$value): $interfacePrefix$interfaceName\n\t{\n\t\t\$this->setData('$key', \$value);\n\t\treturn \$this;\n\t}\n\n";
$magicMethods[] = " * @method $interfaceName set$ucKey($type \$value)";
$interfaceBody .= "\t/**\n\t * @return $type $key\n\t */\n\tpublic function get$ucKey(): ?$phpType;\n\n";
$modelBody .= "\t/**\n\t * @return $type $key\n\t */\n\tpublic function get$ucKey(): ?$phpType\n\t{\n\t\treturn \$this->getData('$key');\n\t}\n\n";
$magicMethods[] = " * @method $type get$ucKey()";
}
$ifRet = '';
$ifRet .= "<?php\n\nnamespace $moduleNs" . API_NS . ";\n\n";
// $ifRet .= "/**\n" . implode("\n", $methods) . "\n */\n"; // magic methods version, doesnt pass API input validation
$ifRet .= "interface ".$interfaceName."\n{\n";
$ifRet .= $interfaceBody;
$ifRet .= "\n}\n";
$modelRet = '';
$modelRet .= "<?php\n\nnamespace $moduleNs" . MODEL_NS . ";\n\n";
// $modelRet .= "/**\n" . implode("\n", $methods) . "\n */\n"; // magic methods version, doesnt pass API input validation
$modelRet .= "class ".$modelName." extends \Magento\Framework\DataObject implements \\" . $moduleNs . API_NS . "\\$interfaceName\n{\n";
$modelRet .= $modelBody;
$modelRet .= "\n}\n";
file_put_contents(str_replace('\\', '/', './' . API_NS . '/' . "$interfaceName.php"), $ifRet);
file_put_contents(str_replace('\\', '/', './' . MODEL_NS . '/' . "$modelName.php"), $modelRet);
echo "<preference for=\"$moduleNs" . API_NS . "\\$interfaceName\" type=\"$moduleNs" . MODEL_NS . "\\$modelName\" />\n";
return $interfaceName;
}
echo "Created a " . writeInterface($object, $baseName) . "\n";
@johnorourke
Copy link
Author

I got fed up of writing setters and getters to satisfy the Magento REST API. This takes a JSON file and generates the Models with matching interfaces, including all setters and getters, using the types found in the json file. If it finds an empty array, it uses the type mixed[], otherwise it'll take the array type from the first array item.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment