初始化仓库

This commit is contained in:
wangxiaowei
2025-04-22 14:09:52 +08:00
commit 8b100110bb
5155 changed files with 664201 additions and 0 deletions

View File

@ -0,0 +1,57 @@
<?php
namespace GuzzleHttp\Command\Guzzle\ResponseLocation;
use GuzzleHttp\Command\Guzzle\Parameter;
use GuzzleHttp\Command\ResultInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Class AbstractLocation
*/
abstract class AbstractLocation implements ResponseLocationInterface
{
/** @var string */
protected $locationName;
/**
* Set the name of the location
*/
public function __construct($locationName)
{
$this->locationName = $locationName;
}
/**
* @return ResultInterface
*/
public function before(
ResultInterface $result,
ResponseInterface $response,
Parameter $model
) {
return $result;
}
/**
* @return ResultInterface
*/
public function after(
ResultInterface $result,
ResponseInterface $response,
Parameter $model
) {
return $result;
}
/**
* @return ResultInterface
*/
public function visit(
ResultInterface $result,
ResponseInterface $response,
Parameter $param
) {
return $result;
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace GuzzleHttp\Command\Guzzle\ResponseLocation;
use GuzzleHttp\Command\Guzzle\Parameter;
use GuzzleHttp\Command\ResultInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Extracts the body of a response into a result field
*/
class BodyLocation extends AbstractLocation
{
/**
* Set the name of the location
*
* @param string $locationName
*/
public function __construct($locationName = 'body')
{
parent::__construct($locationName);
}
/**
* @return ResultInterface
*/
public function visit(
ResultInterface $result,
ResponseInterface $response,
Parameter $param
) {
$result[$param->getName()] = $param->filter($response->getBody());
return $result;
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace GuzzleHttp\Command\Guzzle\ResponseLocation;
use GuzzleHttp\Command\Guzzle\Parameter;
use GuzzleHttp\Command\ResultInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Extracts headers from the response into a result fields
*/
class HeaderLocation extends AbstractLocation
{
/**
* Set the name of the location
*
* @param string $locationName
*/
public function __construct($locationName = 'header')
{
parent::__construct($locationName);
}
/**
* @return ResultInterface
*/
public function visit(
ResultInterface $result,
ResponseInterface $response,
Parameter $param
) {
// Retrieving a single header by name
$name = $param->getName();
if ($header = $response->getHeader($param->getWireName())) {
if (is_array($header)) {
$header = array_shift($header);
}
$result[$name] = $param->filter($header);
}
return $result;
}
}

View File

@ -0,0 +1,168 @@
<?php
namespace GuzzleHttp\Command\Guzzle\ResponseLocation;
use GuzzleHttp\Command\Guzzle\Parameter;
use GuzzleHttp\Command\Result;
use GuzzleHttp\Command\ResultInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Extracts elements from a JSON document.
*/
class JsonLocation extends AbstractLocation
{
/** @var array The JSON document being visited */
private $json = [];
/**
* Set the name of the location
*
* @param string $locationName
*/
public function __construct($locationName = 'json')
{
parent::__construct($locationName);
}
/**
* @return \GuzzleHttp\Command\ResultInterface
*/
public function before(
ResultInterface $result,
ResponseInterface $response,
Parameter $model
) {
$body = (string) $response->getBody();
$body = $body ?: '{}';
$this->json = \GuzzleHttp\json_decode($body, true);
// relocate named arrays, so that they have the same structure as
// arrays nested in objects and visit can work on them in the same way
if ($model->getType() === 'array' && ($name = $model->getName())) {
$this->json = [$name => $this->json];
}
return $result;
}
/**
* @return ResultInterface
*/
public function after(
ResultInterface $result,
ResponseInterface $response,
Parameter $model
) {
// Handle additional, undefined properties
$additional = $model->getAdditionalProperties();
if (!($additional instanceof Parameter)) {
return $result;
}
// Use the model location as the default if one is not set on additional
$addLocation = $additional->getLocation() ?: $model->getLocation();
if ($addLocation == $this->locationName) {
foreach ($this->json as $prop => $val) {
if (!isset($result[$prop])) {
// Only recurse if there is a type specified
$result[$prop] = $additional->getType()
? $this->recurse($additional, $val)
: $val;
}
}
}
$this->json = [];
return $result;
}
/**
* @return Result|ResultInterface
*/
public function visit(
ResultInterface $result,
ResponseInterface $response,
Parameter $param
) {
$name = $param->getName();
$key = $param->getWireName();
// Check if the result should be treated as a list
if ($param->getType() == 'array') {
// Treat as javascript array
if ($name) {
// name provided, store it under a key in the array
$subArray = isset($this->json[$key]) ? $this->json[$key] : null;
$result[$name] = $this->recurse($param, $subArray);
} else {
// top-level `array` or an empty name
$result = new Result(array_merge(
$result->toArray(),
$this->recurse($param, $this->json)
));
}
} elseif (isset($this->json[$key])) {
$result[$name] = $this->recurse($param, $this->json[$key]);
}
return $result;
}
/**
* Recursively process a parameter while applying filters
*
* @param Parameter $param API parameter being validated
* @param mixed $value Value to process.
*
* @return mixed|null
*/
private function recurse(Parameter $param, $value)
{
if (!is_array($value)) {
return $param->filter($value);
}
$result = [];
$type = $param->getType();
if ($type == 'array') {
$items = $param->getItems();
foreach ($value as $val) {
$result[] = $this->recurse($items, $val);
}
} elseif ($type == 'object' && !isset($value[0])) {
// On the above line, we ensure that the array is associative and
// not numerically indexed
if ($properties = $param->getProperties()) {
foreach ($properties as $property) {
$key = $property->getWireName();
if (array_key_exists($key, $value)) {
$result[$property->getName()] = $this->recurse(
$property,
$value[$key]
);
// Remove from the value so that AP can later be handled
unset($value[$key]);
}
}
}
// Only check additional properties if everything wasn't already
// handled
if ($value) {
$additional = $param->getAdditionalProperties();
if ($additional === null || $additional === true) {
// Merge the JSON under the resulting array
$result += $value;
} elseif ($additional instanceof Parameter) {
// Process all child elements according to the given schema
foreach ($value as $prop => $val) {
$result[$prop] = $this->recurse($additional, $val);
}
}
}
}
return $param->filter($result);
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace GuzzleHttp\Command\Guzzle\ResponseLocation;
use GuzzleHttp\Command\Guzzle\Parameter;
use GuzzleHttp\Command\ResultInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Extracts the reason phrase of a response into a result field
*/
class ReasonPhraseLocation extends AbstractLocation
{
/**
* Set the name of the location
*
* @param string $locationName
*/
public function __construct($locationName = 'reasonPhrase')
{
parent::__construct($locationName);
}
/**
* @return ResultInterface
*/
public function visit(
ResultInterface $result,
ResponseInterface $response,
Parameter $param
) {
$result[$param->getName()] = $param->filter(
$response->getReasonPhrase()
);
return $result;
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace GuzzleHttp\Command\Guzzle\ResponseLocation;
use GuzzleHttp\Command\Guzzle\Parameter;
use GuzzleHttp\Command\ResultInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Location visitor used to parse values out of a response into an associative
* array
*/
interface ResponseLocationInterface
{
/**
* Called before visiting all parameters. This can be used for seeding the
* result of a command with default data (e.g. populating with JSON data in
* the response then adding to the parsed data).
*
* @param ResultInterface $result Result being created
* @param ResponseInterface $response Response being visited
* @param Parameter $model Response model
*
* @return ResultInterface Modified result
*/
public function before(
ResultInterface $result,
ResponseInterface $response,
Parameter $model
);
/**
* Called after visiting all parameters
*
* @param ResultInterface $result Result being created
* @param ResponseInterface $response Response being visited
* @param Parameter $model Response model
*
* @return ResultInterface Modified result
*/
public function after(
ResultInterface $result,
ResponseInterface $response,
Parameter $model
);
/**
* Called once for each parameter being visited that matches the location
* type.
*
* @param ResultInterface $result Result being created
* @param ResponseInterface $response Response being visited
* @param Parameter $param Parameter being visited
*
* @return ResultInterface Modified result
*/
public function visit(
ResultInterface $result,
ResponseInterface $response,
Parameter $param
);
}

View File

@ -0,0 +1,36 @@
<?php
namespace GuzzleHttp\Command\Guzzle\ResponseLocation;
use GuzzleHttp\Command\Guzzle\Parameter;
use GuzzleHttp\Command\ResultInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Extracts the status code of a response into a result field
*/
class StatusCodeLocation extends AbstractLocation
{
/**
* Set the name of the location
*
* @param string $locationName
*/
public function __construct($locationName = 'statusCode')
{
parent::__construct($locationName);
}
/**
* @return ResultInterface
*/
public function visit(
ResultInterface $result,
ResponseInterface $response,
Parameter $param
) {
$result[$param->getName()] = $param->filter($response->getStatusCode());
return $result;
}
}

View File

@ -0,0 +1,302 @@
<?php
namespace GuzzleHttp\Command\Guzzle\ResponseLocation;
use GuzzleHttp\Command\Guzzle\Parameter;
use GuzzleHttp\Command\Result;
use GuzzleHttp\Command\ResultInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Extracts elements from an XML document
*/
class XmlLocation extends AbstractLocation
{
/** @var \SimpleXMLElement XML document being visited */
private $xml;
/**
* Set the name of the location
*
* @param string $locationName
*/
public function __construct($locationName = 'xml')
{
parent::__construct($locationName);
}
/**
* @return ResultInterface
*/
public function before(
ResultInterface $result,
ResponseInterface $response,
Parameter $model
) {
$this->xml = simplexml_load_string((string) $response->getBody());
return $result;
}
/**
* @return Result|ResultInterface
*/
public function after(
ResultInterface $result,
ResponseInterface $response,
Parameter $model
) {
// Handle additional, undefined properties
$additional = $model->getAdditionalProperties();
if ($additional instanceof Parameter &&
$additional->getLocation() == $this->locationName
) {
$result = new Result(array_merge(
$result->toArray(),
self::xmlToArray($this->xml)
));
}
$this->xml = null;
return $result;
}
/**
* @return ResultInterface
*/
public function visit(
ResultInterface $result,
ResponseInterface $response,
Parameter $param
) {
$sentAs = $param->getWireName();
$ns = null;
if (null !== $sentAs && strstr($sentAs, ':')) {
list($ns, $sentAs) = explode(':', $sentAs);
}
// Process the primary property
if (count($this->xml->children($ns, true)->{$sentAs})) {
$result[$param->getName()] = $this->recursiveProcess(
$param,
$this->xml->children($ns, true)->{$sentAs}
);
}
return $result;
}
/**
* Recursively process a parameter while applying filters
*
* @param Parameter $param API parameter being processed
* @param \SimpleXMLElement $node Node being processed
*
* @return array
*/
private function recursiveProcess(
Parameter $param,
\SimpleXMLElement $node
) {
$result = [];
$type = $param->getType();
if ($type == 'object') {
$result = $this->processObject($param, $node);
} elseif ($type == 'array') {
$result = $this->processArray($param, $node);
} else {
// We are probably handling a flat data node (i.e. string or
// integer), so let's check if it's childless, which indicates a
// node containing plain text.
if ($node->children()->count() == 0) {
// Retrieve text from node
$result = (string) $node;
}
}
// Filter out the value
if (isset($result)) {
$result = $param->filter($result);
}
return $result;
}
/**
* @return array
*/
private function processArray(Parameter $param, \SimpleXMLElement $node)
{
// Cast to an array if the value was a string, but should be an array
$items = $param->getItems();
$sentAs = $items->getWireName();
$result = [];
$ns = null;
if (null !== $sentAs && strstr($sentAs, ':')) {
// Get namespace from the wire name
list($ns, $sentAs) = explode(':', $sentAs);
} else {
// Get namespace from data
$ns = $items->getData('xmlNs');
}
if ($sentAs === null) {
// A general collection of nodes
foreach ($node as $child) {
$result[] = $this->recursiveProcess($items, $child);
}
} else {
// A collection of named, repeating nodes
// (i.e. <collection><foo></foo><foo></foo></collection>)
$children = $node->children($ns, true)->{$sentAs};
foreach ($children as $child) {
$result[] = $this->recursiveProcess($items, $child);
}
}
return $result;
}
/**
* Process an object
*
* @param Parameter $param API parameter being parsed
* @param \SimpleXMLElement $node Value to process
*
* @return array
*/
private function processObject(Parameter $param, \SimpleXMLElement $node)
{
$result = $knownProps = $knownAttributes = [];
// Handle known properties
if ($properties = $param->getProperties()) {
foreach ($properties as $property) {
$name = $property->getName();
$sentAs = $property->getWireName();
$knownProps[$sentAs] = 1;
if (strpos($sentAs, ':')) {
list($ns, $sentAs) = explode(':', $sentAs);
} else {
$ns = $property->getData('xmlNs');
}
if ($property->getData('xmlAttribute')) {
// Handle XML attributes
$result[$name] = (string) $node->attributes($ns, true)->{$sentAs};
$knownAttributes[$sentAs] = 1;
} elseif (count($node->children($ns, true)->{$sentAs})) {
// Found a child node matching wire name
$childNode = $node->children($ns, true)->{$sentAs};
$result[$name] = $this->recursiveProcess(
$property,
$childNode
);
}
}
}
// Handle additional, undefined properties
$additional = $param->getAdditionalProperties();
if ($additional instanceof Parameter) {
// Process all child elements according to the given schema
foreach ($node->children($additional->getData('xmlNs'), true) as $childNode) {
$sentAs = $childNode->getName();
if (!isset($knownProps[$sentAs])) {
$result[$sentAs] = $this->recursiveProcess(
$additional,
$childNode
);
}
}
} elseif ($additional === null || $additional === true) {
// Blindly transform the XML into an array preserving as much data
// as possible. Remove processed, aliased properties.
$array = array_diff_key(self::xmlToArray($node), $knownProps);
// Remove @attributes that were explicitly plucked from the
// attributes list.
if (isset($array['@attributes']) && $knownAttributes) {
$array['@attributes'] = array_diff_key($array['@attributes'], $knownProps);
if (!$array['@attributes']) {
unset($array['@attributes']);
}
}
// Merge it together with the original result
$result = array_merge($array, $result);
}
return $result;
}
/**
* Convert an XML document to an array.
*
* @param int $nesting
* @param null $ns
*
* @return array
*/
private static function xmlToArray(
\SimpleXMLElement $xml,
$ns = null,
$nesting = 0
) {
$result = [];
$children = $xml->children($ns, true);
foreach ($children as $name => $child) {
$attributes = (array) $child->attributes($ns, true);
if (!isset($result[$name])) {
$childArray = self::xmlToArray($child, $ns, $nesting + 1);
$result[$name] = $attributes
? array_merge($attributes, $childArray)
: $childArray;
continue;
}
// A child element with this name exists so we're assuming
// that the node contains a list of elements
if (!is_array($result[$name])) {
$result[$name] = [$result[$name]];
} elseif (!isset($result[$name][0])) {
// Convert the first child into the first element of a numerically indexed array
$firstResult = $result[$name];
$result[$name] = [];
$result[$name][] = $firstResult;
}
$childArray = self::xmlToArray($child, $ns, $nesting + 1);
if ($attributes) {
$result[$name][] = array_merge($attributes, $childArray);
} else {
$result[$name][] = $childArray;
}
}
// Extract text from node
$text = trim((string) $xml);
if ($text === '') {
$text = null;
}
// Process attributes
$attributes = (array) $xml->attributes($ns, true);
if ($attributes) {
if ($text !== null) {
$result['value'] = $text;
}
$result = array_merge($attributes, $result);
} elseif ($text !== null) {
$result = $text;
}
// Make sure we're always returning an array
if ($nesting == 0 && !is_array($result)) {
$result = [$result];
}
return $result;
}
}