<?php 
namespace Aws\Api\Parser; 
 
use Aws\Api\DateTimeResult; 
use Aws\Api\Shape; 
use Aws\Api\StructureShape; 
use Aws\Result; 
use Aws\CommandInterface; 
use Psr\Http\Message\ResponseInterface; 
 
/** 
 * @internal 
 */ 
abstract class AbstractRestParser extends AbstractParser 
{ 
    /** 
     * Parses a payload from a response. 
     * 
     * @param ResponseInterface $response Response to parse. 
     * @param StructureShape    $member   Member to parse 
     * @param array             $result   Result value 
     * 
     * @return mixed 
     */ 
    abstract protected function payload( 
        ResponseInterface $response, 
        StructureShape $member, 
        array &$result 
    ); 
 
    public function __invoke( 
        CommandInterface $command, 
        ResponseInterface $response 
    ) { 
        $output = $this->api->getOperation($command->getName())->getOutput(); 
        $result = []; 
 
        if ($payload = $output['payload']) { 
            $this->extractPayload($payload, $output, $response, $result); 
        } 
 
        foreach ($output->getMembers() as $name => $member) { 
            switch ($member['location']) { 
                case 'header': 
                    $this->extractHeader($name, $member, $response, $result); 
                    break; 
                case 'headers': 
                    $this->extractHeaders($name, $member, $response, $result); 
                    break; 
                case 'statusCode': 
                    $this->extractStatus($name, $response, $result); 
                    break; 
            } 
        } 
 
        if (!$payload 
            && $response->getBody()->getSize() > 0 
            && count($output->getMembers()) > 0 
        ) { 
            // if no payload was found, then parse the contents of the body 
            $this->payload($response, $output, $result); 
        } 
 
        return new Result($result); 
    } 
 
    private function extractPayload( 
        $payload, 
        StructureShape $output, 
        ResponseInterface $response, 
        array &$result 
    ) { 
        $member = $output->getMember($payload); 
 
        if ($member instanceof StructureShape) { 
            // Structure members parse top-level data into a specific key. 
            $result[$payload] = []; 
            $this->payload($response, $member, $result[$payload]); 
        } else { 
            // Streaming data is just the stream from the response body. 
            $result[$payload] = $response->getBody(); 
        } 
    } 
 
    /** 
     * Extract a single header from the response into the result. 
     */ 
    private function extractHeader( 
        $name, 
        Shape $shape, 
        ResponseInterface $response, 
        &$result 
    ) { 
        $value = $response->getHeaderLine($shape['locationName'] ?: $name); 
 
        switch ($shape->getType()) { 
            case 'float': 
            case 'double': 
                $value = (float) $value; 
                break; 
            case 'long': 
                $value = (int) $value; 
                break; 
            case 'boolean': 
                $value = filter_var($value, FILTER_VALIDATE_BOOLEAN); 
                break; 
            case 'blob': 
                $value = base64_decode($value); 
                break; 
            case 'timestamp': 
                try { 
                    $value = new DateTimeResult($value); 
                    break; 
                } catch (\Exception $e) { 
                    // If the value cannot be parsed, then do not add it to the 
                    // output structure. 
                    return; 
                } 
        } 
 
        $result[$name] = $value; 
    } 
 
    /** 
     * Extract a map of headers with an optional prefix from the response. 
     */ 
    private function extractHeaders( 
        $name, 
        Shape $shape, 
        ResponseInterface $response, 
        &$result 
    ) { 
        // Check if the headers are prefixed by a location name 
        $result[$name] = []; 
        $prefix = $shape['locationName']; 
        $prefixLen = strlen($prefix); 
 
        foreach ($response->getHeaders() as $k => $values) { 
            if (!$prefixLen) { 
                $result[$name][$k] = implode(', ', $values); 
            } elseif (stripos($k, $prefix) === 0) { 
                $result[$name][substr($k, $prefixLen)] = implode(', ', $values); 
            } 
        } 
    } 
 
    /** 
     * Places the status code of the response into the result array. 
     */ 
    private function extractStatus( 
        $name, 
        ResponseInterface $response, 
        array &$result 
    ) { 
        $result[$name] = (int) $response->getStatusCode(); 
    } 
} 
 
 |