Completed
Branch master (e562f1)
by Antony
02:11
created

UnleashedUpdateProductTask::run()   F

Complexity

Conditions 23
Paths 96

Size

Total Lines 163
Code Lines 112

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 112
nc 96
nop 1
dl 0
loc 163
rs 3.3333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace AntonyThorpe\SilverShopUnleashed;
4
5
use Psr\Http\Message\ResponseInterface;
6
use GuzzleHttp\Exception\RequestException;
7
use DateTime;
8
use DateTimeZone;
9
use SilverStripe\Core\Convert;
10
use SilverStripe\Dev\Debug;
11
use SilverStripe\Control\Email\Email;
12
use SilverShop\Page\Product;
13
use SilverShop\Page\ProductCategory;
14
use SilverShop\Extension\ShopConfigExtension;
15
use AntonyThorpe\Consumer\Consumer;
16
use AntonyThorpe\Consumer\Utilities;
17
18
/**
19
 * Update Products with fresh data from Unleashed Inventory Management Software
20
 *
21
 * @package silvershop-unleashed
22
 * @subpackage tasks
23
 */
24
25
abstract class UnleashedUpdateProductTask extends UnleashedBuildTask
26
{
27
    /**
28
     * @var string
29
     */
30
    protected $title = "Unleashed: Update Products";
31
32
    /**
33
     * @var string
34
     */
35
    protected $description = "Update the Products in Silvershop with data from Unleashed.  Will not automatically bring over new items but will update Titles, Base Price, etc.";
36
37
    protected $email_subject = "API Unleashed Software - Update Product Results";
38
39
    public function run($request)
40
    {
41
        // Definitions
42
        $silvershopInternalItemIDMustBeUnique = Product::get()->column('InternalItemID');
43
        $silvershopTitleMustBeUnique = Product::get()->column('Title');
44
        $consumer = Consumer::get()->find('Title', 'ProductUpdate');
45
46
        // Get Products from Unleashed
47
        if (!$consumer) {
0 ignored issues
show
introduced by
$consumer is of type SilverStripe\ORM\DataObject, thus it always evaluated to true.
Loading history...
48
            $response = UnleashedAPI::sendCall(
49
                'GET',
50
                'https://api.unleashedsoftware.com/Products'
51
            );
52
53
            $apidata_array = json_decode($response->getBody()->getContents(), true);
54
            $apidata = $apidata_array['Items'];
55
            $pagination = $apidata_array['Pagination'];
56
            $numberofpages = (int) $pagination['NumberOfPages'];
57
58
            if ($numberofpages > 1) {
59
                for ($i = 2; $i <= $numberofpages; $i++) {
60
                    $response = UnleashedAPI::sendCall(
61
                        'GET',
62
                        'https://api.unleashedsoftware.com/Products/' . $i
63
                    );
64
                    $apidata_array = json_decode($response->getBody()->getContents(), true);
65
                    $apidata = array_merge($apidata, $apidata_array['Items']);
66
                }
67
            }
68
        } else {
69
            $query = [];
70
            $date = new DateTime($consumer->ExternalLastEdited);
71
            $date->setTimezone(new DateTimeZone("UTC"));  // required for Unleashed Products (not for other endpoints)
72
            $query['modifiedSince'] = substr($date->format('Y-m-d\TH:i:s.u'), 0, 23);
73
74
            $response = UnleashedAPI::sendCall(
75
                'GET',
76
                'https://api.unleashedsoftware.com/Products',
77
                ['query' => $query]
78
            );
79
80
            $apidata_array = json_decode($response->getBody()->getContents(), true);
81
            $apidata = $apidata_array['Items'];
82
            $pagination = $apidata_array['Pagination'];
83
            $numberofpages = (int) $pagination['NumberOfPages'];
84
85
            if ($numberofpages > 1) {
86
                for ($i = 2; $i <= $numberofpages; $i++) {
87
                    $response = UnleashedAPI::sendCall(
88
                        'GET',
89
                        'https://api.unleashedsoftware.com/Products/' . $i,
90
                        ['query' => $query]
91
                    );
92
                    $apidata_array = json_decode($response->getBody()->getContents(), true);
93
                    $apidata = array_merge($apidata, $apidata_array['Items']);
94
                }
95
            }
96
        }
97
98
        $this->log('<h2>Preliminary Checks</h2>');
99
        // Check for duplicates in DataList before proceeding further
100
        $duplicates = Utilities::getDuplicates($silvershopInternalItemIDMustBeUnique);
101
        if (!empty($duplicates)) {
102
            echo "<h2>Duplicate check of Product InternalItemID within Silvershop</h2>";
103
            foreach ($duplicates as $duplicate) {
104
                $this->log($duplicate);
105
            }
106
            $this->log('Please remove duplicates from Silvershop before running this Build Task');
107
            $this->log('Exit');
108
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
109
        } else {
110
            $this->log('No duplicate found');
111
        }
112
113
        $duplicates = Utilities::getDuplicates($silvershopTitleMustBeUnique);
114
        if (!empty($duplicates)) {
115
            echo "<h2>Duplicate check of Product Titles within Silvershop</h2>";
116
            foreach ($duplicates as $duplicate) {
117
                $this->log($duplicate);
118
            }
119
            $this->log('Please remove duplicates from Silvershop before running this Build Task');
120
            $this->log('Exit');
121
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
122
        } else {
123
            $this->log('No duplicate found');
124
        }
125
126
        // Check for duplicates in apidata before proceeding further
127
        $duplicates = Utilities::getDuplicates(array_column($apidata, 'ProductCode'));
128
        if (!empty($duplicates)) {
129
            echo "<h2>Duplicate check of ProductCode within Unleashed</h2>";
130
            foreach ($duplicates as $duplicate) {
131
                $this->log(htmlspecialchars($duplicate, ENT_QUOTES, 'utf-8'));
132
            }
133
            $this->log(
134
                'Please remove duplicates from Unleashed before running this Build Task'
135
            );
136
            $this->log('Exit');
137
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
138
        } else {
139
            $this->log('No duplicate found');
140
        }
141
142
        // Update
143
        $this->log('<h3>Update Product records in Silvershop</h3>');
144
        $loader = ProductBulkLoader::create('SilverShop\Page\Product');
145
        $loader->transforms = [
146
            'Parent' => [
147
                'callback' => function ($value) {
148
                    $obj = ProductCategory::get()->find('Guid', $value['Guid']);
149
                    if ($obj) {
150
                        return $obj;
151
                    } else {
152
                        return ProductCategory::get()->find('Title', $value['GroupName']);
153
                    }
154
                }
155
            ],
156
            'BasePrice' => [
157
                'callback' => function ($value) {
158
                    return (float)$value;
159
                }
160
            ],
161
            'Title' => [
162
                'callback' => function ($value, &$placeholder) {
163
                    $placeholder->URLSegment = Convert::raw2url($value);
164
                    return $value;
165
                }
166
            ]
167
        ];
168
        $results = $loader->updateRecords($apidata, $this->preview);
169
170
        if ($results->UpdatedCount()) {
171
            $this->log(Debug::text($results->getData()));
172
        }
173
        $this->log("Done");
174
        Debug::show($results->Count());
175
        Debug::show(!$this->preview);
176
        Debug::show(Email::config()->admin_email);
177
        Debug::show($this->email_subject);
178
        // Send email
179
        if ($results->Count() && !$this->preview && Email::config()->admin_email && $this->email_subject) {
180
            // send email
181
            $email = Email::create(
182
                ShopConfigExtension::config()->email_from ? ShopConfigExtension::config()->email_from : Email::config()->admin_email,
183
                Email::config()->admin_email,
184
                $this->email_subject,
185
                Debug::text($results->getData())
186
            );
187
            $dispatched = $email->send();
188
            if ($dispatched) {
189
                $this->log('Email sent');
190
            }
191
        }
192
193
        if (!$this->preview && $apidata) {
194
            if (!$consumer) {
0 ignored issues
show
introduced by
$consumer is of type SilverStripe\ORM\DataObject, thus it always evaluated to true.
Loading history...
195
                $consumer = Consumer::create([
196
                    'Title' => 'ProductUpdate',
197
                    'ExternalLastEditedKey' => 'LastModifiedOn'
198
                ]);
199
            }
200
            $consumer->setMaxExternalLastEdited($apidata);
201
            $consumer->write();
202
        }
203
    }
204
}
205