Imported code from old repository
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class AbstractAddDependenciesCommand extends AbstractObjectCommand {
|
||||
|
||||
protected function configure() {
|
||||
$this->addOption('confjob', null, InputOption::VALUE_NONE, 'Calls "cloudobjects" to create a configuration job for the updated class.');
|
||||
}
|
||||
|
||||
protected function dependencyPrecheck() {
|
||||
$this->assertRDF();
|
||||
$this->assertPHPExists();
|
||||
}
|
||||
|
||||
protected function getObjectAndAssertType(string $coid, string $type) {
|
||||
// Retrieve configuration
|
||||
$config = shell_exec("cloudobjects get ".$coid);
|
||||
if (!isset($config))
|
||||
throw new \Exception("Could not retrieve <".$coid.">.");
|
||||
|
||||
// Parse and validate configuration
|
||||
$parser = \ARC2::getRDFXMLParser();
|
||||
$parser->parse('', $config);
|
||||
$index = $parser->getSimpleIndex(false);
|
||||
if (!isset($index) || !isset($index[$coid])
|
||||
|| !isset($index[$coid]['http://www.w3.org/1999/02/22-rdf-syntax-ns#type']))
|
||||
throw new \Exception("<".$coid."> is not a valid CloudObjects object.");
|
||||
|
||||
$hasType = false;
|
||||
foreach ($index[$coid]['http://www.w3.org/1999/02/22-rdf-syntax-ns#type'] as $property => $values) {
|
||||
if ($values['value'] == $type) {
|
||||
$hasType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasType)
|
||||
throw new \Exception("<".$coid."> must have the type <".$type.">.");
|
||||
}
|
||||
|
||||
protected function addDependency(string $key, string $type, array $valuesToMerge,
|
||||
InputInterface $input, OutputInterface $output) {
|
||||
|
||||
$this->index['_:dep-'.$key] = array_merge([
|
||||
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' => [
|
||||
[ 'type' => 'uri', 'value' => $type ]
|
||||
],
|
||||
'coid://phpmae.dev/hasKey' => [
|
||||
[ 'type' => 'literal', 'value' => $key ]
|
||||
]
|
||||
], $valuesToMerge);
|
||||
|
||||
// Edit configuration
|
||||
$object = $this->index[(string)$this->coid];
|
||||
if (isset($object['coid://phpmae.dev/hasDependency'])) {
|
||||
foreach ($object['coid://phpmae.dev/hasDependency'] as $o) {
|
||||
if ($o['type'] != 'bnode') continue;
|
||||
$bnode = $this->index[$o['value']];
|
||||
if (isset($bnode['coid://phpmae.dev/hasKey']) && $bnode['coid://phpmae.dev/hasKey'][0]['value'] == $key)
|
||||
throw new \Exception("A dependency with the key '".$key."' already exists.");
|
||||
|
||||
foreach ($valuesToMerge as $k => $values)
|
||||
if (isset($bnode[$k]))
|
||||
foreach ($bnode[$k] as $a)
|
||||
foreach ($valuesToMerge[$k] as $b)
|
||||
if ($a['type'] == $b['type'] && $a['value'] == $b['value'])
|
||||
throw new \Exception("This dependency was already added.");
|
||||
}
|
||||
$object['coid://phpmae.dev/hasDependency'][] = [ 'type' => 'bnode', 'value' => '_:dep-'.$key ];
|
||||
} else
|
||||
$object['coid://phpmae.dev/hasDependency'] = [['type' => 'bnode', 'value' => '_:dep-'.$key ]];
|
||||
|
||||
// Persist configuration
|
||||
$this->index[(string)$this->coid] = $object;
|
||||
$this->updateRDFLocally($output);
|
||||
|
||||
if ($input->getOption('confjob'))
|
||||
$this->createConfigurationJob($output);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Exception;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use ML\IRI\IRI;
|
||||
use CloudObjects\SDK\COIDParser;
|
||||
use CloudObjects\PhpMAE\CredentialManager;
|
||||
|
||||
abstract class AbstractObjectCommand extends Command {
|
||||
|
||||
protected $coid;
|
||||
protected $fullName;
|
||||
protected $phpFileName;
|
||||
protected $xmlFileName;
|
||||
protected $rdfTypes;
|
||||
protected $index;
|
||||
|
||||
protected function requireCloudObjectsCLI() {
|
||||
if (!CredentialManager::isConfigured())
|
||||
throw new Exception("The 'cloudobjects' CLI tool must be installed and authorized.");
|
||||
}
|
||||
|
||||
protected function parse($coid) {
|
||||
$this->coid = COIDParser::fromString($coid);
|
||||
|
||||
if (COIDParser::getType($this->coid)!=COIDParser::COID_VERSIONED
|
||||
&& COIDParser::getType($this->coid)!=COIDParser::COID_UNVERSIONED)
|
||||
throw new Exception("Invalid COID: ".(string)$this->coid);
|
||||
|
||||
$name = COIDParser::getName($this->coid);
|
||||
$version = COIDParser::getVersion($this->coid);
|
||||
$this->fullName = isset($version) ? $name.".".$version : $name;
|
||||
$this->phpFileName = $this->fullName.'.php';
|
||||
$this->xmlFileName = $this->fullName.'.xml';
|
||||
}
|
||||
|
||||
protected function assertRDF() {
|
||||
if (!file_exists($this->xmlFileName))
|
||||
throw new Exception("File not found: ".$this->xmlFileName);
|
||||
|
||||
$parser = \ARC2::getRDFXMLParser();
|
||||
$parser->parse('', file_get_contents($this->xmlFileName));
|
||||
$index = $parser->getSimpleIndex(false);
|
||||
$id = (string)$this->coid;
|
||||
if (!isset($index) || !isset($index[$id])
|
||||
|| !isset($index[$id]['http://www.w3.org/1999/02/22-rdf-syntax-ns#type']))
|
||||
throw new Exception($this->xmlFileName." does not contain a valid RDF description of the object.");
|
||||
|
||||
$this->rdfTypes = [];
|
||||
foreach ($index[$id]['http://www.w3.org/1999/02/22-rdf-syntax-ns#type'] as $o)
|
||||
if ($o['type'] == 'uri') $this->rdfTypes[] = $o['value'];
|
||||
$this->index = $index;
|
||||
}
|
||||
|
||||
protected function updateRDFLocally(OutputInterface $output) {
|
||||
file_put_contents($this->xmlFileName,
|
||||
$this->getSerializer()->getSerializedIndex($this->index));
|
||||
$output->writeln("Updated ".$this->xmlFileName);
|
||||
}
|
||||
|
||||
protected function createConfigurationJob(OutputInterface $output) {
|
||||
$output->writeln("Calling cloudobjects configuration-job:create ...");
|
||||
passthru("cloudobjects configuration-job:create ".$this->xmlFileName);
|
||||
}
|
||||
|
||||
protected function ensureFilenameInConfig(OutputInterface $output, $interface = false) {
|
||||
$property = ($interface ? 'coid://phpmae.dev/hasDefinitionFile'
|
||||
: 'coid://phpmae.dev/hasSourceFile');
|
||||
$object = $this->index[(string)$this->coid];
|
||||
if (!isset($object[$property])) {
|
||||
$object[$property] = [[
|
||||
'value' => 'file:///'.$this->fullName.'.php',
|
||||
'type' => 'uri'
|
||||
]];
|
||||
$this->index[(string)$this->coid] = $object;
|
||||
$this->updateRDFLocally($output);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function assertPHPExists() {
|
||||
if (!file_exists($this->phpFileName))
|
||||
throw new Exception("File not found: ".$this->phpFileName);
|
||||
}
|
||||
|
||||
protected function getSerializer() {
|
||||
return \ARC2::getRDFXMLSerializer(array(
|
||||
'serializer_type_nodes' => true,
|
||||
'ns' => array(
|
||||
'co' => 'coid://cloudobjects.io/',
|
||||
'phpmae' => 'coid://phpmae.dev/'
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
protected function watchPHPFile(OutputInterface $output, callable $callable) {
|
||||
$fileTime = filemtime($this->phpFileName);
|
||||
$output->writeln('Watching for changes ...');
|
||||
set_time_limit(0);
|
||||
while (true) {
|
||||
clearstatcache();
|
||||
if (filemtime($this->phpFileName) != $fileTime) {
|
||||
// File has changed ...
|
||||
sleep(1);
|
||||
$fileTime = filemtime($this->phpFileName);
|
||||
$callable();
|
||||
$output->writeln('Watching for changes ...');
|
||||
}
|
||||
sleep(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getAdditionalTypes() {
|
||||
$coids = [];
|
||||
foreach ($this->rdfTypes as $t) {
|
||||
if (in_array($t, [ 'coid://phpmae.dev/Class',
|
||||
'coid://phpmae.dev/HTTPInvokableClass',
|
||||
'coid://phpmae.dev/Interface' ]))
|
||||
continue;
|
||||
$coids[] = new IRI($t);
|
||||
}
|
||||
|
||||
return $coids;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use ML\IRI\IRI;
|
||||
use CloudObjects\SDK\COIDParser;
|
||||
use CloudObjects\PhpMAE\CredentialManager, CloudObjects\PhpMAE\ClassValidator;
|
||||
use CloudObjects\PhpMAE\Exceptions\PhpMAEException;
|
||||
|
||||
class ClassCreateCommand extends Command {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('class:create')
|
||||
->setDescription('Create a new class for the phpMAE.')
|
||||
->addArgument('coid', InputArgument::REQUIRED, 'The COID of the object.')
|
||||
->addOption('http-invokable', 'hi', InputOption::VALUE_NONE, 'Makes the class HTTP-invokable.')
|
||||
->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces new object creation and replaces existing files.')
|
||||
->addOption('public', null, InputOption::VALUE_NONE, 'Marks new object as public.')
|
||||
->addOption('confjob', null, InputOption::VALUE_NONE, 'Calls "cloudobjects" to create a configuration job for the new class.')
|
||||
->addOption('autowire', null, InputOption::VALUE_REQUIRED, 'Creates a constructor that autowires a PHP dependency.', null)
|
||||
->addOption('implements', null, InputOption::VALUE_REQUIRED, 'Make this class an implementation of the phpMAE interface with the specified COID.', null);
|
||||
}
|
||||
|
||||
private function getAndValidateInterfaceConfig($implements) {
|
||||
// Check interface COID
|
||||
$interfaceCoid = COIDParser::fromString($implements);
|
||||
if (COIDParser::getType($interfaceCoid) != COIDParser::COID_VERSIONED
|
||||
&& COIDParser::getType($interfaceCoid) != COIDParser::COID_UNVERSIONED)
|
||||
throw new \Exception("Invalid Interface COID: ".(string)$interfaceCoid);
|
||||
|
||||
// Retrieve interface configuration
|
||||
$implements = (string)$interfaceCoid;
|
||||
$interfaceConfig = shell_exec("cloudobjects get ".$implements);
|
||||
if (!isset($interfaceConfig))
|
||||
throw new \Exception("Could not retrieve interface configuration.");
|
||||
|
||||
// Parse and validate interface configuration
|
||||
$parser = \ARC2::getRDFXMLParser();
|
||||
$parser->parse('', $interfaceConfig);
|
||||
$index = $parser->getSimpleIndex(false);
|
||||
if (!isset($index) || !isset($index[$implements])
|
||||
|| !isset($index[$implements]['http://www.w3.org/1999/02/22-rdf-syntax-ns#type']))
|
||||
throw new \Exception("<".$implements."> is not a valid CloudObjects object.");
|
||||
|
||||
$isInterface = false;
|
||||
foreach ($index[$implements]['http://www.w3.org/1999/02/22-rdf-syntax-ns#type'] as $property => $values) {
|
||||
if ($values['value'] == 'coid://phpmae.dev/Interface')
|
||||
$isInterface = true;
|
||||
}
|
||||
|
||||
if (!$isInterface || !isset($index[$implements]['coid://phpmae.dev/hasDefinitionFile']))
|
||||
throw new \Exception("<".$implements."> is not a valid phpMAE interface.");
|
||||
|
||||
return [
|
||||
'classname' => COIDParser::getName($interfaceCoid),
|
||||
'filename' => basename($index[$implements]['coid://phpmae.dev/hasDefinitionFile'][0]['value']),
|
||||
'coid' => (string)$interfaceCoid,
|
||||
];
|
||||
}
|
||||
|
||||
private function getAndParseInterfaceCode($interface, $filename) {
|
||||
// Retrieve interface code
|
||||
$interfaceCode = shell_exec("cloudobjects attachment:get ".$interface
|
||||
." ".$filename);
|
||||
|
||||
// Run through validator
|
||||
$validator = new ClassValidator;
|
||||
$validator->validateInterface($interfaceCode, new IRI($interface));
|
||||
|
||||
// Find use statements
|
||||
$matches = [];
|
||||
preg_match_all("/use\s+(.+);/", $interfaceCode, $matches);
|
||||
$use = $matches[1];
|
||||
|
||||
// Parse method definitions
|
||||
// (this is the same algorithm as the DirectoryTemplateVariableGenerator,
|
||||
// but less filtering on comment string)
|
||||
$matches = [];
|
||||
preg_match_all("/(?:\/\*\*((?:[\s\S](?!\/\*))*?)\*\/+\s*)?public\s+function\s+(\w+)\s*\((.+)\)/",
|
||||
$interfaceCode, $matches);
|
||||
|
||||
// The following groups are captured through RegExes:
|
||||
// 0 - complete definition block
|
||||
// 1 - comment string
|
||||
// 2 - method name
|
||||
// 3 - method parameters
|
||||
|
||||
$methods = [];
|
||||
for ($i = 0; $i < count($matches[0]); $i++) {
|
||||
// List methods with parameters and comment
|
||||
$methods[] = [
|
||||
'name' => $matches[2][$i],
|
||||
'params' => trim($matches[3][$i]),
|
||||
'comment' => trim($matches[1][$i])
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'methods' => $methods,
|
||||
'use' => $use
|
||||
];
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
if (!CredentialManager::isConfigured())
|
||||
throw new \Exception("The 'cloudobjects' CLI tool must be installed and authorized.");
|
||||
|
||||
$coid = COIDParser::fromString($input->getArgument('coid'));
|
||||
|
||||
if (COIDParser::getType($coid) != COIDParser::COID_VERSIONED
|
||||
&& COIDParser::getType($coid) != COIDParser::COID_UNVERSIONED)
|
||||
throw new \Exception("Invalid COID: ".(string)$coid);
|
||||
|
||||
$name = COIDParser::getName($coid);
|
||||
$version = COIDParser::getVersion($coid);
|
||||
$fullName = isset($version) ? $name.".".$version : $name;
|
||||
$invokable = $input->getOption('http-invokable');
|
||||
|
||||
if ($input->getOption('implements') != null) {
|
||||
if ($invokable)
|
||||
throw new \Exception("The 'implements' option cannot be used with 'http-invokable'.");
|
||||
|
||||
$implements = $input->getOption('implements');
|
||||
$output->writeln("Fetching configuration for ".$implements." ...");
|
||||
$interfaceData = $this->getAndValidateInterfaceConfig($implements);
|
||||
}
|
||||
|
||||
if (!file_exists($fullName.'.xml') || $input->getOption('force')) {
|
||||
// Create RDF configuration file
|
||||
$content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
. "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"
|
||||
. " xmlns:co=\"coid://cloudobjects.io/\"\n"
|
||||
. " xmlns:phpmae=\"coid://phpmae.dev/\">\n"
|
||||
. "\n"
|
||||
. " <phpmae:".($invokable ? "HTTPInvokable" : "")."Class rdf:about=\"".(string)$coid."\">\n";
|
||||
|
||||
// Mark as public if option was defined
|
||||
if ($input->getOption('public'))
|
||||
$content .= " <co:isVisibleTo rdf:resource=\"coid://cloudobjects.io/Public\" />\n"
|
||||
. " <co:permitsUsageTo rdf:resource=\"coid://cloudobjects.io/Public\" />\n";
|
||||
else
|
||||
$content .= " <co:isVisibleTo rdf:resource=\"coid://cloudobjects.io/Vendor\" />\n";
|
||||
|
||||
if (isset($implements))
|
||||
$content .= " <rdf:type rdf:resource=\"".$interfaceData['coid']."\" />\n";
|
||||
$content .=" </phpmae:".($invokable ? "HTTPInvokable" : "")."Class>\n"
|
||||
. "</rdf:RDF>";
|
||||
file_put_contents($fullName.'.xml', $content);
|
||||
$output->writeln("Written ".$fullName.".xml.");
|
||||
} else {
|
||||
// RDF configuration file already exists
|
||||
$output->writeln($fullName.".xml already exists.");
|
||||
}
|
||||
|
||||
if (!file_exists($fullName.'.php') || $input->getOption('force') !== false) {
|
||||
$useStatements = [];
|
||||
$classVariables = [];
|
||||
$constructor = '';
|
||||
|
||||
if ($input->getOption('autowire') != null) {
|
||||
$fullyQualifiedClassname = $input->getOption('autowire');
|
||||
$validator = new ClassValidator;
|
||||
if (!$validator->isWhitelisted($fullyQualifiedClassname))
|
||||
throw new PhpMAEException('Cannot autowire non-whitelisted type <'.$fullyQualifiedClassname.'>.');
|
||||
$useStatements[] = $fullyQualifiedClassname;
|
||||
$className = substr($fullyQualifiedClassname, strrpos($fullyQualifiedClassname, '\\') + 1);
|
||||
$variableName = strtolower($className[0]).substr($className, 1);
|
||||
$classVariables[] = $variableName;
|
||||
$constructor = " public function __construct(".$className." \$".$variableName.") {\n"
|
||||
. " \$this->".$variableName." = \$".$variableName.";\n"
|
||||
. " }\n\n";
|
||||
}
|
||||
|
||||
if (isset($implements)) {
|
||||
// Retrieve interface code
|
||||
$output->writeln("Fetching code for ".$interfaceData['coid']." ...");
|
||||
$parsedInterface = $this->getAndParseInterfaceCode($interfaceData['coid'], $interfaceData['filename']);
|
||||
// Add use statements
|
||||
foreach ($parsedInterface['use'] as $u)
|
||||
$useStatements[] = $u;
|
||||
}
|
||||
|
||||
// Create PHP source file
|
||||
$content = "<?php\n"
|
||||
. "\n";
|
||||
foreach ($useStatements as $u)
|
||||
$content .= "use ".$u.";\n";
|
||||
if (count($useStatements) > 0)
|
||||
$content .= "\n";
|
||||
|
||||
$content .= "/**\n"
|
||||
. " * Implementation for ".(string)$coid."\n"
|
||||
. (isset($implements) ? " * Using interface ".$interfaceData['coid']."\n" : "")
|
||||
. " */\n"
|
||||
. "class ".$name." ".(isset($implements) ? "implements ".$interfaceData['classname']." " : "")
|
||||
. "{\n"
|
||||
. "\n";
|
||||
foreach ($classVariables as $v)
|
||||
$content .= " private \$".$v.";\n";
|
||||
if (count($classVariables) > 0)
|
||||
$content .= "\n"
|
||||
. $constructor;
|
||||
|
||||
if (isset($implements)) {
|
||||
// Build PHP template with interface methods
|
||||
foreach ($parsedInterface['methods'] as $m) {
|
||||
$content .= ($m['comment'] != "" ? " /**\n ".$m['comment']."\n */\n" : "")
|
||||
. " public function ".$m['name']."(".$m['params'].") {\n"
|
||||
. " // TODO: Implement this\n"
|
||||
. " }\n\n";
|
||||
}
|
||||
} else {
|
||||
// Build PHP template for standard or HTTP-invokable class
|
||||
$content .= ($invokable
|
||||
? " public function __invoke(\$args) {\n // TODO: Add your code here\n }\n"
|
||||
: " // TODO: Add methods here ...\n")
|
||||
. "\n";
|
||||
}
|
||||
|
||||
$content .= "}";
|
||||
|
||||
file_put_contents($fullName.'.php', $content);
|
||||
$output->writeln("Written ".$fullName.".php.");
|
||||
} else {
|
||||
$output->writeln($fullName.".php already exists.");
|
||||
}
|
||||
|
||||
if ($input->getOption('confjob')) {
|
||||
$output->writeln("Calling cloudobjects ...");
|
||||
passthru("cloudobjects configuration-job:create ".$fullName.".xml");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use CloudObjects\SDK\COIDParser;
|
||||
use CloudObjects\PhpMAE\ClassValidator;
|
||||
|
||||
class ClassDeployCommand extends AbstractObjectCommand {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('class:deploy')
|
||||
->setDescription('Validates a class for the phpMAE and uploads it into CloudObjects. Updates the configuration if necessary.')
|
||||
->addArgument('coid', InputArgument::REQUIRED, 'The COID of the object.');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$this->requireCloudObjectsCLI();
|
||||
|
||||
$this->parse($input->getArgument('coid'));
|
||||
$this->assertRDF();
|
||||
if (!in_array('coid://phpmae.dev/Class', $this->rdfTypes)
|
||||
&& !in_array('coid://phpmae.dev/HTTPInvokableClass', $this->rdfTypes))
|
||||
throw new \Exception("Object does not have a valid class type.");
|
||||
$this->assertPHPExists();
|
||||
|
||||
// Running validator
|
||||
$validator = new ClassValidator;
|
||||
$validator->validate(file_get_contents($this->fullName.'.php'),
|
||||
$this->coid, $this->getAdditionalTypes());
|
||||
$output->writeln("Validated successfully, calling cloudobjects ...");
|
||||
|
||||
passthru("cloudobjects attachment:put ".(string)$this->coid." ".$this->fullName.".php");
|
||||
|
||||
// Updates configuration if necessary
|
||||
if ($this->ensureFilenameInConfig($output, false))
|
||||
$this->createConfigurationJob($output);
|
||||
|
||||
// Print URL so developer can easily access it
|
||||
$output->writeln("");
|
||||
$visibility = isset($object['coid://cloudobjects.io/isVisibleTo'])
|
||||
? $object['coid://cloudobjects.io/isVisibleTo'][0]['value']
|
||||
: 'coid://cloudobjects.io/Vendor';
|
||||
$path = $this->coid->getHost().$this->coid->getPath();
|
||||
|
||||
switch ($visibility) {
|
||||
case "coid://cloudobjects.io/Private":
|
||||
$output->writeln("<info>Private URL for Class Execution:</info>");
|
||||
$output->writeln("➡️ http://YOUR_PHPMAE_INSTANCE/".$path);
|
||||
break;
|
||||
case "coid://cloudobjects.io/Public":
|
||||
$output->writeln("<info>Public URL for Class Execution:</info>");
|
||||
$output->writeln("➡️ https://phpmae.dev/".$path);
|
||||
break;
|
||||
case "coid://cloudobjects.io/Vendor":
|
||||
$output->writeln("<info>Authenticated URL for Class Execution:</info>");
|
||||
$output->writeln("➡️ https://".$this->coid->getHost().":SECRET@phpmae.dev/".$path);
|
||||
$output->writeln("");
|
||||
$output->writeln("To get value for SECRET:");
|
||||
$output->writeln("➡️ cloudobjects domain-providers:secret ".$this->coid->getHost()." phpmae.dev");
|
||||
break;
|
||||
}
|
||||
$output->writeln("");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use ML\IRI\IRI;
|
||||
use Guzzle\Http\Exception\BadResponseException;
|
||||
use CloudObjects\SDK\COIDParser;
|
||||
use CloudObjects\PhpMAE\ClassValidator, CloudObjects\PhpMAE\TestEnvironmentManager;
|
||||
|
||||
class ClassTestEnvCommand extends AbstractObjectCommand {
|
||||
|
||||
private $container;
|
||||
|
||||
protected function getContainer() {
|
||||
if (!isset($this->container)) {
|
||||
$this->container = TestEnvironmentManager::getContainer();
|
||||
}
|
||||
|
||||
return $this->container;
|
||||
}
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('class:testenv')
|
||||
->setDescription('Uploads a class into the current test environment.')
|
||||
->addArgument('coid', InputArgument::REQUIRED, 'The COID of the object.')
|
||||
->addOption('config', null, InputOption::VALUE_NONE, 'Upload the local configuration of the class to the test environment instead of retrieving it from CloudObjects.')
|
||||
->addOption('watch', null, InputOption::VALUE_NONE, 'Keep watching for changes of the file and reupload automatically.');
|
||||
}
|
||||
|
||||
private function upload(OutputInterface $output) {
|
||||
try {
|
||||
$this->validator->validate(file_get_contents($this->phpFileName),
|
||||
$this->coid, $this->getAdditionalTypes());
|
||||
$this->getContainer()->get('testenv.client')->put('/uploadTestenv?type=source&coid='.urlencode((string)$this->coid), [
|
||||
'body' => file_get_contents($this->phpFileName)
|
||||
]);
|
||||
$output->writeln('File uploaded successfully!');
|
||||
} catch (BadResponseException $e) {
|
||||
if ($e->getResponse()->getContentType()=='application/json') {
|
||||
$errorMessage = $e->getResponse()->json();
|
||||
$output->writeln('<error>'.$errorMessage['error_code'].':</error> '
|
||||
.$errorMessage['error_message']);
|
||||
} else
|
||||
$output->writeln('<error>'.get_class($e).'</error> '.(string)$e->getResponse());
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln('<error>'.get_class($e).'</error> '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$this->requireCloudObjectsCLI();
|
||||
|
||||
$container = $this->getContainer();
|
||||
if (!$container->has('testenv.client'))
|
||||
throw new \Exception("No test environment configured.");
|
||||
|
||||
$this->parse($input->getArgument('coid'));
|
||||
$this->assertRDF();
|
||||
if (!in_array('coid://phpmae.dev/Class', $this->rdfTypes)
|
||||
&& !in_array('coid://phpmae.dev/HTTPInvokableClass', $this->rdfTypes))
|
||||
throw new \Exception("Object does not have a valid class type.");
|
||||
$this->assertPHPExists();
|
||||
|
||||
// Print URL so developer can easily access it
|
||||
$output->writeln("<info>Test Environment Base URL for Class Execution:</info>");
|
||||
$output->writeln("➡️ ".$container->get('testenv.url').$this->coid->getHost()
|
||||
.$this->coid->getPath());
|
||||
$output->writeln("");
|
||||
|
||||
if ($input->getOption('config')) {
|
||||
// Upload configuration before uploading implementation
|
||||
$this->ensureFilenameInConfig($output);
|
||||
$container->get('testenv.client')->put('/uploadTestenv?type=config&coid='.urlencode((string)$this->coid), [
|
||||
'body' => file_get_contents($this->xmlFileName)
|
||||
]);
|
||||
$output->writeln('Configuration uploaded successfully!');
|
||||
}
|
||||
|
||||
$this->validator = new ClassValidator;
|
||||
$this->upload($output);
|
||||
|
||||
if ($input->getOption('watch')) {
|
||||
$cmd = $this;
|
||||
$this->watchPHPFile($output, function() use ($cmd, $output) {
|
||||
$cmd->upload($output);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use JsonRpc\Client;
|
||||
use CloudObjects\PhpMAE\TestEnvironmentManager;
|
||||
|
||||
class ClassTestEnvRPCCommand extends AbstractObjectCommand {
|
||||
|
||||
private $container;
|
||||
|
||||
protected function getContainer() {
|
||||
if (!isset($this->container)) {
|
||||
$this->container = TestEnvironmentManager::getContainer();
|
||||
}
|
||||
|
||||
return $this->container;
|
||||
}
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('class:testenv-rpc')
|
||||
->setDescription('Executes a JSON-RPC method call on a class in the current test environment.')
|
||||
->addArgument('coid', InputArgument::REQUIRED, 'The COID of the object.')
|
||||
->addArgument('method', InputArgument::REQUIRED, 'The method name.')
|
||||
->addArgument('parameters', InputArgument::IS_ARRAY, 'The parameters for the method.');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$this->requireCloudObjectsCLI();
|
||||
|
||||
$container = $this->getContainer();
|
||||
if (!$container->has('testenv.client'))
|
||||
throw new \Exception("No test environment configured.");
|
||||
|
||||
$this->parse($input->getArgument('coid'));
|
||||
$this->assertRDF();
|
||||
if (!in_array('coid://phpmae.dev/Class', $this->rdfTypes)
|
||||
&& !in_array('coid://phpmae.dev/HTTPInvokableClass', $this->rdfTypes))
|
||||
throw new \Exception("Object does not have a valid class type.");
|
||||
$this->assertPHPExists();
|
||||
|
||||
// Create JSON-RPC Client
|
||||
$client = new Client($container->get('testenv.url')
|
||||
.$this->coid->getHost().$this->coid->getPath());
|
||||
|
||||
// Check parameters and load files
|
||||
$parameters = [];
|
||||
foreach ($input->getArgument('parameters') as $p) {
|
||||
if ($p[0] == '@')
|
||||
$parameters[] = @file_get_contents(substr($p, 1));
|
||||
else
|
||||
$parameters[] = $p;
|
||||
}
|
||||
|
||||
// Make RPC Call
|
||||
if ($client->call($input->getArgument('method'), $parameters)
|
||||
&& isset($client->result))
|
||||
$output->writeln(is_string($client->result)
|
||||
? $client->result
|
||||
: json_encode($client->result, JSON_PRETTY_PRINT));
|
||||
else
|
||||
$output->writeln("<error>RPC has failed!</error>");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use CloudObjects\PhpMAE\ClassValidator;
|
||||
|
||||
class ClassValidateCommand extends AbstractObjectCommand {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('class:validate')
|
||||
->setAliases([ 'validate', 'v' ])
|
||||
->setDescription('Validates a class for the phpMAE.')
|
||||
->addArgument('coid', InputArgument::REQUIRED, 'The COID of the object.')
|
||||
->addOption('watch', null, InputOption::VALUE_NONE, 'Keep watching for changes of the file and revalidate automatically.');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$this->parse($input->getArgument('coid'));
|
||||
$this->assertRDF();
|
||||
if (!in_array('coid://phpmae.dev/Class', $this->rdfTypes)
|
||||
&& !in_array('coid://phpmae.dev/HTTPInvokableClass', $this->rdfTypes))
|
||||
throw new \Exception("Object does not have a valid class type.");
|
||||
$this->assertPHPExists();
|
||||
|
||||
// Running validator
|
||||
$validator = new ClassValidator;
|
||||
try {
|
||||
$validator->validate(file_get_contents($this->phpFileName),
|
||||
$this->coid, $this->getAdditionalTypes());
|
||||
$output->writeln("Validated successfully.");
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln('<error>'.get_class($e).'</error> '.$e->getMessage());
|
||||
}
|
||||
|
||||
if ($input->getOption('watch')) {
|
||||
$cmd = $this;
|
||||
$this->watchPHPFile($output, function() use ($validator, $cmd, $output) {
|
||||
try {
|
||||
$validator->validate(file_get_contents($cmd->phpFileName),
|
||||
$this->coid, $this->getAdditionalTypes());
|
||||
$output->writeln("Validated successfully.");
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln('<error>'.get_class($e).'</error> '.$e->getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use CloudObjects\SDK\COIDParser;
|
||||
|
||||
class DependenciesAddAttachmentCommand extends AbstractObjectCommand {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('dependencies:add-attachment')
|
||||
->setDescription('Adds an attachment to the specification of a class.')
|
||||
->addArgument('coid-target', InputArgument::REQUIRED, 'The COID of the target class.')
|
||||
->addArgument('filename', InputArgument::REQUIRED, 'The name of the file that should be attached.')
|
||||
->addOption('upload', null, InputOption::VALUE_NONE, 'Calls "cloudobjects" to actually upload the file to CloudObjects.');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$this->requireCloudObjectsCLI();
|
||||
|
||||
$this->parse($input->getArgument('coid-target'));
|
||||
$this->assertRDF();
|
||||
$this->assertPHPExists();
|
||||
|
||||
$filename = $input->getArgument('filename');
|
||||
if (!file_exists($filename))
|
||||
throw new \Exception("File not found: ".$filename);
|
||||
|
||||
$fileUri = "file:///".basename($filename);
|
||||
|
||||
// Edit configuration
|
||||
$found = false;
|
||||
$object = $this->index[(string)$this->coid];
|
||||
if (isset($object['coid://phpmae.dev/usesAttachedFile'])) {
|
||||
foreach ($object['coid://phpmae.dev/usesAttachedFile'] as $o) {
|
||||
if ($o['type'] != 'uri') continue;
|
||||
if ($o['value'] == $fileUri) $found = true;
|
||||
}
|
||||
if (!$found)
|
||||
$object['coid://phpmae.dev/usesAttachedFile'][] = [ 'type' => 'uri', 'value' => $fileUri ];
|
||||
} else
|
||||
$object['coid://phpmae.dev/usesAttachedFile'] = [[ 'type' => 'uri', 'value' => $fileUri ]];
|
||||
|
||||
// Persist configuration
|
||||
if (!$found) {
|
||||
$this->index[(string)$this->coid] = $object;
|
||||
$this->updateRDFLocally($output);
|
||||
}
|
||||
|
||||
if ($input->getOption('upload') !== null) {
|
||||
$output->writeln("Calling cloudobjects ...");
|
||||
passthru("cloudobjects attachment:put ".(string)$this->coid." ".$filename);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use CloudObjects\SDK\COIDParser;
|
||||
|
||||
class DependenciesAddClassCommand extends AbstractAddDependenciesCommand {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('dependencies:add-class')
|
||||
->setDescription('Adds a class dependency to the specification of a class.')
|
||||
->addArgument('coid-target', InputArgument::REQUIRED, 'The COID of the target class.')
|
||||
->addOption('key', null, InputArgument::OPTIONAL, 'The key for dependency injection. Randomly generated if not provided.', null)
|
||||
->addArgument('coid-class', InputArgument::REQUIRED, 'The COID of the dependency class.');
|
||||
|
||||
parent::configure();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$this->requireCloudObjectsCLI();
|
||||
|
||||
$this->parse($input->getArgument('coid-target'));
|
||||
$this->dependencyPrecheck();
|
||||
|
||||
// Check Class
|
||||
$coidClass = COIDParser::fromString($input->getArgument('coid-class'));
|
||||
if (COIDParser::getType($coidClass) != COIDParser::COID_VERSIONED
|
||||
&& COIDParser::getType($coidClass) != COIDParser::COID_UNVERSIONED)
|
||||
throw new \Exception("Invalid COID: ".$coid);
|
||||
|
||||
// Checking type
|
||||
$output->writeln("Fetching configuration for ".(string)$coidClass." ...");
|
||||
$this->getObjectAndAssertType((string)$coidClass, 'coid://phpmae.dev/Class');
|
||||
|
||||
// Add dependency
|
||||
$this->addDependency(
|
||||
$input->getOption('key') ? $input->getOption('key') : uniqid('class-'),
|
||||
'coid://phpmae.dev/ClassDependency',
|
||||
[
|
||||
'coid://phpmae.dev/hasClass' => [
|
||||
[ 'type' => 'uri', 'value' => (string)$coidClass ]
|
||||
]
|
||||
],
|
||||
$input, $output
|
||||
);
|
||||
|
||||
// Print documentation
|
||||
$className = COIDParser::getName($coidClass);
|
||||
$key = $input->getOption('key') ? $input->getOption('key')
|
||||
: strtolower($className[0]).substr($className, 1);
|
||||
$output->writeln("");
|
||||
$output->writeln("<info>Use your class dependency:</info>");
|
||||
$output->writeln("");
|
||||
$output->writeln("1) Add the class ".$className." to your constructor parameters.");
|
||||
$output->writeln("2) Assign the class to \$this->".$key.".");
|
||||
$output->writeln("");
|
||||
$output->writeln(" private \$".$key.";");
|
||||
$output->writeln("");
|
||||
$output->writeln(" public function __construct(".$className." \$".$key.") {");
|
||||
$output->writeln(" \$this->".$key." = \$".$key.";");
|
||||
$output->writeln(" }");
|
||||
$output->writeln("");
|
||||
$output->writeln("3) Use \$this->".$key." wherever required.");
|
||||
$output->writeln("");
|
||||
$output->writeln("You can find the documentation for the available class methods on this page:");
|
||||
$output->writeln("➡️ https://cloudobjects.io/".$coidClass->getHost().$coidClass->getPath());
|
||||
$output->writeln("");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use CloudObjects\SDK\COIDParser;
|
||||
|
||||
class DependenciesAddStaticTextCommand extends AbstractAddDependenciesCommand {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('dependencies:add-text')
|
||||
->setDescription('Adds a static text dependency to the specification of a class.')
|
||||
->addArgument('coid-target', InputArgument::REQUIRED, 'The COID of the target class.')
|
||||
->addArgument('key', InputArgument::REQUIRED, 'The key for dependency injection.')
|
||||
->addArgument('value', InputArgument::REQUIRED, 'The text value.');
|
||||
|
||||
parent::configure();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$this->requireCloudObjectsCLI();
|
||||
|
||||
$this->parse($input->getArgument('coid-target'));
|
||||
$this->assertRDF();
|
||||
$this->dependencyPrecheck();
|
||||
|
||||
// Add dependency
|
||||
$this->addDependency(
|
||||
$input->getArgument('key'),
|
||||
'coid://phpmae.dev/StaticTextDependency',
|
||||
[
|
||||
'coid://phpmae.dev/hasValue' => [
|
||||
[ 'type' => 'literal', 'value' => $input->getArgument('value') ]
|
||||
]
|
||||
],
|
||||
$input, $output
|
||||
);
|
||||
|
||||
// Print documentation
|
||||
$key = $input->getArgument('key');
|
||||
$output->writeln("");
|
||||
$output->writeln("<info>Use your static text dependency:</info>");
|
||||
$output->writeln("");
|
||||
$output->writeln("1) Make sure you have access to the dependency injection container by adding the container to your class constructor.");
|
||||
$output->writeln("2) Request the value string from the container using the key \"".$key."\".");
|
||||
$output->writeln("");
|
||||
$output->writeln(" private \$".$key.";");
|
||||
$output->writeln("");
|
||||
$output->writeln(" public function __construct(\Psr\Container\ContainerInterface \$container) {");
|
||||
$output->writeln(" \$this->".$key." = \$container->get('".$key."');");
|
||||
$output->writeln(" }");
|
||||
$output->writeln("");
|
||||
$output->writeln("3) Use \$this->".$key." wherever required.");
|
||||
$output->writeln("");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use CloudObjects\SDK\COIDParser;
|
||||
|
||||
class DependenciesAddTemplateCommand extends AbstractAddDependenciesCommand {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('dependencies:add-template')
|
||||
->setDescription('Adds a Twig template dependency to the specification of a class.')
|
||||
->addArgument('coid-target', InputArgument::REQUIRED, 'The COID of the target class.')
|
||||
->addArgument('key', InputArgument::REQUIRED, 'The key for dependency injection.')
|
||||
->addArgument('filename', InputArgument::REQUIRED, 'The filename for the Twig template.')
|
||||
->addOption('upload', null, InputOption::VALUE_NONE, 'Calls "cloudobjects" to actually upload the template file to CloudObjects.');
|
||||
|
||||
parent::configure();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$this->requireCloudObjectsCLI();
|
||||
|
||||
$this->parse($input->getArgument('coid-target'));
|
||||
$this->dependencyPrecheck();
|
||||
|
||||
// Check filename
|
||||
$filename = $input->getArgument('filename');
|
||||
if (!file_exists($filename))
|
||||
throw new \Exception("File not found: ".$filename);
|
||||
|
||||
// Upload file if requested
|
||||
if ($input->getOption('upload')) {
|
||||
$output->writeln("Calling cloudobjects for file upload ...");
|
||||
passthru("cloudobjects attachment:put ".(string)$this->coid." ".$filename);
|
||||
}
|
||||
|
||||
// Add dependency
|
||||
$this->addDependency(
|
||||
$input->getArgument('key'),
|
||||
'coid://phpmae.dev/TwigTemplateDependency',
|
||||
[
|
||||
'coid://phpmae.dev/usesAttachedTwigFile' => [
|
||||
[ 'type' => 'uri', 'value' => "file:///".basename($filename) ]
|
||||
]
|
||||
],
|
||||
$input, $output
|
||||
);
|
||||
|
||||
// Print documentation
|
||||
$key = $input->getArgument('key');
|
||||
$output->writeln("");
|
||||
$output->writeln("<info>Use your Twig template dependency:</info>");
|
||||
$output->writeln("");
|
||||
$output->writeln("1) Make sure you have access to the dependency injection container by adding the container to your class constructor.");
|
||||
$output->writeln("2) Request the template from the container using the key \"".$key."\".");
|
||||
$output->writeln("");
|
||||
$output->writeln(" private \$".$key."Template;");
|
||||
$output->writeln("");
|
||||
$output->writeln(" public function __construct(\Psr\Container\ContainerInterface \$container) {");
|
||||
$output->writeln(" \$this->".$key."Template = \$container->get('".$key."');");
|
||||
$output->writeln(" }");
|
||||
$output->writeln("");
|
||||
$output->writeln("3) Render your template by calling \$this->".$key."Template->render(\$context).");
|
||||
$output->writeln("");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use CloudObjects\SDK\COIDParser;
|
||||
|
||||
class DependenciesAddWebAPICommand extends AbstractAddDependenciesCommand {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('dependencies:add-webapi')
|
||||
->setDescription('Adds a dependency to the specification of a class.')
|
||||
->addArgument('coid-target', InputArgument::REQUIRED, 'The COID of the target class.')
|
||||
->addArgument('key', InputArgument::REQUIRED, 'The key for dependency injection.')
|
||||
->addArgument('coid-webapi', InputArgument::REQUIRED, 'The COID of the Web API.');
|
||||
|
||||
parent::configure();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$this->requireCloudObjectsCLI();
|
||||
|
||||
$this->parse($input->getArgument('coid-target'));
|
||||
$this->dependencyPrecheck();
|
||||
|
||||
// Check Web API
|
||||
$coidWebAPI = COIDParser::fromString($input->getArgument('coid-webapi'));
|
||||
if (COIDParser::getType($coidWebAPI) != COIDParser::COID_VERSIONED
|
||||
&& COIDParser::getType($coidWebAPI) != COIDParser::COID_UNVERSIONED)
|
||||
throw new \Exception("Invalid COID: ".$coid);
|
||||
|
||||
// Checking type
|
||||
$output->writeln("Fetching configuration for ".(string)$coidWebAPI." ...");
|
||||
$this->getObjectAndAssertType((string)$coidWebAPI, 'coid://webapis.co-n.net/HTTPEndpoint');
|
||||
|
||||
// Add dependency
|
||||
$this->addDependency(
|
||||
$input->getArgument('key'),
|
||||
'coid://phpmae.dev/WebAPIDependency',
|
||||
[
|
||||
'coid://phpmae.dev/hasAPI' => [
|
||||
[ 'type' => 'uri', 'value' => (string)$coidWebAPI ]
|
||||
]
|
||||
],
|
||||
$input, $output
|
||||
);
|
||||
|
||||
// Print documentation
|
||||
$key = $input->getArgument('key');
|
||||
$output->writeln("");
|
||||
$output->writeln("<info>Use your WebAPI dependency:</info>");
|
||||
$output->writeln("");
|
||||
$output->writeln("1) Make sure you have access to the dependency injection container by adding the container to your class constructor.");
|
||||
$output->writeln("2) Request an API client from the container using the key \"".$key."\".");
|
||||
$output->writeln("");
|
||||
$output->writeln(" private \$".$key."Api;");
|
||||
$output->writeln("");
|
||||
$output->writeln(" public function __construct(\Psr\Container\ContainerInterface \$container) {");
|
||||
$output->writeln(" \$this->".$key."Api = \$container->get('".$key."');");
|
||||
$output->writeln(" }");
|
||||
$output->writeln("");
|
||||
$output->writeln("3) Make API requests in your class by calling methods on \$this->".$key."Api.");
|
||||
$output->writeln("");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use CloudObjects\SDK\COIDParser;
|
||||
use CloudObjects\PhpMAE\CredentialManager, CloudObjects\PhpMAE\ClassValidator;
|
||||
use CloudObjects\PhpMAE\Exceptions\PhpMAEException;
|
||||
|
||||
class InterfaceCreateCommand extends Command {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('interface:create')
|
||||
->setDescription('Create a new interface for the phpMAE.')
|
||||
->addArgument('coid', InputArgument::REQUIRED, 'The COID of the object.')
|
||||
->addOption('force', 'f', InputOption::VALUE_OPTIONAL, 'Forces new object creation and replaces existing files.', false)
|
||||
->addOption('confjob', null, InputOption::VALUE_OPTIONAL, 'Calls "cloudobjects" to create a configuration job for the new interface.', false);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
if (!CredentialManager::isConfigured())
|
||||
throw new \Exception("The 'cloudobjects' CLI tool must be installed and authorized.");
|
||||
|
||||
$coid = COIDParser::fromString($input->getArgument('coid'));
|
||||
|
||||
if (COIDParser::getType($coid)!=COIDParser::COID_VERSIONED
|
||||
&& COIDParser::getType($coid)!=COIDParser::COID_UNVERSIONED)
|
||||
throw new \Exception("Invalid COID: ".(string)$coid);
|
||||
|
||||
$name = COIDParser::getName($coid);
|
||||
$version = COIDParser::getVersion($coid);
|
||||
$fullName = isset($version) ? $name.".".$version : $name;
|
||||
|
||||
if (!file_exists($fullName.'.xml') || $input->getOption('force') !== false) {
|
||||
// Create RDF configuration file
|
||||
$content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
. "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"
|
||||
. " xmlns:co=\"coid://cloudobjects.io/\"\n"
|
||||
. " xmlns:phpmae=\"coid://phpmae.dev/\">\n"
|
||||
. "\n"
|
||||
. " <phpmae:Interface rdf:about=\"".(string)$coid."\">\n"
|
||||
. " <co:isVisibleTo rdf:resource=\"coid://cloudobjects.io/Vendor\" />\n"
|
||||
. " </phpmae:Interface>\n"
|
||||
. "</rdf:RDF>";
|
||||
file_put_contents($fullName.'.xml', $content);
|
||||
$output->writeln("Written ".$fullName.".xml.");
|
||||
} else {
|
||||
// RDF configuration file already exists
|
||||
$output->writeln($fullName.".xml already exists.");
|
||||
}
|
||||
|
||||
if (!file_exists($fullName.'.php') || $input->getOption('force') !== false) {
|
||||
// Create PHP source file
|
||||
$content = "<?php\n"
|
||||
. "\n"
|
||||
. "/**\n"
|
||||
. " * Definition for ".(string)$coid."\n"
|
||||
. " */\n"
|
||||
. "interface ".$name." {\n"
|
||||
. "\n"
|
||||
. " // Add methods here ...\n"
|
||||
. "\n"
|
||||
. "}";
|
||||
file_put_contents($fullName.'.php', $content);
|
||||
$output->writeln("Written ".$fullName.".php.");
|
||||
} else {
|
||||
$output->writeln($fullName.".php already exists.");
|
||||
}
|
||||
|
||||
if ($input->getOption('confjob') !== false) {
|
||||
$output->writeln("Calling cloudobjects ...");
|
||||
passthru("cloudobjects configuration-job:create ".$fullName.".xml");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use CloudObjects\SDK\COIDParser;
|
||||
use CloudObjects\PhpMAE\ClassValidator;
|
||||
|
||||
class InterfaceDeployCommand extends AbstractObjectCommand {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('interface:deploy')
|
||||
->setDescription('Validates an interface for the phpMAE and uploads it into CloudObjects. Updates the configuration if necessary.')
|
||||
->addArgument('coid', InputArgument::REQUIRED, 'The COID of the object.');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$this->parse($input->getArgument('coid'));
|
||||
$this->assertRDF();
|
||||
if (!in_array('coid://phpmae.dev/Interface', $this->rdfTypes))
|
||||
throw new \Exception("Object does not have athevalid interface type.");
|
||||
$this->assertPHPExists();
|
||||
|
||||
// Running validator
|
||||
$validator = new ClassValidator();
|
||||
$validator->validateInterface(file_get_contents($this->fullName.'.php'), $this->coid);
|
||||
$output->writeln("Validated successfully, calling cloudobjects ...");
|
||||
|
||||
passthru("cloudobjects attachment:put ".(string)$this->coid." ".$this->fullName.".php");
|
||||
|
||||
// Updates configuration if necessary
|
||||
if ($this->ensureFilenameInConfig($output, true)) {
|
||||
$this->createConfigurationJob($output);
|
||||
}
|
||||
|
||||
// Print URL so developer can easily access it
|
||||
$output->writeln("");
|
||||
$visibility = isset($object['coid://cloudobjects.io/isVisibleTo'])
|
||||
? $object['coid://cloudobjects.io/isVisibleTo'][0]['value']
|
||||
: 'coid://cloudobjects.io/Vendor';
|
||||
$path = $this->coid->getHost().$this->coid->getPath();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use CloudObjects\PhpMAE\ClassValidator;
|
||||
|
||||
class InterfaceValidateCommand extends AbstractObjectCommand {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('interface:validate')
|
||||
->setDescription('Validates an interface for the phpMAE.')
|
||||
->addArgument('coid', InputArgument::REQUIRED, 'The COID of the object.')
|
||||
->addOption('watch', null, InputOption::VALUE_OPTIONAL, 'Keep watching for changes of the file and revalidate automatically.', null);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$this->parse($input->getArgument('coid'));
|
||||
$this->assertRDF();
|
||||
if (!in_array('coid://phpmae.dev/Interface', $this->rdfTypes))
|
||||
throw new \Exception("Object does not have the valid interface type.");
|
||||
$this->assertPHPExists();
|
||||
|
||||
// Running validator
|
||||
$validator = new ClassValidator;
|
||||
try {
|
||||
$validator->validateInterface(file_get_contents($this->phpFileName), $this->coid);
|
||||
$output->writeln("Validated successfully.");
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln('<error>'.get_class($e).'</error> '.$e->getMessage());
|
||||
}
|
||||
|
||||
if ($input->getOption('watch') !== null) {
|
||||
$cmd = $this;
|
||||
$this->watchPHPFile($output, function() use ($validator, $cmd, $output) {
|
||||
try {
|
||||
$validator->validateInterface(file_get_contents($cmd->phpFileName), $this->coid);
|
||||
$output->writeln("Validated successfully.");
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln('<error>'.get_class($e).'</error> '.$e->getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace CloudObjects\PhpMAE\Commands;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use CloudObjects\PhpMAE\TestEnvironmentManager;
|
||||
use CloudObjects\PhpMAE\CredentialManager;
|
||||
|
||||
class TestEnvironmentStartCommand extends Command {
|
||||
|
||||
protected function configure() {
|
||||
$this->setName('testenv:start')
|
||||
->setDescription('Starts a local test environment.')
|
||||
->addOption('port', null, InputOption::VALUE_OPTIONAL, 'Use this port for test environment.', 9000)
|
||||
->addOption('host', null, InputOption::VALUE_OPTIONAL, 'Bind test environment to this host.', '127.0.0.1');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
if (!CredentialManager::isConfigured())
|
||||
throw new \Exception("The 'cloudobjects' CLI tool must be installed and authorized.");
|
||||
|
||||
$port = $input->getOption('port');
|
||||
$host = $input->getOption('host');
|
||||
|
||||
TestEnvironmentManager::setTestEnvironment('http://localhost:'.$port.'/');
|
||||
$output->writeln('Local webserver started on port '.$port.'.');
|
||||
$phar = \Phar::running();
|
||||
if (!$phar || $phar == "") {
|
||||
// Run extracted version
|
||||
$dir = realpath(__DIR__."/../../web/");
|
||||
passthru('cd '.$dir.'; php -S '.$host.':'.$port.' index.php');
|
||||
} else {
|
||||
// Run from phar
|
||||
if (strpos($phar, '.phar') !== false) {
|
||||
// Run directly
|
||||
passthru('php -S '.$host.':'.$port.' '.$phar.'/web/index.php');
|
||||
} else {
|
||||
// Create copy with .phar extension because PHP might not recognize the file otherwise
|
||||
$pharCp = sys_get_temp_dir().DIRECTORY_SEPARATOR.'phpmae.phar';
|
||||
copy(substr($phar, 7), $pharCp);
|
||||
passthru('php -S '.$host.':'.$port.' phar://'.$pharCp.'/web/index.php');
|
||||
die("THRU!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user