Skip to content
40 changes: 40 additions & 0 deletions tests/SearchHighlightTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

use PHPUnit\Framework\TestCase;

require_once __DIR__ . '/../www/includes/easyparliament/search.php';

/**
* Tests for highlighted_html.
*/
class SearchHighlightTest extends TestCase {

public function test_empty_searchterm_returns_escaped_text(): void {
$input = '<script>alert("x")</script> Test';
$result = highlighted_html($input, '');

$this->assertSame('&lt;script&gt;alert(&quot;x&quot;)&lt;/script&gt; Test', $result);
}

public function test_matches_are_highlighted_case_insensitively(): void {
$input = 'Canberra CANBERRA';
$result = highlighted_html($input, 'canberra');

$this->assertSame('<span class="hi">Canberra</span> <span class="hi">CANBERRA</span>', $result);
}

public function test_regex_characters_in_searchterm_are_treated_literally(): void {
$input = '<b>A+B?</b>';
$result = highlighted_html($input, 'A+B?');

$this->assertSame('&lt;b&gt;<span class="hi">A+B?</span>&lt;/b&gt;', $result);
}

public function test_no_match_returns_escaped_text_without_highlight(): void {
$input = 'Parliament House';
$result = highlighted_html($input, 'senate');

$this->assertSame('Parliament House', $result);
}

}
230 changes: 2 additions & 228 deletions www/docs/search/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
include_once __DIR__ . '/../../includes/easyparliament/init.php';
include_once __DIR__ . '/../../includes/easyparliament/member.php';
include_once __DIR__ . '/../../includes/easyparliament/glossary.php';
include_once __DIR__ . '/../../includes/easyparliament/search.php';

// From http://cvs.sourceforge.net/viewcvs.py/publicwhip/publicwhip/website/
include_once __DIR__ . '/../../includes/postcode.php';
Expand Down Expand Up @@ -100,7 +101,7 @@
</th>
<th>Date range</th>
</tr>
<?
<?php
foreach ($data['speakers'] as $pid => $speaker) {
print '<tr><td align="center">';
print $speaker['count'] . '</td><td>';
Expand Down Expand Up @@ -198,230 +199,3 @@
]
]);
$PAGE->page_end();

function find_comments($args){
$commentlist = new COMMENTLIST;
$commentlist->display('search', $args);
}

function find_constituency($args){
// We see if the user is searching for a postcode or constituency.
global $PAGE;
$db = getParlDB();

if ($args['s'] != '') {
$searchterm = $args['s'];
} else {
$PAGE->error_message('No search string');
return false;
}

$constituencies = [];
$constituency = '';
$validpostcode = false;

if (validate_postcode($searchterm)) {
// Looks like a postcode - can we find the constituency?
$constituencies = postcode_to_constituency($searchterm);
if ($constituencies == '') {
$constituencies = [];
} else {
$validpostcode = true;
}
if (!is_array($constituencies)) {
$constituencies = [$constituencies];
}
}

if ($constituencies == [] && $searchterm) {
// No luck so far - let's see if they're searching for a constituency.
$try = strtolower($searchterm);
if (normalise_constituency_name($try)) {
$constituency = normalise_constituency_name($try);
} else {
$q = $db->query("SELECT DISTINCT
(SELECT name FROM constituency WHERE cons_id = o.cons_id AND main_name) AS name
FROM constituency AS o WHERE name LIKE ?
AND from_date <= DATE(NOW()) AND DATE(NOW()) <= to_date",
"%$try%"
);
for ($n = 0; $n < $q->rows(); $n++) {
$constituencies[] = $q->field($n, 'name');
}
}
}

if (count($constituencies) == 1) {
$constituency = $constituencies[0];
}

if ($constituency != '') {
// Got a match, display....

$MEMBER = new MEMBER(['constituency' => $constituency]);
$URL = new URL('mp');
if ($MEMBER->valid) {
$URL->insert(['m' => $MEMBER->member_id()]);
print '<h3>MP for ' . preg_replace("#$searchterm#i", '<span class="hi">$0</span>', $constituency);
if ($validpostcode) {
// Display the postcode the user searched for.
print ' (' . htmlentities(strtoupper($args['s'])) . ')';
}
print "</h2>";
print "<p><a href=\"" . $URL->generate() . "\"><strong>" . htmlentities($MEMBER->first_name()) . ' ' . htmlentities($MEMBER->last_name()) . "</strong></a>
(" . htmlentities($MEMBER->party()) . ")</p>";
}

} elseif (count($constituencies)) {
print "<h3>MPs in constituencies matching '" . htmlentities($searchterm) . "'</h3><ul>";
foreach ($constituencies as $constituency) {
$MEMBER = new MEMBER(['constituency' => $constituency]);
$URL = new URL('mp');
if ($MEMBER->valid) {
$URL->insert(['m' => $MEMBER->member_id()]);
}
print '<li><a href="' . $URL->generate() . '"><strong>' . htmlentities($MEMBER->first_name()) . ' ' . htmlentities($MEMBER->last_name()) . '</strong></a>';
print '(' . preg_replace("#$searchterm#i", '<span class="hi">$0</span>', $constituency) . ', ' . htmlentities($MEMBER->party()) . ')</li>';
}
print '</ul>';
}
}

function find_members($args){
// Maybe there'll be a better place to put this at some point...
global $PAGE, $parties;
$db = getParlDB();



if ($args['s'] != '') {
// $args['s'] should have been tidied up by the time we get here.
// eg, by doing filter_user_input($s, 'strict');
$searchstring = $args['s'];
} else {
$PAGE->error_message("No search string");
return false;
}

$searchwords = explode(' ', preg_replace('#[^a-z ]#i', '', $searchstring));
foreach ($searchwords as $i => $searchword) {
$searchwords[$i] = htmlentities($searchword);
if (!strcasecmp($searchword, 'Opik'))
$searchwords[$i] = '&Ouml;pik';
}

$params = [];
if (count($searchwords) == 1) {
$where = "first_name LIKE ? OR last_name LIKE ?";
$params = ["%$searchwords[0]%", "%$searchwords[0]%"];
} elseif (count($searchwords) == 2) {
// We don't do anything special if there are more than two search words.
// And here we're assuming the user's put the names in the right order.
$where = "(first_name LIKE ? AND last_name LIKE ?)";
$where .= " OR (first_name LIKE ? AND last_name LIKE ?)";
$params = [
"%$searchwords[0]%",
"%$searchwords[1]%",
"%$searchwords[1]%",
"%$searchwords[0]%",
];
} else {
$where = "(first_name LIKE ? AND last_name LIKE ?)";
$where .= " OR (first_name LIKE ? AND last_name LIKE ?)";
$params = [
"%$searchwords[0] $searchwords[1]%",
"%$searchwords[2]%",
"%$searchwords[0]%",
"%$searchwords[1] $searchwords[2]%",
];
}
$q = $db->query("SELECT person_id,
title, first_name, last_name,
constituency, party,
left_house, house
FROM member
WHERE ($where)
ORDER BY last_name, first_name, person_id, entered_house desc
", ...$params);

if ($q->rows() > 0) {

$URL1 = new URL('mp');
$URL2 = new URL('peer');
$members = [];

$last_pid = -1;
for ($n = 0; $n < $q->rows(); $n++) {
if ($q->field($n, 'person_id') != $last_pid) {
$last_pid = $q->field($n, 'person_id');
if ($q->field($n, 'left_house') != '9999-12-31') {
$former = 'formerly ';
} else {
$former = '';
}
if ($q->field($n, 'house') == 1) {
$URL1->insert(array('pid' => $last_pid));
$s = '<a href="' . $URL1->generate() . '"><strong>';
$s .= $q->field($n, 'first_name') . ' ' . $q->field($n, 'last_name') . '</strong></a> (' . $former . $q->field($n, 'constituency') . ', ';
} else {
$URL2->insert(array('pid' => $last_pid));
$s = '<a href="' . $URL2->generate() . '"><strong>';
$s .= member_full_name($q->field($n, 'house'), $q->field($n, 'title'), $q->field($n, 'first_name'), $q->field($n, 'last_name'), $q->field($n, 'constituency'));
$s .= '</strong></a> (';
}
$party = $q->field($n, 'party');
if (isset($parties[$party]))
$party = $parties[$party];
$s .= $party . ')';
$MOREURL = new URL('search');
$MOREURL->insert(array('pid' => $last_pid, 'pop' => 1, 's' => null));
$s .= ' - <a href="' . $MOREURL->generate() . '">View recent appearances</a>';
$members[] = $s;
}
}
?>
<div id="people_results">
<h3>Representatives matching '<?php echo htmlentities($searchstring); ?>'</h3>
<ul>
<li><?php print implode("</li>\n\t<li>", $members); ?></li>
</ul>
</div>
<?php
}

// We don't display anything if there were no matches.

}

// Checks to see if the search term provided has any similar matching entries in the glossary.
// If it does, show links off to them.
function find_glossary_items($args){

$searchterm = $args['s'];
$GLOSSARY = new GLOSSARY($args);

if (isset($GLOSSARY->num_search_matches) && $GLOSSARY->num_search_matches >= 1) {

// Got a match(es), display....
$URL = new URL('glossary');
$URL->insert(['gl' => ""]);
?>
<h3>Matching glossary terms:</h3>
<p>
<?php
$n = 1;
foreach ($GLOSSARY->search_matches as $glossary_id => $term) {
$URL->update(['gl' => $glossary_id]);
?><a
href="<?php echo $URL->generate(); ?>"><strong><?php echo htmlentities($term['title']); ?></strong></a>
<?php
if ($n < $GLOSSARY->num_search_matches) {
print ", ";
}
$n++;
}
?>
</p>
<?php
}
}
Loading
Loading