Subversion Repositories cheapmusic

Rev

Rev 134 | Rev 141 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
81 - 1
<?php
2
include_once ('php/constants.php');
3
 
4
error_reporting(E_ALL);
5
 
6
// Get itunes listings
7
function get_amazon($query, $searchCondition) {
8
    $vendors = Vendors::getInstance();
9
    $config = $vendors->getVendor(Vendors::AMAZON);
10
 
11
    $needMatches = empty($_SESSION["discogs"]);
12
    $arrMusic = [];
13
    $arrDigital = [];
82 - 14
    $arrBooks = [];
81 - 15
 
16
    // Music
17
    $arrMusic = get_amazonCategory($config, $query, "Music", $needMatches);
18
 
19
    // Digital Music
20
    if ($_SESSION["filterMediaType"]["Digital"]) {
99 - 21
        $arrDigital = get_amazonCategory($config, $query, "DigitalMusic");
81 - 22
    }
23
 
24
    if ($_SESSION["filterMediaType"]["Book"]) {
25
        // Books
26
        $arrBooks = get_amazonCategory($config, $query, "Books");
27
    }
28
 
29
    return (array_merge($arrMusic, $arrDigital, $arrBooks));
30
}
31
 
32
// Get Amazon listings
33
function get_amazonCategory($config, $query, $searchIndex, $needMatches = false) {
94 - 34
    $numResults = $config['numResults'];
81 - 35
 
36
    if ($needMatches) {
37
        $_SESSION["discogs"] = "";
38
    }
39
 
99 - 40
    $response = getSearchCache("amazon", $query, $searchIndex);
41
    if ($response === false) {
42
        $serviceName = "ProductAdvertisingAPI";
43
        $region = "us-east-1";
44
        $accessKey = $config["access_key_id"];
45
        $secretKey = $config["secret_key"];
46
        $associate_tag = $config['associate_tag'];
47
$payload="{"
48
        ." \"Keywords\": \"$query\","
49
        ." \"Resources\": ["
50
        ."  \"Images.Primary.Medium\","
51
        ."  \"Images.Primary.Large\","
52
        ."  \"ItemInfo.ByLineInfo\","
53
        ."  \"ItemInfo.ContentInfo\","
54
        ."  \"ItemInfo.Classifications\","
55
        ."  \"ItemInfo.ExternalIds\","
56
        ."  \"ItemInfo.ManufactureInfo\","
57
        ."  \"ItemInfo.ProductInfo\","
58
        ."  \"ItemInfo.TechnicalInfo\","
59
        ."  \"ItemInfo.Title\","
60
        ."  \"Offers.Listings.Condition\","
61
        ."  \"Offers.Listings.Condition.SubCondition\","
62
        ."  \"Offers.Listings.DeliveryInfo.IsAmazonFulfilled\","
63
        ."  \"Offers.Listings.DeliveryInfo.IsFreeShippingEligible\","
64
        ."  \"Offers.Listings.DeliveryInfo.IsPrimeEligible\","
65
        ."  \"Offers.Listings.DeliveryInfo.ShippingCharges\","
66
        ."  \"Offers.Listings.MerchantInfo\","
67
        ."  \"Offers.Listings.Price\""
68
        ." ],"
69
        ." \"SearchIndex\": \"$searchIndex\","
70
        ." \"Availability\": \"Available\","
71
        ." \"Condition\": \"Any\","
72
        ." \"OfferCount\": 3,"
73
        ." \"SortBy\": \"Price:LowToHigh\","
74
        ." \"PartnerTag\": \"$associate_tag\","
75
        ." \"PartnerType\": \"Associates\","
76
        ." \"Marketplace\": \"www.amazon.com\""
77
        ."}";
78
        $host = "webservices.amazon.com";
79
        $uriPath = "/paapi5/searchitems";
81 - 80
 
99 - 81
        $awsv4 = new AwsV4($accessKey, $secretKey);
82
        $awsv4->setRegionName($region);
83
        $awsv4->setServiceName($serviceName);
84
        $awsv4->setPath($uriPath);
85
        $awsv4->setPayload($payload);
86
        $awsv4->setRequestMethod("POST");
87
        $awsv4->addHeader('content-encoding', 'amz-1.0');
88
        $awsv4->addHeader('content-type', 'application/json; charset=utf-8');
89
        $awsv4->addHeader('host', $host);
90
        $awsv4->addHeader('x-amz-target', 'com.amazon.paapi5.v1.ProductAdvertisingAPIv1.SearchItems');
91
        $headers = $awsv4->getHeaders();
92
        $headerArr = [];
93
        foreach ($headers as $key => $value) {
94
            $headerArr[] = $key . ': ' . $value;
95
        }
81 - 96
 
99 - 97
        $ch = curl_init();
98
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArr);
99
        curl_setopt($ch, CURLOPT_URL, 'https://' . $host . $uriPath);
100
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
101
        curl_setopt($ch, CURLOPT_TIMEOUT, 15);
102
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
103
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
104
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
105
        curl_setopt($ch, CURLOPT_REFERER, 'https://' . $host . $uriPath);
106
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
107
        curl_setopt($ch, CURLOPT_POST, 1);
108
        $response = curl_exec($ch);
109
        curl_close($ch);
81 - 110
 
99 - 111
        saveSearchCache("amazon", $query, $searchIndex, $response);
81 - 112
    }
113
 
99 - 114
    $parsed_json = json_decode($response);
115
//echo "<br><pre>";print_r($parsed_json);echo "</pre>";
116
    $arr = [];
81 - 117
 
99 - 118
    if (isset($parsed_json->Errors)) {
119
        foreach ($parsed_json->Errors as $error) {
120
            if ($error->Code != "NoResults") {
121
                my_error_log("Amazon Search - " . $error->Message . " (" . $error->Code . ")");
122
            }
123
        }
124
        return [];
106 - 125
    } else if (!isset($parsed_json->SearchResult)) {
126
        my_error_log("Amazon Search - No Search Result.");
127
        return [];
99 - 128
    }
81 - 129
 
99 - 130
    if ($needMatches) {
131
        $cnt = 0;
127 - 132
 
133
        $xh = new Html;
134
        $xh->init($_SESSION["htmlIndent"]);
135
        startMatches($xh);
99 - 136
    }
81 - 137
 
99 - 138
    $listings = 0;
139
    // If the response was loaded, parse it and store in array
140
    foreach ($parsed_json->SearchResult->Items as $current) {
141
        if (isset($current->ItemInfo->ExternalIds->UPCs)) {
142
            $barcode = (string)$current->ItemInfo->ExternalIds->UPCs->DisplayValues[0];
143
        }
144
        else if (isset($current->ItemInfo->ExternalIds->EANs)) {
145
            $barcode = (string)$current->ItemInfo->ExternalIds->EANs->DisplayValues[0];
146
        }
147
        else if (isset($current->ItemInfo->ExternalIds->ISBNs)) {
148
            $barcode = (string)$current->ItemInfo->ExternalIds->ISBNs->DisplayValues[0];
149
        }
150
        else if (isset($current->ItemInfo->ExternalIds->EISBNs)) {
151
            $barcode = (string)$current->ItemInfo->ExternalIds->EISBNs->DisplayValues[0];
152
        }
153
        else {
154
            $barcode = "";
155
        }
156
        $barcodeType = clsLibGTIN::GTINCheck($barcode, false, 1);
81 - 157
 
102 - 158
        $pic = !empty($current->Images->Primary->Medium->URL) ? (string)$current->Images->Primary->Medium->URL : "images/no-image-available.jpg";
100 - 159
        $pic = str_replace('http://', 'https://', $pic);
99 - 160
        if (empty($pic)) {
161
            continue;
162
        }
81 - 163
 
99 - 164
        if (strpos($current->ItemInfo->Classifications->Binding->DisplayValue, "Audio CD") !== false) {
165
            $mediaType = "CD";
166
        }
167
        else if (strpos($current->ItemInfo->Classifications->Binding->DisplayValue, "MP3 Music") !== false) {
168
            $mediaType = "Digital";
169
        }
170
        else if (strpos($current->ItemInfo->Classifications->Binding->DisplayValue, "Vinyl") !== false) {
171
            $mediaType = "Record";
172
        }
173
        else if (strpos($current->ItemInfo->Classifications->Binding->DisplayValue, "Paperback") !== false || strpos($current->ItemInfo->Classifications->Binding->DisplayValue, "Sheet") !== false || strpos($current->ItemInfo->Classifications->Binding->DisplayValue, "Hardcover") !== false) {
174
            $mediaType = "Book";
175
        }
176
        else {
177
            continue;
178
        }
81 - 179
 
180
        if ($needMatches) {
99 - 181
            // bugbug: check maxMasterCnt?
130 - 182
            addMatch($xh, $current, ++$cnt, $mediaType);
81 - 183
        }
184
 
99 - 185
        $title = (string)$current->ItemInfo->Title->DisplayValue;
186
        $artists = getArtists($current);
187
        $contributers = getContributers($current);
188
        if (!empty($artists)) {
189
            $title .= " by " . join(", ", $artists);
190
        }
191
        else if (!empty($contributers)) {
192
            $title .= " by " . join(", ", $contributers);
193
        }
81 - 194
 
99 - 195
        $url = str_replace('http://', 'https://', (string)$current->DetailPageURL);
81 - 196
 
99 - 197
        if (empty($url)) {
198
            continue;
199
        }
81 - 200
 
99 - 201
        $bestOffer = false;
81 - 202
 
99 - 203
        $url = str_replace('http://', 'https://', (string)$current->DetailPageURL);
204
        $url .= "&condition=";
81 - 205
 
99 - 206
        if (!empty($current->Offers->Listings)) {
207
            foreach ($current->Offers->Listings as $offer) {
208
                $country = 'US';
209
                if (isset($offer->MerchantInfo->DefaultShippingCountry)) {
210
                    $country = $offer->MerchantInfo->DefaultShippingCountry;
211
                }
212
                $merchantName = "Amazon";
213
                if (strpos($offer->MerchantInfo->Name, "Amazon") === false) {
214
                    $merchantName .= " Marketplace";
215
                }
81 - 216
 
99 - 217
                $condition = (string)$offer->Condition->Value;
218
                $url .= $condition;
219
                $detailCondition = $condition;
220
                if ($condition == "Collectible") {
221
                    $condition = 'Used';
222
                    $detailCondition = "Collectible";
223
                }
224
                if ($condition == "Refurbished") {
225
                    $condition = 'Used';
226
                    $detailCondition = "Refurbished";
227
                }
228
                $currency = (string)$offer->Price->Currency;
229
                $price = number_format(floatval($offer->Price->Amount) , 2, '.', '');
81 - 230
 
99 - 231
                if ($price <= "0.00") {
232
                    continue;
233
                }
81 - 234
 
99 - 235
                $timeLeft = 0;
236
                $listingType = 'Fixed';
237
                $location = 'US';
238
                $zip = '';
239
                $feedbackScore = - 1;
240
                $feedbackPercent = - 1;
241
                $sellerName = "";
242
                $handlingTime = 0;
243
                if ($offer->DeliveryInfo->IsPrimeEligible === true) {
244
                    $sellerName = "Prime";
81 - 245
                }
99 - 246
                if ($mediaType == "Digital") {
247
                    $shippingCost = 0.00;
248
                    $shippingEstimated = false;
249
                    $shippingCurrency = 'USD';
250
                }
251
                else {
252
                    $shippingCost = 3.99; // bugbug
253
                    $shippingEstimated = true; // bugbug
254
                    $shippingCurrency = 'USD';
255
                }
256
                $freeShippingCap = !empty($offer->DeliveryInfo->IsFreeShippingEligible) ? 25 : 0;
81 - 257
 
99 - 258
                if (++$listings > $numResults) {
259
                    continue;
260
                }
81 - 261
 
99 - 262
                $arr[] = array(
263
                    "Merchant" => $merchantName,
264
                    "Condition" => $condition,
265
                    "Title" => $title,
266
                    "Barcode" => $barcode,
267
                    "BarcodeType" => $barcodeType,
268
                    "Image" => $pic,
269
                    "URL" => $url,
270
                    "MediaType" => $mediaType,
271
                    "DetailCondition" => $detailCondition,
272
                    "Country" => $country,
273
                    "BestOffer" => $bestOffer,
274
                    "TimeLeft" => $timeLeft,
275
                    "Price" => $price,
276
                    "Currency" => $currency,
277
                    "ListingType" => $listingType,
278
                    "Location" => $location,
279
                    "Zip" => $zip,
280
                    "FeedbackScore" => $feedbackScore,
281
                    "FeedbackPercent" => $feedbackPercent,
282
                    "SellerName" => $sellerName,
283
                    "HandlingTime" => $handlingTime,
284
                    "ShippingCost" => $shippingCost,
285
                    "ShippingEstimated" => $shippingEstimated,
286
                    "ShippingCurrency" => $shippingCurrency,
287
                    "FreeShippingCap" => $freeShippingCap,
288
                    "Show" => true
289
                );
81 - 290
            }
291
        }
99 - 292
    }
81 - 293
 
99 - 294
    if ($needMatches) {
295
        if ($cnt = 0) {
296
            $_SESSION["discogs"] = "";
81 - 297
        }
99 - 298
        else {
130 - 299
            endMatches($xh);
127 - 300
 
301
            $_SESSION["discogs"] = $xh->flush();
302
            error_log(print_r($_SESSION["discogs"], 1));
99 - 303
        }
81 - 304
    }
99 - 305
 
81 - 306
    // If the response does not indicate 'Success,' log the error(s)
99 - 307
    /******************
81 - 308
    else {
96 - 309
        my_error_log($url);
99 - 310
        if (!empty($parsed_json->OperationRequest->Errors)) {
311
            foreach($parsed_json->OperationRequest->Errors->Error as $error){
96 - 312
                my_error_log($error->Message . " (" . $error->Code . ")");
81 - 313
            }
99 - 314
        } else if (!empty($parsed_json->Errors)) {
315
            foreach($parsed_json->OperationRequest->Errors->Error as $error){
96 - 316
                my_error_log($error->Message . " (" . $error->Code . ")");
81 - 317
            }
99 - 318
        } else if (!empty($parsed_json->Error)) {
319
            my_error_log($parsed_json->Error->Message . " (" . $parsed_json->Error->Code . ")");
81 - 320
        } else {
96 - 321
            my_error_log(print_r($result, 1));
81 - 322
        }
323
    }
99 - 324
    ******************/
81 - 325
 
326
    return $arr;
327
}
328
 
127 - 329
function startMatches(&$xh) {
330
    $xh->add_attribute("class", "container-fluid bg-light");
331
    $xh->tag('div');
332
    $xh->add_attribute("class", "text-center py-2");
333
    $xh->tag('h2', "Matching Albums");
81 - 334
 
137 - 335
    $xh->add_attribute("id", "discogsDeckForm");
336
    $xh->add_attribute("method", "post");
337
    $xh->add_attribute("action", "/index.php");
127 - 338
    $xh->tag('form');
339
    $xh->insert_code(inputSessionTab());
340
    $xh->insert_code(inputNonce());
341
    $xh->add_attribute("id", "discogsTitle");
342
    $xh->add_attribute("type", "hidden");
343
    $xh->add_attribute("name", "discogsTitle");
344
    $xh->add_attribute("value", "");
345
    $xh->single_tag('input');
346
    $xh->add_attribute("id", "discogsArtist");
347
    $xh->add_attribute("type", "hidden");
348
    $xh->add_attribute("name", "discogsArtist");
349
    $xh->add_attribute("value", "");
350
    $xh->single_tag('input');
351
    $xh->add_attribute("id", "discogsBarcode");
352
    $xh->add_attribute("type", "hidden");
353
    $xh->add_attribute("name", "discogsBarcode");
354
    $xh->add_attribute("value", "");
355
    $xh->single_tag('input');
356
    $xh->add_attribute("id", "discogsDeck");
357
    $xh->add_attribute("class", "card-deck");
358
    $xh->tag('div');
81 - 359
}
360
 
130 - 361
function endMatches(&$xh) {
362
    $xh->insert_code(discogsEvents());
81 - 363
 
127 - 364
    $xh->close(); // div
365
    $xh->close(); // form>";
366
    $xh->close(); // div>";
81 - 367
}
368
 
130 - 369
function addMatch(&$xh, $item, $cnt, $mediaType) {
127 - 370
    $xhmod = new Html;
371
    $xhmod->init($_SESSION["htmlIndent"]);
372
 
81 - 373
    $artists = getArtists($item);
99 - 374
    $contributers = getContributers($item);
81 - 375
 
99 - 376
    $label = "";
377
    if (!empty($item->ItemInfo->ByLineInfo->Manufacturer)) {
100 - 378
        $label = $item->ItemInfo->ByLineInfo->Manufacturer->DisplayValue;
81 - 379
    }
380
 
381
    $languages = [];
99 - 382
    if (!empty($item->ItemInfo->ContentInfo->Languages)) {
383
        foreach ($item->ItemInfo->ContentInfo->Languages->DisplayValues as $language) {
81 - 384
            if ((string)$language->Type != "Unknown") {
99 - 385
                $languages[] = $language->DisplayValue . " (" . $language->Type . ")";
81 - 386
            }
387
        }
388
    }
389
 
101 - 390
    $genres = [];
391
    if (!empty($item->ItemInfo->Genre)) {
392
        foreach($item->ItemInfo->Genre as $genre) {
393
            $genres[] = join(" ", array_map('ucfirst', explode('-', $genre)));
394
        }
395
    }
396
 
397
    $runningTime = "";
398
    if (!empty($item->ItemInfo->RunningTime)) {
399
        if ($mediaType != 'Digital') {
400
            $runningTime = (string)$item->ItemInfo->RunningTime . " minutes";
401
        } else {
402
            $runningTime = gmdate("H:i:s", (int)$item->ItemInfo->RunningTime);
403
        }
404
    }
405
 
127 - 406
    $xh->add_attribute("class", "card mx-auto discogs-card");
407
    $xh->tag('div');
408
    $xh->add_attribute("class", "card-header bg-secondary d-flex");
409
    $xh->tag('div');
81 - 410
    $searchArtists = "";
105 - 411
    $wlArtists = "";
99 - 412
    if (!empty($artists)) {
413
        if (count($artists) < 5) {
414
            $wlArtists = join(", ", $artists);
415
            if (!empty($artists) && $artists[0] != 'Various') {
416
                $searchArtists = join(" ", $artists);
417
            }
418
        } else {
419
            $wlArtists = "Various Artists";
81 - 420
        }
421
    }
99 - 422
    else if (!empty($contributers)) {
423
        if (count($contributers) < 5) {
424
            $wlArtists = join(", ", $contributers);
425
            if (!empty($contributers) && $contributers[0] != 'Various') {
426
                $searchArtists = join(" ", $contributers);
427
            }
428
        } else {
429
            $wlArtists = "Various Artists";
430
        }
81 - 431
    }
127 - 432
 
433
    $str = htmlentities((string)$item->ItemInfo->Title->DisplayValue);
124 - 434
    if (!empty($wlArtists)) {
125 - 435
        $str .= " by " . htmlentities($wlArtists);
124 - 436
    }
127 - 437
    $xh->add_attribute("class", "card-title font-weight-bold small flex-grow-1");
438
    $xh->tag('p', $str);
439
    $xh->close(); // div
81 - 440
 
99 - 441
    $thumbnail = !empty($item->Images->Primary->Medium->URL) ? (string)$item->Images->Primary->Medium->URL : "images/no-image-available.jpg";
81 - 442
 
127 - 443
    $xh->add_attribute("class", "card-body d-flex justify-content-center align-items-center p-1 m-0");
444
    $xh->tag('div');
445
    $xh->add_attribute("class", "btn p-0 m-0 lazyload");
446
    $xh->add_attribute("src", PIXEL);
447
    $xh->add_attribute("data-src",  $thumbnail);
448
    $xh->add_attribute("data-toggle", "modal");
449
    $xh->add_attribute("data-target", "#masterModal" . $cnt);
450
    $xh->add_attribute("title", "Album Information");
451
    $xh->add_attribute("data-toggle2", "tooltip");
452
    $xh->add_attribute("alt", "Cover Thumbnail");
453
    $xh->single_tag('img');
454
    $xh->close(); // div
455
    $xh->add_attribute("class", "card-footer bg-secondary p-0 m-0");
456
    $xh->tag('div');
457
    $xh->add_attribute("class", "container clearfix p-0 m-0");
458
    $xh->tag('div');
459
    $xh->add_attribute("class", "float-left btn-group-sm");
460
    $xh->tag('span');
130 - 461
    $xh->add_attribute("id", "discogsInfo" . $cnt);
127 - 462
    $xh->add_attribute("type", "button");
463
    $xh->add_attribute("class", "btn btn-info btn-sm");
464
    $xh->add_attribute("data-toggle", "modal");
465
    $xh->add_attribute("data-target", "#masterModal" . $cnt);
466
    $xh->add_attribute("title", "Album Information");
467
    $xh->add_attribute("aria-label", "Album Information");
468
    $xh->add_attribute("data-toggle2", "tooltip");
469
    $xh->tag('button');
470
    $xh->add_attribute("class", "material-icons");
471
    $xh->tag('i', "info_outline");
472
    $xh->close(); // button
81 - 473
 
127 - 474
    $xh->close(); // span
81 - 475
 
127 - 476
    $xh->add_attribute("class", "float-right btn-group-sm");
477
    $xh->tag('span');
81 - 478
 
479
    $barcode = "";
480
    $tmpBarcode = "";
99 - 481
    if (isset($item->ItemInfo->ExternalIds->UPCs)) {
482
        $tmpBarcode = (string)$item->ItemInfo->ExternalIds->UPCs->DisplayValues[0];
81 - 483
    }
99 - 484
    else if (isset($item->ItemInfo->ExternalIds->EANs)) {
485
        $tmpBarcode = (string)$item->ItemInfo->ExternalIds->EANs->DisplayValues[0];
486
    }
487
    else if (isset($item->ItemInfo->ExternalIds->ISBNs)) {
488
        $tmpBarcode = (string)$item->ItemInfo->ExternalIds->ISBNs->DisplayValues[0];
489
    }
490
    else if (isset($item->ItemInfo->ExternalIds->EISBNs)) {
491
        $tmpBarcode = (string)$item->ItemInfo->ExternalIds->EISBNs->DisplayValues[0];
492
    }
81 - 493
    $barcodeType = clsLibGTIN::GTINCheck($tmpBarcode, false, 1);
494
    if (!empty($barcodeType)) {
495
        $barcode = $tmpBarcode;
496
    }
497
 
498
    if (isLoggedIn() && !checkWishlist('asin', $item->ASIN)) {
499
        $wlArr = array(
500
            'asin' => (string)$item->ASIN,
99 - 501
            'title' => (string)$item->ItemInfo->Title->DisplayValue,
81 - 502
            'artist' => $wlArtists,
503
            'barcode' => $barcode,
504
            'thumbnail' => $thumbnail,
505
            'url' => (string)$item->DetailPageURL
506
        );
507
        $wl = base64_encode(json_encode($wlArr));
127 - 508
        $xh->add_attribute("id", "wl" . $cnt . "Btn");
509
        $xh->add_attribute("type", "button");
510
        $xh->add_attribute("class", "btn btn-info btn-sm");
511
        $xh->add_attribute("title", "Add to Wishlist");
512
        $xh->add_attribute("aria-label", "Add to Wishlist");
513
        $xh->add_attribute("data-toggle", "tooltip");
130 - 514
        $xh->add_attribute("data-user", $_SESSION['sessData']['userID']);
515
        $xh->add_attribute("data-cnt", $cnt);
516
        $xh->add_attribute("data-wl", $wl);
127 - 517
        $xh->tag('button');
518
        $xh->add_attribute("class", "material-icons");
519
        $xh->tag('i', "bookmark");
520
        $xh->close(); // button
81 - 521
    }
522
 
125 - 523
    $searchTitle = 'Searching for:<br><br><strong>' . htmlentities((string)$item->ItemInfo->Title->DisplayValue) . ' by ' . htmlentities($wlArtists) . '</strong>';
81 - 524
    if (!empty($barcode)) {
525
        $searchTitle .= " (" . displayBarcode($barcode) . ")";
526
    }
527
 
127 - 528
    $xh->tag('span', " ");
529
    $xh->add_attribute("id", "discogsSearch" . $cnt . "Btn");
530
    $xh->add_attribute("type", "submit");
134 - 531
    $xh->add_attribute("name", "submitBtn");
127 - 532
    $xh->add_attribute("value", "discogsSearch");
533
    $xh->add_attribute("class", "btn btn-success btn-sm");
534
    $xh->add_attribute("title", "Search for Store Offers");
535
    $xh->add_attribute("aria-label", "Search for Store Offers");
536
    $xh->add_attribute("data-toggle", "tooltip");
130 - 537
    $xh->add_attribute("data-title", htmlentities((string)$item->ItemInfo->Title->DisplayValue));
538
    $xh->add_attribute("data-artist", htmlentities($searchArtists));
539
    $xh->add_attribute("data-barcode", $barcode);
540
    $xh->add_attribute("data-search-title", $searchTitle);
127 - 541
    $xh->tag('button');
542
    $xh->add_attribute("class", "material-icons");
543
    $xh->tag('i', "search");
544
    $xh->close(); // button
545
    $xh->close(); // span
546
    $xh->close(); // div
120 - 547
 
127 - 548
    $xh->add_attribute("id", "wishlistAdd" . $cnt);
549
    $xh->tag('span', "");
550
    $xh->close(); // div
81 - 551
 
127 - 552
    $xhmod->add_attribute("id", "masterModal" . $cnt);
553
    $xhmod->add_attribute("class", "modal");
554
    $xhmod->tag('div');
555
    $xhmod->add_attribute("class", "modal-dialog");
556
    $xhmod->tag('div');
557
    $xhmod->add_attribute("class", "modal-content");
558
    $xhmod->tag('div');
559
    $xhmod->add_attribute("class", "modal-header bg-secondary");
560
    $xhmod->tag('div');
561
    $xhmod->add_attribute("class", "modal-title mx-auto display-6");
562
    $xhmod->tag('p', htmlentities((string)$item->ItemInfo->Title->DisplayValue) . " by " . htmlentities($wlArtists));
563
    $xhmod->add_attribute("type", "button");
564
    $xhmod->add_attribute("class", "close");
565
    $xhmod->add_attribute("data-dismiss", "modal");
566
    $xhmod->tag('button');
567
    $xhmod->add_attribute("class", "material-icons btn-dismiss");
568
    $xhmod->tag('i', "cancel_presentation");
569
    $xhmod->close(); // button
570
    $xhmod->close(); // div
81 - 571
 
127 - 572
    $xhmod->add_attribute("class", "modal-body mx-auto");
573
    $xhmod->tag('div');
81 - 574
 
99 - 575
    if (!empty($item->Images->Primary->Large->URL)) {
127 - 576
        $xhmod->add_attribute("class", "responsive-image mx-auto mb-4 lazyload");
577
        $xhmod->add_attribute("src", PIXEL);
578
        $xhmod->add_attribute("data-src", (string)$item->Images->Primary->Large->URL);
579
        $xhmod->add_attribute("alt", "Cover Image");
580
        $xhmod->single_tag('img');
81 - 581
    }
582
 
127 - 583
    $xhmod->add_attribute("class", "table-borderless table-condensed small mx-auto");
584
    $xhmod->tag('table');
81 - 585
 
127 - 586
    $xhmod->tag('tr');
587
    $xhmod->add_attribute("class", "px-1");
588
    $xhmod->tag('td', "Title:");
589
    $xhmod->add_attribute("class", "px-1");
590
    $xhmod->tag('td', htmlentities((string)$item->ItemInfo->Title->DisplayValue));
591
    $xhmod->close(); // tr
592
 
593
    $xhmod->tag('tr');
594
    $xhmod->add_attribute("class", "px-1");
595
    $xhmod->tag('td', "Artist:");
596
    $xhmod->add_attribute("class", "px-1");
597
    $xhmod->tag('td', htmlentities(join(", ", $artists)));
598
    $xhmod->close(); // tr
599
 
99 - 600
    if (!empty($contributers)) {
127 - 601
        $xhmod->tag('tr');
602
        $xhmod->add_attribute("class", "px-1");
603
        $xhmod->tag('td', "Creator:");
604
        $xhmod->add_attribute("class", "px-1");
605
        $xhmod->tag('td', htmlentities(join(", ", $contributers)));
606
        $xhmod->close(); // tr
81 - 607
    }
608
 
609
    if (!empty($actors)) {
127 - 610
        $xhmod->tag('tr');
611
        $xhmod->add_attribute("class", "px-1");
612
        $xhmod->tag('td', "Actor:");
613
        $xhmod->add_attribute("class", "px-1");
614
        $xhmod->tag('td', htmlentities(join(", ", $actors)));
615
        $xhmod->close(); // tr
81 - 616
    }
617
 
618
    if (!empty($directors)) {
127 - 619
        $xhmod->tag('tr');
620
        $xhmod->add_attribute("class", "px-1");
621
        $xhmod->tag('td', "Director:");
622
        $xhmod->add_attribute("class", "px-1");
623
        $xhmod->tag('td', htmlentities(join(", ", $directors)));
624
        $xhmod->close(); // tr
81 - 625
    }
626
 
627
    if (!empty($authors)) {
127 - 628
        $xhmod->tag('tr');
629
        $xhmod->add_attribute("class", "px-1");
630
        $xhmod->tag('td', "Author:");
631
        $xhmod->add_attribute("class", "px-1");
632
        $xhmod->tag('td', htmlentities(join(", ", $authors)));
633
        $xhmod->close(); // tr
81 - 634
    }
635
 
99 - 636
    if (!empty($item->ItemInfo->Classifications->Binding)) {
127 - 637
        $xhmod->tag('tr');
638
        $xhmod->add_attribute("class", "px-1");
639
        $xhmod->tag('td', "Type:");
640
        $xhmod->add_attribute("class", "px-1");
641
        $xhmod->tag('td', htmlentities((string)$item->ItemInfo->Classifications->Binding->DisplayValue));
642
        $xhmod->close(); // tr
81 - 643
    }
644
 
101 - 645
    if (!empty($item->ItemInfo->MediaType)) { //
127 - 646
        $xhmod->tag('tr');
647
        $xhmod->add_attribute("class", "px-1");
648
        $xhmod->tag('td', "Media Type:");
649
        $xhmod->add_attribute("class", "px-1");
650
        $xhmod->tag('td', htmlentities((string)$item->ItemInfo->MediaType));
651
        $xhmod->close(); // tr
81 - 652
    }
653
 
654
    if (!empty($barcode)) {
127 - 655
        $xhmod->tag('tr');
656
        $xhmod->add_attribute("class", "px-1");
657
        $xhmod->tag('td', "Barcode:");
658
        $xhmod->add_attribute("class", "px-1");
659
        $xhmod->tag('td', displayBarcode($barcode));
660
        $xhmod->close(); // tr
81 - 661
    }
662
 
99 - 663
    if (!empty($label)) {
127 - 664
        $xhmod->tag('tr');
665
        $xhmod->add_attribute("class", "px-1");
666
        $xhmod->tag('td', "Label:");
667
        $xhmod->add_attribute("class", "px-1");
668
        $xhmod->tag('td', htmlentities($label));
669
        $xhmod->close(); // tr
81 - 670
    }
671
 
672
    if (!empty($languages)) {
127 - 673
        $xhmod->tag('tr');
674
        $xhmod->add_attribute("class", "px-1");
675
        $xhmod->tag('td', "Languages:");
676
        $xhmod->add_attribute("class", "px-1");
677
        $xhmod->tag('td', htmlentities(join(", ", $languages)));
678
        $xhmod->close(); // tr
81 - 679
    }
680
 
99 - 681
    if (!empty($item->ItemInfo->ContentInfo->PublicationDate)) {
127 - 682
        $xhmod->tag('tr');
683
        $xhmod->add_attribute("class", "px-1");
684
        $xhmod->tag('td', "Publication Date:");
685
        $xhmod->add_attribute("class", "px-1");
686
        $xhmod->tag('td', htmlentities((string)$item->ItemInfo->ContentInfo->PublicationDate->DisplayValue));
687
        $xhmod->close(); // tr
81 - 688
    }
689
 
99 - 690
    if (!empty($item->ItemInfo->ContentInfo->ReleaseDate)) {
127 - 691
        $xhmod->tag('tr');
692
        $xhmod->add_attribute("class", "px-1");
693
        $xhmod->tag('td', "Release Date:");
694
        $xhmod->add_attribute("class", "px-1");
695
        $xhmod->tag('td', htmlentities((string)$item->ItemInfo->ContentInfo->ReleaseDate->DisplayValue));
696
        $xhmod->close(); // tr
81 - 697
    }
698
 
101 - 699
    if (!empty($genres)) {
127 - 700
        $xhmod->tag('tr');
701
        $xhmod->add_attribute("class", "px-1");
702
        $xhmod->tag('td', "Genre:");
703
        $xhmod->add_attribute("class", "px-1");
704
        $xhmod->tag('td', htmlentities(join(", ", $genres)));
705
        $xhmod->close(); // tr
101 - 706
    }
707
 
99 - 708
    if (!empty($item->ItemInfo->ContentInfo->UnitCount->DisplayValue)) {
127 - 709
        $xhmod->tag('tr');
710
        $xhmod->add_attribute("class", "px-1");
711
        $xhmod->tag('td', "Number of Discs:");
712
        $xhmod->add_attribute("class", "px-1");
713
        $xhmod->tag('td', htmlentities((string)$item->ItemInfo->ContentInfo->UnitCount->DisplayValue));
714
        $xhmod->close(); // tr
81 - 715
    }
716
 
99 - 717
    if (!empty($item->ItemInfo->ContentInfo->PagesCount->DisplayValue)) {
127 - 718
        $xhmod->tag('tr');
719
        $xhmod->add_attribute("class", "px-1");
720
        $xhmod->tag('td', "Number of Pages:");
721
        $xhmod->add_attribute("class", "px-1");
722
        $xhmod->tag('td', htmlentities((string)$item->ItemInfo->ContentInfo->PagesCount->DisplayValue));
723
        $xhmod->close(); // tr
81 - 724
    }
725
 
101 - 726
    if (!empty($item->ItemInfo->RunningTime)) {
127 - 727
        $xhmod->tag('tr');
728
        $xhmod->add_attribute("class", "px-1");
729
        $xhmod->tag('td', "Running Time:");
730
        $xhmod->add_attribute("class", "px-1");
731
        $xhmod->tag('td', htmlentities($runningTime));
732
        $xhmod->close(); // tr
101 - 733
    }
734
 
735
    if (!empty($item->ItemInfo->Edition)) {
127 - 736
        $xhmod->tag('tr');
737
        $xhmod->add_attribute("class", "px-1");
738
        $xhmod->tag('td', "Edition:");
739
        $xhmod->add_attribute("class", "px-1");
740
        $xhmod->tag('td', htmlentities((string)$item->ItemInfo->Edition));
741
        $xhmod->close(); // tr
101 - 742
    }
743
 
744
    if (!empty($item->Tracks)) {
127 - 745
        $xhmod->tag('tr');
746
        $xhmod->add_attribute("colspan", "2");
747
        $xhmod->add_attribute("class", "px-1");
748
        $xhmod->tag('td', "Tracks:");
749
        $xhmod->close(); // tr
750
 
751
        $xhmod->tag('tr');
752
        $xhmod->add_attribute("colspan", "2");
753
        $xhmod->tag('td');
754
        $xhmod->add_attribute("class", "pl-3 pt-0 small list-unstyled");
755
        $xhmod->tag('ul');
101 - 756
        foreach ($item->Tracks->Disc as $disc) {
757
            if ((int)$item->ItemInfo->ContentInfo->UnitCount->DisplayValue > 1 && !empty($disc->attributes())) {
127 - 758
                $xhmod->add_attribute("class", "font-weight-bold");
759
                $xhmod->tag('li', "Disc " . $disc->attributes() . ":");
101 - 760
            }
761
 
762
            foreach($disc->Track as $track) {
127 - 763
                $xhmod->tag('li', (!empty($track->attributes()) ? $track->attributes() . ") " : "") . htmlentities($track));
101 - 764
            }
765
        }
127 - 766
        $xhmod->close(); // ul
767
        $xhmod->close(); // td
768
        $xhmod->close(); // tr
101 - 769
    }
770
 
127 - 771
    $xhmod->close(); // table
772
    $xhmod->close(); // div
773
    $xhmod->add_attribute("class", "modal-footer bg-secondary justify-content-between");
774
    $xhmod->tag('div');
775
    $xhmod->add_attribute("class", "float-right");
776
    $xhmod->tag('span');
777
    $xhmod->add_attribute("type", "button");
778
    $xhmod->add_attribute("class", "btn btn-danger");
779
    $xhmod->add_attribute("data-dismiss", "modal");
780
    $xhmod->tag('button', "Close");
781
    $xhmod->close(); // span
782
    $xhmod->close(); // div
783
    $xhmod->close(); // div
784
    $xhmod->close(); // div
785
    $xhmod->close(); // div
786
    $html = $xhmod->flush();
787
    //error_log(print_r($html, 1));
81 - 788
 
127 - 789
    $xh->insert_code($html);
790
    $xh->close(); // div
791
 
792
    return;
81 - 793
}
794
 
795
function getArtists($item) {
796
    $artists = [];
797
 
101 - 798
    if (!empty($item->ItemInfo->Artist)){
799
        $artists[] = $item->ItemInfo->Artist;
800
    } else if (!empty($item->ItemInfo->ByLineInfo->Contributors)) {
99 - 801
        foreach ($item->ItemInfo->ByLineInfo->Contributors as $artist) {
802
            if ((string)$artist->Role == "Artist") {
803
                $artists[] = $artist->Name;
804
            }
81 - 805
        }
806
    }
807
 
808
    return $artists;
809
}
810
 
99 - 811
function getContributers($item) {
812
    $contributers = [];
813
 
814
    if (!empty($item->ItemInfo->ByLineInfo->Contributors)) {
815
        foreach ($item->ItemInfo->ByLineInfo->Contributors as $creator) {
816
            if ((string)$creator->Role == "Primary Contributor") {
817
                $contributers[] = $creator->Name;
81 - 818
            }
99 - 819
            else {
820
                $contributers[] = $creator->Name . " (" . $creator->Role . ")";
821
            }
81 - 822
        }
823
    }
824
 
99 - 825
    return $contributers;
81 - 826
}
99 - 827
 
828
class AwsV4 {
829
 
830
    private $accessKey = null;
831
    private $secretKey = null;
832
    private $path = null;
833
    private $regionName = null;
834
    private $serviceName = null;
835
    private $httpMethodName = null;
836
    private $queryParametes = array();
837
    private $awsHeaders = array();
838
    private $payload = "";
839
 
840
    private $HMACAlgorithm = "AWS4-HMAC-SHA256";
841
    private $aws4Request = "aws4_request";
842
    private $strSignedHeader = null;
843
    private $xAmzDate = null;
844
    private $currentDate = null;
845
 
846
    public function __construct($accessKey, $secretKey) {
847
        $this->accessKey = $accessKey;
848
        $this->secretKey = $secretKey;
849
        $this->xAmzDate = $this->getTimeStamp();
850
        $this->currentDate = $this->getDate();
851
    }
852
 
853
    function setPath($path) {
854
        $this->path = $path;
855
    }
856
 
857
    function setServiceName($serviceName) {
858
        $this->serviceName = $serviceName;
859
    }
860
 
861
    function setRegionName($regionName) {
862
        $this->regionName = $regionName;
863
    }
864
 
865
    function setPayload($payload) {
866
        $this->payload = $payload;
867
    }
868
 
869
    function setRequestMethod($method) {
870
        $this->httpMethodName = $method;
871
    }
872
 
873
    function addHeader($headerName, $headerValue) {
874
        $this->awsHeaders[$headerName] = $headerValue;
875
    }
876
 
877
    private function prepareCanonicalRequest() {
878
        $canonicalURL = "";
879
        $canonicalURL .= $this->httpMethodName . "\n";
880
        $canonicalURL .= $this->path . "\n" . "\n";
881
        $signedHeaders = '';
882
        foreach ($this->awsHeaders as $key => $value) {
883
            $signedHeaders .= $key . ";";
884
            $canonicalURL .= $key . ":" . $value . "\n";
885
        }
886
        $canonicalURL .= "\n";
887
        $this->strSignedHeader = substr($signedHeaders, 0, -1);
888
        $canonicalURL .= $this->strSignedHeader . "\n";
889
        $canonicalURL .= $this->generateHex($this->payload);
890
        return $canonicalURL;
891
    }
892
 
893
    private function prepareStringToSign($canonicalURL) {
894
        $stringToSign = '';
895
        $stringToSign .= $this->HMACAlgorithm . "\n";
896
        $stringToSign .= $this->xAmzDate . "\n";
897
        $stringToSign .= $this->currentDate . "/" . $this->regionName . "/" . $this->serviceName . "/" . $this->aws4Request . "\n";
898
        $stringToSign .= $this->generateHex($canonicalURL);
899
        return $stringToSign;
900
    }
901
 
902
    private function calculateSignature($stringToSign) {
903
        $signatureKey = $this->getSignatureKey($this->secretKey, $this->currentDate, $this->regionName, $this->serviceName);
904
        $signature = hash_hmac("sha256", $stringToSign, $signatureKey, true);
905
        $strHexSignature = strtolower(bin2hex($signature));
906
        return $strHexSignature;
907
    }
908
 
909
    public function getHeaders() {
910
        $this->awsHeaders['x-amz-date'] = $this->xAmzDate;
911
        ksort($this->awsHeaders);
912
 
913
        // Step 1: CREATE A CANONICAL REQUEST
914
        $canonicalURL = $this->prepareCanonicalRequest();
915
 
916
        // Step 2: CREATE THE STRING TO SIGN
917
        $stringToSign = $this->prepareStringToSign($canonicalURL);
918
 
919
        // Step 3: CALCULATE THE SIGNATURE
920
        $signature = $this->calculateSignature($stringToSign);
921
 
922
        // Step 4: CALCULATE AUTHORIZATION HEADER
923
        if ($signature) {
924
            $this->awsHeaders['Authorization'] = $this->buildAuthorizationString($signature);
925
            return $this->awsHeaders;
926
        }
927
    }
928
 
929
    private function buildAuthorizationString($strSignature) {
930
        return $this->HMACAlgorithm . " " . "Credential=" . $this->accessKey . "/" . $this->getDate() . "/" . $this->regionName . "/" . $this->serviceName . "/" . $this->aws4Request . "," . "SignedHeaders=" . $this->strSignedHeader . "," . "Signature=" . $strSignature;
931
    }
932
 
933
    private function generateHex($data) {
934
        return strtolower(bin2hex(hash("sha256", $data, true)));
935
    }
936
 
937
    private function getSignatureKey($key, $date, $regionName, $serviceName) {
938
        $kSecret = "AWS4" . $key;
939
        $kDate = hash_hmac("sha256", $date, $kSecret, true);
940
        $kRegion = hash_hmac("sha256", $regionName, $kDate, true);
941
        $kService = hash_hmac("sha256", $serviceName, $kRegion, true);
942
        $kSigning = hash_hmac("sha256", $this->aws4Request, $kService, true);
943
 
944
        return $kSigning;
945
    }
946
 
947
    private function getTimeStamp() {
948
        return gmdate("Ymd\THis\Z");
949
    }
950
 
951
    private function getDate() {
952
        return gmdate("Ymd");
953
    }
954
}