Completed
Push — master ( 6612d0...777946 )
by Daniel
03:01
created

CommonCode::getContentFromUrlThroughCurlRawArray()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 28
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 28
rs 8.5806
cc 4
eloc 23
nc 4
nop 2
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
            return [
76
                'info'     => $this->lclMsgCmn('i18n_Error_ExtensionNotLoaded'),
77
                'response' => '',
78
            ];
79
        }
80
        if (!filter_var($fullURL, FILTER_VALIDATE_URL)) {
81
            return [
82
                'info'     => $this->lclMsgCmn('i18n_Error_GivenUrlIsNotValid'),
83
                'response' => '',
84
            ];
85
        }
86
        $aReturn = $this->getContentFromUrlThroughCurlRawArray($fullURL, $features);
87
        return '{ ' . $this->packIntoJson($aReturn, 'info') . ', ' . $this->packIntoJson($aReturn, 'response') . ' }';
88
    }
89
90
    /**
91
     * Reads the content of a remote file through CURL extension
92
     *
93
     * @param string $fullURL
94
     * @param array $features
95
     * @return blob
96
     */
97
    protected function getContentFromUrlThroughCurlAsArrayIfJson($fullURL, $features = null)
98
    {
99
        $result = $this->setJsonToArray($this->getContentFromUrlThroughCurl($fullURL, $features));
0 ignored issues
show
Bug introduced by
It seems like $this->getContentFromUrl...rl($fullURL, $features) targeting danielgp\common_lib\Comm...entFromUrlThroughCurl() can also be of type array<string,string,{"in...","response":"string"}>; however, danielgp\common_lib\CommonCode::setJsonToArray() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
100 View Code Duplication
        if (isset($result['info'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
101
            if (is_array($result['info'])) {
102
                ksort($result['info']);
103
            }
104
        }
105 View Code Duplication
        if (isset($result['response'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
106
            if (is_array($result['response'])) {
107
                ksort($result['response']);
108
            }
109
        }
110
        return $result;
111
    }
112
113
    protected function getContentFromUrlThroughCurlRawArray($fullURL, $features = null)
114
    {
115
        $chanel = curl_init();
116
        curl_setopt($chanel, CURLOPT_USERAGENT, $this->getUserAgentByCommonLib());
117
        if ((strpos($fullURL, 'https') !== false) || (isset($features['forceSSLverification']))) {
118
            curl_setopt($chanel, CURLOPT_SSL_VERIFYHOST, false);
119
            curl_setopt($chanel, CURLOPT_SSL_VERIFYPEER, false);
120
        }
121
        curl_setopt($chanel, CURLOPT_URL, $fullURL);
122
        curl_setopt($chanel, CURLOPT_HEADER, false);
123
        curl_setopt($chanel, CURLOPT_RETURNTRANSFER, true);
124
        curl_setopt($chanel, CURLOPT_FRESH_CONNECT, true); //avoid a cached response
125
        curl_setopt($chanel, CURLOPT_FAILONERROR, true);
126
        $rspJsonFromClient = curl_exec($chanel);
127
        $aReturn           = [];
128
        if (curl_errno($chanel)) {
129
            $aReturn['info']     = $this->setArrayToJson([
130
                '#'           => curl_errno($chanel),
131
                'description' => curl_error($chanel)
132
            ]);
133
            $aReturn['response'] = '';
134
        } else {
135
            $aReturn['info']     = $this->setArrayToJson(curl_getinfo($chanel));
136
            $aReturn['response'] = $rspJsonFromClient;
137
        }
138
        curl_close($chanel);
139
        return $aReturn;
140
    }
141
142
    protected function getFeedbackMySQLAffectedRecords()
143
    {
144
        if (is_null($this->mySQLconnection)) {
145
            $message = 'No MySQL';
146
        } else {
147
            $afRows  = $this->mySQLconnection->affected_rows;
148
            $message = sprintf($this->lclMsgCmnNumber('i18n_Record', 'i18n_Records', $afRows), $afRows);
149
        }
150
        return '<div>' . $message . '</div>';
151
    }
152
153
    /**
154
     * returns the details about Communicator (current) file
155
     *
156
     * @param string $fileGiven
157
     * @return array
158
     */
159
    protected function getFileDetails($fileGiven)
160
    {
161
        if (!file_exists($fileGiven)) {
162
            return ['error' => sprintf($this->lclMsgCmn('i18n_Error_GivenFileDoesNotExist'), $fileGiven)];
163
        }
164
        $info = new \SplFileInfo($fileGiven);
165
        return [
166
            'File Extension'         => $info->getExtension(),
167
            'File Group'             => $info->getGroup(),
168
            'File Inode'             => $info->getInode(),
169
            'File Link Target'       => ($info->isLink() ? $info->getLinkTarget() : '-'),
170
            'File is Dir'            => $info->isDir(),
171
            'File is Executable'     => $info->isExecutable(),
172
            'File is File'           => $info->isFile(),
173
            'File is Link'           => $info->isLink(),
174
            'File is Readable'       => $info->isReadable(),
175
            'File is Writable'       => $info->isWritable(),
176
            'File Name'              => $info->getBasename('.' . $info->getExtension()),
177
            'File Name w. Extension' => $info->getFilename(),
178
            'File Owner'             => $info->getOwner(),
179
            'File Path'              => $info->getPath(),
180
            'File Permissions'       => $this->explainPerms($info->getPerms()),
181
            'Name'                   => $info->getRealPath(),
182
            'Size'                   => $info->getSize(),
183
            'Sha1'                   => sha1_file($fileGiven),
184
            'Timestamp Accessed'     => [
185
                'PHP number' => $info->getATime(),
186
                'SQL format' => date('Y-m-d H:i:s', $info->getATime()),
187
            ],
188
            'Timestamp Changed'      => [
189
                'PHP number' => $info->getCTime(),
190
                'SQL format' => date('Y-m-d H:i:s', $info->getCTime()),
191
            ],
192
            'Timestamp Modified'     => [
193
                'PHP number' => $info->getMTime(),
194
                'SQL format' => date('Y-m-d H:i:s', $info->getMTime()),
195
            ],
196
            'Type'                   => $info->getType(),
197
        ];
198
    }
199
200
    /**
201
     * returns a multi-dimensional array with list of file details within a given path
202
     * (by using Symfony/Finder package)
203
     *
204
     * @param  string $pathAnalised
205
     * @return array
206
     */
207
    protected function getListOfFiles($pathAnalised)
208
    {
209
        if (realpath($pathAnalised) === false) {
210
            return ['error' => sprintf($this->lclMsgCmn('i18n_Error_GivenPathIsNotValid'), $pathAnalised)];
211
        } elseif (!is_dir($pathAnalised)) {
212
            return ['error' => $this->lclMsgCmn('i18n_Error_GivenPathIsNotFolder')];
213
        }
214
        $aFiles   = null;
215
        $finder   = new \Symfony\Component\Finder\Finder();
216
        $iterator = $finder
217
                ->files()
218
                ->sortByName()
219
                ->in($pathAnalised);
220
        foreach ($iterator as $file) {
221
            $aFiles[$file->getRealPath()] = $this->getFileDetails($file);
222
        }
223
        return $aFiles;
224
    }
225
226
    /**
227
     * Returns server Timestamp into various formats
228
     *
229
     * @param string $returnType
230
     * @return string
231
     */
232
    protected function getTimestamp($returnType = 'string')
233
    {
234
        $crtTime = gettimeofday();
235
        switch ($returnType) {
236
            case 'array':
237
                $sReturn = [
238
                    'float'  => ($crtTime['sec'] + $crtTime['usec'] / pow(10, 6)),
239
                    'string' => implode('', [
240
                        '<span style="color:black!important;font-weight:bold;">[',
241
                        date('Y-m-d H:i:s.', $crtTime['sec']),
242
                        substr(round($crtTime['usec'], -3), 0, 3),
243
                        ']</span> '
244
                    ]),
245
                ];
246
                break;
247
            case 'float':
248
                $sReturn = ($crtTime['sec'] + $crtTime['usec'] / pow(10, 6));
249
                break;
250
            case 'string':
251
                $sReturn = implode('', [
252
                    '<span style="color:black!important;font-weight:bold;">[',
253
                    date('Y-m-d H:i:s.', $crtTime['sec']),
254
                    substr(round($crtTime['usec'], -3), 0, 3),
255
                    ']</span> '
256
                ]);
257
                break;
258
            default:
259
                $sReturn = sprintf($this->lclMsgCmn('i18n_Error_UnknownReturnType'), $returnType);
260
                break;
261
        }
262
        return $sReturn;
263
    }
264
265
    /**
266
     * Moves files into another folder
267
     *
268
     * @param type $sourcePath
269
     * @param type $targetPath
270
     * @return type
271
     */
272
    protected function moveFilesIntoTargetFolder($sourcePath, $targetPath)
273
    {
274
        $filesystem = new \Symfony\Component\Filesystem\Filesystem();
275
        $filesystem->mirror($sourcePath, $targetPath);
276
        $finder     = new \Symfony\Component\Finder\Finder();
277
        $iterator   = $finder
278
                ->files()
279
                ->ignoreUnreadableDirs(true)
280
                ->followLinks()
281
                ->in($sourcePath);
282
        $sFiles     = [];
283
        foreach ($iterator as $file) {
284
            $relativePathFile = str_replace($sourcePath, '', $file->getRealPath());
285
            if (!file_exists($targetPath . $relativePathFile)) {
286
                $sFiles[$relativePathFile] = $targetPath . $relativePathFile;
287
            }
288
        }
289
        return $this->setArrayToJson($sFiles);
290
    }
291
292
    /**
293
     * Send an array of parameters like a form through a POST action
294
     *
295
     * @param string $urlToSendTo
296
     * @param array $params
297
     * @throws \Exception
298
     * @throws \UnexpectedValueException
299
     */
300
    protected function sendBackgroundEncodedFormElementsByPost($urlToSendTo, $params = [])
301
    {
302
        try {
303
            $postingUrl = filter_var($urlToSendTo, FILTER_VALIDATE_URL);
304
            if ($postingUrl === false) {
305
                throw new \Exception($exc);
306
            } else {
307
                if (is_array($params)) {
308
                    $postingString = $this->setArrayToStringForUrl('&', $params);
309
                    $pUrlParts     = parse_url($postingUrl);
310
                    $postingPort   = (isset($pUrlParts['port']) ? $pUrlParts['port'] : 80);
311
                    $flPointer     = fsockopen($pUrlParts['host'], $postingPort, $errNo, $errorMessage, 30);
312
                    if ($flPointer === false) {
313
                        throw new \UnexpectedValueException($this->lclMsgCmn('i18n_Error_FailedToConnect') . ': '
314
                        . $errNo . ' (' . $errorMessage . ')');
315
                    } else {
316
                        fwrite($flPointer, $this->sendBackgroundPrepareData($pUrlParts, $postingString));
317
                        fclose($flPointer);
318
                    }
319
                } else {
320
                    throw new \UnexpectedValueException($this->lclMsgCmn('i18n_Error_GivenParameterIsNotAnArray'));
321
                }
322
            }
323
        } catch (\Exception $exc) {
324
            echo '<pre style="color:#f00">' . $exc->getTraceAsString() . '</pre>';
325
        }
326
    }
327
328
    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...
329
    {
330
        $this->initializeSprGlbAndSession();
331
        $out   = [];
332
        $out[] = 'POST ' . $pUrlParts['path'] . ' ' . $this->tCmnSuperGlobals->server->get['SERVER_PROTOCOL'];
333
        $out[] = 'Host: ' . $pUrlParts['host'];
334
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
335
            $out[] = 'User-Agent: ' . $this->tCmnSuperGlobals->server->get('HTTP_USER_AGENT');
336
        }
337
        $out[] = 'Content-Type: application/x-www-form-urlencoded';
338
        $out[] = 'Content-Length: ' . strlen($postingString);
339
        $out[] = 'Connection: Close' . "\r\n";
340
        $out[] = $postingString;
341
        return implode("\r\n", $out);
342
    }
343
344
    /**
345
     * Converts an array into JSON string
346
     *
347
     * @param array $inArray
348
     * @return string
349
     */
350
    protected function setArrayToJson(array $inArray)
351
    {
352
        if (!is_array($inArray)) {
353
            return $this->lclMsgCmn('i18n_Error_GivenInputIsNotArray');
354
        }
355
        $rtrn      = utf8_encode(json_encode($inArray, JSON_FORCE_OBJECT | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
356
        $jsonError = $this->setJsonErrorInPlainEnglish();
357
        if (is_null($jsonError)) {
358
            return $rtrn;
359
        } else {
360
            return $jsonError;
361
        }
362
    }
363
364
    /**
365
     * Returns proper result from a mathematical division in order to avoid Zero division erorr or Infinite results
366
     *
367
     * @param float $fAbove
368
     * @param float $fBelow
369
     * @param mixed $mArguments
370
     * @return decimal
371
     */
372
    protected function setDividedResult($fAbove, $fBelow, $mArguments = 0)
373
    {
374
        // prevent infinite result AND division by 0
375
        if (($fAbove == 0) || ($fBelow == 0)) {
376
            return 0;
377
        }
378
        if (is_array($mArguments)) {
379
            return $this->setNumberFormat(($fAbove / $fBelow), [
380
                        'MinFractionDigits' => $mArguments[1],
381
                        'MaxFractionDigits' => $mArguments[1],
382
            ]);
383
        }
384
        return $this->setNumberFormat(round(($fAbove / $fBelow), $mArguments));
385
    }
386
387
    /**
388
     * Converts a JSON string into an Array
389
     *
390
     * @param string $inputJson
391
     * @return array
392
     */
393
    protected function setJsonToArray($inputJson)
394
    {
395
        if (!$this->isJsonByDanielGP($inputJson)) {
396
            return ['error' => $this->lclMsgCmn('i18n_Error_GivenInputIsNotJson')];
397
        }
398
        $sReturn   = (json_decode($inputJson, true));
399
        $jsonError = $this->setJsonErrorInPlainEnglish();
400
        if (is_null($jsonError)) {
401
            return $sReturn;
402
        } else {
403
            return ['error' => $jsonError];
404
        }
405
    }
406
}
407