123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- <?php
- namespace Aws;
- use Psr\Http\Message\RequestInterface;
- use GuzzleHttp\ClientInterface;
- use GuzzleHttp\Promise\FulfilledPromise;
- //-----------------------------------------------------------------------------
- // Functional functions
- //-----------------------------------------------------------------------------
- /**
- * Returns a function that always returns the same value;
- *
- * @param mixed $value Value to return.
- *
- * @return callable
- */
- function constantly($value)
- {
- return function () use ($value) { return $value; };
- }
- /**
- * Filters values that do not satisfy the predicate function $pred.
- *
- * @param mixed $iterable Iterable sequence of data.
- * @param callable $pred Function that accepts a value and returns true/false
- *
- * @return \Generator
- */
- function filter($iterable, callable $pred)
- {
- foreach ($iterable as $value) {
- if ($pred($value)) {
- yield $value;
- }
- }
- }
- /**
- * Applies a map function $f to each value in a collection.
- *
- * @param mixed $iterable Iterable sequence of data.
- * @param callable $f Map function to apply.
- *
- * @return \Generator
- */
- function map($iterable, callable $f)
- {
- foreach ($iterable as $value) {
- yield $f($value);
- }
- }
- /**
- * Creates a generator that iterates over a sequence, then iterates over each
- * value in the sequence and yields the application of the map function to each
- * value.
- *
- * @param mixed $iterable Iterable sequence of data.
- * @param callable $f Map function to apply.
- *
- * @return \Generator
- */
- function flatmap($iterable, callable $f)
- {
- foreach (map($iterable, $f) as $outer) {
- foreach ($outer as $inner) {
- yield $inner;
- }
- }
- }
- /**
- * Partitions the input sequence into partitions of the specified size.
- *
- * @param mixed $iterable Iterable sequence of data.
- * @param int $size Size to make each partition (except possibly the last chunk)
- *
- * @return \Generator
- */
- function partition($iterable, $size)
- {
- $buffer = [];
- foreach ($iterable as $value) {
- $buffer[] = $value;
- if (count($buffer) === $size) {
- yield $buffer;
- $buffer = [];
- }
- }
- if ($buffer) {
- yield $buffer;
- }
- }
- /**
- * Returns a function that invokes the provided variadic functions one
- * after the other until one of the functions returns a non-null value.
- * The return function will call each passed function with any arguments it
- * is provided.
- *
- * $a = function ($x, $y) { return null; };
- * $b = function ($x, $y) { return $x + $y; };
- * $fn = \Aws\or_chain($a, $b);
- * echo $fn(1, 2); // 3
- *
- * @return callable
- */
- function or_chain()
- {
- $fns = func_get_args();
- return function () use ($fns) {
- $args = func_get_args();
- foreach ($fns as $fn) {
- $result = $args ? call_user_func_array($fn, $args) : $fn();
- if ($result) {
- return $result;
- }
- }
- return null;
- };
- }
- //-----------------------------------------------------------------------------
- // JSON compiler and loading functions
- //-----------------------------------------------------------------------------
- /**
- * Loads a compiled JSON file from a PHP file.
- *
- * If the JSON file has not been cached to disk as a PHP file, it will be loaded
- * from the JSON source file and returned.
- *
- * @param string $path Path to the JSON file on disk
- *
- * @return mixed Returns the JSON decoded data. Note that JSON objects are
- * decoded as associative arrays.
- */
- function load_compiled_json($path)
- {
- $compiledFilepath = "{$path}.php";
- if (is_readable($compiledFilepath)) {
- return include($compiledFilepath);
- }
- if (!file_exists($path)) {
- throw new \InvalidArgumentException(
- sprintf("File not found: %s", $path)
- );
- }
- return json_decode(file_get_contents($path), true);
- }
- /**
- * No-op
- */
- function clear_compiled_json()
- {
- // pass
- }
- //-----------------------------------------------------------------------------
- // Directory iterator functions.
- //-----------------------------------------------------------------------------
- /**
- * Iterates over the files in a directory and works with custom wrappers.
- *
- * @param string $path Path to open (e.g., "s3://foo/bar").
- * @param resource $context Stream wrapper context.
- *
- * @return \Generator Yields relative filename strings.
- */
- function dir_iterator($path, $context = null)
- {
- $dh = $context ? opendir($path, $context) : opendir($path);
- if (!$dh) {
- throw new \InvalidArgumentException('File not found: ' . $path);
- }
- while (($file = readdir($dh)) !== false) {
- yield $file;
- }
- closedir($dh);
- }
- /**
- * Returns a recursive directory iterator that yields absolute filenames.
- *
- * This iterator is not broken like PHP's built-in DirectoryIterator (which
- * will read the first file from a stream wrapper, then rewind, then read
- * it again).
- *
- * @param string $path Path to traverse (e.g., s3://bucket/key, /tmp)
- * @param resource $context Stream context options.
- *
- * @return \Generator Yields absolute filenames.
- */
- function recursive_dir_iterator($path, $context = null)
- {
- $invalid = ['.' => true, '..' => true];
- $pathLen = strlen($path) + 1;
- $iterator = dir_iterator($path, $context);
- $queue = [];
- do {
- while ($iterator->valid()) {
- $file = $iterator->current();
- $iterator->next();
- if (isset($invalid[basename($file)])) {
- continue;
- }
- $fullPath = "{$path}/{$file}";
- yield $fullPath;
- if (is_dir($fullPath)) {
- $queue[] = $iterator;
- $iterator = map(
- dir_iterator($fullPath, $context),
- function ($file) use ($fullPath, $pathLen) {
- return substr("{$fullPath}/{$file}", $pathLen);
- }
- );
- continue;
- }
- }
- $iterator = array_pop($queue);
- } while ($iterator);
- }
- //-----------------------------------------------------------------------------
- // Misc. functions.
- //-----------------------------------------------------------------------------
- /**
- * Debug function used to describe the provided value type and class.
- *
- * @param mixed $input
- *
- * @return string Returns a string containing the type of the variable and
- * if a class is provided, the class name.
- */
- function describe_type($input)
- {
- switch (gettype($input)) {
- case 'object':
- return 'object(' . get_class($input) . ')';
- case 'array':
- return 'array(' . count($input) . ')';
- default:
- ob_start();
- var_dump($input);
- // normalize float vs double
- return str_replace('double(', 'float(', rtrim(ob_get_clean()));
- }
- }
- /**
- * Creates a default HTTP handler based on the available clients.
- *
- * @return callable
- */
- function default_http_handler()
- {
- $version = (string) ClientInterface::VERSION;
- if ($version[0] === '5') {
- return new \Aws\Handler\GuzzleV5\GuzzleHandler();
- }
- if ($version[0] === '6') {
- return new \Aws\Handler\GuzzleV6\GuzzleHandler();
- }
- throw new \RuntimeException('Unknown Guzzle version: ' . $version);
- }
- /**
- * Gets the default user agent string depending on the Guzzle version
- *
- * @return string
- */
- function default_user_agent()
- {
- $version = (string) ClientInterface::VERSION;
- if ($version[0] === '5') {
- return \GuzzleHttp\Client::getDefaultUserAgent();
- }
- if ($version[0] === '6') {
- return \GuzzleHttp\default_user_agent();
- }
- throw new \RuntimeException('Unknown Guzzle version: ' . $version);
- }
- /**
- * Serialize a request for a command but do not send it.
- *
- * Returns a promise that is fulfilled with the serialized request.
- *
- * @param CommandInterface $command Command to serialize.
- *
- * @return RequestInterface
- * @throws \RuntimeException
- */
- function serialize(CommandInterface $command)
- {
- $request = null;
- $handlerList = $command->getHandlerList();
- // Return a mock result.
- $handlerList->setHandler(
- function (CommandInterface $_, RequestInterface $r) use (&$request) {
- $request = $r;
- return new FulfilledPromise(new Result([]));
- }
- );
- call_user_func($handlerList->resolve(), $command)->wait();
- if (!$request instanceof RequestInterface) {
- throw new \RuntimeException(
- 'Calling handler did not serialize request'
- );
- }
- return $request;
- }
- /**
- * Retrieves data for a service from the SDK's service manifest file.
- *
- * Manifest data is stored statically, so it does not need to be loaded more
- * than once per process. The JSON data is also cached in opcache.
- *
- * @param string $service Case-insensitive namespace or endpoint prefix of the
- * service for which you are retrieving manifest data.
- *
- * @return array
- * @throws \InvalidArgumentException if the service is not supported.
- */
- function manifest($service = null)
- {
- // Load the manifest and create aliases for lowercased namespaces
- static $manifest = [];
- static $aliases = [];
- if (empty($manifest)) {
- $manifest = load_compiled_json(__DIR__ . '/data/manifest.json');
- foreach ($manifest as $endpoint => $info) {
- $alias = strtolower($info['namespace']);
- if ($alias !== $endpoint) {
- $aliases[$alias] = $endpoint;
- }
- }
- }
- // If no service specified, then return the whole manifest.
- if ($service === null) {
- return $manifest;
- }
- // Look up the service's info in the manifest data.
- $service = strtolower($service);
- if (isset($manifest[$service])) {
- return $manifest[$service] + ['endpoint' => $service];
- }
- if (isset($aliases[$service])) {
- return manifest($aliases[$service]);
- }
- throw new \InvalidArgumentException(
- "The service \"{$service}\" is not provided by the AWS SDK for PHP."
- );
- }
- /**
- * Checks if supplied parameter is a valid hostname
- *
- * @param string $hostname
- * @return bool
- */
- function is_valid_hostname($hostname)
- {
- return (
- preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*\.?$/i", $hostname)
- && preg_match("/^.{1,253}$/", $hostname)
- && preg_match("/^[^\.]{1,63}(\.[^\.]{0,63})*$/", $hostname)
- );
- }
|