Skip to content
This repository has been archived by the owner on Jun 13, 2021. It is now read-only.

Commit

Permalink
Merge branch 'release-15.0.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
David T. Sadler committed Mar 5, 2018
2 parents 927d0ee + 031daa8 commit 2bc1b2f
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 6 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,11 @@
# CHANGELOG

## 15.0.0 - 2018-03-05

### Fixes

- Use multipart/form-data when uploading pictures via the Trading UploadSiteHostedPictures operation.

## 14.0.0 - 2017-12-15

### Features
Expand Down
2 changes: 1 addition & 1 deletion src/Sdk.php
Expand Up @@ -30,7 +30,7 @@
*/
class Sdk
{
const VERSION = '14.0.0';
const VERSION = '15.0.0';

/**
* @var bool Controls if the SDK should enforce strict types
Expand Down
46 changes: 42 additions & 4 deletions src/Services/BaseService.php
Expand Up @@ -199,7 +199,7 @@ private function getUrl()
*
* @return string The request body.
*/
private function buildRequestBody(\DTS\eBaySDK\Types\BaseType $request)
protected function buildRequestBody(\DTS\eBaySDK\Types\BaseType $request)
{
if (!$request->hasAttachment()) {
return $request->toRequestXml();
Expand Down Expand Up @@ -230,7 +230,7 @@ private function buildXopDocument(\DTS\eBaySDK\Types\BaseType $request)
/**
* Builds the attachment part of the request body string.
*
* @param array $attachment The attachement
* @param array $attachment The attachment
*
* @return string The attachment part of request body.
*/
Expand All @@ -247,6 +247,44 @@ private function buildAttachmentBody(array $attachment)
);
}

/**
* Builds the XML payload part of a multipart/form-data request body.
*
* @param \DTS\eBaySDK\Types\BaseType $request Request object containing the request information.
*
* @return string The XML payload part of a multipart/form-data request body.
*/
protected function buildMultipartFormDataXMLPayload(\DTS\eBaySDK\Types\BaseType $request)
{
return sprintf(
'%s%s%s',
'--boundary'.self::CRLF,
'Content-Disposition: form-data; name="XML Payload"'.self::CRLF.self::CRLF,
$request->toRequestXml().self::CRLF
);
}


/**
* Builds the file part of a multipart/form-data request body.
*
* @param string $name
* @param array $attachment
*
* @return string The file part of a multipart/form-data request body.
*/
protected function buildMultipartFormDataFilePayload($name, $attachment)
{
return sprintf(
'%s%s%s%s%s',
'--boundary'.self::CRLF,
'Content-Disposition: form-data; name="'.$name.'"; filename="picture"'.self::CRLF,
'Content-Type: '.$attachment['mimeType'].self::CRLF.self::CRLF,
$attachment['data'].self::CRLF,
'--boundary--'
);
}

/**
* Helper function that builds the HTTP request headers.
*
Expand All @@ -258,7 +296,7 @@ private function buildAttachmentBody(array $attachment)
*/
private function buildRequestHeaders($name, $request, $body)
{
$headers = $this->getEbayHeaders($name);
$headers = [];

if ($request->hasAttachment()) {
$headers['Content-Type'] = 'multipart/related;boundary=MIME_boundary;type="application/xop+xml";start="<request.xml@devbay.net>";start-info="text/xml"';
Expand All @@ -272,7 +310,7 @@ private function buildRequestHeaders($name, $request, $body)

$headers['Content-Length'] = strlen($body);

return $headers;
return array_merge($headers, $this->getEbayHeaders($name));
}

/**
Expand Down
25 changes: 25 additions & 0 deletions src/Trading/Services/TradingBaseService.php
@@ -1,6 +1,8 @@
<?php
namespace DTS\eBaySDK\Trading\Services;

use DTS\eBaySDK\Trading\Types;

/**
* Base class for the Trading service.
*/
Expand Down Expand Up @@ -154,6 +156,29 @@ protected function getEbayHeaders($operationName)
$headers[self::HDR_AUTHORIZATION] = $this->getConfig('authorization');
}

/**
* Note that we have no way of detecting that the actual request has an attachment.
*/
if ($operationName === 'UploadSiteHostedPictures') {
$headers['Content-Type'] = 'multipart/form-data;boundary="boundary"';
}

return $headers;
}

/**
* Builds the request body string.
*
* @param \DTS\eBaySDK\Types\BaseType $request Request object containing the request information.
*
* @return string The request body.
*/
protected function buildRequestBody(\DTS\eBaySDK\Types\BaseType $request)
{
if ($request->hasAttachment() && $request instanceof Types\UploadSiteHostedPicturesRequestType) {
return $this->buildMultipartFormDataXMLPayload($request).$this->buildMultipartFormDataFilePayload($request->PictureName, $request->attachment());
} else {
return parent::buildRequestBody($request);
}
}
}
11 changes: 11 additions & 0 deletions test/Mocks/MultipartFormDataRequest
@@ -0,0 +1,11 @@
--boundary
Content-Disposition: form-data; name="XML Payload"

<?xml version="1.0" encoding="UTF-8"?>
<UploadSiteHostedPicturesRequest xmlns="urn:ebay:apis:eBLBaseComponents"><PictureName>Example Picture</PictureName></UploadSiteHostedPicturesRequest>
--boundary
Content-Disposition: form-data; name="Example Picture"; filename="picture"
Content-Type: image/jpeg

ABC123
--boundary--
54 changes: 54 additions & 0 deletions test/Trading/Services/MultipartFormDataTest.php
@@ -0,0 +1,54 @@
<?php
namespace DTS\eBaySDK\Types\Test;

use DTS\eBaySDK\Trading\Services;
use DTS\eBaySDK\Trading\Types;
use DTS\eBaySDK\Test\Mocks\HttpHandler;

class MultipartFormDataTest extends \PHPUnit_Framework_TestCase
{
private $httpHandler;
private $service;
private $request;
private $requestXml;

protected function setUp()
{
/**
* Use a class that will fake sending requests and getting responses.
* The idea is that all the information needed to make the request is
* passed to the client by the service. What we want to test is that the
* is actually passed correctly. We are not testing the sending of the request
* over the internet.
* The HttpHandler contains properties that will be set when the service
* makes the request. We can test these properties to check what the service is passing.
*/
$this->httpHandler = new HttpHandler();
$this->service = new Services\TradingService([
'apiVersion' => '123',
'credentials' => ['appId' => '', 'certId' => '', 'devId' => ''],
'siteId' => 0,
'httpHandler' => $this->httpHandler
]);
$this->request = new Types\UploadSiteHostedPicturesRequestType();
$this->request->PictureName = 'Example Picture';
$this->requestXml = rtrim(file_get_contents(__DIR__.'/../../Mocks/MultipartFormDataRequest'));
}

public function testHttpHeadersAreCreated()
{
$this->request->attachment('ABC123', 'image/jpeg');
$this->service->uploadSiteHostedPictures($this->request);
$this->assertArrayHasKey('Content-Type', $this->httpHandler->headers);
$this->assertEquals('multipart/form-data;boundary="boundary"', $this->httpHandler->headers['Content-Type']);
$this->assertArrayHasKey('Content-Length', $this->httpHandler->headers);
$this->assertEquals(strlen($this->requestXml), $this->httpHandler->headers['Content-Length']);
}

public function testMultipartFormDataIsCreated()
{
$this->request->attachment('ABC123', 'image/jpeg');
$this->service->uploadSiteHostedPictures($this->request);
$this->assertEquals($this->requestXml, $this->httpHandler->body);
}
}
2 changes: 1 addition & 1 deletion test/Types/AttachmentTest.php
Expand Up @@ -18,7 +18,7 @@ protected function setUp()
* Use a class that will fake sending requests and getting responses.
* The idea is that all the information needed to make the request is
* passed to the client by the service. What we want to test is that the
* is actualy passed correctly. We are not testing the sending of the request
* is actually passed correctly. We are not testing the sending of the request
* over the internet.
* The HttpHandler contains properties that will be set when the service
* makes the request. We can test these properties to check what the service is passing.
Expand Down

0 comments on commit 2bc1b2f

Please sign in to comment.