Completed
Push — master ( 39ca89...64a0db )
by James Ekow Abaka
03:49
created

Input::decode()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 14
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
c 0
b 0
f 0
rs 9.2
cc 4
eloc 12
nc 6
nop 2
1
<?php
2
3
/*
4
 * Ntentan Framework
5
 * Copyright (c) 2008-2015 James Ekow Abaka Ainooson
6
 * 
7
 * Permission is hereby granted, free of charge, to any person obtaining
8
 * a copy of this software and associated documentation files (the
9
 * "Software"), to deal in the Software without restriction, including
10
 * without limitation the rights to use, copy, modify, merge, publish,
11
 * distribute, sublicense, and/or sell copies of the Software, and to
12
 * permit persons to whom the Software is furnished to do so, subject to
13
 * the following conditions:
14
 * 
15
 * The above copyright notice and this permission notice shall be
16
 * included in all copies or substantial portions of the Software.
17
 * 
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
25
 * 
26
 */
27
28
namespace ntentan\utils;
29
30
/**
31
 * An input filter class which is wraped around PHP's `filter_input` and
32
 * `filter_input_array` classes. This class provides methods which allow safe
33
 * and secure access to data passed to an application. 
34
 *
35
 * @author James Ainooson
36
 */
37
class Input {
38
39
    const POST = INPUT_POST;
40
    const GET = INPUT_GET;
41
    const REQUEST = INPUT_REQUEST;
42
43
    private static $arrays = [];
44
    
45
    /**
46
     * http://stackoverflow.com/a/14432765
47
     * 
48
     * @param type $input
49
     * @param type $query
0 ignored issues
show
Bug introduced by
There is no parameter named $query. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
50
     * @return type
51
     */
52
    private static function decode($input, $key) {
53
        if(!isset(self::$arrays[$input])) {
54
            $query = $input == self::GET 
55
                ? filter_input(INPUT_SERVER, 'QUERY_STRING') 
56
                : file_get_contents('php://input');
57
            $data = preg_replace_callback('/(?:^|(?<=&))[^=[]+/', 
58
                function($match) {
59
                    return bin2hex(urldecode($match[0]));
60
                }, $query);
61
            parse_str($data, $values);
62
            self::$arrays[$input] = array_combine(array_map('hex2bin', array_keys($values)), $values);        
63
        }
64
        return $key ? self::$arrays[$input][$key] : self::$arrays[$input];
65
    }
66
    
67
    /**
68
     * Does the actual work of calling either the filter_input of 
69
     * filter_input_array. Calls the filter_input when a data key is provided
70
     * and callse the filte_input_array when a data key is absent.
71
     * 
72
     * @param string $input Input type
73
     * @param string $key The data key
74
     * @return string|array The value.
75
     */
76
    private static function getVariable($input, $key) {
77
        if ($key === null) {
78
            if (!isset(self::$arrays[$input])) {
79
                self::$arrays[$input] = filter_input_array($input);
80
            }
81
            $return = self::$arrays[$input];
82
        } else {
83
            $return = filter_input($input, $key);
84
        }
85
86
        if ($return === null && $key === null) {
87
            $return = array();
88
        }
89
90
        return $return;
91
    }
92
    
93
    /**
94
     * Retrieves GET request variables.
95
     * 
96
     * @param string $key
97
     * @return string|array
0 ignored issues
show
Documentation introduced by
Should the return type not be type?

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...
98
     */
99
    public static function get($key = null) {
100
        return self::decode(self::GET, $key);
101
    }
102
103
    /**
104
     * Retrieves post request variables.
105
     * 
106
     * @param string $key
107
     * @return string|array
0 ignored issues
show
Documentation introduced by
Should the return type not be type?

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...
108
     */
109
    public static function post($key = null) {
110
        return self::decode(self::POST, $key);
111
    }
112
113
    /**
114
     * Retrieves server variables.
115
     * 
116
     * @param string $key
117
     * @return string|array
118
     */
119
    public static function server($key = null) {
120
        return self::getVariable(INPUT_SERVER, $key);
121
    }
122
123
    /**
124
     * Retrieves cookie variables.
125
     * 
126
     * @param string $key
127
     * @return string|array
128
     */
129
    public static function cookie($key = null) {
130
        return self::getVariable(INPUT_COOKIE, $key);
131
    }
132
133
    public static function exists($input, $key) {
134
        return isset(self::getVariable($input, null)[$key]);
135
    }
136
137
    public static function files($key = null) {
0 ignored issues
show
Coding Style introduced by
files uses the super-global variable $_FILES 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...
138
        $files = [];
139
        if (!isset($_FILES[$key])) {
140
            return null;
141
        }
142
        if (is_array($_FILES[$key]['name'])) {
143
            for ($i = 0; $i < count($_FILES[$key]['name']); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
144
                $files[] = new filesystem\UploadedFile([
145
                    'name' => $_FILES[$key]['name'][$i],
146
                    'type' => $_FILES[$key]['type'][$i],
147
                    'tmp_name' => $_FILES[$key]['tmp_name'][$i],
148
                    'error' => $_FILES[$key]['error'][$i],
149
                    'size' => $_FILES[$key]['size'][$i],
150
                ]);
151
            }
152
            return $files;
153
        } else {
154
            return new filesystem\UploadedFile($_FILES);
155
        }
156
    }
157
158
}
159