ListObjectsV2Output.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <?php
  2. namespace AsyncAws\S3\Result;
  3. use AsyncAws\Core\Exception\InvalidArgument;
  4. use AsyncAws\Core\Response;
  5. use AsyncAws\Core\Result;
  6. use AsyncAws\S3\Enum\ChecksumAlgorithm;
  7. use AsyncAws\S3\Enum\EncodingType;
  8. use AsyncAws\S3\Enum\RequestCharged;
  9. use AsyncAws\S3\Input\ListObjectsV2Request;
  10. use AsyncAws\S3\S3Client;
  11. use AsyncAws\S3\ValueObject\AwsObject;
  12. use AsyncAws\S3\ValueObject\CommonPrefix;
  13. use AsyncAws\S3\ValueObject\Owner;
  14. /**
  15. * @implements \IteratorAggregate<AwsObject|CommonPrefix>
  16. */
  17. class ListObjectsV2Output extends Result implements \IteratorAggregate
  18. {
  19. /**
  20. * Set to false if all of the results were returned. Set to true if more keys are available to return. If the number of
  21. * results exceeds that specified by MaxKeys, all of the results might not be returned.
  22. */
  23. private $isTruncated;
  24. /**
  25. * Metadata about each object returned.
  26. */
  27. private $contents;
  28. /**
  29. * The bucket name.
  30. *
  31. * When using this action with an access point, you must direct requests to the access point hostname. The access point
  32. * hostname takes the form *AccessPointName*-*AccountId*.s3-accesspoint.*Region*.amazonaws.com. When using this action
  33. * with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket
  34. * name. For more information about access point ARNs, see Using access points [^1] in the *Amazon S3 User Guide*.
  35. *
  36. * When you use this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3
  37. * on Outposts hostname takes the form `*AccessPointName*-*AccountId*.*outpostID*.s3-outposts.*Region*.amazonaws.com`.
  38. * When you use this action with S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts access
  39. * point ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see What is S3 on Outposts
  40. * [^2] in the *Amazon S3 User Guide*.
  41. *
  42. * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-access-points.html
  43. * [^2]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/S3onOutposts.html
  44. */
  45. private $name;
  46. /**
  47. * Keys that begin with the indicated prefix.
  48. */
  49. private $prefix;
  50. /**
  51. * Causes keys that contain the same string between the prefix and the first occurrence of the delimiter to be rolled up
  52. * into a single result element in the CommonPrefixes collection. These rolled-up keys are not returned elsewhere in the
  53. * response. Each rolled-up result counts as only one return against the `MaxKeys` value.
  54. */
  55. private $delimiter;
  56. /**
  57. * Sets the maximum number of keys returned in the response. By default the action returns up to 1,000 key names. The
  58. * response might contain fewer keys but will never contain more.
  59. */
  60. private $maxKeys;
  61. /**
  62. * All of the keys (up to 1,000) rolled up into a common prefix count as a single return when calculating the number of
  63. * returns.
  64. *
  65. * A response can contain `CommonPrefixes` only if you specify a delimiter.
  66. *
  67. * `CommonPrefixes` contains all (if there are any) keys between `Prefix` and the next occurrence of the string
  68. * specified by a delimiter.
  69. *
  70. * `CommonPrefixes` lists keys that act like subdirectories in the directory specified by `Prefix`.
  71. *
  72. * For example, if the prefix is `notes/` and the delimiter is a slash (`/`) as in `notes/summer/july`, the common
  73. * prefix is `notes/summer/`. All of the keys that roll up into a common prefix count as a single return when
  74. * calculating the number of returns.
  75. */
  76. private $commonPrefixes;
  77. /**
  78. * Encoding type used by Amazon S3 to encode object key names in the XML response.
  79. *
  80. * If you specify the encoding-type request parameter, Amazon S3 includes this element in the response, and returns
  81. * encoded key name values in the following response elements:
  82. *
  83. * `Delimiter, Prefix, Key,` and `StartAfter`.
  84. */
  85. private $encodingType;
  86. /**
  87. * KeyCount is the number of keys returned with this request. KeyCount will always be less than or equal to the
  88. * `MaxKeys` field. Say you ask for 50 keys, your result will include 50 keys or fewer.
  89. */
  90. private $keyCount;
  91. /**
  92. * If ContinuationToken was sent with the request, it is included in the response.
  93. */
  94. private $continuationToken;
  95. /**
  96. * `NextContinuationToken` is sent when `isTruncated` is true, which means there are more keys in the bucket that can be
  97. * listed. The next list requests to Amazon S3 can be continued with this `NextContinuationToken`.
  98. * `NextContinuationToken` is obfuscated and is not a real key.
  99. */
  100. private $nextContinuationToken;
  101. /**
  102. * If StartAfter was sent with the request, it is included in the response.
  103. */
  104. private $startAfter;
  105. private $requestCharged;
  106. /**
  107. * @param bool $currentPageOnly When true, iterates over items of the current page. Otherwise also fetch items in the next pages.
  108. *
  109. * @return iterable<CommonPrefix>
  110. */
  111. public function getCommonPrefixes(bool $currentPageOnly = false): iterable
  112. {
  113. if ($currentPageOnly) {
  114. $this->initialize();
  115. yield from $this->commonPrefixes;
  116. return;
  117. }
  118. $client = $this->awsClient;
  119. if (!$client instanceof S3Client) {
  120. throw new InvalidArgument('missing client injected in paginated result');
  121. }
  122. if (!$this->input instanceof ListObjectsV2Request) {
  123. throw new InvalidArgument('missing last request injected in paginated result');
  124. }
  125. $input = clone $this->input;
  126. $page = $this;
  127. while (true) {
  128. $page->initialize();
  129. if ($page->nextContinuationToken) {
  130. $input->setContinuationToken($page->nextContinuationToken);
  131. $this->registerPrefetch($nextPage = $client->listObjectsV2($input));
  132. } else {
  133. $nextPage = null;
  134. }
  135. yield from $page->commonPrefixes;
  136. if (null === $nextPage) {
  137. break;
  138. }
  139. $this->unregisterPrefetch($nextPage);
  140. $page = $nextPage;
  141. }
  142. }
  143. /**
  144. * @param bool $currentPageOnly When true, iterates over items of the current page. Otherwise also fetch items in the next pages.
  145. *
  146. * @return iterable<AwsObject>
  147. */
  148. public function getContents(bool $currentPageOnly = false): iterable
  149. {
  150. if ($currentPageOnly) {
  151. $this->initialize();
  152. yield from $this->contents;
  153. return;
  154. }
  155. $client = $this->awsClient;
  156. if (!$client instanceof S3Client) {
  157. throw new InvalidArgument('missing client injected in paginated result');
  158. }
  159. if (!$this->input instanceof ListObjectsV2Request) {
  160. throw new InvalidArgument('missing last request injected in paginated result');
  161. }
  162. $input = clone $this->input;
  163. $page = $this;
  164. while (true) {
  165. $page->initialize();
  166. if ($page->nextContinuationToken) {
  167. $input->setContinuationToken($page->nextContinuationToken);
  168. $this->registerPrefetch($nextPage = $client->listObjectsV2($input));
  169. } else {
  170. $nextPage = null;
  171. }
  172. yield from $page->contents;
  173. if (null === $nextPage) {
  174. break;
  175. }
  176. $this->unregisterPrefetch($nextPage);
  177. $page = $nextPage;
  178. }
  179. }
  180. public function getContinuationToken(): ?string
  181. {
  182. $this->initialize();
  183. return $this->continuationToken;
  184. }
  185. public function getDelimiter(): ?string
  186. {
  187. $this->initialize();
  188. return $this->delimiter;
  189. }
  190. /**
  191. * @return EncodingType::*|null
  192. */
  193. public function getEncodingType(): ?string
  194. {
  195. $this->initialize();
  196. return $this->encodingType;
  197. }
  198. public function getIsTruncated(): ?bool
  199. {
  200. $this->initialize();
  201. return $this->isTruncated;
  202. }
  203. /**
  204. * Iterates over Contents and CommonPrefixes.
  205. *
  206. * @return \Traversable<AwsObject|CommonPrefix>
  207. */
  208. public function getIterator(): \Traversable
  209. {
  210. $client = $this->awsClient;
  211. if (!$client instanceof S3Client) {
  212. throw new InvalidArgument('missing client injected in paginated result');
  213. }
  214. if (!$this->input instanceof ListObjectsV2Request) {
  215. throw new InvalidArgument('missing last request injected in paginated result');
  216. }
  217. $input = clone $this->input;
  218. $page = $this;
  219. while (true) {
  220. $page->initialize();
  221. if ($page->nextContinuationToken) {
  222. $input->setContinuationToken($page->nextContinuationToken);
  223. $this->registerPrefetch($nextPage = $client->listObjectsV2($input));
  224. } else {
  225. $nextPage = null;
  226. }
  227. yield from $page->getContents(true);
  228. yield from $page->getCommonPrefixes(true);
  229. if (null === $nextPage) {
  230. break;
  231. }
  232. $this->unregisterPrefetch($nextPage);
  233. $page = $nextPage;
  234. }
  235. }
  236. public function getKeyCount(): ?int
  237. {
  238. $this->initialize();
  239. return $this->keyCount;
  240. }
  241. public function getMaxKeys(): ?int
  242. {
  243. $this->initialize();
  244. return $this->maxKeys;
  245. }
  246. public function getName(): ?string
  247. {
  248. $this->initialize();
  249. return $this->name;
  250. }
  251. public function getNextContinuationToken(): ?string
  252. {
  253. $this->initialize();
  254. return $this->nextContinuationToken;
  255. }
  256. public function getPrefix(): ?string
  257. {
  258. $this->initialize();
  259. return $this->prefix;
  260. }
  261. /**
  262. * @return RequestCharged::*|null
  263. */
  264. public function getRequestCharged(): ?string
  265. {
  266. $this->initialize();
  267. return $this->requestCharged;
  268. }
  269. public function getStartAfter(): ?string
  270. {
  271. $this->initialize();
  272. return $this->startAfter;
  273. }
  274. protected function populateResult(Response $response): void
  275. {
  276. $headers = $response->getHeaders();
  277. $this->requestCharged = $headers['x-amz-request-charged'][0] ?? null;
  278. $data = new \SimpleXMLElement($response->getContent());
  279. $this->isTruncated = ($v = $data->IsTruncated) ? filter_var((string) $v, \FILTER_VALIDATE_BOOLEAN) : null;
  280. $this->contents = !$data->Contents ? [] : $this->populateResultObjectList($data->Contents);
  281. $this->name = ($v = $data->Name) ? (string) $v : null;
  282. $this->prefix = ($v = $data->Prefix) ? (string) $v : null;
  283. $this->delimiter = ($v = $data->Delimiter) ? (string) $v : null;
  284. $this->maxKeys = ($v = $data->MaxKeys) ? (int) (string) $v : null;
  285. $this->commonPrefixes = !$data->CommonPrefixes ? [] : $this->populateResultCommonPrefixList($data->CommonPrefixes);
  286. $this->encodingType = ($v = $data->EncodingType) ? (string) $v : null;
  287. $this->keyCount = ($v = $data->KeyCount) ? (int) (string) $v : null;
  288. $this->continuationToken = ($v = $data->ContinuationToken) ? (string) $v : null;
  289. $this->nextContinuationToken = ($v = $data->NextContinuationToken) ? (string) $v : null;
  290. $this->startAfter = ($v = $data->StartAfter) ? (string) $v : null;
  291. }
  292. /**
  293. * @return list<ChecksumAlgorithm::*>
  294. */
  295. private function populateResultChecksumAlgorithmList(\SimpleXMLElement $xml): array
  296. {
  297. $items = [];
  298. foreach ($xml as $item) {
  299. $a = ($v = $item) ? (string) $v : null;
  300. if (null !== $a) {
  301. $items[] = $a;
  302. }
  303. }
  304. return $items;
  305. }
  306. /**
  307. * @return CommonPrefix[]
  308. */
  309. private function populateResultCommonPrefixList(\SimpleXMLElement $xml): array
  310. {
  311. $items = [];
  312. foreach ($xml as $item) {
  313. $items[] = new CommonPrefix([
  314. 'Prefix' => ($v = $item->Prefix) ? (string) $v : null,
  315. ]);
  316. }
  317. return $items;
  318. }
  319. /**
  320. * @return AwsObject[]
  321. */
  322. private function populateResultObjectList(\SimpleXMLElement $xml): array
  323. {
  324. $items = [];
  325. foreach ($xml as $item) {
  326. $items[] = new AwsObject([
  327. 'Key' => ($v = $item->Key) ? (string) $v : null,
  328. 'LastModified' => ($v = $item->LastModified) ? new \DateTimeImmutable((string) $v) : null,
  329. 'ETag' => ($v = $item->ETag) ? (string) $v : null,
  330. 'ChecksumAlgorithm' => !$item->ChecksumAlgorithm ? null : $this->populateResultChecksumAlgorithmList($item->ChecksumAlgorithm),
  331. 'Size' => ($v = $item->Size) ? (string) $v : null,
  332. 'StorageClass' => ($v = $item->StorageClass) ? (string) $v : null,
  333. 'Owner' => !$item->Owner ? null : new Owner([
  334. 'DisplayName' => ($v = $item->Owner->DisplayName) ? (string) $v : null,
  335. 'ID' => ($v = $item->Owner->ID) ? (string) $v : null,
  336. ]),
  337. ]);
  338. }
  339. return $items;
  340. }
  341. }