forked from aws/aws-sdk-php
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
398 additions
and
28 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
<?php | ||
|
||
/** | ||
* Adds and removes annotations to a class. | ||
* | ||
* @internal | ||
*/ | ||
class ClassAnnotationUpdater | ||
{ | ||
use PhpFileLinterTrait; | ||
|
||
/** @var ReflectionClass */ | ||
private $reflection; | ||
/** @var string[] */ | ||
private $linesToAppend; | ||
/** @var string */ | ||
private $defaultDocBlock; | ||
/** @var string */ | ||
private $removeMatching; | ||
|
||
public function __construct( | ||
ReflectionClass $reflection, | ||
array $linesToAppend, | ||
$defaultDocBlock, | ||
$removeMatching = '' | ||
) { | ||
$this->reflection = $reflection; | ||
$this->linesToAppend = $linesToAppend; | ||
$this->defaultDocBlock = $defaultDocBlock; | ||
$this->removeMatching = $removeMatching; | ||
} | ||
|
||
public function update() | ||
{ | ||
// copy the code into memory | ||
$backup = file($this->reflection->getFileName()); | ||
|
||
list($preamble, $class) = $this->splitClassFile($backup); | ||
$preamble = $this->stripOutExistingDocBlock($preamble); | ||
$preamble .= $this->buildUpdatedDocBlock(); | ||
|
||
if ($this->writeClassFile(implode(PHP_EOL, [$preamble, $class])) | ||
&& $this->lintFile($this->reflection->getFileName()) | ||
) { | ||
return true; | ||
} | ||
|
||
$this->writeClassFile(implode('', $backup)); | ||
return false; | ||
} | ||
|
||
private function splitClassFile(array $lines) | ||
{ | ||
$classLineOffset = $this->reflection->getStartLine() - 1; | ||
return [ | ||
implode('', array_slice($lines, 0, $classLineOffset)), | ||
implode('', array_slice($lines, $classLineOffset)), | ||
]; | ||
} | ||
|
||
private function stripOutExistingDocBlock($preamble) | ||
{ | ||
if ($this->reflection->getDocComment()) { | ||
return str_replace( | ||
$this->reflection->getDocComment() . PHP_EOL, | ||
'', | ||
$preamble | ||
); | ||
} | ||
|
||
return $preamble; | ||
} | ||
|
||
private function buildUpdatedDocBlock() | ||
{ | ||
$docBlockLines = explode( | ||
PHP_EOL, | ||
$this->reflection->getDocComment() ?: $this->defaultDocBlock | ||
); | ||
|
||
// remove lines matching exclusion patterns | ||
if ($this->removeMatching) { | ||
$docBlockLines = array_filter($docBlockLines, function ($line) { | ||
return !preg_match($this->removeMatching, trim($line)); | ||
}); | ||
} | ||
|
||
// hold on to the closing line | ||
$lastLine = array_pop($docBlockLines); | ||
|
||
// add a padding line if needed | ||
if (' *' !== end($docBlockLines)) { | ||
$docLines []= ' *'; | ||
} | ||
|
||
// append API @method annotations | ||
$docBlockLines = array_merge($docBlockLines, $this->linesToAppend); | ||
|
||
// add back the closing line | ||
$docBlockLines []= $lastLine; | ||
|
||
// send everything back as a string | ||
return implode(PHP_EOL, $docBlockLines); | ||
} | ||
|
||
private function writeClassFile($contents) | ||
{ | ||
return (bool) file_put_contents( | ||
$this->reflection->getFileName(), | ||
$contents, | ||
LOCK_EX | ||
); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
<?php | ||
|
||
use Aws\Api\ApiProvider; | ||
|
||
class ClientAnnotator | ||
{ | ||
use PhpFileLinterTrait; | ||
|
||
/** @var ReflectionClass */ | ||
private $reflection; | ||
|
||
public function __construct($clientClassName) | ||
{ | ||
$this->reflection = new ReflectionClass($clientClassName); | ||
} | ||
|
||
public function updateApiMethodAnnotations() | ||
{ | ||
return (new ClassAnnotationUpdater( | ||
$this->reflection, | ||
$this->getMethodAnnotations(), | ||
$this->getDefaultDocComment(), | ||
'/^\* @method \\\\Aws\\\\Result /' | ||
)) | ||
->update(); | ||
} | ||
|
||
private function getMethodAnnotations() | ||
{ | ||
$annotations = []; | ||
|
||
foreach ($this->getMethods() as $method => $apiVersions) { | ||
$signature = lcfirst($method) . '(array $args = [])'; | ||
$annotation = " * @method \\Aws\\Result $signature"; | ||
|
||
if ($apiVersions !== $this->getVersions()) { | ||
$supportedIn = implode(', ', $apiVersions); | ||
$annotation .= " (supported in versions $supportedIn)"; | ||
} | ||
|
||
$annotations []= $annotation; | ||
} | ||
|
||
return $annotations; | ||
} | ||
|
||
private function getMethods() | ||
{ | ||
static $methods; | ||
|
||
if (empty($methods)) { | ||
$methods = []; | ||
$provider = ApiProvider::defaultProvider(); | ||
|
||
foreach ($this->getVersions() as $version) { | ||
$methodsInVersion = array_keys( | ||
$provider('api', $this->getEndpoint(), $version)['operations'] | ||
); | ||
foreach ($methodsInVersion as $method) { | ||
if (empty($methods[$method])) { | ||
$methods[$method] = []; | ||
} | ||
|
||
$methods[$method] []= $version; | ||
} | ||
} | ||
} | ||
|
||
return $methods; | ||
} | ||
|
||
private function getVersions() | ||
{ | ||
static $versions; | ||
|
||
if (empty($versions)) { | ||
$versions = ApiProvider::defaultProvider() | ||
->getVersions($this->getEndpoint()); | ||
|
||
// ensure that versions are always iterated from oldest to newest | ||
sort($versions); | ||
} | ||
|
||
return $versions; | ||
} | ||
|
||
private function getApiDefinition() | ||
{ | ||
static $api; | ||
|
||
if (empty($api)) { | ||
$provider = ApiProvider::defaultProvider(); | ||
$api = $provider('api', $this->getEndpoint(), 'latest'); | ||
} | ||
|
||
return $api; | ||
} | ||
|
||
private function getEndpoint() | ||
{ | ||
static $endpoint; | ||
|
||
if (empty($endpoint)) { | ||
$service = strtolower( | ||
preg_replace('/Client$/', '', $this->reflection->getShortName()) | ||
); | ||
|
||
$endpoint = Aws\manifest($service)['endpoint']; | ||
} | ||
|
||
return $endpoint; | ||
} | ||
|
||
private function getDefaultDocComment() | ||
{ | ||
return <<<EODC | ||
/** | ||
* This client is used to interact with the **{$this->getApiDefinition()['metadata']['serviceFullName']}** service. | ||
*/ | ||
EODC; | ||
} | ||
} |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
|
||
/** | ||
* A trait that provides a method for linting a PHP file. It will use | ||
* `opcache_compile` if available and fall back to shelling out to `php -l` | ||
* otherwise. | ||
* | ||
* @internal | ||
*/ | ||
trait PhpFileLinterTrait | ||
{ | ||
|
||
/** | ||
* @param string $path | ||
* | ||
* @return bool | ||
*/ | ||
private function lintFile($path) | ||
{ | ||
static $linter; | ||
|
||
if (empty($linter)) { | ||
$linter = !empty(opcache_get_status(false)['opcache_enabled']) | ||
? [$this, 'opcacheLint'] | ||
: [$this, 'commandLineLint']; | ||
} | ||
|
||
return call_user_func($linter, $path); | ||
} | ||
|
||
/** | ||
* @param string $path | ||
* | ||
* @return bool | ||
*/ | ||
private function commandLineLint($path) | ||
{ | ||
list($output, $exitCode) = [[], 1]; | ||
exec("php -l $path", $output, $exitCode); | ||
|
||
return 0 === $exitCode; | ||
} | ||
|
||
/** | ||
* @param string $path | ||
* | ||
* @return bool | ||
*/ | ||
private function opcacheLint($path) | ||
{ | ||
opcache_invalidate($path, true); | ||
|
||
return @opcache_compile_file($path); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
/** | ||
* This file updates the '@method' annotations on the Aws\Sdk class. | ||
*/ | ||
|
||
require __DIR__ . '/../vendor/autoload.php'; | ||
|
||
$namespaces = array_map(function (array $manifest) { | ||
return $manifest['namespace']; | ||
}, array_values(Aws\manifest())); | ||
|
||
sort($namespaces); | ||
|
||
$annotations = array_map(function ($namespace) { | ||
return " * @method \\Aws\\{$namespace}\\{$namespace}Client" | ||
. " create{$namespace}(array \$args = [])"; | ||
}, $namespaces); | ||
$previousAnnotationPattern = '/^\* @method' | ||
. ' \\\\Aws\\\\(?:[a-zA-Z0-9]+)\\\\(?:[a-zA-Z0-9]+)Client' | ||
. ' create(?:[a-zA-Z0-9]+)\\(array \$args = \\[\\]\\)/'; | ||
|
||
(new ClassAnnotationUpdater( | ||
new ReflectionClass(\Aws\Sdk::class), | ||
$annotations, | ||
'', | ||
$previousAnnotationPattern | ||
)) | ||
->update(); |
Oops, something went wrong.