Completed
Push — master ( ae6724...e8c5d5 )
by Joseph
03:12
created

Adapter::makeProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace STS\StorageConnect\Drivers\Google;
4
5
use Google_Client;
6
use Google_Http_MediaFileUpload;
7
use Google_Service_Drive;
8
use Google_Service_Drive_DriveFile;
9
use STS\StorageConnect\Drivers\AbstractAdapter;
10
use STS\StorageConnect\Types\Quota;
11
use StorageConnect;
12
13
class Adapter extends AbstractAdapter
14
{
15
    /**
16
     * @var string
17
     */
18
    protected $driver = "google";
19
20
    /**
21
     * @var string
22
     */
23
    protected $providerClass = Provider::class;
24
25
    /**
26
     * @param $user
27
     *
28
     * @return array
29
     */
30
    protected function mapUserDetails($user)
31
    {
32
        return [
33
            'name'  => $user->name,
34
            'email' => $user->email,
35
        ];
36
    }
37
38
    /**
39
     * @return Quota
40
     */
41
    public function getQuota()
42
    {
43
        $about = $this->service()->about->get();
44
45
        return new Quota($about->getQuotaBytesTotal(), $about->getQuotaBytesUsed());
46
    }
47
48
    /**
49
     * @return Google_Service_Drive
50
     */
51
    protected function makeService()
52
    {
53
        $client = new Google_Client([
54
            'client_id'     => $this->config['client_id'],
55
            'client_secret' => $this->config['client_secret']
56
        ]);
57
58
        $client->setApplicationName(
59
            config('storage-connect.app_name', config('app.name'))
60
        );
61
62
        $client->setAccessToken($this->token);
63
64
        if ($client->isAccessTokenExpired()) {
65
            $this->updateToken($client->refreshToken($client->getRefreshToken()));
66
        }
67
68
        return new Google_Service_Drive($client);
69
    }
70
71
    /**
72
     * @param $sourcePath
73
     * @param $destinationPath
74
     *
75
     * @return string
76
     */
77
    public function upload( $sourcePath, $destinationPath )
78
    {
79
        $file = $this->prepareFile($destinationPath);
80
        list($filesize, $mimeType) = $this->stat($sourcePath);
81
82
        if ($filesize >= 5 * 1024 * 1024) {
83
            return $this->uploadChunked($sourcePath, $file, $filesize);
84
        }
85
86
        return $this->service()->files->create($file, [
87
            'data'       => file_get_contents($sourcePath),
88
            'mimeType'   => $mimeType,
89
            'uploadType' => 'media',
90
        ])->id;
91
    }
92
93
    /**
94
     * @param $destinationPath
95
     *
96
     * @return Google_Service_Drive_DriveFile
97
     */
98
    protected function prepareFile( $destinationPath )
99
    {
100
        $folderId = $this->getFolderIdForPath(StorageConnect::appName() . "/" . dirname($destinationPath));
101
102
        return new Google_Service_Drive_DriveFile([
103
            'name'    => basename($destinationPath),
104
            'parents' => [$folderId],
105
        ]);
106
    }
107
108
    /**
109
     * @param $sourcePath
110
     *
111
     * @return array
112
     */
113
    protected function stat( $sourcePath )
114
    {
115
        if (starts_with($sourcePath, "http")) {
116
            $headers = array_change_key_case(get_headers($sourcePath, 1));
117
            return [$headers['content-length'], $headers['content-type']];
118
        }
119
120
        return [filesize($sourcePath), mime_content_type($sourcePath)];
121
    }
122
123
    /**
124
     * @param $path
125
     *
126
     * @return mixed
127
     */
128
    protected function getFolderIdForPath( $path )
129
    {
130
        return $this->prepareFolderTree(
131
            array_filter(explode("/", $path))
132
        );
133
    }
134
135
    /**
136
     * @param                                $sourcePath
137
     * @param Google_Service_Drive_DriveFile $file
138
     * @param                                $filesize
139
     *
140
     * @return string
141
     */
142
    protected function uploadChunked( $sourcePath, Google_Service_Drive_DriveFile $file, $filesize )
143
    {
144
        $chunkSize = 2 * 1024 * 1024;
145
146
        $this->service()->getClient()->setDefer(true);
147
        $request = $this->service()->files->create($file);
148
149
        $upload = new Google_Http_MediaFileUpload(
150
            $this->service()->getClient(),
151
            $request,
152
            $file->getMimeType(),
153
            null,
154
            true,
155
            $chunkSize
0 ignored issues
show
Documentation introduced by
$chunkSize 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...
156
        );
157
        $upload->setFileSize($filesize);
158
159
        $file = false;
160
        $handle = fopen($sourcePath, "rb");
161
162
        while (!$file && !feof($handle)) {
163
            $chunk = fread($handle, $chunkSize);
164
            $file = $upload->nextChunk($chunk);
0 ignored issues
show
Documentation introduced by
$chunk is of type string, 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...
165
        }
166
167
        fclose($handle);
168
        $this->service()->getClient()->setDefer(false);
169
170
        return $file->id;
171
    }
172
173
    /**
174
     * @param array  $folders
175
     * @param string $parentFolderId
176
     *
177
     * @return mixed
178
     */
179
    protected function prepareFolderTree( array $folders, $parentFolderId = 'root' )
180
    {
181
        $foldername = array_shift($folders);
182
183
        if (!$folder = $this->folderExists($foldername, $parentFolderId)) {
184
            $fileMetadata = new Google_Service_Drive_DriveFile([
185
                'name'     => $foldername,
186
                'parents'  => [$parentFolderId],
187
                'mimeType' => 'application/vnd.google-apps.folder'
188
            ]);
189
190
            $folder = $this->service()->files->create($fileMetadata, [
191
                'fields' => 'id'
192
            ]);
193
        }
194
195
        return count($folders)
196
            ? $this->prepareFolderTree($folders, $folder->id)
197
            : $folder->id;
198
    }
199
200
    /**
201
     * @param        $name
202
     * @param string $parentFolderId
203
     *
204
     * @return mixed
205
     */
206
    protected function folderExists( $name, $parentFolderId = 'root' )
207
    {
208
        $name = str_replace("'", "", $name);
209
210
        return collect($this->service()->files->listFiles([
211
            'q'      => "mimeType = 'application/vnd.google-apps.folder' and name = '$name' and trashed = false  and '$parentFolderId' in parents",
212
            'spaces' => 'drive',
213
            'fields' => 'files(id, name)',
214
        ]))->first();
215
    }
216
}