MetaData   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 154
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 3
dl 0
loc 154
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
objectData() 0 1 ?
apiClient() 0 1 ?
objectMetaType() 0 1 ?
absolutePath() 0 1 ?
A extractMetaData() 0 16 3
A findMetaHeaders() 0 9 1
A sanitizeMetaName() 0 6 1
A hasMeta() 0 6 1
A getMeta() 0 10 2
A setMeta() 0 22 3
1
<?php
2
3
namespace ArgentCrusade\Selectel\CloudStorage\Traits;
4
5
use InvalidArgumentException;
6
use Psr\Http\Message\ResponseInterface;
7
use ArgentCrusade\Selectel\CloudStorage\Exceptions\ApiRequestFailedException;
8
9
trait MetaData
10
{
11
    /**
12
     * Returns specific object data.
13
     *
14
     * @param string $key
15
     * @param mixed  $default = null
16
     *
17
     * @return mixed
18
     */
19
    abstract protected function objectData($key, $default = null);
20
21
    /**
22
     * API Client.
23
     *
24
     * @return \ArgentCrusade\Selectel\CloudStorage\Contracts\Api\ApiClientContract
25
     */
26
    abstract public function apiClient();
27
28
    /**
29
     * Returns object meta type.
30
     *
31
     * @return string
32
     */
33
    abstract public function objectMetaType();
34
35
    /**
36
     * Returns absolute path to current object.
37
     *
38
     * @return string
39
     */
40
    abstract protected function absolutePath($path = '');
41
42
    /**
43
     * Extracts meta data from Object's response headers.
44
     *
45
     * @param \Psr\Http\Message\ResponseInterface $response
46
     *
47
     * @return array
48
     */
49
    protected function extractMetaData(ResponseInterface $response)
50
    {
51
        $headers = $this->findMetaHeaders($response);
52
53
        if (!count($headers)) {
54
            return [];
55
        }
56
57
        $metaData = [];
58
59
        foreach ($headers as $header) {
60
            $metaData[$header] = $response->getHeaderLine($header);
61
        }
62
63
        return $metaData;
64
    }
65
66
    /**
67
     * Filters meta headers from response.
68
     *
69
     * @param \Psr\Http\Message\ResponseInterface $response
70
     *
71
     * @return array
72
     */
73
    protected function findMetaHeaders(ResponseInterface $response)
74
    {
75
        $headerNames = array_keys($response->getHeaders());
76
        $metaType = $this->objectMetaType();
77
78
        return array_filter($headerNames, function ($header) use ($metaType) {
79
            return strpos($header, 'X-'.$metaType.'-Meta') !== false;
80
        });
81
    }
82
83
    /**
84
     * Sanitizes meta data name.
85
     *
86
     * @param string $name Meta name
87
     *
88
     * @return string
89
     */
90
    protected function sanitizeMetaName($name)
91
    {
92
        $metaType = $this->objectMetaType();
93
94
        return 'X-'.$metaType.'-Meta-'.str_replace('X-'.$metaType.'-Meta-', '', $name);
95
    }
96
97
    /**
98
     * Checks if given meta data exists.
99
     *
100
     * @param string $name Meta name
101
     *
102
     * @return bool
103
     */
104
    public function hasMeta($name)
105
    {
106
        $meta = $this->objectData('meta', []);
107
108
        return isset($meta[$this->sanitizeMetaName($name)]);
109
    }
110
111
    /**
112
     * Returns meta data.
113
     *
114
     * @param string $name Meta name
115
     *
116
     * @throws \InvalidArgumentException
117
     *
118
     * @return mixed
119
     */
120
    public function getMeta($name)
121
    {
122
        if (!$this->hasMeta($name)) {
123
            throw new InvalidArgumentException('Meta data with name "'.$name.'" does not exists.');
124
        }
125
126
        $meta = $this->objectData('meta', []);
127
128
        return $meta[$this->sanitizeMetaName($name)];
129
    }
130
131
    /**
132
     * Updates object meta data.
133
     *
134
     * @param array $meta Array of meta data (without "X-{Object}-Meta" prefixes).
135
     *
136
     * @throws \ArgentCrusade\Selectel\CloudStorage\Exceptions\ApiRequestFailedException
137
     *
138
     * @return bool
139
     */
140
    public function setMeta(array $meta)
141
    {
142
        $headers = [];
143
        $metaType = $this->objectMetaType();
144
145
        // We will replace any 'X-{Object}-Meta-' prefixes in meta name
146
        // and prepend final header names with same prefix so API will
147
        // receive sanitized headers and won't produce any errors.
148
149
        foreach ($meta as $name => $value) {
150
            $key = str_replace('X-'.$metaType.'-Meta-', '', $name);
151
            $headers['X-'.$metaType.'-Meta-'.$key] = $value;
152
        }
153
154
        $response = $this->apiClient()->request('POST', $this->absolutePath(), ['headers' => $headers]);
155
156
        if ($response->getStatusCode() !== 202) {
157
            throw new ApiRequestFailedException('Unable to update container meta data.', $response->getStatusCode());
158
        }
159
160
        return true;
161
    }
162
}
163