silently failing to push images to user's Google Drive via PHP SDK

76 views Asked by At

I am making an open source application where a user can backup their facebook albums to google drive using PHP SDK. I am done with the facebook part and now stuck with google's awfully written documentation. So here is how I am working with is step by step:

user authentication: all my requests and callbacks are managed in one PHP file, sought of works like an API. So this is code block that handles request to upload documents to google:

<?php
session_start();
require_once __DIR__.'/classes/facebook.class.php';
require_once __DIR__.'/classes/drive.class.php';
$fb = new Facebook();
$google = Drive::getInstance();
$query = $_REQUEST['i'];
switch($query){
        case "backup_req":
            $agent = $google->getAgent();
            if(!isset($_SESSION['google_access_token'])){
                $_SESSION['album_temp'] = $_REQUEST['album'];
                header("location: ".filter_var($agent->createAuthUrl(), FILTER_SANITIZE_URL));
            } else{
                $google->uploadAlbum($fb, $_REQUEST['album']);
            }
        break;
        case "google_callback":
            $agent = $google->getAgent();
            if(!isset($_SESSION['google_access_token'])){
                $code = $_GET['code']; // just to keep the code neat.. no need to store in other var!
                $res = $google->getAgent()->authenticate($code); // hope this works
                $_SESSION['google_access_token'] = $agent->getAccessToken();
            }
            $google->uploadAlbum($fb, $_SESSION['album_temp']);
        break;
}

Here what I am trying to do is, if there is no access token of google in the session, we redirect user to google's sign in page. which when done redirects to same file but this time requesting google_callback along with a code. This is then stored onto session and we proceed with uploadAlbum method.

NOTE, I have echoed the contents of the server, and yes, I do get access token and refresh token

Now, for uploading the album, there are 4 methods in Drive class which is a singleton. here is the code:

    class Drive{
    private static $instance;
    private $fileRequest;
    private $mimeType;
    private $filename;
    private $path;
    private $client;
    private $clientId = "<client-id>";
    private $clientSecret = "<client-secret>";
    private final function __construct(){
        $this->client = new Google_Client();
        $this->client->setApplicationName("fb album backup tool");
        $this->client->setClientId($this->clientId);
        $this->client->setClientSecret($this->clientSecret);
        $this->client->setRedirectUri("https://fbrtc.sameer-manek.com/fb_caller.php?i=google_callback");
        $this->client->setScopes(array('https://www.googleapis.com/auth/drive.file'));
        $this->client->setAccessType("offline");
        $this->client->setApprovalPrompt('force');
    }
    public static function getInstance(){
        if(self::$instance == null) {
            self::$instance = new Drive();
        }
        return self::$instance;
    }
    public function getAgent(){
        return $this->client;
    }
    public function uploadAlbum($fb, $album){
            $nodes = $fb->get_photos($album);
            $client = new GearmanClient();
            $client->addServer();
            foreach ($nodes as $node) {
                //$client->addTask('init', $node['picture']);
                try{
                    $data = file_get_contents($node['picture']);
                    $saveto = __DIR__."/../scripts/tmp/".rand().".jpg";
                    $file = fopen($saveto, "w+");
                    fwrite($file, $data);
                    fclose($file);
                    $this->init($saveto);
                    echo "uploaded ".$saveto."\n";
                } catch(Exception $e) {
                    return false;
                }

            }
            return true;
            //$client->runTasks();
    }
    public function init($file){
        $at = $_SESSION['google_access_token']['access_token'];
        $this->client->setAccessToken($at);
        $this->fileRequest = $file;
        $client = $this->client;
        //$client->refreshToken($_SESSION['google_access_token']['refreshToken']);
        $tokens = $client->getAccessToken();
        $client->setAccessToken($tokens);
        $client->setDefer(true);
        $this->client->setAccessToken($at);
        $this->processFile();
    }
    public function processFile(){
        $fileRequest = $this->fileRequest;
        $path_parts = pathinfo($this->fileRequest);
        $this->path = $path_parts['dirname'];
        $this->fileName = $path_parts['basename'];
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $this->mimeType = finfo_file($finfo, $fileRequest);
        finfo_close($finfo);
        $this->upload();
    }
    public function upload(){
        $client = $this->client;
        $service = new Google_Service_Drive($this->client);
        //Insert a file
        $file = new Google_Service_Drive_DriveFile();
        $file->setName($this->fileName.'.jpg');
        $file->setDescription('A test document');
        $file->setMimeType('image/jpeg');
        $data = file_get_contents($this->fileRequest);
        $createdFile = $service->files->create($file, array(
              'data' => $data,
              'mimeType' => 'image/jpeg',
              'uploadType' => 'multipart'
        ));
    }
}

uploadAlbum() method is fetching images from the requested album. init() method is prepping the object for uploading that image (here we use assign access token to the object) processFile() method is fetching and storing information about the image. upload() method is actually uploading to image to user's google drive.

after this has been executed, there are no exceptions generated, neither any error generated, but the image is not uploaded to the drive when I cross check..

I cannot pin point what the problem is, please help me resolve this error. Thanks.

[EDIT] I var_dumped the contents of $createdFile and it dumped following on the screen:

object(GuzzleHttp\Psr7\Request)#73 (7) { ["method":"GuzzleHttp\Psr7\Request":private]=> string(4) "POST" ["requestTarget":"GuzzleHttp\Psr7\Request":private]=> NULL ["uri":"GuzzleHttp\Psr7\Request":private]=> object(GuzzleHttp\Psr7\Uri)#69 (7) { ["scheme":"GuzzleHttp\Psr7\Uri":private]=> string(5) "https" ["userInfo":"GuzzleHttp\Psr7\Uri":private]=> string(0) "" ["host":"GuzzleHttp\Psr7\Uri":private]=> string(18) "www.googleapis.com" ["port":"GuzzleHttp\Psr7\Uri":private]=> NULL ["path":"GuzzleHttp\Psr7\Uri":private]=> string(22) "/upload/drive/v3/files" ["query":"GuzzleHttp\Psr7\Uri":private]=> string(20) "uploadType=multipart" ["fragment":"GuzzleHttp\Psr7\Uri":private]=> string(0) "" } ["headers":"GuzzleHttp\Psr7\Request":private]=> array(3) { ["Host"]=> array(1) { [0]=> string(18) "www.googleapis.com" } ["content-type"]=> array(1) { [0]=> string(37) "multipart/related; boundary=344323595" } ["X-Php-Expected-Class"]=> array(1) { [0]=> string(30) "Google_Service_Drive_DriveFile" } } ["headerNames":"GuzzleHttp\Psr7\Request":private]=> array(3) { ["content-type"]=> string(12) "content-type" ["host"]=> string(4) "Host" ["x-php-expected-class"]=> string(20) "X-Php-Expected-Class" } ["protocol":"GuzzleHttp\Psr7\Request":private]=> string(3) "1.1" ["stream":"GuzzleHttp\Psr7\Request":private]=> object(GuzzleHttp\Psr7\Stream)#67 (7) { ["stream":"GuzzleHttp\Psr7\Stream":private]=> resource(11) of type (stream) ["size":"GuzzleHttp\Psr7\Stream":private]=> NULL ["seekable":"GuzzleHttp\Psr7\Stream":private]=> bool(true) ["readable":"GuzzleHttp\Psr7\Stream":private]=> bool(true) ["writable":"GuzzleHttp\Psr7\Stream":private]=> bool(true) ["uri":"GuzzleHttp\Psr7\Stream":private]=> string(10) "php://temp" ["customMetadata":"GuzzleHttp\Psr7\Stream":private]=> array(0) { } } } uploaded /sites/facebook_backup/classes/../scripts/tmp/264708337.jpg

here's the link to the GitHub repo for reference.

0

There are 0 answers