Completed
Branch master (10ea4f)
by Thierry
02:34
created

Manager::__argumentDecodeUTF8_iconv()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 5
nop 1
dl 0
loc 22
rs 8.6737
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Manager.php - Jaxon Request Manager
5
 *
6
 * This class processes the input arguments from the GET or POST data of the request.
7
 * If this is a request for the initial page load, no arguments will be processed.
8
 * During a jaxon request, any arguments found in the GET or POST will be converted to a PHP array.
9
 *
10
 * @package jaxon-core
11
 * @author Jared White
12
 * @author J. Max Wilson
13
 * @author Joseph Woolley
14
 * @author Steffen Konerow
15
 * @author Thierry Feuzeu <[email protected]>
16
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
17
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
18
 * @copyright 2016 Thierry Feuzeu <[email protected]>
19
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
20
 * @link https://github.com/jaxon-php/jaxon-core
21
 */
22
23
namespace Jaxon\Request;
24
25
use Jaxon\Jaxon;
26
27
class Manager
28
{
29
    use \Jaxon\Utils\Traits\Config;
30
    use \Jaxon\Utils\Traits\Translator;
31
32
    /**
33
     * An array of arguments received via the GET or POST parameter jxnargs.
34
     *
35
     * @var array
36
     */
37
    private $aArgs;
38
    
39
    /**
40
     * Stores the method that was used to send the arguments from the client.
41
     * Will be one of: Jaxon::METHOD_UNKNOWN, Jaxon::METHOD_GET, Jaxon::METHOD_POST.
42
     *
43
     * @var integer
44
     */
45
    private $nMethod;
46
    
47
    /**
48
     * The constructor
49
     *
50
     * Get and decode the arguments of the HTTP request
51
     */
52
    public function __construct()
2 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_POST 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...
Coding Style introduced by
__construct uses the super-global variable $_GET 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...
53
    {
54
55
        $this->aArgs = array();
56
        $this->nMethod = Jaxon::METHOD_UNKNOWN;
57
        
58
        if(isset($_POST['jxnargs']))
59
        {
60
            $this->nMethod = Jaxon::METHOD_POST;
61
            $this->aArgs = $_POST['jxnargs'];
62
        }
63
        else if(isset($_GET['jxnargs']))
64
        {
65
            $this->nMethod = Jaxon::METHOD_GET;
66
            $this->aArgs = $_GET['jxnargs'];
67
        }
68
        if(get_magic_quotes_gpc() == 1)
69
        {
70
            array_walk($this->aArgs, array(&$this, '__argumentStripSlashes'));
71
        }
72
        array_walk($this->aArgs, array(&$this, '__argumentDecode'));
73
    }
74
75
    /**
76
     * Converts a string to a boolean var
77
     *
78
     * @param string        $sValue                The string to be converted
79
     *
80
     * @return boolean
81
     */
82
    private function __convertStringToBool($sValue)
83
    {
84
        if(strcasecmp($sValue, 'true') == 0)
85
        {
86
            return true;
87
        }
88
        if(strcasecmp($sValue, 'false') == 0)
89
        {
90
            return false;
91
        }
92
        if(is_numeric($sValue))
93
        {
94
            if($sValue == 0)
95
            {
96
                return false;
97
            }
98
            return true;
99
        }
100
        return false;
101
    }
102
    
103
    /**
104
     * Strip the slashes from a string
105
     *
106
     * @param string        $sArg                The string to be stripped
107
     *
108
     * @return string
109
     */
110
    private function __argumentStripSlashes(&$sArg)
111
    {
112
        if(!is_string($sArg))
113
        {
114
            return '';
115
        }
116
        $sArg = stripslashes($sArg);
117
    }
118
    
119
    /**
120
     * Convert an Jaxon request argument to its value
121
     *
122
     * Depending of its first char, the Jaxon request argument is converted to a given type.
123
     *
124
     * @param string        $sValue                The keys of the options in the file
125
     *
126
     * @return mixed
127
     */
128
    private function __convertValue($sValue)
129
    {
130
        $cType = substr($sValue, 0, 1);
131
        $sValue = substr($sValue, 1);
132
        switch ($cType)
133
        {
134
            case 'S':
135
                $value = ($sValue === false ? '' : $sValue);
136
                break;
137
            case 'B':
138
                $value = $this->__convertStringToBool($sValue);
139
                break;
140
            case 'N':
141
                $value = ($sValue == floor($sValue) ? (int)$sValue : (float)$sValue);
142
                break;
143
            case '*':
144
            default:
145
                $value = null;
146
                break;
147
        }
148
        return $value;
149
    }
150
151
    /**
152
     * Decode and convert an Jaxon request argument from JSON
153
     *
154
     * @param string        $sArg                The Jaxon request argument
155
     *
156
     * @return mixed
157
     */
158
    private function __argumentDecode(&$sArg)
159
    {
160
        if($sArg == '')
161
        {
162
            return '';
163
        }
164
165
        $data = json_decode($sArg, true);
166
167
        if($data !== null && $sArg != $data)
168
        {
169
            $sArg = $data;
170
        }
171
        else
172
        {
173
            $sArg = $this->__convertValue($sArg);
174
        }
175
    }
176
177
    /**
178
     * Decode an Jaxon request argument and convert to UTF8 with iconv
179
     *
180
     * @param string|array        $mArg                The Jaxon request argument
181
     *
182
     * @return void
183
     */
184
    private function __argumentDecodeUTF8_iconv(&$mArg)
185
    {
186
        if(is_array($mArg))
187
        {
188
            foreach($mArg as $sKey => $xArg)
189
            {
190
                $sNewKey = $sKey;
191
                $this->__argumentDecodeUTF8_iconv($sNewKey);
192
                if($sNewKey != $sKey)
193
                {
194
                    $mArg[$sNewKey] = $xArg;
195
                    unset($mArg[$sKey]);
196
                    $sKey = $sNewKey;
197
                }
198
                $this->__argumentDecodeUTF8_iconv($xArg);
199
            }
200
        }
201
        else if(is_string($mArg))
202
        {
203
            $mArg = iconv("UTF-8", $this->getOption('core.encoding') . '//TRANSLIT', $mArg);
204
        }
205
    }
206
    
207
    /**
208
     * Decode an Jaxon request argument and convert to UTF8 with mb_convert_encoding
209
     *
210
     * @param string|array        $mArg                The Jaxon request argument
211
     *
212
     * @return void
213
     */
214 View Code Duplication
    private function __argumentDecodeUTF8_mb_convert_encoding(&$mArg)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
215
    {
216
        if(is_array($mArg))
217
        {
218
            foreach($mArg as $sKey => $xArg)
219
            {
220
                $sNewKey = $sKey;
221
                $this->__argumentDecodeUTF8_mb_convert_encoding($sNewKey);
222
                if($sNewKey != $sKey)
223
                {
224
                    $mArg[$sNewKey] = $xArg;
225
                    unset($mArg[$sKey]);
226
                    $sKey = $sNewKey;
227
                }
228
                $this->__argumentDecodeUTF8_mb_convert_encoding($xArg);
229
            }
230
        }
231
        else if(is_string($mArg))
232
        {
233
            $mArg = mb_convert_encoding($mArg, $this->getOption('core.encoding'), "UTF-8");
234
        }
235
    }
236
    
237
    /**
238
     * Decode an Jaxon request argument from UTF8
239
     *
240
     * @param string|array        $mArg                The Jaxon request argument
241
     *
242
     * @return void
243
     */
244 View Code Duplication
    private function __argumentDecodeUTF8_utf8_decode(&$mArg)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
    {
246
        if(is_array($mArg))
247
        {
248
            foreach($mArg as $sKey => $xArg)
249
            {
250
                $sNewKey = $sKey;
251
                $this->__argumentDecodeUTF8_utf8_decode($sNewKey);
252
                
253
                if($sNewKey != $sKey)
254
                {
255
                    $mArg[$sNewKey] = $xArg;
256
                    unset($mArg[$sKey]);
257
                    $sKey = $sNewKey;
258
                }
259
                
260
                $this->__argumentDecodeUTF8_utf8_decode($xArg);
261
            }
262
        }
263
        else if(is_string($mArg))
264
        {
265
            $mArg = utf8_decode($mArg);
266
        }
267
    }
268
    
269
    /**
270
     * Return the method that was used to send the arguments from the client
271
     *
272
     * The method is one of: Jaxon::METHOD_UNKNOWN, Jaxon::METHOD_GET, Jaxon::METHOD_POST.
273
     *
274
     * @return integer
275
     */
276
    public function getRequestMethod()
277
    {
278
        return $this->nMethod;
279
    }
280
    
281
    /**
282
     * Return the array of arguments that were extracted and parsed from the GET or POST data
283
     *
284
     * @return array
285
     */
286
    public function process()
287
    {
288
        if(($this->getOption('core.decode_utf8')))
289
        {
290
            $sFunction = '';
1 ignored issue
show
Unused Code introduced by
$sFunction is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
291
            
292
            if(function_exists('iconv'))
293
            {
294
                $sFunction = "iconv";
295
            }
296
            else if(function_exists('mb_convert_encoding'))
297
            {
298
                $sFunction = "mb_convert_encoding";
299
            }
300
            else if($this->getOption('core.encoding') == "ISO-8859-1")
301
            {
302
                $sFunction = "utf8_decode";
303
            }
304
            else
305
            {
306
                throw new \Jaxon\Exception\Error($this->trans('errors.request.conversion'));
307
            }
308
309
            $mFunction = array(&$this, '__argumentDecodeUTF8_' . $sFunction);
310
            array_walk($this->aArgs, $mFunction);
311
            $this->setOption('core.decode_utf8', false);
312
        }
313
        
314
        return $this->aArgs;
315
    }
316
}
317