Completed
Push — master ( 465cbd...e0d13e )
by Marco
06:44 queued 11s
created

Model::getLocation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
c 0
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 1
nc 1
nop 0
crap 1
1
<?php namespace Comodojo\Dispatcher\Response;
2
3
use \Comodojo\Dispatcher\Components\AbstractModel;
4
use \Comodojo\Dispatcher\Request\Model as Request;
5
use \Comodojo\Dispatcher\Router\Route;
6
use \Comodojo\Foundation\Timing\TimingTrait;
7
use \Comodojo\Foundation\Base\Configuration;
8
use \Comodojo\Cookies\CookieManager;
9
use \Psr\Log\LoggerInterface;
10
use \Serializable;
11
12
/**
13
 * @package     Comodojo Dispatcher
14
 * @author      Marco Giovinazzi <[email protected]>
15
 * @author      Marco Castiello <[email protected]>
16
 * @license     MIT
17
 *
18
 * LICENSE:
19
 *
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
 * THE SOFTWARE.
27
 */
28
29
class Model extends AbstractModel implements Serializable {
30
31
    use TimingTrait;
32
33
    protected static $no_content_statuses = [100, 101, 102, 204, 304];
34
35
    protected static $cacheable_methods = ['GET', 'HEAD', 'POST', 'PUT'];
36
37
    protected static $cacheable_statuses = [200, 203, 300, 301, 302, 404, 410];
38
39
    protected $headers;
40
41
    protected $cookies;
42
43
    protected $status;
44
45
    protected $content;
46
47
    protected $location;
48
49 5
    public function __construct(Configuration $configuration, LoggerInterface $logger) {
50
51 5
        parent::__construct($configuration, $logger);
52
53 5
        $this->setHeaders(new Headers());
54 5
        $this->setCookies(new CookieManager());
55 5
        $this->setStatus(new Status());
56 5
        $this->setContent(new Content());
57 5
        $this->setLocation(new Location());
58
59 5
        $this->setTiming();
60
61 5
    }
62
63 5
    public function getHeaders() {
64
65 5
        return $this->headers;
66
67
    }
68
69 5
    public function setHeaders(Headers $headers) {
70
71 5
        $this->headers = $headers;
72
73 5
        return $this;
74
75
    }
76
77 5
    public function getCookies() {
78
79 5
        return $this->cookies;
80
81
    }
82
83 5
    public function setCookies(CookieManager $cookies) {
84
85 5
        $this->cookies = $cookies;
86
87 5
        return $this;
88
89
    }
90
91 7
    public function getStatus() {
92
93 7
        return $this->status;
94
95
    }
96
97 5
    public function setStatus(Status $status) {
98
99 5
        $this->status = $status;
100
101 5
        return $this;
102
103
    }
104
105 7
    public function getContent() {
106
107 7
        return $this->content;
108
109
    }
110
111 5
    public function setContent(Content $content) {
112
113 5
        $this->content = $content;
114
115 5
        return $this;
116
117
    }
118
119 2
    public function getLocation() {
120
121 2
        return $this->location;
122
123
    }
124
125 5
    public function setLocation(Location $location) {
126
127 5
        $this->location = $location;
128
129 5
        return $this;
130
131
    }
132
133
    public function serialize() {
134
135
        return serialize($this->export());
136
137
    }
138
139
    public function unserialize($data) {
140
141
        $this->import(unserialize($data));
142
143
    }
144
145
    public function export() {
146
147
        return (object)[
148
            'headers' => $this->getHeaders(),
149
            'cookies' => $this->getCookies()->getAll(),
150
            'status' => $this->getStatus(),
151
            'content' => $this->getContent(),
152
            'location' => $this->getLocation()
153
        ];
154
155
    }
156
157
    public function import($data) {
158
159
        if (isset($data->headers)) $this->setHeaders($data->headers);
160
        if (isset($data->status)) $this->setStatus($data->status);
161
        if (isset($data->content)) $this->setContent($data->content);
162
        if (isset($data->location)) $this->setLocation($data->location);
163
164
        if (isset($data->cookies) && is_array($data->cookies)) {
165
            $cookies = $this->getCookies();
166
            foreach ($data->cookies as $name => $cookie) $cookies->add($cookie);
167
        }
168
169
    }
170
171 2
    public function consolidate(Request $request, Route $route = null) {
172
173 2
        $status = $this->getStatus()->get();
174
175 2
        $output_class_name = "\\Comodojo\\Dispatcher\\Response\\Preprocessor\\Status".$status;
176
177
        // @TODO: this condition will be removed when all preprocessors ready
178 2
        if (class_exists($output_class_name)) {
179 2
            $output = new $output_class_name($this);
180 2
        } else {
181
            $output = new \Comodojo\Dispatcher\Response\Preprocessor\Status200($this);
182
        }
183
184 2
        $output->consolidate();
185
186 2
        if ($route != null) {
187
            $this->setClientCache($request, $route);
188
        }
189
190
        // extra checks
191 2
        $content = $this->getContent();
192 2
        $headers = $this->getHeaders();
193
194 2
        if ((string)$request->getMethod() == 'HEAD' && !in_array($status, self::$no_content_statuses)) {
195
            $length = $content->length();
196
            $content->set(null);
197
            if ($length) {
198
                $headers->set('Content-Length', $length);
199
            }
200
        }
201
202 2
        if ($headers->get('Transfer-Encoding') != null) {
203
            $headers->delete('Content-Length');
204
        }
205
206 2
        if ((string)$request->getVersion() == '1.0' && false !== strpos($headers->get('Cache-Control'), 'no-cache')) {
207
            $headers->set('pragma', 'no-cache');
208
            $headers->set('expires', -1);
209
        }
210
211 2
    }
212
213
    private function setClientCache(Request $request, Route $route) {
214
215
        $cache = strtoupper($route->getParameter('cache'));
216
        $ttl = (int)$route->getParameter('ttl');
217
218
        if (
219
            ($cache == 'CLIENT' || $cache == 'BOTH') &&
220
            in_array((string)$request->getMethod(), self::$cacheable_methods) &&
221
            in_array($this->getStatus()->get(), self::$cacheable_statuses)
222
            // @TODO: here we should also check for Cache-Control no-store or private;
223
            //        the cache layer will be improoved in future versions.
224
        ) {
225
226
            $headers = $this->getHeaders();
227
            $timestamp = (int) $this->getTime()->format('U')+$ttl;
228
229
            if ($ttl > 0) {
230
231
                $headers->set("Cache-Control", "max-age=".$ttl.", must-revalidate");
232
                $headers->set("Expires", gmdate("D, d M Y H:i:s", $timestamp)." GMT");
233
234
            } else {
235
236
                $headers->set("Cache-Control", "no-cache, must-revalidate");
237
                $headers->set("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
238
239
            }
240
241
        }
242
243
    }
244
245
}
246