8

ive been using Zend Gdata for a while now, and today im getting an error of

Notice: Undefined offset: ClientLogin.php on line 150

via php, this has been working for a while now, and today without changing anything it stopped working, im guessing some deprecated service on behalf of google with the zend gdata maybe the Zend_Gdata_ClientLogin::getHttpClient( ) method or something, can any one confirm or help me with this issue. the code im using to connect is as follows:

    require_once('Zend/Loader.php');
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Docs');
Zend_Loader::loadClass('Zend_Gdata_Spreadsheets');
require_once 'Zend/Gdata.php';
require_once 'Zend/Gdata/AuthSub.php';
require_once 'Zend/Gdata/Spreadsheets.php';
require_once 'Zend/Gdata/Spreadsheets/DocumentQuery.php';
require_once 'Zend/Gdata/Spreadsheets/ListQuery.php';
require_once 'Zend/Loader.php';


$sourceUser = "myemail";
$sourcePass = "mysuperawesomepassword";
$service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
$sourceClient = Zend_Gdata_ClientLogin::getHttpClient($sourceUser, $sourcePass, $service);
$connection = new Zend_Gdata_Spreadsheets($sourceClient);

i am using the zend gdata with the google spreadsheets

also the error points specifically to this line

$sourceClient = Zend_Gdata_ClientLogin::getHttpClient($sourceUser, $sourcePass, $service);

as i said, i was using this for a while now, and nothing has changed on my end

nonaxanon
  • 237
  • 4
  • 18

5 Answers5

4

I uses ClientLogin for a server to server application.

needed to switch to oAuth2 in a hurry today. I merged some examples I found to get the authorisation token using a 'Service account'

function get_token() {
$client_email = '0-1.apps.googleusercontent.com';
$client_email = '0-1@developer.gserviceaccount.com';
$private_key = file_get_contents('abc.p12');
$scopes = array('https://spreadsheets.google.com/feeds');
$credentials = new Google_Auth_AssertionCredentials(
    $client_email,
    $scopes,
    $private_key,
    'notasecret',                                 // Default P12 password
    'http://oauth.net/grant_type/jwt/1.0/bearer' // Default grant type
);

$client = new Google_Client();
$client->setAssertionCredentials($credentials);
if ($client->getAuth()->isAccessTokenExpired()) {
 $client->getAuth()->refreshTokenWithAssertion();
}
 $tokenData = json_decode($client->getAccessToken());
        return $tokenData->access_token;
}

I needed to use the developer email not the app email, same email must be added as a user to the spreadsheet

the generated token can then be used with php-google-spreadsheet-client

$accessToken = get_token();

$serviceRequest = new DefaultServiceRequest($accessToken);
ServiceRequestFactory::setInstance($serviceRequest);

$spreadsheetService = new Google\Spreadsheet\SpreadsheetService();
$spreadsheetFeed = $spreadsheetService->getSpreadsheets();

$spreadsheet = $spreadsheetFeed->getByTitle('Hello World');
  • could you explain how you generated the "abc.p12" file? when i created the service account, it downloaded a .json file instead. also, which dependency files are needed for your get_token() function? thanks! – Concept211 May 28 '15 at 20:55
  • 1
    the .p12 file is generated in your api console, go to google type api console, usually first link, sign in with the account corresponding to the service, and create client id, service account, it will auto download a file with extension as .p12 do not change the file name,,, the file name is super long – nonaxanon May 29 '15 at 14:32
0

Been stuck with this issue aswell, seems like google's ClientLogin was finally removed

Important: Do not use ClientLogin for new applications. Instead, use the more secure OAuth authentication protocol. ClientLogin is a deprecated authentication protocol and is being turned down on April 20, 2015. At that time, ClientLogin requests will no longer be answered. If you have existing applications that use ClientLogin, we encourage you to migrate to OAuth. The ClientLogin support in this library will be removed in the next major release.

Going to try remake my spreadsheets with OAuth now, this may be the solution: removed cuz no more reputation, will post link into commets

edit; having some troubles with magnetikonline, so gonna try this solution: removed cuz no more reputation, will post link into comments

edit2; /'\ this solution is much better, I must go now, but I've got some success with this library, it works much better as far as I see and provide more functionality, try it.

For your problem with token, try https://github.com/asimlqt/php-google-oauth . THis way also worked for me and its much easier, I reveived array with my token info(if u gonna try that token with second library, ur token gonna be array, while u need only $accessToken['access_token'] part in order to make $serviceRequest = new DefaultServiceRequest($accessToken);

Another big tutorial I found: http://konstantinshkut.com/blog/2014/11/01/how_to_get_data_from_google_spreadsheet_in_yii_php_application (thats for second solution, asimlqt/php-google-spreadsheet-client), step 6 helps a lot to understand how my file must be looking.

farefray
  • 16
  • 3
  • Usage: exchangecodefortokens.php -c AUTHORIZATION CODE im stuck there, think u can share some pointers ? – nonaxanon May 27 '15 at 11:48
  • Your code must be looking like 4/z7xfjN3RI3dNTy38cfMzu4zF9pJNrJxCk2m-55LA.cqdvdLrNQ335uyeEpmwI#, it was giving me error until I tried to use only part before dot, so in my case 4/z7xfjN3RI3dNTy38cfMzu4zF9pJNrJxCk2m-55LA (php exchangecodefortorkens.php -c 4/z7xfjN3RI3dNTy38cfMzu4zF9pJNrJxCk2m-55LA) – farefray May 27 '15 at 12:07
  • ok but how do i run that php exchange... thats what i got no clue – nonaxanon May 27 '15 at 12:20
  • I'm using linux machine, so did it from console terminal, moment, will try with web server – farefray May 27 '15 at 12:34
  • Everything were working fine, but now I can't get new token =.= aswell as its not accepting my old token; Error: OAuth2 request access token failed – farefray May 27 '15 at 12:45
  • i honestly cant get it to work...the part where your supposed to call the exchangetoken thing... – nonaxanon May 27 '15 at 12:47
  • Try this way(exchangecodefortokens.php): http://pastebin.com/RJu99rq3 just replace your authCode with part of your authCode(until dot) and call this file from webbrowser, like http://localhost/GoogleSpreadsheet/exchangecodefortokens.php – farefray May 27 '15 at 13:19
  • can't make it add new cells or update current ones, aswell as my token not getting updated automatically :( and sometimes when retrieving data from google 500+ error comes out :( may try this one: https://github.com/asimlqt/php-google-spreadsheet-client – farefray May 27 '15 at 14:04
  • at least u got it working, i cant still get my token , nor save it, just able to accept the button , url returns with code in it, but thats it, wont accept or make the token, i was able to run the commando via cmd in windows, php etc. code , but returns error – nonaxanon May 27 '15 at 14:20
  • edited my answer with a reply for you, also leaving links for both libraries here cuz can't keep them in main post; First one: https://github.com/magnetikonline/phpgooglespreadsheetapi Second one:https://github.com/asimlqt/php-google-spreadsheet-client – farefray May 27 '15 at 15:09
0

In the end I'm ending with something like this(very raw code so far, but enought for those who's seaching for solution. You need php google spreadsheet client of https://github.com/asimlqt/php-google-spreadsheet-client). Thats tiny example of inserting one row to my spreadsheet (sorry about my code, but showing just working example) Thanks for bram brambring showing better way to authorization - answer by bram brambring

<?php
/*
 * Google Spreadsheet class to work with google spreadsheets obviously ;D [using OAuth 2.0, as Zend Gdata is not anymore working]
 */

require_once('/Google/Spreadsheet/ServiceRequestInterface.php');
require_once('/Google/Spreadsheet/DefaultServiceRequest.php');
require_once('/Google/Spreadsheet/ServiceRequestFactory.php');
require_once('/Google/Spreadsheet/Spreadsheet.php');
require_once('/Google/Spreadsheet/SpreadsheetFeed.php');
require_once('/Google/Spreadsheet/SpreadsheetService.php');
require_once('/Google/Spreadsheet/Exception.php');
require_once('/Google/Spreadsheet/UnauthorizedException.php');
require_once('/Google/Spreadsheet/Spreadsheet.php');
require_once('/Google/Spreadsheet/Util.php');
require_once('/Google/Spreadsheet/Worksheet.php');
require_once('/Google/Spreadsheet/WorksheetFeed.php');
require_once('/Google/Spreadsheet/ListFeed.php');
require_once('/Google/Spreadsheet/ListEntry.php');
require_once('/Google/Spreadsheet/CellFeed.php');
require_once('/Google/Spreadsheet/CellEntry.php');
require_once('/Google/Config.php');
require_once('/Google/Client.php');
require_once('/Google/Auth/Abstract.php');
require_once('/Google/Auth/OAuth2.php');
require_once('/Google/Http/Request.php');
require_once('/Google/Utils.php');
require_once('/Google/IO/Abstract.php');
require_once('/Google/IO/Curl.php');
require_once('/Google/Http/CacheParser.php');
require_once('/Google/Logger/Abstract.php');
require_once('/Google/Logger/Null.php');
require_once('/Google/Exception.php');
require_once('/Google/Auth/Exception.php');
require_once('/Google/Auth/AssertionCredentials.php');
require_once('/Google/Cache/Abstract.php');
require_once('/Google/Cache/File.php');
require_once('/Google/Signer/Abstract.php');
require_once('/Google/Signer/P12.php');

use Google\Spreadsheet\DefaultServiceRequest;
use Google\Spreadsheet\ServiceRequestFactory;

class Google_Spreadsheet
{
    private $default = array(
        'worksheetCols' => 12,
        'worksheetRows' => 25
    );

    private $spreadsheetKey;
    private $spreadsheetName;
    private $worksheetName;
    private $spreadsheetFeed;

    public $initialized = true;

    public function __construct($spreadsheetKey, $worksheetName, $spreadsheetName = '')
    {
        $this->spreadsheetKey = $spreadsheetKey;
        $this->worksheetName = $worksheetName;
        $this->spreadsheetName = $spreadsheetName;

        $this->initialized = $this->initialize();
        return true;
    }

    private function getToken() {
        $client_email = '318977712937456456454656563tcfjblgoi@developer.gserviceaccount.com';
        $private_key = file_get_contents('API Project-f10e456456b60.p12');
        $scopes = array('https://spreadsheets.google.com/feeds');
        $credentials = new Google_Auth_AssertionCredentials(
            $client_email,
            $scopes,
            $private_key,
            'notasecret',                                 // Default P12 password
            'http://oauth.net/grant_type/jwt/1.0/bearer' // Default grant type
        );

        $client = new Google_Client();
        $client->setAssertionCredentials($credentials);
        if ($client->getAuth()->isAccessTokenExpired()) {
            $client->getAuth()->refreshTokenWithAssertion();
        }

        $tokenData = json_decode($client->getAccessToken());
        return $tokenData->access_token;
    }

    public function initialize(/*$reInitialized = false*/)
    {
        // load OAuth2 token data - exit if false
        $tokenData = $this->getToken();
        $serviceRequest = new DefaultServiceRequest($tokenData);
        ServiceRequestFactory::setInstance($serviceRequest);
        $spreadsheetService = new Google\Spreadsheet\SpreadsheetService();
        try {
            $spreadsheetFeed = $spreadsheetService->getSpreadsheets();
        } catch (\Google\Spreadsheet\UnauthorizedException $e) {    
            Google_Spreadsheet::warnAdmin($e->getMessage());
            return false;
        }

        $this->spreadsheetFeed = $spreadsheetFeed;
        return true;
    }

    public function insertRow($rowData, $default_fields = array()) {
        $spreadsheetFeed = $this->spreadsheetFeed;
        $spreadsheet = $this->spreadsheetKey ? $spreadsheetFeed->getByKey($this->spreadsheetKey) : $spreadsheetFeed->getByTitle($this->spreadsheetName);
        if(!$spreadsheet && !empty($this->spreadsheetName)) {
            $spreadsheet = $spreadsheetFeed->getByTitle($this->spreadsheetName);
        }

        if(!$spreadsheet) {
            Google_Spreadsheet::warnAdmin('No spreadsheet', serialize($rowData));
            return false;
        }

        $worksheetFeed = $spreadsheet->getWorksheets();
        $worksheet = $worksheetFeed->getByTitle($this->worksheetName);

        if(!$worksheet) {
            //create worksheet if not exist
            $worksheet = $spreadsheet->addWorksheet($this->worksheetName, $this->default['worksheetRows'], $this->default['worksheetCols']);

            $cellFeed = $worksheet->getCellFeed();
            for( $i= 1 ; $i <= $this->default['worksheetCols']; $i++ ) {
                if(isset($default_fields[$i])) {
                    $cellFeed->editCell(1, $i, $default_fields[$i]);
                }
                else {
                    $cellFeed->editCell(1, $i, "head");
                }

                $cellFeed->editCell(2,$i,"content");
            }
        }

        if(!$worksheet) {
            Google_Spreadsheet::warnAdmin('No worksheet', serialize($rowData));
            return false;
        }

        $listFeed = $worksheet->getListFeed();

        $data = array();
        foreach ($listFeed->getEntries() as $entry) {
            $values = $entry->getValues();
            $data[] = $values;
            break; //only first row needed, as we need keys
        }

        $keys = array();
        if(!count($data)) {
            Google_Spreadsheet::warnAdmin('No data', serialize($rowData));
            return false;
        }

        foreach ($data[0] as $key => $value) {
            $keys[] = $key;
        }

        $newRow = array();
        $count = 0;
        foreach($keys as $key) {
            if(isset($rowData[$count])) {
                $newRow["$key"] = $rowData[$count];
            }
            else {
                $newRow["$key"] = '';
            }

            $count++;
        }

        $listFeed->insert($newRow);
        return true;
    }


    static function warnAdmin($reason = '', $content = '') {
        //temporal function to warn myself about all the stuff happening wrong :)

    }
}

And in main model I'm using:

$spreadsheet = new Google_Spreadsheet("spreadsheet name or ID", $worksheetname, "My spreadsheet name");

        if(!$spreadsheet->initialized) {
            Google_Spreadsheet::warnAdmin('cannot initialize spreadsheet', serialize($rowValues));
        }


        if(!$spreadsheet->initialized || !$spreadsheet->insertRow($rowValues, $this->default_fields)) {
            Google_Spreadsheet::warnAdmin('failed to insert row ');
        }

@Edit, thanks to bram brambring for his token solution, seems more easier than my. Working like a charm now, I hope his way it gonna refresh token normally. THANK YOU DUDE!

Community
  • 1
  • 1
farefray
  • 16
  • 3
  • Maxim Fedan, if you can please visit my other question [link]http://stackoverflow.com/questions/30532607/copyfile-function-google-api-php if you can help me with that please – nonaxanon May 29 '15 at 14:55
  • not really worked with google drive api and never copied/created/removed :( sorry – farefray May 29 '15 at 15:09
-2

I also have had php scripts using Zend for Google Spreadsheets. They have been running great for years, but stopped working today at noon for no reason. What has changed on Google's side and how to easily fix it?

-3

That deprecated ClientLogin, it works again! It was such a surprise on the eve of the conference Google I / O? I had to write a self-made solution. Third-party libraries were in basically unusable, I wrote about 10 methods, I think it is better than the alternatives, which are too complex and cumbersome. You can buy from me)) Not yet ready to put on github)