<?php 
namespace Aws\Api\Serializer; 
 
use Aws\Api\StructureShape; 
use Aws\Api\ListShape; 
use Aws\Api\MapShape; 
use Aws\Api\Shape; 
use Aws\Api\TimestampShape; 
 
/** 
 * @internal 
 */ 
class QueryParamBuilder 
{ 
    private $methods; 
 
    protected function queryName(Shape $shape, $default = null) 
    { 
        if (null !== $shape['queryName']) { 
            return $shape['queryName']; 
        } 
 
        if (null !== $shape['locationName']) { 
            return $shape['locationName']; 
        } 
 
        if ($this->isFlat($shape) && !empty($shape['member']['locationName'])) { 
            return $shape['member']['locationName']; 
        } 
 
        return $default; 
    } 
 
    protected function isFlat(Shape $shape) 
    { 
        return $shape['flattened'] === true; 
    } 
 
    public function __invoke(StructureShape $shape, array $params) 
    { 
        if (!$this->methods) { 
            $this->methods = array_fill_keys(get_class_methods($this), true); 
        } 
 
        $query = []; 
        $this->format_structure($shape, $params, '', $query); 
 
        return $query; 
    } 
 
    protected function format(Shape $shape, $value, $prefix, array &$query) 
    { 
        $type = 'format_' . $shape['type']; 
        if (isset($this->methods[$type])) { 
            $this->{$type}($shape, $value, $prefix, $query); 
        } else { 
            $query[$prefix] = (string) $value; 
        } 
    } 
 
    protected function format_structure( 
        StructureShape $shape, 
        array $value, 
        $prefix, 
        &$query 
    ) { 
        if ($prefix) { 
            $prefix .= '.'; 
        } 
 
        foreach ($value as $k => $v) { 
            if ($shape->hasMember($k)) { 
                $member = $shape->getMember($k); 
                $this->format( 
                    $member, 
                    $v, 
                    $prefix . $this->queryName($member, $k), 
                    $query 
                ); 
            } 
        } 
    } 
 
    protected function format_list( 
        ListShape $shape, 
        array $value, 
        $prefix, 
        &$query 
    ) { 
        // Handle empty list serialization 
        if (!$value) { 
            $query[$prefix] = ''; 
            return; 
        } 
 
        $items = $shape->getMember(); 
 
        if (!$this->isFlat($shape)) { 
            $locationName = $shape->getMember()['locationName'] ?: 'member'; 
            $prefix .= ".$locationName"; 
        } elseif ($name = $this->queryName($items)) { 
            $parts = explode('.', $prefix); 
            $parts[count($parts) - 1] = $name; 
            $prefix = implode('.', $parts); 
        } 
 
        foreach ($value as $k => $v) { 
            $this->format($items, $v, $prefix . '.' . ($k + 1), $query); 
        } 
    } 
 
    protected function format_map( 
        MapShape $shape, 
        array $value, 
        $prefix, 
        array &$query 
    ) { 
        $vals = $shape->getValue(); 
        $keys = $shape->getKey(); 
 
        if (!$this->isFlat($shape)) { 
            $prefix .= '.entry'; 
        } 
 
        $i = 0; 
        $keyName = '%s.%d.' . $this->queryName($keys, 'key'); 
        $valueName = '%s.%s.' . $this->queryName($vals, 'value'); 
 
        foreach ($value as $k => $v) { 
            $i++; 
            $this->format($keys, $k, sprintf($keyName, $prefix, $i), $query); 
            $this->format($vals, $v, sprintf($valueName, $prefix, $i), $query); 
        } 
    } 
 
    protected function format_blob(Shape $shape, $value, $prefix, array &$query) 
    { 
        $query[$prefix] = base64_encode($value); 
    } 
 
    protected function format_timestamp( 
        TimestampShape $shape, 
        $value, 
        $prefix, 
        array &$query 
    ) { 
        $query[$prefix] = TimestampShape::format($value, 'iso8601'); 
    } 
 
    protected function format_boolean(Shape $shape, $value, $prefix, array &$query) 
    { 
        $query[$prefix] = ($value) ? 'true' : 'false'; 
    } 
} 
 
 |