Test Setup Failed
Push — master ( f6c2b2...066293 )
by Marco
03:25
created

Client::getItems()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 22
rs 9.2
cc 1
eloc 15
nc 1
nop 2
1
<?php
2
3
namespace SeoFood\AmazonRevenue;
4
5
use Goutte\Client as HttpCrawler;
6
use GuzzleHttp\Client as HttpClient;
7
8
class Client
9
{
10
    /**
11
     * @var array
12
     */
13
    private $hostNames = [
14
        'DE' => 'partnernet.amazon.de'
15
    ];
16
17
    /**
18
     * @var HttpCrawler
19
     */
20
    private $client;
21
22
    /**
23
     * @var String
24
     */
25
    private $username;
26
27
    /**
28
     * @var String
29
     */
30
    private $password;
31
32
    /**
33
     * @var String
34
     */
35
    private $host;
36
37
    /**
38
     * @var String
39
     */
40
    private $country;
41
42
    /**
43
     * @var string
44
     */
45
    private $associateTag;
46
47
    /**
48
     * @param string $username
49
     * @param string $password
50
     * @param string $country
51
     *
52
     * @throws Exception
53
     */
54
    public function __construct($username, $password, $country = 'DE')
55
    {
56
        $this->username = $username;
57
        $this->password = $password;
58
        $this->country = $country;
59
60
        if (! array_key_exists($country, $this->hostNames)) {
61
            throw new Exception('No hostname for the given country available.');
62
        }
63
        $this->host = 'https://' . $this->hostNames[$country] . '/';
64
65
        $ua = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17';
66
        $this->client = new HttpCrawler;
67
        $this->client->setClient(new HttpClient([
68
            'cookies' => true,
69
            'debug' => false,
70
            'headers' => [
71
                'User-Agent' => $ua,
72
                'Accept-Language' => 'de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4'
73
            ]
74
        ]));
75
76
        $this->login();
77
    }
78
79
    private function login()
80
    {
81
        // send a request before the login to accept session cookies
82
        $crawler = $this->client->request('GET', $this->host);
83
84
        // login
85
        $form = $crawler->filter('form[name="sign_in"]')->form();
86
        $form['username'] = $this->username;
87
        $form['password'] = $this->password;
88
        $form['rememberMe'] = false;
89
90
        $this->client->submit($form);
0 ignored issues
show
Documentation introduced by
$form is of type array<string,string|false,{"rememberMe":"false"}>, but the function expects a object<Symfony\Component\DomCrawler\Form>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
91
92
        $this->deactivateCombinedReports();
93
    }
94
95
    /**
96
     * @param $id
97
     */
98
    public function setStore($id)
99
    {
100
        $crawler = $this->client->request('GET', $this->host . 'gp/associates/network/reports/report.html');
101
102
        $form = $crawler->filter('form[name="idbox_store_id_form"]')->form();
103
        $form['idbox_store_id'] = $id;
104
        $this->client->submit($form);
0 ignored issues
show
Documentation introduced by
$form is of type array<string,?,{"idbox_store_id":"?"}>, but the function expects a object<Symfony\Component\DomCrawler\Form>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
105
106
        $this->deactivateCombinedReports();
107
    }
108
    
109
    /**
110
     * @param \DateTime $start
111
     * @param \DateTime $end
112
     * @return array
113
     */
114
    public function getItems(\DateTime $start, \DateTime $end)
115
    {
116
        $xml = $this->client->request('GET', $this->_getTransactionUrl($start, $end));
117
118
        $items = [];
119
        $xml->filter('Items Item')->each(function ($item) use (&$items) {
120
            $amazonItem = new Item;
121
122
            $amazonItem->setAsin((string)$item->attr('ASIN'));
123
            $amazonItem->setEDate((string)$item->attr('EDate'));
124
            $amazonItem->setType((string)$item->attr('LinkType'));
125
            $amazonItem->setPrice((float)str_replace(',', '.', (string)$item->attr('Price')));
126
            $amazonItem->setCommission((float)str_replace(',', '.', (string)$item->attr('Earnings')));
127
            $amazonItem->setName((string)$item->attr('Title'));
128
            $amazonItem->setQuantity((int)$item->attr('Qty'));
129
            $amazonItem->setDate(new \DateTime((string)$item->attr('Date')));
130
131
            $items[] = $amazonItem;
132
        });
133
134
        return $items;
135
    }
136
137
    /**
138
     * @param \DateTime $start
139
     * @param \DateTime $end
140
     * @return string
141
     */
142
    private function _getTransactionUrl(\DateTime $start, \DateTime $end)
143
    {
144
        $url = $this->host . 'gp/associates/network/reports/report.html?__mk_de_%s=ÅMÅZÕÑ&idbox_tracking_id=%s&reportType=earningsReport&program=all&preSelectedPeriod=monthToDate&periodType=exact&startDay=%d&startMonth=%d&startYear=%d&endDay=%d&endMonth=%d&endYear=%d&submit.download_XML.x=84&submit.download_XML.y=4&submit.download_XML=Bericht+herunterladen+(XML)';
145
146
        return sprintf($url,
147
            strtolower($this->country),
148
            $this->associateTag,
149
            $start->format('j'),
150
            $start->format('n') - 1,
151
            $start->format('Y'),
152
            $end->format('j'),
153
            $end->format('n') - 1,
154
            $end->format('Y'));
155
    }
156
157
    /**
158
     * @param $tag string
159
     */
160
    public function setAssociateTag($tag)
161
    {
162
        $this->associateTag = $tag;
163
    }
164
165
    /**
166
     */
167
    private function deactivateCombinedReports()
168
    {
169
        $crawler = $this->client->request('GET', $this->host . 'gp/associates/network/reports/report.html');
170
171
        // always deactivate combine buttons
172
        if ($crawler->filter('input[name="combinedReports"]')->attr('checked') === 'checked') {
173
            $form = $crawler->filter('form[name="idbox_combined_reports_form"]')->form();
174
            $form['combinedReports'] = false;
175
            $this->client->submit($form);
0 ignored issues
show
Documentation introduced by
$form is of type array<string,false,{"combinedReports":"false"}>, but the function expects a object<Symfony\Component\DomCrawler\Form>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
176
        }
177
    }
178
}
179