Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
GoogleDriveClient
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
4 / 4
7
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 uploadFileFromFileSys
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
3
 listFileIds
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 deleteFile
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace pvc\cloud\google;
4
5use Google\Service\Drive\Resource\Files;
6use Google_Service_Drive;
7use Google_Service_Drive_DriveFile;
8use pvc\cloud\google\err\GoogleAuthenticationException;
9use pvc\cloud\google\err\InvalidOrUnauthorizedScopeException;
10use pvc\err\pvc\file\FileDoesNotExistException;
11use pvc\err\pvc\file\FileNotReadableException;
12use pvc\http\mime\MimeTypes;
13use pvc\interfaces\http\mime\MimeTypesInterface;
14use function PHPUnit\Framework\assertIsString;
15
16class GoogleDriveClient
17{
18    public readonly Google_Service_Drive $driveService;
19
20    public readonly Files $files;
21
22    protected MimeTypesInterface $mimeTypes;
23
24    /**
25     * @param array<string> $credentials
26     * @param MimeTypesInterface|null $mimeTypes
27     * @throws GoogleAuthenticationException
28     * @throws InvalidOrUnauthorizedScopeException
29     */
30    public function __construct(
31        array $credentials,
32        ?MimeTypesInterface $mimeTypes = null,
33    ) {
34        $client = new GoogleClient($credentials);
35        $client->addScope(Google_Service_Drive::DRIVE);
36        $this->mimeTypes = $mimeTypes ?? new MimeTypes();
37        $this->driveService = new Google_Service_Drive($client);
38        /** @var Files $files */
39        $files = $this->driveService->files;
40        $this->files = $files;
41    }
42
43    public function uploadFileFromFileSys(string $localFilePath): string
44    {
45        if (!file_exists($localFilePath)) {
46            throw new FileDoesNotExistException($localFilePath);
47        }
48        if (!is_readable($localFilePath)) {
49            throw new FileNotReadableException($localFilePath);
50        }
51        $fileName = basename($localFilePath);
52        $mimeType = $this->mimeTypes->detect(
53            $localFilePath,
54            MimeTypes::DETECT_FROM_CONTENTS|MimeTypes::USE_FILE_EXTENSION
55        )->getMimeTypeName();
56
57        $file = new Google_Service_Drive_DriveFile();
58        $file->setName($fileName);
59        $file->setMimeType($mimeType);
60
61        $data = file_get_contents($localFilePath);
62
63        /**
64         * tempted to put this in a try / throw / catch.  But it would be very hard to test.  Hard to mock the files
65         * object (which is a property of the drive service) and then stub it to fail.  And the resulting thrown
66         * exception would not really add any value other than to echo the underlying exception from the create method
67         * of the files object.
68         */
69        $file = $this->files->create($file, array(
70                'data' => $data,
71                'mimeType' => $mimeType,
72                'uploadType' => 'multipart'
73        ));
74        $fileId = $file['id'];
75        assertIsString($fileId);
76        return $fileId;
77    }
78
79    /**
80     * @param string $folderFileId
81     * @return array<string>
82     * @throws \Google\Service\Exception
83     */
84    public function listFileIds(string $folderFileId = 'root'): array
85    {
86        $fileList = $this->files->listFiles(array('q' => "'$folderFileId' in parents"));
87        $result = [];
88        foreach ($fileList->getFiles() as $file) {
89            $result[] = $file->getId();
90        }
91        return $result;
92    }
93
94    /**
95     * @param string $fileId
96     * @return void
97     * @throws \Google\Service\Exception
98     */
99    public function deleteFile(string $fileId): void
100    {
101        $this->files->delete($fileId);
102    }
103}