Completed
Push — master ( 61c24d...075a0d )
by recca
07:28
created

elFinderVolumeDropbox2   D

Complexity

Total Complexity 222

Size/Duplication

Total Lines 1468
Duplicated Lines 13.9 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 204
loc 1468
rs 4.4102
c 0
b 0
f 0
wmc 222
lcom 1
cbo 3

50 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 21 21 1
A getTokenFromOauth1() 0 23 3
F netmountPrepare() 22 162 32
A netunmount() 0 10 3
A umount() 0 3 1
D getContentUrl() 7 44 16
A debug() 0 10 3
A _db_splitPath() 0 19 3
D _db_parseRaw() 0 51 11
A _db_getThumbnail() 0 8 2
A _db_joinName() 0 4 1
F init() 6 76 24
A configure() 16 16 4
D cacheDir() 0 29 9
D doSearch() 0 33 9
A copy() 0 20 4
D remove() 29 29 9
C createTmb() 56 56 19
A tmbname() 0 9 3
A _dirname() 0 6 1
A _basename() 0 6 1
A _joinPath() 0 4 1
A _normpath() 0 4 1
A _relpath() 0 8 2
A _abspath() 0 8 2
A _path() 0 6 1
A _inpath() 0 4 2
A _stat() 0 8 2
B _subdirs() 0 21 5
A _dimensions() 0 18 4
A _scandir() 0 6 2
B _fopen() 0 18 5
A _fclose() 0 4 1
A _mkdir() 8 8 2
A _mkfile() 0 4 1
A _symlink() 0 4 1
A _copy() 10 10 2
A _move() 8 8 2
A _unlink() 0 12 2
A _rmdir() 0 4 1
B _save() 5 28 6
A _getContents() 0 13 2
B _filePutContents() 16 16 5
A _checkArchivers() 0 5 1
A _chmod() 0 4 1
A _unpack() 0 5 1
A _findSymlinks() 0 4 1
A _extract() 0 4 1
A _archive() 0 4 1
B _db_getFile() 0 18 5

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

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

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

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

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 18 and the first side effect is on line 10.

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
use \Kunnu\Dropbox\Dropbox;
4
use \Kunnu\Dropbox\DropboxApp;
5
use \Kunnu\Dropbox\DropboxFile;
6
use \Kunnu\Dropbox\Models\FileMetadata;
7
use \Kunnu\Dropbox\Models\FolderMetadata;
8
use \Kunnu\Dropbox\Exceptions\DropboxClientException;
9
10
elFinder::$netDrivers['dropbox2'] = 'Dropbox2';
11
12
/**
13
 * Simple elFinder driver for Dropbox
14
 * kunalvarma05/dropbox-php-sdk:0.1.5 or above.
15
 *
16
 * @author Naoki Sawada
17
 **/
18
class elFinderVolumeDropbox2 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...
19
{
20
    /**
21
     * Net mount key.
22
     *
23
     * @var string
24
     **/
25
    public $netMountKey = '';
26
    /**
27
     * Driver id
28
     * Must be started from letter and contains [a-z0-9]
29
     * Used as part of volume id.
30
     *
31
     * @var string
32
     **/
33
    protected $driverId = 'db';
34
35
    /**
36
     * Dropbox service object.
37
     *
38
     * @var object
39
     **/
40
    protected $service = null;
41
42
    /**
43
     * Directory for tmp files
44
     * If not set driver will try to use tmbDir as tmpDir.
45
     *
46
     * @var string
47
     **/
48
    protected $tmp = '';
49
50
    /**
51
     * Fetch options.
52
     *
53
     * @var string
54
     */
55
    private $FETCH_OPTIONS = [];
56
57
    /**
58
     * Constructor
59
     * Extend options with required fields.
60
     *
61
     * @author Naoki Sawada
62
     **/
63 View Code Duplication
    public function __construct()
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...
64
    {
65
        $opts = [
66
            'app_key' => '',
67
            'app_secret' => '',
68
            'access_token' => '',
69
            'aliasFormat' => '%s@Dropbox',
70
            'path' => '/',
71
            'separator' => '/',
72
            'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#',
73
            'rootCssClass' => 'elfinder-navbar-root-dropbox',
74
            'publishPermission' => [
75
                'requested_visibility' => 'public',
76
                //'link_password' => '',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
77
                //'expires' => '',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
78
            ],
79
            'getThumbSize' => 'medium', // Available sizes: 'thumb', 'small', 'medium', 'large', 'huge'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
80
        ];
81
        $this->options = array_merge($this->options, $opts);
82
        $this->options['mimeDetect'] = 'internal';
83
    }
84
85
    /**
86
     * Get OAuth2 access token form OAuth1 tokens.
87
     *
88
     * @param string $app_key
89
     * @param string $app_secret
90
     * @param string $oauth1_token
91
     * @param string $oauth1_secret
92
     *
93
     * @return string|false
94
     */
95
    public static function getTokenFromOauth1($app_key, $app_secret, $oauth1_token, $oauth1_secret)
96
    {
97
        $data = [
98
                'oauth1_token' => $oauth1_token,
99
                'oauth1_token_secret' => $oauth1_secret,
100
        ];
101
        $auth = base64_encode($app_key.':'.$app_secret);
102
103
        $ch = curl_init('https://api.dropboxapi.com/2/auth/token/from_oauth1');
104
        curl_setopt($ch, CURLOPT_POST, true);
105
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
106
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
107
            'Content-Type: application/json',
108
            'Authorization: Basic '.$auth,
109
        ]);
110
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
111
        $result = curl_exec($ch);
112
        curl_close($ch);
113
114
        $res = $result ? json_decode($result, true) : [];
115
116
        return isset($res['oauth2_token']) ? $res['oauth2_token'] : false;
117
    }
118
119
    /*********************************************************************/
120
    /*                        EXTENDED FUNCTIONS                         */
121
    /*********************************************************************/
122
123
    /**
124
     * Prepare
125
     * Call from elFinder::netmout() before volume->mount().
126
     *
127
     * @return array
128
     *
129
     * @author Naoki Sawada
130
     **/
131
    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...
132
    {
133
        if (empty($options['app_key']) && defined('ELFINDER_DROPBOX_APPKEY')) {
134
            $options['app_key'] = ELFINDER_DROPBOX_APPKEY;
135
        }
136
        if (empty($options['app_secret']) && defined('ELFINDER_DROPBOX_APPSECRET')) {
137
            $options['app_secret'] = ELFINDER_DROPBOX_APPSECRET;
138
        }
139
140
        if (! isset($options['pass'])) {
141
            $options['pass'] = '';
142
        }
143
144
        try {
145
            $this->session->start();
146
            $app = new DropboxApp($options['app_key'], $options['app_secret']);
147
            $dropbox = new Dropbox($app);
148
            $authHelper = $dropbox->getAuthHelper();
149
150
            if ($options['pass'] === 'reauth') {
151
                $options['pass'] = '';
152
                $this->session->set('Dropbox2AuthParams', [])->set('Dropbox2Tokens', []);
153
            } elseif ($options['pass'] === 'dropbox2') {
154
                $options['pass'] = '';
155
            }
156
157
            $options = array_merge($this->session->get('Dropbox2AuthParams', []), $options);
158
159
            if (! isset($options['tokens'])) {
160
                $options['tokens'] = $this->session->get('Dropbox2Tokens', []);
161
                $this->session->remove('Dropbox2Tokens');
162
            }
163
            $aToken = $options['tokens'];
164
            if (! is_array($aToken) || ! isset($aToken['access_token'])) {
165
                $aToken = [];
166
            }
167
168
            $rootObj = $service = null;
0 ignored issues
show
Unused Code introduced by
$service 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...
Unused Code introduced by
$rootObj 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...
169
            if ($aToken) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $aToken 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...
170
                try {
171
                    $dropbox->setAccessToken($aToken['access_token']);
172
                    $this->session->set('Dropbox2AuthParams', $options);
173
                } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
174
                    $aToken = [];
175
                    $options['tokens'] = [];
176
                    if ($options['user'] !== 'init') {
177
                        $this->session->set('Dropbox2AuthParams', $options);
178
179
                        return ['exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE];
180
                    }
181
                }
182
            }
183
184
            if ($options['user'] === 'init') {
185
                if (empty($options['url'])) {
186
                    $options['url'] = elFinder::getConnectorUrl();
187
                }
188
189
                $callback = $options['url']
190
                           .'?cmd=netmount&protocol=dropbox2&host=1';
191
192
                if (! $aToken && empty($_GET['code'])) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $aToken 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...
193
                    $url = $authHelper->getAuthUrl($callback);
194
195
                    $html = '<input id="elf-volumedriver-dropbox2-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.'\')">';
196
                    $html .= '<script>
197
                        $("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox2", mode: "makebtn"});
198
                    </script>';
199 View Code Duplication
                    if (empty($options['pass']) && $options['host'] !== '1') {
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...
200
                        $options['pass'] = 'return';
201
                        $this->session->set('Dropbox2AuthParams', $options);
202
203
                        return ['exit' => true, 'body' => $html];
204
                    } else {
205
                        $out = [
206
                            'node' => $options['id'],
207
                            'json' => '{"protocol": "dropbox2", "mode": "makebtn", "body" : "'.str_replace($html, '"', '\\"').'", "error" : "'.elFinder::ERROR_ACCESS_DENIED.'"}',
208
                            'bind' => 'netmount',
209
                        ];
210
211
                        return ['exit' => 'callback', 'out' => $out];
212
                    }
213
                } else {
214
                    if (! empty($_GET['code']) && isset($_GET['state'])) {
215
                        $tokenObj = $authHelper->getAccessToken($_GET['code'], $_GET['state'], $callback);
216
                        $options['tokens'] = [
217
                            'access_token' => $tokenObj->getToken(),
218
                            'uid' => $tokenObj->getUid(),
219
                        ];
220
                        $this->session->set('Dropbox2Tokens', $options['tokens'])->set('Dropbox2AuthParams', $options);
221
                        $out = [
222
                            'node' => $options['id'],
223
                            'json' => '{"protocol": "dropbox2", "mode": "done", "reset": 1}',
224
                            'bind' => 'netmount',
225
                        ];
226
227
                        return ['exit' => 'callback', 'out' => $out];
228
                    }
229
                    $path = $options['path'];
230
                    $folders = [];
231
                    $listFolderContents = $dropbox->listFolder($path);
232
                    $items = $listFolderContents->getItems();
233
                    foreach ($items as $item) {
234
                        $data = $item->getData();
235
                        if ($data['.tag'] === 'folder') {
236
                            $folders[$data['path_lower']] = $data['name'];
237
                        }
238
                    }
239
                    natcasesort($folders);
240
241
                    if ($options['pass'] === 'folders') {
242
                        return ['exit' => true, 'folders' => $folders];
243
                    }
244
245
                    $folders = ['/' => '/'] + $folders;
246
                    $folders = json_encode($folders);
247
                    $json = '{"protocol": "dropbox2", "mode": "done", "folders": '.$folders.'}';
248
                    $options['pass'] = 'return';
249
                    $html = 'Dropbox.com';
250
                    $html .= '<script>
251
                        $("#'.$options['id'].'").elfinder("instance").trigger("netmount", '.$json.');
252
                    </script>';
253
                    $this->session->set('Dropbox2AuthParams', $options);
254
255
                    return ['exit' => true, 'body' => $html];
256
                }
257
            }
258
        } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
259
            $this->session->remove('Dropbox2AuthParams')->remove('Dropbox2Tokens');
260 View Code Duplication
            if (empty($options['pass'])) {
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...
261
                return ['exit' => true, 'body' => '{msg:'.elFinder::ERROR_ACCESS_DENIED.'}'.' '.$e->getMessage()];
262
            } else {
263
                return ['exit' => true, 'error' => [elFinder::ERROR_ACCESS_DENIED, $e->getMessage()]];
264
            }
265
        }
266
267
        if (! $aToken) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $aToken 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...
268
            return ['exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE];
269
        }
270
271
        if ($options['path'] === 'root') {
272
            $options['path'] = '/';
273
        }
274
275
        try {
276
            if ($options['path'] !== '/') {
277
                $file = $dropbox->getMetadata($options['path']);
278
                $name = $file->getName();
279
            } else {
280
                $name = 'root';
281
            }
282
            $options['alias'] = sprintf($this->options['aliasFormat'], $name);
283
        } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
284
            return ['exit' => true, 'error' => $e->getMessage()];
285
        }
286
287 View Code Duplication
        foreach (['host', 'user', 'pass', 'id', 'offline'] as $key) {
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...
288
            unset($options[$key]);
289
        }
290
291
        return $options;
292
    }
293
294
    /**
295
     * process of on netunmount
296
     * Drop `Dropbox` & rm thumbs.
297
     *
298
     * @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...
299
     *
300
     * @return bool
301
     */
302
    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...
303
    {
304
        if ($tmbs = glob(rtrim($this->options['tmbPath'], '\\/').DIRECTORY_SEPARATOR.$this->driverId.'_'.$this->options['tokens']['uid'].'*.png')) {
305
            foreach ($tmbs as $file) {
306
                unlink($file);
307
            }
308
        }
309
310
        return true;
311
    }
312
313
    /*********************************************************************/
314
    /*                               FS API                              */
315
    /*********************************************************************/
316
317
    /**
318
     * Close opened connection.
319
     **/
320
    public function umount()
321
    {
322
    }
323
324
    /**
325
     * Return content URL (for netmout volume driver)
326
     * If file.url == 1 requests from JavaScript client with XHR.
327
     *
328
     * @param string $hash    file hash
329
     * @param array  $options options array
330
     *
331
     * @return bool|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
        $file = $this->file($hash);
345
        if (($file = $this->file($hash)) !== false && (! $file['url'] || $file['url'] == 1)) {
346
            $path = $this->decode($hash);
347
            $url = '';
348
            try {
349
                $res = $this->service->postToAPI('/sharing/list_shared_links', ['path' => $path, 'direct_only' => true])->getDecodedBody();
350
                if ($res && ! empty($res['links'])) {
351
                    foreach ($res['links'] as $link) {
352
                        if (isset($link['link_permissions'])
353
                                && isset($link['link_permissions']['requested_visibility'])
354
                                && $link['link_permissions']['requested_visibility']['.tag'] === $this->options['publishPermission']['requested_visibility']) {
355
                            $url = $link['url'];
356
                            break;
357
                        }
358
                    }
359
                }
360
                if (! $url) {
361
                    $res = $this->service->postToAPI('/sharing/create_shared_link_with_settings', ['path' => $path, 'settings' => $this->options['publishPermission']])->getDecodedBody();
362
                    if (isset($res['url'])) {
363
                        $url = $res['url'];
364
                    }
365
                }
366
                if ($url) {
367
                    $url = str_replace('www.dropbox.com', 'dl.dropboxusercontent.com', $url);
368
                    $url = str_replace('?dl=0', '', $url);
369
370
                    return $url;
371
                }
372
            } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
373
                return $this->$this->setError('Dropbox error: '.$e->getMessage());
374
            }
375
        }
376
377
        return false;
378
    }
379
380
    /**
381
     * Return debug info for client.
382
     *
383
     * @return array
384
     **/
385
    public function debug()
386
    {
387
        $res = parent::debug();
388
        if (isset($this->options['tokens']) && ! empty($this->options['tokens']['uid'])) {
389
            $res['Dropbox uid'] = $this->options['tokens']['uid'];
390
            $res['access_token'] = $this->options['tokens']['access_token'];
391
        }
392
393
        return $res;
394
    }
395
396
    /*********************************************************************/
397
    /*                        ORIGINAL FUNCTIONS                         */
398
    /*********************************************************************/
399
400
    /**
401
     * Get Parent ID, Item ID, Parent Path as an array from path.
402
     *
403
     * @param string $path
404
     *
405
     * @return array
406
     */
407
    protected function _db_splitPath($path)
408
    {
409
        $path = trim($path, '/');
410
        if ($path === '') {
411
            $dirname = '/';
412
            $basename = '';
413
        } else {
414
            $pos = strrpos($path, '/');
415
            if ($pos === false) {
416
                $dirname = '/';
417
                $basename = $path;
418
            } else {
419
                $dirname = '/'.substr($path, 0, $pos);
420
                $basename = substr($path, $pos + 1);
421
            }
422
        }
423
424
        return [$dirname, $basename];
425
    }
426
427
    /**
428
     * Parse line from Dropbox metadata output and return file stat (array).
429
     *
430
     * @param string $raw line from ftp_rawlist() output
431
     *
432
     * @return array
433
     *
434
     * @author Naoki Sawada
435
     **/
436
    protected function _db_parseRaw($raw)
437
    {
438
        $stat = [];
439
        $isFolder = false;
440
        if ($raw === true) {
441
            // root folder
442
            $isFolder = true;
443
            $stat['name'] = '';
444
            $stat['iid'] = '0';
445
        }
446
447
        $data = [];
448
        if (is_object($raw)) {
449
            $isFolder = $raw instanceof FolderMetadata;
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Models\FolderMetadata does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
450
            $data = $raw->getData();
451
        } elseif (is_array($raw)) {
452
            $isFolder = $raw['.tag'] === 'folder';
453
            $data = $raw;
454
        }
455
456
        if (isset($data['path_lower'])) {
457
            $stat['path'] = $data['path_lower'];
458
        }
459
460
        if (isset($data['name'])) {
461
            $stat['name'] = $data['name'];
462
        }
463
464
        if (isset($data['id'])) {
465
            $stat['iid'] = substr($data['id'], 3);
466
        }
467
468
        if ($isFolder) {
469
            $stat['mime'] = 'directory';
470
            $stat['size'] = 0;
471
            $stat['ts'] = 0;
472
            $stat['dirs'] = -1;
473
        } else {
474
            $stat['size'] = isset($data['size']) ? (int) $data['size'] : 0;
475
            if (isset($data['server_modified'])) {
476
                $stat['ts'] = strtotime($data['server_modified']);
477
            } elseif (isset($data['client_modified'])) {
478
                $stat['ts'] = strtotime($data['client_modified']);
479
            } else {
480
                $stat['ts'] = 0;
481
            }
482
            $stat['url'] = '1';
483
        }
484
485
        return $stat;
486
    }
487
488
    /**
489
     * Get thumbnail from Dropbox.
490
     *
491
     * @param string $path
492
     * @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...
493
     *
494
     * @return string | boolean
495
     */
496
    protected function _db_getThumbnail($path)
497
    {
498
        try {
499
            return $this->service->getThumbnail($path, $this->options['getThumbSize'])->getContents();
500
        } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
501
            return false;
502
        }
503
    }
504
505
    /**
506
     * Join dir name and file name(display name) and retur full path.
507
     *
508
     * @param unknown $dir
509
     * @param unknown $displayName
510
     *
511
     * @return string
512
     */
513
    protected function _db_joinName($dir, $displayName)
514
    {
515
        return rtrim($dir, '/').'/'.$displayName;
516
    }
517
518
    /*********************************************************************/
519
    /*                        INIT AND CONFIGURE                         */
520
    /*********************************************************************/
521
522
    /**
523
     * Prepare FTP connection
524
     * Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn.
525
     *
526
     * @return bool
527
     *
528
     * @author Naoki Sawada
529
     **/
530
    protected function init()
531
    {
532
        if (empty($options['app_key'])) {
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...
533
            if (defined('ELFINDER_DROPBOX_APPKEY') && ELFINDER_DROPBOX_APPKEY) {
534
                $this->options['app_key'] = ELFINDER_DROPBOX_APPKEY;
535
            } else {
536
                return $this->setError('Required option "app_key" is undefined.');
537
            }
538
        }
539
        if (empty($options['app_secret'])) {
540
            if (defined('ELFINDER_DROPBOX_APPSECRET') && ELFINDER_DROPBOX_APPSECRET) {
541
                $this->options['app_secret'] = ELFINDER_DROPBOX_APPSECRET;
542
            } else {
543
                return $this->setError('Required option "app_secret" is undefined.');
544
            }
545
        }
546 View Code Duplication
        if (isset($this->options['tokens']) && is_array($this->options['tokens']) && ! empty($this->options['tokens']['access_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...
547
            $this->options['access_token'] = $this->options['tokens']['access_token'];
548
        }
549
        if (! $this->options['access_token']) {
550
            return $this->setError('Required option "access_token" or "refresh_token" is undefined.');
551
        }
552
553
        try {
554
            // make net mount key for network mount
555
            $aToken = $this->options['access_token'];
556
            $this->netMountKey = md5($aToken.'-'.$this->options['path']);
557
558
            $errors = [];
559
            if (! $this->service) {
560
                $app = new DropboxApp($this->options['app_key'], $this->options['app_secret'], $aToken);
561
                $this->service = new Dropbox($app);
562
            }
563
        } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
564
            $errors[] = 'Dropbox error: '.$e->getMessage();
0 ignored issues
show
Bug introduced by
The variable $errors does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
565
        } catch (Exception $e) {
566
            $errors[] = $e->getMessage();
567
        }
568
569
        if (! $this->service) {
570
            $errors[] = 'Dropbox Service could not be loaded.';
571
572
            return $this->setError($errors);
573
        }
574
575
        // normalize root path
576
        $this->options['path'] = strtolower($this->options['path']);
577
        if ($this->options['path'] == 'root') {
578
            $this->options['path'] = '/';
579
        }
580
        $this->root = $this->options['path'] = $this->_normpath($this->options['path']);
581
582 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...
583
            $this->options['alias'] = sprintf($this->options['aliasFormat'], ($this->options['path'] === '/') ? 'root' : $this->_basename($this->options['path']));
584
        }
585
586
        $this->rootName = $this->options['alias'];
587
588
        if (! empty($this->options['tmpPath'])) {
589
            if ((is_dir($this->options['tmpPath']) || mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) {
590
                $this->tmp = $this->options['tmpPath'];
591
            }
592
        }
593
594
        if (! $this->tmp && ($tmp = elFinder::getStaticVar('commonTempPath'))) {
595
            $this->tmp = $tmp;
596
        }
597
598
        // This driver dose not support `syncChkAsTs`
599
        $this->options['syncChkAsTs'] = false;
600
601
        // 'lsPlSleep' minmum 10 sec
602
        $this->options['lsPlSleep'] = max(10, $this->options['lsPlSleep']);
603
604
        return true;
605
    }
606
607
    /**
608
     * Configure after successfull mount.
609
     *
610
     * @author Naoki Sawada
611
     **/
612 View Code Duplication
    protected function configure()
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...
613
    {
614
        parent::configure();
615
616
        // fallback of $this->tmp
617
        if (! $this->tmp && $this->tmbPathWritable) {
618
            $this->tmp = $this->tmbPath;
619
        }
620
621
        $this->disabled[] = 'archive';
622
        $this->disabled[] = 'extract';
623
624
        if ($this->isMyReload()) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
625
            //$this->_db_getDirectoryData(false);
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% 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...
626
        }
627
    }
628
629
    /**
630
     * Cache dir contents.
631
     *
632
     * @param string $path dir path
633
     *
634
     * @author Naoki Sawada
635
     **/
636
    protected function cacheDir($path)
637
    {
638
        $this->dirsCache[$path] = [];
639
        $hasDir = false;
640
641
        $res = $this->service->listFolder($path, $this->FETCH_OPTIONS);
642
643
        if ($res) {
644
            $items = $res->getItems()->all();
645
            foreach ($items as $raw) {
646
                if ($stat = $this->_db_parseRaw($raw)) {
647
                    $mountPath = $this->_joinPath($path, $stat['name']);
648
                    $stat = $this->updateCache($mountPath, $stat);
649
                    if (empty($stat['hidden']) && $path !== $mountPath) {
650
                        if (! $hasDir && $stat['mime'] === 'directory') {
651
                            $hasDir = true;
652
                        }
653
                        $this->dirsCache[$path][] = $mountPath;
654
                    }
655
                }
656
            }
657
        }
658
659
        if (isset($this->sessionCache['subdirs'])) {
660
            $this->sessionCache['subdirs'][$path] = $hasDir;
661
        }
662
663
        return $this->dirsCache[$path];
664
    }
665
666
    /**
667
     * Recursive files search.
668
     *
669
     * @param string $path  dir path
670
     * @param string $q     search string
671
     * @param array  $mimes
672
     *
673
     * @return array
674
     *
675
     * @author Naoki Sawada
676
     **/
677
    protected function doSearch($path, $q, $mimes)
678
    {
679
        if ($mimes) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $mimes 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...
680
            return parent::doSearch($path, $q, $mimes);
681
        }
682
683
        $timeout = $this->options['searchTimeout'] ? $this->searchStart + $this->options['searchTimeout'] : 0;
684
685
        $searchRes = $this->service->search($path, $q, ['start' => 0, 'max_results' => 1000]);
686
        $items = $searchRes->getItems();
687
        $more = $searchRes->hasMoreItems();
688
        while ($more) {
689
            if ($timeout && $timeout < time()) {
690
                $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->_path($path));
691
                break;
692
            }
693
            $searchRes = $this->service->search($path, $q, ['start' => $searchRes->getCursor(), 'max_results' => 1000]);
694
            $more = $searchRes->hasMoreItems();
695
            $items = $items->merge($searchRes->getItems());
696
        }
697
698
        $result = [];
699
        foreach ($items as $raw) {
700
            if ($stat = $this->_db_parseRaw($raw->getMetadata())) {
701
                $stat = $this->updateCache($stat['path'], $stat);
702
                if (empty($stat['hidden'])) {
703
                    $result[] = $stat;
704
                }
705
            }
706
        }
707
708
        return $result;
709
    }
710
711
    /**
712
     * Copy file/recursive copy dir only in current volume.
713
     * Return new file path or false.
714
     *
715
     * @param string $src  source path
716
     * @param string $dst  destination dir path
717
     * @param string $name new file name (optionaly)
718
     *
719
     * @return string|false
720
     *
721
     * @author Naoki Sawada
722
     **/
723
    protected function copy($src, $dst, $name)
724
    {
725
        $srcStat = $this->stat($src);
726
        $target = $this->_joinPath($dst, $name);
727
        $tgtStat = $this->stat($target);
728
        if ($tgtStat) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $tgtStat 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...
729
            if ($srcStat['mime'] === 'directory') {
730
                return parent::copy($src, $dst, $name);
731
            } else {
732
                $this->_unlink($target);
733
            }
734
        }
735
        $this->clearcache();
736
        if ($res = $this->_copy($src, $dst, $name)) {
737
            $this->added[] = $this->stat($target);
738
            $res = $target;
739
        }
740
741
        return $res;
742
    }
743
744
    /**
745
     * Remove file/ recursive remove dir.
746
     *
747
     * @param string $path  file path
748
     * @param bool   $force try to remove even if file locked
749
     *
750
     * @return bool
751
     *
752
     * @author Naoki Sawada
753
     **/
754 View Code Duplication
    protected function remove($path, $force = false, $recursive = 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...
755
    {
756
        $stat = $this->stat($path);
757
        $stat['realpath'] = $path;
758
        $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...
759
        $this->clearcache();
760
761
        if (empty($stat)) {
762
            return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND);
763
        }
764
765
        if (! $force && ! empty($stat['locked'])) {
766
            return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path));
767
        }
768
769
        if ($stat['mime'] == 'directory') {
770
            if (! $recursive && ! $this->_rmdir($path)) {
771
                return $this->setError(elFinder::ERROR_RM, $this->_path($path));
772
            }
773
        } else {
774
            if (! $recursive && ! $this->_unlink($path)) {
775
                return $this->setError(elFinder::ERROR_RM, $this->_path($path));
776
            }
777
        }
778
779
        $this->removed[] = $stat;
780
781
        return true;
782
    }
783
784
    /**
785
     * Create thumnbnail and return it's URL on success.
786
     *
787
     * @param string $path file path
788
     * @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...
789
     *
790
     * @return string|false
791
     *
792
     * @author Naoki Sawada
793
     **/
794 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...
795
    {
796
        if (! $stat || ! $this->canCreateTmb($path, $stat)) {
797
            return false;
798
        }
799
800
        $name = $this->tmbname($stat);
801
        $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name;
802
803
        // copy image into tmbPath so some drivers does not store files on local fs
804
        if (! $data = $this->_db_getThumbnail($path)) {
805
            return false;
806
        }
807
        if (! file_put_contents($tmb, $data)) {
808
            return false;
809
        }
810
811
        $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...
812
813
        $tmbSize = $this->tmbSize;
814
815
        if (($s = getimagesize($tmb)) == false) {
816
            return false;
817
        }
818
819
        /* If image smaller or equal thumbnail size - just fitting to thumbnail square */
820
        if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) {
821
            $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png');
822
        } else {
823
            if ($this->options['tmbCrop']) {
824
825
                /* Resize and crop if image bigger than thumbnail */
826
                if (! (($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize)) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) {
827
                    $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...
828
                }
829
830
                if (($s = getimagesize($tmb)) != false) {
831
                    $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize) / 2) : 0;
832
                    $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize) / 2) : 0;
833
                    $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...
834
                }
835
            } else {
836
                $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...
837
            }
838
839
            $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png');
840
        }
841
842
        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...
843
            unlink($tmb);
844
845
            return false;
846
        }
847
848
        return $name;
849
    }
850
851
    /**
852
     * Return thumbnail file name for required file.
853
     *
854
     * @param array $stat file stat
855
     *
856
     * @return string
857
     *
858
     * @author Naoki Sawada
859
     **/
860
    protected function tmbname($stat)
861
    {
862
        $name = $this->driverId.'_';
863
        if (isset($this->options['tokens']) && is_array($this->options['tokens'])) {
864
            $name .= $this->options['tokens']['uid'];
865
        }
866
867
        return $name.md5($stat['iid']).$stat['ts'].'.png';
868
    }
869
870
    /*********************** paths/urls *************************/
871
872
    /**
873
     * Return parent directory path.
874
     *
875
     * @param string $path file path
876
     *
877
     * @return string
878
     *
879
     * @author Naoki Sawada
880
     **/
881
    protected function _dirname($path)
882
    {
883
        list($dirname) = $this->_db_splitPath($path);
884
885
        return $dirname;
886
    }
887
888
    /**
889
     * Return file name.
890
     *
891
     * @param string $path file path
892
     *
893
     * @return string
894
     *
895
     * @author Naoki Sawada
896
     **/
897
    protected function _basename($path)
898
    {
899
        list(, $basename) = $this->_db_splitPath($path);
900
901
        return $basename;
902
    }
903
904
    /**
905
     * Join dir name and file name and retur full path.
906
     *
907
     * @param string $dir
908
     * @param string $name
909
     *
910
     * @return string
911
     *
912
     * @author Dmitry (dio) Levashov
913
     **/
914
    protected function _joinPath($dir, $name)
915
    {
916
        return rtrim($dir, '/').'/'.strtolower($name);
917
    }
918
919
    /**
920
     * Return normalized path, this works the same as os.path.normpath() in Python.
921
     *
922
     * @param string $path path
923
     *
924
     * @return string
925
     *
926
     * @author Naoki Sawada
927
     **/
928
    protected function _normpath($path)
929
    {
930
        return '/'.ltrim($path, '/');
931
    }
932
933
    /**
934
     * Return file path related to root dir.
935
     *
936
     * @param string $path file path
937
     *
938
     * @return string
939
     *
940
     * @author Dmitry (dio) Levashov
941
     **/
942
    protected function _relpath($path)
943
    {
944
        if ($path === $this->root) {
945
            return '';
946
        } else {
947
            return ltrim(substr($path, strlen($this->root)), '/');
948
        }
949
    }
950
951
    /**
952
     * Convert path related to root dir into real path.
953
     *
954
     * @param string $path file path
955
     *
956
     * @return string
957
     *
958
     * @author Naoki Sawada
959
     **/
960
    protected function _abspath($path)
961
    {
962
        if ($path === '/') {
963
            return $this->root;
964
        } else {
965
            return $this->_joinPath($this->root, $path);
966
        }
967
    }
968
969
    /**
970
     * Return fake path started from root dir.
971
     *
972
     * @param string $path file path
973
     *
974
     * @return string
975
     *
976
     * @author Naoki Sawada
977
     **/
978
    protected function _path($path)
979
    {
980
        $path = $this->_normpath(substr($path, strlen($this->root)));
981
982
        return $path;
983
    }
984
985
    /**
986
     * Return true if $path is children of $parent.
987
     *
988
     * @param string $path   path to check
989
     * @param string $parent parent path
990
     *
991
     * @return bool
992
     *
993
     * @author Naoki Sawada
994
     **/
995
    protected function _inpath($path, $parent)
996
    {
997
        return $path == $parent || strpos($path, $parent.'/') === 0;
998
    }
999
1000
    /***************** file stat ********************/
1001
1002
    /**
1003
     * Return stat for given path.
1004
     * Stat contains following fields:
1005
     * - (int)    size    file size in b. required
1006
     * - (int)    ts      file modification time in unix time. required
1007
     * - (string) mime    mimetype. required for folders, others - optionally
1008
     * - (bool)   read    read permissions. required
1009
     * - (bool)   write   write permissions. required
1010
     * - (bool)   locked  is object locked. optionally
1011
     * - (bool)   hidden  is object hidden. optionally
1012
     * - (string) alias   for symlinks - link target path relative to root path. optionally
1013
     * - (string) target  for symlinks - link target path. optionally.
1014
     *
1015
     * If file does not exists - returns empty array or false.
1016
     *
1017
     * @param string $path file path
1018
     *
1019
     * @return array|false
1020
     *
1021
     * @author Dmitry (dio) Levashov
1022
     **/
1023
    protected function _stat($path)
1024
    {
1025
        if ($raw = $this->_db_getFile($path)) {
1026
            return $this->_db_parseRaw($raw);
0 ignored issues
show
Bug introduced by
It seems like $raw defined by $this->_db_getFile($path) on line 1025 can also be of type boolean; however, elFinderVolumeDropbox2::_db_parseRaw() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1027
        }
1028
1029
        return false;
1030
    }
1031
1032
    /**
1033
     * Return true if path is dir and has at least one childs directory.
1034
     *
1035
     * @param string $path dir path
1036
     *
1037
     * @return bool
1038
     *
1039
     * @author Naoki Sawada
1040
     **/
1041
    protected function _subdirs($path)
1042
    {
1043
        $hasdir = false;
1044
1045
        try {
1046
            $res = $this->service->listFolder($path);
1047
            if ($res) {
1048
                $items = $res->getItems();
1049
                foreach ($items as $raw) {
1050
                    if ($raw instanceof FolderMetadata) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Models\FolderMetadata does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
1051
                        $hasdir = true;
1052
                        break;
1053
                    }
1054
                }
1055
            }
1056
        } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1057
            $this->setError('Dropbox error: '.$e->getMessage());
1058
        }
1059
1060
        return $hasdir;
1061
    }
1062
1063
    /**
1064
     * Return object width and height
1065
     * Ususaly used for images, but can be realize for video etc...
1066
     *
1067
     * @param string $path file path
1068
     * @param string $mime file mime type
1069
     *
1070
     * @return string
1071
     *
1072
     * @author Naoki Sawada
1073
     **/
1074
    protected function _dimensions($path, $mime)
1075
    {
1076
        if (strpos($mime, 'image') !== 0) {
1077
            return '';
1078
        }
1079
        $ret = '';
1080
1081
        if ($data = $this->_getContents($path)) {
1082
            $tmp = $this->getTempFile();
1083
            file_put_contents($tmp, $data);
1084
            $size = getimagesize($tmp);
1085
            if ($size) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $size 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...
1086
                return $size[0].'x'.$size[1];
1087
            }
1088
        }
1089
1090
        return $ret;
1091
    }
1092
1093
    /******************** file/dir content *********************/
1094
1095
    /**
1096
     * Return files list in directory.
1097
     *
1098
     * @param string $path dir path
1099
     *
1100
     * @return array
1101
     *
1102
     * @author Naoki Sawada
1103
     **/
1104
    protected function _scandir($path)
1105
    {
1106
        return isset($this->dirsCache[$path])
1107
            ? $this->dirsCache[$path]
1108
            : $this->cacheDir($path);
1109
    }
1110
1111
    /**
1112
     * Open file and return file pointer.
1113
     *
1114
     * @param string $path  file path
1115
     * @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...
1116
     *
1117
     * @return resource|false
1118
     *
1119
     * @author Naoki Sawada
1120
     **/
1121
    protected function _fopen($path, $mode = 'rb')
1122
    {
1123
        if ($mode === 'rb' || $mode === 'r') {
1124
            if ($link = $this->service->getTemporaryLink($path)) {
1125
                $access_token = $this->service->getAccessToken();
1126
                if ($access_token) {
1127
                    $data = [
1128
                                'target' => $link->getLink(),
1129
                                'headers' => ['Authorization: Bearer '.$access_token],
1130
                        ];
1131
1132
                    return elFinder::getStreamByUrl($data);
1133
                }
1134
            }
1135
        }
1136
1137
        return false;
1138
    }
1139
1140
    /**
1141
     * Close opened file.
1142
     *
1143
     * @param resource $fp file pointer
1144
     *
1145
     * @return bool
1146
     *
1147
     * @author Naoki Sawada
1148
     **/
1149
    protected function _fclose($fp, $path = '')
1150
    {
1151
        fclose($fp);
1152
    }
1153
1154
    /********************  file/dir manipulations *************************/
1155
1156
    /**
1157
     * Create dir and return created dir path or false on failed.
1158
     *
1159
     * @param string $path parent dir path
1160
     * @param string $name new directory name
1161
     *
1162
     * @return string|bool
1163
     *
1164
     * @author Naoki Sawada
1165
     **/
1166 View Code Duplication
    protected function _mkdir($path, $name)
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...
1167
    {
1168
        try {
1169
            return $this->service->createFolder($this->_db_joinName($path, $name))->getPathLower();
0 ignored issues
show
Documentation introduced by
$path is of type string, but the function expects a object<unknown>.

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
$name is of type string, but the function expects a object<unknown>.

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...
1170
        } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1171
            return $this->setError('Dropbox error: '.$e->getMessage());
1172
        }
1173
    }
1174
1175
    /**
1176
     * Create file and return it's path or false on failed.
1177
     *
1178
     * @param string $path parent dir path
1179
     * @param string $name new file name
1180
     *
1181
     * @return string|bool
1182
     *
1183
     * @author Naoki Sawada
1184
     **/
1185
    protected function _mkfile($path, $name)
1186
    {
1187
        return $this->_save(tmpfile(), $path, $name, []);
1188
    }
1189
1190
    /**
1191
     * Create symlink. FTP driver does not support symlinks.
1192
     *
1193
     * @param string $target link target
1194
     * @param string $path   symlink path
1195
     *
1196
     * @return bool
1197
     *
1198
     * @author Naoki Sawada
1199
     **/
1200
    protected function _symlink($target, $path, $name)
1201
    {
1202
        return false;
1203
    }
1204
1205
    /**
1206
     * Copy file into another file.
1207
     *
1208
     * @param string $source    source file path
1209
     * @param string $targetDir target directory path
1210
     * @param string $name      new file name
1211
     *
1212
     * @return bool
1213
     *
1214
     * @author Naoki Sawada
1215
     **/
1216 View Code Duplication
    protected function _copy($source, $targetDir, $name)
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...
1217
    {
1218
        try {
1219
            $this->service->copy($source, $this->_db_joinName($targetDir, $name))->getPathLower();
0 ignored issues
show
Documentation introduced by
$targetDir is of type string, but the function expects a object<unknown>.

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
$name is of type string, but the function expects a object<unknown>.

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...
1220
        } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1221
            return $this->setError('Dropbox error: '.$e->getMessage());
1222
        }
1223
1224
        return true;
1225
    }
1226
1227
    /**
1228
     * Move file into another parent dir.
1229
     * Return new file path or false.
1230
     *
1231
     * @param string $source source file path
1232
     * @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...
1233
     * @param string $name   file name
1234
     *
1235
     * @return string|bool
1236
     *
1237
     * @author Naoki Sawada
1238
     **/
1239 View Code Duplication
    protected function _move($source, $targetDir, $name)
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...
1240
    {
1241
        try {
1242
            return $this->service->move($source, $this->_db_joinName($targetDir, $name))->getPathLower();
0 ignored issues
show
Documentation introduced by
$name is of type string, but the function expects a object<unknown>.

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...
1243
        } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1244
            return $this->setError('Dropbox error: '.$e->getMessage());
1245
        }
1246
    }
1247
1248
    /**
1249
     * Remove file.
1250
     *
1251
     * @param string $path file path
1252
     *
1253
     * @return bool
1254
     *
1255
     * @author Naoki Sawada
1256
     **/
1257
    protected function _unlink($path)
1258
    {
1259
        try {
1260
            $this->service->delete($path);
1261
1262
            return true;
1263
        } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1264
            return $this->setError('Dropbox error: '.$e->getMessage());
1265
        }
1266
1267
        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...
1268
    }
1269
1270
    /**
1271
     * Remove dir.
1272
     *
1273
     * @param string $path dir path
1274
     *
1275
     * @return bool
1276
     *
1277
     * @author Naoki Sawada
1278
     **/
1279
    protected function _rmdir($path)
1280
    {
1281
        return $this->_unlink($path);
1282
    }
1283
1284
    /**
1285
     * Create new file and write into it from file pointer.
1286
     * Return new file path or false on error.
1287
     *
1288
     * @param resource $fp   file pointer
1289
     * @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...
1290
     * @param string   $name file name
1291
     * @param array    $stat file stat (required by some virtual fs)
1292
     *
1293
     * @return bool|string
1294
     *
1295
     * @author Naoki Sawada
1296
     **/
1297
    protected function _save($fp, $path, $name, $stat)
1298
    {
1299
        try {
1300
            $info = stream_get_meta_data($fp);
1301
            if (empty($info['uri']) || preg_match('#^[a-z0-9.-]+://#', $info['uri'])) {
1302 View Code Duplication
                if ($filepath = $this->getTempFile()) {
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...
1303
                    $_fp = fopen($filepath, 'wb');
1304
                    stream_copy_to_stream($fp, $_fp);
1305
                    fclose($_fp);
1306
                }
1307
            } else {
1308
                $filepath = $info['uri'];
1309
            }
1310
            $dropboxFile = new DropboxFile($filepath);
1311
            if ($name === '') {
1312
                $dir = $this->_dirname($path);
0 ignored issues
show
Unused Code introduced by
$dir 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...
1313
                $name = $this->_basename($path);
0 ignored issues
show
Unused Code introduced by
$name 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...
1314
                $fullpath = $path;
1315
            } else {
1316
                $dir = $path;
0 ignored issues
show
Unused Code introduced by
$dir 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...
1317
                $fullpath = $this->_db_joinName($path, $name);
0 ignored issues
show
Documentation introduced by
$path is of type string, but the function expects a object<unknown>.

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
$name is of type string, but the function expects a object<unknown>.

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...
1318
            }
1319
1320
            return $this->service->upload($dropboxFile, $fullpath, ['mode' => 'overwrite'])->getPathLower();
1321
        } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1322
            return $this->setError('Dropbox error: '.$e->getMessage());
1323
        }
1324
    }
1325
1326
    /**
1327
     * Get file contents.
1328
     *
1329
     * @param string $path file path
1330
     *
1331
     * @return string|false
1332
     *
1333
     * @author Naoki Sawada
1334
     **/
1335
    protected function _getContents($path)
1336
    {
1337
        $contents = '';
1338
1339
        try {
1340
            $file = $this->service->download($path);
1341
            $contents = $file->getContents();
1342
        } catch (Exception $e) {
1343
            return $this->setError('Dropbox error: '.$e->getMessage());
1344
        }
1345
1346
        return $contents;
1347
    }
1348
1349
    /**
1350
     * Write a string to a file.
1351
     *
1352
     * @param string $path    file path
1353
     * @param string $content new file content
1354
     *
1355
     * @return bool
1356
     *
1357
     * @author Naoki Sawada
1358
     **/
1359 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...
1360
    {
1361
        $res = false;
1362
1363
        if ($local = $this->getTempFile($path)) {
1364
            if (file_put_contents($local, $content, LOCK_EX) !== false
1365
            && ($fp = fopen($local, 'rb'))) {
1366
                clearstatcache();
1367
                $res = $this->_save($fp, $path, '', []);
1368
                fclose($fp);
1369
            }
1370
            file_exists($local) && unlink($local);
1371
        }
1372
1373
        return $res;
1374
    }
1375
1376
    /**
1377
     * Detect available archivers.
1378
     **/
1379
    protected function _checkArchivers()
1380
    {
1381
        // 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...
1382
        return [];
1383
    }
1384
1385
    /**
1386
     * chmod implementation.
1387
     *
1388
     * @return bool
1389
     **/
1390
    protected function _chmod($path, $mode)
1391
    {
1392
        return false;
1393
    }
1394
1395
    /**
1396
     * Unpack archive.
1397
     *
1398
     * @param string $path archive path
1399
     * @param array  $arc  archiver command and arguments (same as in $this->archivers)
1400
     *
1401
     * @return true
1402
     *
1403
     * @author Dmitry (dio) Levashov
1404
     * @author Alexey Sukhotin
1405
     **/
1406
    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...
1407
    {
1408
        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...
1409
        //return false;
1410
    }
1411
1412
    /**
1413
     * Recursive symlinks search.
1414
     *
1415
     * @param string $path file/dir path
1416
     *
1417
     * @return bool
1418
     *
1419
     * @author Dmitry (dio) Levashov
1420
     **/
1421
    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...
1422
    {
1423
        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...
1424
    }
1425
1426
    /**
1427
     * Extract files from archive.
1428
     *
1429
     * @param string $path archive path
1430
     * @param array  $arc  archiver command and arguments (same as in $this->archivers)
1431
     *
1432
     * @return true
1433
     *
1434
     * @author Dmitry (dio) Levashov,
1435
     * @author Alexey Sukhotin
1436
     **/
1437
    protected function _extract($path, $arc)
1438
    {
1439
        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...
1440
    }
1441
1442
    /**
1443
     * Create archive and return its path.
1444
     *
1445
     * @param string $dir   target dir
1446
     * @param array  $files files names list
1447
     * @param string $name  archive name
1448
     * @param array  $arc   archiver options
1449
     *
1450
     * @return string|bool
1451
     *
1452
     * @author Dmitry (dio) Levashov,
1453
     * @author Alexey Sukhotin
1454
     **/
1455
    protected function _archive($dir, $files, $name, $arc)
1456
    {
1457
        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...
1458
    }
1459
1460
    /**
1461
     * Get dat(Dropbox metadata) from Dropbox.
1462
     *
1463
     * @param string $path
1464
     *
1465
     * @return object Dropbox metadata
1466
     */
1467
    private function _db_getFile($path, $fields = '')
0 ignored issues
show
Unused Code introduced by
The parameter $fields 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...
1468
    {
1469
        if ($path === '/') {
1470
            return true;
1471
        }
1472
1473
        $res = false;
1474
        try {
1475
            $file = $this->service->getMetadata($path, $this->FETCH_OPTIONS);
1476
            if ($file instanceof FolderMetadata || $file instanceof FileMetadata) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Models\FolderMetadata does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
Bug introduced by
The class Kunnu\Dropbox\Models\FileMetadata does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
1477
                $res = $file;
1478
            }
1479
1480
            return $res;
1481
        } catch (DropboxClientException $e) {
0 ignored issues
show
Bug introduced by
The class Kunnu\Dropbox\Exceptions\DropboxClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1482
            return false;
1483
        }
1484
    }
1485
} // END class
1486