Completed
Pull Request — master (#13)
by Marko
01:45
created

Headers::checkOrigin()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 0
cts 7
cp 0
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 2
nop 0
crap 12
1
<?php
2
/**
3
 * ******************************************************************
4
 * Created by   Marko Kungla on 09 Oct 2016
5
 * @package     toolshedr
6
 * Encoding     UTF-8
7
 * File         Headers.php
8
 * Code format  PSR-2 and 12
9
 * *******************************************************************/
10
11
namespace Toolshedr\Core;
12
13
14
class Headers
15
{
16
    /**
17
     * Domains allowed to connect
18
     * @var array
19
     */
20
    private $whitlisted = array();
21
22
    private $http_response_code = 200;
23
    /**
24
     * Headers constructor.
25
     */
26
    public function __construct()
27
    {
28
        $this->addToWhitelist('localhost');
29
    }
30
    
31
    /**
32
     * Whitelist your UI
33
     *
34
     * @param $origin
35
     * @return void
36
     */
37
    public function addToWhitelist(string $origin)
38
    {
39
        array_push($this->whitlisted, $origin);
40
    }
41
42
    /**
43
     * Send all headers
44
     *
45
     * @return void
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
46
     */
47
    public function areOk()
48
    {
49
        header('Access-Control-Allow-Headers: X-Toolshedr-API-KEY');
50
        header('X-Powered-By: Toolshedr Server');
51
        header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
52
53
        return $this->checkOrigin();
54
    }
55
56
    /**
57
     * Check request origin
58
     *
59
     * @return bool
60
     */
61
    private function checkOrigin()
0 ignored issues
show
Coding Style introduced by
checkOrigin uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
62
    {
63
        if (!empty($_SERVER['HTTP_ORIGIN']) && in_array($_SERVER['HTTP_ORIGIN'], $this->whitlisted)) {
64
            header(sprintf('Access-Control-Allow-Origin: %s', $_SERVER['HTTP_ORIGIN']));
65
            return true;
66
        } else {
67
            $this->setStatusCode(403);
68
            header(sprintf('Access-Control-Allow-Origin: %s', $_SERVER['HTTP_HOST']));
69
            return false;
70
        }
71
    }
72
73
    /**
74
     * Set HTTP Status Code
75
     * 
76
     * @param int $code
77
     */
78
    public function setStatusCode(int $code)
79
    {
80
        // Do not allow overwrite previous code other than 200
81
        if($this->http_response_code !== 200) return;
82
83
        $this->http_response_code = $code;
84
       
85
    }
86
87
    /**
88
     * Check does request have required headers
89
     * 
90
     * @return bool
91
     */
92
    public function containsRequiredHeaders()
0 ignored issues
show
Coding Style introduced by
containsRequiredHeaders uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
93
    {
94
        return !empty($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']) && 
95
            $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'] === 'x-toolshedr-api-key';
96
    }
97
98
    /**
99
     * Send remaining headers
100
     * 
101
     * @return void
102
     */
103
    public function send()
104
    {
105
        http_response_code($this->http_response_code);
106
        $this->setContentType('application/json');
107
    }
108
109
    /**
110
     * Set output content type
111
     * 
112
     * @param string $content_type
113
     */
114
    public function setContentType($content_type = 'application/json')
115
    {
116
        header(sprintf('Content-Type: %s', $content_type));
117
    }
118
}
119