Jump to content

[SOLVED] Lost query on search pages


3fingers
 Share

Recommended Posts

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

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 ?

  • Like 4
Link to comment
Share on other sites

@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.

  • Like 2
Link to comment
Share on other sites

@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

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>&hellip;</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

11 minutes ago, Sergio said:

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

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

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:

 

  • Like 1
Link to comment
Share on other sites

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!

  • Like 1
Link to comment
Share on other sites

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); 
}
?>

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...