I felt optimistic when I've started investigate this issue because it looked like I wasn't the first one...
I have a Laravel app using Google Drive as storage. It works when I add / rename files using Storage facade.
To rename a folder I'm using $googleDriveService->files->update($folder->getId(), $folder)
but I got an error 403 "The resource body includes fields which are not directly writable."
On the Google OAuth 2.0 Playground I have the following scope:
Here is my code
$client_id = env('GOOGLE_DRIVE_CLIENT_ID');
$client_secret = env('GOOGLE_DRIVE_CLIENT_SECRET');
$refresh_token = env('GOOGLE_DRIVE_REFRESH_TOKEN');
/* Instantiate Google Client */
$googleClient = new GoogleClient();
$googleClient->setClientId($client_id);
$googleClient->setClientSecret($client_secret);
$googleClient->refreshToken($refresh_token);
$googleClient->addScope([
Google_Service_Drive::DRIVE,
Google_Service_Drive::DRIVE_FILE,
Google_Service_Drive::DRIVE_METADATA
]);
/* Instantiate Google Drive service */
$googleDriveService = new GoogleDriveService($googleClient);
function renameFolder($oldName, $newName, $path, $service)
{
/* list all folders with $oldName and select the first one matching $path */
$oldFolder = collect($service->files->listFiles(['q' => "mimeType='application/vnd.google-apps.folder' and name='$oldName'"]))
->first(fn($folder) => getFolderPath($folder->getId(), $service) === "$path/$oldName");
if(!$oldFolder) { return 'folder unknown'; }
$oldFolder->setName($newName);
/* this is the line pointed by the error */ $service->files->update($oldFolder->getId(), $oldFolder);
return compact('oldFolder');
}
function getFolderPath($folderId, $service, $delimiter = '/')
{
$path = '';
while ($folderId) {
$folder = $service->files->get($folderId, ['fields' => 'name, parents']);
if($folder->name === env('GOOGLE_DRIVE_FOLDER')) { break; }
$path = $folder->name . $delimiter . $path;
$folderId = $folder->parents;
}
return rtrim($path, $delimiter);
}
return renameFolder('old_name', 'new_name', 'path_to_folder', $googleDriveService);
When I comment the line with …->files->update(…
I see the correct folder (I compared the Id with Google Drive) and the name is the right one.
I've tried as well $googleDriveService->files->update($folder->getId(), $folder)->execute()
but I don't know what else to try… any idea is welcome
Thanks to Tanaike comments, I understood the problem came from
$service->files->update($oldFolder->getId(), $oldFolder);
the 2nd parameter of update method shouldn't be $oldFolder
but a new metadata object.
I've replaced
$oldFolder->setName($newName);
$service->files->update($oldFolder->getId(), $oldFolder);
by
$newMetadata = new GoogleServiceDriveDriveFile(['name' => $newName]);
$service->files->update($oldFolder->getId(), $newMetadata);
And it works.