3fingers Posted June 17, 2020 Share Posted June 17, 2020 Hey all, I know about $input->whitelist and tried all my way down to solve this problem. Basically the query string get lost in some way on the 2nd and subsequent pages I get this url: myurl/page2?q=WireInputData My eyes and brain got a twist and cannot go further. I post my code in here, if somebody would like to help me figuring it out: Here the form Spoiler <?php namespace ProcessWire; ?> <body> <div class="main-container"> <div class="section-title-container"> <div class="section-title-wrapper"> <div class="section-title"> <h1><?= $page->title ?></h1> </div> </div> <div class="section-body-container"> <div class="section-body-wrapper ptneg"> <p><?= $page->body ?></p> </div> </div> <div class="form-container"> <!-- SEARCH FORM !--> <form name='search' id='product-search' method='get' action='<?= $page->url ?>'> <ul> <li class="settori-strip"> <label for='search_forma'>Settori</label> <?php $field = $fields->get('categoria_alimentare'); $categorie_array = $field->type->getOptions($field); $categorie_options = array(); foreach($categorie_array as $categorie) { array_push($categorie_options, $categorie->title); } foreach($categorie_options as $key => $value) { $checked= ''; if($input->get->categorie_options) { foreach ($input->get->categorie_options as $categoria) { $categoria = $sanitizer->selectorValue($categoria); if($categoria == $value) $checked = 'checked="checked"'; } } echo "<input type='checkbox' name='categorie_options[]' value='$value' id='sec-$value' $checked><label for='sec-$value'>$value</label>"; } ?> </li> <div class="middle-strip"> <label for='search_forma'>Forma</label> <?php $field = $fields->get('forma_prodotto'); $forme_array = $field->type->getOptions($field); $forme_options = array(); foreach($forme_array as $forme) { array_push($forme_options, $forme->title); } $i = 0; $images = $page->images; foreach($forme_options as $key => $value) { $checked= ''; if($input->get->forme_options) { foreach ($input->get->forme_options as $forma) { $forma = $sanitizer->selectorValue($forma); if($forma == $value) $checked = 'checked="checked"'; } } echo "<li class='icons'><input type='checkbox' name='forme_options[]' value='$value' id='ico-$value' $checked><label for='ico-$value'><img src='{$images->eq($i)->url}'/></label></li>"; $i++; } ?> <li class="checks"> <input type='checkbox' name='coperchio' id='search_coperchio' <?php if($input->get->coperchio){echo 'checked="checked"';} ?>> <label for='search_coperchio'>Coperchio</label> </li> <li class="checks"> <input type='checkbox' name='cpet' id='search_cpet' <?php if($input->get->cpet){echo 'checked="checked"';} ?> /> <label for='search_cpet'>Cpet</label> </li> </div> <div class="select-strip"> <li> <label for='search_codice'>Lunghezza Prodotto</label> <input type='text' name='lunghezze' class='selectize' value=' <?php if($input->whitelist->lunghezze) echo $sanitizer->entities($input->whitelist->lunghezze); if($input->get->lunghezze) echo ($input->get->lunghezze); ?>' /> </li> <li> <label for='search_codice'>Larghezza Prodotto</label> <input type='text' name='larghezze' class='selectize' value=' <?php if($input->whitelist->larghezze) echo $sanitizer->entities($input->whitelist->larghezze); if($input->get->larghezze) echo ($input->get->larghezze); ?>' /> </li> <li> <label for='search_codice'>Altezza Prodotto</label> <input type='text' name='altezze' class='selectize' value=' <?php if($input->whitelist->altezze) echo $sanitizer->entities($input->whitelist->altezze); if($input->get->altezze) echo ($input->get->altezze); ?>' /> </li> </div> <div class="codice-strip"> <li> <label for='search_codice'>Codice Prodotto</label> <input type='text' name='codice' class='selectize' value=' <?php if($input->whitelist->codice) echo $sanitizer->entities($input->whitelist->codice); if($input->get->codice) echo ($input->get->codice); ?>' /> </li> <li> <button type='submit' id='search_submit' name='submit1' value='Search'>Cerca</button> </li> </div> </form> </div> </div> <?php include "./search/search_alimentare.php"; // HERE COMES THE LOGIC FOR THE FORM, IN THE NEXT "SPOILER" HERE IN THE TOPIC // START LISTATO PRODOTTI // if(count($input->get)) { $products= ''; $products.="<div class='listato-container'>"; $products.="<div class='listato-wrapper'>"; foreach($matches as $product) { // START SINGLE PRODUCT // $products.="<div class='single-product'>"; $products.="<img src='{$product->image->url}' alt='Codice prodotto:{$product->title}'>"; $products.="<div class='single-product-info'>"; $products.="<span class='product-title'>Codice: {$product->title}</span>"; $products.="<span>Lunghezza/larghezza (mm):<p>"; $products.="<p>{$product->variante_prodotto[0]->lunghezza}x{$product->variante_prodotto[0]->larghezza}</p>"; $products.="<span>Altezze disponibili (mm):</span>"; $products.="<p>"; foreach($product->variante_prodotto as $variante) { if($variante->variante_attiva){ $products.="{$variante->altezza}/"; } } $products.="</p>"; $products.="<div class='single-product-pills'>"; if($product->coperchio) { $products.="<span>Disponibile coperchio</span>"; } if($product->variante_prodotto->has('cpet=1')) { $products.="<span>Disponibile Cpet</span>"; } $products.="</div>"; $products.="</div>"; $products.="</div>"; // END SINGLE PRODUCT // } $products.="</div>"; $pagination = $matches->renderPager(); $products.= "{$pagination}"; $products.="</div>"; // END LISTATO PRODOTTI // echo $products; } ?> </body> Here the logic Spoiler <?php namespace ProcessWire; // check if there are GET variables present in the URL if (count($input->get)) { $q = $sanitizer->selectorValue($input->get); $input->whitelist('q', $q); $selector = ''; $percentuale = 20; // Check se è presente il codice if ($input->get->codice) { $codice = $sanitizer->selectorValue($input->get->codice); $selector .= "title=$codice, "; } // Check se è presente il coperchio nella query if ($input->get->coperchio) { $coperchio = $sanitizer->checkbox($input->get->coperchio); $selector .= "coperchio=$coperchio, "; } // Check se è presente il materiale CPET nella query if ($input->get->cpet) { $cpet = $sanitizer->checkbox($input->get->cpet); $selector .= "variante_prodotto.cpet=$cpet, "; } // Check se sono presenti delle forme nella query if ($input->get->forme_options) { foreach ($input->get->forme_options as $forma) { $forma = $sanitizer->selectorValue($forma); $selector .= "forma_prodotto.title=$forma, "; } } // Check se è presente la categoria alimentare nella query if ($input->get->categorie_options) { foreach ($input->get->categorie_options as $categoria) { $categoria = $sanitizer->selectorValue($categoria); $selector .= "categoria_alimentare.title=$categoria, "; } } // Check se è presente lunghezza if ($input->get->lunghezze) { $lunghezza = $sanitizer->selectorValue($input->get->lunghezze); $tolleranza = ($percentuale / 100) * $lunghezza; $val_up = $lunghezza + $tolleranza; $val_down = $lunghezza - $tolleranza; $selector .= "variante_prodotto.lunghezza>=$val_down, "; $selector .= "variante_prodotto.lunghezza<=$val_up, "; } // Check se è presente larghezza if ($input->get->larghezze) { $larghezza = $sanitizer->selectorValue($input->get->larghezze); $tolleranza = ($percentuale / 100) * $larghezza; $val_up = $larghezza + $tolleranza; $val_down = $larghezza - $tolleranza; $selector .= "variante_prodotto.larghezza>=$val_down, "; $selector .= "variante_prodotto.larghezza<=$val_up, "; } // Check se è presente altezza if ($input->get->altezze) { $altezza = $sanitizer->selectorValue($input->get->altezze); $tolleranza = ($percentuale / 100) * $altezza; $val_up = $altezza + $tolleranza; $val_down = $altezza - $tolleranza; $selector .= "variante_prodotto.altezza>=$val_down, "; $selector .= "variante_prodotto.altezza<=$val_up, "; } $output = ''; $selector .= "limit=20, template=prodotto_alimentare, sort=variante_prodotto.lunghezza"; $matches = $pages->find("$selector"); bd($selector); $count = count($matches); $start = $matches->getStart() + 1; $end = $matches->getStart() + $count; $total = $matches->getTotal(); if ($count) { $output .= "<div class='listato-container mbneg'><h3 class='res-count'>Stai visualizzando da $start a $end di $total prodotti totali:</h3></div>"; } else { $output .= "<div class='listato-container mbneg'><h3>La tua ricerca non ha prodotto alcun risultato, riprova con altri criteri.</h3></div>"; } } else { $output = "<div class='listato-container mbneg'><h3>Incomincia la ricerca selezionando un campo dal form.</h3></div>"; } echo $output; Many thanks! Link to comment Share on other sites More sharing options...
Jan Romero Posted June 17, 2020 Share Posted June 17, 2020 Quote myurl/page2?q=WireInputData This suggests that the query string does not receive the search string but an object of type WireInputData instead. WireInputData is the class behind the WireInput properties $input->get, $input->post, and so on. $q = $sanitizer->selectorValue($input->get); $input->whitelist('q', $q); Here you put the $input->get object of type WireInputData into a sanitizer method. The method only accepts strings and arrays. Since you gave it neither, it makes a string out of it. I guess this turns the WireInputData object into the string "WireInputData". Not sure what the right fix is. What is “q” supposed to be? It looks more like the query string you want is something like “?larghezze=123&lunghezze=456”. So you should put each of those into a separate whitelist item, eg. $input->whitelist('larghezze', $input->get->selectorValue('larghezze')). ProcessWire’s pagination will automatically put everything from $input->whitelist in the url query string. if($input->whitelist->lunghezze) echo $sanitizer->entities($input->whitelist->lunghezze); if($input->get->lunghezze) echo ($input->get->lunghezze); //delete this! Here you output lunghezze twice, only the first line doesn’t work, because you never put anything into $input->whitelist->lunghezze. Also, the whitelist is stored on the server and you’re expected to only fill it with things you already sanitized, so there is no need to sanitize it again at that point. In the second line you output untrusted unsanitized input straight from the GET request! You should delete that line and the others like it. They’re unnecessary anyway, because you already output the whitelisted stuff above ? Change it to this: echo $input->whitelist->lunghezze; That should be all you need. Then, in search_alimentare.php, add the line I highlighted: if ($input->get->lunghezze) { $lunghezza = $sanitizer->selectorValue($input->get->lunghezze); $input->whitelist->lunghezze = $lunghezza; //add this line for each get variable $tolleranza = ($percentuale / 100) * $lunghezza; $val_up = $lunghezza + $tolleranza; $val_down = $lunghezza - $tolleranza; $selector .= "variante_prodotto.lunghezza>=$val_down, "; $selector .= "variante_prodotto.lunghezza<=$val_up, "; } Sorry I’m being so incoherent ? 4 Link to comment Share on other sites More sharing options...
3fingers Posted June 17, 2020 Author Share Posted June 17, 2020 @Jan Romero Just here to say thanks for your detailed answer, is such amazing how much this community surprises me even after years. I'm going to test your suggestion tomorrow at office time, and be back here to mark (hopefully) solved this thread. Thanks again, really really appreciated your effort. 2 Link to comment Share on other sites More sharing options...
3fingers Posted June 18, 2020 Author Share Posted June 18, 2020 @Jan Romero Got success for single values but still have troubles with multi-selection choices (such as checkboxes). I'm trying to solve this way, but without success: // In the code for the form foreach($forme_options as $key => $value) { echo "<li class='icons'><input type='checkbox' name='forme_options[]' value='$value' id='ico-$value'><label for='ico-$value'><img src='{$images->eq($i)->url}'/></label></li>"; $i++; } // Later in the logic if ($input->get->forme_options) { $forma = $sanitizer->selectorValue($input->get->forme_options); $input->whitelist->forme_options = $forma; foreach ($input->get->forme_options as $forma) { $selector .= "forma_prodotto.title=$forma, "; } } In the first page of the result I got this GET query back and results are correct: myurl/?forme_options%5B%5D=rettangolare on the second page (and onwards) i GET this, but the query is lost: myurl/page2?forme_options=rettangolare which looks kinda right, but...no. ? Sorry but this is my first "complex" search form with processwire and I'm not really an expert with this. Any clue? Link to comment Share on other sites More sharing options...
Sergio Posted June 18, 2020 Share Posted June 18, 2020 Here's how I did it on a similar project. The search query: https://www.brightline.org/resources/?keywords=distributed&resource_type=Reports&topic=Blockchain&author=Blockchain+Research+Institute&submit=1 On the page: if(count($resources) > 0) { $segment = ''; if($input->urlSegment1) { $segment = $sanitizer->selectorValue($input->urlSegment1); $segment .= "/"; } echo $pagination = renderPagination($resources, $segment); } And on a _func.php (or any other file like _init.php) function renderPagination(PageArray $items, $segment = '') { if(!$items->getLimit() || $items->getTotal() <= $items->getLimit()) return ''; $next = isset($options['next']) ? $options['next'] : __('Next'); $previous = isset($options['previous']) ? $options['previous'] : __('Previous'); $page = page(); if(!$page->template->allowPageNum) { return "Pagination is not enabled for this template"; } // customize the MarkupPagerNav to output $options = array( 'numPageLinks' => 4, //4 is a good size for mobile as we're using next and prev items 'nextItemLabel' => $next, 'nextItemClass' => 'js-next', // 'previousItemLabel' => '<span><i class="uk-icon-angle-double-left"></i></span>', // 'previousItemClass' => '', // 'lastItemClass' => '', // 'currentItemClass' => 'tw-bg-orange tw-font-bold', 'separatorItemLabel' => '<span>…</span>', 'listMarkup' => "<ul id='js-pagination' class='tw-my-8 tw-justify-center tw-text-lg tw-list-reset tw-flex'>{out}</ul>", 'itemMarkup' => "<li class='{class} tw-mr-3'>{out}</li>", 'linkMarkup' => "<a href='{url}' class='tw-rounded tw-bg-white tw-px-3 tw-py-2 hover:tw-bg-orange hover:tw-text-white'>{out}</a>", 'currentLinkMarkup' => "<span class='tw-px-2 tw-py-2'>{out}</span>" ); $pager = modules('MarkupPagerNav'); $pager->setBaseUrl($page->url.$segment); return $pager->render($items, $options); } Link to comment Share on other sites More sharing options...
Sergio Posted June 18, 2020 Share Posted June 18, 2020 11 minutes ago, Sergio said: Here's how I did it on a similar project. The search query: https://www.brightline.org/resources/?keywords=distributed&resource_type=Reports&topic=Blockchain&author=Blockchain+Research+Institute&submit=1 Forgot to mention that although I load more items using javascript, the query parameters are kept between the pages. Link to comment Share on other sites More sharing options...
3fingers Posted June 18, 2020 Author Share Posted June 18, 2020 Thanks @Sergio but I don't think my problem is related to pagination, infact it works correctly on my side. I think it's rather something to do with whitelist on multiple checkbox (eg. forme_options[] ) which I cannot get it works. Also take a look at my url in my last post above: %5B%5D // I think it's [] encoded, but then it get lost on subsequent pages Link to comment Share on other sites More sharing options...
Sergio Posted June 18, 2020 Share Posted June 18, 2020 1 hour ago, 3fingers said: Thanks @Sergio but I don't think my problem is related to pagination, infact it works correctly on my side. I think it's rather something to do with whitelist on multiple checkbox (eg. forme_options[] ) which I cannot get it works. Also take a look at my url in my last post above: %5B%5D // I think it's [] encoded, but then it get lost on subsequent pages My bad, I misread it. Maybe this will help you: 1 Link to comment Share on other sites More sharing options...
3fingers Posted June 18, 2020 Author Share Posted June 18, 2020 And this particular post it's the key to success ? Here's the solution: if ($input->get->forme_options) { $san_array = array(); foreach ($input->get->forme_options as $forma) { $san = $sanitizer->selectorValue($forma); $san_array[] = $san; $selector .= "forma_prodotto.title=$san, "; } $input->whitelist('forme_options', $san_array); } My Lord, that was hard! (at least for me :)). Thanks! 1 Link to comment Share on other sites More sharing options...
Sergio Posted June 18, 2020 Share Posted June 18, 2020 I'm happy that you found the solution ? Link to comment Share on other sites More sharing options...
3fingers Posted June 18, 2020 Author Share Posted June 18, 2020 1 minute ago, Sergio said: I'm happy that you found the solution ? Thanks Sergio, you've saved my day! 1 Link to comment Share on other sites More sharing options...
Sergio Posted June 18, 2020 Share Posted June 18, 2020 Here's my version: <?php // Cache all topics $template = $templates->get("topics"); $topics_children = $cache->get("all_topics", $template, function($pages) { return $pages->get("/topics/")->children(); }); //Topic1|Topic2 $search_topics = explode("|", $input->whitelist->topic); //Get Topics from cache foreach($topics_children as $topic) { $checked = (is_array($search_topics) && in_array($topic->title, $search_topics)) ? ' checked ' : ''; echo "<label for='{$topic->title}'><input type='checkbox' name='topic[]' $checked value='{$topic->title}' id='{$topic->title}' /> {$topic->title}</label></br>"; } //On my search template if($input->get('topic')) { $value = $sanitizer->selectorValue($input->get('topic')); $selector .= "topics=$value, "; $input->whitelist('topic', $value); } ?> 1 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now