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 .= '';
- foreach ($serviceExamples[$service->name]['scenarios'] as $title => $link) {
- $html .= sprintf('- %s
', $link, $title);
+
+ if ($hasNewExamples) {
+ $html .= 'Basics, Actions and Scenarios
';
+ $html .= 'The following code examples show you how to perform actions and implement common scenarios by using the AWS SDK for PHP with ' . htmlspecialchars($service->title) . '.
';
+ $html .= '';
+ }
+
+ if ($hasLegacyExamples) {
+ $html .= 'Legacy Code Examples With Guidance
';
+ $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 .= '';
+ foreach ($legacyExamples[$service->name]['scenarios'] as $title => $link) {
+ $html .= sprintf('- %s
', htmlspecialchars($link), htmlspecialchars($title));
+ }
+ $html .= '
';
}
- $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 = [])