Subversion Repositories cheapmusic

Rev

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

Rev Author Line No. Line
1 - 1
<?php
93 - 2
use Fuse\Fuse;
65 - 3
include_once ('php/clsLibGTIN.php');
4
include_once ('php/exchangeRates.php');
5
include_once ('php/countryCodes.php');
6
include_once ('php/constants.php');
7
include_once ('php/ebay.php');
8
include_once ('php/discogs.php');
9
include_once ('php/linkshare.php');
10
include_once ('php/cjaffiliate.php');
11
include_once ('php/walmart.php');
12
include_once ('php/itunes.php');
81 - 13
include_once ('php/amazon.php');
91 - 14
include_once ('php/amazon_scrape.php');
83 - 15
include_once ('php/impact.php');
99 - 16
include_once ('php/sessions_db.php');
1 - 17
 
20 - 18
error_reporting(E_ALL);
19
 
107 - 20
// meta description
21
function metaDescription($page) {
22
    switch ($page) {
23
        case "terms":
24
            $metaText = "By visiting our site and/or purchasing something from us, you engage in our Service and agree to be bound by these terms and conditions.";
25
            break;
26
 
27
        case "privacy":
28
            $metaText = "In our User Privacy Notice, we have compiled all essential information about our handling of your personal data and your corresponding rights for you.";
29
            break;
30
 
31
        case "help":
32
            $metaText = "The help page explains the basic functionality of the search page with its various sections of supporting information.";
33
            break;
34
 
35
        case "wishlist":
36
            $metaText = "Maintain a wishlist at FindCheapMusic to keep track of your favorite music albums or to receive price drop alerts right to your email. Free login required.";
37
            break;
38
 
39
        case "coupons":
40
            $metaText = "Weekly updated coupons and special offers from various music online stores. When they are gone, they are gone. Free login required.";
41
            break;
42
 
43
        case "priceMonitor":
44
            $metaText = "Explore your personal price monitor results. Results will be updated at user-defined intervals and published via email. Free login required.";
45
            break;
46
 
47
        case "random":
48
            $metaText = "See several completely random music album suggestions.";
49
            break;
50
 
51
        default:
52
            $metaText = "Search dozens of online stores at once for low-priced or hard to find Compact Discs, Vinyl Records, MP3s, Music Sheets and Music related books.";
53
            break;
54
    }
55
 
56
    return ('<meta name="description" content="' . $metaText . '">');
57
}
58
 
65 - 59
// search
5 - 60
function performSearch() {
14 - 61
    $currentMd5SearchTerm = md5SearchTerm();
62
    if ($currentMd5SearchTerm == $_SESSION['md5LastSearch']) {
63
        return;
64
    }
65
    $_SESSION['md5LastSearch'] = $currentMd5SearchTerm;
66
 
81 - 67
    $_SESSION["barcode"]["Type"] = clsLibGTIN::GTINCheck($_SESSION["searchTerm"], false, 1);
68
    $_SESSION["barcode"]["Value"] = clsLibGTIN::GTINCheck($_SESSION["searchTerm"]);
69
 
22 - 70
    updatePbFile(true);
71
 
107 - 72
    getGeoLocation();
73
 
74
    updatePbFile(true);
75
 
81 - 76
    findDiscogsMaster($_SESSION["searchTerm"]);
77
    updatePbFile();
78
 
65 - 79
    $_SESSION["currentView"] = 'All';
80
    $_SESSION["currentLayout"] = 'TableView';
81
    $_SESSION["resultArr"] = [];
99 - 82
    expireSearchCache();
65 - 83
    $_SESSION["resultArr"] = searchAll($_SESSION["searchTerm"]);
93 - 84
 
99 - 85
    verifyResultArr();
93 - 86
 
22 - 87
    updatePbFile();
23 - 88
 
65 - 89
    $_SESSION["resultArr"] = applySearchFilter($_SESSION["resultArr"]);
22 - 90
    updatePbFile();
5 - 91
 
65 - 92
    //echo "<pre>";print_r($_SESSION["resultArr"]);echo "</pre>";
66 - 93
    $_SESSION["lowestPrice"]["Used"] = findLowestCondition("Used");
94
    $_SESSION["lowestPrice"]["New"] = findLowestCondition("New");
95
    $_SESSION["lowestPrice"]["CD"] = findLowestMediaType("CD");
96
    $_SESSION["lowestPrice"]["Record"] = findLowestMediaType("Record");
97
    $_SESSION["lowestPrice"]["Digital"] = findLowestMediaType("Digital");
98
    $_SESSION["lowestPrice"]["Book"] = findLowestMediaType("Book");
65 - 99
    $_SESSION["lowestPrice"]["All"] = 0.00;
100
    if (array_sum($_SESSION["lowestPrice"]) > 0) {
101
        $_SESSION["lowestPrice"]["All"] = minNotNull($_SESSION["lowestPrice"]);
102
    }
22 - 103
    updatePbFile();
13 - 104
 
65 - 105
    saveSearchResult();
22 - 106
    updatePbFile();
5 - 107
}
108
 
9 - 109
function resetSessionVars() {
110
    $_SESSION["searchTerm"] = '';
46 - 111
    $_SESSION["discogsTitle"] = '';
112
    $_SESSION["discogsArtist"] = '';
14 - 113
    $_SESSION['md5LastSearch'] = '';
65 - 114
    $_SESSION["currentView"] = 'All';
115
    $_SESSION["currentLayout"] = 'TableView';
116
    $_SESSION["barcode"]["Type"] = '';
117
    $_SESSION["barcode"]["Value"] = '';
9 - 118
 
65 - 119
    $_SESSION["resultArr"] = [];
9 - 120
 
65 - 121
    $_SESSION["lowestPrice"]["Used"] = 0.00;
122
    $_SESSION["lowestPrice"]["New"] = 0.00;
123
    $_SESSION["lowestPrice"]["CD"] = 0.00;
124
    $_SESSION["lowestPrice"]["Record"] = 0.00;
125
    $_SESSION["lowestPrice"]["Digital"] = 0.00;
126
    $_SESSION["lowestPrice"]["Book"] = 0.00;
127
    $_SESSION["lowestPrice"]["All"] = 0.00;
9 - 128
}
129
 
65 - 130
// search for items on all sites
72 - 131
function searchAll($searchKey, $batchFlag = false) {
65 - 132
    $arr = [];
133
    if ($_SESSION["filterCondition"]["New"]) {
134
        $arr = get_vendor($arr, 'get_ebay', $searchKey, constant("NEW"));
135
    }
72 - 136
    if (!$batchFlag) { updatePbFile(); }
65 - 137
    if ($_SESSION["filterCondition"]["New"]) {
138
        $arr = get_vendor($arr, 'get_linkshare', $searchKey, constant("NEW"));
139
    }
72 - 140
    if (!$batchFlag) { updatePbFile(); }
65 - 141
    if ($_SESSION["filterCondition"]["New"]) {
142
        $arr = get_vendor($arr, 'get_cjaffiliate', $searchKey, constant("NEW"));
143
    }
72 - 144
    if (!$batchFlag) { updatePbFile(); }
65 - 145
    if ($_SESSION["filterCondition"]["New"]) {
146
        $arr = get_vendor($arr, 'get_walmart', $searchKey, constant("NEW"));
147
    }
72 - 148
    if (!$batchFlag) { updatePbFile(); }
65 - 149
    if ($_SESSION["filterCondition"]["New"]) {
150
        $arr = get_vendor($arr, 'get_itunes', $searchKey, constant("NEW"));
151
    }
72 - 152
    if (!$batchFlag) { updatePbFile(); }
17 - 153
 
91 - 154
    $cntArr = count($arr);
81 - 155
    $arr = get_vendor($arr, 'get_amazon', $searchKey, constant("NEW"));
91 - 156
    if ($cntArr == count($arr)) {
157
        $arr = get_vendor($arr, 'get_amazon_scrape', $searchKey, constant("NEW"));
158
    }
81 - 159
    if (!$batchFlag) { updatePbFile(); }
160
 
83 - 161
    $arr = get_vendor($arr, 'get_impact', $searchKey, constant("NEW"));
162
    if (!$batchFlag) { updatePbFile(); }
163
 
65 - 164
    if ($_SESSION["filterCondition"]["Used"]) {
165
        $arr = get_vendor($arr, 'get_ebay', $searchKey, constant("USED"));
166
    }
72 - 167
    if (!$batchFlag) { updatePbFile(); }
17 - 168
 
66 - 169
//echo "<pre>";print_r($arr);echo "</pre";
24 - 170
 
65 - 171
    $arr = applyExchangeRates($arr);
172
    usort($arr, 'compare_price');
72 - 173
    if (!$batchFlag) { updatePbFile(); }
5 - 174
 
65 - 175
    return $arr;
5 - 176
}
177
 
20 - 178
// Search and merge
179
function get_vendor($arr, $func, $searchKey, $condition) {
65 - 180
    $arrTemp = $func($searchKey, $condition);
20 - 181
    return array_merge($arrTemp, $arr);
182
}
183
 
65 - 184
// check search filters
13 - 185
function checkSearchFilters() {
5 - 186
    $_SESSION["filterWarnings"] = "";
187
    $filterOk = true;
188
 
65 - 189
    if (!$_SESSION["filterCondition"]["New"] && !$_SESSION["filterCondition"]["Used"]) {
190
        $_SESSION["filterWarnings"] .= '<div class="alert alert-danger"><i class="fas fa-filter mr-1"></i> Please select at least one Condition (New or Used)</div>';
191
        $filterOk = false;
192
    }
5 - 193
 
65 - 194
    if (!$_SESSION["filterMediaType"]["CD"] && !$_SESSION["filterMediaType"]["Record"] && !$_SESSION["filterMediaType"]["Digital"] && !$_SESSION["filterMediaType"]["Book"]) {
195
        $_SESSION["filterWarnings"] .= '<div class="alert alert-danger"><i class="fas fa-filter mr-1"></i> Please select at least one Media Type (CD, Record, Digital or Book)</div>';
196
        $filterOk = false;
197
    }
13 - 198
 
65 - 199
    return ($filterOk);
5 - 200
}
201
 
21 - 202
// delete results from array that do not match the search filters
203
function applySearchFilter($arr) {
66 - 204
    unset($_SESSION['AdditionalFilterCounters']);
205
    unset($_SESSION['AdditionalFilters']);
65 - 206
    foreach ($arr as $key => $row) {
66 - 207
        if (!$_SESSION["filterMediaType"][$row["MediaType"]] || !$_SESSION["filterCondition"][$row["Condition"]]) {
21 - 208
            unset($arr[$key]);
66 - 209
        } else {
210
            if (isset($_SESSION['AdditionalFilterCounters']['Condition']['All'])) {
211
                $_SESSION['AdditionalFilterCounters']['Condition']['All']++;
212
            } else {
213
                $_SESSION['AdditionalFilterCounters']['Condition']['All'] = 1;
214
            }
215
 
216
            if (isset($_SESSION['AdditionalFilterCounters']['Merchant'][$row['Merchant']])) {
217
                $_SESSION['AdditionalFilterCounters']['Merchant'][$row['Merchant']]++;
218
            } else {
219
                $_SESSION['AdditionalFilterCounters']['Merchant'][$row['Merchant']] = 1;
220
                $_SESSION['AdditionalFilters']['Merchant'][$row['Merchant']] = true;
221
            }
222
 
223
            if (!empty($row['SellerName'])) {
224
                if (isset($_SESSION['AdditionalFilterCounters']['Seller'][$row['SellerName']])) {
225
                    $_SESSION['AdditionalFilterCounters']['Seller'][$row['SellerName']]++;
226
                } else {
227
                    $_SESSION['AdditionalFilterCounters']['Seller'][$row['SellerName']] = 1;
228
                    $_SESSION['AdditionalFilters']['Seller'][$row['SellerName']] = true;
229
                }
230
            }
231
 
232
            if (isset($_SESSION['AdditionalFilterCounters']['Condition'][$row['Condition']])) {
233
                $_SESSION['AdditionalFilterCounters']['Condition'][$row['Condition']]++;
234
            } else {
235
                $_SESSION['AdditionalFilterCounters']['Condition'][$row['Condition']] = 1;
236
                $_SESSION['AdditionalFilters']['Condition'][$row['Condition']] = true;
237
            }
238
 
239
            if (isset($_SESSION['AdditionalFilterCounters']['MediaType'][$row['MediaType']])) {
240
                $_SESSION['AdditionalFilterCounters']['MediaType'][$row['MediaType']]++;
241
            } else {
242
                $_SESSION['AdditionalFilterCounters']['MediaType'][$row['MediaType']] = 1;
243
                $_SESSION['AdditionalFilters']['MediaType'][$row['MediaType']] = true;
244
            }
245
 
246
            if (isset($_SESSION['AdditionalFilterCounters']['DetailCondition'][$row['DetailCondition']])) {
247
                $_SESSION['AdditionalFilterCounters']['DetailCondition'][$row['DetailCondition']]++;
248
            } else {
249
                $_SESSION['AdditionalFilterCounters']['DetailCondition'][$row['DetailCondition']] = 1;
250
                $_SESSION['AdditionalFilters']['DetailCondition'][$row['DetailCondition']] = true;
251
            }
252
 
253
            if (isset($_SESSION['AdditionalFilterCounters']['ShippingFrom'][$row['Country']])) {
254
                $_SESSION['AdditionalFilterCounters']['ShippingFrom'][$row['Country']]++;
255
            } else {
256
                $_SESSION['AdditionalFilterCounters']['ShippingFrom'][$row['Country']] = 1;
257
                $_SESSION['AdditionalFilters']['ShippingFrom'][$row['Country']] = true;
258
            }
65 - 259
        }
260
    }
23 - 261
 
66 - 262
    if (isset($_SESSION['AdditionalFilters']['Merchant'])) {
263
        ksort($_SESSION['AdditionalFilters']['Merchant'], SORT_NATURAL | SORT_FLAG_CASE);
264
    }
265
 
266
    if (isset($_SESSION['AdditionalFilters']['Seller'])) {
267
        ksort($_SESSION['AdditionalFilters']['Seller'], SORT_NATURAL | SORT_FLAG_CASE);
268
    }
269
 
270
    if (isset($_SESSION['AdditionalFilters']['Condition'])) {
271
        ksort($_SESSION['AdditionalFilters']['Condition'], SORT_NATURAL | SORT_FLAG_CASE);
272
    }
273
 
274
    if (isset($_SESSION['AdditionalFilters']['DetailCondition'])) {
275
        ksort($_SESSION['AdditionalFilters']['DetailCondition'], SORT_NATURAL | SORT_FLAG_CASE);
276
    }
277
 
278
    if (isset($_SESSION['AdditionalFilters']['ShippingFrom'])) {
279
        ksort($_SESSION['AdditionalFilters']['ShippingFrom'], SORT_NATURAL | SORT_FLAG_CASE);
280
    }
281
 
282
    if (isset($_SESSION['AdditionalFilters']['MediaType'])) {
283
        ksort($_SESSION['AdditionalFilters']['MediaType'], SORT_NATURAL | SORT_FLAG_CASE);
284
    }
285
 
21 - 286
    return $arr;
287
}
288
 
65 - 289
// filter view result table $_SESSION["resultArr"] for All, New, Used, Digital, or Book
290
function filterResults() {
291
    foreach ($_SESSION["resultArr"] as & $row) {
292
        if ($_SESSION["currentView"] == 'All') {
293
            $row["Show"] = true;
294
        }
295
        else {
66 - 296
            $row["Show"] = ($_SESSION["currentView"] == $row["Condition"] || $_SESSION["currentView"] == $row["MediaType"]);
65 - 297
        }
298
    }
5 - 299
}
13 - 300
 
66 - 301
// filter view result table $_SESSION["resultArr"] for detailed filter selection
302
function detailFilterResults($selArr) {
67 - 303
    if (!empty($selArr['filterCondition'])) {
304
        foreach($_SESSION['AdditionalFilters']['Condition'] as $key => $value) {
305
            $_SESSION['AdditionalFilters']['Condition'][$key] = false;
306
        }
307
        if (!is_array($selArr['filterCondition'])) { $selArr['filterCondition'] = [ $selArr['filterCondition'] ];}
308
        foreach($selArr['filterCondition'] as $value) {
309
            $_SESSION['AdditionalFilters']['Condition'][$value] = true;
310
        }
311
    } else {
68 - 312
        $selArr['filterCondition'] = [];
77 - 313
        if (!empty($_SESSION['AdditionalFilters']['Condition'])) {
314
            foreach($_SESSION['AdditionalFilters']['Condition'] as $key => $value) {
315
                if ($value) {
316
                    $selArr['filterCondition'][] = $key;
317
                }
68 - 318
            }
319
        }
66 - 320
    }
321
 
67 - 322
    if (!empty($selArr['filterMediaType'])) {
323
        foreach($_SESSION['AdditionalFilters']['MediaType'] as $key => $value) {
324
            $_SESSION['AdditionalFilters']['MediaType'][$key] = false;
325
        }
326
        if (!is_array($selArr['filterMediaType'])) { $selArr['filterMediaType'] = [ $selArr['filterMediaType'] ];}
327
        foreach($selArr['filterMediaType'] as $value) {
328
            $_SESSION['AdditionalFilters']['MediaType'][$value] = true;
329
        }
330
    } else {
68 - 331
        $selArr['filterMediaType'] = [];
77 - 332
        if (!empty($_SESSION['AdditionalFilters']['MediaType'])) {
333
            foreach($_SESSION['AdditionalFilters']['MediaType'] as $key => $value) {
334
                if ($value) {
335
                    $selArr['filterMediaType'][] = $key;
336
                }
68 - 337
            }
338
        }
66 - 339
    }
340
 
67 - 341
    if (!empty($selArr['filterShipFrom'])) {
342
        foreach($_SESSION['AdditionalFilters']['ShippingFrom'] as $key => $value) {
343
            $_SESSION['AdditionalFilters']['ShippingFrom'][$key] = false;
344
        }
345
        if (!is_array($selArr['filterShipFrom'])) { $selArr['filterShipFrom'] = [ $selArr['filterShipFrom'] ];}
346
        foreach($selArr['filterShipFrom'] as $value) {
347
            $_SESSION['AdditionalFilters']['ShippingFrom'][$value] = true;
348
        }
349
    } else {
68 - 350
        $selArr['filterShipFrom'] = [];
77 - 351
        if (!empty($_SESSION['AdditionalFilters']['ShippingFrom'])) {
352
            foreach($_SESSION['AdditionalFilters']['ShippingFrom'] as $key => $value) {
353
                if ($value) {
354
                    $selArr['filterShipFrom'][] = $key;
355
                }
68 - 356
            }
357
        }
66 - 358
    }
359
 
67 - 360
    if (!empty($selArr['filterMerchant'])) {
361
        foreach($_SESSION['AdditionalFilters']['Merchant'] as $key => $value) {
362
            $_SESSION['AdditionalFilters']['Merchant'][$key] = false;
363
        }
364
        if (!is_array($selArr['filterMerchant'])) { $selArr['filterMerchant'] = [ $selArr['filterMerchant'] ];}
365
        foreach($selArr['filterMerchant'] as $value) {
366
            $_SESSION['AdditionalFilters']['Merchant'][$value] = true;
367
        }
368
    } else {
68 - 369
        $selArr['filterMerchant'] = [];
77 - 370
        if (!empty($_SESSION['AdditionalFilters']['Merchant'])) {
371
            foreach($_SESSION['AdditionalFilters']['Merchant'] as $key => $value) {
372
                if ($value) {
373
                    $selArr['filterMerchant'][] = $key;
374
                }
68 - 375
            }
376
        }
66 - 377
    }
378
 
379
    foreach ($_SESSION["resultArr"] as & $row) {
380
        $row["Show"] = true;
381
 
382
        if (!in_array($row["Condition"], $selArr['filterCondition']) ||
383
            !in_array($row["MediaType"], $selArr['filterMediaType']) ||
384
            !in_array($row["Merchant"], $selArr['filterMerchant']) ||
385
            !in_array($row["Country"], $selArr['filterShipFrom'])) {
386
            $row["Show"] = false;
387
        }
388
    }
389
}
390
 
391
function resetDetailFilter() {
392
    if (isset($_SESSION['AdditionalFilters']['Merchant'])) {
393
        foreach($_SESSION['AdditionalFilters']['Merchant'] as $key => $field) {
394
            $_SESSION['AdditionalFilters']['Merchant'][$key] = true;
395
        }
396
    }
397
 
398
    if (isset($_SESSION['AdditionalFilters']['Seller'])) {
399
        foreach($_SESSION['AdditionalFilters']['Seller'] as $key => $field) {
400
            $_SESSION['AdditionalFilters']['Seller'][$key] = true;
401
        }
402
    }
403
 
404
    if (isset($_SESSION['AdditionalFilters']['Condition'])) {
405
        foreach($_SESSION['AdditionalFilters']['Condition'] as $key => $field) {
406
            $_SESSION['AdditionalFilters']['Condition'][$key] = true;
407
        }
408
    }
409
 
410
    if (isset($_SESSION['AdditionalFilters']['DetailCondition'])) {
411
        foreach($_SESSION['AdditionalFilters']['DetailCondition'] as $key => $field) {
412
            $_SESSION['AdditionalFilters']['DetailCondition'][$key] = true;
413
        }
414
    }
415
 
416
    if (isset($_SESSION['AdditionalFilters']['ShippingFrom'])) {
417
        foreach($_SESSION['AdditionalFilters']['ShippingFrom'] as $key => $field) {
418
            $_SESSION['AdditionalFilters']['ShippingFrom'][$key] = true;
419
        }
420
    }
421
 
422
    if (isset($_SESSION['AdditionalFilters']['MediaType'])) {
423
        foreach($_SESSION['AdditionalFilters']['MediaType'] as $key => $field) {
424
            $_SESSION['AdditionalFilters']['MediaType'][$key] = true;
425
        }
426
    }
107 - 427
 
66 - 428
    foreach ($_SESSION["resultArr"] as & $row) {
429
        $row["Show"] = true;
430
    }
431
}
432
 
65 - 433
// print result table or card deck
59 - 434
function printResult() {
435
    if ($_SESSION["currentLayout"] == 'TableView') {
78 - 436
        return buildTable($_SESSION["resultArr"]);
65 - 437
    }
438
    else /* CardView */ {
78 - 439
        return buildCardDeck($_SESSION["resultArr"]);
59 - 440
    }
441
}
442
 
65 - 443
// build HTML table from array
78 - 444
function buildTable($arr) {
66 - 445
    global $mediaTypeTextArr;
446
    global $mediaTypeIconArr;
86 - 447
    global $buyItNowTooltip;
107 - 448
 
59 - 449
    $str = "";
1 - 450
 
78 - 451
    if (count($arr) > 0) {
81 - 452
        $str .= "<div class=\"table\">"; // bugbug responsive?
68 - 453
        $str .= "<table class=\"table table-striped table-condensed table-hover small bg-info\">";
81 - 454
        $str .= "<thead class=\"thead-dark table-header-sticky\"><tr><th>Image</th><th class=\"text-left\">Title / Merchant</th><th>Condition</th><th class=\"hide-small\">Price</th><th class=\"hide-small\">S/H</th><th>Total</th><th class=\"hide-extra-small\"></th></tr></thead>";
65 - 455
        $str .= "<tbody>";
17 - 456
 
78 - 457
        foreach ($arr as $row) {
65 - 458
            if (!$row["Show"]) {
459
                continue;
460
            }
1 - 461
 
107 - 462
            $href = "href=\"" . $row["URL"] . "\" target=\"_blank\" rel=\"nofollow noreferrer noopener\" onclick=\"saveTransfer('" . $row["URL"] . "'); return true;\"";
59 - 463
            $title = $row["Title"];
464
            if (mb_strlen($row["Title"], 'UTF-8') > MAXTITLELENGTH) {
65 - 465
                $title = mb_substr($row["Title"], 0, MAXTITLELENGTH, 'UTF-8') . '...';
59 - 466
            }
5 - 467
 
65 - 468
            $str .= "<tr>";
13 - 469
 
9 - 470
            // Image
107 - 471
            $str .= "<td><a " . $href . " data-toggle=\"tooltip\" title=\"" . $buyItNowTooltip . "\"><img class=\"img-fluid lazyload\" src=\"data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" data-src=\"" . $row["Image"] . "\" alt=\"Item Image\"></a></td>";
1 - 472
 
9 - 473
            // Title / Merchant
86 - 474
            $str .= "<td class=\"text-left\"><span class=\"font-weight-bold\"><a class=\"bg-info\" " . $href . " data-toggle=\"tooltip\" title=\"" . $buyItNowTooltip . "\">" . $title . "</a></span>";
58 - 475
            $str .= "<br/><br/>";
65 - 476
            $str .= "<span class=\"font-weight-bold\">" . $row["Merchant"] . "</span>";
477
            if ($row["FeedbackScore"] != - 1) {
478
                $str .= "<span class=\"hide-extra-small\"><br/>" . $row["SellerName"] . " (" . number_format($row["FeedbackScore"], 0, "", ",") . " / " . $row["FeedbackPercent"] . "%)</span>";
479
            }
480
            else if (!empty($row["SellerName"])) {
481
                $str .= "<span class=\"hide-extra-small\"><br/>" . $row["SellerName"] . "</span>";
482
            }
483
            if (!empty($row["TimeLeft"])) {
24 - 484
                $str .= "<br>" . $row["TimeLeft"];
65 - 485
            }
486
            $str .= "</td>";
1 - 487
 
9 - 488
            // Condition
65 - 489
            $str .= "<td>";
66 - 490
            $mediaTypeIcon = 'media-icon ' . $mediaTypeIconArr[$row["MediaType"]];
491
            $tooltip = $mediaTypeTextArr[$row["MediaType"]];
492
            $str .= "<span class=\"font-weight-bold\">" . $row["DetailCondition"] . "</span>";
65 - 493
            $str .= "<br/><br/>";
66 - 494
            $str .= "<i class=\"" . $mediaTypeIcon . "\" title=\"" . $tooltip . "\" data-toggle=\"tooltip\" data-placement=\"right\" data-delay=\"200\"></i>";
65 - 495
            $str .= "</td>";
5 - 496
 
9 - 497
            // Price
65 - 498
            $str .= "<td class=\"hide-small\">" . print_monetary($row["Price"], $row["Currency"]);
499
            if ($row["Currency"] != $_SESSION["buyer"]["Currency"]) {
500
                $str .= "<br/>&asymp; " . print_monetary($row["ConvertedPrice"], $_SESSION["buyer"]["Currency"]);
501
            }
502
            if ($row["BestOffer"] == "true") {
503
                $str .= "<br>Best Offer Accepted";
504
            }
505
            $str .= "</td>";
1 - 506
 
9 - 507
            // Shipping and Handling Cost
65 - 508
            $str .= "<td class=\"hide-small\">";
509
            if ($row["ShippingCost"] == 0.00) {
510
                $str .= "Free Shipping";
511
            }
512
            else {
513
                $str .= print_monetary($row["ShippingCost"], $row["ShippingCurrency"]);
81 - 514
                if ($row["ShippingEstimated"]) {
515
                    $str .= "*";
516
                }
65 - 517
            }
518
            if ($row["ShippingCost"] > 0.00 && $row["ShippingCurrency"] != $_SESSION["buyer"]["Currency"]) {
519
                $str .= "<br/>&asymp; " . print_monetary($row["ConvertedShippingCost"], $_SESSION["buyer"]["Currency"]);
520
            }
24 - 521
            if ($row["HandlingTime"] > 0) {
522
                $str .= "<br>Handling Time " . $row["HandlingTime"] . " day" . ($row["HandlingTime"] > 1 ? "s" : "");
523
            }
524
            if ($row["ShippingCost"] > 0.00 && $row["FreeShippingCap"] > 0) {
525
                $str .= "<br>Free Shipping over " . print_monetary($row["FreeShippingCap"], $_SESSION["buyer"]["Currency"]);
526
            }
108 - 527
            $str .= "<br/><img class=\"img-fluid lazyload\" title=\"Ships from " . getCountry($row["Country"]) . "\" data-toggle=\"tooltip\" data-placement=\"right\" data-delay=\"200\" src=\"data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" data-src=\"" . timeStampUrl("images/flags/" . $row["Country"] . ".png") . "\" alt=\"" . getCountry($row["Country"]) . " Flag\"></td>";
1 - 528
 
9 - 529
            // Total Price
65 - 530
            $str .= "<td class=\"font-weight-bolder\">" . print_monetary($row["ConvertedTotalPrice"], $_SESSION["buyer"]["Currency"]) . "</td>";
1 - 531
 
9 - 532
            // Link
54 - 533
            if ($row["Merchant"] == "iTunes") {
66 - 534
                if ($row["MediaType"] == "Digital") {
108 - 535
                    $badge = timeStampUrl("images/US-UK_Apple_Music_Badge_RGB.svg");
65 - 536
                }
537
                else {
108 - 538
                    $badge = timeStampUrl("images/US_UK_Apple_Books_Badge_Get_RGB_071818.svg");
54 - 539
                }
107 - 540
                $linkImage = "<a class=\"btn\" title=\"" . $buyItNowTooltip . "\" aria-label=\"Go to store\" data-toggle=\"tooltip\" role=\"button\" " . $href . "><img class=\"lazyload\" src=\"data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" data-src=\"" . $badge . "\" alt=\"iTunes Badge\"></a>";
81 - 541
            } else if (strpos($row["Merchant"], "eBay") !== false) {
108 - 542
                $linkImage = "<a class=\"btn\" title=\"" . $buyItNowTooltip . "\" aria-label=\"Go to store\" data-toggle=\"tooltip\" role=\"button\" " . $href . "><img class=\"lazyload\" src=\"data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" data-src=\"" . timeStampUrl("images/ebay-right-now.gif") . "\" alt=\"iTunes Badge\"></a>";
81 - 543
            } else if (strpos($row["Merchant"], "Amazon") !== false) {
108 - 544
                $linkImage = "<a class=\"btn\" title=\"" . $buyItNowTooltip . "\" aria-label=\"Go to store\" data-toggle=\"tooltip\" role=\"button\" " . $href . "><img class=\"lazyload\" src=\"data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" data-src=\"" . timeStampUrl("images/amazon-buy3.gif") . "\" alt=\"iTunes Badge\"></a>";
81 - 545
            } else {
107 - 546
                $linkImage = "<a class=\"btn btn-danger\" title=\"" . $buyItNowTooltip . "\" aria-label=\"Go to store\" data-toggle=\"tooltip\" role=\"button\" " . $href . "><i class=\"fas fa-shopping-cart btn-shop\"></i></a>";
54 - 547
            }
65 - 548
            $str .= "<td class=\"hide-extra-small text-center\">" . $linkImage . "</td>";
1 - 549
 
65 - 550
            $str .= "</tr>";
9 - 551
        }
17 - 552
 
65 - 553
        $str .= "</tbody>";
554
        $str .= "<tfoot class=\"text-right\"><tr><td class=\"font-italic\" colspan=\"7\">Prices retrieved on " . gmdate("Y-m-d H:i") . " UTC<br>Daily exchange rates update</td></tr></tfoot>";
555
        $str .= "</table>";
556
        $str .= "</div>";
557
    }
558
    else {
59 - 559
        $str = printNoResultsWarning();
9 - 560
    }
1 - 561
 
65 - 562
    return ($str);
59 - 563
}
1 - 564
 
65 - 565
// build HTML card deck from array
78 - 566
function buildCardDeck($arr) {
66 - 567
    global $mediaTypeTextArr;
568
    global $mediaTypeIconArr;
86 - 569
    global $buyItNowTooltip;
66 - 570
 
65 - 571
    $str = "";
59 - 572
 
78 - 573
    if (count($arr) > 0) {
61 - 574
        $str .= "<div class=\"card-deck small\">";
59 - 575
 
78 - 576
        foreach ($arr as $row) {
65 - 577
            if (!$row["Show"]) {
578
                continue;
579
            }
59 - 580
 
107 - 581
            $href = "href=\"" . $row["URL"] . "\" target=\"_blank\" rel=\"nofollow noreferrer noopener\" onclick=\"saveTransfer('" . $row["URL"] . "'); return true;\"";
59 - 582
            $title = $row["Title"];
583
            if (mb_strlen($row["Title"], 'UTF-8') > MAXTITLELENGTH) {
65 - 584
                $title = mb_substr($row["Title"], 0, MAXTITLELENGTH, 'UTF-8') . '...';
59 - 585
            }
586
 
65 - 587
            $str .= "<div class=\"card m-2 shadow mx-auto result-card\">";
59 - 588
 
589
            // Image
107 - 590
            $str .= "<a class=\"p-0 m-0 bg-light text-center result-image\" " . $href . " data-toggle=\"tooltip\" title=\"" . $buyItNowTooltip . "\"><img class=\"p-0 m-0 responsive-image lazyload\" src=\"data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" data-src=\"" . $row["Image"] . "\" alt=\"Item Image\"></a>";
59 - 591
 
65 - 592
            $str .= "<div class=\"card-body bg-light d-flex flex-column\">";
59 - 593
            // Title / Merchant
86 - 594
            $str .= "<p class=\"card-title font-weight-bold\"><a " . $href . " data-toggle=\"tooltip\" title=\"" . $buyItNowTooltip . "\">" . $title . "</a></p>";
65 - 595
            $str .= "<div class=\"card-text mt-auto\"><span class=\"font-weight-bold\">" . $row["Merchant"] . "</span>";
596
            $str .= "<br>";
59 - 597
 
66 - 598
            // Condition / MediaType
599
            $mediaTypeIcon = 'media-icon ' . $mediaTypeIconArr[$row["MediaType"]];
600
            $tooltip = $mediaTypeTextArr[$row["MediaType"]];
601
            $str .= $row["DetailCondition"];
602
            $str .= "<i class=\"float-right " . $mediaTypeIcon . "\" title=\"" . $tooltip . "\" data-toggle=\"tooltip\" data-placement=\"right\" data-delay=\"200\"></i>";
65 - 603
            $str .= "<br>";
59 - 604
 
605
            // Total Price
65 - 606
            $str .= "<span class=\"font-weight-bolder\">" . print_monetary($row["ConvertedTotalPrice"], $_SESSION["buyer"]["Currency"]) . "</span>";
60 - 607
            $str .= "</div>";
59 - 608
 
609
            $str .= "</div>";
610
 
611
            // Link / Ships from Flag
64 - 612
            $str .= "<div class=\"card-footer bg-dark\">";
60 - 613
            $str .= "<div class=\"row\">";
65 - 614
            $str .= "<div class=\"col-9\">";
59 - 615
            if ($row["Merchant"] == "iTunes") {
66 - 616
                if ($row["MediaType"] == "Digital") {
108 - 617
                    $badge = timeStampUrl("images/US-UK_Apple_Music_Badge_RGB.svg");
65 - 618
                }
619
                else {
108 - 620
                    $badge = timeStampUrl("images/US_UK_Apple_Books_Badge_Get_RGB_071818.svg");
59 - 621
                }
107 - 622
                $linkImage = "<a class=\"btn p-0 m-0\" title=\"" . $buyItNowTooltip . "\" aria-label=\"Go to store\" data-toggle=\"tooltip\" role=\"button\" " . $href . "><img class=\"img-fluid p-0 m-0 lazyload\" src=\"data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" data-src=\"" . $badge . "\" alt=\"iTunes Badge\"></a>";
81 - 623
            } else if (strpos($row["Merchant"], "eBay") !== false) {
108 - 624
                $linkImage = "<a class=\"btn p-0 m-0\" title=\"" . $buyItNowTooltip . "\" aria-label=\"Go to store\" data-toggle=\"tooltip\" role=\"button\" " . $href . "><img class=\"img-fluid p-0 m-0 lazyload\" src=\"data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" data-src=\"" . timeStampUrl("images/ebay-right-now.gif") . "\" alt=\"iTunes Badge\"></a>";
81 - 625
            } else if (strpos($row["Merchant"], "Amazon") !== false) {
108 - 626
                $linkImage = "<a class=\"btn p-0 m-0\" title=\"" . $buyItNowTooltip . "\" aria-label=\"Go to store\" data-toggle=\"tooltip\" role=\"button\" " . $href . "><img class=\"img-fluid p-0 m-0 lazyload\" src=\"data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" data-src=\"" . timeStampUrl("images/amazon-buy3.gif") . "\" alt=\"iTunes Badge\"></a>";
65 - 627
            }
628
            else {
107 - 629
                $linkImage = "<a class=\"btn btn-danger m-0\" title=\"" . $buyItNowTooltip . "\" aria-label=\"Go to store\" data-toggle=\"tooltip\" role=\"button\" " . $href . "><i class=\"fas fa-shopping-cart\"></i></a>";
59 - 630
            }
65 - 631
            $str .= $linkImage;
59 - 632
            $str .= "</div>";
65 - 633
            $str .= "<div class=\"col-3\">";
108 - 634
            $str .= "<img class=\"float-right lazyload\" title=\"Ships from " . getCountry($row["Country"]) . "\" data-toggle=\"tooltip\" data-placement=\"right\" data-delay=\"200\" src=\"data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" data-src=\"" . timeStampUrl("images/flags/" . $row["Country"] . ".png") . "\" alt=\"" . getCountry($row["Country"]) . " Flag\">";
60 - 635
            $str .= "</div>";
65 - 636
            $str .= "</div>";
637
            $str .= "</div>";
59 - 638
 
65 - 639
            $str .= "</div>";
59 - 640
        }
641
 
65 - 642
        $str .= "</div>";
643
        $str .= "<div class=\"py-2 text-right\"><p class=\"font-italic\">Prices retrieved on " . gmdate("Y-m-d H:i") . " UTC<br>Daily exchange rates update</p></div>";
644
    }
645
    else {
59 - 646
        $str = printNoResultsWarning();
647
    }
648
 
65 - 649
    return ($str);
5 - 650
}
651
 
65 - 652
// print directions when no results are found
59 - 653
function printNoResultsWarning() {
654
    $str = "<div class=\"text-center bg-warning p-3 rounded\">";
104 - 655
    $str .= "<p class=\"display-5 font-weight-bold\">Your search returned no store offers</p>";
59 - 656
    $str .= "<p>You may want to try the following:</p>";
70 - 657
    $str .= "<ul><li>Check the spelling</li><li>Try using fewer words</li><li>Check the search filter (<i class=\"fas fa-filter\"></i>) if you used one</li><li>Try using artist and title if you used a barcode; some albums have been released under various barcodes</li></ul>";
59 - 658
    $str .= "</div>";
659
 
660
    return $str;
661
}
662
 
66 - 663
function printResultHeader() {
664
    $str = '';
665
    $str .= '<nav class="navbar bg-black mt-2 pb-0">';
666
    $str .= '<ul class="nav nav-tabs">';
107 - 667
/*
66 - 668
    $str .= '  <li class="nav-item border-0">';
669
    $str .= '    <a id="quickTab" class="nav-link';
68 - 670
    $str .= ($_SESSION["currentView"] == 'Apply' ? ' bg-white invert' : ' active bg-white') . '" href="#quickFilter">Quick</a>';
66 - 671
    $str .= '  </li>';
107 - 672
*/
66 - 673
    $str .= '  <li class="nav-item border-0">';
107 - 674
    $str .= '    <a id="detailTab" class="nav-link active bg-white" href="#detailFilter">Filter <span id="detailTabArrow"><i class="fas fa-caret-down"></i></span></a>';
66 - 675
    $str .= '  </li>';
676
    $str .= '</ul>';
677
    $str .= '<span class="ml-auto">';
107 - 678
    if ($_SESSION["currentLayout"] == 'CardView') {
679
        $str .= '    <button name="submit" value="TableView" type="' . getButtonType("TableView") . '" class="btn btn-sm filterButtonSmall btn-primary active"';
680
        $str .= ' data-toggle="tooltip" title="Table View" aria-label="Results Table View" onclick="$(this).tooltip(\'hide\');"><span class="display-6 font-weight-bolder"><i class="fas fa-th-list"></i></span></button>';
681
    } else {
682
        $str .= '    <button name="submit" value="CardView" aria-label="Results Card View" type="' . getButtonType("CardView") . '" class="btn btn-sm filterButtonSmall btn-primary active"';
683
        $str .= ' data-toggle="tooltip" title="Card View" onclick="$(this).tooltip(\'hide\');"><span class="display-6 font-weight-bolder"><i class="fas fa-th-large"></i></span></button>';
684
    }
66 - 685
    $str .= '</span>';
686
    $str .= '<span class="navbar-text text-white float-right ml-3">Showing ' . count(array_filter($_SESSION["resultArr"], function ($entry) { return ($entry['Show'] === true); })) . ' of ' . count($_SESSION["resultArr"]) . '</span>';
687
    $str .= '</nav>';
68 - 688
    $str .= '<div class="tab-content mb-3 bg-white">';
107 - 689
/*
66 - 690
    $str .= '  <div id="quickFilter" class="tab-pane';
691
    $str .= ($_SESSION["currentView"] == 'Apply' ? '' : ' active') . '"><br>';
107 - 692
    $str .=  resultHeader();
66 - 693
    $str .= '  </div>';
107 - 694
*/
695
    $str .= '  <div id="detailFilter" class="container tab-pane bg-white"><br>';
66 - 696
    $str .= detailResultHeader();
697
    $str .= '  </div>';
698
    $str .= '</div>';
699
 
700
  return $str;
701
}
702
 
107 - 703
/*
65 - 704
// print summary/header on top of listing table
66 - 705
function resultHeader() {
11 - 706
    $str = '<div class="d-flex flex-wrap justify-content-center p-2">';
65 - 707
    $str .= '    <button name="submit" value="All" type="' . getButtonType("All") . '" class="btn mx-2 filterButton ' . getBackgroundColor("All") . '"';
708
    if ($_SESSION["lowestPrice"]["All"] <= 0) {
709
        $str .= ' disabled';
710
    }
711
    $str .= '><span class="display-6 font-weight-bolder">All</span><span class="display-7"> from</span><br><span class="display-6 font-weight-bolder">' . print_monetary($_SESSION["lowestPrice"]["All"], $_SESSION["buyer"]["Currency"]) . '</span>';
66 - 712
    $str .= '    <span class="badge">' . (isset($_SESSION['AdditionalFilterCounters']['Condition']['All']) ? $_SESSION['AdditionalFilterCounters']['Condition']['All'] : '') . '</span></button>';
62 - 713
    $str .= '    <button name="submit" value="New" type="' . getButtonType("New") . '" class="btn mx-2 filterButton ' . getBackgroundColor("New") . '"';
65 - 714
    if ($_SESSION["lowestPrice"]["New"] <= 0) {
715
        $str .= ' disabled';
716
    }
717
    $str .= '><span class="display-6 font-weight-bolder">New</span><span class="display-7"> from</span><br><span class="display-6 font-weight-bolder">' . print_monetary($_SESSION["lowestPrice"]["New"], $_SESSION["buyer"]["Currency"]) . '</span>';
66 - 718
    $str .= '    <span class="badge">' . (isset($_SESSION['AdditionalFilterCounters']['Condition']['New']) ? $_SESSION['AdditionalFilterCounters']['Condition']['New'] : '') . '</span></button>';
62 - 719
    $str .= '    <button name="submit" value="Used" type="' . getButtonType("Used") . '" class="btn mx-2 filterButton ' . getBackgroundColor("Used") . '"';
65 - 720
    if ($_SESSION["lowestPrice"]["Used"] <= 0) {
721
        $str .= ' disabled';
722
    }
20 - 723
    $str .= '><span class="display-6 font-weight-bolder">Used</span><span class="display-7"> from</span><br><span class="display-6 font-weight-bolder">' . print_monetary($_SESSION["lowestPrice"]["Used"], $_SESSION["buyer"]["Currency"]) . '</span>';
66 - 724
    $str .= '    <span class="badge">' . (isset($_SESSION['AdditionalFilterCounters']['Condition']['Used']) ? $_SESSION['AdditionalFilterCounters']['Condition']['Used'] : '') . '</span></button>';
725
 
726
    $str .= '</div>';
727
 
728
    return $str;
729
}
107 - 730
*/
66 - 731
 
107 - 732
// print summary/header on top of listing table
66 - 733
function detailResultHeader() {
734
    global $mediaTypeTextArr;
735
    global $mediaTypeIconArr;
736
 
737
    $str = '';
738
    $str .= '            <form id="detailFilterForm">';
739
    $str .= '                <input type="hidden" name="sessionTab" value="' . MySessionHandler::getSessionTab() . '">';
740
    $str .= '                <div class="">';
741
    $str .= '                    <div class="card-group">';
742
    $str .= '';
743
 
744
    // Condition
745
    if (isset($_SESSION['AdditionalFilterCounters']['Condition'])) {
746
        $str .= '                        <div class="card m-2">';
747
        $str .= '                            <div class="card-header font-weight-bold">Condition</div>';
748
        $str .= '                            <div class="card-body">';
749
        $cnt = count($_SESSION['AdditionalFilterCounters']['Condition']);
750
        foreach($_SESSION['AdditionalFilters']['Condition'] as $key => $value) {
751
            $str .= '                                <div class="form-check">';
752
            $str .= '                                    <label class="form-check-label">';
753
            $str .= '                                        <input name="filterCondition[]" type="checkbox" value="' . $key . '" class="form-check-input"';
754
            $str .= ($value ? " checked" : "");
755
            $str .= ($cnt > 2 ? "" : " disabled");
756
            $str .= '>' . $key . '<span class="badge badge-pill badge-dark ml-2">' . $_SESSION['AdditionalFilterCounters']['Condition'][$key] . '</span>';
757
            $str .= '                                    </label>';
758
            $str .= '                                </div>';
759
        }
760
        $str .= '                            </div>';
761
        $str .= '                        </div>';
13 - 762
    }
66 - 763
 
764
    // Media Type
765
    if (isset($_SESSION['AdditionalFilterCounters']['MediaType'])) {
766
        $str .= '                        <div class="card m-2">';
767
        $str .= '                            <div class="card-header font-weight-bold">Media Type</div>';
768
        $str .= '                            <div class="card-body">';
769
        $cnt = count($_SESSION['AdditionalFilterCounters']['MediaType']);
770
        foreach($_SESSION['AdditionalFilters']['MediaType'] as $key => $value) {
771
            $str .= '                                <div class="form-check">';
772
            $str .= '                                    <label class="form-check-label">';
773
            $str .= '                                        <input name="filterMediaType[]" type="checkbox" value="' . $key . '" class="form-check-input"';
774
            $str .= ($value ? " checked" : "");
775
            $str .= ($cnt > 1 ? "" : " disabled");
776
            $str .= '><i class="' . $mediaTypeIconArr[$key] . '"></i> ' . $mediaTypeTextArr[$key];
777
            $str .= '<span class="badge badge-pill badge-dark ml-2">' . $_SESSION['AdditionalFilterCounters']['MediaType'][$key] . '</span>';
778
            $str .= '                                    </label>';
779
            $str .= '                                </div>';
780
        }
781
        $str .= '                            </div>';
782
        $str .= '                        </div>';
65 - 783
    }
59 - 784
 
66 - 785
    // Merchant
786
    if (isset($_SESSION['AdditionalFilterCounters']['Merchant'])) {
787
        $str .= '                        <div class="card m-2">';
788
        $str .= '                            <div class="card-header font-weight-bold">Merchant</div>';
789
        $str .= '                            <div class="card-body">';
790
        $cnt = count($_SESSION['AdditionalFilterCounters']['Merchant']);
791
        foreach($_SESSION['AdditionalFilters']['Merchant'] as $key => $value) {
792
            $str .= '                                <div class="form-check">';
793
            $str .= '                                    <label class="form-check-label">';
794
            $str .= '                                        <input name="filterMerchant[]" type="checkbox" value="' . $key . '" class="form-check-input"';
795
            $str .= ($value ? " checked" : "");
796
            $str .= ($cnt > 1 ? "" : " disabled");
797
            $str .= '>' . $key . '<span class="badge badge-pill badge-dark ml-2">' . $_SESSION['AdditionalFilterCounters']['Merchant'][$key] . '</span>';
798
            $str .= '                                    </label>';
799
            $str .= '                                </div>';
800
        }
801
        $str .= '                            </div>';
802
        $str .= '                        </div>';
803
    }
1 - 804
 
66 - 805
    // Shipping From
806
    if (isset($_SESSION['AdditionalFilterCounters']['ShippingFrom'])) {
807
        $str .= '                        <div class="card m-2">';
808
        $str .= '                            <div class="card-header font-weight-bold">Shipping From</div>';
809
        $str .= '                            <div class="card-body">';
810
        $cnt = count($_SESSION['AdditionalFilterCounters']['ShippingFrom']);
811
        foreach($_SESSION['AdditionalFilters']['ShippingFrom'] as $key => $value) {
812
            $str .= '                                <div class="form-check">';
813
            $str .= '                                    <label class="form-check-label">';
814
            $str .= '                                        <input name="filterShipFrom[]" type="checkbox" value="' . $key . '" class="form-check-input"';
815
            $str .= ($value ? " checked" : "");
816
            $str .= ($cnt > 1 ? "" : " disabled");
108 - 817
            $str .= '><img class="img-fluid lazyload" title="Ships from ' . getCountry($key) . '" data-toggle="tooltip" data-delay="200" src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="' . timeStampUrl("images/flags/" . $key . ".png") . '" alt="' . getCountry($key) . ' Flag"><span class="badge badge-pill badge-dark ml-2">' . $_SESSION['AdditionalFilterCounters']['ShippingFrom'][$key] . '</span>';
66 - 818
            $str .= '                                    </label>';
819
            $str .= '                                </div>';
820
        }
821
        $str .= '                            </div>';
822
        $str .= '                        </div>';
823
    }
824
 
825
    $str .= '                    </div>';
826
    $str .= '                </div>';
827
    $str .= '';
828
    $str .= '                <div class="p-2">';
829
    $str .= '                    <button type="submit" class="btn btn-success detailFilterButton" name="submit" value="Apply">Apply</button>';
830
    $str .= '                    <button type="submit" class="btn btn-danger detailFilterButton" name="submit" value="Reset">Reset</button>';
831
    $str .= '                </div>';
832
    $str .= '            </form>';
833
 
65 - 834
    return $str;
5 - 835
}
1 - 836
 
65 - 837
// get top button background color
838
function getBackgroundColor($sel) {
839
    if ($_SESSION["currentView"] == $sel || $_SESSION["currentLayout"] == $sel) {
840
        return ("btn-primary active");
841
    }
5 - 842
 
65 - 843
    return ("btn-primary invert");
13 - 844
}
5 - 845
 
65 - 846
// get top button type
847
function getButtonType($sel) {
848
    if ($_SESSION["currentView"] == $sel || $_SESSION["currentLayout"] == $sel) {
849
        return ("button");
850
    }
5 - 851
 
65 - 852
    return ("submit");
13 - 853
}
5 - 854
 
65 - 855
// compare price for sort low to high
856
function compare_price($a, $b) {
857
    return strnatcmp($a['ConvertedTotalPrice'], $b['ConvertedTotalPrice']);
5 - 858
}
13 - 859
 
65 - 860
// print monetary values with correct symbol and thousands/decimal delimiters
861
function print_monetary($num, $curr) {
862
    if ($curr == "USD") {
863
        return ("$" . number_format($num, 2, '.', ','));
864
    }
865
    else if ($curr == "CAD") {
866
        return ("C $" . number_format($num, 2, '.', ','));
867
    }
868
    else if ($curr == "EUR") {
869
        return (number_format($num, 2, ',', '.') . "&euro;");
870
    }
871
    else if ($curr == "GBP") {
872
        return ("&pound;" . number_format($num, 2, '.', ','));
873
    }
874
    else if ($curr == "AUD") {
875
        return ("AU $" . number_format($num, 2, '.', ','));
876
    }
1 - 877
 
65 - 878
    return ($curr . " " . number_format($num, 2, '.', ','));
5 - 879
}
1 - 880
 
65 - 881
// find lowest used / new prices
66 - 882
function findLowestCondition($condition) {
65 - 883
    foreach ($_SESSION["resultArr"] as $row) {
884
        if (!$row["Show"]) {
885
            continue;
886
        }
1 - 887
 
66 - 888
        if ($condition == $row["Condition"]) {
65 - 889
            return ($row["ConvertedTotalPrice"]);
890
        }
891
    }
5 - 892
 
65 - 893
    return (0);
5 - 894
}
895
 
65 - 896
// find lowest cd, record, digital and book prices
66 - 897
function findLowestMediaType($mediaType) {
65 - 898
    foreach ($_SESSION["resultArr"] as $row) {
899
        if (!$row["Show"]) {
900
            continue;
901
        }
20 - 902
 
66 - 903
        if ($mediaType == $row["MediaType"]) {
65 - 904
            return ($row["ConvertedTotalPrice"]);
905
        }
906
    }
20 - 907
 
65 - 908
    return (0);
20 - 909
}
910
 
65 - 911
// find lowest non-zero double value in array
912
function minNotNull(Array $values) {
913
    return min(array_diff(array_map('doubleval', $values) , array(
914
 
915
    )));
13 - 916
}
11 - 917
 
65 - 918
// apply exchange rates
919
function applyExchangeRates($arr) {
920
    foreach ($arr as & $value) {
921
        $value["ConvertedPrice"] = $value["Price"];
922
        $value["ConvertedShippingCost"] = $value["ShippingCost"];
1 - 923
 
65 - 924
        if ($_SESSION["buyer"]["Currency"] != $value["Currency"]) {
925
            $value["ConvertedPrice"] = number_format($value["Price"] / getExchangeRate($_SESSION["buyer"]["Currency"], $value["Currency"]) , 2, '.', '');
926
        }
1 - 927
 
65 - 928
        if ($_SESSION["buyer"]["Currency"] != $value["ShippingCurrency"]) {
929
            $value["ConvertedShippingCost"] = number_format($value["ShippingCost"] / getExchangeRate($_SESSION["buyer"]["Currency"], $value["ShippingCurrency"]) , 2, '.', '');
930
        }
1 - 931
 
65 - 932
        $value["ConvertedTotalPrice"] = number_format($value["ConvertedPrice"] + $value["ConvertedShippingCost"], 2, '.', '');
933
    }
5 - 934
 
65 - 935
    return ($arr);
5 - 936
}
937
 
36 - 938
// sanitize user input
65 - 939
function sanitizeInput($data) {
940
    $data = trim(preg_replace('/[\t\n\r\s]+/', ' ', $data));
941
    $data = stripslashes($data);
942
    $data = htmlspecialchars($data);
943
    return $data;
5 - 944
}
1 - 945
 
52 - 946
// sanitize user input (plus delete apostrophe)
947
function sanitizeInput2($data) {
65 - 948
    $data = trim(preg_replace('/[\t\n\r\s\']+/', ' ', $data));
949
    $data = stripslashes($data);
950
    $data = htmlspecialchars($data, ENT_QUOTES | ENT_HTML5);
951
    return $data;
52 - 952
}
953
 
14 - 954
// convert certain utf-8 characters to ascii
955
function cleanString($str) {
956
    $utf8 = array(
65 - 957
        '/[áàâãªä]/u' => 'a',
958
        '/[ÁÀÂÃÄ]/u' => 'A',
959
        '/[ÍÌÎÏ]/u' => 'I',
960
        '/[íìîï]/u' => 'i',
961
        '/[éèêë]/u' => 'e',
962
        '/[ÉÈÊË]/u' => 'E',
963
        '/[óòôõºö]/u' => 'o',
964
        '/[ÓÒÔÕÖ]/u' => 'O',
965
        '/[úùûü]/u' => 'u',
966
        '/[ÚÙÛÜ]/u' => 'U',
967
        '/ç/' => 'c',
968
        '/Ç/' => 'C',
969
        '/ñ/' => 'n',
970
        '/Ñ/' => 'N',
971
        '/–/' => '-', // UTF-8 hyphen to "normal" hyphen
972
        '/[’‘‹›‚]/u' => ' ', // Literally a single quote
973
        '/[“”«»„]/u' => ' ', // Double quote
974
        '/ /' => ' ', // nonbreaking space (equiv. to 0x160)
66 - 975
 
14 - 976
    );
977
 
65 - 978
    return preg_replace(array_keys($utf8) , array_values($utf8) , $str);
14 - 979
}
980
 
981
// Clean the search string
982
function searchFriendlyString($str) {
983
    $str = strip_tags($str);
984
    $str = stripslashes($str);
985
    $str = cleanString($str);
65 - 986
    $str = str_replace(array(
987
        "[",
988
        "]",
989
        "<",
990
        ">",
991
        "(",
992
        ")",
993
        " - ",
994
        " & ",
995
        " / "
996
    ) , " ", $str); // eliminate single '-', '&', '/' and brackets
997
    $str = trim(preg_replace('/[\t\n\r\s]+/', ' ', $str)); // delete extra whitespaces
14 - 998
    return ucwords($str);
999
}
1000
 
65 - 1001
// get a SESSION value, return empty string if not set
1002
function getSV($var) {
1003
    if (!isset($_SESSION[$var])) {
1004
        return ('');
1005
    }
1 - 1006
 
65 - 1007
    return ($_SESSION[$var]);
5 - 1008
}
1009
 
65 - 1010
// initialize a SESSION value if not set
1011
function initSV($var, $value) {
1012
    if (!isset($_SESSION[$var])) {
1013
        $_SESSION[$var] = $value;
1014
    }
5 - 1015
}
1 - 1016
 
65 - 1017
// initialize sessions variables
1018
function initSessionVariables() {
1019
    initSV("resultArr", []);
1020
    initSV("barcode", array(
1021
        "Type" => "",
1022
        "Value" => ""
1023
    ));
1024
    initSV("buyer", array(
1025
        "Country" => "United States",
1026
        "Currency" => "USD",
1027
        "Zip" => ""
1028
    ));
1029
    initSV("filterCondition", array(
1030
        "New" => true,
1031
        "Used" => true
1032
    ));
1033
    initSV("filterMediaType", array(
1034
        "CD" => true,
1035
        "Record" => true,
1036
        "Digital" => true,
1037
        "Book" => true
1038
    ));
1039
    initSV("currentView", "All");
1040
    initSV("currentLayout", "TableView");
1041
    initSV("lowestPrice", array(
1042
        "Used" => 0.00,
1043
        "New" => 0.00,
1044
        "CD" => 0.00,
1045
        "Record" => 0.00,
1046
        "Digital" => 0.00,
1047
        "Book" => "0.00",
1048
        "All" => 0.00
1049
    ));
1050
    initSV("filterWarnings", "");
1051
    initSV("md5LastSearch", "");
5 - 1052
}
1053
 
14 - 1054
function md5SearchTerm() {
1055
    $data = array();
1056
    $data['cond'] = $_SESSION['filterCondition'];
1057
    $data['type'] = $_SESSION['filterMediaType'];
17 - 1058
    $data['buyer'] = $_SESSION['buyer'];
65 - 1059
    $data['term'] = array(
1060
        $_SESSION['searchTerm']
1061
    );
14 - 1062
 
65 - 1063
    return (md5(json_encode($data)));
14 - 1064
}
1065
 
65 - 1066
// check POST value, return true if set and false if not
1067
function checkPV($var) {
1068
    if (isset($_POST[$var])) {
1069
        return (true);
1070
    }
1 - 1071
 
65 - 1072
    return (false);
5 - 1073
}
1074
 
65 - 1075
// get POST or GET value, return empty if not set
1076
function getPGV($var) {
1077
    if (isset($_POST[$var])) {
1078
        return ($_POST[$var]);
1079
    }
1080
    else if (isset($_GET[$var])) {
1081
        return ($_GET[$var]);
1082
    }
14 - 1083
 
65 - 1084
    return ("");
14 - 1085
}
1086
 
1 - 1087
// print search filter modal with current selection
65 - 1088
function printSearchFilterModal() {
66 - 1089
    global $mediaTypeTextArr;
1090
    global $mediaTypeIconArr;
1091
 
65 - 1092
    $str = '';
1093
    $str .= '<div class="modal fade" id="filterModal">';
1094
    $str .= '    <div class="modal-dialog">';
1095
    $str .= '        <div class="modal-content">';
1096
    $str .= '';
1097
    $str .= '            <div class="modal-header bg-primary">';
107 - 1098
    $str .= '                <p class="modal-title display-5">Search Filters</p>';
65 - 1099
    $str .= '            </div>';
1100
    $str .= '';
1101
    $str .= '            <form method="post" action="/index.php" onsubmit="progressBar(\'Applying Modified Search Filter...\');">';
20 - 1102
    $str .= '                <input type="hidden" name="sessionTab" value="' . MySessionHandler::getSessionTab() . '">';
65 - 1103
    $str .= '                <div class="modal-body">';
1104
    $str .= '                    <div class="card-group">';
1105
    $str .= '';
1106
    $str .= '                        <div class="card m-2">';
1107
    $str .= '                            <div class="card-header font-weight-bold">Condition</div>';
1108
    $str .= '                            <div class="card-body">';
1109
    $str .= '                                <div class="form-check">';
1110
    $str .= '                                    <label class="form-check-label">';
66 - 1111
    $str .= '                                        <input name="filterCondition[]" type="checkbox" class="form-check-input" value="New"' . ($_SESSION["filterCondition"]["New"] ? " checked" : "") . '>New';
65 - 1112
    $str .= '                                    </label>';
1113
    $str .= '                                </div>';
1114
    $str .= '                                <div class="form-check">';
1115
    $str .= '                                    <label class="form-check-label">';
66 - 1116
    $str .= '                                        <input name="filterCondition[]" type="checkbox" class="form-check-input" value="Used"' . ($_SESSION["filterCondition"]["Used"] ? " checked" : "") . '>Used';
65 - 1117
    $str .= '                                    </label>';
1118
    $str .= '                                </div>';
1119
    $str .= '                            </div>';
1120
    $str .= '                        </div>';
1121
    $str .= '';
1122
    $str .= '                        <div class="card m-2">';
1123
    $str .= '                            <div class="card-header font-weight-bold">Media Type</div>';
1124
    $str .= '                            <div class="card-body">';
1125
    $str .= '                                <div class="form-check">';
1126
    $str .= '                                    <label class="form-check-label">';
66 - 1127
    $str .= '                                        <input name="filterMediaType[]" type="checkbox" class="form-check-input" value="CD"' . ($_SESSION["filterMediaType"]["CD"] ? " checked" : "") . '><i class="' . $mediaTypeIconArr["CD"] . '"></i> ' . $mediaTypeTextArr["CD"];
65 - 1128
    $str .= '                                    </label>';
1129
    $str .= '                                </div>';
1130
    $str .= '                                <div class="form-check">';
1131
    $str .= '                                    <label class="form-check-label">';
66 - 1132
    $str .= '                                        <input name="filterMediaType[]" type="checkbox" class="form-check-input" value="Record"' . ($_SESSION["filterMediaType"]["Record"] ? " checked" : "") . '><i class="' . $mediaTypeIconArr["Record"] . '"></i> ' . $mediaTypeTextArr["Record"];
65 - 1133
    $str .= '                                    </label>';
1134
    $str .= '                                </div>';
1135
    $str .= '                                <div class="form-check">';
1136
    $str .= '                                    <label class="form-check-label">';
66 - 1137
    $str .= '                                        <input name="filterMediaType[]" type="checkbox" class="form-check-input" value="Digital"' . ($_SESSION["filterMediaType"]["Digital"] ? " checked" : "") . '><i class="' . $mediaTypeIconArr["Digital"] . '"></i> ' . $mediaTypeTextArr["Digital"];
65 - 1138
    $str .= '                                    </label>';
1139
    $str .= '                                </div>';
1140
    $str .= '                                <div class="form-check">';
1141
    $str .= '                                    <label class="form-check-label">';
66 - 1142
    $str .= '                                        <input name="filterMediaType[]" type="checkbox" class="form-check-input" value="Book"' . ($_SESSION["filterMediaType"]["Book"] ? " checked" : "") . '><i class="' . $mediaTypeIconArr["Book"] . '"></i> ' . $mediaTypeTextArr["Book"];
65 - 1143
    $str .= '                                    </label>';
1144
    $str .= '                                </div>';
1145
    $str .= '                            </div>';
1146
    $str .= '                        </div>';
1147
    $str .= '                    </div>';
1148
    $str .= '                </div>';
1149
    $str .= '';
1150
    $str .= '                <div class="modal-footer bg-primary">';
1151
    $str .= '                  	 <input id="tempSearchTerm" type="hidden" name="searchTerm" value="">';
1152
    $str .= '                    <button type="submit" class="btn btn-success" name="submit" value="Save" onclick="document.getElementById(\'tempSearchTerm\').value = document.getElementById(\'searchTerm\').value;$(\'#filterModal\').modal(\'hide\');">Save</button>';
1153
    $str .= '                    <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>';
1154
    $str .= '                </div>';
1155
    $str .= '            </form>';
1156
    $str .= '        </div>';
1157
    $str .= '    </div>';
1158
    $str .= '</div>';
1 - 1159
 
65 - 1160
    return ($str);
1 - 1161
}
3 - 1162
 
1163
// print search info modal
65 - 1164
function printSearchInfoModal() {
66 - 1165
    global $mediaTypeTextArr;
1166
    global $mediaTypeIconArr;
1167
 
65 - 1168
    $str = '';
1169
    $str .= '<div class="modal fade" id="searchInfoModal">';
1170
    $str .= '    <div class="modal-dialog">';
1171
    $str .= '        <div class="modal-content">';
1172
    $str .= '';
1173
    $str .= '            <div class="modal-header bg-primary">';
107 - 1174
    $str .= '                <p class="modal-title display-5">Search Tips</p>';
65 - 1175
    $str .= '                <button type="button" class="close" data-dismiss="modal"><i class="fas fa-window-close btn-dismiss"></i></button>';
1176
    $str .= '            </div>';
1177
    $str .= '';
1178
    $str .= '            <div class="modal-body bg-light text-dark">';
107 - 1179
/*
65 - 1180
    $str .= '              <div class="shadow p-4 mb-4 bg-white">';
107 - 1181
    $str .= '                <p class="display-5"><i class="fas fa-filter"></i> Filter</p>';
65 - 1182
    $str .= '                <p><span class="font-weight-bold">Condition:</span>';
1183
    $str .= '                    <br>Select "New" and / or "Used". The standard is to search for both.</p>';
1184
    $str .= '                <p><span class="font-weight-bold">Media Type:</span>';
66 - 1185
    $str .= '                    <br>Select <i class="' . $mediaTypeIconArr["CD"] . '"></i> "' . $mediaTypeTextArr["CD"] . '", <i class="' . $mediaTypeIconArr["Record"] . '"></i> "' . $mediaTypeTextArr["Record"] . '", <i class="' . $mediaTypeIconArr["Digital"] . '"></i> "' . $mediaTypeTextArr["Digital"] . '" and / or <i class="' . $mediaTypeIconArr["Book"] . '"></i> "' . $mediaTypeTextArr["Book"] . '". The standard is to search for all types.</p>';
65 - 1186
    $str .= '              </div>';
1187
    $str .= '              <div class="shadow p-4 mb-4 bg-white">';
107 - 1188
    $str .= '                <p class="display-5"><i class="fas fa-shipping-fast"></i> Shipping To</p>';
65 - 1189
    $str .= '                <p><span class="font-weight-bold">Country / Currency:</span>';
1190
    $str .= '                    <br>At this time only "United States" / "USD" are supported. The exchange rates are updated daily.</p>';
1191
    $str .= '                <p><span class="font-weight-bold">Zip Code:</span>';
1192
    $str .= '                    <br>Enter your postal code to get the accurate shipping cost for items listed using a shipping rate table.</p>';
1193
    $str .= '              </div>';
107 - 1194
*/
65 - 1195
    $str .= '              <div class="shadow p-4 bg-white">';
107 - 1196
    $str .= '                <p class="display-5"><i class="fas fa-search"></i> Search Keywords</p>';
65 - 1197
    $str .= '                <p><span class="font-weight-bold">Barcode:</span>';
1198
    $str .= '                    <br>The 12 or 13 digit barcode, normally located on the back, offers the best chance to find a specific album.</p>';
1199
    $str .= '                <p><span class="font-weight-bold">Artist and Title:</span>';
1200
    $str .= '                    <br>The full name of the album, including artist and title, will usually lead to a specific album.</p>';
1201
    $str .= '                <p><span class="font-weight-bold">Just Artist or Title:</span>';
1202
    $str .= '                    <br>Searches for artist or title alone will bring up multiple albums. You can later narrow your search further down, if necessary.</p>';
82 - 1203
    $str .= '                    <p><span class="font-italic">The search algorithm prefers the barcode number whenever available. Since some albums have been released under various barcodes, try searching again for artist and title should the barcode search come up empty.</span></p>';
65 - 1204
    $str .= '              </div>';
1205
    $str .= '            </div>';
1206
    $str .= '            <div class="modal-footer bg-primary">';
1207
    $str .= '                <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>';
1208
    $str .= '            </div>';
1209
    $str .= '        </div>';
1210
    $str .= '    </div>';
1211
    $str .= '</div>';
3 - 1212
 
65 - 1213
    return ($str);
3 - 1214
}
8 - 1215
 
65 - 1216
function saveSearchResult() {
1217
    $conn = MySessionHandler::getDBSessionId();
13 - 1218
 
65 - 1219
    $access = mysqli_real_escape_string($conn, time());
1220
    // BUGBUG
1221
    //  country
1222
    //  currency
1223
    $zip = mysqli_real_escape_string($conn, $_SESSION['buyer']['Zip']);
1224
    $condNew = $_SESSION['filterCondition']['New'] ? 'Y' : 'N';
1225
    $condUsed = $_SESSION['filterCondition']['Used'] ? 'Y' : 'N';
1226
    $mediaCD = $_SESSION['filterMediaType']['CD'] ? 'Y' : 'N';
1227
    $mediaRecord = $_SESSION['filterMediaType']['Record'] ? 'Y' : 'N';
1228
    $mediaDigital = $_SESSION['filterMediaType']['Digital'] ? 'Y' : 'N';
1229
    $mediaBook = $_SESSION['filterMediaType']['Book'] ? 'Y' : 'N';
1230
    $data = mysqli_real_escape_string($conn, $_SESSION['searchTerm']);
1231
    $lowNew = floatval($_SESSION['lowestPrice']['New']);
1232
    $lowUsed = floatval($_SESSION['lowestPrice']['Used']);
1233
    $lowDigital = floatval($_SESSION['lowestPrice']['Digital']);
1234
    $lowBook = floatval($_SESSION['lowestPrice']['Book']);
1235
    $count = count($_SESSION['resultArr']);
1236
    $userId = (empty($_SESSION['sessData']['userID']) ? 'NULL' : $_SESSION['sessData']['userID']);
96 - 1237
    $ip = inet_pton($_SERVER['REMOTE_ADDR']);
8 - 1238
 
65 - 1239
    $sql = "INSERT
20 - 1240
                INTO searches
96 - 1241
                (sessId, access, ip, zip, condNew, condUsed, mediaCD, mediaRecord, mediaDigital, mediaBook, data, lowNew, lowUsed, lowDigital, lowBook, count, userId)
1242
                VALUES ('" . session_id() . "', '$access', '$ip', '$zip', '$condNew', '$condUsed', '$mediaCD', '$mediaRecord', '$mediaDigital', '$mediaBook', '$data', $lowNew, $lowUsed, $lowDigital, $lowBook, $count, $userId)";
8 - 1243
 
65 - 1244
    if (!($result = mysqli_query($conn, $sql))) {
1245
        error_log("MySQL Write Searches Error: " . mysqli_error($conn) . " (" . mysqli_errno($conn) . ")");
1246
    }
13 - 1247
 
65 - 1248
    return $result;
1249
}
13 - 1250
 
17 - 1251
function getUrl($url, $userAgent = null) {
1252
    $ch = curl_init();
1253
 
1254
    // Set request header with language and charset
1255
    $header = array(
1256
        "Accept-Language: en-US,en;q=0.5",
1257
        "Accept-Charset: UTF-8,*;q=0.5"
1258
    );
1259
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
1260
 
1261
    // Set optional user-agent
1262
    if ($userAgent) {
1263
        curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
1264
    }
1265
 
1266
    curl_setopt($ch, CURLOPT_ENCODING, "gzip,deflate");
1267
    curl_setopt($ch, CURLOPT_AUTOREFERER, true);
1268
    curl_setopt($ch, CURLOPT_HEADER, 0);
84 - 1269
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
1270
    curl_setopt($ch, CURLOPT_TIMEOUT, 15);
17 - 1271
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1272
    curl_setopt($ch, CURLOPT_URL, $url);
1273
    $response = curl_exec($ch);
1274
    if ($response === false) {
20 - 1275
        error_log('Curl Request Error: ' . curl_error($ch) . ' (' . curl_errno($ch) . ')');
1276
        error_log('Url: ' . $url);
17 - 1277
        $response = '';
1278
    }
23 - 1279
 
17 - 1280
    curl_close($ch);
1281
 
1282
    return $response;
1283
}
1284
 
20 - 1285
// Retrieve search history for current session id
14 - 1286
function getSearchHistory() {
1287
    $str = "";
38 - 1288
    $sql = "select data, max(access) from searches where sessId = '" . session_id() . "'";
1289
    if (!empty($_SESSION['sessData']['userID'])) {
1290
        $sql .= " or userID = '" . $_SESSION['sessData']['userID'] . "'";
1291
    }
1292
    $sql .= " group by data order by max(access) desc, data limit 0,30;";
14 - 1293
    $conn = MySessionHandler::getDBSessionId();
1294
 
20 - 1295
    if ($result = mysqli_query($conn, $sql)) {
1296
        if (mysqli_num_rows($result) > 0) {
65 - 1297
            while ($row = mysqli_fetch_assoc($result)) {
20 - 1298
                $str .= "<option>" . $row["data"] . "</option>";
1299
            }
14 - 1300
        }
1301
    }
65 - 1302
    else if (mysqli_errno($conn)) {
1303
        error_log("MySQL Read Searches SQL: " . $sql);
1304
        error_log("MySQL Read Searches Error: " . mysqli_error($conn) . " (" . mysqli_errno($conn) . ")");
1305
    }
14 - 1306
 
1307
    return $str;
1308
}
1309
 
41 - 1310
// Retrieve coupons codes
1311
function getCouponCodes() {
1312
    $str = "";
1313
    $lastAdvertiser = "";
1314
 
1315
    if (!isLoggedIn()) {
107 - 1316
        return ('<div class="container bg-warning text-center py-3"><p class="display-6"><i class="fas fa-bookmark"></i> Please login to your Find Cheap Music account in order to see the coupons.</p></div>');
41 - 1317
    }
1318
 
65 - 1319
    $sql = 'select advertiser, date_format(enddate, "%M %e, %Y") as enddate, description, couponcode, url, pixel from coupons where DATE(NOW()) between startdate and enddate group by advertiser, description order by advertiser, id';
41 - 1320
    $conn = MySessionHandler::getDBSessionId();
1321
 
1322
    if ($result = mysqli_query($conn, $sql)) {
1323
        if (mysqli_num_rows($result) > 0) {
68 - 1324
            $str .= "<div class=\"container py-4 bg-secondary border\">";
65 - 1325
            while ($row = mysqli_fetch_assoc($result)) {
1326
                if ($row["advertiser"] != $lastAdvertiser) {
41 - 1327
                    if (!empty($lastAdvertiser)) {
68 - 1328
                        $str .= "</ul>";
41 - 1329
                    }
107 - 1330
                    $str .= "<h2 class=\"bg-primary text-center mt-3 mb-1\">" . $row["advertiser"] . "</h2>";
68 - 1331
                    $str .= "<ul class=\"list-group\">";
41 - 1332
                    $lastAdvertiser = $row["advertiser"];
1333
                }
51 - 1334
                if (!empty($row["url"])) {
68 - 1335
                    $str .= "<li class=\"list-group-item\"><a class=\"btn btn-link text-left\" target=\"_blank\" href=\"";
51 - 1336
                    $str .= $row["url"];
107 - 1337
                    $str .= "\" rel=\"nofollow noreferrer noopener\">";
68 - 1338
                    $str .= "<strong>" . $row["description"] . "</strong> until " . $row["enddate"];
51 - 1339
                    if (!empty($row["couponcode"])) {
1340
                        $str .= " (Use Coupon Code \"" . $row["couponcode"] . "\")";
1341
                    }
1342
                    $str .= "</a>";
1343
                    if (!empty($row["pixel"])) {
107 - 1344
                        $str .= "<img class=\"lazyload\" src=\"data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" data-src=\"" . $row["pixel"] . "\" width=\"1\" height=\"1\" class=\"border-0\" alt=\"" . $row["advertiser"] . " Coupon\"/>";
51 - 1345
                    }
68 - 1346
                    $str .= "</li>";
41 - 1347
                }
1348
            }
68 - 1349
            $str .= "</ul>";
41 - 1350
            $str .= "</div>";
1351
        }
65 - 1352
    }
1353
    else if (mysqli_errno($conn)) {
41 - 1354
        $str .= "<h2>No Coupons available at the moment...</h2>";
1355
    }
1356
 
1357
    return $str;
1358
}
1359
 
14 - 1360
// Delete left over progressbar files older than 2 days
1361
function cleanupPbFiles() {
84 - 1362
    $files = glob("../MyFiles/tmp/pb*.txt");
65 - 1363
    $now = time();
14 - 1364
    foreach ($files as $file) {
1365
        if (is_file($file)) {
1366
            if ($now - filemtime($file) >= 60 * 60 * 24 * 2) { // 2 days and older
1367
                unlink($file);
1368
            }
65 - 1369
        }
14 - 1370
    }
1371
}
1372
 
1373
// Update progressbar file for a session
22 - 1374
function updatePbFile($flag = false) {
107 - 1375
    static $max_pb = 15; // max progressbar steps
22 - 1376
    static $current = 0;
23 - 1377
 
22 - 1378
    if ($flag) {
1379
        $current = 0;
65 - 1380
    }
1381
    else {
22 - 1382
        ++$current;
1383
    }
1384
 
1385
    if ($current > $max_pb) {
1386
        error_log("max_pb $max_pb is too small, current step is $current. Adjust tools.php (updatePbFile).");
1387
        $max_pb = $current;
1388
    }
65 - 1389
    $filename = session_id() . "_" . MySessionHandler::getSessionTab();
14 - 1390
    $arr_content = array();
1391
 
20 - 1392
    $percent = intval($current / $max_pb * 100);
14 - 1393
 
1394
    $arr_content['percent'] = $percent;
1395
    $arr_content['message'] = $current . " search(es) processed.";
84 - 1396
    $file = "../MyFiles/tmp/pb_" . $filename . ".txt";
14 - 1397
 
77 - 1398
    if ($percent >= 100) {
1399
        @unlink($file);
1400
    } else {
1401
        file_put_contents($file, json_encode($arr_content));
1402
    }
14 - 1403
}
20 - 1404
 
1405
// Linkshare / CJ Affiliate csv dump
1406
function ls_cj_csv($fields) {
1407
    static $fh = null;
1408
    $delimiter = ',';
1409
    $enclosure = '"';
1410
    $mysql_null = false;
1411
 
1412
    if (!$fh) {
1413
        $fh = fopen("ls_cj.csv", "a+");
1414
    }
1415
 
1416
    $delimiter_esc = preg_quote($delimiter, '/');
1417
    $enclosure_esc = preg_quote($enclosure, '/');
1418
 
1419
    $output = array();
1420
    foreach ($fields as $field) {
1421
        if ($field === null && $mysql_null) {
1422
            $output[] = 'NULL';
1423
            continue;
1424
        }
1425
 
65 - 1426
        $output[] = preg_match("/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field) ? ($enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure) : $field;
20 - 1427
    }
1428
 
1429
    fwrite($fh, join($delimiter, $output) . "\n");
1430
}
35 - 1431
 
1432
// Login in check
1433
function isLoggedIn() {
65 - 1434
    return (!empty($_SESSION['sessData']['userLoggedIn']) && !empty($_SESSION['sessData']['userID'])) ? true : false;
35 - 1435
}
1436
 
1437
// unset all login system session data
1438
function unsetSessData() {
1439
    unset($_SESSION['sessData']['userLoggedIn']);
1440
    unset($_SESSION['sessData']['userID']);
1441
    unset($_SESSION['sessData']['loginType']);
36 - 1442
}
1443
 
1444
// get user image name
1445
function getUserImage($userData) {
1446
    if (empty($userData) || empty($userData['picture'])) {
109 - 1447
        return 'login/assets/images/default.png';
36 - 1448
    }
38 - 1449
 
36 - 1450
    $httpPos = strpos($userData['picture'], 'http');
1451
    if ($httpPos === false) {
65 - 1452
        return 'login/' . UPLOAD_PATH . 'profile_picture/' . $userData['picture'];
36 - 1453
    }
1454
 
1455
    return $userData['picture'];
38 - 1456
}
39 - 1457
 
1458
function startsWith($haystack, $needle) {
1459
    return substr_compare($haystack, $needle, 0, strlen($needle)) === 0;
1460
}
1461
 
1462
function endsWith($haystack, $needle) {
1463
    return substr_compare($haystack, $needle, -strlen($needle)) === 0;
45 - 1464
}
50 - 1465
 
1466
function displayBarcode($barcode) {
1467
    $barcode = trim(preg_replace("/[^0-9]/", "", $barcode));
1468
    $barcodeType = clsLibGTIN::GTINCheck($barcode, false, 1);
1469
 
1470
    if ($barcodeType == "UPC" && strlen($barcode) == 12) {
1471
        return substr($barcode, 0, 1) . "-" . substr($barcode, 1, 5) . "-" . substr($barcode, 6, 5) . "-" . substr($barcode, 11, 1);
65 - 1472
    }
1473
    else if (($barcodeType == "EAN" || $barcodeType == "ISBN") && strlen($barcode) == 13) {
50 - 1474
        return substr($barcode, 0, 1) . "-" . substr($barcode, 1, 6) . "-" . substr($barcode, 7, 6);
65 - 1475
    }
1476
    else if ($barcodeType == "EAN" && strlen($barcode) == 14) {
50 - 1477
        return substr($barcode, 0, 1) . "-" . substr($barcode, 1, 2) . "-" . substr($barcode, 3, 5) . "-" . substr($barcode, 8, 5) . "-" . substr($barcode, 13, 1);
65 - 1478
    }
1479
    else {
50 - 1480
        return $barcode;
1481
    }
52 - 1482
}
93 - 1483
 
1484
// fuzzy search to verify titles are relevant
1485
function verifyResultArr() {
1486
    require_once ('php/Fuse/Bitap/Bitap.php');
1487
    require_once ('php/Fuse/Bitap/matched_indices.php');
1488
    require_once ('php/Fuse/Bitap/pattern_alphabet.php');
1489
    require_once ('php/Fuse/Bitap/regex_search.php');
1490
    require_once ('php/Fuse/Bitap/score.php');
1491
    require_once ('php/Fuse/Bitap/search.php');
1492
    require_once ('php/Fuse/Helpers/deep_value.php');
1493
    require_once ('php/Fuse/Helpers/is_list.php');
1494
    require_once ('php/Fuse/Fuse.php');
1495
 
1496
    if (!empty($_SESSION["barcode"]["Value"]) || empty($_SESSION["resultArr"])) {
1497
        return;
1498
    }
1499
 
1500
    $options = [
1501
      'shouldSort' => false,
1502
    //  'tokenize' => true,
1503
    //  'matchAllTokens' => true,
1504
    //  'findAllMatches' => true,
1505
      'includeScore' => true,
1506
      'includeMatches' => true,
1507
      'threshold' => 0.6,
1508
      'location' => 0,
1509
      'distance' => 100,
1510
      'minMatchCharLength' => 5,
1511
      'keys' => [ "Title" ]
1512
    ];
1513
 
1514
    $fuse = new Fuse($_SESSION["resultArr"], $options);
1515
    $result = $fuse->search($_SESSION["searchTerm"]);
1516
 
1517
    $_SESSION["resultArr"] = [];
1518
    foreach($result as $r) {
97 - 1519
        $r['item']['score'] = (!empty($r['score']) ? $r['score'] : 0);
1520
        $r['item']['indices'] = (!empty($r['matches'][0]['indices']) ? $r['matches'][0]['indices'] : []);
93 - 1521
        $_SESSION['resultArr'][] = $r['item'];
1522
    }
1523
 
1524
    /* debug start
1525
    $lines = [];
1526
    foreach($_SESSION['resultArr'] as $r) {
1527
        $p = 0;
1528
        $t = '';
1529
        foreach($r['indices'] as $ind) {
1530
            if ($p < $ind[0]) {
1531
                $t .= substr($r['Title'], $p, $ind[0] - $p);
1532
            }
1533
            $t .= "<b>" . substr($r['Title'], $ind[0], $ind[1] - $ind[0] + 1) . "</b>";
1534
            $p = $ind[1] + 1;
1535
        }
1536
        if ($p < strlen($r['Title'])) {
1537
            $t .= substr($r['Title'], $p);
1538
        }
1539
        $lines[] = array ('score' => $r['score'], 'title' => $t);
1540
    }
1541
 
1542
    usort($lines, 'compare_score');
1543
    echo "<p>";
1544
    foreach($lines as $l) {
1545
        echo $l['score'] . ": " . $l['title'] . "<br/>";
1546
    }
1547
    echo "</p>";
1548
    debug end */
1549
}
1550
 
1551
// compare score for sort low to high
1552
function compare_score($a, $b) {
1553
    return ($a['score'] > $b['score']);
1554
}
96 - 1555
 
1556
function my_error_log($msg) {
1557
    error_log("[" . date("d-M-Y H:m:s") . "] " . $msg . PHP_EOL, 3, $_SERVER['DOCUMENT_ROOT'] . "/../MyFiles/logs/my_php_error.log");
1558
}
99 - 1559
 
1560
function saveSearchCache($vendor, $query, $subquery, $text) {
1561
    $conn = MySessionHandler::getDBSessionId();
1562
 
1563
    $created = mysqli_real_escape_string($conn, time());
1564
    $v = mysqli_real_escape_string($conn, $vendor);
1565
    $q = mysqli_real_escape_string($conn, $query);
1566
    $s = mysqli_real_escape_string($conn, $subquery);
1567
    $r = base64_encode(gzencode($text));
1568
 
1569
    $sql = "INSERT
1570
                INTO searchCache
1571
                (created, vendor, query, subquery, result)
110 - 1572
                VALUES ('$created', '$v', '$q', '$s', '$r')
1573
                ON DUPLICATE KEY UPDATE result = '$r'";
99 - 1574
 
1575
    if (!($result = mysqli_query($conn, $sql))) {
1576
        error_log("MySQL Write SearchCache Error: " . mysqli_error($conn) . " (" . mysqli_errno($conn) . ")");
1577
    }
1578
 
1579
    return $result;
1580
}
1581
 
1582
 
1583
function expireSearchCache() {
1584
    $conn = MySessionHandler::getDBSessionId();
1585
    $t = MySessionHandler::getDBExpirationTime();
1586
 
1587
    $expired = mysqli_real_escape_string($conn, time() - $t);
1588
 
1589
    $sql = "DELETE
1590
                FROM searchCache
1591
                WHERE created < $expired";
1592
 
1593
    if (!($result = mysqli_query($conn, $sql))) {
1594
        error_log("MySQL Delete SearchCache Error: " . mysqli_error($conn) . " (" . mysqli_errno($conn) . ")");
1595
    }
1596
}
1597
 
1598
function getSearchCache($vendor, $query, $subquery) {
1599
    $conn = MySessionHandler::getDBSessionId();
1600
 
1601
    $v = mysqli_real_escape_string($conn, $vendor);
1602
    $q = mysqli_real_escape_string($conn, $query);
1603
    $s = mysqli_real_escape_string($conn, $subquery);
1604
    $sql = "select result from searchCache where vendor = '$v' and query = '$q' and subquery = '$s'";
1605
 
1606
    if ($result = mysqli_query($conn, $sql)) {
1607
        if (mysqli_num_rows($result) == 1) {
1608
            if ($row = mysqli_fetch_assoc($result)) {
1609
                return gzdecode(base64_decode($row["result"]));
1610
            }
1611
        }
1612
    }
1613
    else if (mysqli_errno($conn)) {
1614
        error_log("MySQL Read SearchCache SQL: " . $sql);
1615
        error_log("MySQL Read SearchCache Error: " . mysqli_error($conn) . " (" . mysqli_errno($conn) . ")");
1616
    }
1617
 
1618
    return false;
104 - 1619
}
107 - 1620
 
1621
 
1622
function getGeoLocation() {
1623
    if (!empty($_SESSION['buyer']['Zip']) || empty($_SERVER['REMOTE_ADDR'])) {
1624
        return;
1625
    }
1626
 
1627
    $conn = MySessionHandler::getDBSessionId();
1628
    $ip = inet_pton($_SERVER['REMOTE_ADDR']);
1629
 
1630
    $sql = "select zip from geoLocation where ip = '$ip'";
1631
 
1632
    if ($result = mysqli_query($conn, $sql)) {
1633
        if (mysqli_num_rows($result) == 1) {
1634
            if ($row = mysqli_fetch_assoc($result)) {
1635
                $_SESSION['buyer']['Zip'] = $row["zip"];
1636
                return;
1637
            }
1638
        }
1639
    }
1640
    else if (mysqli_errno($conn)) {
1641
        error_log("MySQL Read geoLocation SQL: " . $sql);
1642
        error_log("MySQL Read geoLocation Error: " . mysqli_error($conn) . " (" . mysqli_errno($conn) . ")");
1643
    }
1644
 
1645
    $vendors = Vendors::getInstance();
1646
    $config = $vendors->getVendor(Vendors::IPAPI);
1647
    $key = $config['KEY'];
1648
 
1649
    $loc = file_get_contents("http://api.ipapi.com/api/" . $_SERVER['REMOTE_ADDR'] . "?access_key=" . $key);
1650
    if ($loc == false) {
1651
        return;
1652
    }
1653
 
1654
    $json = json_decode($loc);
1655
    if (!empty($json->error)) {
1656
        error_log("geoLocation Error: " . $json->error->info . " (" . $json->error->code . " | " . $json->error->type . ")");
1657
        return;
1658
    }
1659
 
1660
    $created = mysqli_real_escape_string($conn, time());
1661
    $countryCode = mysqli_real_escape_string($conn, $json->{'country_code'});
1662
    $zip = mysqli_real_escape_string($conn, $json->zip);
1663
    $language = mysqli_real_escape_string($conn, $json->location->languages[0]->code);
1664
    $is_eu = mysqli_real_escape_string($conn, $json->location->{'is_eu'} ? '1' : '0');
1665
 
1666
    $sql = "INSERT
1667
                INTO geoLocation
1668
                (ip, created, countryCode, zip, language, is_eu)
1669
                VALUES ('$ip', $created, '$countryCode', '$zip', '$language', '$is_eu')";
1670
 
1671
    if (!($result = mysqli_query($conn, $sql))) {
1672
        error_log("MySQL Write geoLocation Error: " . mysqli_error($conn) . " (" . mysqli_errno($conn) . ")");
1673
    }
1674
}
1675
 
1676
function timeStampUrl($file) {
109 - 1677
    if (file_exists($file)) {
1678
        return $file . "?" . filemtime($file);
1679
    }
1680
 
1681
    return $file;
108 - 1682
}