madhabkirank / google-api-adwords-php

Automatically exported from code.google.com/p/google-api-adwords-php
0 stars 0 forks source link

Pseudo namespaces not properly creating the XML to include the serviceSelector #67

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
Which version of the library are you using?

2.7.1

Which version of PHP are you using?

5.3.6

What steps will reproduce the problem?

- Download client library
- Modify 'build.properties' to set `wsdl2php.enablePseudoNamespaces=true
`
- Initialize an instance of a class that extends AdWordsUser as $AdWordsUser
- Attempt to execute the following code within a class method:

    /**
     * Get All Campaigns associated with a login
     *
     * @param array $options
     */
    public function GetAllCampaigns( $options = array() ) {

        // Declare service
        $campaignService = $this->GetService('CampaignService', 'v201109');

        // Create selector
        $selector = $campaignService->Create('Selector');
        $selector->fields = array('Id', 'Name', 'Status', 'ServingStatus', 'StartDate', 'EndDate', 'AdServingOptimizationStatus', 'Settings', 'Amount', 'Period', 'DeliveryMethod', 'PricingModel', 'ConversionOptimizerBidType', 'DeduplicationMode', 'EnhancedCpcEnabled', 'BidCeiling', 'Eligible', 'RejectionReasons', 'Clicks', 'Impressions', 'Cost', 'AveragePosition', 'AverageCpc', 'AverageCpm', 'Ctr', 'Conversions', 'ConversionRate', 'CostPerConversion', 'ConversionsManyPerClick', 'ConversionRateManyPerClick', 'CostPerConversionManyPerClick', 'ViewThroughConversions', 'TotalConvValue', 'ValuePerConv', 'ValuePerConvManyPerClick', 'InvalidClicks', 'InvalidClickRate', 'FrequencyCapMaxImpressions', 'TimeUnit', 'Level', 'TargetGoogleSearch', 'TargetSearchNetwork', 'TargetContentNetwork', 'TargetContentContextual', 'TargetPartnerSearchNetwork');

        $selector->ordering = array($campaignService->Create('OrderBy', array('Name', 'ASCENDING') ));

        // Retrieve campaign data
        try {
            $return = $campaignService->get($selector);
            return $return;
        } catch(Exception $e) {
            die ($e->getMessage());
        }
    }

In a non-pseudo-namespaced environment, the code above generates a full request 
XML (observed as $serviceSelector->__last_request). In the build version, it 
omits the contents of <get>.

What is the expected output? What do you see instead?

A CampaignPage object should be the value of $return. Instead, and API 
Exception is thrown:

O:8:"stdClass":1:{s:17:"ApiExceptionFault";O:8:"stdClass":3:{s:7:"message";s:42:
"[RequiredError.REQUIRED @ 
serviceSelector]";s:25:"ApplicationException.Type";s:12:"ApiException";s:6:"erro
rs";O:7:"SoapVar":4:{s:8:"enc_type";i:0;s:9:"enc_value";O:33:"GoogleApiAdsAdWord
s_RequiredError":6:{s:6:"reason";s:8:"REQUIRED";s:9:"fieldPath";s:15:"serviceSel
ector";s:7:"trigger";s:0:"";s:11:"errorString";s:22:"RequiredError.REQUIRED";s:1
2:"ApiErrorType";s:13:"RequiredError";s:43:"

Please provide any additional information below.

I have previously patched my library version files to rename conflicting 
classes. While those seem to work, I'm wanting to move away from doing that if 
possible and have a more automated approach to updating the library since we 
have to do it about every six months.

I've attached a copy of my generated v201109 folder.

Original issue reported on code.google.com by stephen....@gmail.com on 6 Dec 2011 at 3:42

Attachments:

GoogleCodeExporter commented 8 years ago
Second item of reproduction steps should include '..., run /usr/local/bin/phing 
to create build.'

Original comment by stephen....@gmail.com on 6 Dec 2011 at 3:54

GoogleCodeExporter commented 8 years ago
I am not able to replicate this issue. I made the same changes, ran the same 
code under 5.3.6, and it worked fine.  Can you provide the full class that 
implements the method you pasted above, as well as the SOAP XML that is 
generated?

Original comment by ekoleda+devrel@googlers.com on 6 Dec 2011 at 6:26

GoogleCodeExporter commented 8 years ago

Original comment by ekoleda+devrel@googlers.com on 6 Dec 2011 at 6:26

GoogleCodeExporter commented 8 years ago
Request XML

v201109 (build with pseudo namespaces)
===
<?xml version="1.0" encoding="UTF-8"?>\n<SOAP-ENV:Envelope 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ns1="https://adwords.google.com/api/adwords/cm/v201109"><SOAP-ENV:Header><
ns1:RequestHeader><ns1:clientCustomerId>*[redacted]*</ns1:clientCustomerId><ns1:
developerToken>*[redacted]*</ns1:developerToken><ns1:userAgent>AwApi-PHP-2.7.2-*
[redacted]*</ns1:userAgent></ns1:RequestHeader></SOAP-ENV:Header><SOAP-ENV:Body>
<ns1:get/></SOAP-ENV:Body></SOAP-ENV:Envelope>

v201101 (patched to manually rename conflicting classes)
===
<?xml version="1.0" encoding="UTF-8"?>\n<SOAP-ENV:Envelope 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ns1="https://adwords.google.com/api/adwords/cm/v201101"><SOAP-ENV:Header><
ns1:RequestHeader><ns1:clientCustomerId>*[redacted]*</ns1:clientCustomerId><ns1:
developerToken>*[redacted]*</ns1:developerToken><ns1:userAgent>AwApi-PHP-2.7.2-*
[redacted]*</ns1:userAgent></ns1:RequestHeader></SOAP-ENV:Header><SOAP-ENV:Body>
<ns1:get><ns1:serviceSelector><ns1:fields>Id</ns1:fields><ns1:fields>Name</ns1:f
ields><ns1:fields>Status</ns1:fields><ns1:fields>ServingStatus</ns1:fields><ns1:
fields>StartDate</ns1:fields><ns1:fields>EndDate</ns1:fields><ns1:fields>AdServi
ngOptimizationStatus</ns1:fields><ns1:fields>Settings</ns1:fields><ns1:fields>Am
ount</ns1:fields><ns1:fields>Period</ns1:fields><ns1:fields>DeliveryMethod</ns1:
fields><ns1:fields>PricingModel</ns1:fields><ns1:fields>ConversionOptimizerBidTy
pe</ns1:fields><ns1:fields>DeduplicationMode</ns1:fields><ns1:fields>EnhancedCpc
Enabled</ns1:fields><ns1:fields>BidCeiling</ns1:fields><ns1:fields>Eligible</ns1
:fields><ns1:fields>RejectionReasons</ns1:fields><ns1:fields>Clicks</ns1:fields>
<ns1:fields>Impressions</ns1:fields><ns1:fields>Cost</ns1:fields><ns1:fields>Ave
ragePosition</ns1:fields><ns1:fields>AverageCpc</ns1:fields><ns1:fields>AverageC
pm</ns1:fields><ns1:fields>Ctr</ns1:fields><ns1:fields>Conversions</ns1:fields><
ns1:fields>ConversionRate</ns1:fields><ns1:fields>CostPerConversion</ns1:fields>
<ns1:fields>ConversionsManyPerClick</ns1:fields><ns1:fields>ConversionRateManyPe
rClick</ns1:fields><ns1:fields>CostPerConversionManyPerClick</ns1:fields><ns1:fi
elds>ViewThroughConversions</ns1:fields><ns1:fields>TotalConvValue</ns1:fields><
ns1:fields>ValuePerConv</ns1:fields><ns1:fields>ValuePerConvManyPerClick</ns1:fi
elds><ns1:fields>InvalidClicks</ns1:fields><ns1:fields>InvalidClickRate</ns1:fie
lds><ns1:fields>FrequencyCapMaxImpressions</ns1:fields><ns1:fields>TimeUnit</ns1
:fields><ns1:fields>Level</ns1:fields><ns1:fields>TargetGoogleSearch</ns1:fields
><ns1:fields>TargetSearchNetwork</ns1:fields><ns1:fields>TargetContentNetwork</n
s1:fields><ns1:fields>TargetContentContextual</ns1:fields><ns1:fields>TargetPart
nerSearchNetwork</ns1:fields><ns1:predicates><ns1:field>Status</ns1:field><ns1:o
perator>NOT_EQUALS</ns1:operator><ns1:values>DELETED</ns1:values></ns1:predicate
s><ns1:dateRange><ns1:min>20111105</ns1:min><ns1:max>20111205</ns1:max></ns1:dat
eRange><ns1:ordering><ns1:field>Name</ns1:field><ns1:sortOrder>ASCENDING</ns1:so
rtOrder></ns1:ordering></ns1:serviceSelector></ns1:get></SOAP-ENV:Body></SOAP-EN
V:Envelope>

Original comment by stephen....@gmail.com on 6 Dec 2011 at 6:42

GoogleCodeExporter commented 8 years ago
Can you post the full content of your source file?  If not, can you post the 
result of print_r($selector) run right before the request?  Are you 
constructing or loading other versions of the CampaignService within the same 
execution?

Original comment by ekoleda+devrel@googlers.com on 6 Dec 2011 at 10:17

GoogleCodeExporter commented 8 years ago
var_dump($selector) directly prior to $campaignService->get();

v201109 (build with pseudo namespaces)
===
object(GoogleApiAdsAdWords_Selector)#18 (5) { ["fields"]=> array(45) { [0]=> 
string(2) "Id" [1]=> string(4) "Name" [2]=> string(6) "Status" [3]=> string(13) 
"ServingStatus" [4]=> string(9) "StartDate" [5]=> string(7) "EndDate" [6]=> 
string(27) "AdServingOptimizationStatus" [7]=> string(8) "Settings" [8]=> 
string(6) "Amount" [9]=> string(6) "Period" [10]=> string(14) "DeliveryMethod" 
[11]=> string(12) "PricingModel" [12]=> string(26) "ConversionOptimizerBidType" 
[13]=> string(17) "DeduplicationMode" [14]=> string(18) "EnhancedCpcEnabled" 
[15]=> string(10) "BidCeiling" [16]=> string(8) "Eligible" [17]=> string(16) 
"RejectionReasons" [18]=> string(6) "Clicks" [19]=> string(11) "Impressions" 
[20]=> string(4) "Cost" [21]=> string(15) "AveragePosition" [22]=> string(10) 
"AverageCpc" [23]=> string(10) "AverageCpm" [24]=> string(3) "Ctr" [25]=> 
string(11) "Conversions" [26]=> string(14) "ConversionRate" [27]=> string(17) 
"CostPerConversion" [28]=> string(23) "ConversionsManyPerClick" [29]=> 
string(26) "ConversionRateManyPerClick" [30]=> string(29) 
"CostPerConversionManyPerClick" [31]=> string(22) "ViewThroughConversions" 
[32]=> string(14) "TotalConvValue" [33]=> string(12) "ValuePerConv" [34]=> 
string(24) "ValuePerConvManyPerClick" [35]=> string(13) "InvalidClicks" [36]=> 
string(16) "InvalidClickRate" [37]=> string(26) "FrequencyCapMaxImpressions" 
[38]=> string(8) "TimeUnit" [39]=> string(5) "Level" [40]=> string(18) 
"TargetGoogleSearch" [41]=> string(19) "TargetSearchNetwork" [42]=> string(20) 
"TargetContentNetwork" [43]=> string(23) "TargetContentContextual" [44]=> 
string(26) "TargetPartnerSearchNetwork" } ["predicates"]=> array(1) { [0]=> 
object(GoogleApiAdsAdWords_Predicate)#21 (3) { ["field"]=> string(6) "Status" 
["operator"]=> string(10) "NOT_EQUALS" ["values"]=> array(1) { [0]=> string(7) 
"DELETED" } } } ["dateRange"]=> object(GoogleApiAdsAdWords_DateRange)#20 (2) { 
["min"]=> string(8) "20111105" ["max"]=> string(8) "20111205" } ["ordering"]=> 
array(1) { [0]=> object(GoogleApiAdsAdWords_OrderBy)#19 (2) { ["field"]=> 
string(4) "Name" ["sortOrder"]=> string(9) "ASCENDING" } } ["paging"]=> NULL } 

v201101 (patched manually to rename conflicting classes)
===
object(Selector)#58 (5) {
["fields"]=> array(45) { [0]=> string(2) "Id" [1]=> string(4) "Name" [2]=> 
string(6) "Status" [3]=> string(13) "ServingStatus" [4]=> string(9) "StartDate" 
[5]=> string(7) "EndDate" [6]=> string(27) "AdServingOptimizationStatus" [7]=> 
string(8) "Settings" [8]=> string(6) "Amount" [9]=> string(6) "Period" [10]=> 
string(14) "DeliveryMethod" [11]=> string(12) "PricingModel" [12]=> string(26) 
"ConversionOptimizerBidType" [13]=> string(17) "DeduplicationMode" [14]=> 
string(18) "EnhancedCpcEnabled" [15]=> string(10) "BidCeiling" [16]=> string(8) 
"Eligible" [17]=> string(16) "RejectionReasons" [18]=> string(6) "Clicks" 
[19]=> string(11) "Impressions" [20]=> string(4) "Cost" [21]=> string(15) 
"AveragePosition" [22]=> string(10) "AverageCpc" [23]=> string(10) "AverageCpm" 
[24]=> string(3) "Ctr" [25]=> string(11) "Conversions" [26]=> string(14) 
"ConversionRate" [27]=> string(17) "CostPerConversion" [28]=> string(23) 
"ConversionsManyPerClick" [29]=> string(26) "ConversionRateManyPerClick" [30]=> 
string(29) "CostPerConversionManyPerClick" [31]=> string(22) 
"ViewThroughConversions" [32]=> string(14) "TotalConvValue" [33]=> string(12) 
"ValuePerConv" [34]=> string(24) "ValuePerConvManyPerClick" [35]=> string(13) 
"InvalidClicks" [36]=> string(16) "InvalidClickRate" [37]=> string(26) 
"FrequencyCapMaxImpressions" [38]=> string(8) "TimeUnit" [39]=> string(5) 
"Level" [40]=> string(18) "TargetGoogleSearch" [41]=> string(19) 
"TargetSearchNetwork" [42]=> string(20) "TargetContentNetwork" [43]=> 
string(23) "TargetContentContextual" [44]=> string(26) 
"TargetPartnerSearchNetwork" } ["predicates"]=> array(1) { [0]=> 
object(Predicate)#61 (3) { ["field"]=> string(6) "Status" ["operator"]=> 
string(10) "NOT_EQUALS" ["values"]=> array(1) { [0]=> string(7) "DELETED" } } } 
["dateRange"]=> object(DateRange)#60 (2) { ["min"]=> string(8) "20111105" 
["max"]=> string(8) "20111205" } ["ordering"]=> array(1) { [0]=> 
object(OrderBy)#59 (2) { ["field"]=> string(4) "Name" ["sortOrder"]=> string(9) 
"ASCENDING" } } ["paging"]=> NULL } 

Original comment by stephen....@gmail.com on 6 Dec 2011 at 10:29

GoogleCodeExporter commented 8 years ago
I'm always calling a service with:

->GetService('CampaignService', ADWORDS_DEFAULT_VERSION);

.. so that I can easily swap out in one constant the version I want to use 
(rather than using settings.ini) based on environment. I double checked and can 
see that all service creators are relying on this constant.

Original comment by stephen....@gmail.com on 6 Dec 2011 at 10:34

GoogleCodeExporter commented 8 years ago
Thank you for the additional information. I've been able to replicate your 
var_dump exactly, but that request runs successfully on my system. Can you send 
me a var_dump of $campaignService from right before your call?  I'm wondering 
if the classmap is not setup correctly.

Original comment by ekoleda+devrel@googlers.com on 7 Dec 2011 at 4:30

GoogleCodeExporter commented 8 years ago
I think we're on to something ... There are other services (ex. 
ServicedAccountService) that are called prior to CampaignService (both with the 
same version). But if you look in the generated classes from the build. Take a 
look at these two code blocks:

===

// ServicedAccountService.php, ~line 1142

class GoogleApiAdsAdWords_get {
  /**
   * @access public
   * @var ServicedAccountSelector
   */
  public $selector;

  /**
   * Gets the namesapce of this class
   * @return the namespace of this class
   */
  public function getNamespace() {
    return "https://adwords.google.com/api/adwords/mcm/v201109";
  }

  /**
   * Gets the xsi:type name of this class
   * @return the xsi:type name of this class
   */
  public function getXsiTypeName() {
    return "";
  }

  public function __construct($selector = NULL) {
    if(get_parent_class('GoogleApiAdsAdWords_get')) parent::__construct();
    $this->selector = $selector;
  }
}}

===

// CampaignService.php, ~line 3163

class GoogleApiAdsAdWords_get {
  /**
   * @access public
   * @var Selector
   */
  public $serviceSelector;

  /**
   * Gets the namesapce of this class
   * @return the namespace of this class
   */
  public function getNamespace() {
    return "https://adwords.google.com/api/adwords/cm/v201109";
  }

  /**
   * Gets the xsi:type name of this class
   * @return the xsi:type name of this class
   */
  public function getXsiTypeName() {
    return "";
  }

  public function __construct($serviceSelector = NULL) {
    if(get_parent_class('GoogleApiAdsAdWords_get')) parent::__construct();
    $this->serviceSelector = $serviceSelector;
  }
}}

===

The property of $selector vs. $serviceSelector may be our root cause. When I 
call $AdWordsUser->GetService('CampaignService') first in any procedure, I'm 
getting data back with v201109. Because both of these have:

if (!class_exists("GoogleApiAdsAdWords_get", FALSE)) {

... set ahead of them, only the first one would be used.

Original comment by stephen....@gmail.com on 7 Dec 2011 at 5:20

GoogleCodeExporter commented 8 years ago
Turns out, if you call CampaignService before calling ServicedAccountService, 
an internal API error is thrown on the $servicedAccountService->get();

O:8:"stdClass":1:{s:17:"ApiExceptionFault";O:8:"stdClass":3:{s:7:"message";s:129
:"InternalApiError.UNEXPECTED_INTERNAL_API_ERROR @ 
com.google.ads.api.services.common.error.InternalApiError.<init>(InternalApiErro
";s:25:"ApplicationException.Type";s:12:"ApiException";s:6:"errors";O:7:"SoapVar
":4:{s:8:"enc_type";i:0;s:9:"enc_value";O:36:"GoogleApiAdsAdWords_InternalApiErr
or":6:{s:6:"reason";s:29:"UNEXPECTED_INTERNAL_API_ERROR";s:9:"fieldPath";s:0:"";
s:7:"trigger";s:0:"";s:11:"errorString";s:46:"InternalApiError.UNEXPECTED_INTERN
AL_API_ERROR";s:12:"ApiErrorType";s:16:"InternalApiError";s:43:"

I'm thinking this must be related.

Original comment by stephen....@gmail.com on 7 Dec 2011 at 5:29

GoogleCodeExporter commented 8 years ago
Ya, I think you've found it. In the build.xml file I pass in a classmap that is 
used to rename the service's "get" type to "CampaignServieceGet" when the class 
is generated, to avoid conflicts with other services.  Currently the classmap 
is disregarded when pseudo namespaces are enabled, because there are other 
renamings that were done due to lack of namespaces.  I'll work on a solution 
and update this issue when I've found out more.

Original comment by ekoleda+devrel@googlers.com on 7 Dec 2011 at 6:11

GoogleCodeExporter commented 8 years ago
Fixed in r231. Please download the head revision (including build.xml file) and 
let me know if this resolves the issue for you.

Original comment by ekoleda+devrel@googlers.com on 8 Dec 2011 at 3:28

GoogleCodeExporter commented 8 years ago
Confirmed fix.

- Verified current issue exists as-is.
- Reset sandbox to ^HEAD
- Modified build.properties
- Ran `phing`
- Moved generated v201109/* files into place within our app.
- Confirmed current issue is resolved.

Thank you!

Original comment by stephen....@gmail.com on 8 Dec 2011 at 3:58

GoogleCodeExporter commented 8 years ago

Original comment by ekoleda+devrel@googlers.com on 8 Dec 2011 at 4:22