Completed
Push — master ( 777946...d26973 )
by Daniel
02:41
created

CommonCode   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 369
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 7

Importance

Changes 47
Bugs 5 Features 3
Metric Value
wmc 52
c 47
b 5
f 3
lcom 2
cbo 7
dl 0
loc 369
rs 7.9487

14 Methods

Rating   Name   Duplication   Size   Complexity  
B arrayDiffAssocRecursive() 0 19 8
A getContentFromUrlThroughCurl() 0 19 3
A getContentFromUrlThroughCurlAsArrayIfJson() 0 11 3
B getContentFromUrlThroughCurlRawArray() 0 28 4
A getFeedbackMySQLAffectedRecords() 0 10 2
B getFileDetails() 0 40 3
A getListOfFiles() 0 18 4
B getTimestamp() 0 32 4
A moveFilesIntoTargetFolder() 0 19 3
B sendBackgroundEncodedFormElementsByPost() 0 27 6
A sendBackgroundPrepareData() 0 15 2
A setArrayToJson() 0 13 3
A setDividedResult() 0 14 4
A setJsonToArray() 0 13 3

How to fix   Complexity   

Complex Class

Complex classes like CommonCode often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CommonCode, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 *
5
 * The MIT License (MIT)
6
 *
7
 * Copyright (c) 2015 Daniel Popiniuc
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy
10
 * of this software and associated documentation files (the "Software"), to deal
11
 * in the Software without restriction, including without limitation the rights
12
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 * copies of the Software, and to permit persons to whom the Software is
14
 * furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
 * SOFTWARE.
26
 *
27
 */
28
29
namespace danielgp\common_lib;
30
31
/**
32
 * usefull functions to get quick results
33
 *
34
 * @author Daniel Popiniuc
35
 */
36
trait CommonCode
37
{
38
39
    use CommonBasic,
40
        CommonPermissions,
41
        DomComponentsByDanielGP,
42
        MySQLiByDanielGPqueries,
43
        MySQLiByDanielGP;
44
45
    protected function arrayDiffAssocRecursive($array1, $array2)
46
    {
47
        $difference = [];
48
        foreach ($array1 as $key => $value) {
49
            if (is_array($value)) {
50
                if (!isset($array2[$key]) || !is_array($array2[$key])) {
51
                    $difference[$key] = $value;
52
                } else {
53
                    $workingDiff = $this->arrayDiffAssocRecursive($value, $array2[$key]);
54
                    if (!empty($workingDiff)) {
55
                        $difference[$key] = $workingDiff;
56
                    }
57
                }
58
            } elseif (!array_key_exists($key, $array2) || $array2[$key] !== $value) {
59
                $difference[$key] = $value;
60
            }
61
        }
62
        return $difference;
63
    }
64
65
    /**
66
     * Reads the content of a remote file through CURL extension
67
     *
68
     * @param string $fullURL
69
     * @param array $features
70
     * @return blob
71
     */
72
    protected function getContentFromUrlThroughCurl($fullURL, $features = null)
73
    {
74
        if (!function_exists('curl_init')) {
75
            $aReturn = [
76
                'info'     => $this->lclMsgCmn('i18n_Error_ExtensionNotLoaded'),
77
                'response' => '',
78
            ];
79
            return $this->setArrayToJson($aReturn);
80
        }
81
        if (!filter_var($fullURL, FILTER_VALIDATE_URL)) {
82
            $aReturn = [
83
                'info'     => $this->lclMsgCmn('i18n_Error_GivenUrlIsNotValid'),
84
                'response' => '',
85
            ];
86
            return $this->setArrayToJson($aReturn);
87
        }
88
        $aReturn = $this->getContentFromUrlThroughCurlRawArray($fullURL, $features);
89
        return '{ ' . $this->packIntoJson($aReturn, 'info') . ', ' . $this->packIntoJson($aReturn, 'response') . ' }';
90
    }
91
92
    /**
93
     * Reads the content of a remote file through CURL extension
94
     *
95
     * @param string $fullURL
96
     * @param array $features
97
     * @return blob
98
     */
99
    protected function getContentFromUrlThroughCurlAsArrayIfJson($fullURL, $features = null)
100
    {
101
        $result = $this->setJsonToArray($this->getContentFromUrlThroughCurl($fullURL, $features));
102
        if (is_array($result['info'])) {
103
            ksort($result['info']);
104
        }
105
        if (is_array($result['response'])) {
106
            ksort($result['response']);
107
        }
108
        return $result;
109
    }
110
111
    protected function getContentFromUrlThroughCurlRawArray($fullURL, $features = null)
112
    {
113
        $chanel = curl_init();
114
        curl_setopt($chanel, CURLOPT_USERAGENT, $this->getUserAgentByCommonLib());
115
        if ((strpos($fullURL, 'https') !== false) || (isset($features['forceSSLverification']))) {
116
            curl_setopt($chanel, CURLOPT_SSL_VERIFYHOST, false);
117
            curl_setopt($chanel, CURLOPT_SSL_VERIFYPEER, false);
118
        }
119
        curl_setopt($chanel, CURLOPT_URL, $fullURL);
120
        curl_setopt($chanel, CURLOPT_HEADER, false);
121
        curl_setopt($chanel, CURLOPT_RETURNTRANSFER, true);
122
        curl_setopt($chanel, CURLOPT_FRESH_CONNECT, true); //avoid a cached response
123
        curl_setopt($chanel, CURLOPT_FAILONERROR, true);
124
        $rspJsonFromClient = curl_exec($chanel);
125
        $aReturn           = [];
126
        if (curl_errno($chanel)) {
127
            $aReturn['info']     = $this->setArrayToJson([
128
                '#'           => curl_errno($chanel),
129
                'description' => curl_error($chanel)
130
            ]);
131
            $aReturn['response'] = '';
132
        } else {
133
            $aReturn['info']     = $this->setArrayToJson(curl_getinfo($chanel));
134
            $aReturn['response'] = $rspJsonFromClient;
135
        }
136
        curl_close($chanel);
137
        return $aReturn;
138
    }
139
140
    protected function getFeedbackMySQLAffectedRecords()
141
    {
142
        if (is_null($this->mySQLconnection)) {
143
            $message = 'No MySQL';
144
        } else {
145
            $afRows  = $this->mySQLconnection->affected_rows;
146
            $message = sprintf($this->lclMsgCmnNumber('i18n_Record', 'i18n_Records', $afRows), $afRows);
147
        }
148
        return '<div>' . $message . '</div>';
149
    }
150
151
    /**
152
     * returns the details about Communicator (current) file
153
     *
154
     * @param string $fileGiven
155
     * @return array
156
     */
157
    protected function getFileDetails($fileGiven)
158
    {
159
        if (!file_exists($fileGiven)) {
160
            return ['error' => sprintf($this->lclMsgCmn('i18n_Error_GivenFileDoesNotExist'), $fileGiven)];
161
        }
162
        $info = new \SplFileInfo($fileGiven);
163
        return [
164
            'File Extension'         => $info->getExtension(),
165
            'File Group'             => $info->getGroup(),
166
            'File Inode'             => $info->getInode(),
167
            'File Link Target'       => ($info->isLink() ? $info->getLinkTarget() : '-'),
168
            'File is Dir'            => $info->isDir(),
169
            'File is Executable'     => $info->isExecutable(),
170
            'File is File'           => $info->isFile(),
171
            'File is Link'           => $info->isLink(),
172
            'File is Readable'       => $info->isReadable(),
173
            'File is Writable'       => $info->isWritable(),
174
            'File Name'              => $info->getBasename('.' . $info->getExtension()),
175
            'File Name w. Extension' => $info->getFilename(),
176
            'File Owner'             => $info->getOwner(),
177
            'File Path'              => $info->getPath(),
178
            'File Permissions'       => $this->explainPerms($info->getPerms()),
179
            'Name'                   => $info->getRealPath(),
180
            'Size'                   => $info->getSize(),
181
            'Sha1'                   => sha1_file($fileGiven),
182
            'Timestamp Accessed'     => [
183
                'PHP number' => $info->getATime(),
184
                'SQL format' => date('Y-m-d H:i:s', $info->getATime()),
185
            ],
186
            'Timestamp Changed'      => [
187
                'PHP number' => $info->getCTime(),
188
                'SQL format' => date('Y-m-d H:i:s', $info->getCTime()),
189
            ],
190
            'Timestamp Modified'     => [
191
                'PHP number' => $info->getMTime(),
192
                'SQL format' => date('Y-m-d H:i:s', $info->getMTime()),
193
            ],
194
            'Type'                   => $info->getType(),
195
        ];
196
    }
197
198
    /**
199
     * returns a multi-dimensional array with list of file details within a given path
200
     * (by using Symfony/Finder package)
201
     *
202
     * @param  string $pathAnalised
203
     * @return array
204
     */
205
    protected function getListOfFiles($pathAnalised)
206
    {
207
        if (realpath($pathAnalised) === false) {
208
            return ['error' => sprintf($this->lclMsgCmn('i18n_Error_GivenPathIsNotValid'), $pathAnalised)];
209
        } elseif (!is_dir($pathAnalised)) {
210
            return ['error' => $this->lclMsgCmn('i18n_Error_GivenPathIsNotFolder')];
211
        }
212
        $aFiles   = null;
213
        $finder   = new \Symfony\Component\Finder\Finder();
214
        $iterator = $finder
215
                ->files()
216
                ->sortByName()
217
                ->in($pathAnalised);
218
        foreach ($iterator as $file) {
219
            $aFiles[$file->getRealPath()] = $this->getFileDetails($file);
220
        }
221
        return $aFiles;
222
    }
223
224
    /**
225
     * Returns server Timestamp into various formats
226
     *
227
     * @param string $returnType
228
     * @return string
229
     */
230
    protected function getTimestamp($returnType = 'string')
231
    {
232
        $crtTime = gettimeofday();
233
        switch ($returnType) {
234
            case 'array':
235
                $sReturn = [
236
                    'float'  => ($crtTime['sec'] + $crtTime['usec'] / pow(10, 6)),
237
                    'string' => implode('', [
238
                        '<span style="color:black!important;font-weight:bold;">[',
239
                        date('Y-m-d H:i:s.', $crtTime['sec']),
240
                        substr(round($crtTime['usec'], -3), 0, 3),
241
                        ']</span> '
242
                    ]),
243
                ];
244
                break;
245
            case 'float':
246
                $sReturn = ($crtTime['sec'] + $crtTime['usec'] / pow(10, 6));
247
                break;
248
            case 'string':
249
                $sReturn = implode('', [
250
                    '<span style="color:black!important;font-weight:bold;">[',
251
                    date('Y-m-d H:i:s.', $crtTime['sec']),
252
                    substr(round($crtTime['usec'], -3), 0, 3),
253
                    ']</span> '
254
                ]);
255
                break;
256
            default:
257
                $sReturn = sprintf($this->lclMsgCmn('i18n_Error_UnknownReturnType'), $returnType);
258
                break;
259
        }
260
        return $sReturn;
261
    }
262
263
    /**
264
     * Moves files into another folder
265
     *
266
     * @param type $sourcePath
267
     * @param type $targetPath
268
     * @return type
269
     */
270
    protected function moveFilesIntoTargetFolder($sourcePath, $targetPath)
271
    {
272
        $filesystem = new \Symfony\Component\Filesystem\Filesystem();
273
        $filesystem->mirror($sourcePath, $targetPath);
274
        $finder     = new \Symfony\Component\Finder\Finder();
275
        $iterator   = $finder
276
                ->files()
277
                ->ignoreUnreadableDirs(true)
278
                ->followLinks()
279
                ->in($sourcePath);
280
        $sFiles     = [];
281
        foreach ($iterator as $file) {
282
            $relativePathFile = str_replace($sourcePath, '', $file->getRealPath());
283
            if (!file_exists($targetPath . $relativePathFile)) {
284
                $sFiles[$relativePathFile] = $targetPath . $relativePathFile;
285
            }
286
        }
287
        return $this->setArrayToJson($sFiles);
288
    }
289
290
    /**
291
     * Send an array of parameters like a form through a POST action
292
     *
293
     * @param string $urlToSendTo
294
     * @param array $params
295
     * @throws \Exception
296
     * @throws \UnexpectedValueException
297
     */
298
    protected function sendBackgroundEncodedFormElementsByPost($urlToSendTo, $params = [])
299
    {
300
        try {
301
            $postingUrl = filter_var($urlToSendTo, FILTER_VALIDATE_URL);
302
            if ($postingUrl === false) {
303
                throw new \Exception($exc);
304
            } else {
305
                if (is_array($params)) {
306
                    $postingString = $this->setArrayToStringForUrl('&', $params);
307
                    $pUrlParts     = parse_url($postingUrl);
308
                    $postingPort   = (isset($pUrlParts['port']) ? $pUrlParts['port'] : 80);
309
                    $flPointer     = fsockopen($pUrlParts['host'], $postingPort, $errNo, $errorMessage, 30);
310
                    if ($flPointer === false) {
311
                        throw new \UnexpectedValueException($this->lclMsgCmn('i18n_Error_FailedToConnect') . ': '
312
                        . $errNo . ' (' . $errorMessage . ')');
313
                    } else {
314
                        fwrite($flPointer, $this->sendBackgroundPrepareData($pUrlParts, $postingString));
315
                        fclose($flPointer);
316
                    }
317
                } else {
318
                    throw new \UnexpectedValueException($this->lclMsgCmn('i18n_Error_GivenParameterIsNotAnArray'));
319
                }
320
            }
321
        } catch (\Exception $exc) {
322
            echo '<pre style="color:#f00">' . $exc->getTraceAsString() . '</pre>';
323
        }
324
    }
325
326
    protected function sendBackgroundPrepareData($pUrlParts, $postingString)
0 ignored issues
show
Coding Style introduced by
sendBackgroundPrepareData 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...
327
    {
328
        $this->initializeSprGlbAndSession();
329
        $out   = [];
330
        $out[] = 'POST ' . $pUrlParts['path'] . ' ' . $this->tCmnSuperGlobals->server->get['SERVER_PROTOCOL'];
331
        $out[] = 'Host: ' . $pUrlParts['host'];
332
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
333
            $out[] = 'User-Agent: ' . $this->tCmnSuperGlobals->server->get('HTTP_USER_AGENT');
334
        }
335
        $out[] = 'Content-Type: application/x-www-form-urlencoded';
336
        $out[] = 'Content-Length: ' . strlen($postingString);
337
        $out[] = 'Connection: Close' . "\r\n";
338
        $out[] = $postingString;
339
        return implode("\r\n", $out);
340
    }
341
342
    /**
343
     * Converts an array into JSON string
344
     *
345
     * @param array $inArray
346
     * @return string
347
     */
348
    protected function setArrayToJson(array $inArray)
349
    {
350
        if (!is_array($inArray)) {
351
            return $this->lclMsgCmn('i18n_Error_GivenInputIsNotArray');
352
        }
353
        $rtrn      = utf8_encode(json_encode($inArray, JSON_FORCE_OBJECT | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
354
        $jsonError = $this->setJsonErrorInPlainEnglish();
355
        if (is_null($jsonError)) {
356
            return $rtrn;
357
        } else {
358
            return $jsonError;
359
        }
360
    }
361
362
    /**
363
     * Returns proper result from a mathematical division in order to avoid Zero division erorr or Infinite results
364
     *
365
     * @param float $fAbove
366
     * @param float $fBelow
367
     * @param mixed $mArguments
368
     * @return decimal
369
     */
370
    protected function setDividedResult($fAbove, $fBelow, $mArguments = 0)
371
    {
372
        // prevent infinite result AND division by 0
373
        if (($fAbove == 0) || ($fBelow == 0)) {
374
            return 0;
375
        }
376
        if (is_array($mArguments)) {
377
            return $this->setNumberFormat(($fAbove / $fBelow), [
378
                        'MinFractionDigits' => $mArguments[1],
379
                        'MaxFractionDigits' => $mArguments[1],
380
            ]);
381
        }
382
        return $this->setNumberFormat(round(($fAbove / $fBelow), $mArguments));
383
    }
384
385
    /**
386
     * Converts a JSON string into an Array
387
     *
388
     * @param string $inputJson
389
     * @return array
390
     */
391
    protected function setJsonToArray($inputJson)
392
    {
393
        if (!$this->isJsonByDanielGP($inputJson)) {
394
            return ['error' => $this->lclMsgCmn('i18n_Error_GivenInputIsNotJson')];
395
        }
396
        $sReturn   = (json_decode($inputJson, true));
397
        $jsonError = $this->setJsonErrorInPlainEnglish();
398
        if (is_null($jsonError)) {
399
            return $sReturn;
400
        } else {
401
            return ['error' => $jsonError];
402
        }
403
    }
404
}
405