From a8cca2eb33f0f3918c9d19114c89d63c60e92016 Mon Sep 17 00:00:00 2001 From: Sean O'Brien Date: Wed, 17 Dec 2025 19:28:03 -0500 Subject: [PATCH] chore: api docs updates --- build/docs/classes/DocsBuilder.php | 179 +++++++++++++----- .../config/dev-guide-service-examples.php | 6 + build/remove-method-annotations.php | 2 +- src/AutoScaling/AutoScalingClient.php | 2 +- 4 files changed, 135 insertions(+), 54 deletions(-) diff --git a/build/docs/classes/DocsBuilder.php b/build/docs/classes/DocsBuilder.php index 8645f0faba..486180568b 100644 --- a/build/docs/classes/DocsBuilder.php +++ b/build/docs/classes/DocsBuilder.php @@ -9,6 +9,7 @@ use Aws\Api\Service as Api; use Aws\Api\StructureShape; use Aws\Api\DocModel; +use GuzzleHttp\Client; use TokenReflection\Broker; use TokenReflection\ReflectionBase; use TokenReflection\ReflectionFunction; @@ -21,6 +22,8 @@ */ class DocsBuilder { + private const EXAMPLES_URL = 'https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/php_code_examples.html'; + /** @var string HTML template to replace {{ contents }} */ private $template; @@ -48,6 +51,9 @@ class DocsBuilder /** @var bool Enables writing of build-issues.log file when set. */ private $issueLoggingEnabled; + /** @var Client */ + private $guzzleClient; + /** @var array Printable error names for build-issues.log file */ private static $ERROR_PRINT_NAMES =[ E_ERROR => 'Error', @@ -72,7 +78,8 @@ public function __construct( $baseUrl, array $quickLinks, array $sources, - $issueLoggingEnabled = false + $issueLoggingEnabled = false, + ?Client $guzzleClient = null ) { $this->apiProvider = $provider; $this->outputDir = $outputDir; @@ -81,6 +88,7 @@ public function __construct( $this->quickLinks = $quickLinks; $this->sources = $sources; $this->issueLoggingEnabled = $issueLoggingEnabled; + $this->guzzleClient = $guzzleClient ?? new Client(); } public function build() @@ -178,8 +186,8 @@ private function updateQuickLinks(array $services) // Determine which services in the provided array should have a quick link $services = array_filter($services, function (array $versions) { return 0 < count(array_filter($versions, function (Service $service) { - return in_array($service->name, $this->quickLinks); - })); + return in_array($service->name, $this->quickLinks); + })); }); // Drop all but the latest version of each service from the array @@ -448,10 +456,62 @@ private function loadExamples($name, $version) } } + /** + * Fetches service examples from the AWS SDK for PHP Developer Guide. + * + * @return array Associative array of service ID => documentation URL + */ + private function fetchServiceExamplesFromDocs(): array + { + try { + $response = $this->guzzleClient->get(self::EXAMPLES_URL); + $html = (string) $response->getBody(); + } catch (\Exception $e) { + fwrite(STDERR, "Failed to fetch examples from docs: " . $e->getMessage() . "\n"); + return []; + } + + $doc = new \DOMDocument(); + @$doc->loadHTML($html); + $xpath = new \DOMXPath($doc); + + $canonicalNode = $xpath->query('//link[@rel="canonical"]/@href')->item(0); + if (!$canonicalNode) { + fwrite(STDERR, "Could not find canonical URL in examples page\n"); + return []; + } + $baseUrl = dirname($canonicalNode->nodeValue); + + $links = $xpath->query('//div[@class="highlights"]//ul//a'); + + $services = []; + foreach ($links as $link) { + $href = $link->getAttribute('href'); + + // Extract service ID: remove "php_", "_code_examples.html", and leading "./" + $serviceId = preg_replace('/^\.\//', '', $href); + $serviceId = preg_replace('/^php_/', '', $serviceId); + $serviceId = preg_replace('/_code_examples\.html$/', '', $serviceId); + + $fullUrl = $baseUrl . '/' . ltrim($href, './'); + + $services[$serviceId] = $fullUrl; + } + + fwrite(STDOUT, "Fetched " . count($services) . " service examples from AWS docs\n"); + + return $services; + } + private function updateClients(array $services) { fwrite(STDOUT, "Updating client pages with service links\n"); + // Fetch new examples once for all services + $newExamples = $this->fetchServiceExamplesFromDocs(); + $legacyExamples = require __DIR__ . '/../config/dev-guide-service-examples.php'; + $serviceIdMap = $legacyExamples['_service_id_map'] ?? []; + foreach ($services as $versions) { krsort($versions); $service = reset($versions); @@ -483,16 +543,31 @@ private function updateClients(array $services) } $html .= ''; - // Add Examples (from the developer guide) section, where applicable - $serviceExamples = require __DIR__ . '/../config/dev-guide-service-examples.php'; - if (isset($serviceExamples[$service->name])) { + // Add Examples section + $docsServiceId = $serviceIdMap[$service->name] ?? $service->name; + $hasNewExamples = isset($newExamples[$docsServiceId]); + $hasLegacyExamples = isset($legacyExamples[$service->name]); + + if ($hasNewExamples || $hasLegacyExamples) { $html .= '

Examples

'; - $html .= '

The following examples demonstrate how to use this service with the AWS SDK for PHP. These code examples are available in the AWS SDK for PHP Developer Guide.

'; - $html .= ''; } $this->replaceInner($service->clientLink, $html, ''); @@ -744,26 +819,26 @@ private function createHtmlForWaiters(HtmlDocument $html, Api $service) $html->section(2, 'Waiters'); $html->elem('p', 'phpdocumentor-summary', $desc); $html->open('table', 'table-responsive table-striped'); - $html->open('thead'); - $html->open('tr'); - $html->elem('th', null, 'Waiter name'); - $html->elem('th', null, 'API Operation'); - $html->elem('th', null, 'Delay'); - $html->elem('th', null, 'Max Attempts'); - $html->close(); - $html->close(); - $html->open('tbody'); - foreach ($waiters as $name => $config) { - $html->open('tr'); - $html->elem('td', null, $name); - $html->elem('td', null, '' . $config['operation'] . ''); - $html->elem('td', null, $config['delay']); - $html->elem('td', null, $config['maxAttempts']); - $html->close(); - } + $html->open('thead'); + $html->open('tr'); + $html->elem('th', null, 'Waiter name'); + $html->elem('th', null, 'API Operation'); + $html->elem('th', null, 'Delay'); + $html->elem('th', null, 'Max Attempts'); + $html->close(); + $html->close(); + $html->open('tbody'); + foreach ($waiters as $name => $config) { + $html->open('tr'); + $html->elem('td', null, $name); + $html->elem('td', null, '' . $config['operation'] . ''); + $html->elem('td', null, $config['delay']); + $html->elem('td', null, $config['maxAttempts']); $html->close(); + } + $html->close(); $html->close(); } @@ -787,12 +862,12 @@ private function createHtmlForPaginators(HtmlDocument $html, Api $service) $html->section(2, 'Paginators'); $html->elem('p', 'phpdocumentor-summary', $desc); $html->open('dl'); - foreach ($paginators as $name => $config) { - $html->open('dt', 'phpdocumentor-table-of-contents__entry'); - $attr = ['href' => '#' . strtolower($name), 'aria-label' => strtolower($name)]; - $html->elem('a', $attr, '' . $name . ''); - $html->close(); - } + foreach ($paginators as $name => $config) { + $html->open('dt', 'phpdocumentor-table-of-contents__entry'); + $attr = ['href' => '#' . strtolower($name), 'aria-label' => strtolower($name)]; + $html->elem('a', $attr, '' . $name . ''); + $html->close(); + } $html->close(); } @@ -890,15 +965,15 @@ private function createHtmlForOperation(Service $service, $name, Operation $oper ?: 'This error does not currently have a description.'; $html ->open('dt') - ->elem( - 'a', - [ - 'href' => $service->exceptionLink . '#shape-' - . strtolower($error->getName()), - 'aria-label' => strtolower($error->getName()) - ], - '' . $error['name'] . ': ' . '') - ->elem('dd', 'phpdocumentor-summary', $desc) + ->elem( + 'a', + [ + 'href' => $service->exceptionLink . '#shape-' + . strtolower($error->getName()), + 'aria-label' => strtolower($error->getName()) + ], + '' . $error['name'] . ': ' . '') + ->elem('dd', 'phpdocumentor-summary', $desc) ->close(); } $html->close(); @@ -920,15 +995,15 @@ private function createHtmlForOperation(Service $service, $name, Operation $oper } $comments = $example['comments'] ?? []; $html->elem('pre', 'phpdocumentor-code', $generator->generateInput( - $name, - isset($example['input']) ? $example['input'] : [], + $name, + isset($example['input']) ? $example['input'] : [], isset($comments['input']) ? $comments['input'] : [] )); if (isset($example['output'])) { $html->elem('p', 'phpdocumentor-summary', 'Result syntax:'); $html->elem('pre', 'phpdocumentor-code', $generator->generateOutput( - $name, - $example['output'], + $name, + $example['output'], isset($comments['output']) ? $comments['output'] : [] @@ -966,8 +1041,8 @@ private function logIssues($serviceName, $serviceVersion, $issuesToLog) foreach ($shapeIssues as $level => $messages) { foreach ($messages as $message => $exampleName) { $this->issues[$level][$serviceName][$serviceVersion][ - $exampleName . ' has an issue - ' - . $message . ' on ' . $shapeName + $exampleName . ' has an issue - ' + . $message . ' on ' . $shapeName ] = true; } } @@ -1094,7 +1169,7 @@ function ($carry, $item) { private function getDocumentText(StructureShape $member) { return 'document (null|bool|string|numeric) or an (array|associative array)' - . ' whose members are all valid documents'; + . ' whose members are all valid documents'; } private function getPrimitivePhpType($member) diff --git a/build/docs/config/dev-guide-service-examples.php b/build/docs/config/dev-guide-service-examples.php index 27878b9310..896d0a2674 100644 --- a/build/docs/config/dev-guide-service-examples.php +++ b/build/docs/config/dev-guide-service-examples.php @@ -130,5 +130,11 @@ 'scenarios' => [ 'Send events to Amazon EventBridge global endpoints' => 'https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/eventbridge-examples.html' ] + ], + '_service_id_map' => [ + 'apigateway' => 'api-gateway', + 'email' => 'ses', + 'autoscaling' => 'auto-scaling', + 'rds-data' => 'aurora', ] ]; diff --git a/build/remove-method-annotations.php b/build/remove-method-annotations.php index 4056614574..92027835a0 100644 --- a/build/remove-method-annotations.php +++ b/build/remove-method-annotations.php @@ -20,7 +20,7 @@ function removeMethodAnnotations($dir, $fileSuffix) { // Regular expression to match @method annotations // This pattern assumes @method annotations may span multiple lines and are within comment blocks - $pattern = '/\*\s+@method\s+[^\n]+\n/'; + $pattern = '/^\s*\*\s+@method\s+[^\n]+\n/m'; if (preg_match($pattern, $content)) { // Remove @method annotations diff --git a/src/AutoScaling/AutoScalingClient.php b/src/AutoScaling/AutoScalingClient.php index 59ea026a44..13500cbdcb 100644 --- a/src/AutoScaling/AutoScalingClient.php +++ b/src/AutoScaling/AutoScalingClient.php @@ -4,7 +4,7 @@ use Aws\AwsClient; /** - * Auto Scaling client. + * This client is used to interact with the **AWS Auto Scaling** service. * * @method \Aws\Result attachInstances(array $args = []) * @method \GuzzleHttp\Promise\Promise attachInstancesAsync(array $args = [])