Subversion Repositories cheapmusic

Rev

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