PluginProbe
Datafeedr API / 1.0.26
Datafeedr API v1.0.26
1.4.3 1.4.2 1.0.125 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.2 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28 1.0.29 1.0.3 1.0.30 1.0.31 1.0.32 All 182 releases
datafeedr-api / classes / class-dfrapi-searchform.php

class-dfrapi-searchform.php in Datafeedr API 1.0.26, at classes/class-dfrapi-searchform.php

863 lines 39.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3
4
5 class Dfrapi_SearchForm
6 {
7 function fields() {
8 $opFulltext = array(
9 'contain' => __( 'contains', DFRAPI_DOMAIN ),
10 'not_contain' => __( 'doesn\'t contain', DFRAPI_DOMAIN ),
11 'start' => __( 'starts with', DFRAPI_DOMAIN ),
12 'end' => __( 'ends with', DFRAPI_DOMAIN ),
13 'match' => __( 'matches', DFRAPI_DOMAIN )
14 );
15 $opFulltextExact = array_merge($opFulltext, array(
16 'is' => __( 'is', DFRAPI_DOMAIN )
17 ));
18 $opRange = array(
19 'lt' => __( 'less than', DFRAPI_DOMAIN ),
20 'gt' => __( 'greater than', DFRAPI_DOMAIN ),
21 'between' => __( 'between', DFRAPI_DOMAIN )
22 );
23 $opIs = array(
24 'is' => __( 'is', DFRAPI_DOMAIN )
25 );
26 $opIsIsnt = array(
27 'is' => __( 'is', DFRAPI_DOMAIN ),
28 'is_not' => __( 'isn\'t', DFRAPI_DOMAIN )
29 );
30 $opYesNo = array(
31 'yes' => __( 'yes', DFRAPI_DOMAIN ),
32 'no' => __( 'no', DFRAPI_DOMAIN )
33 );
34
35 $sortOpts = array(
36 '' => __( 'Relevance', DFRAPI_DOMAIN ),
37 '+price' => __( 'Price Ascending', DFRAPI_DOMAIN ),
38 '-price' => __( 'Price Decending', DFRAPI_DOMAIN ),
39 '+saleprice' => __( 'Sale Price Ascending', DFRAPI_DOMAIN ),
40 '-saleprice' => __( 'Sale Price Decending', DFRAPI_DOMAIN ),
41 '+salediscount' => __( 'Discount Ascending', DFRAPI_DOMAIN ),
42 '-salediscount' => __( 'Discount Decending', DFRAPI_DOMAIN ),
43 '+merchant' => __( 'Merchant', DFRAPI_DOMAIN ),
44 '+time_updated' => __( 'Last Updated Ascending', DFRAPI_DOMAIN ),
45 '-time_updated' => __( 'Last Updated Decending', DFRAPI_DOMAIN )
46 );
47
48 return array(
49 array(
50 'title' => __( 'Any Field', DFRAPI_DOMAIN ),
51 'name' => 'any',
52 'input' => 'text',
53 'operator' => $opFulltext,
54 'help' => $this->help('any')
55 ),
56 array(
57 'title' => __( 'Product Name', DFRAPI_DOMAIN ),
58 'name' => 'name',
59 'input' => 'text',
60 'operator' => $opFulltextExact,
61 'help' => $this->help('name')
62 ),
63 array(
64 'title' => __( 'Brand', DFRAPI_DOMAIN ),
65 'name' => 'brand',
66 'input' => 'text',
67 'operator' => $opFulltextExact,
68 'help' => $this->help('brand')
69 ),
70 array(
71 'title' => __( 'Description', DFRAPI_DOMAIN ),
72 'name' => 'description',
73 'input' => 'text',
74 'operator' => $opFulltext,
75 'help' => $this->help('description')
76 ),
77 array(
78 'title' => __( 'Tags', DFRAPI_DOMAIN ),
79 'name' => 'tags',
80 'input' => 'text',
81 'operator' => array(
82 'in' => __( 'contain', DFRAPI_DOMAIN ),
83 'not_in' => __( 'don\'t contain', DFRAPI_DOMAIN )
84 ),
85 'help' => $this->help('tags')
86 ),
87 array(
88 'title' => __( 'Category', DFRAPI_DOMAIN ),
89 'name' => 'category',
90 'input' => 'text',
91 'operator' => $opFulltext,
92 'help' => $this->help('category')
93 ),
94 array(
95 'title' => __( 'Product Type', DFRAPI_DOMAIN ),
96 'name' => 'type',
97 'input' => 'select',
98 'options' => array(
99 'products' => __( 'Product', DFRAPI_DOMAIN ),
100 'coupons' => __( 'Coupon', DFRAPI_DOMAIN )
101 ),
102 'operator' => $opIs,
103 'help' => $this->help('type')
104 ),
105 array(
106 'title' => __( 'Currency', DFRAPI_DOMAIN ),
107 'name' => 'currency',
108 'input' => 'select',
109 'options' => array(
110 'AUD' => 'AUD',
111 'CAD' => 'CAD',
112 'CHF' => 'CHF',
113 'DKK' => 'DKK',
114 'EUR' => 'EUR',
115 'GBP' => 'GBP',
116 'NOK' => 'NOK',
117 'NZD' => 'NZD',
118 'SEK' => 'SEK',
119 'TRY' => 'TRY',
120 'USD' => 'USD',
121 ),
122 'operator' => $opIsIsnt,
123 'help' => $this->help('currency')
124 ),
125 array(
126 'title' => __( 'Price', DFRAPI_DOMAIN ),
127 'name' => 'price',
128 'input' => 'range',
129 'operator' => $opRange,
130 'help' => $this->help('price')
131 ),
132 array(
133 'title' => __( 'Sale Price', DFRAPI_DOMAIN ),
134 'name' => 'saleprice',
135 'input' => 'range',
136 'operator' => $opRange,
137 'help' => $this->help('saleprice')
138 ),
139 array(
140 'title' => __( 'Network', DFRAPI_DOMAIN ),
141 'name' => 'source_id',
142 'input' => 'network',
143 'operator' => $opIsIsnt,
144 'help' => $this->help('source_id')
145 ),
146 array(
147 'title' => __( 'Merchant', DFRAPI_DOMAIN ),
148 'name' => 'merchant_id',
149 'input' => 'merchant',
150 'operator' => $opIsIsnt,
151 'help' => $this->help('merchant_id')
152 ),
153 array(
154 'title' => __( 'On Sale', DFRAPI_DOMAIN ),
155 'name' => 'onsale',
156 'input' => 'none',
157 'operator' => $opYesNo,
158 'help' => $this->help('onsale')
159 ),
160 array(
161 'title' => __( 'Discount', DFRAPI_DOMAIN ),
162 'name' => 'salediscount',
163 'input' => 'range',
164 'operator' => $opRange,
165 'help' => $this->help('salediscount')
166 ),
167 array(
168 'title' => __( 'Has Image', DFRAPI_DOMAIN ),
169 'name' => 'image',
170 'input' => 'none',
171 'operator' => $opYesNo,
172 'help' => $this->help('image')
173 ),
174 array(
175 'title' => __( 'Last Updated', DFRAPI_DOMAIN ),
176 'name' => 'time_updated',
177 'input' => 'range',
178 'operator' => array('lt' => 'before', 'gt' => 'after', 'between' => 'between'),
179 'help' => $this->help('time_updated')
180 ),
181 array(
182 'title' => __( 'Limit', DFRAPI_DOMAIN ),
183 'name' => 'limit',
184 'input' => 'text',
185 'operator' => array('is' => 'is'),
186 'help' => $this->help('limit')
187 ),
188 array(
189 'title' => __( 'Sort By', DFRAPI_DOMAIN ),
190 'name' => 'sort',
191 'input' => 'none',
192 'operator' => $sortOpts,
193 'help' => $this->help('sort')
194 ),
195 array(
196 'title' => __( 'Exclude Duplicates', DFRAPI_DOMAIN ),
197 'name' => 'duplicates',
198 'input' => 'text',
199 'operator' => array(
200 'is' => __( 'matching these fields', DFRAPI_DOMAIN ),
201 ),
202 'help' => $this->help('duplicates')
203 )
204 );
205 }
206
207 function defaults() {
208 return array(
209 'any' => array('operator' => 'contain', 'value'=> ''),
210 'name' => array('operator' => 'contain', 'value'=> ''),
211 'type' => array('value'=> 'product'),
212 'currency' => array('value'=> 'USD'),
213 'price' => array('operator' => 'between', 'value'=> '0', 'value2' => '999999'),
214 'saleprice' => array('operator' => 'between', 'value'=> '0', 'value2' => '999999'),
215 'source_id' => array('value'=> array()),
216 'merchant_id' => array('value'=> array()),
217 'onsale' => array('value'=> '1'),
218 'image' => array('value'=> '1'),
219 'thumbnail' => array('value'=> '1'),
220 'time_updated' => array('operator' => 'lt', 'value'=> 'today'),
221 'limit' => array('value'=> 1000),
222 );
223 }
224
225 public $useSelected;
226 public $prefix;
227
228 function get($ary, $key, $default="") {
229 return is_array($ary) && isset($ary[$key]) ? $ary[$key] : $default;
230 }
231
232 function inputPrefix($index) {
233 return sprintf('%s[%s]', $this->prefix ? $this->prefix : "query", $index);
234 }
235
236 function byName($a, $b) {
237 return strcasecmp($a['name'], $b['name']);
238 }
239
240 function ary($s) {
241 if(!is_array($s))
242 $s = explode(',', trim($s));
243 return array_filter($s, 'strlen');
244 }
245
246 function ids($lst) {
247 $ids = array();
248 foreach($lst as $obj)
249 $ids []= $obj['_id'];
250 return $ids;
251 }
252
253 function selectOpts($opts, $selectedValue=NULL) {
254 $html = "";
255 foreach($opts as $value => $title) {
256 $sel = $selectedValue == $value ? "selected='selected'" : "";
257 $title = htmlspecialchars($title);
258 $value = htmlspecialchars($value);
259 $html .= "<option value=\"$value\" $sel>$title</option>";
260 }
261 return $html;
262 }
263
264 function allNetworks() {
265 $lst = dfrapi_api_get_all_networks();
266 usort($lst, array($this, 'byName'));
267 return $lst;
268 }
269
270 function selectedNetworks() {
271 $selected = $this->get(get_option( 'dfrapi_networks' ), 'ids');
272 if(empty($selected))
273 return array();
274
275 $lst = array();
276 foreach($this->allNetworks() as $net)
277 if(isset($selected[$net['_id']]))
278 $lst []= $net;
279 return $lst;
280 }
281
282 function groupClass($nid) {
283 if (empty($nid)) { return ''; }
284 $networks = $this->allNetworks();
285 foreach($networks as $network) {
286 if ($network['_id'] == $nid) {
287 $name = str_replace( array( " ", "-", "." ), "", $network['group'] );
288 $type = ( $network['type'] == 'coupons' ) ? '_coupons' : '';
289 return 'network_logo_16x16_' . strtolower( $name . $type );
290 }
291 }
292 }
293
294 function selectedMerchants() {
295 $selected = $this->get(get_option( 'dfrapi_merchants' ), 'ids');
296 if(empty($selected))
297 return array();
298
299 $lst = array();
300 foreach(dfrapi_api_get_merchants_by_id($selected) as $merchant) {
301 $lst []= $merchant;
302 }
303 usort($lst, array($this, 'byName'));
304 return $lst;
305 }
306
307 function networksMerchantsPopup($kind, $value) {
308 $title = array(
309 'network' => __( 'Select Networks', DFRAPI_DOMAIN ),
310 'merchant' => __( 'Select Merchants', DFRAPI_DOMAIN )
311 );
312 $clear = __( 'Clear search', DFRAPI_DOMAIN );
313 $ok = __( 'OK', DFRAPI_DOMAIN );
314 $cells = "";
315
316 $all = ($kind == 'network') ?
317 ($this->useSelected ? $this->selectedNetworks() : $this->allNetworks()) :
318 $this->selectedMerchants();
319
320 foreach($all as $obj) {
321 $id = $obj['_id'];
322 $nid = ($kind == 'network') ? $obj['_id'] : $obj['source_id'];
323 $group_class = $this->groupClass($nid);
324
325 $name = $obj['name'];
326 $checked = in_array($id, $value) ? "checked='checked'" : "";
327
328 $cells .= "
329 <div class='inline_frame_element nid_{$nid}'>
330 <label>
331 <input type='checkbox' value='{$id}' $checked />
332 <span class='element_name {$group_class}'>{$name}</span>
333 </label>
334 </div>
335 ";
336 }
337
338 return "
339 <h1>{$title[$kind]}</h1>
340 <div class='filter_action'>
341 Search: <input type='text' />
342 <a class='reset_search button' title='{$clear}'>&times;</a>
343 </div>
344 <div class='inline_frame'>
345 <div>
346 {$cells}
347 <div class='clearfix'></div>
348 </div>
349 </div>
350 <div><a class='button submit'>$ok</a></div>
351 ";
352 }
353
354 function networksMerchantsNames($kind, $value, $maxNames=5) {
355 $all = ($kind == 'network') ? $this->allNetworks() : dfrapi_api_get_merchants_by_id($value);
356 $names = array();
357 foreach($all as $obj) {
358 if(in_array($obj['_id'], $value)) {
359 $names []= "<span>{$obj['name']}</span>";
360 if(count($names) >= $maxNames)
361 break;
362 }
363 }
364 $html = implode(', ', $names);
365 if(count($value) - count($names)) {
366 $html .= ' ' . sprintf(__( 'and %s more', DFRAPI_DOMAIN ), count($value) - count($names));
367 }
368 return $html;
369 }
370
371 function chooseBox($kind, $field, $index, $value) {
372 $pfx = $this->inputPrefix($index);
373 $value = implode(',', $this->ary($value));
374 $choose = __( 'choose', DFRAPI_DOMAIN );
375 return "
376 <div class='dfrapi_choose_box' rel='{$kind}'>
377 <span class='names'></span>
378 <a class='button choose_{$kind}'>{$choose}</a>
379 <input name='{$pfx}[value]' type='hidden' value=\"$value\"/>
380 </div>
381 ";
382 }
383
384 function ajaxHandler() {
385 $command = $this->get($_POST, 'command');
386 $value = $this->ary($this->get($_POST, 'value'));
387 $this->useSelected = intval($this->get($_POST, 'useSelected', 1));
388
389 switch($command) {
390 case "choose_network":
391 return $this->networksMerchantsPopup('network', $value);
392 case "choose_merchant":
393 return $this->networksMerchantsPopup('merchant', $value);
394 case "names_network":
395 return $this->networksMerchantsNames('network', $value);
396 case "names_merchant":
397 return $this->networksMerchantsNames('merchant', $value);
398 }
399 return "";
400 }
401
402 function renderField($field, $index, $params) {
403 $pfx = $this->inputPrefix($index);
404 $value = $this->get($params, 'value');
405 $operator = $this->get($params, 'operator');
406 $input = "";
407 $percent_sign = ( isset( $field['name'] ) && $field['name'] == 'salediscount') ? '%' : '';
408
409 switch($field['input']) {
410 case 'text':
411 $value = htmlspecialchars($value);
412 $input = "<input class='long' name='{$pfx}[value]' type='text' value=\"$value\"/>";
413 break;
414 case 'select':
415 $opts = $this->selectOpts($field['options'], $value);
416 $input = "<select name='{$pfx}[value]'>{$opts}</select>";
417 break;
418 case 'range':
419 $value = htmlspecialchars($value);
420 $value2 = htmlspecialchars($this->get($params, 'value2'));
421 $and = __( 'and', DFRAPI_DOMAIN );
422 $input = "
423 <input class='short' name='{$pfx}[value]' type='text' value=\"$value\"/>{$percent_sign}
424 <span class='value2' style='display:none'>
425 $and
426 <input class='short' name='{$pfx}[value2]' type='text' value=\"$value2\" />
427 </span>
428 ";
429 break;
430 case 'network':
431 $input = $this->chooseBox('network', $field, $index, $value);
432 break;
433 case 'merchant':
434 $input = $this->chooseBox('merchant', $field, $index, $value);
435 break;
436 case 'none':
437 $input = "";
438 break;
439 }
440
441 if(count($field['operator']) == 1) {
442 $key = key($field['operator']);
443 $val = current($field['operator']);
444 $operator = "
445 <input type='hidden' name='{$pfx}[operator]' value=\"{$key}\" />
446 <span>{$val}</span>
447 ";
448 } else {
449 $opts = $this->selectOpts($field['operator'], $operator);
450 $operator = "<select name='{$pfx}[operator]'>{$opts}</select>";
451 }
452 return array($operator, $input);
453 }
454
455 function renderRow($field, $index, $params, $show) {
456 $pfx = $this->inputPrefix($index);
457 list($operator, $input) = $this->renderField($field, $index, $params);
458 $fieldOpts = '';
459 foreach($this->fields() as $f) {
460 if(!$this->useSelected && $f['name'] == 'merchant_id')
461 continue;
462 $sel = $field['name'] == $f['name'] ? "selected='selected'" : "";
463 $fieldOpts .= "<option value=\"{$f['name']}\" $sel>{$f['title']}</option>";
464 }
465 $style = $show ? "" : "style='display:none'";
466 return "
467 <div class='filter filter_{$field['name']}' {$style}>
468 <div class='valuewrapper'>
469 <div class='value'>{$input}</div>
470 </div>
471 <div class='plusminus'><a class='minus'></a> </div>
472 <div class='field'><select name='{$pfx}[field]' style='width: 140px'>{$fieldOpts}</select><a href='#' class='dfrapi_search_help'>?</a></div>
473 <div class='operator'>{$operator}</div>
474 <div class='clearfix'></div>
475 <div class='help' style='display:none;'><a href='#' class='dfrapi_search_help'><span class='dashicons dashicons-no'> </span></a>{$field['help']}</div>
476 </div>
477 ";
478 }
479
480 function render($prefix, $query, $useSelected=TRUE) {
481 $this->prefix = $prefix;
482 $this->useSelected = intval($useSelected);
483 if(!$query)
484 $query = array(
485 array('field'=>'any', 'value'=>'')
486 );
487 $defaults = $this->defaults();
488
489 $fieldMap = array();
490 $fieldUsed = array();
491 foreach($this->fields() as $f) {
492 if(!$this->useSelected && $f['name'] == 'merchant_id')
493 continue;
494 $fieldMap[$f['name']] = $f;
495 }
496
497 $form = "";
498 $index = 0;
499 foreach($query as $params) {
500 $field = $this->get($fieldMap, $this->get($params, 'field'));
501 if(!$field)
502 continue;
503 $fieldUsed[$field['name']] = 1;
504 $form .= $this->renderRow($field, $index++, $params, TRUE);
505 }
506 $show = ($index == 0); // if none shown, show the first
507 foreach($fieldMap as $field) {
508 $name = $field['name'];
509 if(!isset($fieldUsed[$name])) {
510 $form .= $this->renderRow($field, $index++, isset($defaults[$name]) ? $defaults[$name] : null, $show);
511 $show = FALSE;
512 }
513 }
514
515 $loading = __( 'Loading, please wait', DFRAPI_DOMAIN );
516 $add = __( 'add filter', DFRAPI_DOMAIN );
517 return "
518 <div id='dfrapi_search_form'>
519 <input type='hidden' id='dfrapi_useSelected' value='{$this->useSelected}' />
520 <div id='dfprs_loading_content' style='display:none'>
521 <div class='dfrapi_loading'></div>
522 <h3>{$loading}</h3>
523 </div>
524 {$form}
525 <div class='clearfix'></div>
526 <div id='dfrapi_search_form_filter'><a href='#'><span class='dashicons dashicons-plus'> </span> $add</a></div>
527 </div>
528 ";
529 }
530
531 function combineLists($lst, $func) {
532 if(!count($lst))
533 return array();
534 if(count($lst) == 1)
535 return current($lst);
536 $lst = call_user_func_array($func, $lst);
537 return count($lst) ? $lst : NULL;
538 }
539
540 function idFilter($inList, $exList) {
541 $inList = $this->combineLists($inList, 'array_intersect');
542 $exList = $this->combineLists($exList, 'array_merge');
543
544 if(is_null($inList) || is_null($exList)) {
545 return NULL;
546 }
547 if(count($inList)) {
548 if(count($exList)) {
549 $inList = array_diff($inList, $exList);
550 if(!count($inList))
551 return NULL;
552 }
553 return array("IN", $inList);
554 }
555 if(count($exList)) {
556 return array("!IN", $exList);
557 }
558 return array(NULL, NULL);
559 }
560
561 function fulltextFilter($operator, $value) {
562 if($operator == 'match')
563 return array("LIKE", $value);
564 $value = trim(preg_replace('~[!\\[\\]"^$]+~', " ", $value));
565 if(strlen($value)) {
566 switch($operator) {
567 case 'is': return array('LIKE', "^$value\$");
568 case 'contain': return array('LIKE', $value);
569 case 'not_contain': return array('!LIKE', $value);
570 case 'start': return array('LIKE', "^$value");
571 case 'end': return array('LIKE', "$value\$");
572 }
573 }
574 return array(NULL, NULL);
575 }
576
577 function makeFilters($query, $useSelected=TRUE) {
578
579 $filters = array();
580
581 $selected = array(
582 'in:source_id' => array(),
583 'ex:source_id' => array(),
584 'in:merchant_id' => array(),
585 'ex:merchant_id' => array(),
586 );
587
588 $allNetworks = $this->ids($this->allNetworks());
589
590 if($useSelected) {
591 $selected['in:source_id'] []= $this->ids($this->selectedNetworks());
592 $selected['in:merchant_id'] []= $this->ids($this->selectedMerchants());
593 } else {
594 $selected['in:source_id'] []= $allNetworks;
595 }
596
597 foreach($query as $params) {
598 $fname = $params['field'];
599 $value = $this->get($params, 'value');
600 $value2 = $this->get($params, 'value2');
601 $operator = strtolower($this->get($params, 'operator'));
602
603 switch($fname) {
604 case 'any':
605 case 'name':
606 case 'brand':
607 case 'description':
608 case 'category':
609 $s = $this->fulltextFilter($operator, $value);
610 if(!is_null($s[0])) {
611 $filters []= "{$fname} {$s[0]} {$s[1]}";
612 }
613 break;
614 case 'tags':
615 $operator = ($operator == 'in') ? "LIKE" : "!LIKE";
616 $filters []= "{$fname} {$operator} {$value}";
617 break;
618 case 'currency':
619 $filters []= "{$fname} = {$value}";
620 break;
621 case 'price':
622 case 'saleprice':
623 case 'salediscount':
624 $conv = $fname == 'salediscount' ? 'intval' : 'dfrapi_price_to_int';
625 $value = $conv($value);
626 switch($operator) {
627 case 'between':
628 $value2 = $conv($value2);
629 $filters []= "{$fname} > {$value}";
630 $filters []= "{$fname} < {$value2}";
631 break;
632 case 'lt':
633 $filters []= "{$fname} < {$value}";
634 break;
635 case 'gt':
636 $filters []= "{$fname} > {$value}";
637 break;
638 }
639 break;
640 case 'source_id':
641 case 'merchant_id':
642 $key = ($operator == 'is') ? 'in' : 'ex';
643 $selected["$key:$fname"] []= $this->ary($value);
644 break;
645 case 'type':
646 $ids = array();
647 foreach($this->allNetworks() as $net) {
648 if($net['type'] == $value)
649 $ids []= $net['_id'];
650 }
651 $selected["in:source_id"] []= $ids;
652 break;
653 case 'onsale':
654 $value = ($operator == 'yes') ? '1' : '0';
655 $filters []= "{$fname} = {$value}";
656 break;
657 case 'image':
658 case 'thumbnail':
659 $operator = ($operator == 'yes') ? '!EMPTY' : 'EMPTY';
660 $filters []= "image {$operator}";
661 break;
662 case 'time_updated':
663 $value = @date('Y-m-d H:i:s', strtotime($value));
664 switch($operator) {
665 case 'between':
666 $value2 = @date('Y-m-d H:i:s', strtotime($value2));
667 $filters []= "{$fname} > {$value}";
668 $filters []= "{$fname} < {$value2}";
669 break;
670 case 'lt':
671 $filters []= "{$fname} < {$value}";
672 break;
673 case 'gt':
674 $filters []= "{$fname} > {$value}";
675 break;
676 }
677 break;
678 }
679 }
680
681 $s = $this->idFilter($selected['in:source_id'], $selected['ex:source_id']);
682 if(is_null($s))
683 return array('error' => 'No networks selected');
684 if(!is_null($s[0]) && count($s[1]) < count($allNetworks))
685 $filters []= "source_id {$s[0]} ". implode(',', $s[1]);
686
687 $s = $this->idFilter($selected['in:merchant_id'], $selected['ex:merchant_id']);
688 if(is_null($s))
689 return array('error' => 'No merchants selected');
690 if(!is_null($s[0]))
691 $filters []= "merchant_id {$s[0]} ". implode(',', $s[1]);
692
693 return $filters;
694
695 }
696
697 function help_tip($tip) {
698 return '
699 <div class="dfrapi_search_tip">
700 <span class="dashicons dashicons-lightbulb"></span>
701 <p>
702 <strong>' . __( 'TIP:', DFRAPI_DOMAIN ) . '</strong> ' .
703 $tip . '
704 </p>
705 </div>
706 ';
707 }
708
709 function help_operators() {
710 return '
711 <p>
712 <span class="dashicons dashicons-info"></span>
713 <em>
714 <a href="https://v4.datafeedr.com/node/620" target="_blank">' . __('Learn more', DFRAPI_DOMAIN ) . '</a> ' .
715 __('about advanced uses of this field.', DFRAPI_DOMAIN ) . '
716 </em>
717 </p>
718 ';
719 }
720
721 function help($field) {
722
723 $help = array();
724
725 // Any
726 $help['any'] = '<h3>' . __('Any Field', DFRAPI_DOMAIN ) . '</h3>';
727 $help['any'] .= '<p>' . __( 'Search all indexed text fields at once to return a broad set of results.', DFRAPI_DOMAIN ) . '</p>';
728 $help['any'] .= '<p>' . __( 'The fields listed below are indexed as text fields and searchable using Any Field. Image, currency, and price fields are not searched.', DFRAPI_DOMAIN ) . '</p>';
729 $help['any'] .= '<p><em>' . __( '*Note that not all merchants and networks provide every field. ', DFRAPI_DOMAIN ) . '</em></p>';
730 $help['any'] .= '<p>' . __( 'Fields searched using Any Field:', DFRAPI_DOMAIN ) . '</p>';
731 $help['any'] .= '<table width="100%" border="0" style="margin-bottom:20px"><tr><td width="33%" valign="top">accommodationtype<br />address<br />artist<br />author<br />bestsellers<br />brand<br />category<br />city<br />color<br />commissiontype<br />condition<br />country<br />county<br />description<br />destination<br />discount</td><td width="33%" valign="top">discounttype<br />ean<br />fabric<br />featured<br />flavour<br />gender<br />genre<br />isbn<br />language<br />location<br />manufacturer<br />manufacturerid<br />material<br />model<br />mpn<br />name</td><td width="33%" valign="top">offercode<br />offertype<br />platform<br />productnumber<br />promo<br />publisher<br />rating<br />region<br />size<br />sku<br />stars<br />state<br />subcategory<br />tags<br />upc<br />weight</td></tr></table>';
732 $help['any'] .= $this->help_operators();
733
734 // Name
735 $help['name'] = '<h3>' . __('Product Name', DFRAPI_DOMAIN ) . '</h3>';
736 $help['name'] .= '<p>' . __( 'Search by product name to narrow your results.', DFRAPI_DOMAIN ) . '</p>';
737 $help['name'] .= $this->help_tip( __( 'Some merchants include color, size, gender, product codes, sale information and promotions in the product name field.', DFRAPI_DOMAIN ) );
738 $help['name'] .= $this->help_operators();
739
740 // Brand
741 $help['brand'] = '<h3>' . __('Brand', DFRAPI_DOMAIN ) . '</h3>';
742 $help['brand'] .= '<p>' . __( 'Search by brand name to get specific results. Not every item has a brand name.', DFRAPI_DOMAIN ) . '</p>';
743 $help['brand'] .= $this->help_tip( __( 'Enter the shorter version of a brand name in this field. Omit words such as "Incorporated", "Limited" and their abbreviations like Inc., Ltd. and so on.', DFRAPI_DOMAIN ) );
744 $help['brand'] .= $this->help_operators();
745
746 // Description
747 $help['description'] = '<h3>' . __('Description', DFRAPI_DOMAIN ) . '</h3>';
748 $help['description'] .= '<p>' . __( 'Search the description field for product attributes such as size, color, material, or usage.', DFRAPI_DOMAIN ) . '</p>';
749 $help['description'] .= $this->help_tip( __( 'Most merchants provide a product description. Some product details may only appear in the description and not in any other field. However, some merchants duplicate the product name or product code in the description field without supplying additional details or leave the product description blank.', DFRAPI_DOMAIN ) );
750 $help['description'] .= $this->help_operators();
751
752 // Tags
753 $help['tags'] = '<h3>' . __('Tags', DFRAPI_DOMAIN ) . '</h3>';
754 $help['tags'] .= '<p>' . __( 'Limit search results based on product tag and keyword information.', DFRAPI_DOMAIN ) . '</p>';
755 $help['tags'] .= $this->help_tip( __( 'This field contains data from various keyword-related fields provided by the merchant. This field does not always exist.', DFRAPI_DOMAIN ) );
756
757 // Category
758 $help['category'] = '<h3>' . __('Category', DFRAPI_DOMAIN ) . '</h3>';
759 $help['category'] .= '<p>' . __( 'Limit search results based on category information.', DFRAPI_DOMAIN ) . '</p>';
760 $help['category'] .= $this->help_tip( __( 'This field contains data from various category-related fields provided by the merchant. This field does not always exist.', DFRAPI_DOMAIN ) );
761 $help['category'] .= $this->help_operators();
762
763 // Type
764 $help['type'] = '<h3>' . __('Product Type', DFRAPI_DOMAIN ) . '</h3>';
765 $help['type'] .= '<p>' . __( 'Limit your search results to one type of item, either Product or Coupon.', DFRAPI_DOMAIN ) . '</p>';
766 $help['type'] .= $this->help_tip( __( 'In order to use this filter, you must have already selected merchants that provide that type of item. For example, if you choose "Product type: Coupon" but have not selected any merchants that offer coupons, your search will return an error.', DFRAPI_DOMAIN ) );
767
768 // Currency
769 $help['currency'] = '<h3>' . __('Currency', DFRAPI_DOMAIN ) . '</h3>';
770 $help['currency'] .= '<p>' . __( 'Limit your search results to items with a specific currency code.', DFRAPI_DOMAIN ) . '</p>';
771 $help['currency'] .= $this->help_tip( __( 'Selecting a currency code is one way to limit your search results to items from a specific country. However, not every item has been given a currency code value by the merchant. Items without a currency code will be excluded from your search results.', DFRAPI_DOMAIN ) );
772
773 // Price
774 $help['price'] = '<h3>' . __('Price', DFRAPI_DOMAIN ) . '</h3>';
775 $help['price'] .= '<p>' . __( 'Filter your search results based on price. Return products less than, greater than, or within a price range that you set.', DFRAPI_DOMAIN ) . '</p>';
776 $help['price'] .= $this->help_tip( __( 'This field does not search on sale price. If you set a price range to less than 30, you will exclude an item with a regular price of 40 that is on sale for less than 30.', DFRAPI_DOMAIN ) );
777
778 // Sale Price
779 $help['saleprice'] = '<h3>' . __('Sale Price', DFRAPI_DOMAIN ) . '</h3>';
780 $help['saleprice'] .= '<p>' . __( 'Filter your search results based on sale price. Return items less than, greater than, or within a sale price range that you set.', DFRAPI_DOMAIN ) . '</p>';
781 $help['saleprice'] .= $this->help_tip( __( 'This field does not search on regular price. If you set a sale price range to between 50 and 100, an item with a sale price of 40 will be excluded even if it\'s regular price matches the range you set.', DFRAPI_DOMAIN ) );
782
783 // Network
784 $help['source_id'] = '<h3>' . __('Network', DFRAPI_DOMAIN ) . '</h3>';
785 $help['source_id'] .= '<p>' . __( 'Limit your search results to items from one or more affiliate networks.', DFRAPI_DOMAIN ) . '</p>';
786 $help['source_id'] .= $this->help_tip( __( 'Affiliate networks are generally country-specific. Using the Network filter is one way to limit your search results by country.', DFRAPI_DOMAIN ) );
787
788 // Merchant
789 $help['merchant_id'] = '<h3>' . __('Merchant', DFRAPI_DOMAIN ) . '</h3>';
790 $help['merchant_id'] .= '<p>' . __( 'Limit your search results to items from one or more merchants.', DFRAPI_DOMAIN ) . '</p>';
791 $help['merchant_id'] .= $this->help_tip( __( 'Using the Merchant filter is a quick way to exclude unrelated products and reduce the number of API requests made when building a Product Set. For example, if you are creating a Product Set related to cat products, exclude all merchants that only sell dog products.', DFRAPI_DOMAIN ) );
792
793 // On Sale
794 $help['onsale'] = '<h3>' . __('On Sale', DFRAPI_DOMAIN ) . '</h3>';
795 $help['onsale'] .= '<p>' . __( 'Set this field to "<strong>yes</strong>" to return only items which are on sale. To exclude products which are on sale, set this field to "<strong>no</strong>".', DFRAPI_DOMAIN ) . '</p>';
796
797 // Discount
798 $help['salediscount'] = '<h3>' . __('Discount', DFRAPI_DOMAIN ) . '</h3>';
799 $help['salediscount'] .= '<p>' . __( 'Limit your search results to items with a specified discount. Enter the number in terms of percentage (1 - 100) to indicate a discount less than, greater than, or between a given range. You do not need to enter the percentage sign.', DFRAPI_DOMAIN ) . '</p>';
800 $help['salediscount'] .= $this->help_tip( __( 'To display, for example, only products that are on sale for a discount of 20% or more, choose the "greater than" operator and type "19".', DFRAPI_DOMAIN ) );
801
802 // Has Image
803 $help['image'] = '<h3>' . __('Has Image', DFRAPI_DOMAIN ) . '</h3>';
804 $help['image'] .= '<p>' . __( 'Limit your search results to items which have an image (or which don\'t).', DFRAPI_DOMAIN ) . '</p>';
805 $help['image'] .= $this->help_tip( __( 'Sometimes the image URL in the merchant\'s data feed is broken. Items with broken images will still return in search results even though there appears to be no image.', DFRAPI_DOMAIN ) );
806
807 // Last Updated
808 $help['time_updated'] = '<h3>' . __('Last Updated', DFRAPI_DOMAIN ) . '</h3>';
809 $help['time_updated'] .= '<p>' . __( 'Filter products by the last time they were updated by the merchant. Enter an English textual datetime description using PHP\'s <a href="http://www.php.net/strtotime" target="_blank">strtotime()</a> function.', DFRAPI_DOMAIN ) . '</p>';
810 $help['time_updated'] .= '<h3>' . __('Examples', DFRAPI_DOMAIN ) . '</h3>';
811 $help['time_updated'] .= '<p>';
812 $help['time_updated'] .= '<tt>' . __('last week', DFRAPI_DOMAIN ) . '</tt><br />';
813 $help['time_updated'] .= '<tt>' . __('2 days ago', DFRAPI_DOMAIN ) . '</tt><br />';
814 $help['time_updated'] .= '<tt>' . __('1 month ago', DFRAPI_DOMAIN ) . '</tt>';
815 $help['time_updated'] .= '</p>';
816 $help['time_updated'] .= '<p>' . __( '', DFRAPI_DOMAIN ) . '</p>';
817 $help['time_updated'] .= $this->help_tip( __( 'An item\'s Last Updated date will not change if the merchant does not change any product information during a data feed update.', DFRAPI_DOMAIN ) );
818
819 // Limit
820 $help['limit'] = '<h3>' . __('Limit', DFRAPI_DOMAIN ) . '</h3>';
821 $help['limit'] .= '<p>' . __( 'Limit the number of items returned in your search results. The maximum number of products that can be returned is 10,000.', DFRAPI_DOMAIN ) . '</p>';
822 $help['limit'] .= $this->help_tip( __( 'Limiting the number of products returned helps reduce the number of API requests made during searching and updating Product Sets.', DFRAPI_DOMAIN ) );
823
824 // Sort By
825 $help['sort'] = '<h3>' . __('Sort By', DFRAPI_DOMAIN ) . '</h3>';
826 $help['sort'] .= '<p>' . __( 'Change the sort criteria by which items are displayed in your search results.', DFRAPI_DOMAIN ) . '</p>';
827 $help['sort'] .= $this->help_tip( __( 'By default, search results are sorted by relevance. You can change that to sort by price, sale price, discount, or last updated date in ascending order (lowest to highest) or descending order (highest to lowest). You can also sort by merchant, which lists items alphabetically by merchant name.', DFRAPI_DOMAIN ) );
828
829 // Exclude Duplicates
830 $help['duplicates'] = '<h3>' . __('Exclude Duplicates', DFRAPI_DOMAIN ) . '</h3>';
831 $help['duplicates'] .= '<p>' . __( 'Exclude items that contain identical product names, image URLs, etc. Enter one or more terms from the list below. Separate terms by a space (meaning AND) or | (pipe symbol, meaning OR).', DFRAPI_DOMAIN ) . '<br />';
832 $help['duplicates'] .= '<p>' . __( 'Enter one of these terms to exclude duplicates matching these fields:', DFRAPI_DOMAIN ) . '<br />';
833 $help['duplicates'] .= '<tt>' . __('name', DFRAPI_DOMAIN ) . '</tt><br />';
834 $help['duplicates'] .= '<tt>' . __('brand', DFRAPI_DOMAIN ) . '</tt><br />';
835 $help['duplicates'] .= '<tt>' . __('currency', DFRAPI_DOMAIN ) . '</tt><br />';
836 $help['duplicates'] .= '<tt>' . __('price', DFRAPI_DOMAIN ) . '</tt><br />';
837 $help['duplicates'] .= '<tt>' . __('saleprice', DFRAPI_DOMAIN ) . '</tt><br />';
838 $help['duplicates'] .= '<tt>' . __('source_id', DFRAPI_DOMAIN ) . '</tt><br />';
839 $help['duplicates'] .= '<tt>' . __('merchant_id', DFRAPI_DOMAIN ) . '</tt><br />';
840 $help['duplicates'] .= '<tt>' . __('onsale', DFRAPI_DOMAIN ) . '</tt><br />';
841 $help['duplicates'] .= '<tt>' . __('image', DFRAPI_DOMAIN ) . '</tt><br />';
842 $help['duplicates'] .= '<tt>' . __('thumbnail', DFRAPI_DOMAIN ) . '</tt>';
843 $help['duplicates'] .= '</p>';
844 $help['duplicates'] .= '<h3>' . __('Examples', DFRAPI_DOMAIN ) . '</h3>';
845 $help['duplicates'] .= '<p>';
846 $help['duplicates'] .= '<tt>' . __('image</tt> - Exclude items which have the same image URL.', DFRAPI_DOMAIN ) . '<br />';
847 $help['duplicates'] .= '<tt>' . __('name image</tt> - Exclude items with the same name AND the same image URL.', DFRAPI_DOMAIN ) . '<br />';
848 $help['duplicates'] .= '<tt>' . __('name|image</tt> - Exclude items with the same name OR the same image URL.', DFRAPI_DOMAIN ) . '<br />';
849 $help['duplicates'] .= '<tt>' . __('merchant_id name|image</tt> - Exclude items which have the same merchant id AND (product name OR image URL).', DFRAPI_DOMAIN ) . '<br />';
850 $help['duplicates'] .= '</p>';
851 $help['duplicates'] .= $this->help_tip( __( 'By excluding duplicates, you will eliminate all but one item. For example, if 20 products have identical image URLs and you exclude duplicates matching the <strong>image</strong> field, <em>one</em> item will be returned and 19 items will be excluded.', DFRAPI_DOMAIN ) );
852
853
854 if (isset($help[$field])) {
855 return $help[$field];
856 } else {
857 return '';
858 }
859
860 } // help()
861
862 }
863