Subversion Repositories cheapmusic

Rev

Rev 104 | Rev 106 | 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 [];
125
    }
81 - 126
 
99 - 127
    if ($needMatches) {
128
        $cnt = 0;
129
        $_SESSION["discogs"] = startMatches();
130
    }
81 - 131
 
99 - 132
    $listings = 0;
133
    // If the response was loaded, parse it and store in array
134
    foreach ($parsed_json->SearchResult->Items as $current) {
135
        if (isset($current->ItemInfo->ExternalIds->UPCs)) {
136
            $barcode = (string)$current->ItemInfo->ExternalIds->UPCs->DisplayValues[0];
137
        }
138
        else if (isset($current->ItemInfo->ExternalIds->EANs)) {
139
            $barcode = (string)$current->ItemInfo->ExternalIds->EANs->DisplayValues[0];
140
        }
141
        else if (isset($current->ItemInfo->ExternalIds->ISBNs)) {
142
            $barcode = (string)$current->ItemInfo->ExternalIds->ISBNs->DisplayValues[0];
143
        }
144
        else if (isset($current->ItemInfo->ExternalIds->EISBNs)) {
145
            $barcode = (string)$current->ItemInfo->ExternalIds->EISBNs->DisplayValues[0];
146
        }
147
        else {
148
            $barcode = "";
149
        }
150
        $barcodeType = clsLibGTIN::GTINCheck($barcode, false, 1);
81 - 151
 
102 - 152
        $pic = !empty($current->Images->Primary->Medium->URL) ? (string)$current->Images->Primary->Medium->URL : "images/no-image-available.jpg";
100 - 153
        $pic = str_replace('http://', 'https://', $pic);
99 - 154
        if (empty($pic)) {
155
            continue;
156
        }
81 - 157
 
99 - 158
        if (strpos($current->ItemInfo->Classifications->Binding->DisplayValue, "Audio CD") !== false) {
159
            $mediaType = "CD";
160
        }
161
        else if (strpos($current->ItemInfo->Classifications->Binding->DisplayValue, "MP3 Music") !== false) {
162
            $mediaType = "Digital";
163
        }
164
        else if (strpos($current->ItemInfo->Classifications->Binding->DisplayValue, "Vinyl") !== false) {
165
            $mediaType = "Record";
166
        }
167
        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) {
168
            $mediaType = "Book";
169
        }
170
        else {
171
            continue;
172
        }
81 - 173
 
174
        if ($needMatches) {
99 - 175
            // bugbug: check maxMasterCnt?
176
            $_SESSION["discogs"] .= addMatch($current, ++$cnt, $mediaType);
81 - 177
        }
178
 
99 - 179
        $title = (string)$current->ItemInfo->Title->DisplayValue;
180
        $artists = getArtists($current);
181
        $contributers = getContributers($current);
182
        if (!empty($artists)) {
183
            $title .= " by " . join(", ", $artists);
184
        }
185
        else if (!empty($contributers)) {
186
            $title .= " by " . join(", ", $contributers);
187
        }
81 - 188
 
99 - 189
        $url = str_replace('http://', 'https://', (string)$current->DetailPageURL);
81 - 190
 
99 - 191
        if (empty($url)) {
192
            continue;
193
        }
81 - 194
 
99 - 195
        $bestOffer = false;
81 - 196
 
99 - 197
        $url = str_replace('http://', 'https://', (string)$current->DetailPageURL);
198
        $url .= "&condition=";
81 - 199
 
99 - 200
        if (!empty($current->Offers->Listings)) {
201
            foreach ($current->Offers->Listings as $offer) {
202
                $country = 'US';
203
                if (isset($offer->MerchantInfo->DefaultShippingCountry)) {
204
                    $country = $offer->MerchantInfo->DefaultShippingCountry;
205
                }
206
                $merchantName = "Amazon";
207
                if (strpos($offer->MerchantInfo->Name, "Amazon") === false) {
208
                    $merchantName .= " Marketplace";
209
                }
81 - 210
 
99 - 211
                $condition = (string)$offer->Condition->Value;
212
                $url .= $condition;
213
                $detailCondition = $condition;
214
                if ($condition == "Collectible") {
215
                    $condition = 'Used';
216
                    $detailCondition = "Collectible";
217
                }
218
                if ($condition == "Refurbished") {
219
                    $condition = 'Used';
220
                    $detailCondition = "Refurbished";
221
                }
222
                $currency = (string)$offer->Price->Currency;
223
                $price = number_format(floatval($offer->Price->Amount) , 2, '.', '');
81 - 224
 
99 - 225
                if ($price <= "0.00") {
226
                    continue;
227
                }
81 - 228
 
99 - 229
                $timeLeft = 0;
230
                $listingType = 'Fixed';
231
                $location = 'US';
232
                $zip = '';
233
                $feedbackScore = - 1;
234
                $feedbackPercent = - 1;
235
                $sellerName = "";
236
                $handlingTime = 0;
237
                if ($offer->DeliveryInfo->IsPrimeEligible === true) {
238
                    $sellerName = "Prime";
81 - 239
                }
99 - 240
                if ($mediaType == "Digital") {
241
                    $shippingCost = 0.00;
242
                    $shippingEstimated = false;
243
                    $shippingCurrency = 'USD';
244
                }
245
                else {
246
                    $shippingCost = 3.99; // bugbug
247
                    $shippingEstimated = true; // bugbug
248
                    $shippingCurrency = 'USD';
249
                }
250
                $freeShippingCap = !empty($offer->DeliveryInfo->IsFreeShippingEligible) ? 25 : 0;
81 - 251
 
99 - 252
                if (++$listings > $numResults) {
253
                    continue;
254
                }
81 - 255
 
99 - 256
                $arr[] = array(
257
                    "Merchant" => $merchantName,
258
                    "Condition" => $condition,
259
                    "Title" => $title,
260
                    "Barcode" => $barcode,
261
                    "BarcodeType" => $barcodeType,
262
                    "Image" => $pic,
263
                    "URL" => $url,
264
                    "MediaType" => $mediaType,
265
                    "DetailCondition" => $detailCondition,
266
                    "Country" => $country,
267
                    "BestOffer" => $bestOffer,
268
                    "TimeLeft" => $timeLeft,
269
                    "Price" => $price,
270
                    "Currency" => $currency,
271
                    "ListingType" => $listingType,
272
                    "Location" => $location,
273
                    "Zip" => $zip,
274
                    "FeedbackScore" => $feedbackScore,
275
                    "FeedbackPercent" => $feedbackPercent,
276
                    "SellerName" => $sellerName,
277
                    "HandlingTime" => $handlingTime,
278
                    "ShippingCost" => $shippingCost,
279
                    "ShippingEstimated" => $shippingEstimated,
280
                    "ShippingCurrency" => $shippingCurrency,
281
                    "FreeShippingCap" => $freeShippingCap,
282
                    "Show" => true
283
                );
81 - 284
            }
285
        }
99 - 286
    }
81 - 287
 
99 - 288
    if ($needMatches) {
289
        if ($cnt = 0) {
290
            $_SESSION["discogs"] = "";
81 - 291
        }
99 - 292
        else {
293
            $_SESSION["discogs"] .= endMatches();
294
        }
81 - 295
    }
99 - 296
 
81 - 297
    // If the response does not indicate 'Success,' log the error(s)
99 - 298
    /******************
81 - 299
    else {
96 - 300
        my_error_log($url);
99 - 301
        if (!empty($parsed_json->OperationRequest->Errors)) {
302
            foreach($parsed_json->OperationRequest->Errors->Error as $error){
96 - 303
                my_error_log($error->Message . " (" . $error->Code . ")");
81 - 304
            }
99 - 305
        } else if (!empty($parsed_json->Errors)) {
306
            foreach($parsed_json->OperationRequest->Errors->Error as $error){
96 - 307
                my_error_log($error->Message . " (" . $error->Code . ")");
81 - 308
            }
99 - 309
        } else if (!empty($parsed_json->Error)) {
310
            my_error_log($parsed_json->Error->Message . " (" . $parsed_json->Error->Code . ")");
81 - 311
        } else {
96 - 312
            my_error_log(print_r($result, 1));
81 - 313
        }
314
    }
99 - 315
    ******************/
81 - 316
 
317
    return $arr;
318
}
319
 
320
function startMatches() {
321
    $str = "<div class=\"container-fluid bg-secondary\">";
322
    $str .= "<h4 class=\"text-center py-2\">Matching Albums</h4>";
323
    $str .= "<form method=\"post\" action=\"/index.php\">";
324
    $str .= "<input type=\"hidden\" name=\"sessionTab\" value=\"" . MySessionHandler::getSessionTab() . "\">";
325
    $str .= "<input id=\"discogsTitle\" type=\"hidden\" name=\"discogsTitle\" value=\"\">";
326
    $str .= "<input id=\"discogsArtist\" type=\"hidden\" name=\"discogsArtist\" value=\"\">";
327
    $str .= "<input id=\"discogsBarcode\" type=\"hidden\" name=\"discogsBarcode\" value=\"\">";
328
    $str .= "<div id=\"discogsDeck\" class=\"card-deck\">";
329
 
330
    return $str;
331
}
332
 
333
function endMatches() {
334
    $str = "</div>";
335
    $str .= "</form>";
336
    $str .= "</div>";
337
 
338
    return $str;
339
}
340
 
341
function addMatch($item, $cnt, $mediaType) {
342
    $artists = getArtists($item);
343
 
99 - 344
    $contributers = getContributers($item);
81 - 345
 
99 - 346
    $label = "";
347
    if (!empty($item->ItemInfo->ByLineInfo->Manufacturer)) {
100 - 348
        $label = $item->ItemInfo->ByLineInfo->Manufacturer->DisplayValue;
81 - 349
    }
350
 
351
    $languages = [];
99 - 352
    if (!empty($item->ItemInfo->ContentInfo->Languages)) {
353
        foreach ($item->ItemInfo->ContentInfo->Languages->DisplayValues as $language) {
81 - 354
            if ((string)$language->Type != "Unknown") {
99 - 355
                $languages[] = $language->DisplayValue . " (" . $language->Type . ")";
81 - 356
            }
357
        }
358
    }
359
 
101 - 360
    $genres = [];
361
    if (!empty($item->ItemInfo->Genre)) {
362
        foreach($item->ItemInfo->Genre as $genre) {
363
            $genres[] = join(" ", array_map('ucfirst', explode('-', $genre)));
364
        }
365
    }
366
 
367
    $runningTime = "";
368
    if (!empty($item->ItemInfo->RunningTime)) {
369
        if ($mediaType != 'Digital') {
370
            $runningTime = (string)$item->ItemInfo->RunningTime . " minutes";
371
        } else {
372
            $runningTime = gmdate("H:i:s", (int)$item->ItemInfo->RunningTime);
373
        }
374
    }
375
 
81 - 376
    $modal = "";
377
    $str = "<div class=\"card mx-auto discogs-card\">";
378
    $str .= "<div class=\"card-header bg-info d-flex h-100\">";
99 - 379
    $str .= "<p class=\"card-title font-weight-bold small flex-grow-1\">" . (string)$item->ItemInfo->Title->DisplayValue . " by ";
81 - 380
    $searchArtists = "";
105 - 381
    $wlArtists = "";
99 - 382
    if (!empty($artists)) {
383
        if (count($artists) < 5) {
384
            $wlArtists = join(", ", $artists);
385
            if (!empty($artists) && $artists[0] != 'Various') {
386
                $searchArtists = join(" ", $artists);
387
            }
388
        } else {
389
            $wlArtists = "Various Artists";
81 - 390
        }
391
    }
99 - 392
    else if (!empty($contributers)) {
393
        if (count($contributers) < 5) {
394
            $wlArtists = join(", ", $contributers);
395
            if (!empty($contributers) && $contributers[0] != 'Various') {
396
                $searchArtists = join(" ", $contributers);
397
            }
398
        } else {
399
            $wlArtists = "Various Artists";
400
        }
81 - 401
    }
402
    $str .= $wlArtists;
403
    $str .= "</p>";
404
    $str .= "</div>";
405
 
99 - 406
    $thumbnail = !empty($item->Images->Primary->Medium->URL) ? (string)$item->Images->Primary->Medium->URL : "images/no-image-available.jpg";
81 - 407
 
408
    $str .= "<div class=\"card-body bg-light mx-auto p-0 m-0\">";
409
    $str .= "<img class=\"btn responsive-image p-0 m-0\" src=\"" . $thumbnail . "\" data-toggle=\"modal\" data-target=\"#masterModal" . $cnt . "\" title=\"Album Information\" data-toggle2=\"tooltip\" alt=\"Cover Thumbnail\">";
410
    $str .= "</div>";
411
    $str .= "<div class=\"card-footer bg-dark p-0 m-0\">";
412
    $str .= "<div class=\"container clearfix p-0 m-0\">";
413
    $str .= "<span class=\"float-left\">";
414
    $str .= "<button type=\"button\" class=\"btn btn-primary m-1 btn-sm\" data-toggle=\"modal\" data-target=\"#masterModal" . $cnt . "\" title=\"Album Information\" data-toggle2=\"tooltip\"><i class=\"fas fa-info\"></i></button>";
415
 
416
    $str .= "</span>";
417
 
418
    $str .= "<span class=\"float-right\">";
419
 
420
    $barcode = "";
421
    $tmpBarcode = "";
99 - 422
    if (isset($item->ItemInfo->ExternalIds->UPCs)) {
423
        $tmpBarcode = (string)$item->ItemInfo->ExternalIds->UPCs->DisplayValues[0];
81 - 424
    }
99 - 425
    else if (isset($item->ItemInfo->ExternalIds->EANs)) {
426
        $tmpBarcode = (string)$item->ItemInfo->ExternalIds->EANs->DisplayValues[0];
427
    }
428
    else if (isset($item->ItemInfo->ExternalIds->ISBNs)) {
429
        $tmpBarcode = (string)$item->ItemInfo->ExternalIds->ISBNs->DisplayValues[0];
430
    }
431
    else if (isset($item->ItemInfo->ExternalIds->EISBNs)) {
432
        $tmpBarcode = (string)$item->ItemInfo->ExternalIds->EISBNs->DisplayValues[0];
433
    }
81 - 434
    $barcodeType = clsLibGTIN::GTINCheck($tmpBarcode, false, 1);
435
    if (!empty($barcodeType)) {
436
        $barcode = $tmpBarcode;
437
    }
438
 
439
    if (isLoggedIn() && !checkWishlist('asin', $item->ASIN)) {
440
        $wlArr = array(
441
            'asin' => (string)$item->ASIN,
99 - 442
            'title' => (string)$item->ItemInfo->Title->DisplayValue,
81 - 443
            'artist' => $wlArtists,
444
            'barcode' => $barcode,
445
            'thumbnail' => $thumbnail,
446
            'url' => (string)$item->DetailPageURL
447
        );
448
        $wl = base64_encode(json_encode($wlArr));
449
        $str .= "  <button type=\"button\" class=\"btn btn-primary m-1 btn-sm\" onclick=\"addWishlist('" . $_SESSION['sessData']['userID'] . "',this," . $cnt . ",'" . $wl . "');\" title=\"Add to Wishlist\" data-toggle=\"tooltip\"><i class=\"fas fa-bookmark\"></i></button>";
450
    }
451
 
104 - 452
    $searchTitle = 'Searching for:<br><br><strong>' . (string)$item->ItemInfo->Title->DisplayValue . ' by ' . $wlArtists . '</strong>';
81 - 453
    if (!empty($barcode)) {
454
        $searchTitle .= " (" . displayBarcode($barcode) . ")";
455
    }
456
 
99 - 457
    $str .= "  <button type=\"submit\" name=\"submit\" value=\"discogsSearch\" class=\"btn btn-primary m-1 btn-sm\" onclick=\"document.getElementById('discogsTitle').value = '" . addslashes((string)$item->ItemInfo->Title->DisplayValue) . "';document.getElementById('discogsArtist').value = '" . addslashes($searchArtists) . "';document.getElementById('discogsBarcode').value = '" . $barcode . "';progressBar('" . sanitizeInput2($searchTitle) . "');\" title=\"Search for Store Offers\" data-toggle=\"tooltip\"><i class=\"fas fa-search\"></i></button>";
81 - 458
    $str .= "</span>";
459
    $str .= "</div>";
460
    $str .= "<span id=\"wishlistAdd" . $cnt . "\"></span>";
461
    $str .= "</div>";
462
 
463
    $modal .= "<div id=\"masterModal" . $cnt . "\" class=\"modal\">";
464
    $modal .= "<div class=\"modal-dialog\">";
465
    $modal .= "<div class=\"modal-content\">";
466
    $modal .= "<div class=\"modal-header bg-primary\">";
99 - 467
    $modal .= "<h4 class=\"modal-title mx-auto\">" . (string)$item->ItemInfo->Title->DisplayValue . " by " . $wlArtists . "</h4>";
81 - 468
    $modal .= "<button type=\"button\" class=\"close\" data-dismiss=\"modal\"><i class=\"fas fa-window-close btn-dismiss\"></i></button>";
469
    $modal .= "</div>";
470
 
471
    $modal .= "<div class=\"modal-body bg-white mx-auto\">";
472
 
99 - 473
    if (!empty($item->Images->Primary->Large->URL)) {
474
        $modal .= "<img class=\"responsive-image mx-auto mb-4\" src=\"" . (string)$item->Images->Primary->Large->URL . "\" alt=\"Cover Image\">";
81 - 475
    }
476
 
477
    $modal .= "<table class=\"table-borderless table-condensed small mx-auto\">";
99 - 478
    $modal .= "<tr><td class=\"px-1\">Title:</td><td class=\"px-1\">" . (string)$item->ItemInfo->Title->DisplayValue . "</td></tr>";
81 - 479
 
480
    $modal .= "<tr><td class=\"px-1\">Artist:</td><td class=\"px-1\">" . join(", ", $artists) . "</td></tr>";
99 - 481
    if (!empty($contributers)) {
482
        $modal .= "<tr><td class=\"px-1\">Creator:</td><td class=\"px-1\">" . join(", ", $contributers) . "</td></tr>";
81 - 483
    }
484
 
485
    if (!empty($actors)) {
486
        $modal .= "<tr><td class=\"px-1\">Actor:</td><td class=\"px-1\">" . join(", ", $actors) . "</td></tr>";
487
    }
488
 
489
    if (!empty($directors)) {
490
        $modal .= "<tr><td class=\"px-1\">Director:</td><td class=\"px-1\">" . join(", ", $directors) . "</td></tr>";
491
    }
492
 
493
    if (!empty($authors)) {
494
        $modal .= "<tr><td class=\"px-1\">Author:</td><td class=\"px-1\">" . join(", ", $authors) . "</td></tr>";
495
    }
496
 
99 - 497
    if (!empty($item->ItemInfo->Classifications->Binding)) {
498
        $modal .= "<tr><td class=\"px-1\">Type:</td><td class=\"px-1\">" . (string)$item->ItemInfo->Classifications->Binding->DisplayValue . "</td></tr>";
81 - 499
    }
500
 
101 - 501
    if (!empty($item->ItemInfo->MediaType)) { //
502
        $modal .= "<tr><td class=\"px-1\">Media Type:</td><td class=\"px-1\">" . (string)$item->ItemInfo->MediaType . "</td></tr>";
81 - 503
    }
504
 
505
    if (!empty($barcode)) {
506
        $modal .= "<tr><td class=\"px-1\">Barcode:</td><td class=\"px-1\">" . displayBarcode($barcode) . "</td></tr>";
507
    }
508
 
99 - 509
    if (!empty($label)) {
510
        $modal .= "<tr><td class=\"px-1\">Label:</td><td class=\"px-1\">" . $label . "</td></tr>";
81 - 511
    }
512
 
513
    if (!empty($languages)) {
514
        $modal .= "<tr><td class=\"px-1\">Languages:</td><td class=\"px-1\">" . join(", ", $languages) . "</td></tr>";
515
    }
516
 
99 - 517
    if (!empty($item->ItemInfo->ContentInfo->PublicationDate)) {
100 - 518
        $modal .= "<tr><td class=\"px-1\">Publication Date:</td><td class=\"px-1\">" . (string)$item->ItemInfo->ContentInfo->PublicationDate->DisplayValue . "</td></tr>";
81 - 519
    }
520
 
99 - 521
    if (!empty($item->ItemInfo->ContentInfo->ReleaseDate)) {
100 - 522
        $modal .= "<tr><td class=\"px-1\">Release Date:</td><td class=\"px-1\">" . (string)$item->ItemInfo->ContentInfo->ReleaseDate->DisplayValue . "</td></tr>";
81 - 523
    }
524
 
101 - 525
    if (!empty($genres)) {
526
        $modal .= "<tr><td class=\"px-1\">Genre:</td><td class=\"px-1\">" . join(", ", $genres) . "</td></tr>";
527
    }
528
 
99 - 529
    if (!empty($item->ItemInfo->ContentInfo->UnitCount->DisplayValue)) {
530
        $modal .= "<tr><td class=\"px-1\">Number of Discs:</td><td class=\"px-1\">" . (string)$item->ItemInfo->ContentInfo->UnitCount->DisplayValue . "</td></tr>";
81 - 531
    }
532
 
99 - 533
    if (!empty($item->ItemInfo->ContentInfo->PagesCount->DisplayValue)) {
534
        $modal .= "<tr><td class=\"px-1\">Number of Pages:</td><td class=\"px-1\">" . (string)$item->ItemInfo->ContentInfo->PagesCount->DisplayValue . "</td></tr>";
81 - 535
    }
536
 
101 - 537
    if (!empty($item->ItemInfo->RunningTime)) {
538
        $modal .= "<tr><td class=\"px-1\">Running Time:</td><td class=\"px-1\">" . $runningTime . "</td></tr>";
539
    }
540
 
541
    if (!empty($item->ItemInfo->Edition)) {
542
        $modal .= "<tr><td class=\"px-1\">Edition:</td><td class=\"px-1\">" . (string)$item->ItemInfo->Edition . "</td></tr>";
543
    }
544
 
545
    if (!empty($item->Tracks)) {
546
        $modal .= "<tr><td colspan=\"2\" class=\"px-1\">Tracks:</td></tr>";
547
        $modal .= "<tr><td colspan=\"2\">";
548
        $modal .= "<ul class=\"pl-3 pt-0 small list-unstyled\">";
549
        foreach ($item->Tracks->Disc as $disc) {
550
            if ((int)$item->ItemInfo->ContentInfo->UnitCount->DisplayValue > 1 && !empty($disc->attributes())) {
551
                $modal .= "<li class=\"font-weight-bold\">Disc " . $disc->attributes() . ":</li>";
552
            }
553
 
554
            foreach($disc->Track as $track) {
555
                $modal .= "<li>" . (!empty($track->attributes()) ? $track->attributes() . ") " : "") . $track . "</li>";
556
            }
557
        }
558
        $modal .= "</ul>";
559
        $modal .= "</td></tr>";
560
    }
561
 
81 - 562
    $modal .= "</table>";
563
    $modal .= "</div>";
564
    $modal .= "<div class=\"modal-footer bg-white justify-content-between\">";
565
    $modal .= "<span class=\"float-right\"><button type=\"button\" class=\"btn btn-danger\" data-dismiss=\"modal\">Close</button></span>";
566
    $modal .= "</div>";
567
    $modal .= "</div>";
568
    $modal .= "</div>";
569
    $modal .= "</div>";
570
    $str .= $modal;
571
    $str .= "</div>";
572
 
573
    return $str;
574
}
575
 
576
function getArtists($item) {
577
    $artists = [];
578
 
101 - 579
    if (!empty($item->ItemInfo->Artist)){
580
        $artists[] = $item->ItemInfo->Artist;
581
    } else if (!empty($item->ItemInfo->ByLineInfo->Contributors)) {
99 - 582
        foreach ($item->ItemInfo->ByLineInfo->Contributors as $artist) {
583
            if ((string)$artist->Role == "Artist") {
584
                $artists[] = $artist->Name;
585
            }
81 - 586
        }
587
    }
588
 
589
    return $artists;
590
}
591
 
99 - 592
function getContributers($item) {
593
    $contributers = [];
594
 
595
    if (!empty($item->ItemInfo->ByLineInfo->Contributors)) {
596
        foreach ($item->ItemInfo->ByLineInfo->Contributors as $creator) {
597
            if ((string)$creator->Role == "Primary Contributor") {
598
                $contributers[] = $creator->Name;
81 - 599
            }
99 - 600
            else {
601
                $contributers[] = $creator->Name . " (" . $creator->Role . ")";
602
            }
81 - 603
        }
604
    }
605
 
99 - 606
    return $contributers;
81 - 607
}
99 - 608
 
609
class AwsV4 {
610
 
611
    private $accessKey = null;
612
    private $secretKey = null;
613
    private $path = null;
614
    private $regionName = null;
615
    private $serviceName = null;
616
    private $httpMethodName = null;
617
    private $queryParametes = array();
618
    private $awsHeaders = array();
619
    private $payload = "";
620
 
621
    private $HMACAlgorithm = "AWS4-HMAC-SHA256";
622
    private $aws4Request = "aws4_request";
623
    private $strSignedHeader = null;
624
    private $xAmzDate = null;
625
    private $currentDate = null;
626
 
627
    public function __construct($accessKey, $secretKey) {
628
        $this->accessKey = $accessKey;
629
        $this->secretKey = $secretKey;
630
        $this->xAmzDate = $this->getTimeStamp();
631
        $this->currentDate = $this->getDate();
632
    }
633
 
634
    function setPath($path) {
635
        $this->path = $path;
636
    }
637
 
638
    function setServiceName($serviceName) {
639
        $this->serviceName = $serviceName;
640
    }
641
 
642
    function setRegionName($regionName) {
643
        $this->regionName = $regionName;
644
    }
645
 
646
    function setPayload($payload) {
647
        $this->payload = $payload;
648
    }
649
 
650
    function setRequestMethod($method) {
651
        $this->httpMethodName = $method;
652
    }
653
 
654
    function addHeader($headerName, $headerValue) {
655
        $this->awsHeaders[$headerName] = $headerValue;
656
    }
657
 
658
    private function prepareCanonicalRequest() {
659
        $canonicalURL = "";
660
        $canonicalURL .= $this->httpMethodName . "\n";
661
        $canonicalURL .= $this->path . "\n" . "\n";
662
        $signedHeaders = '';
663
        foreach ($this->awsHeaders as $key => $value) {
664
            $signedHeaders .= $key . ";";
665
            $canonicalURL .= $key . ":" . $value . "\n";
666
        }
667
        $canonicalURL .= "\n";
668
        $this->strSignedHeader = substr($signedHeaders, 0, -1);
669
        $canonicalURL .= $this->strSignedHeader . "\n";
670
        $canonicalURL .= $this->generateHex($this->payload);
671
        return $canonicalURL;
672
    }
673
 
674
    private function prepareStringToSign($canonicalURL) {
675
        $stringToSign = '';
676
        $stringToSign .= $this->HMACAlgorithm . "\n";
677
        $stringToSign .= $this->xAmzDate . "\n";
678
        $stringToSign .= $this->currentDate . "/" . $this->regionName . "/" . $this->serviceName . "/" . $this->aws4Request . "\n";
679
        $stringToSign .= $this->generateHex($canonicalURL);
680
        return $stringToSign;
681
    }
682
 
683
    private function calculateSignature($stringToSign) {
684
        $signatureKey = $this->getSignatureKey($this->secretKey, $this->currentDate, $this->regionName, $this->serviceName);
685
        $signature = hash_hmac("sha256", $stringToSign, $signatureKey, true);
686
        $strHexSignature = strtolower(bin2hex($signature));
687
        return $strHexSignature;
688
    }
689
 
690
    public function getHeaders() {
691
        $this->awsHeaders['x-amz-date'] = $this->xAmzDate;
692
        ksort($this->awsHeaders);
693
 
694
        // Step 1: CREATE A CANONICAL REQUEST
695
        $canonicalURL = $this->prepareCanonicalRequest();
696
 
697
        // Step 2: CREATE THE STRING TO SIGN
698
        $stringToSign = $this->prepareStringToSign($canonicalURL);
699
 
700
        // Step 3: CALCULATE THE SIGNATURE
701
        $signature = $this->calculateSignature($stringToSign);
702
 
703
        // Step 4: CALCULATE AUTHORIZATION HEADER
704
        if ($signature) {
705
            $this->awsHeaders['Authorization'] = $this->buildAuthorizationString($signature);
706
            return $this->awsHeaders;
707
        }
708
    }
709
 
710
    private function buildAuthorizationString($strSignature) {
711
        return $this->HMACAlgorithm . " " . "Credential=" . $this->accessKey . "/" . $this->getDate() . "/" . $this->regionName . "/" . $this->serviceName . "/" . $this->aws4Request . "," . "SignedHeaders=" . $this->strSignedHeader . "," . "Signature=" . $strSignature;
712
    }
713
 
714
    private function generateHex($data) {
715
        return strtolower(bin2hex(hash("sha256", $data, true)));
716
    }
717
 
718
    private function getSignatureKey($key, $date, $regionName, $serviceName) {
719
        $kSecret = "AWS4" . $key;
720
        $kDate = hash_hmac("sha256", $date, $kSecret, true);
721
        $kRegion = hash_hmac("sha256", $regionName, $kDate, true);
722
        $kService = hash_hmac("sha256", $serviceName, $kRegion, true);
723
        $kSigning = hash_hmac("sha256", $this->aws4Request, $kService, true);
724
 
725
        return $kSigning;
726
    }
727
 
728
    private function getTimeStamp() {
729
        return gmdate("Ymd\THis\Z");
730
    }
731
 
732
    private function getDate() {
733
        return gmdate("Ymd");
734
    }
735
}