1<?php 2namespace Aws; 3 4use Aws\Exception\AwsException; 5use GuzzleHttp\Promise; 6use GuzzleHttp\Promise\RejectedPromise; 7use Psr\Http\Message\RequestInterface; 8use Exception; 9 10/** 11 * Returns promises that are rejected or fulfilled using a queue of 12 * Aws\ResultInterface and Aws\Exception\AwsException objects. 13 */ 14class MockHandler implements \Countable 15{ 16 private $queue; 17 private $lastCommand; 18 private $lastRequest; 19 private $onFulfilled; 20 private $onRejected; 21 22 /** 23 * The passed in value must be an array of {@see Aws\ResultInterface} or 24 * {@see AwsException} objects that acts as a queue of results or 25 * exceptions to return each time the handler is invoked. 26 * 27 * @param array $resultOrQueue 28 * @param callable $onFulfilled Callback to invoke when the return value is fulfilled. 29 * @param callable $onRejected Callback to invoke when the return value is rejected. 30 */ 31 public function __construct( 32 array $resultOrQueue = [], 33 callable $onFulfilled = null, 34 callable $onRejected = null 35 ) { 36 $this->onFulfilled = $onFulfilled; 37 $this->onRejected = $onRejected; 38 39 if ($resultOrQueue) { 40 call_user_func_array([$this, 'append'], $resultOrQueue); 41 } 42 } 43 44 /** 45 * Adds one or more variadic ResultInterface or AwsException objects to the 46 * queue. 47 */ 48 public function append() 49 { 50 foreach (func_get_args() as $value) { 51 if ($value instanceof ResultInterface 52 || $value instanceof Exception 53 || is_callable($value) 54 ) { 55 $this->queue[] = $value; 56 } else { 57 throw new \InvalidArgumentException('Expected an Aws\ResultInterface or Exception.'); 58 } 59 } 60 } 61 62 /** 63 * Adds one or more \Exception or \Throwable to the queue 64 */ 65 public function appendException() 66 { 67 foreach (func_get_args() as $value) { 68 if ($value instanceof \Exception || $value instanceof \Throwable) { 69 $this->queue[] = $value; 70 } else { 71 throw new \InvalidArgumentException('Expected an \Exception or \Throwable.'); 72 } 73 } 74 } 75 76 public function __invoke( 77 CommandInterface $command, 78 RequestInterface $request 79 ) { 80 if (!$this->queue) { 81 $last = $this->lastCommand 82 ? ' The last command sent was ' . $this->lastCommand->getName() . '.' 83 : ''; 84 throw new \RuntimeException('Mock queue is empty. Trying to send a ' 85 . $command->getName() . ' command failed.' . $last); 86 } 87 88 $this->lastCommand = $command; 89 $this->lastRequest = $request; 90 91 $result = array_shift($this->queue); 92 93 if (is_callable($result)) { 94 $result = $result($command, $request); 95 } 96 97 if ($result instanceof \Exception) { 98 $result = new RejectedPromise($result); 99 } else { 100 // Add an effective URI and statusCode if not present. 101 $meta = $result['@metadata']; 102 if (!isset($meta['effectiveUri'])) { 103 $meta['effectiveUri'] = (string) $request->getUri(); 104 } 105 if (!isset($meta['statusCode'])) { 106 $meta['statusCode'] = 200; 107 } 108 $result['@metadata'] = $meta; 109 $result = Promise\promise_for($result); 110 } 111 112 $result->then($this->onFulfilled, $this->onRejected); 113 114 return $result; 115 } 116 117 /** 118 * Get the last received request. 119 * 120 * @return RequestInterface 121 */ 122 public function getLastRequest() 123 { 124 return $this->lastRequest; 125 } 126 127 /** 128 * Get the last received command. 129 * 130 * @return CommandInterface 131 */ 132 public function getLastCommand() 133 { 134 return $this->lastCommand; 135 } 136 137 /** 138 * Returns the number of remaining items in the queue. 139 * 140 * @return int 141 */ 142 public function count() 143 { 144 return count($this->queue); 145 } 146} 147