PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/api/vendor/aws/aws-sdk-php/src/Aws/S3/Sync/AbstractSyncBuilder.php

https://gitlab.com/x33n/respond
PHP | 435 lines | 188 code | 63 blank | 184 comment | 11 complexity | 7d1c544735d825f66189b6c2f7726ea4 MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License").
  6. * You may not use this file except in compliance with the License.
  7. * A copy of the License is located at
  8. *
  9. * http://aws.amazon.com/apache2.0
  10. *
  11. * or in the "license" file accompanying this file. This file is distributed
  12. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  13. * express or implied. See the License for the specific language governing
  14. * permissions and limitations under the License.
  15. */
  16. namespace Aws\S3\Sync;
  17. use Aws\Common\Exception\RuntimeException;
  18. use Aws\Common\Exception\UnexpectedValueException;
  19. use Aws\Common\Model\MultipartUpload\TransferInterface;
  20. use Aws\S3\S3Client;
  21. use Aws\S3\Iterator\OpendirIterator;
  22. use Guzzle\Common\Event;
  23. use Guzzle\Common\HasDispatcherInterface;
  24. use Guzzle\Iterator\FilterIterator;
  25. use Guzzle\Service\Command\CommandInterface;
  26. abstract class AbstractSyncBuilder
  27. {
  28. /** @var \Iterator Iterator that returns SplFileInfo objects to upload */
  29. protected $sourceIterator;
  30. /** @var S3Client Amazon S3 client used to send requests */
  31. protected $client;
  32. /** @var string Bucket used with the transfer */
  33. protected $bucket;
  34. /** @var int Number of files that can be transferred concurrently */
  35. protected $concurrency = 10;
  36. /** @var array Custom parameters to add to each operation sent while transferring */
  37. protected $params = array();
  38. /** @var FilenameConverterInterface */
  39. protected $sourceConverter;
  40. /** @var FilenameConverterInterface */
  41. protected $targetConverter;
  42. /** @var string Prefix at prepend to each Amazon S3 object key */
  43. protected $keyPrefix = '';
  44. /** @var string Directory separator for Amazon S3 keys */
  45. protected $delimiter = '/';
  46. /** @var string Base directory to remove from each file path before converting to an object name or file name */
  47. protected $baseDir;
  48. /** @var bool Whether or not to only transfer modified or new files */
  49. protected $forcing = false;
  50. /** @var bool Whether or not debug output is enable */
  51. protected $debug;
  52. /**
  53. * @return static
  54. */
  55. public static function getInstance()
  56. {
  57. return new static();
  58. }
  59. /**
  60. * Set the bucket to use with the sync
  61. *
  62. * @param string $bucket Amazon S3 bucket name
  63. *
  64. * @return $this
  65. */
  66. public function setBucket($bucket)
  67. {
  68. $this->bucket = $bucket;
  69. return $this;
  70. }
  71. /**
  72. * Set the Amazon S3 client object that will send requests
  73. *
  74. * @param S3Client $client Amazon S3 client
  75. *
  76. * @return $this
  77. */
  78. public function setClient(S3Client $client)
  79. {
  80. $this->client = $client;
  81. return $this;
  82. }
  83. /**
  84. * Set a custom iterator that returns \SplFileInfo objects for the source data
  85. *
  86. * @param \Iterator $iterator
  87. *
  88. * @return $this
  89. */
  90. public function setSourceIterator(\Iterator $iterator)
  91. {
  92. $this->sourceIterator = $iterator;
  93. return $this;
  94. }
  95. /**
  96. * Set a custom object key provider instead of building one internally
  97. *
  98. * @param FileNameConverterInterface $converter Filename to object key provider
  99. *
  100. * @return $this
  101. */
  102. public function setSourceFilenameConverter(FilenameConverterInterface $converter)
  103. {
  104. $this->sourceConverter = $converter;
  105. return $this;
  106. }
  107. /**
  108. * Set a custom object key provider instead of building one internally
  109. *
  110. * @param FileNameConverterInterface $converter Filename to object key provider
  111. *
  112. * @return $this
  113. */
  114. public function setTargetFilenameConverter(FilenameConverterInterface $converter)
  115. {
  116. $this->targetConverter = $converter;
  117. return $this;
  118. }
  119. /**
  120. * Set the base directory of the files being transferred. The base directory is removed from each file path before
  121. * converting the file path to an object key or vice versa.
  122. *
  123. * @param string $baseDir Base directory, which will be deleted from each uploaded object key
  124. *
  125. * @return $this
  126. */
  127. public function setBaseDir($baseDir)
  128. {
  129. $this->baseDir = $baseDir;
  130. return $this;
  131. }
  132. /**
  133. * Specify a prefix to prepend to each Amazon S3 object key or the prefix where object are stored in a bucket
  134. *
  135. * Can be used to upload files to a pseudo sub-folder key or only download files from a pseudo sub-folder
  136. *
  137. * @param string $keyPrefix Prefix for each uploaded key
  138. *
  139. * @return $this
  140. */
  141. public function setKeyPrefix($keyPrefix)
  142. {
  143. // Removing leading slash
  144. $this->keyPrefix = ltrim($keyPrefix, '/');
  145. return $this;
  146. }
  147. /**
  148. * Specify the delimiter used for the targeted filesystem (default delimiter is "/")
  149. *
  150. * @param string $delimiter Delimiter to use to separate paths
  151. *
  152. * @return $this
  153. */
  154. public function setDelimiter($delimiter)
  155. {
  156. $this->delimiter = $delimiter;
  157. return $this;
  158. }
  159. /**
  160. * Specify an array of operation parameters to apply to each operation executed by the sync object
  161. *
  162. * @param array $params Associative array of PutObject (upload) GetObject (download) parameters
  163. *
  164. * @return $this
  165. */
  166. public function setOperationParams(array $params)
  167. {
  168. $this->params = $params;
  169. return $this;
  170. }
  171. /**
  172. * Set the number of files that can be transferred concurrently
  173. *
  174. * @param int $concurrency Number of concurrent transfers
  175. *
  176. * @return $this
  177. */
  178. public function setConcurrency($concurrency)
  179. {
  180. $this->concurrency = $concurrency;
  181. return $this;
  182. }
  183. /**
  184. * Set to true to force transfers even if a file already exists and has not changed
  185. *
  186. * @param bool $force Set to true to force transfers without checking if it has changed
  187. *
  188. * @return $this
  189. */
  190. public function force($force = false)
  191. {
  192. $this->forcing = (bool) $force;
  193. return $this;
  194. }
  195. /**
  196. * Enable debug mode
  197. *
  198. * @param bool|resource $enabledOrResource Set to true or false to enable or disable debug output. Pass an opened
  199. * fopen resource to write to instead of writing to standard out.
  200. * @return $this
  201. */
  202. public function enableDebugOutput($enabledOrResource = true)
  203. {
  204. $this->debug = $enabledOrResource;
  205. return $this;
  206. }
  207. /**
  208. * Add a filename filter that uses a regular expression to filter out files that you do not wish to transfer.
  209. *
  210. * @param string $search Regular expression search (in preg_match format). Any filename that matches this regex
  211. * will not be transferred.
  212. * @return $this
  213. */
  214. public function addRegexFilter($search)
  215. {
  216. $this->assertFileIteratorSet();
  217. $this->sourceIterator = new FilterIterator($this->sourceIterator, function ($i) use ($search) {
  218. return !preg_match($search, (string) $i);
  219. });
  220. $this->sourceIterator->rewind();
  221. return $this;
  222. }
  223. /**
  224. * Builds a UploadSync or DownloadSync object
  225. *
  226. * @return AbstractSync
  227. */
  228. public function build()
  229. {
  230. $this->validateRequirements();
  231. $this->sourceConverter = $this->sourceConverter ?: $this->getDefaultSourceConverter();
  232. $this->targetConverter = $this->targetConverter ?: $this->getDefaultTargetConverter();
  233. // Only wrap the source iterator in a changed files iterator if we are not forcing the transfers
  234. if (!$this->forcing) {
  235. $this->sourceIterator->rewind();
  236. $this->sourceIterator = new ChangedFilesIterator(
  237. new \NoRewindIterator($this->sourceIterator),
  238. $this->getTargetIterator(),
  239. $this->sourceConverter,
  240. $this->targetConverter
  241. );
  242. $this->sourceIterator->rewind();
  243. }
  244. $sync = $this->specificBuild();
  245. if ($this->params) {
  246. $this->addCustomParamListener($sync);
  247. }
  248. if ($this->debug) {
  249. $this->addDebugListener($sync, is_bool($this->debug) ? STDOUT : $this->debug);
  250. }
  251. return $sync;
  252. }
  253. /**
  254. * Hook to implement in subclasses
  255. *
  256. * @return AbstractSync
  257. */
  258. abstract protected function specificBuild();
  259. /**
  260. * @return \Iterator
  261. */
  262. abstract protected function getTargetIterator();
  263. /**
  264. * @return FilenameConverterInterface
  265. */
  266. abstract protected function getDefaultSourceConverter();
  267. /**
  268. * @return FilenameConverterInterface
  269. */
  270. abstract protected function getDefaultTargetConverter();
  271. /**
  272. * Add a listener to the sync object to output debug information while transferring
  273. *
  274. * @param AbstractSync $sync Sync object to listen to
  275. * @param resource $resource Where to write debug messages
  276. */
  277. abstract protected function addDebugListener(AbstractSync $sync, $resource);
  278. /**
  279. * Validate that the builder has the minimal requirements
  280. *
  281. * @throws RuntimeException if the builder is not configured completely
  282. */
  283. protected function validateRequirements()
  284. {
  285. if (!$this->client) {
  286. throw new RuntimeException('No client was provided');
  287. }
  288. if (!$this->bucket) {
  289. throw new RuntimeException('No bucket was provided');
  290. }
  291. $this->assertFileIteratorSet();
  292. }
  293. /**
  294. * Ensure that the base file iterator has been provided
  295. *
  296. * @throws RuntimeException
  297. */
  298. protected function assertFileIteratorSet()
  299. {
  300. // Interesting... Need to use isset because: Object of class GlobIterator could not be converted to boolean
  301. if (!isset($this->sourceIterator)) {
  302. throw new RuntimeException('A source file iterator must be specified');
  303. }
  304. }
  305. /**
  306. * Wraps a generated iterator in a filter iterator that removes directories
  307. *
  308. * @param \Iterator $iterator Iterator to wrap
  309. *
  310. * @return \Iterator
  311. * @throws UnexpectedValueException
  312. */
  313. protected function filterIterator(\Iterator $iterator)
  314. {
  315. $f = new FilterIterator($iterator, function ($i) {
  316. if (!$i instanceof \SplFileInfo) {
  317. throw new UnexpectedValueException('All iterators for UploadSync must return SplFileInfo objects');
  318. }
  319. return $i->isFile();
  320. });
  321. $f->rewind();
  322. return $f;
  323. }
  324. /**
  325. * Add the custom param listener to a transfer object
  326. *
  327. * @param HasDispatcherInterface $sync
  328. */
  329. protected function addCustomParamListener(HasDispatcherInterface $sync)
  330. {
  331. $params = $this->params;
  332. $sync->getEventDispatcher()->addListener(
  333. UploadSync::BEFORE_TRANSFER,
  334. function (Event $e) use ($params) {
  335. if ($e['command'] instanceof CommandInterface) {
  336. $e['command']->overwriteWith($params);
  337. }
  338. }
  339. );
  340. }
  341. /**
  342. * Create an Amazon S3 file iterator based on the given builder settings
  343. *
  344. * @return OpendirIterator
  345. */
  346. protected function createS3Iterator()
  347. {
  348. // Ensure that the stream wrapper is registered
  349. $this->client->registerStreamWrapper();
  350. // Calculate the opendir() bucket and optional key prefix location
  351. $dir = "s3://{$this->bucket}";
  352. if ($this->keyPrefix) {
  353. $dir .= '/' . ltrim($this->keyPrefix, '/ ');
  354. }
  355. // Use opendir so that we can pass stream context to the iterator
  356. $dh = opendir($dir, stream_context_create(array(
  357. 's3' => array(
  358. 'delimiter' => '',
  359. 'listFilter' => function ($obj) {
  360. // Ensure that we do not try to download a glacier object.
  361. return !isset($obj['StorageClass']) ||
  362. $obj['StorageClass'] != 'GLACIER';
  363. }
  364. )
  365. )));
  366. // Add the trailing slash for the OpendirIterator concatenation
  367. if (!$this->keyPrefix) {
  368. $dir .= '/';
  369. }
  370. return $this->filterIterator(new \NoRewindIterator(new OpendirIterator($dh, $dir)));
  371. }
  372. }