Subversion Repositories cheapmusic

Rev

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