davidtsadler / ebay-sdk-php

An eBay SDK for PHP. Use the eBay API in your PHP projects.
Apache License 2.0
349 stars 341 forks source link

FindProduct by type in Shopping API is not correct #200

Closed krydos closed 6 years ago

krydos commented 6 years ago

Hi @davidtsadler, thank you for the great package.

I'm currently trying to use Find Product Shopping API and I want to find a product by ProductID. But unfortunately can't make it working.

The issue is ebay documentation asks me to pass type attribute (for ProductID). The src/Shopping/Types/FindProductsRequestType.php has ProductIDType class as a type of ProductID. Unfortunately there is no type property defined in ProductIDType (of shopping api) and of course I can't pass it.

I was trying to redefine ProductIDType with my own class but it doesn't work since type check is there. Assigning false value to Sdk::$STRICT_PROPERTY_TYPES doesn't work as well because checkPropertyType function is going to return false only for basic types (int, string, etc...).

Is there any way I can extend a class from SDK and pass it to the request without type checking?

P.S. Let me know if I described it in a bit complex way, I'll try to do it better.

krydos commented 6 years ago

ok, I was able to fix it with composer.json and psr-4

basically I've added this:

        "psr-4": {
          "DTS\\eBaySDK\\Shopping\\": "myapp/sdkfixes"
        }

and in myapp/sdkfixes I've added Types directory with ProductIDType class. So composer helped a lot and it uses my own implementation before the original implementation which is good.

Feel free to close the issue if there is no better solution for now.

davidtsadler commented 6 years ago

The SDK is generated from the eBay WSDLs. I agree that the type attribute should be a member of the class. I'll need to look into why the code generator is not picking that property up from the WSDLs.

krydos commented 6 years ago

cool, thank you @davidtsadler is there any way I can help? I was trying to find the code that generates the repo code from WSDL (as you've mentioned) but wasn't able to find it.

ChangePlaces commented 6 years ago

Yep I'm hitting the same problem and was pulling my hair out until I found this issue! I'm guessing the problem is something to do with type as the name, and used as an attribute in the xml? Should ProductIDType be in this file: https://github.com/davidtsadler/ebay-api-sdk-php/blob/master/wsdls_meta/CatalogTypes ?

<xs:complexType name="ProductIDType">
        <xs:annotation>
            <xs:documentation>
                Product ID has an attribute of ProductIDCodeType and a string value.
            </xs:documentation>
        </xs:annotation>
        <xs:simpleContent>
            <xs:extension base="xs:string">
                <xs:attribute name="type" type="ns:ProductIDCodeType">
                    <xs:annotation>
                        <xs:documentation>
                            The nature of identifier being used. For FindHalfProducts and FindProducts, only Reference, ISBN, UPC, and EAN are supported. Required when ProductID is specified.
                        </xs:documentation>
                        <xs:appinfo>
                            <CallInfo>
                                <CallName>FindHalfProducts</CallName>
                                <CallName>FindProducts</CallName>
                                <AllValuesExcept>CatalogItem, Keywords</AllValuesExcept>
                                <RequiredInput>Conditionally</RequiredInput>
                                <Returned>Always</Returned>
                            </CallInfo>
                            <CallInfo>
                                <DeprecationVersion>971</DeprecationVersion>
                                <EndOfLifeVersion>981</EndOfLifeVersion>
                        <DeprecationDetails>Avoid</DeprecationDetails>
                                <CallName>FindReviewsAndGuides</CallName>
                                <AllValuesExcept>CatalogItem, Keywords</AllValuesExcept>
                                <RequiredInput>Conditionally</RequiredInput>
                            </CallInfo>
                            <CallInfo>
                                <DeprecationVersion>971</DeprecationVersion>
                                <EndOfLifeVersion>981</EndOfLifeVersion>
                        <DeprecationDetails>Avoid</DeprecationDetails>
                                <CallName>FindReviewsAndGuides</CallName>
                                <Returned>Conditionally</Returned>
                            </CallInfo>
                        </xs:appinfo>
                    </xs:annotation>
                </xs:attribute>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>

After searching a bit, I'm guessing the real problem is in the xsl transformation file. Can you slot an if/else in the type: / `name="foo" section? I don't have access to a node setup to do any testing

<xsl:template match="*:element|*:attribute" mode="properties">
  <xsl:variable name="type" as="xs:string">
    <xsl:choose>
      <xsl:when test="@type">
        <xsl:value-of select="substring-after(@type, ':')"/>
      </xsl:when>
      <xsl:otherwise><xsl:value-of select="@name"/></xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:variable name="restriction" as="xs:string">
    <xsl:choose>
      <xsl:when test="//*:simpleType[@name=$type]/*:restriction/@base">
        <xsl:value-of select="substring-after(//*:simpleType[@name=$type]/*:restriction/@base, ':')"/>
      </xsl:when>
      <xsl:otherwise><xsl:text/></xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:variable name="restrictionIsEnum" as="xs:boolean">
    <xsl:choose>
      <xsl:when test="//*:simpleType[@name=$type]/*:restriction[*:enumeration]">
        <xsl:copy-of select="true()"/>
      </xsl:when>
      <xsl:otherwise><xsl:copy-of select="false()"/></xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:element name="property">
    <!--
      Converts
        FooBar into fooBar.
        FOO into foo.
        foo into foo.
        FOOBar into fooBar.
        eBay into eBay.
    -->
    <xsl:attribute name="name" select="@name"/>
    <xsl:attribute name="actual-name" select="@name"/>
    <xsl:attribute name="property-type" select="dts:type_to_datatype($type, $restriction, $restrictionIsEnum, true())"/>
    <xsl:attribute name="is-attribute" select="local-name()='attribute'"/>
    <xsl:attribute name="actual-type" select="if ($restriction != '')
                                                then dts:type_to_datatype($restriction, '', false(), false())
                                                else dts:type_to_datatype($type, '', false(), false())"/>
    <xsl:attribute name="repeatable" select="@maxOccurs = 'unbounded' or @maxOccurs > 1 or xs:annotation/xs:appinfo//*:MaxOccurs > 1"/>
  </xsl:element>
</xsl:template>