1

I'm currently working on a form in PHP which would consolidate two different tasks: booking a space for an event, and registering the event for an online calendar. I have the Google Calendar piece nailed down with the API Client for PHP, but the Calendar Resources are still proving to be a problem.

Here is some information as to where I currently am:

My current dilemma involves the data I have returned from the call. When I use Google OAuth2 Playground to make the request with the above URIs, it retrieves the XML data without an issue. When I make the same attempt in PHP, I get the data in a single string with the following format:

I know that each request will only return 100 resources per request, and both the playground and my php return what appear to be 100 entries, so it does not appear to necessarily be an authorization problem. That being said, I'm not sure what I would be doing differently than the playground.

My cURL request is the following (once retrieving the access_token):

$url = 'https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain/';

$token = json_decode($_SESSION['access_token'], true);
$access_token = $token['access_token'];
$token_type = $token['token_type'];

//open connection
$ch = curl_init();

curl_setopt_array($ch, array(
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_URL => $url,
    CURLOPT_HTTPHEADER => array('Authorization: '.$token_type.' '.$access_token,),
));

// $output contains the returned data
$output = curl_exec($ch);

if($output === false) { echo 'Curl error: ' . curl_error($ch); }
else { echo $output; }

// close curl resource to free up system resources
curl_close($ch);   

Is there something, a cURL setting or a header, that I am missing? I can't guess what it would be, especially when the Playground's request is just the following:

GET /a/feeds/calendar/resource/2.0/domain/ HTTP/1.1
Host: apps-apis.google.com
Content-length: 0
Authorization: Bearer access_token

UPDATE

Hans Z.'s answer prompted me (thank you!) to search for ways to put the XML data into an array, since I need to use the data obtained rather than display it. (My apologies for not making that clear initially.) There are a lot of posts on the subject, and after putting the output through SimpleXML, I retrieve the following as an entry for each resource (x100):

[0] => SimpleXMLElement Object
(
    [id] => https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain/579841149621
    [updated] => 2015-02-18T17:04:16.481Z
    [link] => Array
    (
        [0] => SimpleXMLElement Object
        (
            [@attributes] => Array
            (
                [rel] => self
                [type] => application/atom+xml
                [href] => https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain/579841149621
            )
        )

        [1] => SimpleXMLElement Object
        (
            [@attributes] => Array
            (
                [rel] => edit
                [type] => header('Content-type: application/xml');
                [href] => https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain/579841149621
            )
        )
    )
)

As seen above, this does not provide any information about the resource itself, such as it's name or email (or id, in any direct parse-less way). I tried running the XML output from the playground through SimpleXML and am reviving the exact same output. Assuming it to be something with SimpleXML, I did some more searches and came across this question, this question, and this blog post. I myself have been poking around with what they suggest, but with little success thus far. If anyone would like to figure it out before me (as I have to attend meetings for most of the rest of this day), here is an example of the XML structure:

<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:apps='http://schemas.google.com/apps/2006'>
    <id>https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain</id>
    <updated>2015-02-18T17:03:03.057Z</updated>
    <link rel='next' type='application/atom+xml' href='https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain/?start=579841149621'/>
    <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain'/>
    <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain'/>
    <link rel='self' type='application/atom+xml' href='https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain'/>
    <openSearch:startIndex>1</openSearch:startIndex>

    <entry>
        <id>https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain/579841149621</id>
        <updated>2015-02-18T17:03:03.056Z</updated>
        <link rel='self' type='application/atom+xml' href='https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain/579841149621'/>
        <link rel='edit' type='application/atom+xml' href='https://apps-apis.google.com/a/feeds/calendar/resource/2.0/domain/579841149621'/>

        <apps:property name='resourceId' value='579841149621'/>
        <apps:property name='resourceCommonName' value='Projector'/>
        <apps:property name='resourceEmail' value='domain_key@resource.calendar.google.com'/>
    </entry>

    //99 more times:
    <entry>
        ...
    </entry>
Community
  • 1
  • 1
Nick Mischler
  • 175
  • 5
  • 22
  • check this link for oauth client on php https://github.com/google/google-api-php-client – SGC Feb 12 '15 at 22:46
  • Are you giving token_type as "Bearer"?? – SGC Feb 12 '15 at 22:54
  • @SGC $token_type is pulled from the token obtained from using that PHP client- `$_SESSION['access_token']`- which has the value of Bearer. That is passed to the cURL call. – Nick Mischler Feb 13 '15 at 02:06
  • @SGC Correction: `$_SESSION['access_token']` is the token itself, `$_SESSION['token_type']` has the value of "Bearer". – Nick Mischler Feb 16 '15 at 20:38
  • @NickMischler: your code suggests that `$_SESSION['access_token']` is a JSON object that contains the actual access token and the token type; which is it? – Hans Z. Feb 17 '15 at 21:52
  • @HansZ.My apologies, I keep mixing them up when trying to explain here in these comments. `$_SESSION['access_token']` is decoded into an array $token, and two of the components of that array, `$token['token_type']` and `$token['access_token']`, are put into variables to authorize the cURL call. The former is "Bearer", the latter is the actual access token string. – Nick Mischler Feb 18 '15 at 16:28

2 Answers2

1

Your script works fine but you're looking at the output of the script in a browser. The browser will try and parse the XML output as HTML, leading to the observed result. Change your code so that it indicates to the browser that the response is XML as follows:

header('Content-type: application/xml');
if($output === false) { echo 'Curl error: ' . curl_error($ch); }
else { echo $output; }

or look at the output using a commandline PHP interpreter.

Edit:

You may be happier parsing JSON in PHP; you can obtain the results in JSON by adding alt=json to the request as in:

https://apps-apis.google.com/a/feeds/calendar/resource/2.0/<domain>/?alt=json

and apply $output = json_decode($output) to the output; you can then access the required data, e.g. the e-mail address of the first resource, as follows:

$output->feed->entry[0]->{'apps$property'}[2]->value 
Hans Z.
  • 50,496
  • 12
  • 102
  • 115
  • Thanks Hans Z. I neglected to mention that I'm looking to get and manipulate this data. I tried what you suggested and received a XML parsing error as the page is overall supposed to be HTML, but your answer did prompt me to do more research in line with what I need. I've updated the question with additional information should you be interested. – Nick Mischler Feb 18 '15 at 18:30
  • added sample JSON parsing – Hans Z. Feb 18 '15 at 18:45
  • Thank you. I've answered with the alternative I would rather use personally and proposed an edit to improve the readability of your example, but your answer is exactly what I needed to find. – Nick Mischler Feb 18 '15 at 22:13
0

The following is an alternative to the solution given by Hans Z. for those who would rather deal with the resources as arrays:

$array = json_decode($output, true);
$resources = $array['feed']['entry'];

foreach ($resources as $resource) {
    $id = $resource['apps$property']['0']['value'];
    $name = $resource['apps$property']['1']['value'];
    $email = $resource['apps$property']['2']['value'];

    //do something with data
}
Nick Mischler
  • 175
  • 5
  • 22