elFinderVolumeOneDrive::_od_parseRaw()   F
last analyzed

Complexity

Conditions 14
Paths 496

Size

Total Lines 41
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 27
nc 496
nop 1
dl 0
loc 41
rs 3.1537
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 12 and the first side effect is on line 3.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
elFinder::$netDrivers['onedrive'] = 'OneDrive';
4
5
/**
6
 * Simple elFinder driver for OneDrive
7
 * onedrive api v5.0.
8
 *
9
 * @author Dmitry (dio) Levashov
10
 * @author Cem (discofever)
11
 **/
12
class elFinderVolumeOneDrive extends elFinderVolumeDriver
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
13
{
14
    /**
15
     * @var string The base URL for API requests
16
     **/
17
    const API_URL = 'https://api.onedrive.com/v1.0/drive/items/';
18
19
    /**
20
     * @var string The base URL for authorization requests
21
     */
22
    const AUTH_URL = 'https://login.live.com/oauth20_authorize.srf';
23
24
    /**
25
     * @var string The base URL for token requests
26
     */
27
    const TOKEN_URL = 'https://login.live.com/oauth20_token.srf';
28
29
    /**
30
     * Net mount key.
31
     *
32
     * @var string
33
     **/
34
    public $netMountKey = '';
35
    /**
36
     * Driver id
37
     * Must be started from letter and contains [a-z0-9]
38
     * Used as part of volume id.
39
     *
40
     * @var string
41
     **/
42
    protected $driverId = 'od';
43
44
    /**
45
     * OneDrive token object.
46
     *
47
     * @var object
48
     **/
49
    protected $token = null;
50
51
    /**
52
     * Directory for tmp files
53
     * If not set driver will try to use tmbDir as tmpDir.
54
     *
55
     * @var string
56
     **/
57
    protected $tmp = '';
58
59
    /**
60
     * Thumbnail prefix.
61
     *
62
     * @var string
63
     **/
64
    protected $tmbPrefix = '';
65
66
    /**
67
     * hasCache by folders.
68
     *
69
     * @var array
70
     **/
71
    protected $HasdirsCache = [];
72
73
    /**
74
     * Query options of API call.
75
     *
76
     * @var array
77
     */
78
    protected $queryOptions = [];
79
80
    /**
81
     * Constructor
82
     * Extend options with required fields.
83
     *
84
     * @author Dmitry (dio) Levashov
85
     * @author Cem (DiscoFever)
86
     **/
87
    public function __construct()
88
    {
89
        $opts = [
90
            'client_id' => '',
91
            'client_secret' => '',
92
            'accessToken' => '',
93
            'root' => 'OneDrive.com',
94
            'OneDriveApiClient' => '',
95
            'path' => '/',
96
            'separator' => '/',
97
            'tmbPath' => '',
98
            'tmbURL' => '',
99
            'tmpPath' => '',
100
            'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#',
101
            'rootCssClass' => 'elfinder-navbar-root-onedrive',
102
            'useApiThumbnail' => true,
103
        ];
104
        $this->options = array_merge($this->options, $opts);
105
        $this->options['mimeDetect'] = 'internal';
106
    }
107
108
    /*********************************************************************/
109
    /*                        OVERRIDE FUNCTIONS                         */
110
    /*********************************************************************/
111
112
    /**
113
     * Prepare
114
     * Call from elFinder::netmout() before volume->mount().
115
     *
116
     * @return array
117
     *
118
     * @author Naoki Sawada
119
     * @author Raja Sharma updating for OneDrive
120
     **/
121
    public function netmountPrepare($options)
0 ignored issues
show
Coding Style introduced by
netmountPrepare 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...
Coding Style introduced by
netmountPrepare 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...
Coding Style introduced by
netmountPrepare 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...
122
    {
123
        if (empty($options['client_id']) && defined('ELFINDER_ONEDRIVE_CLIENTID')) {
124
            $options['client_id'] = ELFINDER_ONEDRIVE_CLIENTID;
125
        }
126
        if (empty($options['client_secret']) && defined('ELFINDER_ONEDRIVE_CLIENTSECRET')) {
127
            $options['client_secret'] = ELFINDER_ONEDRIVE_CLIENTSECRET;
128
        }
129
130 View Code Duplication
        if (isset($options['pass']) && $options['pass'] === 'reauth') {
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...
131
            $options['user'] = 'init';
132
            $options['pass'] = '';
133
            $this->session->remove('OneDriveTokens');
134
        }
135
136 View Code Duplication
        if (isset($options['id'])) {
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...
137
            $this->session->set('nodeId', $options['id']);
138
        } elseif ($_id = $this->session->get('nodeId')) {
139
            $options['id'] = $_id;
140
            $this->session->set('nodeId', $_id);
141
        }
142
143
        try {
144 View Code Duplication
            if (empty($options['client_id']) || empty($options['client_secret'])) {
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...
145
                return ['exit' => true, 'body' => '{msg:errNetMountNoDriver}'];
146
            }
147
148 View Code Duplication
            if (isset($_GET['code'])) {
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...
149
                try {
150
                    // Obtain the token using the code received by the OneDrive API
151
                    $this->session->set('OneDriveTokens',
152
                                        $this->_od_obtainAccessToken($options['client_id'], $options['client_secret'], $_GET['code']));
153
154
                    $out = [
155
                            'node' => $options['id'],
156
                            'json' => '{"protocol": "onedrive", "mode": "done", "reset": 1}',
157
                            'bind' => 'netmount',
158
                    ];
159
160
                    return ['exit' => 'callback', 'out' => $out];
161
                } catch (Exception $e) {
162
                    $out = [
163
                            'node' => $options['id'],
164
                            'json' => json_encode(['error' => elFinder::ERROR_ACCESS_DENIED.' '.$e->getMessage()]),
165
                    ];
166
167
                    return ['exit' => 'callback', 'out' => $out];
168
                }
169
            } elseif (! empty($_GET['error'])) {
170
                $out = [
171
                        'node' => $options['id'],
172
                        'json' => json_encode(['error' => elFinder::ERROR_ACCESS_DENIED]),
173
                ];
174
175
                return ['exit' => 'callback', 'out' => $out];
176
            }
177
178
            if ($options['user'] === 'init') {
179
                $this->token = $this->session->get('OneDriveTokens');
180
181 View Code Duplication
                if ($this->token) {
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...
182
                    try {
183
                        $this->_od_refreshToken();
184
                    } catch (Exception $e) {
185
                        $this->setError($e->getMessage());
186
                        $this->token = null;
187
                        $this->session->remove('OneDriveTokens');
188
                    }
189
                }
190
191
                if (empty($this->token)) {
192
                    $result = false;
193
                } else {
194
                    $path = $options['path'];
195
                    if ($path === '/') {
196
                        $path = 'root';
197
                    }
198
                    $result = $this->_od_query($path, false, false, [
199
                        'query' => [
200
                            'select' => 'id,name',
201
                            'filter' => 'folder ne null',
202
                        ],
203
                    ]);
204
                }
205
206
                if ($result === false) {
207
                    $cdata = '';
208
                    $innerKeys = ['cmd', 'host', 'options', 'pass', 'protocol', 'user'];
209
                    $this->ARGS = $_SERVER['REQUEST_METHOD'] === 'POST' ? $_POST : $_GET;
210 View Code Duplication
                    foreach ($this->ARGS as $k => $v) {
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...
211
                        if (! in_array($k, $innerKeys)) {
212
                            $cdata .= '&'.$k.'='.rawurlencode($v);
213
                        }
214
                    }
215
                    if (empty($options['url'])) {
216
                        $options['url'] = elFinder::getConnectorUrl();
217
                    }
218
                    $callback = $options['url']
219
                        .'?cmd=netmount&protocol=onedrive&host=onedrive.com&user=init&pass=return&node='.$options['id'].$cdata;
220
221
                    try {
222
                        $this->session->set('OneDriveTokens', (object) ['token' => null]);
223
224
                        $offline = '';
225
                        // Gets a log in URL with sufficient privileges from the OneDrive API
226
                        if (! empty($options['offline'])) {
227
                            $offline = ' wl.offline_access';
228
                        }
229
230
                        $redirect_uri = $options['url'].'/netmount/onedrive/1';
231
                        $url = self::AUTH_URL
232
                            .'?client_id='.urlencode($options['client_id'])
233
                            .'&scope='.urlencode('wl.skydrive_update'.$offline)
234
                            .'&response_type=code'
235
                            .'&redirect_uri='.urlencode($redirect_uri);
236
237
                        $url .= '&oauth_callback='.rawurlencode($callback);
238
                    } catch (Exception $e) {
239
                        return ['exit' => true, 'body' => '{msg:errAccess}'];
240
                    }
241
242
                    $html = '<input id="elf-volumedriver-onedrive-host-btn" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" value="{msg:btnApprove}" type="button" onclick="window.open(\''.$url.'\')">';
243
                    $html .= '<script>
244
							$("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "onedrive", mode: "makebtn"});
245
							</script>';
246
247
                    return ['exit' => true, 'body' => $html];
248 View Code Duplication
                } else {
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...
249
                    $folders = [];
250
251
                    if ($result) {
252
                        foreach ($result as $res) {
253
                            $folders[$res->id] = $res->name;
254
                        }
255
                        natcasesort($folders);
256
                    }
257
258
                    if ($options['pass'] === 'folders') {
259
                        return ['exit' => true, 'folders' => $folders];
260
                    }
261
262
                    $folders = ['root' => 'My OneDrive'] + $folders;
263
                    $folders = json_encode($folders);
264
265
                    $expires = empty($this->token->data->refresh_token) ? (int) $this->token->expires : 0;
266
                    $json = '{"protocol": "onedrive", "mode": "done", "folders": '.$folders.', "expires": '.$expires.'}';
267
                    $html = 'OneDrive.com';
268
                    $html .= '<script>
269
							$("#'.$options['id'].'").elfinder("instance").trigger("netmount", '.$json.');
270
							</script>';
271
272
                    return ['exit' => true, 'body' => $html];
273
                }
274
            }
275
        } catch (Exception $e) {
276
            return ['exit' => true, 'body' => '{msg:errNetMountNoDriver}'];
277
        }
278
279 View Code Duplication
        if ($_aToken = $this->session->get('OneDriveTokens')) {
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...
280
            $options['accessToken'] = json_encode($_aToken);
281
        } else {
282
            $this->setError(elFinder::ERROR_NETMOUNT, $options['host'], implode(' ', $this->error()));
283
284
            return ['exit' => true, 'error' => $this->error()];
285
        }
286
287
        $this->session->remove('nodeId');
288
        unset($options['user'], $options['pass'], $options['id']);
289
290
        return $options;
291
    }
292
293
    /**
294
     * process of on netunmount
295
     * Drop `onedrive` & rm thumbs.
296
     *
297
     * @param array $options
0 ignored issues
show
Bug introduced by
There is no parameter named $options. 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...
298
     *
299
     * @return bool
300
     */
301 View Code Duplication
    public function netunmount($netVolumes, $key)
0 ignored issues
show
Unused Code introduced by
The parameter $netVolumes is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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...
302
    {
303
        if ($tmbs = glob(rtrim($this->options['tmbPath'], '\\/').DIRECTORY_SEPARATOR.$this->tmbPrefix.'*.png')) {
304
            foreach ($tmbs as $file) {
305
                unlink($file);
306
            }
307
        }
308
309
        return true;
310
    }
311
312
    /*********************************************************************/
313
    /*                               FS API                              */
314
    /*********************************************************************/
315
316
    /**
317
     * Close opened connection.
318
     *
319
     * @author Dmitry (dio) Levashov
320
     **/
321
    public function umount()
322
    {
323
    }
324
325
    /**
326
     * Return content URL.
327
     *
328
     * @param string $hash    file hash
329
     * @param array  $options options
330
     *
331
     * @return string
332
     *
333
     * @author Naoki Sawada
334
     **/
335
    public function getContentUrl($hash, $options = [])
336
    {
337 View Code Duplication
        if (! empty($options['temporary'])) {
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...
338
            // try make temporary file
339
            $url = parent::getContentUrl($hash, $options);
340
            if ($url) {
341
                return $url;
342
            }
343
        }
344
        $res = '';
345
        if (($file = $this->file($hash)) == false || ! $file['url'] || $file['url'] == 1) {
346
            $path = $this->decode($hash);
347
348
            list(, $itemId) = $this->_od_splitPath($path);
349
            try {
350
                $url = self::API_URL.$itemId.'/action.createLink';
351
                $data = (object) [
352
                    'type' => 'embed',
353
                    'scope' => 'anonymous',
354
                ];
355
                $curl = $this->_od_prepareCurl($url);
356
                curl_setopt_array($curl, [
357
                    CURLOPT_POST => true,
358
                    CURLOPT_POSTFIELDS => json_encode($data),
359
                ]);
360
361
                $result = curl_exec($curl);
362
                curl_close($curl);
363
                if ($result) {
364
                    $result = json_decode($result);
365
                    if (isset($result->link)) {
366
                        list(, $res) = explode('?', $result->link->webUrl);
367
                        $res = 'https://onedrive.live.com/download.aspx?'.$res;
368
                    }
369
                }
370
            } catch (Exception $e) {
371
                $res = '';
372
            }
373
        }
374
375
        return $res;
376
    }
377
378
    /*********************************************************************/
379
    /*                        ORIGINAL FUNCTIONS                         */
380
    /*********************************************************************/
381
382
    /**
383
     * Obtains a new access token from OAuth. This token is valid for one hour.
384
     *
385
     * @param string $clientSecret The OneDrive client secret
0 ignored issues
show
Bug introduced by
There is no parameter named $clientSecret. 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...
386
     * @param string $code         The code returned by OneDrive after
387
     *                             successful log in
388
     * @param string $redirectUri  Must be the same as the redirect URI passed
0 ignored issues
show
Bug introduced by
There is no parameter named $redirectUri. 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...
389
     *                             to LoginUrl
390
     *
391
     * @throws \Exception Thrown if this Client instance's clientId is not set
392
     * @throws \Exception Thrown if the redirect URI of this Client instance's
393
     *                    state is not set
394
     */
395
    protected function _od_obtainAccessToken($client_id, $client_secret, $code)
396
    {
397
        if (null === $client_id) {
398
            return 'The client ID must be set to call obtainAccessToken()';
399
        }
400
401
        if (null === $client_secret) {
402
            return 'The client Secret must be set to call obtainAccessToken()';
403
        }
404
405
        $url = self::TOKEN_URL;
406
407
        $curl = curl_init();
408
409
        $fields = http_build_query(
410
                [
411
                        'client_id' => $client_id,
412
                        'redirect_uri' => elFinder::getConnectorUrl(),
413
                        'client_secret' => $client_secret,
414
                        'code' => $code,
415
                        'grant_type' => 'authorization_code',
416
                ]
417
                );
418
419
        curl_setopt_array($curl, [
420
                // General options.
421
                CURLOPT_RETURNTRANSFER => true,
422
                CURLOPT_POST => true,
423
                CURLOPT_POSTFIELDS => $fields,
424
425
                CURLOPT_HTTPHEADER => [
426
                        'Content-Length: '.strlen($fields),
427
                ],
428
429
                CURLOPT_URL => $url,
430
        ]);
431
432
        $result = curl_exec($curl);
433
434 View Code Duplication
        if (false === $result) {
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...
435
            if (curl_errno($curl)) {
436
                throw new \Exception('curl_setopt_array() failed: '
437
                        .curl_error($curl));
438
            } else {
439
                throw new \Exception('curl_setopt_array(): empty response');
440
            }
441
        }
442
        curl_close($curl);
443
444
        $decoded = json_decode($result);
445
446
        if (null === $decoded) {
447
            throw new \Exception('json_decode() failed');
448
        }
449
450
        return (object) [
451
                'expires' => time() + $decoded->expires_in - 30,
452
                'data' => $decoded,
453
        ];
454
    }
455
456
    /**
457
     * Get token and auto refresh.
458
     *
459
     * @return true|Exception
460
     */
461
    protected function _od_refreshToken()
462
    {
463
        if ($this->token->expires < time()) {
464
            if (! $token = $this->session->get('OneDriveTokens')) {
465
                $token = $this->token;
466
            }
467
            if (empty($token->data->refresh_token)) {
468
                $this->session->remove('OneDriveTokens');
469
                throw new \Exception(elFinder::ERROR_REAUTH_REQUIRE);
470
            }
471
472
            if (! $this->options['client_id']) {
473
                $this->options['client_id'] = ELFINDER_ONEDRIVE_CLIENTID;
474
            }
475
476
            if (! $this->options['client_secret']) {
477
                $this->options['client_secret'] = ELFINDER_ONEDRIVE_CLIENTSECRET;
478
            }
479
480
            $url = self::TOKEN_URL;
481
482
            $curl = curl_init();
483
484
            curl_setopt_array($curl, [
485
                        // General options.
486
                        CURLOPT_RETURNTRANSFER => true,
487
                        CURLOPT_POST => true, // i am sending post data
488
                        CURLOPT_POSTFIELDS => 'client_id='.urlencode($this->options['client_id'])
489
                        .'&client_secret='.urlencode($this->options['client_secret'])
490
                        .'&grant_type=refresh_token'
491
                        .'&refresh_token='.urlencode($token->data->refresh_token),
492
493
                        CURLOPT_URL => $url,
494
                ]);
495
496
            $result = curl_exec($curl);
497
498 View Code Duplication
            if (! $result) {
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...
499
                if (curl_errno($curl)) {
500
                    throw new \Exception('curl_setopt_array() failed: '.curl_error($curl));
501
                } else {
502
                    throw new \Exception('curl_setopt_array(): empty response');
503
                }
504
            }
505
            curl_close($curl);
506
507
            $decoded = json_decode($result);
508
509
            if (! $decoded) {
510
                throw new \Exception('json_decode() failed');
511
            }
512
513
            if (empty($decoded->access_token)) {
514
                throw new \Exception(elFinder::ERROR_REAUTH_REQUIRE);
515
            }
516
517
            $token = (object) [
518
                        'expires' => time() + $decoded->expires_in - 30,
519
                        'data' => $decoded,
520
                ];
521
522
            $this->session->set('OneDriveTokens', $token);
523
            $this->options['accessToken'] = json_encode($token);
524
            $this->token = $token;
525
526 View Code Duplication
            if (! empty($this->options['netkey'])) {
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...
527
                elFinder::$instance->updateNetVolumeOption($this->options['netkey'], 'accessToken', $this->options['accessToken']);
528
            }
529
        }
530
531
        return true;
532
    }
533
534
    /**
535
     * Get Parent ID, Item ID, Parent Path as an array from path.
536
     *
537
     * @param string $path
538
     *
539
     * @return array
540
     */
541 View Code Duplication
    protected function _od_splitPath($path)
0 ignored issues
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...
542
    {
543
        $path = trim($path, '/');
544
        $pid = '';
545
        if ($path === '') {
546
            $id = 'root';
547
            $parent = '';
548
        } else {
549
            $paths = explode('/', trim($path, '/'));
550
            $id = array_pop($paths);
551
            if ($paths) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $paths of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
552
                $parent = '/'.implode('/', $paths);
553
                $pid = array_pop($paths);
554
            } else {
555
                $pid = 'root';
556
                $parent = '/';
557
            }
558
        }
559
560
        return [$pid, $id, $parent];
561
    }
562
563
    /**
564
     * Creates a base cURL object which is compatible with the OneDrive API.
565
     *
566
     * @return resource A compatible cURL object
567
     */
568
    protected function _od_prepareCurl($url = null)
569
    {
570
        $curl = curl_init($url);
571
572
        $defaultOptions = [
573
                // General options.
574
                CURLOPT_RETURNTRANSFER => true,
575
                CURLOPT_HTTPHEADER => [
576
                        'Content-Type: application/json',
577
                        'Authorization: Bearer '.$this->token->data->access_token,
578
                ],
579
        ];
580
581
        curl_setopt_array($curl, $defaultOptions);
582
583
        return $curl;
584
    }
585
586
    /**
587
     * Creates a base cURL object which is compatible with the OneDrive API.
588
     *
589
     * @param string $path The path of the API call (eg. me/skydrive)
590
     *
591
     * @return resource A compatible cURL object
592
     */
593
    protected function _od_createCurl($path, $contents = false)
594
    {
595
        elfinder::extendTimeLimit();
596
        $curl = $this->_od_prepareCurl($path);
597
598
        if ($contents) {
599
            $res = elFinder::curlExec($curl);
600
        } else {
601
            $result = json_decode(curl_exec($curl));
602
            curl_close($curl);
603
            if (isset($result->value)) {
604
                $res = $result->value;
605
                unset($result->value);
606
                $result = (array) $result;
607
                if (! empty($result['@odata.nextLink'])) {
608
                    $nextRes = $this->_od_createCurl($result['@odata.nextLink'], false);
609
                    if (is_array($nextRes)) {
610
                        $res = array_merge($res, $nextRes);
611
                    }
612
                }
613
            } else {
614
                $res = $result;
615
            }
616
        }
617
618
        return $res;
619
    }
620
621
    /**
622
     * Drive query and fetchAll.
623
     *
624
     * @param string $sql
0 ignored issues
show
Bug introduced by
There is no parameter named $sql. 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...
625
     *
626
     * @return object|array
627
     */
628
    protected function _od_query($itemId, $fetch_self = false, $recursive = false, $options = [])
629
    {
630
        $result = [];
631
632
        if (null === $itemId) {
633
            $itemId = 'root';
634
        }
635
636
        if ($fetch_self == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
637
            $path = $itemId;
638
        } else {
639
            $path = $itemId.'/children';
640
        }
641
642
        if (isset($options['query'])) {
643
            $path .= '?'.http_build_query($options['query']);
644
        }
645
646
        $url = self::API_URL.$path;
647
648
        $res = $this->_od_createCurl($url);
649
        if (! $fetch_self && $recursive && is_array($res)) {
650
            foreach ($res as $file) {
651
                $result[] = $file;
652
                if (! empty($file->folder)) {
653
                    $result = array_merge($result, $this->_od_query($file->id, false, true, $options));
654
                }
655
            }
656
        } else {
657
            $result = $res;
658
        }
659
660
        return isset($result->error) ? [] : $result;
661
    }
662
663
    /**
664
     * Parse line from onedrive metadata output and return file stat (array).
665
     *
666
     * @param string $raw line from ftp_rawlist() output
667
     *
668
     * @return array
669
     *
670
     * @author Dmitry Levashov
671
     **/
672
    protected function _od_parseRaw($raw)
673
    {
674
        $stat = [];
675
676
        $folder = isset($raw->folder) ? $raw->folder : null;
677
678
        $stat['rev'] = isset($raw->id) ? $raw->id : 'root';
679
        $stat['name'] = $raw->name;
680
        if (isset($raw->lastModifiedDateTime)) {
681
            $stat['ts'] = strtotime($raw->lastModifiedDateTime);
682
        }
683
684
        if ($folder) {
685
            $stat['mime'] = 'directory';
686
            $stat['size'] = 0;
687
            if (empty($folder->childCount)) {
688
                $stat['dirs'] = 0;
689
            } else {
690
                $stat['dirs'] = -1;
691
            }
692
        } else {
693
            if (isset($raw->file->mimeType)) {
694
                $stat['mime'] = $raw->file->mimeType;
695
            }
696
            $stat['size'] = (int) $raw->size;
697
            if (! $this->disabledGetUrl) {
698
                $stat['url'] = '1';
699
            }
700
            if (isset($raw->image) && $img = $raw->image) {
701
                isset($img->width) ? $stat['width'] = $img->width : $stat['width'] = 0;
702
                isset($img->height) ? $stat['height'] = $img->height : $stat['height'] = 0;
703
            }
704
            if (! empty($raw->thumbnails)) {
705
                if ($raw->thumbnails[0]->small->url) {
706
                    $stat['tmb'] = substr($raw->thumbnails[0]->small->url, 8); // remove "https://"
707
                }
708
            }
709
        }
710
711
        return $stat;
712
    }
713
714
    /**
715
     * Get raw data(onedrive metadata) from OneDrive.
716
     *
717
     * @param string $path
718
     *
719
     * @return array|object onedrive metadata
720
     */
721
    protected function _od_getFileRaw($path)
722
    {
723
        list(, $itemId) = $this->_od_splitPath($path);
724
        try {
725
            $res = $this->_od_query($itemId, true, false, $this->queryOptions);
726
727
            return $res;
728
        } catch (Exception $e) {
729
            return [];
730
        }
731
    }
732
733
    /**
734
     * Get thumbnail from OneDrive.com.
735
     *
736
     * @param string $path
737
     * @param string $size
0 ignored issues
show
Bug introduced by
There is no parameter named $size. 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...
738
     *
739
     * @return string | boolean
740
     */
741 View Code Duplication
    protected function _od_getThumbnail($path)
0 ignored issues
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...
742
    {
743
        list(, $itemId) = $this->_od_splitPath($path);
744
745
        try {
746
            $url = self::API_URL.$itemId.'/thumbnails/0/medium/content';
747
748
            return $this->_od_createCurl($url, $contents = true);
749
        } catch (Exception $e) {
750
            return false;
751
        }
752
    }
753
754
    /*********************************************************************/
755
    /*                        INIT AND CONFIGURE                         */
756
    /*********************************************************************/
757
758
    /**
759
     * Prepare FTP connection
760
     * Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn.
761
     *
762
     * @return bool
763
     *
764
     * @author Dmitry (dio) Levashov
765
     * @author Cem (DiscoFever)
766
     **/
767
    protected function init()
768
    {
769
        if (! $this->options['accessToken']) {
770
            return $this->setError('Required option `accessToken` is undefined.');
771
        }
772
773
        try {
774
            $this->token = json_decode($this->options['accessToken']);
775
            $this->_od_refreshToken();
776
        } catch (Exception $e) {
777
            $this->token = null;
778
            $this->session->remove('OneDriveTokens');
779
780
            return $this->setError($e->getMessage());
781
        }
782
783 View Code Duplication
        if (empty($options['netkey'])) {
0 ignored issues
show
Bug introduced by
The variable $options seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
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...
784
            // make net mount key
785
            $_tokenKey = isset($this->token->data->refresh_token) ? $this->token->data->refresh_token : $this->token->data->access_token;
786
            $this->netMountKey = md5(implode('-', ['box', $this->options['path'], $_tokenKey]));
787
        } else {
788
            $this->netMountKey = $options['netkey'];
789
        }
790
791
        // normalize root path
792
        if ($this->options['path'] == 'root') {
793
            $this->options['path'] = '/';
794
        }
795
796
        $this->root = $this->options['path'] = $this->_normpath($this->options['path']);
797
798
        $this->options['root'] == '' ? $this->options['root'] = 'OneDrive.com' : $this->options['root'];
799
800 View Code Duplication
        if (empty($this->options['alias'])) {
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...
801
            $this->options['alias'] = ($this->options['path'] === '/') ? $this->options['root'] :
802
                                      $this->_od_query(basename($this->options['path']), $fetch_self = true)->name.'@OneDrive';
803
        }
804
805
        $this->rootName = $this->options['alias'];
806
807
        $this->tmbPrefix = 'onedrive'.base_convert($this->netMountKey, 10, 32);
808
809
        if (! empty($this->options['tmpPath'])) {
810
            if ((is_dir($this->options['tmpPath']) || mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) {
811
                $this->tmp = $this->options['tmpPath'];
812
            }
813
        }
814
815
        if (! $this->tmp && ($tmp = elFinder::getStaticVar('commonTempPath'))) {
816
            $this->tmp = $tmp;
817
        }
818
819
        // This driver dose not support `syncChkAsTs`
820
        $this->options['syncChkAsTs'] = false;
821
822
        // 'lsPlSleep' minmum 10 sec
823
        $this->options['lsPlSleep'] = max(10, $this->options['lsPlSleep']);
824
825
        $this->queryOptions = [
826
            'query' => [
827
                'select' => 'id,name,lastModifiedDateTime,file,folder,size,image',
828
            ],
829
        ];
830
831
        if ($this->options['useApiThumbnail']) {
832
            $this->options['tmbURL'] = 'https://';
833
            $this->queryOptions['query']['expand'] = 'thumbnails(select=small)';
834
        }
835
836
        return true;
837
    }
838
839
    /**
840
     * Configure after successfull mount.
841
     *
842
     * @author Dmitry (dio) Levashov
843
     **/
844
    protected function configure()
845
    {
846
        parent::configure();
847
848
        // fallback of $this->tmp
849
        if (! $this->tmp && $this->tmbPathWritable) {
850
            $this->tmp = $this->tmbPath;
851
        }
852
853
        $this->disabled[] = 'archive';
854
        $this->disabled[] = 'extract';
855
    }
856
857
    protected function isNameExists($path)
858
    {
859
        list($pid, $name) = $this->_od_splitPath($path);
860
861
        return (bool) $this->_od_query($pid.'/children/'.rawurlencode($name).'?select=id', true);
862
    }
863
864
    /**
865
     * Cache dir contents.
866
     *
867
     * @param string $path dir path
868
     *
869
     * @author Dmitry Levashov
870
     **/
871
    protected function cacheDir($path)
872
    {
873
        $this->dirsCache[$path] = [];
874
        $hasDir = false;
875
876
        list(, $itemId) = $this->_od_splitPath($path);
877
878
        $res = $this->_od_query($itemId, false, false, $this->queryOptions);
879
880
        if ($res) {
881
            foreach ($res as $raw) {
882
                if ($stat = $this->_od_parseRaw($raw)) {
883
                    $itemPath = $this->_joinPath($path, $raw->id);
884
                    $stat = $this->updateCache($itemPath, $stat);
885
                    if (empty($stat['hidden'])) {
886
                        if (! $hasDir && $stat['mime'] === 'directory') {
887
                            $hasDir = true;
888
                        }
889
                        $this->dirsCache[$path][] = $itemPath;
890
                    }
891
                }
892
            }
893
        }
894
895
        if (isset($this->sessionCache['subdirs'])) {
896
            $this->sessionCache['subdirs'][$path] = $hasDir;
897
        }
898
899
        return $this->dirsCache[$path];
900
    }
901
902
    /**
903
     * Copy file/recursive copy dir only in current volume.
904
     * Return new file path or false.
905
     *
906
     * @param string $src  source path
907
     * @param string $dst  destination dir path
908
     * @param string $name new file name (optionaly)
909
     *
910
     * @return string|false
911
     *
912
     * @author Dmitry (dio) Levashov
913
     * @author Naoki Sawada
914
     **/
915
    protected function copy($src, $dst, $name)
916
    {
917
        $itemId = '';
0 ignored issues
show
Unused Code introduced by
$itemId 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...
918 View Code Duplication
        if ($this->options['copyJoin']) {
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...
919
            $test = $this->joinPathCE($dst, $name);
920
            if ($testStat = $this->isNameExists($test)) {
0 ignored issues
show
Unused Code introduced by
$testStat 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...
921
                $this->remove($test);
922
            }
923
        }
924
925
        $path = $this->_copy($src, $dst, $name);
926
927
        return $path
928
            ? $path
929
            : $this->setError(elFinder::ERROR_COPY, $this->_path($src));
930
    }
931
932
    /**
933
     * Remove file/ recursive remove dir.
934
     *
935
     * @param string $path  file path
936
     * @param bool   $force try to remove even if file locked
937
     *
938
     * @return bool
939
     *
940
     * @author Dmitry (dio) Levashov
941
     * @author Naoki Sawada
942
     **/
943 View Code Duplication
    protected function remove($path, $force = false)
0 ignored issues
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...
944
    {
945
        $stat = $this->stat($path);
946
        $stat['realpath'] = $path;
947
        $this->rmTmb($stat);
0 ignored issues
show
Documentation introduced by
$stat is of type array<string,string,{"realpath":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
948
        $this->clearcache();
949
950
        if (empty($stat)) {
951
            return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND);
952
        }
953
954
        if (! $force && ! empty($stat['locked'])) {
955
            return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path));
956
        }
957
958
        if ($stat['mime'] == 'directory') {
959
            if (! $this->_rmdir($path)) {
960
                return $this->setError(elFinder::ERROR_RM, $this->_path($path));
961
            }
962
        } else {
963
            if (! $this->_unlink($path)) {
964
                return $this->setError(elFinder::ERROR_RM, $this->_path($path));
965
            }
966
        }
967
968
        $this->removed[] = $stat;
969
970
        return true;
971
    }
972
973
    /**
974
     * Create thumnbnail and return it's URL on success.
975
     *
976
     * @param string $path file path
977
     * @param string $mime file mime type
0 ignored issues
show
Bug introduced by
There is no parameter named $mime. 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...
978
     *
979
     * @return string|false
980
     *
981
     * @author Dmitry (dio) Levashov
982
     * @author Naoki Sawada
983
     **/
984 View Code Duplication
    protected function createTmb($path, $stat)
0 ignored issues
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...
985
    {
986
        if (! $stat || ! $this->canCreateTmb($path, $stat)) {
987
            return false;
988
        }
989
990
        $name = $this->tmbname($stat);
991
        $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name;
992
993
        // copy image into tmbPath so some drivers does not store files on local fs
994
        if (! $data = $this->_od_getThumbnail($path)) {
995
            return false;
996
        }
997
        if (! file_put_contents($tmb, $data)) {
998
            return false;
999
        }
1000
1001
        $result = false;
0 ignored issues
show
Unused Code introduced by
$result 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...
1002
1003
        $tmbSize = $this->tmbSize;
1004
1005
        if (($s = getimagesize($tmb)) == false) {
1006
            return false;
1007
        }
1008
1009
        /* If image smaller or equal thumbnail size - just fitting to thumbnail square */
1010
        if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) {
1011
            $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png');
1012
        } else {
1013
            if ($this->options['tmbCrop']) {
1014
1015
                /* Resize and crop if image bigger than thumbnail */
1016
                if (! (($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize)) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) {
1017
                    $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png');
0 ignored issues
show
Unused Code introduced by
$result 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...
1018
                }
1019
1020
                if (($s = getimagesize($tmb)) != false) {
1021
                    $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize) / 2) : 0;
1022
                    $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize) / 2) : 0;
1023
                    $result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png');
0 ignored issues
show
Documentation introduced by
$x is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$y is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Unused Code introduced by
$result 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...
1024
                }
1025
            } else {
1026
                $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, 'png');
0 ignored issues
show
Unused Code introduced by
$result 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...
1027
            }
1028
1029
            $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png');
1030
        }
1031
1032
        if (! $result) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1033
            unlink($tmb);
1034
1035
            return false;
1036
        }
1037
1038
        return $name;
1039
    }
1040
1041
    /**
1042
     * Return thumbnail file name for required file.
1043
     *
1044
     * @param array $stat file stat
1045
     *
1046
     * @return string
1047
     *
1048
     * @author Dmitry (dio) Levashov
1049
     **/
1050
    protected function tmbname($stat)
1051
    {
1052
        return $this->tmbPrefix.$stat['rev'].$stat['ts'].'.png';
1053
    }
1054
1055
    /*********************** paths/urls *************************/
1056
1057
    /**
1058
     * Return parent directory path.
1059
     *
1060
     * @param string $path file path
1061
     *
1062
     * @return string
1063
     *
1064
     * @author Dmitry (dio) Levashov
1065
     **/
1066
    protected function _dirname($path)
1067
    {
1068
        list(, , $dirname) = $this->_od_splitPath($path);
1069
1070
        return $dirname;
1071
    }
1072
1073
    /**
1074
     * Return file name.
1075
     *
1076
     * @param string $path file path
1077
     *
1078
     * @return string
1079
     *
1080
     * @author Dmitry (dio) Levashov
1081
     **/
1082
    protected function _basename($path)
1083
    {
1084
        list(, $basename) = $this->_od_splitPath($path);
1085
1086
        return $basename;
1087
    }
1088
1089
    /**
1090
     * Join dir name and file name and retur full path.
1091
     *
1092
     * @param string $dir
1093
     * @param string $name
1094
     *
1095
     * @return string
1096
     *
1097
     * @author Dmitry (dio) Levashov
1098
     **/
1099
    protected function _joinPath($dir, $name)
1100
    {
1101
        if ($dir === 'root') {
1102
            $dir = '';
1103
        }
1104
1105
        return $this->_normpath($dir.'/'.$name);
1106
    }
1107
1108
    /**
1109
     * Return normalized path, this works the same as os.path.normpath() in Python.
1110
     *
1111
     * @param string $path path
1112
     *
1113
     * @return string
1114
     *
1115
     * @author Troex Nevelin
1116
     **/
1117 View Code Duplication
    protected function _normpath($path)
0 ignored issues
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...
1118
    {
1119
        if (DIRECTORY_SEPARATOR !== '/') {
1120
            $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
1121
        }
1122
        $path = '/'.ltrim($path, '/');
1123
1124
        return $path;
1125
    }
1126
1127
    /**
1128
     * Return file path related to root dir.
1129
     *
1130
     * @param string $path file path
1131
     *
1132
     * @return string
1133
     *
1134
     * @author Dmitry (dio) Levashov
1135
     **/
1136
    protected function _relpath($path)
1137
    {
1138
        return $path;
1139
    }
1140
1141
    /**
1142
     * Convert path related to root dir into real path.
1143
     *
1144
     * @param string $path file path
1145
     *
1146
     * @return string
1147
     *
1148
     * @author Dmitry (dio) Levashov
1149
     **/
1150
    protected function _abspath($path)
1151
    {
1152
        return $path;
1153
    }
1154
1155
    /**
1156
     * Return fake path started from root dir.
1157
     *
1158
     * @param string $path file path
1159
     *
1160
     * @return string
1161
     *
1162
     * @author Dmitry (dio) Levashov
1163
     **/
1164
    protected function _path($path)
1165
    {
1166
        return $this->rootName.$this->_normpath(substr($path, strlen($this->root)));
1167
    }
1168
1169
    /**
1170
     * Return true if $path is children of $parent.
1171
     *
1172
     * @param string $path   path to check
1173
     * @param string $parent parent path
1174
     *
1175
     * @return bool
1176
     *
1177
     * @author Dmitry (dio) Levashov
1178
     **/
1179
    protected function _inpath($path, $parent)
1180
    {
1181
        return $path == $parent || strpos($path, $parent.'/') === 0;
1182
    }
1183
1184
    /***************** file stat ********************/
1185
1186
    /**
1187
     * Return stat for given path.
1188
     * Stat contains following fields:
1189
     * - (int)    size    file size in b. required
1190
     * - (int)    ts      file modification time in unix time. required
1191
     * - (string) mime    mimetype. required for folders, others - optionally
1192
     * - (bool)   read    read permissions. required
1193
     * - (bool)   write   write permissions. required
1194
     * - (bool)   locked  is object locked. optionally
1195
     * - (bool)   hidden  is object hidden. optionally
1196
     * - (string) alias   for symlinks - link target path relative to root path. optionally
1197
     * - (string) target  for symlinks - link target path. optionally.
1198
     *
1199
     * If file does not exists - returns empty array or false.
1200
     *
1201
     * @param string $path file path
1202
     *
1203
     * @return array|false
1204
     *
1205
     * @author Dmitry (dio) Levashov
1206
     **/
1207
    protected function _stat($path)
1208
    {
1209
        if ($raw = $this->_od_getFileRaw($path)) {
1210
            return $this->_od_parseRaw($raw);
0 ignored issues
show
Documentation introduced by
$raw is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1211
        }
1212
1213
        return false;
1214
    }
1215
1216
    /**
1217
     * Return true if path is dir and has at least one childs directory.
1218
     *
1219
     * @param string $path dir path
1220
     *
1221
     * @return bool
1222
     *
1223
     * @author Dmitry (dio) Levashov
1224
     **/
1225
    protected function _subdirs($path)
1226
    {
1227
        list(, $itemId) = $this->_od_splitPath($path);
1228
1229
        return (bool) $this->_od_query($itemId, false, false, [
1230
            'query' => [
1231
                'top' => 1,
1232
                'select' => 'id',
1233
                'filter' => 'folder ne null',
1234
            ],
1235
        ]);
1236
    }
1237
1238
    /**
1239
     * Return object width and height
1240
     * Ususaly used for images, but can be realize for video etc...
1241
     *
1242
     * @param string $path file path
1243
     * @param string $mime file mime type
1244
     *
1245
     * @return string
1246
     *
1247
     * @author Dmitry (dio) Levashov
1248
     **/
1249
    protected function _dimensions($path, $mime)
1250
    {
1251
        if (strpos($mime, 'image') !== 0) {
1252
            return '';
1253
        }
1254
1255
        $cache = $this->_od_getFileRaw($path);
1256
1257
        if ($cache && $img = $cache->image) {
1258
            if (isset($img->width) && isset($img->height)) {
1259
                return $img->width.'x'.$img->height;
1260
            }
1261
        }
1262
1263
        $ret = '';
1264 View Code Duplication
        if ($work = $this->getWorkFile($path)) {
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...
1265
            if ($size = @getimagesize($work)) {
1266
                $cache['width'] = $size[0];
1267
                $cache['height'] = $size[1];
1268
                $ret = $size[0].'x'.$size[1];
1269
            }
1270
        }
1271
        is_file($work) && @unlink($work);
1272
1273
        return $ret;
1274
    }
1275
1276
    /******************** file/dir content *********************/
1277
1278
    /**
1279
     * Return files list in directory.
1280
     *
1281
     * @param string $path dir path
1282
     *
1283
     * @return array
1284
     *
1285
     * @author Dmitry (dio) Levashov
1286
     * @author Cem (DiscoFever)
1287
     **/
1288
    protected function _scandir($path)
1289
    {
1290
        return isset($this->dirsCache[$path])
1291
            ? $this->dirsCache[$path]
1292
            : $this->cacheDir($path);
1293
    }
1294
1295
    /**
1296
     * Open file and return file pointer.
1297
     *
1298
     * @param string $path  file path
1299
     * @param bool   $write open file for writing
0 ignored issues
show
Bug introduced by
There is no parameter named $write. 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...
1300
     *
1301
     * @return resource|false
1302
     *
1303
     * @author Dmitry (dio) Levashov
1304
     **/
1305 View Code Duplication
    protected function _fopen($path, $mode = 'rb')
0 ignored issues
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...
1306
    {
1307
        if ($mode === 'rb' || $mode === 'r') {
1308
            list(, $itemId) = $this->_od_splitPath($path);
1309
            $data = [
1310
                'target' => self::API_URL.$itemId.'/content',
1311
                'headers' => ['Authorization: Bearer '.$this->token->data->access_token],
1312
            ];
1313
1314
            return elFinder::getStreamByUrl($data);
1315
        }
1316
1317
        return false;
1318
    }
1319
1320
    /**
1321
     * Close opened file.
1322
     *
1323
     * @param resource $fp file pointer
1324
     *
1325
     * @return bool
1326
     *
1327
     * @author Dmitry (dio) Levashov
1328
     **/
1329
    protected function _fclose($fp, $path = '')
1330
    {
1331
        fclose($fp);
1332
        if ($path) {
1333
            unlink($this->getTempFile($path));
1334
        }
1335
    }
1336
1337
    /********************  file/dir manipulations *************************/
1338
1339
    /**
1340
     * Create dir and return created dir path or false on failed.
1341
     *
1342
     * @param string $path parent dir path
1343
     * @param string $name new directory name
1344
     *
1345
     * @return string|bool
1346
     *
1347
     * @author Dmitry (dio) Levashov
1348
     **/
1349
    protected function _mkdir($path, $name)
1350
    {
1351
        $namePath = $this->_joinPath($path, $name);
1352
        list($parentId) = $this->_od_splitPath($namePath);
1353
1354
        try {
1355
            $properties = [
1356
                'name' => (string) $name,
1357
                'folder' => (object) [],
1358
            ];
1359
1360
            $data = (object) $properties;
1361
1362
            $url = self::API_URL.$parentId.'/children';
1363
1364
            $curl = $this->_od_prepareCurl($url);
1365
1366
            curl_setopt_array($curl, [
1367
                CURLOPT_POST => true,
1368
                CURLOPT_POSTFIELDS => json_encode($data),
1369
            ]);
1370
1371
            //create the Folder in the Parent
1372
            $result = curl_exec($curl);
1373
            curl_close($curl);
1374
            $folder = json_decode($result);
1375
1376
            return $this->_joinPath($path, $folder->id);
1377
        } catch (Exception $e) {
1378
            return $this->setError('OneDrive error: '.$e->getMessage());
1379
        }
1380
    }
1381
1382
    /**
1383
     * Create file and return it's path or false on failed.
1384
     *
1385
     * @param string $path parent dir path
1386
     * @param string $name new file name
1387
     *
1388
     * @return string|bool
1389
     *
1390
     * @author Dmitry (dio) Levashov
1391
     **/
1392
    protected function _mkfile($path, $name)
1393
    {
1394
        return $this->_save(tmpfile(), $path, $name, []);
1395
    }
1396
1397
    /**
1398
     * Create symlink. FTP driver does not support symlinks.
1399
     *
1400
     * @param string $target link target
1401
     * @param string $path   symlink path
1402
     *
1403
     * @return bool
1404
     *
1405
     * @author Dmitry (dio) Levashov
1406
     **/
1407
    protected function _symlink($target, $path, $name)
1408
    {
1409
        return false;
1410
    }
1411
1412
    /**
1413
     * Copy file into another file.
1414
     *
1415
     * @param string $source    source file path
1416
     * @param string $targetDir target directory path
1417
     * @param string $name      new file name
1418
     *
1419
     * @return bool
1420
     *
1421
     * @author Dmitry (dio) Levashov
1422
     **/
1423
    protected function _copy($source, $targetDir, $name)
1424
    {
1425
        $path = $this->_joinPath($targetDir, $name);
0 ignored issues
show
Unused Code introduced by
$path 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...
1426
1427
        try {
1428
            //Set the Parent id
1429
            list(, $parentId) = $this->_od_splitPath($targetDir);
1430
            list(, $itemId) = $this->_od_splitPath($source);
1431
1432
            $url = self::API_URL.$itemId.'/action.copy';
1433
1434
            $properties = [
1435
                'name' => (string) $name,
1436
            ];
1437
            if ($parentId === 'root') {
1438
                $properties['parentReference'] = (object) ['path' => '/drive/root:'];
1439
            } else {
1440
                $properties['parentReference'] = (object) ['id' => (string) $parentId];
1441
            }
1442
            $data = (object) $properties;
1443
            $curl = $this->_od_prepareCurl($url);
1444
            curl_setopt_array($curl, [
1445
                CURLOPT_POST => true,
1446
                CURLOPT_HEADER => true,
1447
                CURLOPT_HTTPHEADER => [
1448
                      'Content-Type: application/json',
1449
                       'Authorization: Bearer '.$this->token->data->access_token,
1450
                    'Prefer: respond-async',
1451
                ],
1452
                CURLOPT_POSTFIELDS => json_encode($data),
1453
            ]);
1454
            $result = curl_exec($curl);
1455
            curl_close($curl);
1456
1457
            $res = false;
1458
            if (preg_match('/Location: (.+)/', $result, $m)) {
1459
                $monUrl = trim($m[1]);
1460
                while (! $res) {
1461
                    usleep(200000);
1462
                    $curl = $this->_od_prepareCurl($monUrl);
1463
                    $state = json_decode(curl_exec($curl));
1464
                    curl_close($curl);
1465
                    if (isset($state->status)) {
1466
                        if ($state->status === 'failed') {
1467
                            break;
1468
                        } else {
1469
                            continue;
1470
                        }
1471
                    }
1472
                    $res = $state;
1473
                }
1474
            }
1475
1476 View Code Duplication
            if ($res && isset($res->id)) {
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...
1477
                if (isset($res->folder) && isset($this->sessionCache['subdirs'])) {
1478
                    $this->sessionCache['subdirs'][$targetDir] = true;
1479
                }
1480
1481
                return $this->_joinPath($targetDir, $res->id);
1482
            }
1483
1484
            return false;
1485
        } catch (Exception $e) {
1486
            return $this->setError('OneDrive error: '.$e->getMessage());
1487
        }
1488
1489
        return true;
0 ignored issues
show
Unused Code introduced by
return true; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1490
    }
1491
1492
    /**
1493
     * Move file into another parent dir.
1494
     * Return new file path or false.
1495
     *
1496
     * @param string $source source file path
1497
     * @param string $target target dir path
0 ignored issues
show
Documentation introduced by
There is no parameter named $target. Did you maybe mean $targetDir?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

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

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

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

Loading history...
1498
     * @param string $name   file name
1499
     *
1500
     * @return string|bool
1501
     *
1502
     * @author Dmitry (dio) Levashov
1503
     **/
1504
    protected function _move($source, $targetDir, $name)
1505
    {
1506
        try {
1507
            list(, $targetParentId) = $this->_od_splitPath($targetDir);
1508
            list($sourceParentId, $itemId, $srcParent) = $this->_od_splitPath($source);
0 ignored issues
show
Unused Code introduced by
The assignment to $srcParent is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1509
1510
            $properties = [
1511
                    'name' => (string) $name,
1512
                ];
1513
            if ($targetParentId !== $sourceParentId) {
1514
                $properties['parentReference'] = (object) ['id' => (string) $targetParentId];
1515
            }
1516
1517
            $url = self::API_URL.$itemId;
1518
            $data = (object) $properties;
1519
1520
            $curl = $this->_od_prepareCurl($url);
1521
1522
            curl_setopt_array($curl, [
1523
                    CURLOPT_CUSTOMREQUEST => 'PATCH',
1524
                    CURLOPT_POSTFIELDS => json_encode($data),
1525
                ]);
1526
1527
            $result = json_decode(curl_exec($curl));
1528
            curl_close($curl);
1529 View Code Duplication
            if ($result && isset($result->id)) {
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...
1530
                return $targetDir.'/'.$result->id;
1531
            } else {
1532
                return false;
1533
            }
1534
        } catch (Exception $e) {
1535
            return $this->setError('OneDrive error: '.$e->getMessage());
1536
        }
1537
1538
        return false;
0 ignored issues
show
Unused Code introduced by
return false; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1539
    }
1540
1541
    /**
1542
     * Remove file.
1543
     *
1544
     * @param string $path file path
1545
     *
1546
     * @return bool
1547
     *
1548
     * @author Dmitry (dio) Levashov
1549
     **/
1550
    protected function _unlink($path)
1551
    {
1552
        $stat = $this->stat($path);
0 ignored issues
show
Unused Code introduced by
$stat 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...
1553
        try {
1554
            list(, $itemId) = $this->_od_splitPath($path);
1555
1556
            $url = self::API_URL.$itemId;
1557
1558
            $curl = $this->_od_prepareCurl($url);
1559
            curl_setopt_array($curl, [
1560
                CURLOPT_CUSTOMREQUEST => 'DELETE',
1561
            ]);
1562
1563
            //unlink or delete File or Folder in the Parent
1564
            $result = curl_exec($curl);
0 ignored issues
show
Unused Code introduced by
$result 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...
1565
            curl_close($curl);
1566
        } catch (Exception $e) {
1567
            return $this->setError('OneDrive error: '.$e->getMessage());
1568
        }
1569
1570
        return true;
1571
    }
1572
1573
    /**
1574
     * Remove dir.
1575
     *
1576
     * @param string $path dir path
1577
     *
1578
     * @return bool
1579
     *
1580
     * @author Dmitry (dio) Levashov
1581
     **/
1582
    protected function _rmdir($path)
1583
    {
1584
        return $this->_unlink($path);
1585
    }
1586
1587
    /**
1588
     * Create new file and write into it from file pointer.
1589
     * Return new file path or false on error.
1590
     *
1591
     * @param resource $fp   file pointer
1592
     * @param string   $dir  target dir path
0 ignored issues
show
Bug introduced by
There is no parameter named $dir. 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...
1593
     * @param string   $name file name
1594
     * @param array    $stat file stat (required by some virtual fs)
1595
     *
1596
     * @return bool|string
1597
     *
1598
     * @author Dmitry (dio) Levashov
1599
     **/
1600
    protected function _save($fp, $path, $name, $stat)
1601
    {
1602
        $itemId = '';
1603 View Code Duplication
        if ($name === '') {
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...
1604
            list($parentId, $itemId, $parent) = $this->_od_splitPath($path);
1605
        } else {
1606
            if ($stat) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $stat of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1607
                if (isset($stat['name'])) {
1608
                    $name = $stat['name'];
1609
                }
1610
                if (isset($stat['rev']) && strpos($stat['hash'], $this->id) === 0) {
1611
                    $itemId = $stat['rev'];
1612
                }
1613
            }
1614
            list(, $parentId) = $this->_od_splitPath($path);
1615
            $parent = $path;
1616
        }
1617
1618
        try {
1619
            //Create or Update a file
1620
            $params = ['overwrite' => 'true'];
1621
            $query = http_build_query($params);
1622
1623
            if ($itemId === '') {
1624
                $url = self::API_URL.$parentId.'/children/'.rawurlencode($name).'/content?'.$query;
1625
            } else {
1626
                $url = self::API_URL.$itemId.'/content?'.$query;
1627
            }
1628
            $curl = $this->_od_prepareCurl();
1629
            $stats = fstat($fp);
1630
1631
            $options = [
1632
                CURLOPT_URL => $url,
1633
                CURLOPT_PUT => true,
1634
                CURLOPT_INFILE => $fp,
1635
            ];
1636
            // Size
1637
            if ($stats[7]) {
1638
                $options[CURLOPT_INFILESIZE] = $stats[7];
1639
            }
1640
1641
            curl_setopt_array($curl, $options);
1642
1643
            //create or update File in the Target
1644
            $file = json_decode(curl_exec($curl));
1645
            curl_close($curl);
1646
1647
            return $this->_joinPath($parent, $file->id);
1648
        } catch (Exception $e) {
1649
            return $this->setError('OneDrive error: '.$e->getMessage());
1650
        }
1651
    }
1652
1653
    /**
1654
     * Get file contents.
1655
     *
1656
     * @param string $path file path
1657
     *
1658
     * @return string|false
1659
     *
1660
     * @author Dmitry (dio) Levashov
1661
     **/
1662 View Code Duplication
    protected function _getContents($path)
0 ignored issues
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...
1663
    {
1664
        $contents = '';
1665
1666
        try {
1667
            list(, $itemId) = $this->_od_splitPath($path);
1668
            $url = self::API_URL.$itemId.'/content';
1669
            $contents = $this->_od_createCurl($url, $contents = true);
1670
        } catch (Exception $e) {
1671
            return $this->setError('OneDrive error: '.$e->getMessage());
1672
        }
1673
1674
        return $contents;
1675
    }
1676
1677
    /**
1678
     * Write a string to a file.
1679
     *
1680
     * @param string $path    file path
1681
     * @param string $content new file content
1682
     *
1683
     * @return bool
1684
     *
1685
     * @author Dmitry (dio) Levashov
1686
     **/
1687 View Code Duplication
    protected function _filePutContents($path, $content)
0 ignored issues
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...
1688
    {
1689
        $res = false;
1690
1691
        if ($local = $this->getTempFile($path)) {
1692
            if (file_put_contents($local, $content, LOCK_EX) !== false
1693
            && ($fp = fopen($local, 'rb'))) {
1694
                clearstatcache();
1695
                $res = $this->_save($fp, $path, '', []);
1696
                fclose($fp);
1697
            }
1698
            file_exists($local) && unlink($local);
1699
        }
1700
1701
        return $res;
1702
    }
1703
1704
    /**
1705
     * Detect available archivers.
1706
     **/
1707
    protected function _checkArchivers()
1708
    {
1709
        // die('Not yet implemented. (_checkArchivers)');
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1710
        return [];
1711
    }
1712
1713
    /**
1714
     * chmod implementation.
1715
     *
1716
     * @return bool
1717
     **/
1718
    protected function _chmod($path, $mode)
1719
    {
1720
        return false;
1721
    }
1722
1723
    /**
1724
     * Unpack archive.
1725
     *
1726
     * @param string $path archive path
1727
     * @param array  $arc  archiver command and arguments (same as in $this->archivers)
1728
     *
1729
     * @return true
1730
     *
1731
     * @author Dmitry (dio) Levashov
1732
     * @author Alexey Sukhotin
1733
     **/
1734
    protected function _unpack($path, $arc)
0 ignored issues
show
Unused Code introduced by
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $arc is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1735
    {
1736
        die('Not yet implemented. (_unpack)');
0 ignored issues
show
Coding Style Compatibility introduced by
The method _unpack() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1737
        //return false;
1738
    }
1739
1740
    /**
1741
     * Recursive symlinks search.
1742
     *
1743
     * @param string $path file/dir path
1744
     *
1745
     * @return bool
1746
     *
1747
     * @author Dmitry (dio) Levashov
1748
     **/
1749
    protected function _findSymlinks($path)
0 ignored issues
show
Unused Code introduced by
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1750
    {
1751
        die('Not yet implemented. (_findSymlinks)');
0 ignored issues
show
Coding Style Compatibility introduced by
The method _findSymlinks() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1752
    }
1753
1754
    /**
1755
     * Extract files from archive.
1756
     *
1757
     * @param string $path archive path
1758
     * @param array  $arc  archiver command and arguments (same as in $this->archivers)
1759
     *
1760
     * @return true
1761
     *
1762
     * @author Dmitry (dio) Levashov,
1763
     * @author Alexey Sukhotin
1764
     **/
1765
    protected function _extract($path, $arc)
1766
    {
1767
        die('Not yet implemented. (_extract)');
0 ignored issues
show
Coding Style Compatibility introduced by
The method _extract() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1768
    }
1769
1770
    /**
1771
     * Create archive and return its path.
1772
     *
1773
     * @param string $dir   target dir
1774
     * @param array  $files files names list
1775
     * @param string $name  archive name
1776
     * @param array  $arc   archiver options
1777
     *
1778
     * @return string|bool
1779
     *
1780
     * @author Dmitry (dio) Levashov,
1781
     * @author Alexey Sukhotin
1782
     **/
1783
    protected function _archive($dir, $files, $name, $arc)
1784
    {
1785
        die('Not yet implemented. (_archive)');
0 ignored issues
show
Coding Style Compatibility introduced by
The method _archive() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1786
    }
1787
} // END class
1788