Repository navigation
Expand file tree
/
Copy pathOperatorResource.php
More file actions
148 lines (118 loc) · 4.29 KB
/
Copy pathOperatorResource.php
File metadata and controls
148 lines (118 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<?php
namespace OpenStack\Common\Resource;
use OpenStack\Common\Api\OperatorInterface;
use OpenStack\Common\Api\OperatorTrait;
use OpenStack\Common\Transport\Utils;
use Psr\Http\Message\ResponseInterface;
abstract class OperatorResource extends AbstractResource implements OperatorInterface
{
use OperatorTrait;
public const DEFAULT_MARKER_KEY = 'id';
/**
* The key that indicates how the API nests resource collections. For example, when
* performing a GET, it could respond with ``{"servers": [{}, {}]}``. In this case, "servers"
* is the resources key, since the array of servers is nested inside.
*
* @var string
*/
protected $resourcesKey;
/**
* Indicates which attribute of the current resource should be used for pagination markers.
*
* @var string
*/
protected $markerKey;
/**
* Will create a new instance of this class with the current HTTP client and API injected in. This
* is useful when enumerating over a collection since multiple copies of the same resource class
* are needed.
*/
public function newInstance(): OperatorResource
{
return new static($this->client, $this->api);
}
/**
* @return \GuzzleHttp\Psr7\Uri:null
*/
protected function getHttpBaseUrl()
{
return $this->client->getConfig('base_uri');
}
public function executeWithState(array $definition)
{
return $this->execute($definition, $this->getAttrs(array_keys($definition['params'])));
}
private function getResourcesKey(): string
{
$resourcesKey = $this->resourcesKey;
if (!$resourcesKey) {
$class = substr(static::class, strrpos(static::class, '\\') + 1);
$resourcesKey = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $class)).'s';
}
return $resourcesKey;
}
/**
* Creates a generator for enumerating over a collection of resources returned by the request.
*
* @returns \Generator<mixed, static>
*/
public function enumerate(array $def, array $userVals = [], ?callable $mapFn = null): \Generator
{
$operation = $this->getOperation($def);
$requestFn = function ($marker) use ($operation, $userVals) {
if ($marker) {
$userVals['marker'] = $marker;
}
return $this->sendRequest($operation, $userVals);
};
$resourceFn = function (array $data) {
$resource = $this->newInstance();
$resource->populateFromArray($data);
return $resource;
};
$opts = [
'limit' => isset($userVals['limit']) ? $userVals['limit'] : null,
'resourcesKey' => $this->getResourcesKey(),
'markerKey' => $this->markerKey,
'mapFn' => $mapFn,
];
$iterator = new Iterator($opts, $requestFn, $resourceFn);
return $iterator();
}
/**
* Extracts multiple instances of the current resource from a response.
*
* @return array<self>
*/
public function extractMultipleInstances(ResponseInterface $response, ?string $key = null): array
{
$key = $key ?: $this->getResourcesKey();
$resourcesData = Utils::jsonDecode($response)[$key];
$resources = [];
foreach ($resourcesData as $resourceData) {
$resources[] = $this->newInstance()->populateFromArray($resourceData);
}
return $resources;
}
protected function getService()
{
$class = static::class;
$service = substr($class, 0, strpos($class, 'Models') - 1).'\\Service';
return new $service($this->client, $this->api);
}
public function model(string $class, $data = null): ResourceInterface
{
$model = new $class($this->client, $this->api);
// @codeCoverageIgnoreStart
if (!$model instanceof ResourceInterface) {
throw new \RuntimeException(sprintf('%s does not implement %s', $class, ResourceInterface::class));
}
// @codeCoverageIgnoreEnd
if ($data instanceof ResponseInterface) {
$model->populateFromResponse($data);
} elseif (is_array($data)) {
$model->populateFromArray($data);
}
return $model;
}
}