123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- #!/usr/bin/env php
- <?php
- /*
- * This file is part of php-restcord.
- *
- * (c) Aaron Scherer <aequasi@gmail.com>
- *
- * This source file is subject to the license that is bundled
- * with this source code in the file LICENSE
- */
- function recursiveRemoveDirectory($directory)
- {
- foreach (glob("{$directory}/*") as $file) {
- if (is_dir($file)) {
- recursiveRemoveDirectory($file);
- } else {
- unlink($file);
- }
- }
- rmdir($directory);
- }
- $path = __DIR__.'/../src/Model';
- try {
- recursiveRemoveDirectory($path);
- } catch (\Exception $e) {
- }
- mkdir($path, 02775, true);
- $path = realpath($path);
- require __DIR__.'/../vendor/autoload.php';
- use gossi\codegen\generator\CodeGenerator;
- use gossi\codegen\model\PhpClass;
- use gossi\codegen\model\PhpMethod;
- use gossi\codegen\model\PhpProperty;
- use Symfony\Component\Console\Application;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- $loader = new Twig_Loader_Filesystem(__DIR__.'/../src/Resources/');
- $twig = new Twig_Environment($loader, ['debug' => true]);
- $twig->addExtension(new Twig_Extension_Debug());
- $license = <<<EOF
- <?php
- /*
- * Copyright 2017 Aaron Scherer
- *
- * This source file is subject to the license that is bundled
- * with this source code in the file LICENSE
- *
- * @package restcord/restcord
- * @copyright Aaron Scherer 2017
- * @license MIT
- */
- \n
- EOF;
- /** @noinspection PhpUnhandledExceptionInspection */
- (new Application('Build Model Classes', '1.0.0'))
- ->register('buildModelClasses')
- ->addArgument('version', InputArgument::REQUIRED, 'Version to build')
- ->setCode(
- function (InputInterface $input, OutputInterface $output) use ($twig, $license, $path) {
- $style = new \Symfony\Component\Console\Style\SymfonyStyle($input, $output);
- $style->title("Building Model Classes for: ".$input->getArgument('version'));
- $definition = \GuzzleHttp\json_decode(
- file_get_contents(
- __DIR__.'/../src/Resources/service_description-v'.$input->getArgument('version').'.json'
- ),
- true
- );
- $generator = new CodeGenerator();
- foreach ($definition['models'] as $resource => $models) {
- foreach ($models as $name => $model) {
- $resource = str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $resource)));
- $name = str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $name)));
- $class = new PhpClass();
- $class->setQualifiedName('RestCord\\Model\\'.ucwords($resource).'\\'.ucwords($name));
- $class->setDescription(ucwords($name)." Model");
- $class->setProperties(
- array_map(
- function (&$name, $property) use ($class, $resource, $model) {
- $optional = strpos($name, '?') !== false;
- $name = lcfirst(str_replace([' ', '?'], '', str_replace('-', '_', $name)));
- $prop = new PhpProperty($name);
- $prop->setType(normalizeType($name, $resource, $property).($optional ? "|null" : ""));
- $prop->setDescription($property['description']);
- if (isset($property['default'])) {
- $prop->setValue($property['default']);
- }
- return $prop;
- },
- array_keys($model['properties']),
- $model['properties']
- )
- );
- addTraits($class, $resource, $name);
- $constructor = new PhpMethod('__construct');
- $constructor->addSimpleParameter('content', 'array', null);
- $constructor->setBody(
- <<<EOF
- if (null === \$content) {
- return;
- }
-
- foreach (\$content as \$key => \$value) {
- \$key = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', \$key))));
- if (property_exists(\$this, \$key)) {
- \$this->{\$key} = \$value;
- }
- }
- EOF
- );
- $constructor->setVisibility('public');
- $class->setMethod($constructor);
- @mkdir($path.'/'.ucwords($resource), 02775, true);
- file_put_contents(
- $path.'/'.ucwords($resource).'/'.ucwords($name).'.php',
- $license.$generator->generate($class)
- );
- }
- }
- $style->success('Finished. Classes built in: '.realpath($path));
- }
- )
- ->getApplication()
- ->setDefaultCommand('buildModelClasses', true)
- ->run();
- function normalizeType(string $name, string $resource, array $property): string
- {
- $type = $property['type'];
- if ($name === 'user' && $resource === 'Guild') {
- $type = "user/user";
- }
- switch ($type) {
- default:
- if (strpos($type, '/') !== false || strpos($type, 'Array<') === 0) {
- $array = false;
- if (stripos($type, 'Array') !== false) {
- $array = true;
- $type = str_replace(['Array<', '>'], '', $type);
- }
- if ($type === 'snowflake') {
- return 'int[]';
- }
- $cls = "\\RestCord\\Model\\";
- $tmp = explode('/', $type);
- $cls .= ucwords($tmp[0])."\\";
- $clean = str_replace(['-object', '-'], ['', ' '], $tmp[1]);
- $clean = ucwords($clean);
- $clean = str_replace(' ', '', $clean);
- $fullClass = $cls.$clean.($array ? '[]' : '');
- $fullClass = mapBadDocs($fullClass);
- return $fullClass;
- }
- return $type;
- case 'array':
- if (strpos($property['description'], "ids") !== false) {
- return "int[]";
- }
- return "array";
- case 'ISO8601 timestamp':
- case 'ISO8601':
- return '\DateTimeImmutable';
- case 'datetime':
- return '\DateTime';
- case 'snowflake':
- case 'integer':
- case 'timestamp':
- return 'int';
- case 'object':
- return 'array';
- case 'boolean':
- return 'bool';
- }
- }
- function isTransformType(string $type): bool
- {
- $nonTransform = ['string', 'array'];
- return array_search($type, $nonTransform) === false;
- }
- function mapBadDocs(string $cls): string
- {
- switch ($cls) {
- case '\RestCord\Model\User\DmChannel':
- return '\RestCord\Model\Channel\DmChannel';
- case '\RestCord\Model\Channel\Invite':
- case '\RestCord\Model\Guild\Invite':
- return '\RestCord\Model\Invite\Invite';
- case '\RestCord\Model\Guild\GuildChannel':
- return '\RestCord\Model\Channel\GuildChannel';
- case '\RestCord\Model\Guild\User':
- case '\RestCord\Model\Channel\User':
- return '\RestCord\Model\User\User';
- case 'ISO8601':
- case '\RestCord\Model\Channel\ISO8601':
- return '\DateTimeImmutable';
- default:
- return $cls;
- }
- return $cls;
- }
- function addTraits(PhpClass $class, string $resource, string $name)
- {
- if ($resource === 'User' && $name === 'User') {
- $class->addUseStatement(\RestCord\Traits\AvatarTrait::class)->addTrait("AvatarTrait");
- }
- if ($resource === 'Guild' && $name === 'Guild') {
- $class->addUseStatement(\RestCord\Traits\IconTrait::class)->addTrait("IconTrait");
- $class->addUseStatement(\RestCord\Traits\SplashTrait::class)->addTrait("SplashTrait");
- }
- }
|