vendor/google/apiclient/src/Service/Resource.php line 88

Open in your IDE?
  1. <?php
  2. /**
  3.  * Copyright 2010 Google Inc.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. namespace Google\Service;
  18. use Google\Exception as GoogleException;
  19. use Google\Http\MediaFileUpload;
  20. use Google\Model;
  21. use Google\Utils\UriTemplate;
  22. use GuzzleHttp\Psr7\Request;
  23. /**
  24.  * Implements the actual methods/resources of the discovered Google API using magic function
  25.  * calling overloading (__call()), which on call will see if the method name (plus.activities.list)
  26.  * is available in this service, and if so construct an apiHttpRequest representing it.
  27.  *
  28.  */
  29. class Resource
  30. {
  31.     // Valid query parameters that work, but don't appear in discovery.
  32.     private $stackParameters = [
  33.         'alt' => ['type' => 'string''location' => 'query'],
  34.         'fields' => ['type' => 'string''location' => 'query'],
  35.         'trace' => ['type' => 'string''location' => 'query'],
  36.         'userIp' => ['type' => 'string''location' => 'query'],
  37.         'quotaUser' => ['type' => 'string''location' => 'query'],
  38.         'data' => ['type' => 'string''location' => 'body'],
  39.         'mimeType' => ['type' => 'string''location' => 'header'],
  40.         'uploadType' => ['type' => 'string''location' => 'query'],
  41.         'mediaUpload' => ['type' => 'complex''location' => 'query'],
  42.         'prettyPrint' => ['type' => 'string''location' => 'query'],
  43.     ];
  44.     /** @var string $rootUrlTemplate */
  45.     private $rootUrlTemplate;
  46.     /** @var \Google\Client $client */
  47.     private $client;
  48.     /** @var string $serviceName */
  49.     private $serviceName;
  50.     /** @var string $servicePath */
  51.     private $servicePath;
  52.     /** @var string $resourceName */
  53.     private $resourceName;
  54.     /** @var array $methods */
  55.     private $methods;
  56.     public function __construct($service$serviceName$resourceName$resource)
  57.     {
  58.         $this->rootUrlTemplate $service->rootUrlTemplate ?? $service->rootUrl;
  59.         $this->client $service->getClient();
  60.         $this->servicePath $service->servicePath;
  61.         $this->serviceName $serviceName;
  62.         $this->resourceName $resourceName;
  63.         $this->methods is_array($resource) && isset($resource['methods']) ?
  64.         $resource['methods'] :
  65.         [$resourceName => $resource];
  66.     }
  67.     /**
  68.      * TODO: This function needs simplifying.
  69.      *
  70.      * @template T
  71.      * @param string $name
  72.      * @param array $arguments
  73.      * @param class-string<T> $expectedClass - optional, the expected class name
  74.      * @return mixed|T|ResponseInterface|RequestInterface
  75.      * @throws \Google\Exception
  76.      */
  77.     public function call($name$arguments$expectedClass null)
  78.     {
  79.         if (! isset($this->methods[$name])) {
  80.             $this->client->getLogger()->error(
  81.                 'Service method unknown',
  82.                 [
  83.                     'service' => $this->serviceName,
  84.                     'resource' => $this->resourceName,
  85.                     'method' => $name
  86.                 ]
  87.             );
  88.             throw new GoogleException(
  89.                 "Unknown function: " .
  90.                 "{$this->serviceName}->{$this->resourceName}->{$name}()"
  91.             );
  92.         }
  93.         $method $this->methods[$name];
  94.         $parameters $arguments[0];
  95.         // postBody is a special case since it's not defined in the discovery
  96.         // document as parameter, but we abuse the param entry for storing it.
  97.         $postBody null;
  98.         if (isset($parameters['postBody'])) {
  99.             if ($parameters['postBody'] instanceof Model) {
  100.                 // In the cases the post body is an existing object, we want
  101.                 // to use the smart method to create a simple object for
  102.                 // for JSONification.
  103.                 $parameters['postBody'] = $parameters['postBody']->toSimpleObject();
  104.             } elseif (is_object($parameters['postBody'])) {
  105.                 // If the post body is another kind of object, we will try and
  106.                 // wrangle it into a sensible format.
  107.                 $parameters['postBody'] =
  108.                     $this->convertToArrayAndStripNulls($parameters['postBody']);
  109.             }
  110.             $postBody = (array) $parameters['postBody'];
  111.             unset($parameters['postBody']);
  112.         }
  113.         // TODO: optParams here probably should have been
  114.         // handled already - this may well be redundant code.
  115.         if (isset($parameters['optParams'])) {
  116.             $optParams $parameters['optParams'];
  117.             unset($parameters['optParams']);
  118.             $parameters array_merge($parameters$optParams);
  119.         }
  120.         if (!isset($method['parameters'])) {
  121.             $method['parameters'] = [];
  122.         }
  123.         $method['parameters'] = array_merge(
  124.             $this->stackParameters,
  125.             $method['parameters']
  126.         );
  127.         foreach ($parameters as $key => $val) {
  128.             if ($key != 'postBody' && !isset($method['parameters'][$key])) {
  129.                 $this->client->getLogger()->error(
  130.                     'Service parameter unknown',
  131.                     [
  132.                         'service' => $this->serviceName,
  133.                         'resource' => $this->resourceName,
  134.                         'method' => $name,
  135.                         'parameter' => $key
  136.                     ]
  137.                 );
  138.                 throw new GoogleException("($name) unknown parameter: '$key'");
  139.             }
  140.         }
  141.         foreach ($method['parameters'] as $paramName => $paramSpec) {
  142.             if (
  143.                 isset($paramSpec['required']) &&
  144.                 $paramSpec['required'] &&
  145.                 ! isset($parameters[$paramName])
  146.             ) {
  147.                 $this->client->getLogger()->error(
  148.                     'Service parameter missing',
  149.                     [
  150.                         'service' => $this->serviceName,
  151.                         'resource' => $this->resourceName,
  152.                         'method' => $name,
  153.                         'parameter' => $paramName
  154.                     ]
  155.                 );
  156.                 throw new GoogleException("($name) missing required param: '$paramName'");
  157.             }
  158.             if (isset($parameters[$paramName])) {
  159.                 $value $parameters[$paramName];
  160.                 $parameters[$paramName] = $paramSpec;
  161.                 $parameters[$paramName]['value'] = $value;
  162.                 unset($parameters[$paramName]['required']);
  163.             } else {
  164.                 // Ensure we don't pass nulls.
  165.                 unset($parameters[$paramName]);
  166.             }
  167.         }
  168.         $this->client->getLogger()->info(
  169.             'Service Call',
  170.             [
  171.                 'service' => $this->serviceName,
  172.                 'resource' => $this->resourceName,
  173.                 'method' => $name,
  174.                 'arguments' => $parameters,
  175.             ]
  176.         );
  177.         // build the service uri
  178.         $url $this->createRequestUri($method['path'], $parameters);
  179.         // NOTE: because we're creating the request by hand,
  180.         // and because the service has a rootUrl property
  181.         // the "base_uri" of the Http Client is not accounted for
  182.         $request = new Request(
  183.             $method['httpMethod'],
  184.             $url,
  185.             $postBody ? ['content-type' => 'application/json'] : [],
  186.             $postBody json_encode($postBody) : ''
  187.         );
  188.         // support uploads
  189.         if (isset($parameters['data'])) {
  190.             $mimeType = isset($parameters['mimeType'])
  191.                 ? $parameters['mimeType']['value']
  192.                 : 'application/octet-stream';
  193.             $data $parameters['data']['value'];
  194.             $upload = new MediaFileUpload($this->client$request$mimeType$data);
  195.             // pull down the modified request
  196.             $request $upload->getRequest();
  197.         }
  198.         // if this is a media type, we will return the raw response
  199.         // rather than using an expected class
  200.         if (isset($parameters['alt']) && $parameters['alt']['value'] == 'media') {
  201.             $expectedClass null;
  202.         }
  203.         // if the client is marked for deferring, rather than
  204.         // execute the request, return the response
  205.         if ($this->client->shouldDefer()) {
  206.             // @TODO find a better way to do this
  207.             $request $request
  208.                 ->withHeader('X-Php-Expected-Class'$expectedClass);
  209.             return $request;
  210.         }
  211.         return $this->client->execute($request$expectedClass);
  212.     }
  213.     protected function convertToArrayAndStripNulls($o)
  214.     {
  215.         $o = (array) $o;
  216.         foreach ($o as $k => $v) {
  217.             if ($v === null) {
  218.                 unset($o[$k]);
  219.             } elseif (is_object($v) || is_array($v)) {
  220.                 $o[$k] = $this->convertToArrayAndStripNulls($o[$k]);
  221.             }
  222.         }
  223.         return $o;
  224.     }
  225.     /**
  226.      * Parse/expand request parameters and create a fully qualified
  227.      * request uri.
  228.      * @static
  229.      * @param string $restPath
  230.      * @param array $params
  231.      * @return string $requestUrl
  232.      */
  233.     public function createRequestUri($restPath$params)
  234.     {
  235.         // Override the default servicePath address if the $restPath use a /
  236.         if ('/' == substr($restPath01)) {
  237.             $requestUrl substr($restPath1);
  238.         } else {
  239.             $requestUrl $this->servicePath $restPath;
  240.         }
  241.         if ($this->rootUrlTemplate) {
  242.             // code for universe domain
  243.             $rootUrl str_replace('UNIVERSE_DOMAIN'$this->client->getUniverseDomain(), $this->rootUrlTemplate);
  244.             // code for leading slash
  245.             if ('/' !== substr($rootUrl, -1) && '/' !== substr($requestUrl01)) {
  246.                 $requestUrl '/' $requestUrl;
  247.             }
  248.             $requestUrl $rootUrl $requestUrl;
  249.         }
  250.         $uriTemplateVars = [];
  251.         $queryVars = [];
  252.         foreach ($params as $paramName => $paramSpec) {
  253.             if ($paramSpec['type'] == 'boolean') {
  254.                 $paramSpec['value'] = $paramSpec['value'] ? 'true' 'false';
  255.             }
  256.             if ($paramSpec['location'] == 'path') {
  257.                 $uriTemplateVars[$paramName] = $paramSpec['value'];
  258.             } elseif ($paramSpec['location'] == 'query') {
  259.                 if (is_array($paramSpec['value'])) {
  260.                     foreach ($paramSpec['value'] as $value) {
  261.                         $queryVars[] = $paramName '=' rawurlencode(rawurldecode($value));
  262.                     }
  263.                 } else {
  264.                     $queryVars[] = $paramName '=' rawurlencode(rawurldecode($paramSpec['value']));
  265.                 }
  266.             }
  267.         }
  268.         if (count($uriTemplateVars)) {
  269.             $uriTemplateParser = new UriTemplate();
  270.             $requestUrl $uriTemplateParser->parse($requestUrl$uriTemplateVars);
  271.         }
  272.         if (count($queryVars)) {
  273.             $requestUrl .= '?' implode('&'$queryVars);
  274.         }
  275.         return $requestUrl;
  276.     }
  277. }