Last active
April 16, 2020 11:41
-
-
Save johnorourke/d1f86c7484d0601ae8db9ad806e090df to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.