-
Notifications
You must be signed in to change notification settings - Fork 262
/
GoogleAdsClientBuilder.php
653 lines (596 loc) · 20.3 KB
/
GoogleAdsClientBuilder.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
<?php
/*
* Copyright 2022 Google LLC
*
* 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
*
* https://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.
*/
namespace Google\Ads\GoogleAds\Lib\V17;
use Google\Ads\GoogleAds\Lib\AbstractGoogleAdsBuilder;
use Google\Ads\GoogleAds\Lib\Configuration;
use Google\Ads\GoogleAds\Lib\ConfigurationLoader;
use Google\Ads\GoogleAds\Lib\GoogleAdsBuilder;
use Google\Ads\GoogleAds\Lib\GoogleAdsMiddlewareAbstract;
use Google\Ads\GoogleAds\Util\Dependencies;
use Google\Ads\GoogleAds\Util\EnvironmentalVariables;
use Google\ApiCore\GrpcSupportTrait;
use Google\Auth\FetchAuthTokenInterface;
use Grpc\ChannelCredentials;
use Grpc\Interceptor;
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use UnexpectedValueException;
/**
* Builds Google Ads API clients.
*
* @see GoogleAdsClient
*/
final class GoogleAdsClientBuilder extends AbstractGoogleAdsBuilder
{
use GrpcSupportTrait;
private const DEFAULT_LOGGER_CHANNEL = 'google-ads';
private const DEFAULT_GRPC_CHANNEL_IS_SECURE = true;
private const DEFAULT_USE_CLOUD_ORG_FOR_API_ACCESS = false;
private $loggerFactory;
private $developerToken;
private $useCloudOrgForApiAccess;
private $loginCustomerId;
private $linkedCustomerId;
private $endpoint;
private $oAuth2Credential;
private $logger;
private $logLevel;
private $proxy;
private $transport;
private $grpcChannelIsSecure;
private $grpcChannelCredential;
private $unaryMiddlewares = [];
private $streamingMiddlewares = [];
private $grpcInterceptors = [];
private $httpHandler = null;
/** @var Dependencies $dependencies */
private $dependencies;
public function __construct(
ConfigurationLoader $configurationLoader = null,
EnvironmentalVariables $environmentalVariables = null
) {
parent::__construct($configurationLoader, $environmentalVariables);
$this->loggerFactory = new LoggerFactory();
$this->grpcChannelIsSecure = self::DEFAULT_GRPC_CHANNEL_IS_SECURE;
}
/**
* Populates this builder from the specified configuration object.
*
* @param Configuration $configuration the configuration
* @return self this builder populated from the configuration
*/
public function from(Configuration $configuration)
{
$this->developerToken =
$configuration->getConfiguration('developerToken', 'GOOGLE_ADS');
$this->useCloudOrgForApiAccess =
is_null($configuration->getConfiguration('useCloudOrgForApiAccess', 'GOOGLE_ADS'))
|| $configuration->getConfiguration('useCloudOrgForApiAccess', 'GOOGLE_ADS') === ""
? self::DEFAULT_USE_CLOUD_ORG_FOR_API_ACCESS
: filter_var(
$configuration->getConfiguration('useCloudOrgForApiAccess', 'GOOGLE_ADS'),
FILTER_VALIDATE_BOOLEAN,
// Defaults when value is not a valid boolean.
[
'options' => ['default' => self::DEFAULT_USE_CLOUD_ORG_FOR_API_ACCESS],
'flags' => FILTER_NULL_ON_FAILURE
]
);
$this->loginCustomerId = $configuration->getConfiguration('loginCustomerId', 'GOOGLE_ADS');
$this->linkedCustomerId =
$configuration->getConfiguration('linkedCustomerId', 'GOOGLE_ADS');
$this->endpoint =
$configuration->getConfiguration('endpoint', 'GOOGLE_ADS');
$this->logLevel = $configuration->getConfiguration('logLevel', 'LOGGING');
$this->logger = $this->loggerFactory->createLogger(
self::DEFAULT_LOGGER_CHANNEL,
$configuration->getConfiguration('logFilePath', 'LOGGING'),
$this->logLevel
);
$this->proxy = $configuration->getConfiguration('proxy', 'CONNECTION');
$this->transport = $configuration->getConfiguration('transport', 'CONNECTION');
$this->grpcChannelIsSecure =
is_null($configuration->getConfiguration('grpcChannelIsSecure', 'CONNECTION'))
|| $configuration->getConfiguration('grpcChannelIsSecure', 'CONNECTION') === ""
// Defaults when value is not defined or an empty string.
? self::DEFAULT_GRPC_CHANNEL_IS_SECURE
: filter_var(
$configuration->getConfiguration('grpcChannelIsSecure', 'CONNECTION'),
FILTER_VALIDATE_BOOLEAN,
// Defaults when value is not a valid boolean.
[
'options' => ['default' => self::DEFAULT_GRPC_CHANNEL_IS_SECURE],
'flags' => FILTER_NULL_ON_FAILURE
]
);
return $this;
}
/**
* Populates this builder from the specified configuration object.
*
* @param Configuration $configuration the configuration
* @return self this builder populated from the configuration
*/
public function fromEnvironmentVariablesConfiguration(Configuration $configuration)
{
$this->developerToken = $configuration->getConfiguration('DEVELOPER_TOKEN') ??
$this->developerToken;
$this->loginCustomerId = $configuration->getConfiguration('LOGIN_CUSTOMER_ID') ??
$this->loginCustomerId;
$this->linkedCustomerId = $configuration->getConfiguration('LINKED_CUSTOMER_ID') ??
$this->linkedCustomerId;
$this->endpoint = $configuration->getConfiguration('ENDPOINT') ?? $this->endpoint;
return $this;
}
/**
* Includes a developer token. This is required.
*
* @param string $developerToken
* @return self this builder
*/
public function withDeveloperToken(string $developerToken)
{
$this->developerToken = $developerToken;
return $this;
}
/**
* Sets whether this library should use Google Cloud organization for API access.
*
* @param bool $useCloudOrgForApiAccess
* @return self this builder
*/
public function usingCloudOrgForApiAccess(bool $useCloudOrgForApiAccess)
{
$this->useCloudOrgForApiAccess = $useCloudOrgForApiAccess;
return $this;
}
/**
* Sets the login customer ID for this client.
* Required for manager accounts only. When authenticating as a Google Ads manager account,
* specifies the customer ID of the authenticating manager account.
*
* <p>If your OAuth credentials are for a user with access to multiple manager accounts you must
* create a separate GoogleAdsClient instance for each manager account. Use this method to
* set each login customer ID and call build() to create a separate instance.
*
* @param int|null $loginCustomerId the login customer ID
* @return self this builder
*/
public function withLoginCustomerId(?int $loginCustomerId)
{
$this->loginCustomerId = $loginCustomerId;
return $this;
}
/**
* Sets the linked customer ID for this client.
*
* This header is only required for methods that update the resources of an entity when
* permissioned via Linked Accounts in the Google Ads UI (AccountLink resource in the Google Ads
* API). Set this value to the customer ID of the data provider that updates the resources of
* the specified customer ID. It should be set without dashes, for example: 1234567890 instead
* of 123-456-7890. Read https://support.google.com/google-ads/answer/7365001 to learn more
* about Linked Accounts.
*
* @param int|null $linkedCustomerId the linked customer ID
* @return self this builder
*/
public function withLinkedCustomerId(?int $linkedCustomerId)
{
$this->linkedCustomerId = $linkedCustomerId;
return $this;
}
/**
* Includes the Google Ads API server's base endpoint. This is optional.
*
* @param string|null $endpoint
* @return self this builder
*/
public function withEndpoint($endpoint)
{
$this->endpoint = $endpoint;
return $this;
}
/**
* Includes the OAuth2 credential to be used for authentication. This is
* required.
*
* @param FetchAuthTokenInterface $oAuth2Credential
* @return self this builder
*/
public function withOAuth2Credential(FetchAuthTokenInterface $oAuth2Credential)
{
$this->oAuth2Credential = $oAuth2Credential;
return $this;
}
/**
* Includes a logger to log requests and responses.
*
* @param LoggerInterface $logger
* @return self this builder
*/
public function withLogger(LoggerInterface $logger)
{
$this->logger = $logger;
return $this;
}
/**
* Sets the log level for Google Ads API requests and responses.
*
* @param string $logLevel the PSR-3 log level name, e.g., INFO
* @return self this builder
*/
public function withLogLevel(string $logLevel)
{
$this->logLevel = $logLevel;
return $this;
}
/**
* Sets the proxy URI for Google Ads API requests in the format protocol://user:pass@host:port.
*
* @param string $proxy the proxy URI, e.g., http://user:password@localhost:8080
* @return self this builder
*/
public function withProxy(string $proxy)
{
$this->proxy = $proxy;
return $this;
}
/**
* Sets the transport for Google Ads API requests.
*
* @param string $transport the transport type to use, supported values are `grpc` and `rest`
* @return self this builder
*/
public function withTransport(string $transport)
{
$this->transport = $transport;
return $this;
}
/**
* Sets whether the gRPC channel for Google Ads API requests is secure or not.
*
* @param bool $grpcChannelIsSecure
* @return self this builder
*/
public function withGrpcChannelIsSecure(bool $grpcChannelIsSecure)
{
$this->grpcChannelIsSecure = $grpcChannelIsSecure;
return $this;
}
/**
* Sets the gRPC channel credential for Google Ads API requests.
*
* @param ChannelCredentials $grpcChannelCredential
* @return self this builder
*/
public function withGrpcChannelCredential(ChannelCredentials $grpcChannelCredential)
{
$this->grpcChannelCredential = $grpcChannelCredential;
return $this;
}
/**
* Sets the unary middlewares for Google Ads API requests. They execute in order after the ones
* defined by the library.
*
* @param GoogleAdsMiddlewareAbstract ...$unaryMiddlewares the Google Ads unary middlewares
* @return self this builder
*/
public function withUnaryMiddlewares(GoogleAdsMiddlewareAbstract ...$unaryMiddlewares)
{
$this->unaryMiddlewares = $unaryMiddlewares;
return $this;
}
/**
* Sets the streaming middlewares for Google Ads API requests. They execute in order after the ones
* defined by the library.
*
* @param GoogleAdsMiddlewareAbstract ...$streamingMiddlewares the Google Ads streaming middlewares
* @return self this builder
*/
public function withStreamingMiddlewares(GoogleAdsMiddlewareAbstract ...$streamingMiddlewares)
{
$this->streamingMiddlewares = $streamingMiddlewares;
return $this;
}
/**
* Sets the gRPC interceptors for Google Ads API requests. They execute in order after the ones
* defined by the library.
*
* @param Interceptor ...$grpcInterceptors the gRPC interceptors
* @return self this builder
*/
public function withGrpcInterceptors(Interceptor ...$grpcInterceptors)
{
$this->grpcInterceptors = $grpcInterceptors;
return $this;
}
/**
* Sets the REST HTTP handler for Google Ads API requests.
*
* @param callable $httpHandler the HTTP handler
* @return self this builder
*/
public function withHttpHandler(callable $httpHandler)
{
$this->httpHandler = $httpHandler;
return $this;
}
/**
* Sets the Dependencies utilities for this Google Ads client builder.
*
* @param Dependencies $dependencies
* @return self this builder
*/
public function withDependencies(Dependencies $dependencies)
{
$this->dependencies = $dependencies;
return $this;
}
/**
* @see GoogleAdsBuilder::build()
*
* @return GoogleAdsClient the created Google Ads client
*/
public function build()
{
$this->defaultOptionals();
$this->validate();
return new GoogleAdsClient($this);
}
/**
* @see GoogleAdsBuilder::defaultOptionals()
*/
public function defaultOptionals()
{
$this->dependencies = $this->dependencies ?? new Dependencies();
}
/**
* @see GoogleAdsBuilder::validate()
*/
public function validate()
{
if (
!$this->useCloudOrgForApiAccess
&& (is_null($this->developerToken) || empty(trim($this->developerToken)))
) {
throw new InvalidArgumentException('A developer token must be set.');
}
if (!empty($this->loginCustomerId) && $this->loginCustomerId < 0) {
throw new InvalidArgumentException('The login customer ID must be a positive number.');
}
if (!empty($this->linkedCustomerId) && $this->linkedCustomerId < 0) {
throw new InvalidArgumentException('The linked customer ID must be a positive number.');
}
// Use parse_url instead of filter_var to do less restrict validation.
// This is because we need to allow endpoint in the form of "googleads.googleapis.com",
// but filter_var doesn't allow that.
if (!empty($this->endpoint) && parse_url($this->endpoint) === false) {
throw new InvalidArgumentException('Endpoint must be a valid URL.');
}
// For the proxy URI using filter_var is ok because the GRPC library expects the URI
// in a very specific format.
if (!empty($this->proxy) && filter_var($this->proxy, FILTER_VALIDATE_URL) === false) {
throw new InvalidArgumentException(
'Proxy must be a valid URI in the form protocol://user:pass@host:port'
);
}
if ($this->oAuth2Credential === null) {
throw new InvalidArgumentException(
'OAuth2 authentication credentials must not be null.'
);
}
if (
!empty($this->transport) && $this->transport !== 'grpc' && $this->transport !== 'rest'
) {
throw new InvalidArgumentException(
'Transport can only be set as "grpc" or "rest".'
);
}
if (
!empty($this->transport) && $this->transport === 'grpc'
) {
self::validateGrpcSupport();
}
if (is_null($this->logLevel)) {
$this->logLevel = LogLevel::INFO;
} elseif (!defined('Psr\Log\LogLevel::' . strtoupper($this->logLevel))) {
throw new InvalidArgumentException("The log level must be a valid PSR log level");
}
if (!$this->grpcChannelIsSecure && $this->grpcChannelCredential !== null) {
throw new InvalidArgumentException(
'The gRPC channel credential can only be set when the gRPC channel is set as ' .
'secure.'
);
}
if (
!empty($this->transport) && $this->transport !== 'grpc'
&& !$this->grpcChannelIsSecure
) {
throw new InvalidArgumentException(
'The gRPC channel can only be set as insecure when the transport is "grpc".'
);
}
if (
!empty($this->transport) && $this->transport !== 'grpc'
&& $this->grpcChannelCredential !== null
) {
throw new InvalidArgumentException(
'The gRPC channel credential can only be set when the transport is "grpc".'
);
}
// Check if the version of the grpc extension installed by Composer is greater than that of
// the extension installed as a system package, throw an exception to remind the user to
// upgrade.
$grpcPackageVersion = $this->dependencies->getGrpcSystemPackageVersion();
$grpcComposerVersion = $this->dependencies->getGrpcComposerVersion();
if (
!empty($grpcComposerVersion) && !empty($grpcPackageVersion)
&& version_compare($grpcComposerVersion, $grpcPackageVersion, '>')
) {
throw new UnexpectedValueException(
'The grpc extension installed by Composer has a greater version than that'
. ' installed by PECL. Upgrade the PECL extension to avoid issues caused by the'
. ' version difference. For linux, run "sudo pecl install grpc".'
);
}
}
/**
* Gets the developer token.
*
* @return string
*/
public function getDeveloperToken()
{
return $this->developerToken;
}
/**
* Returns true when this library is set to use Google Cloud organization for API access.
*
* @return bool
*/
public function useCloudOrgForApiAccess()
{
return $this->useCloudOrgForApiAccess;
}
/**
* Gets the login customer ID for this client.
*
* @return int
*/
public function getLoginCustomerId()
{
return $this->loginCustomerId;
}
/**
* Gets the linked customer ID for this client.
*
* @return int
*/
public function getLinkedCustomerId()
{
return $this->linkedCustomerId;
}
/**
* Gets the endpoint.
*
* @return string
*/
public function getEndpoint()
{
return $this->endpoint;
}
/**
* Gets the OAuth2 credential.
*
* @return FetchAuthTokenInterface
*/
public function getOAuth2Credential()
{
return $this->oAuth2Credential;
}
/**
* Gets the logger used to log requests and responses.
*
* @return LoggerInterface
*/
public function getLogger()
{
return $this->logger;
}
/**
* Gets the PSR-3 log level for Google Ads API requests and responses.
*
* @return string the log level
*/
public function getLogLevel()
{
return $this->logLevel;
}
/**
* Gets the proxy URI.
*
* @return string the proxy URI
*/
public function getProxy()
{
return $this->proxy;
}
/**
* Gets the transport.
*
* @return string the transport
*/
public function getTransport()
{
return $this->transport;
}
/**
* Returns whether the gRPC channel is secure or not.
*
* @return bool
*/
public function getGrpcChannelIsSecure()
{
return $this->grpcChannelIsSecure;
}
/**
* Gets the gRPC channel credential.
*
* @return ChannelCredentials|null
*/
public function getGrpcChannelCredential()
{
return $this->grpcChannelCredential;
}
/**
* Gets the Google Ads unary middlewares.
*
* @return GoogleAdsMiddlewareAbstract[] the Google Ads unary middlewares
*/
public function getUnaryMiddlewares()
{
return $this->unaryMiddlewares;
}
/**
* Gets the Google Ads streaming middlewares.
*
* @return GoogleAdsMiddlewareAbstract[] the Google Ads streaming middlewares
*/
public function getStreamingMiddlewares()
{
return $this->streamingMiddlewares;
}
/**
* Gets the gRPC interceptors.
*
* @return Interceptor[] the gRPC interceptors
*/
public function getGrpcInterceptors()
{
return $this->grpcInterceptors;
}
/**
* Gets the REST HTTP handler.
*
* @return callable|null the REST HTTP handler
*/
public function getHttpHandler()
{
return $this->httpHandler;
}
}