Completed
Push — master ( 28285d...d07412 )
by Daniel
03:13
created

CommonCode::arrayDiffAssocRecursive()   B

Complexity

Conditions 8
Paths 6

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 19
rs 7.7777
cc 8
eloc 13
nc 6
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
            $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 getFeedbackMySQLAffectedRecords()
112
    {
113
        if (is_null($this->mySQLconnection)) {
114
            $message = 'No MySQL';
115
        } else {
116
            $afRows  = $this->mySQLconnection->affected_rows;
117
            $message = sprintf($this->lclMsgCmnNumber('i18n_Record', 'i18n_Records', $afRows), $afRows);
118
        }
119
        return '<div>' . $message . '</div>';
120
    }
121
122
    /**
123
     * returns the details about Communicator (current) file
124
     *
125
     * @param string $fileGiven
126
     * @return array
127
     */
128
    protected function getFileDetails($fileGiven)
129
    {
130
        if (!file_exists($fileGiven)) {
131
            return ['error' => sprintf($this->lclMsgCmn('i18n_Error_GivenFileDoesNotExist'), $fileGiven)];
132
        }
133
        $info = new \SplFileInfo($fileGiven);
134
        return [
135
            'File Extension'         => $info->getExtension(),
136
            'File Group'             => $info->getGroup(),
137
            'File Inode'             => $info->getInode(),
138
            'File Link Target'       => ($info->isLink() ? $info->getLinkTarget() : '-'),
139
            'File is Dir'            => $info->isDir(),
140
            'File is Executable'     => $info->isExecutable(),
141
            'File is File'           => $info->isFile(),
142
            'File is Link'           => $info->isLink(),
143
            'File is Readable'       => $info->isReadable(),
144
            'File is Writable'       => $info->isWritable(),
145
            'File Name'              => $info->getBasename('.' . $info->getExtension()),
146
            'File Name w. Extension' => $info->getFilename(),
147
            'File Owner'             => $info->getOwner(),
148
            'File Path'              => $info->getPath(),
149
            'File Permissions'       => $this->explainPerms($info->getPerms()),
150
            'Name'                   => $info->getRealPath(),
151
            'Size'                   => $info->getSize(),
152
            'Sha1'                   => sha1_file($fileGiven),
153
            'Timestamp Accessed'     => [
154
                'PHP number' => $info->getATime(),
155
                'SQL format' => date('Y-m-d H:i:s', $info->getATime()),
156
            ],
157
            'Timestamp Changed'      => [
158
                'PHP number' => $info->getCTime(),
159
                'SQL format' => date('Y-m-d H:i:s', $info->getCTime()),
160
            ],
161
            'Timestamp Modified'     => [
162
                'PHP number' => $info->getMTime(),
163
                'SQL format' => date('Y-m-d H:i:s', $info->getMTime()),
164
            ],
165
            'Type'                   => $info->getType(),
166
        ];
167
    }
168
169
    /**
170
     * returns a multi-dimensional array with list of file details within a given path
171
     * (by using Symfony/Finder package)
172
     *
173
     * @param  string $pathAnalised
174
     * @return array
175
     */
176
    protected function getListOfFiles($pathAnalised)
177
    {
178
        if (realpath($pathAnalised) === false) {
179
            return ['error' => sprintf($this->lclMsgCmn('i18n_Error_GivenPathIsNotValid'), $pathAnalised)];
180
        } elseif (!is_dir($pathAnalised)) {
181
            return ['error' => $this->lclMsgCmn('i18n_Error_GivenPathIsNotFolder')];
182
        }
183
        $aFiles   = null;
184
        $finder   = new \Symfony\Component\Finder\Finder();
185
        $iterator = $finder
186
                ->files()
187
                ->sortByName()
188
                ->in($pathAnalised);
189
        foreach ($iterator as $file) {
190
            $aFiles[$file->getRealPath()] = $this->getFileDetails($file);
191
        }
192
        return $aFiles;
193
    }
194
195
    /**
196
     * Returns server Timestamp into various formats
197
     *
198
     * @param string $returnType
199
     * @return string
200
     */
201
    protected function getTimestamp($returnType = 'string')
202
    {
203
        $crtTime = gettimeofday();
204
        switch ($returnType) {
205
            case 'array':
206
                $sReturn = [
207
                    'float'  => ($crtTime['sec'] + $crtTime['usec'] / pow(10, 6)),
208
                    'string' => implode('', [
209
                        '<span style="color:black!important;font-weight:bold;">[',
210
                        date('Y-m-d H:i:s.', $crtTime['sec']),
211
                        substr(round($crtTime['usec'], -3), 0, 3),
212
                        ']</span> '
213
                    ]),
214
                ];
215
                break;
216
            case 'float':
217
                $sReturn = ($crtTime['sec'] + $crtTime['usec'] / pow(10, 6));
218
                break;
219
            case 'string':
220
                $sReturn = implode('', [
221
                    '<span style="color:black!important;font-weight:bold;">[',
222
                    date('Y-m-d H:i:s.', $crtTime['sec']),
223
                    substr(round($crtTime['usec'], -3), 0, 3),
224
                    ']</span> '
225
                ]);
226
                break;
227
            default:
228
                $sReturn = sprintf($this->lclMsgCmn('i18n_Error_UnknownReturnType'), $returnType);
229
                break;
230
        }
231
        return $sReturn;
232
    }
233
234
    /**
235
     * Tests if given string has a valid Json format
236
     *
237
     * @param string $inputJson
238
     * @return boolean|string
239
     */
240
    protected function isJsonByDanielGP($inputJson)
241
    {
242
        if (is_string($inputJson)) {
243
            json_decode($inputJson);
244
            return (json_last_error() == JSON_ERROR_NONE);
245
        }
246
        return $this->lclMsgCmn('i18n_Error_GivenInputIsNotJson');
247
    }
248
249
    private function packIntoJson($aReturn, $keyToWorkWith)
250
    {
251
        if ($this->isJsonByDanielGP($aReturn[$keyToWorkWith])) {
252
            return '"' . $keyToWorkWith . '": ' . $aReturn[$keyToWorkWith];
253
        }
254
        return '"' . $keyToWorkWith . '": {' . $aReturn[$keyToWorkWith] . ' }';
255
    }
256
257
    /**
258
     * Send an array of parameters like a form through a POST action
259
     *
260
     * @param string $urlToSendTo
261
     * @param array $params
262
     * @throws \Exception
263
     * @throws \UnexpectedValueException
264
     */
265
    protected function sendBackgroundEncodedFormElementsByPost($urlToSendTo, $params = [])
266
    {
267
        try {
268
            $postingUrl = filter_var($urlToSendTo, FILTER_VALIDATE_URL);
269
            if ($postingUrl === false) {
270
                throw new \Exception($exc);
271
            } else {
272
                if (is_array($params)) {
273
                    $postingString = $this->setArrayToStringForUrl('&', $params);
274
                    $pUrlParts     = parse_url($postingUrl);
275
                    $postingPort   = (isset($pUrlParts['port']) ? $pUrlParts['port'] : 80);
276
                    $flPointer     = fsockopen($pUrlParts['host'], $postingPort, $errNo, $errorMessage, 30);
277
                    if ($flPointer === false) {
278
                        throw new \UnexpectedValueException($this->lclMsgCmn('i18n_Error_FailedToConnect') . ': '
279
                        . $errNo . ' (' . $errorMessage . ')');
280
                    } else {
281
                        fwrite($flPointer, $this->sendBackgroundPrepareData($pUrlParts, $postingString));
282
                        fclose($flPointer);
283
                    }
284
                } else {
285
                    throw new \UnexpectedValueException($this->lclMsgCmn('i18n_Error_GivenParameterIsNotAnArray'));
286
                }
287
            }
288
        } catch (\Exception $exc) {
289
            echo '<pre style="color:#f00">' . $exc->getTraceAsString() . '</pre>';
290
        }
291
    }
292
293
    protected function sendBackgroundPrepareData($pUrlParts, $postingString)
294
    {
295
        $this->initializeSprGlbAndSession();
296
        $out   = [];
297
        $out[] = 'POST ' . $pUrlParts['path'] . ' ' . $this->tCmnSuperGlobals->server->get['SERVER_PROTOCOL'];
298
        $out[] = 'Host: ' . $pUrlParts['host'];
299
        if (is_null($this->tCmnSuperGlobals->server->get('HTTP_USER_AGENT'))) {
300
            $out[] = 'User-Agent: ' . $this->tCmnSuperGlobals->server->get('HTTP_USER_AGENT');
301
        }
302
        $out[] = 'Content-Type: application/x-www-form-urlencoded';
303
        $out[] = 'Content-Length: ' . strlen($postingString);
304
        $out[] = 'Connection: Close' . "\r\n";
305
        $out[] = $postingString;
306
        return implode("\r\n", $out);
307
    }
308
309
    /**
310
     * Returns proper result from a mathematical division in order to avoid Zero division erorr or Infinite results
311
     *
312
     * @param float $fAbove
313
     * @param float $fBelow
314
     * @param mixed $mArguments
315
     * @return decimal
316
     */
317
    protected function setDividedResult($fAbove, $fBelow, $mArguments = 0)
318
    {
319
        if (($fAbove == 0) || ($fBelow == 0)) { // prevent infinite result AND division by 0
320
            return 0;
321
        }
322
        if (is_array($mArguments)) {
323
            $frMinMax = [
324
                'MinFractionDigits' => $mArguments[1],
325
                'MaxFractionDigits' => $mArguments[1],
326
            ];
327
            return $this->setNumberFormat(($fAbove / $fBelow), $frMinMax);
328
        }
329
        return $this->setNumberFormat(round(($fAbove / $fBelow), $mArguments));
330
    }
331
332
    /**
333
     * Converts a JSON string into an Array
334
     *
335
     * @param string $inputJson
336
     * @return array
337
     */
338
    protected function setJsonToArray($inputJson)
339
    {
340
        if (!$this->isJsonByDanielGP($inputJson)) {
341
            return ['error' => $this->lclMsgCmn('i18n_Error_GivenInputIsNotJson')];
342
        }
343
        $sReturn   = (json_decode($inputJson, true));
344
        $jsonError = $this->setJsonErrorInPlainEnglish();
345
        if (is_null($jsonError)) {
346
            return $sReturn;
347
        } else {
348
            return ['error' => $jsonError];
349
        }
350
    }
351
}
352