Skip to content

Commit b28f290

Browse files
stobrien89Sean O'Brien
andauthored
chore: api docs updates (#3231)
Co-authored-by: Sean O'Brien <[email protected]>
1 parent 06e91d2 commit b28f290

File tree

4 files changed

+135
-54
lines changed

4 files changed

+135
-54
lines changed

build/docs/classes/DocsBuilder.php

Lines changed: 127 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Aws\Api\Service as Api;
1010
use Aws\Api\StructureShape;
1111
use Aws\Api\DocModel;
12+
use GuzzleHttp\Client;
1213
use TokenReflection\Broker;
1314
use TokenReflection\ReflectionBase;
1415
use TokenReflection\ReflectionFunction;
@@ -21,6 +22,8 @@
2122
*/
2223
class DocsBuilder
2324
{
25+
private const EXAMPLES_URL = 'https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/php_code_examples.html';
26+
2427
/** @var string HTML template to replace {{ contents }} */
2528
private $template;
2629

@@ -48,6 +51,9 @@ class DocsBuilder
4851
/** @var bool Enables writing of build-issues.log file when set. */
4952
private $issueLoggingEnabled;
5053

54+
/** @var Client */
55+
private $guzzleClient;
56+
5157
/** @var array Printable error names for build-issues.log file */
5258
private static $ERROR_PRINT_NAMES =[
5359
E_ERROR => 'Error',
@@ -72,7 +78,8 @@ public function __construct(
7278
$baseUrl,
7379
array $quickLinks,
7480
array $sources,
75-
$issueLoggingEnabled = false
81+
$issueLoggingEnabled = false,
82+
?Client $guzzleClient = null
7683
) {
7784
$this->apiProvider = $provider;
7885
$this->outputDir = $outputDir;
@@ -81,6 +88,7 @@ public function __construct(
8188
$this->quickLinks = $quickLinks;
8289
$this->sources = $sources;
8390
$this->issueLoggingEnabled = $issueLoggingEnabled;
91+
$this->guzzleClient = $guzzleClient ?? new Client();
8492
}
8593

8694
public function build()
@@ -178,8 +186,8 @@ private function updateQuickLinks(array $services)
178186
// Determine which services in the provided array should have a quick link
179187
$services = array_filter($services, function (array $versions) {
180188
return 0 < count(array_filter($versions, function (Service $service) {
181-
return in_array($service->name, $this->quickLinks);
182-
}));
189+
return in_array($service->name, $this->quickLinks);
190+
}));
183191
});
184192

185193
// Drop all but the latest version of each service from the array
@@ -448,10 +456,62 @@ private function loadExamples($name, $version)
448456
}
449457
}
450458

459+
/**
460+
* Fetches service examples from the AWS SDK for PHP Developer Guide.
461+
*
462+
* @return array Associative array of service ID => documentation URL
463+
*/
464+
private function fetchServiceExamplesFromDocs(): array
465+
{
466+
try {
467+
$response = $this->guzzleClient->get(self::EXAMPLES_URL);
468+
$html = (string) $response->getBody();
469+
} catch (\Exception $e) {
470+
fwrite(STDERR, "Failed to fetch examples from docs: " . $e->getMessage() . "\n");
471+
return [];
472+
}
473+
474+
$doc = new \DOMDocument();
475+
@$doc->loadHTML($html);
476+
$xpath = new \DOMXPath($doc);
477+
478+
$canonicalNode = $xpath->query('//link[@rel="canonical"]/@href')->item(0);
479+
if (!$canonicalNode) {
480+
fwrite(STDERR, "Could not find canonical URL in examples page\n");
481+
return [];
482+
}
483+
$baseUrl = dirname($canonicalNode->nodeValue);
484+
485+
$links = $xpath->query('//div[@class="highlights"]//ul//a');
486+
487+
$services = [];
488+
foreach ($links as $link) {
489+
$href = $link->getAttribute('href');
490+
491+
// Extract service ID: remove "php_", "_code_examples.html", and leading "./"
492+
$serviceId = preg_replace('/^\.\//', '', $href);
493+
$serviceId = preg_replace('/^php_/', '', $serviceId);
494+
$serviceId = preg_replace('/_code_examples\.html$/', '', $serviceId);
495+
496+
$fullUrl = $baseUrl . '/' . ltrim($href, './');
497+
498+
$services[$serviceId] = $fullUrl;
499+
}
500+
501+
fwrite(STDOUT, "Fetched " . count($services) . " service examples from AWS docs\n");
502+
503+
return $services;
504+
}
505+
451506
private function updateClients(array $services)
452507
{
453508
fwrite(STDOUT, "Updating client pages with service links\n");
454509

510+
// Fetch new examples once for all services
511+
$newExamples = $this->fetchServiceExamplesFromDocs();
512+
$legacyExamples = require __DIR__ . '/../config/dev-guide-service-examples.php';
513+
$serviceIdMap = $legacyExamples['_service_id_map'] ?? [];
514+
455515
foreach ($services as $versions) {
456516
krsort($versions);
457517
$service = reset($versions);
@@ -483,16 +543,31 @@ private function updateClients(array $services)
483543
}
484544
$html .= '</ul></article>';
485545

486-
// Add Examples (from the developer guide) section, where applicable
487-
$serviceExamples = require __DIR__ . '/../config/dev-guide-service-examples.php';
488-
if (isset($serviceExamples[$service->name])) {
546+
// Add Examples section
547+
$docsServiceId = $serviceIdMap[$service->name] ?? $service->name;
548+
$hasNewExamples = isset($newExamples[$docsServiceId]);
549+
$hasLegacyExamples = isset($legacyExamples[$service->name]);
550+
551+
if ($hasNewExamples || $hasLegacyExamples) {
489552
$html .= '<h2>Examples</h2>';
490-
$html .= '<p>The following examples demonstrate how to use this service with the AWS SDK for PHP. These code examples are available in the <a href="' . $serviceExamples[$service->name]['landing_page'] . '">AWS SDK for PHP Developer Guide</a>.</p>';
491-
$html .= '<ul>';
492-
foreach ($serviceExamples[$service->name]['scenarios'] as $title => $link) {
493-
$html .= sprintf('<li><a href="%s">%s</a></li>', $link, $title);
553+
554+
if ($hasNewExamples) {
555+
$html .= '<h3>Basics, Actions and Scenarios</h3>';
556+
$html .= '<p>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) . '.</p>';
557+
$html .= '<ul>';
558+
$html .= sprintf('<li><a href="%s">See examples on AWS Docs</a></li>', htmlspecialchars($newExamples[$docsServiceId]));
559+
$html .= '</ul>';
560+
}
561+
562+
if ($hasLegacyExamples) {
563+
$html .= '<h3>Legacy Code Examples With Guidance</h3>';
564+
$html .= '<p>The following examples demonstrate how to use this service with the AWS SDK for PHP. These code examples are available in the <a href="' . htmlspecialchars($legacyExamples[$service->name]['landing_page']) . '">AWS SDK for PHP Developer Guide</a>.</p>';
565+
$html .= '<ul>';
566+
foreach ($legacyExamples[$service->name]['scenarios'] as $title => $link) {
567+
$html .= sprintf('<li><a href="%s">%s</a></li>', htmlspecialchars($link), htmlspecialchars($title));
568+
}
569+
$html .= '</ul>';
494570
}
495-
$html .= '</ul>';
496571
}
497572

498573
$this->replaceInner($service->clientLink, $html, '<!-- api -->');
@@ -744,26 +819,26 @@ private function createHtmlForWaiters(HtmlDocument $html, Api $service)
744819
$html->section(2, 'Waiters');
745820
$html->elem('p', 'phpdocumentor-summary', $desc);
746821
$html->open('table', 'table-responsive table-striped');
747-
$html->open('thead');
748-
$html->open('tr');
749-
$html->elem('th', null, 'Waiter name');
750-
$html->elem('th', null, 'API Operation');
751-
$html->elem('th', null, 'Delay');
752-
$html->elem('th', null, 'Max Attempts');
753-
$html->close();
754-
$html->close();
755-
$html->open('tbody');
756-
foreach ($waiters as $name => $config) {
757-
$html->open('tr');
758-
$html->elem('td', null, $name);
759-
$html->elem('td', null, '<a href="#'
760-
. strtolower($config['operation'])
761-
. '">' . $config['operation'] . '</a>');
762-
$html->elem('td', null, $config['delay']);
763-
$html->elem('td', null, $config['maxAttempts']);
764-
$html->close();
765-
}
822+
$html->open('thead');
823+
$html->open('tr');
824+
$html->elem('th', null, 'Waiter name');
825+
$html->elem('th', null, 'API Operation');
826+
$html->elem('th', null, 'Delay');
827+
$html->elem('th', null, 'Max Attempts');
828+
$html->close();
829+
$html->close();
830+
$html->open('tbody');
831+
foreach ($waiters as $name => $config) {
832+
$html->open('tr');
833+
$html->elem('td', null, $name);
834+
$html->elem('td', null, '<a href="#'
835+
. strtolower($config['operation'])
836+
. '">' . $config['operation'] . '</a>');
837+
$html->elem('td', null, $config['delay']);
838+
$html->elem('td', null, $config['maxAttempts']);
766839
$html->close();
840+
}
841+
$html->close();
767842
$html->close();
768843
}
769844

@@ -787,12 +862,12 @@ private function createHtmlForPaginators(HtmlDocument $html, Api $service)
787862
$html->section(2, 'Paginators');
788863
$html->elem('p', 'phpdocumentor-summary', $desc);
789864
$html->open('dl');
790-
foreach ($paginators as $name => $config) {
791-
$html->open('dt', 'phpdocumentor-table-of-contents__entry');
792-
$attr = ['href' => '#' . strtolower($name), 'aria-label' => strtolower($name)];
793-
$html->elem('a', $attr, '<strong>' . $name . '</strong>');
794-
$html->close();
795-
}
865+
foreach ($paginators as $name => $config) {
866+
$html->open('dt', 'phpdocumentor-table-of-contents__entry');
867+
$attr = ['href' => '#' . strtolower($name), 'aria-label' => strtolower($name)];
868+
$html->elem('a', $attr, '<strong>' . $name . '</strong>');
869+
$html->close();
870+
}
796871
$html->close();
797872
}
798873

@@ -890,15 +965,15 @@ private function createHtmlForOperation(Service $service, $name, Operation $oper
890965
?: 'This error does not currently have a description.';
891966
$html
892967
->open('dt')
893-
->elem(
894-
'a',
895-
[
896-
'href' => $service->exceptionLink . '#shape-'
897-
. strtolower($error->getName()),
898-
'aria-label' => strtolower($error->getName())
899-
],
900-
'<strong>' . $error['name'] . ': ' . '</strong>')
901-
->elem('dd', 'phpdocumentor-summary', $desc)
968+
->elem(
969+
'a',
970+
[
971+
'href' => $service->exceptionLink . '#shape-'
972+
. strtolower($error->getName()),
973+
'aria-label' => strtolower($error->getName())
974+
],
975+
'<strong>' . $error['name'] . ': ' . '</strong>')
976+
->elem('dd', 'phpdocumentor-summary', $desc)
902977
->close();
903978
}
904979
$html->close();
@@ -920,15 +995,15 @@ private function createHtmlForOperation(Service $service, $name, Operation $oper
920995
}
921996
$comments = $example['comments'] ?? [];
922997
$html->elem('pre', 'phpdocumentor-code', $generator->generateInput(
923-
$name,
924-
isset($example['input']) ? $example['input'] : [],
998+
$name,
999+
isset($example['input']) ? $example['input'] : [],
9251000
isset($comments['input']) ? $comments['input'] : []
9261001
));
9271002
if (isset($example['output'])) {
9281003
$html->elem('p', 'phpdocumentor-summary', 'Result syntax:');
9291004
$html->elem('pre', 'phpdocumentor-code', $generator->generateOutput(
930-
$name,
931-
$example['output'],
1005+
$name,
1006+
$example['output'],
9321007
isset($comments['output'])
9331008
? $comments['output']
9341009
: []
@@ -966,8 +1041,8 @@ private function logIssues($serviceName, $serviceVersion, $issuesToLog)
9661041
foreach ($shapeIssues as $level => $messages) {
9671042
foreach ($messages as $message => $exampleName) {
9681043
$this->issues[$level][$serviceName][$serviceVersion][
969-
$exampleName . ' has an issue - '
970-
. $message . ' on ' . $shapeName
1044+
$exampleName . ' has an issue - '
1045+
. $message . ' on ' . $shapeName
9711046
] = true;
9721047
}
9731048
}
@@ -1094,7 +1169,7 @@ function ($carry, $item) {
10941169
private function getDocumentText(StructureShape $member)
10951170
{
10961171
return 'document (null|bool|string|numeric) or an (array|associative array)'
1097-
. ' whose members are all valid documents';
1172+
. ' whose members are all valid documents';
10981173
}
10991174

11001175
private function getPrimitivePhpType($member)

build/docs/config/dev-guide-service-examples.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,11 @@
130130
'scenarios' => [
131131
'Send events to Amazon EventBridge global endpoints' => 'https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/eventbridge-examples.html'
132132
]
133+
],
134+
'_service_id_map' => [
135+
'apigateway' => 'api-gateway',
136+
'email' => 'ses',
137+
'autoscaling' => 'auto-scaling',
138+
'rds-data' => 'aurora',
133139
]
134140
];

build/remove-method-annotations.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function removeMethodAnnotations($dir, $fileSuffix) {
2020

2121
// Regular expression to match @method annotations
2222
// This pattern assumes @method annotations may span multiple lines and are within comment blocks
23-
$pattern = '/\*\s+@method\s+[^\n]+\n/';
23+
$pattern = '/^\s*\*\s+@method\s+[^\n]+\n/m';
2424

2525
if (preg_match($pattern, $content)) {
2626
// Remove @method annotations

src/AutoScaling/AutoScalingClient.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use Aws\AwsClient;
55

66
/**
7-
* Auto Scaling client.
7+
* This client is used to interact with the **AWS Auto Scaling** service.
88
*
99
* @method \Aws\Result attachInstances(array $args = [])
1010
* @method \GuzzleHttp\Promise\Promise attachInstancesAsync(array $args = [])

0 commit comments

Comments
 (0)