* Copyright 2010 Google Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
if (!class_exists('UDP_Google_Client')) {
require_once dirname(__FILE__) . '/../autoload.php';
* Implements the actual methods/resources of the discovered Google API using magic function
* calling overloading (__call()), which on call will see if the method name (plus.activities.list)
* is available in this service, and if so construct an apiHttpRequest representing it.
class UDP_Google_Service_Resource
// Valid query parameters that work, but don't appear in discovery.
private $stackParameters = array(
'alt' => array('type' => 'string', 'location' => 'query'),
'fields' => array('type' => 'string', 'location' => 'query'),
'trace' => array('type' => 'string', 'location' => 'query'),
'userIp' => array('type' => 'string', 'location' => 'query'),
'quotaUser' => array('type' => 'string', 'location' => 'query'),
'data' => array('type' => 'string', 'location' => 'body'),
'mimeType' => array('type' => 'string', 'location' => 'header'),
'uploadType' => array('type' => 'string', 'location' => 'query'),
'mediaUpload' => array('type' => 'complex', 'location' => 'query'),
'prettyPrint' => array('type' => 'string', 'location' => 'query'),
/** @var string $rootUrl */
/** @var Google_Client $client */
/** @var string $serviceName */
/** @var string $servicePath */
/** @var string $resourceName */
/** @var array $methods */
public function __construct($service, $serviceName, $resourceName, $resource)
$this->rootUrl = $service->rootUrl;
$this->client = $service->getClient();
$this->servicePath = $service->servicePath;
$this->serviceName = $serviceName;
$this->resourceName = $resourceName;
$this->methods = is_array($resource) && isset($resource['methods']) ?
array($resourceName => $resource);
* TODO(ianbarber): This function needs simplifying.
* @param $expected_class - optional, the expected class name
* @return Google_Http_Request|expected_class
* @throws Google_Exception
public function call($name, $arguments, $expected_class = null)
if (! isset($this->methods[$name])) {
$this->client->getLogger()->error(
'Service method unknown',
'service' => $this->serviceName,
'resource' => $this->resourceName,
throw new Google_Exception(
"{$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.
if (isset($parameters['postBody'])) {
if ($parameters['postBody'] instanceof Google_Model) {
// In the cases the post body is an existing object, we want
// to use the smart method to create a simple object for
$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(
foreach ($parameters as $key => $val) {
if ($key != 'postBody' && ! isset($method['parameters'][$key])) {
$this->client->getLogger()->error(
'Service parameter unknown',
'service' => $this->serviceName,
'resource' => $this->resourceName,
throw new Google_Exception("($name) unknown parameter: '$key'");
foreach ($method['parameters'] as $paramName => $paramSpec) {
if (isset($paramSpec['required']) &&
$paramSpec['required'] &&
! isset($parameters[$paramName])
$this->client->getLogger()->error(
'Service parameter missing',
'service' => $this->serviceName,
'resource' => $this->resourceName,
'parameter' => $paramName
throw new Google_Exception("($name) missing required param: '$paramName'");
if (isset($parameters[$paramName])) {
$value = $parameters[$paramName];
$parameters[$paramName] = $paramSpec;
$parameters[$paramName]['value'] = $value;
unset($parameters[$paramName]['required']);
// Ensure we don't pass nulls.
unset($parameters[$paramName]);
$this->client->getLogger()->info(
'service' => $this->serviceName,
'resource' => $this->resourceName,
'arguments' => $parameters,
$url = UDP_Google_Http_REST::createRequestUri(
$httpRequest = new UDP_Google_Http_Request(
$httpRequest->setBaseComponent($this->rootUrl);
$httpRequest->setBaseComponent($this->client->getBasePath());
$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(
isset($parameters['mimeType']) ? $parameters['mimeType']['value'] : 'application/octet-stream',
$parameters['data']['value']
if (isset($parameters['alt']) && $parameters['alt']['value'] == 'media') {
$httpRequest->enableExpectedRaw();
if ($this->client->shouldDefer()) {
// If we are in batch or upload mode, return the raw request.
return $this->client->execute($httpRequest);
protected function convertToArrayAndStripNulls($o)
foreach ($o as $k => $v) {
} elseif (is_object($v) || is_array($v)) {
$o[$k] = $this->convertToArrayAndStripNulls($o[$k]);