From 90c9454395673e5209ea66e2bdaf3a0caf6d0f68 Mon Sep 17 00:00:00 2001 From: Sean Molenaar Date: Tue, 17 Jan 2017 22:25:34 +0100 Subject: [PATCH] Allow for online API parsing --- index.php | 22 +++- .../Elements/Tests/ArrayStructureTest.php | 38 ------- src/PHPDraft/Out/UI.php | 93 +++++++++------- src/PHPDraft/Parse/BaseParser.php | 102 ++++++++++++++++++ src/PHPDraft/Parse/Drafter.php | 61 +---------- src/PHPDraft/Parse/DrafterAPI.php | 86 +++++++++++++++ 6 files changed, 270 insertions(+), 132 deletions(-) delete mode 100644 src/PHPDraft/Model/Elements/Tests/ArrayStructureTest.php create mode 100644 src/PHPDraft/Parse/BaseParser.php create mode 100644 src/PHPDraft/Parse/DrafterAPI.php diff --git a/index.php b/index.php index 9d40049c..c5c4433b 100755 --- a/index.php +++ b/index.php @@ -11,13 +11,31 @@ use PHPDraft\In\ApibFileParser; use PHPDraft\Out\UI; use PHPDraft\Parse\Drafter; +use PHPDraft\Parse\DrafterAPI; use PHPDraft\Parse\JsonToHTML; define('VERSION', '0'); $values = UI::main($argv); -$apib = new ApibFileParser($values['file']); -$json = new Drafter($apib); +$apib = new ApibFileParser($values['file']); +$json = new DrafterAPI($apib); +if (!(defined('DRAFTER_ONLINE_MODE') && DRAFTER_ONLINE_MODE === 1)) { + try { + $json = new Drafter($apib); + } catch (RuntimeException $exception) { + file_put_contents('php://stderr', $exception->getMessage()."\n"); + $options = [ + 'y' => 'Yes', + 'n' => 'No', + ]; + $answer = UI::ask('Do you want to use the online version? [y/n]', $options, 'y'); + if (!$answer) { + file_put_contents('php://stderr', 'Could not find a suitable drafter version'); + exit(1); + } + } +} + $html = new JsonToHTML($json->parseToJson()); $html->sorting = $values['sorting']; $html->get_html($values['template'], $values['image'], $values['css'], $values['js']); diff --git a/src/PHPDraft/Model/Elements/Tests/ArrayStructureTest.php b/src/PHPDraft/Model/Elements/Tests/ArrayStructureTest.php deleted file mode 100644 index 8bf32180..00000000 --- a/src/PHPDraft/Model/Elements/Tests/ArrayStructureTest.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ - -namespace PHPDraft\Model\Elements\Tests; - - -use PHPDraft\Core\BaseTest; -use PHPDraft\Model\Elements\ArrayStructureElement; - -class ArrayStructureTest extends BaseTest -{ - public function setUp() - { - $this->class = new ArrayStructureElement(); - $this->reflection = new \ReflectionClass('PHPDraft\Model\Elements\ArrayStructureElement'); - } - - public function tearDown() - { - unset($this->class); - unset($this->reflection); - } - - /** - * Test if the value the class is initialized with is correct - */ - public function testSetupCorrectly() - { - $property = $this->reflection->getProperty('element'); - $property->setAccessible(TRUE); - $this->assertNull($property->getValue($this->class)); - } -} \ No newline at end of file diff --git a/src/PHPDraft/Out/UI.php b/src/PHPDraft/Out/UI.php index d25379f0..ab26b493 100644 --- a/src/PHPDraft/Out/UI.php +++ b/src/PHPDraft/Out/UI.php @@ -13,9 +13,9 @@ */ class UI { - public static $PHPD_SORT_ALL = 3; + public static $PHPD_SORT_ALL = 3; public static $PHPD_SORT_WEBSERVICES = 2; - public static $PHPD_SORT_STRUCTURES = 1; + public static $PHPD_SORT_STRUCTURES = 1; protected $versionStringPrinted; /** @@ -27,41 +27,34 @@ class UI */ static function main($argv = []) { - $options = getopt('f:t:i:c:j:s:hvu'); + $options = getopt('f:t:i:c:j:s:hvuyo'); - if (!isset($argv[1])) - { + if (!isset($argv[1])) { file_put_contents('php://stderr', 'Not enough arguments' . PHP_EOL); self::help(); exit(1); } $sorting = -1; - if (isset($options['s'])) - { + if (isset($options['s'])) { $value = strtoupper($options['s']); - if (isset(UI::${'PHPD_SORT_' . $value})) - { + if (isset(UI::${'PHPD_SORT_' . $value})) { $sorting = UI::${'PHPD_SORT_' . $value}; } } - if (boolval(preg_match('/^\-/', $argv[1]))) - { - if (isset($options['h'])) - { + if (boolval(preg_match('/^\-/', $argv[1]))) { + if (isset($options['h'])) { self::help(); exit(0); } - if (isset($options['v'])) - { + if (isset($options['v'])) { self::version(); exit(0); } - if (isset($options['f'])) - { + if (isset($options['f'])) { $file = $options['f']; } else { file_put_contents('php://stderr', 'No file to parse' . PHP_EOL); @@ -70,11 +63,14 @@ static function main($argv = []) } else { $file = $argv[1]; } + if (isset($options['y']) || isset($options['o'])) { + define('DRAFTER_ONLINE_MODE', 1); + } $template = (isset($options['t']) && $options['t']) ? $options['t'] : 'default'; - $image = (isset($options['i']) && $options['i']) ? $options['i'] : NULL; - $css = (isset($options['c']) && $options['c']) ? $options['i'] : NULL; - $js = (isset($options['j']) && $options['j']) ? $options['i'] : NULL; + $image = (isset($options['i']) && $options['i']) ? $options['i'] : null; + $css = (isset($options['c']) && $options['c']) ? $options['i'] : null; + $js = (isset($options['j']) && $options['j']) ? $options['i'] : null; return [ 'file' => $file, @@ -125,16 +121,6 @@ static function release_id() return (VERSION === '0') ? @exec('git describe --tags 2>&1') : VERSION; } - /** - * Print the version string - * - * @return void - */ - private function printVersionString() - { - print self::version() . "\n\n"; - } - /** * Print the series of the update * @@ -144,8 +130,7 @@ private function printVersionString() */ public static function series() { - if (strpos(self::release_id(), '-')) - { + if (strpos(self::release_id(), '-')) { $version = explode('-', self::release_id())[0]; } else { $version = self::release_id(); @@ -161,14 +146,41 @@ public static function series() */ public static function getReleaseChannel() { - if (strpos(self::release_id(), '-') !== FALSE) - { + if (strpos(self::release_id(), '-') !== false) { return '-nightly'; } return ''; } + /** + * Ask a question to the user + * + * @param string $message The question + * @param array $options Possible answers + * + * @param string $positive The parameter that gives a positive outcome + * + * @return boolean + */ + public static function ask($message, $options, $positive = 'y') + { + file_put_contents('php://stdout', $message); + do { + $selection = fgetc(STDIN); + } while (trim($selection) == ''); + + if (array_key_exists(strtolower($selection), $options)) { + return ($selection === $positive); + } + if (array_search($selection, $options)) { + return (array_search($selection, $options) === $positive); + } + file_put_contents('php://stderr', 'That answer wasn\'t expected, try again.'.PHP_EOL.PHP_EOL); + + return UI::ask($message, $options, $positive); + } + /** * Handle the check for a version * @@ -181,8 +193,7 @@ protected function handleVersionCheck() $this->printVersionString(); $latestVersion = file_get_contents('https://phar.phpdraft.de/latest-version-of/phpdraft'); $isOutdated = version_compare($latestVersion, self::release_id(), '>'); - if ($isOutdated) - { + if ($isOutdated) { print "You are not using the latest version of PHPDraft.\n"; print 'Use "phpdraft --self-upgrade" to install PHPDraft ' . $latestVersion . "\n"; } else { @@ -191,4 +202,14 @@ protected function handleVersionCheck() exit(0); } + + /** + * Print the version string + * + * @return void + */ + private function printVersionString() + { + print self::version() . "\n\n"; + } } \ No newline at end of file diff --git a/src/PHPDraft/Parse/BaseParser.php b/src/PHPDraft/Parse/BaseParser.php new file mode 100644 index 00000000..b36bb2c7 --- /dev/null +++ b/src/PHPDraft/Parse/BaseParser.php @@ -0,0 +1,102 @@ + + */ + +//TODO: Change this + +namespace PHPDraft\Parse; + + +abstract class BaseParser +{ + /** + * The API Blueprint output (JSON) + * + * @var string + */ + public $json; + + /** + * Temp directory + * + * @var array + */ + protected $tmp_dir; + + /** + * The API Blueprint input + * + * @var string + */ + protected $apib; + + /** + * BaseParser constructor. + * + * @param string $apib API Blueprint text + */ + public function __construct($apib) + { + $this->apib = $apib; + } + + /** + * BaseParser destructor. + */ + function __destruct() + { + unset($this->apib); + unset($this->json); + unset($this->tmp_dir); + } + + + /** + * Parse the API Blueprint text to JSON + * + * @return string API Blueprint text + */ + public function parseToJson() + { + if (!file_exists($this->tmp_dir)) { + mkdir($this->tmp_dir); + } + + file_put_contents($this->tmp_dir . '/index.apib', $this->apib); + + $this->parse(); + + if (json_last_error() !== JSON_ERROR_NONE) + { + file_put_contents('php://stdout', 'ERROR: invalid json in ' . $this->tmp_dir . '/index.json'); + throw new \RuntimeException('Drafter generated invalid JSON (' . json_last_error_msg() . ')', 2); + } + + $warnings = false; + foreach ($this->json->content as $item) { + if ($item->element === 'annotation') { + $warnings = true; + $prefix = strtoupper($item->meta->classes[0]); + $error = $item->content; + file_put_contents('php://stdout', "
$prefix: $error
\n"); + } + } + + if ($warnings) { + throw new \RuntimeException('Parsing encountered errors and stopped', 2); + } + + return $this->json; + } + + /** + * Parses the apib for the selected method + * + * @return void + */ + abstract protected function parse(); +} \ No newline at end of file diff --git a/src/PHPDraft/Parse/Drafter.php b/src/PHPDraft/Parse/Drafter.php index f55df124..d8d1f54a 100644 --- a/src/PHPDraft/Parse/Drafter.php +++ b/src/PHPDraft/Parse/Drafter.php @@ -8,26 +8,8 @@ namespace PHPDraft\Parse; -class Drafter +class Drafter extends BaseParser { - /** - * The API Blueprint output (JSON) - * - * @var string - */ - public $json; - /** - * Temp directory - * - * @var array - */ - protected $tmp_dir; - /** - * The API Blueprint input - * - * @var string - */ - protected $apib; /** * The location of the drafter executable @@ -43,7 +25,7 @@ class Drafter */ public function __construct($apib) { - $this->apib = $apib; + parent::__construct($apib); if (!$this->location()) { @@ -69,45 +51,12 @@ function location() } /** - * Parse the API Blueprint text to JSON + * Parses the apib for the selected method * - * @return string API Blueprint text + * @return void */ - public function parseToJson() - { - if (!file_exists($this->tmp_dir)) - { - mkdir($this->tmp_dir); - } - - file_put_contents($this->tmp_dir . '/index.apib', $this->apib); - + protected function parse(){ shell_exec($this->drafter . ' ' . $this->tmp_dir . '/index.apib -f json -o ' . $this->tmp_dir . '/index.json 2> /dev/null'); $this->json = json_decode(file_get_contents($this->tmp_dir . '/index.json')); - - if (json_last_error() !== JSON_ERROR_NONE) - { - file_put_contents('php://stdout', 'ERROR: invalid json in ' . $this->tmp_dir . '/index.json'); - throw new \RuntimeException('Drafter generated invalid JSON (' . json_last_error_msg() . ')', 2); - } - - $warnings = FALSE; - foreach ($this->json->content as $item) { - if ($item->element === 'annotation') - { - $warnings = TRUE; - $prefix = strtoupper($item->meta->classes[0]); - $error = $item->content; - file_put_contents('php://stdout', "$prefix: $error\n"); - } - } - - if ($warnings) - { - throw new \RuntimeException('Parsing encountered errors and stopped', 2); - } - - return $this->json; } - } \ No newline at end of file diff --git a/src/PHPDraft/Parse/DrafterAPI.php b/src/PHPDraft/Parse/DrafterAPI.php new file mode 100644 index 00000000..8c4b2acf --- /dev/null +++ b/src/PHPDraft/Parse/DrafterAPI.php @@ -0,0 +1,86 @@ + + */ + +//TODO: Change this + +namespace PHPDraft\Parse; + + +class DrafterAPI extends BaseParser +{ + /** + * ApibToJson constructor. + * + * @param string $apib API Blueprint text + */ + public function __construct($apib) + { + parent::__construct($apib); + + $ch = $this->curl_init_drafter("# Hello API +## /message +### GET + + Response 200 (text/plain) + + Hello World!"); + + curl_exec($ch); + + if (curl_errno($ch) !== 0) { + throw new \RuntimeException('Drafter webservice is not available!', 1); + } + curl_close($ch); + + $this->tmp_dir = sys_get_temp_dir() . '/drafter'; + } + + /** + * Parses the apib for the selected method + * + * @return void + */ + protected function parse() + { + $ch = $this->curl_init_drafter($this->apib); + + $response = curl_exec($ch); + + if (curl_errno($ch) !== 0) { + throw new \RuntimeException('Drafter webservice failed to parse input', 1); + } + + $this->json = json_decode($response); + } + + /** + * Init curl for drafter webservice + * + * @param string $message API blueprint to parse + * + * @return resource + */ + private function curl_init_drafter($message) + { + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, "https://api.apiblueprint.org/parser"); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HEADER, false); + + curl_setopt($ch, CURLOPT_POST, true); + + curl_setopt($ch, CURLOPT_POSTFIELDS, $message); + + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "Content-Type: text/vnd.apiblueprint", + "Accept: application/vnd.refract.parse-result+json", + ]); + + return $ch; + } +} \ No newline at end of file