Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion bin/model-gen
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#!/usr/bin/env php
<?php
declare(strict_types=1);


use Wave\SDK\ModelGenerator\Generator;
use Wave\SDK\ModelGenerator\Input\Swagger;

ini_set('display_errors', '1');
error_reporting(E_ALL | E_STRICT);
error_reporting(E_ALL);

if(!file_exists('bootstrap.php'))
sg_error("This file should be run from the application root");
Expand Down
17 changes: 14 additions & 3 deletions bin/schema-gen
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#!/usr/bin/env php
<?php
declare(strict_types=1);

use Wave\Config;
use Wave\SDK\SchemaGenerator\Output\Swagger;
use Wave\SDK\SchemaGenerator\Parser\FromRoutes;
use Symfony\Component\Yaml\Yaml;

ini_set('display_errors', '1');
error_reporting(E_ALL | E_STRICT);
error_reporting(E_ALL);

if(!file_exists('bootstrap.php'))
sg_error("This file should be run from the application root");
Expand Down Expand Up @@ -39,8 +40,18 @@ if (Config::get('app')->offsetExists('meta')){
$meta_info = Config::get('app')->meta->getArrayCopy();
}

if('' !== $git_path = trim(shell_exec('which git'))){
$meta_info['version'] = trim(shell_exec(sprintf('%s rev-parse --verify --short HEAD', $git_path)));
$git_path_output = shell_exec('command -v git');
if(is_string($git_path_output)){
$git_path = trim($git_path_output);
if($git_path !== ''){
$git_version_output = shell_exec(sprintf('%s rev-parse --verify --short HEAD', escapeshellarg($git_path)));
if(is_string($git_version_output)){
$git_version_output = trim($git_version_output);
if($git_version_output !== ''){
$meta_info['version'] = $git_version_output;
}
}
}
}

$output = $generator->generate($meta_info);
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"description": "Generates a schema file describing a wave app, then builds a PHP SDK from it",

"require": {
"phindmarsh/statham": "1.0.1",
"php": "^8.1",
"phindmarsh/statham": "1.0.3",
"twig/twig": "3.*"
},

Expand Down
49 changes: 32 additions & 17 deletions src/ModelGenerator/Generator.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

declare(strict_types=1);

namespace Wave\SDK\ModelGenerator;

Expand All @@ -9,16 +10,20 @@

class Generator {

private static $defaults = [];
private static array $defaults = [];

private $twig;
private Schema $input;

private array $args;

private Environment $twig;

public function __construct(Schema $input, array $args = []) {

$this->input = $input;
$this->args = array_merge(self::$defaults, $args);

$loader = new FilesystemLoader(__DIR__ . DS . 'Templates');
$loader = new FilesystemLoader(__DIR__ . DIRECTORY_SEPARATOR . 'Templates');
$this->twig = new Environment($loader, array(
'autoescape' => false,
'debug' => true
Expand All @@ -33,27 +38,30 @@ public function __construct(Schema $input, array $args = []) {

}));
$this->twig->addFilter(new TwigFilter('print_r', 'print_r'));
$this->twig->addFilter(new TwigFilter('explode', function($a, $d){
$this->twig->addFilter(new TwigFilter('explode', function($a, $d){
if ($a === null) {
return [""];
}

return explode($d, $a);
return explode($d, $a);
}));
}

public function generate($output_directory, $base_namespace, $base_model_class){
/**
* @return array<string, array<int, string>>
*/
public function generate(string $output_directory, string $base_namespace, string $base_model_class): array{

$schemas = $this->input->getSchemaNames();

$base_namespace = trim($base_namespace, '\\');
$output_directory = rtrim($output_directory, '/') . '/';
$output_directory = rtrim($output_directory, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;

$files_written = [];
foreach($schemas as $schema){

$namespace = $base_namespace . '\\' . ucfirst($schema);
$directory = $output_directory . ucfirst($schema) . DS;
$directory = $output_directory . ucfirst($schema) . DIRECTORY_SEPARATOR;

$files = $this->generateModelsFor($schema, $directory, $namespace, $base_model_class);
$files_written[$schema] = $files;
Expand All @@ -63,7 +71,10 @@ public function generate($output_directory, $base_namespace, $base_model_class){

}

public function generateModelsFor($schema, $base_directory, $base_namespace, $base_model_class){
/**
* @return array<int, string>
*/
public function generateModelsFor(string $schema, string $base_directory, string $base_namespace, string $base_model_class): array{

$models = $this->input->getModels($schema);
$meta = $this->input->getMeta($schema);
Expand All @@ -78,7 +89,7 @@ public function generateModelsFor($schema, $base_directory, $base_namespace, $ba
$ns = substr($class, 0, $split);
$class = substr($class, $split + 1);
$namespace = $base_namespace . '\\' . $ns;
$directory = $base_directory . str_replace('\\', '/', $ns) . DS;
$directory = $base_directory . str_replace('\\', DIRECTORY_SEPARATOR, $ns) . DIRECTORY_SEPARATOR;
}

$template_data = [
Expand All @@ -90,20 +101,22 @@ public function generateModelsFor($schema, $base_directory, $base_namespace, $ba
];

$base_model = $this->twig->render('base-model.phpt', $template_data);
$base_filename = sprintf('%sBase/%s.php', $directory, $class);
$base_filename = $directory . 'Base' . DIRECTORY_SEPARATOR . $class . '.php';
$this->createDirectory(dirname($base_filename));
$written = file_put_contents($base_filename, $base_model);

if($written > 0)
if($written > 0) {
$files_written[] = $base_filename;
}

$stub_filename = sprintf('%s%s.php', $directory, $class);
$stub_filename = $directory . $class . '.php';
if(!file_exists($stub_filename)){
$stub_model = $this->twig->render('stub-model.phpt', $template_data);
$written = file_put_contents($stub_filename, $stub_model);

if($written > 0)
if($written > 0) {
$files_written[] = $stub_filename;
}
}

}
Expand All @@ -112,15 +125,17 @@ public function generateModelsFor($schema, $base_directory, $base_namespace, $ba

}

private function createDirectory($directory){
private function createDirectory(string $directory): bool{
if(file_exists($directory) && !is_dir($directory)) {
throw new \RuntimeException("[{$directory}] already exists and is not a directory");
}
else if(!is_dir($directory)){
@mkdir($directory, 0770, true);
if(!is_dir($directory) || !is_writable($directory)) {
if(!@mkdir($directory, 0770, true) && !is_dir($directory)) {
throw new \RuntimeException("Failed to create directory [{$directory}]");
}
if(!is_writable($directory)) {
throw new \RuntimeException("Directory [{$directory}] is not writable");
}
return true;
}

Expand Down
12 changes: 7 additions & 5 deletions src/ModelGenerator/Loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,29 @@
* @author Michael Calcinai <michael@calcin.ai>
*/

namespace Wave\SDK\ModelGenerator;
declare(strict_types=1);

namespace Wave\SDK\ModelGenerator;

abstract class Loader {



public static function create(array $config){

switch($config['type']){
case 'git':
return new Loader\Git($config);
case 'file':
return new Loader\File($config);
case 'string':
return new Loader\StringLoader($config);
default:
throw new \InvalidArgumentException(sprintf('[%s] is not a supported loader type'));
$type = $config['type'] ?? 'unknown';
throw new \InvalidArgumentException(sprintf('[%s] is not a supported loader type', $type));
}


}

abstract public function getContent();

}
}
24 changes: 17 additions & 7 deletions src/ModelGenerator/Loader/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,33 @@
* @author Michael Calcinai <michael@calcin.ai>
*/

declare(strict_types=1);

namespace Wave\SDK\ModelGenerator\Loader;

use Wave\SDK\ModelGenerator\Loader;

class File extends Loader {

private $file;
private string $file;

/**
* File constructor.
* @param array $config
* @param array{file: string} $config
*/
public function __construct($config) {
public function __construct(array $config) {
if(empty($config['file'])){
throw new \InvalidArgumentException('File loader configuration requires a "file" key');
}

$this->file = $config['file'];
}

public function getContent() {
return file_get_contents($this->file);
public function getContent(): string{
$content = @file_get_contents($this->file);
if($content === false){
throw new \RuntimeException(sprintf('Failed to read file [%s]', $this->file));
}

return $content;
}
}
}
34 changes: 25 additions & 9 deletions src/ModelGenerator/Loader/Git.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,43 @@
* @author Michael Calcinai <michael@calcin.ai>
*/

declare(strict_types=1);

namespace Wave\SDK\ModelGenerator\Loader;

use Wave\SDK\ModelGenerator\Loader;

class Git extends Loader {

private $repository;
private $file;
private string $repository;
private string $file;

/**
* Git constructor.
* @param array $config
* @param array{repository: string, file: string} $config
*/
public function __construct($config) {
public function __construct(array $config) {
if(empty($config['repository']) || empty($config['file'])){
throw new \InvalidArgumentException('Git loader configuration requires both "repository" and "file" keys');
}

$this->repository = $config['repository'];
$this->file = $config['file'];
}

public function getContent() {
public function getContent(): string{

$command = sprintf(
'git archive --remote=%s HEAD %s | tar -xO',
escapeshellarg($this->repository),
escapeshellarg($this->file)
);

$result = shell_exec($command);

if($result === null){
throw new \RuntimeException(sprintf('Failed to retrieve [%s] from repository [%s]', $this->file, $this->repository));
}

$command = sprintf('git archive --remote=%s HEAD %s | tar -xO', $this->repository, $this->file);
return trim(shell_exec($command));
return trim($result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
* @author Michael Calcinai <michael@calcin.ai>
*/

declare(strict_types=1);

namespace Wave\SDK\ModelGenerator\Loader;

use Wave\SDK\ModelGenerator\Loader;

class String extends Loader {
class StringLoader extends Loader {

public function getContent() {
// TODO: Implement getContent() method.
}
}
}
2 changes: 1 addition & 1 deletion src/SchemaGenerator/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Wave\SDK\SchemaGenerator;


#[\AllowDynamicProperties]
class Definition {

public function __construct($data = null){
Expand Down