/**
  * TODO(ianbarber): This function needs simplifying.
  *
  * @param $name
  * @param $arguments
  * @param $expected_class - optional, the expected class name
  *
  * @return Google_Http_Request|expected_class
  * @throws Google_ApiException
  */
 public function call($name, $arguments, $expected_class = null)
 {
     if (!isset($this->methods[$name])) {
         throw new Google_ApiException("Unknown function: " . "{$this->serviceName}->{$this->resourceName}->{$name}()");
     }
     $method = $this->methods[$name];
     $parameters = $arguments[0];
     // postBody is a special case since it's not defined in the discovery
     // document as parameter, but we abuse the param entry for storing it.
     $postBody = null;
     if (isset($parameters['postBody'])) {
         if ($parameters['postBody'] instanceof Google_ApiModel) {
             // In the cases the post body is an existing object, we want
             // to use the smart method to create a simple object for
             // for JSONification.
             $parameters['postBody'] = $parameters['postBody']->toSimpleObject();
         } else {
             if (is_object($parameters['postBody'])) {
                 // If the post body is another kind of object, we will try and
                 // wrangle it into a sensible format.
                 $parameters['postBody'] = $this->convertToArrayAndStripNulls($parameters['postBody']);
             }
         }
         $postBody = json_encode($parameters['postBody']);
         unset($parameters['postBody']);
     }
     // TODO(ianbarber): optParams here probably should have been
     // handled already - this may well be redundant code.
     if (isset($parameters['optParams'])) {
         $optParams = $parameters['optParams'];
         unset($parameters['optParams']);
         $parameters = array_merge($parameters, $optParams);
     }
     if (!isset($method['parameters'])) {
         $method['parameters'] = array();
     }
     $method['parameters'] = array_merge($method['parameters'], $this->stackParameters);
     foreach ($parameters as $key => $val) {
         if ($key != 'postBody' && !isset($method['parameters'][$key])) {
             throw new Google_ApiException("({$name}) unknown parameter: '{$key}'");
         }
     }
     foreach ($method['parameters'] as $paramName => $paramSpec) {
         if (isset($paramSpec['required']) && $paramSpec['required'] && !isset($parameters[$paramName])) {
             throw new Google_ApiException("({$name}) missing required param: '{$paramName}'");
         }
         if (isset($parameters[$paramName])) {
             $value = $parameters[$paramName];
             $parameters[$paramName] = $paramSpec;
             $parameters[$paramName]['value'] = $value;
             unset($parameters[$paramName]['required']);
         } else {
             // Ensure we don't pass nulls.
             unset($parameters[$paramName]);
         }
     }
     $servicePath = $this->service->servicePath;
     $url = Google_Http_REST::createRequestUri($servicePath, $method['path'], $parameters);
     $httpRequest = new Google_Http_Request($url, $method['httpMethod'], null, $postBody);
     $httpRequest->setBaseComponent($this->client->getBasePath());
     if ($postBody) {
         $contentTypeHeader = array();
         $contentTypeHeader['content-type'] = 'application/json; charset=UTF-8';
         $httpRequest->setRequestHeaders($contentTypeHeader);
         $httpRequest->setPostBody($postBody);
     }
     $httpRequest = $this->client->getAuth()->sign($httpRequest);
     $httpRequest->setExpectedClass($expected_class);
     if (isset($parameters['data']) && ($parameters['uploadType']['value'] == 'media' || $parameters['uploadType']['value'] == 'multipart')) {
         // If we are doing a simple media upload, trigger that as a convenience.
         $mfu = new Google_Http_MediaFileUpload($this->client, $httpRequest, isset($parameters['mimeType']) ? $parameters['mimeType']['value'] : 'application/octet-stream', $parameters['data']['value']);
     }
     if ($this->client->shouldDefer()) {
         // If we are in batch or upload mode, return the raw request.
         return $httpRequest;
     }
     return $this->client->execute($httpRequest);
 }
Exemple #2
0
 /**
  * Downloads backup file from Google Drive to root folder on local server.
  *
  * @param array $args arguments passed to the function
  *                    [google_drive_token] -> user's Google drive token in json form
  *                    [google_drive_directory] -> folder on user's Google Drive account which backup file should be downloaded from
  *                    [google_drive_site_folder] -> subfolder with site name in google_drive_directory which backup file should be downloaded from
  *                    [backup_file] -> absolute path of backup file on local server
  *                    [file_id] -> google file id
  *
  * @return bool|array absolute path to downloaded file is successful, array with error message if not
  */
 public function get_google_drive_backup($args)
 {
     mwp_register_autoload_google();
     $googleClient = new Google_ApiClient();
     $googleClient->setAccessToken($args['google_drive_token']);
     $driveService = new Google_Service_Drive($googleClient);
     mwp_logger()->info('Connecting to Google Drive');
     try {
         $about = $driveService->about->get();
         $rootFolderId = $about->getRootFolderId();
     } catch (Exception $e) {
         mwp_logger()->error('Error while connecting to Google Drive', array('exception' => $e));
         return array('error' => 'Error while connecting to Google Drive: ' . $e->getMessage());
     }
     if (empty($args['file_id'])) {
         mwp_logger()->info('Looking for backup directory');
         try {
             $backupFolderFiles = $driveService->files->listFiles(array('q' => sprintf("title='%s' and '%s' in parents and trashed = false", addslashes($args['google_drive_directory']), $rootFolderId)));
         } catch (Exception $e) {
             mwp_logger()->error('Error while looking for backup directory', array('exception' => $e));
             return array('error' => 'Error while looking for backup directory: ' . $e->getMessage());
         }
         if (!$backupFolderFiles->offsetExists(0)) {
             mwp_logger()->error('Backup directory ("{directory}") does not exist', array('directory' => $args['google_drive_directory']));
             return array('error' => sprintf("The backup directory (%s) does not exist.", $args['google_drive_directory']));
         }
         /** @var Google_Service_Drive_DriveFile $backupFolder */
         $backupFolder = $backupFolderFiles->offsetGet(0);
         if ($args['google_drive_site_folder']) {
             mwp_logger()->info('Looking into the site folder');
             try {
                 $siteFolderFiles = $driveService->files->listFiles(array('q' => sprintf("title='%s' and '%s' in parents and trashed = false", addslashes($this->site_name), $backupFolder->getId())));
             } catch (Exception $e) {
                 mwp_logger()->error('Error while looking for the site folder', array('exception' => $e));
                 return array('error' => 'Error while looking for the site folder: ' . $e->getMessage());
             }
             if ($siteFolderFiles->offsetExists(0)) {
                 $backupFolder = $siteFolderFiles->offsetGet(0);
             }
         }
         try {
             $backupFiles = $driveService->files->listFiles(array('q' => sprintf("title='%s' and '%s' in parents and trashed = false", addslashes($args['backup_file']), $backupFolder->getId())));
         } catch (Exception $e) {
             mwp_logger()->error('Error while fetching Google Drive backup file', array('file_name' => $args['backup_file'], 'exception' => $e));
             return array('error' => 'Error while fetching Google Drive backup file: ' . $e->getMessage());
         }
         if (!$backupFiles->offsetExists(0)) {
             return array('error' => sprintf('Backup file "%s" was not found on your Google Drive account.', $args['backup_file']));
         }
         /** @var Google_Service_Drive_DriveFile $backupFile */
         $backupFile = $backupFiles->offsetGet(0);
     } else {
         try {
             /** @var Google_Service_Drive_DriveFile $backupFile */
             $backupFile = $driveService->files->get($args['file_id']);
         } catch (Exception $e) {
             mwp_logger()->error('Error while fetching Google Drive backup file by id', array('file_id' => $args['file_id'], 'exception' => $e));
             return array('error' => 'Error while fetching Google Drive backup file: ' . $e->getMessage());
         }
     }
     $downloadUrl = $backupFile->getDownloadUrl();
     $downloadLocation = ABSPATH . 'mwp_temp_backup.zip';
     $fileSize = $backupFile->getFileSize();
     $downloaded = 0;
     $chunkSize = 1024 * 1024 * 4;
     $fh = fopen($downloadLocation, 'w+');
     if (!is_resource($fh)) {
         return array('error' => 'Temporary backup download location is not writable (location: "%s").', $downloadLocation);
     }
     while ($downloaded < $fileSize) {
         $request = new Google_Http_Request($downloadUrl);
         $googleClient->getAuth()->sign($request);
         $toDownload = min($chunkSize, $fileSize - $downloaded);
         mwp_logger()->info('Downloading: {downloaded}/{size}', array('downloaded' => mwp_format_bytes($downloaded), 'size' => mwp_format_bytes($fileSize)));
         $request->setRequestHeaders($request->getRequestHeaders() + array('Range' => 'bytes=' . $downloaded . '-' . ($downloaded + $toDownload - 1)));
         $googleClient->getIo()->makeRequest($request);
         if ($request->getResponseHttpCode() !== 206) {
             mwp_logger()->error('Google Drive has returned an invalid response', array('response_headers' => $request->getResponseHeaders(), 'response_body' => $request->getResponseBody()));
             return array('error' => sprintf('Google Drive service has returned an invalid response code (%s)', $request->getResponseHttpCode()));
         }
         fwrite($fh, $request->getResponseBody());
         $downloaded += $toDownload;
     }
     fclose($fh);
     $fileMd5 = md5_file($downloadLocation);
     if ($backupFile->getMd5Checksum() !== $fileMd5) {
         mwp_logger()->error('File checksum does not match, downloaded file is corrupted.', array('original' => $backupFile->getMd5Checksum(), 'downloaded' => $fileMd5));
         return array('error' => 'File downloaded was corrupted.');
     }
     return $downloadLocation;
 }