Skip to content

Commit 929f5af

Browse files
Merge pull request #173 from openaustralia/feature/DRY
Feature/dry
2 parents de341cf + a8c63d5 commit 929f5af

4 files changed

Lines changed: 324 additions & 460 deletions

File tree

tests/SearchHighlightTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
use PHPUnit\Framework\TestCase;
4+
5+
require_once __DIR__ . '/../www/includes/easyparliament/search.php';
6+
7+
/**
8+
* Tests for highlighted_html.
9+
*/
10+
class SearchHighlightTest extends TestCase {
11+
12+
public function test_empty_searchterm_returns_escaped_text(): void {
13+
$input = '<script>alert("x")</script> Test';
14+
$result = highlighted_html($input, '');
15+
16+
$this->assertSame('&lt;script&gt;alert(&quot;x&quot;)&lt;/script&gt; Test', $result);
17+
}
18+
19+
public function test_matches_are_highlighted_case_insensitively(): void {
20+
$input = 'Canberra CANBERRA';
21+
$result = highlighted_html($input, 'canberra');
22+
23+
$this->assertSame('<span class="hi">Canberra</span> <span class="hi">CANBERRA</span>', $result);
24+
}
25+
26+
public function test_regex_characters_in_searchterm_are_treated_literally(): void {
27+
$input = '<b>A+B?</b>';
28+
$result = highlighted_html($input, 'A+B?');
29+
30+
$this->assertSame('&lt;b&gt;<span class="hi">A+B?</span>&lt;/b&gt;', $result);
31+
}
32+
33+
public function test_no_match_returns_escaped_text_without_highlight(): void {
34+
$input = 'Parliament House';
35+
$result = highlighted_html($input, 'senate');
36+
37+
$this->assertSame('Parliament House', $result);
38+
}
39+
40+
}

www/docs/search/index.php

Lines changed: 2 additions & 228 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
include_once __DIR__ . '/../../includes/easyparliament/init.php';
44
include_once __DIR__ . '/../../includes/easyparliament/member.php';
55
include_once __DIR__ . '/../../includes/easyparliament/glossary.php';
6+
include_once __DIR__ . '/../../includes/easyparliament/search.php';
67

78
// From http://cvs.sourceforge.net/viewcvs.py/publicwhip/publicwhip/website/
89
include_once __DIR__ . '/../../includes/postcode.php';
@@ -100,7 +101,7 @@
100101
</th>
101102
<th>Date range</th>
102103
</tr>
103-
<?
104+
<?php
104105
foreach ($data['speakers'] as $pid => $speaker) {
105106
print '<tr><td align="center">';
106107
print $speaker['count'] . '</td><td>';
@@ -198,230 +199,3 @@
198199
]
199200
]);
200201
$PAGE->page_end();
201-
202-
function find_comments($args){
203-
$commentlist = new COMMENTLIST;
204-
$commentlist->display('search', $args);
205-
}
206-
207-
function find_constituency($args){
208-
// We see if the user is searching for a postcode or constituency.
209-
global $PAGE;
210-
$db = getParlDB();
211-
212-
if ($args['s'] != '') {
213-
$searchterm = $args['s'];
214-
} else {
215-
$PAGE->error_message('No search string');
216-
return false;
217-
}
218-
219-
$constituencies = [];
220-
$constituency = '';
221-
$validpostcode = false;
222-
223-
if (validate_postcode($searchterm)) {
224-
// Looks like a postcode - can we find the constituency?
225-
$constituencies = postcode_to_constituency($searchterm);
226-
if ($constituencies == '') {
227-
$constituencies = [];
228-
} else {
229-
$validpostcode = true;
230-
}
231-
if (!is_array($constituencies)) {
232-
$constituencies = [$constituencies];
233-
}
234-
}
235-
236-
if ($constituencies == [] && $searchterm) {
237-
// No luck so far - let's see if they're searching for a constituency.
238-
$try = strtolower($searchterm);
239-
if (normalise_constituency_name($try)) {
240-
$constituency = normalise_constituency_name($try);
241-
} else {
242-
$q = $db->query("SELECT DISTINCT
243-
(SELECT name FROM constituency WHERE cons_id = o.cons_id AND main_name) AS name
244-
FROM constituency AS o WHERE name LIKE ?
245-
AND from_date <= DATE(NOW()) AND DATE(NOW()) <= to_date",
246-
"%$try%"
247-
);
248-
for ($n = 0; $n < $q->rows(); $n++) {
249-
$constituencies[] = $q->field($n, 'name');
250-
}
251-
}
252-
}
253-
254-
if (count($constituencies) == 1) {
255-
$constituency = $constituencies[0];
256-
}
257-
258-
if ($constituency != '') {
259-
// Got a match, display....
260-
261-
$MEMBER = new MEMBER(['constituency' => $constituency]);
262-
$URL = new URL('mp');
263-
if ($MEMBER->valid) {
264-
$URL->insert(['m' => $MEMBER->member_id()]);
265-
print '<h3>MP for ' . preg_replace("#$searchterm#i", '<span class="hi">$0</span>', $constituency);
266-
if ($validpostcode) {
267-
// Display the postcode the user searched for.
268-
print ' (' . htmlentities(strtoupper($args['s'])) . ')';
269-
}
270-
print "</h2>";
271-
print "<p><a href=\"" . $URL->generate() . "\"><strong>" . htmlentities($MEMBER->first_name()) . ' ' . htmlentities($MEMBER->last_name()) . "</strong></a>
272-
(" . htmlentities($MEMBER->party()) . ")</p>";
273-
}
274-
275-
} elseif (count($constituencies)) {
276-
print "<h3>MPs in constituencies matching '" . htmlentities($searchterm) . "'</h3><ul>";
277-
foreach ($constituencies as $constituency) {
278-
$MEMBER = new MEMBER(['constituency' => $constituency]);
279-
$URL = new URL('mp');
280-
if ($MEMBER->valid) {
281-
$URL->insert(['m' => $MEMBER->member_id()]);
282-
}
283-
print '<li><a href="' . $URL->generate() . '"><strong>' . htmlentities($MEMBER->first_name()) . ' ' . htmlentities($MEMBER->last_name()) . '</strong></a>';
284-
print '(' . preg_replace("#$searchterm#i", '<span class="hi">$0</span>', $constituency) . ', ' . htmlentities($MEMBER->party()) . ')</li>';
285-
}
286-
print '</ul>';
287-
}
288-
}
289-
290-
function find_members($args){
291-
// Maybe there'll be a better place to put this at some point...
292-
global $PAGE, $parties;
293-
$db = getParlDB();
294-
295-
296-
297-
if ($args['s'] != '') {
298-
// $args['s'] should have been tidied up by the time we get here.
299-
// eg, by doing filter_user_input($s, 'strict');
300-
$searchstring = $args['s'];
301-
} else {
302-
$PAGE->error_message("No search string");
303-
return false;
304-
}
305-
306-
$searchwords = explode(' ', preg_replace('#[^a-z ]#i', '', $searchstring));
307-
foreach ($searchwords as $i => $searchword) {
308-
$searchwords[$i] = htmlentities($searchword);
309-
if (!strcasecmp($searchword, 'Opik'))
310-
$searchwords[$i] = '&Ouml;pik';
311-
}
312-
313-
$params = [];
314-
if (count($searchwords) == 1) {
315-
$where = "first_name LIKE ? OR last_name LIKE ?";
316-
$params = ["%$searchwords[0]%", "%$searchwords[0]%"];
317-
} elseif (count($searchwords) == 2) {
318-
// We don't do anything special if there are more than two search words.
319-
// And here we're assuming the user's put the names in the right order.
320-
$where = "(first_name LIKE ? AND last_name LIKE ?)";
321-
$where .= " OR (first_name LIKE ? AND last_name LIKE ?)";
322-
$params = [
323-
"%$searchwords[0]%",
324-
"%$searchwords[1]%",
325-
"%$searchwords[1]%",
326-
"%$searchwords[0]%",
327-
];
328-
} else {
329-
$where = "(first_name LIKE ? AND last_name LIKE ?)";
330-
$where .= " OR (first_name LIKE ? AND last_name LIKE ?)";
331-
$params = [
332-
"%$searchwords[0] $searchwords[1]%",
333-
"%$searchwords[2]%",
334-
"%$searchwords[0]%",
335-
"%$searchwords[1] $searchwords[2]%",
336-
];
337-
}
338-
$q = $db->query("SELECT person_id,
339-
title, first_name, last_name,
340-
constituency, party,
341-
left_house, house
342-
FROM member
343-
WHERE ($where)
344-
ORDER BY last_name, first_name, person_id, entered_house desc
345-
", ...$params);
346-
347-
if ($q->rows() > 0) {
348-
349-
$URL1 = new URL('mp');
350-
$URL2 = new URL('peer');
351-
$members = [];
352-
353-
$last_pid = -1;
354-
for ($n = 0; $n < $q->rows(); $n++) {
355-
if ($q->field($n, 'person_id') != $last_pid) {
356-
$last_pid = $q->field($n, 'person_id');
357-
if ($q->field($n, 'left_house') != '9999-12-31') {
358-
$former = 'formerly ';
359-
} else {
360-
$former = '';
361-
}
362-
if ($q->field($n, 'house') == 1) {
363-
$URL1->insert(array('pid' => $last_pid));
364-
$s = '<a href="' . $URL1->generate() . '"><strong>';
365-
$s .= $q->field($n, 'first_name') . ' ' . $q->field($n, 'last_name') . '</strong></a> (' . $former . $q->field($n, 'constituency') . ', ';
366-
} else {
367-
$URL2->insert(array('pid' => $last_pid));
368-
$s = '<a href="' . $URL2->generate() . '"><strong>';
369-
$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'));
370-
$s .= '</strong></a> (';
371-
}
372-
$party = $q->field($n, 'party');
373-
if (isset($parties[$party]))
374-
$party = $parties[$party];
375-
$s .= $party . ')';
376-
$MOREURL = new URL('search');
377-
$MOREURL->insert(array('pid' => $last_pid, 'pop' => 1, 's' => null));
378-
$s .= ' - <a href="' . $MOREURL->generate() . '">View recent appearances</a>';
379-
$members[] = $s;
380-
}
381-
}
382-
?>
383-
<div id="people_results">
384-
<h3>Representatives matching '<?php echo htmlentities($searchstring); ?>'</h3>
385-
<ul>
386-
<li><?php print implode("</li>\n\t<li>", $members); ?></li>
387-
</ul>
388-
</div>
389-
<?php
390-
}
391-
392-
// We don't display anything if there were no matches.
393-
394-
}
395-
396-
// Checks to see if the search term provided has any similar matching entries in the glossary.
397-
// If it does, show links off to them.
398-
function find_glossary_items($args){
399-
400-
$searchterm = $args['s'];
401-
$GLOSSARY = new GLOSSARY($args);
402-
403-
if (isset($GLOSSARY->num_search_matches) && $GLOSSARY->num_search_matches >= 1) {
404-
405-
// Got a match(es), display....
406-
$URL = new URL('glossary');
407-
$URL->insert(['gl' => ""]);
408-
?>
409-
<h3>Matching glossary terms:</h3>
410-
<p>
411-
<?php
412-
$n = 1;
413-
foreach ($GLOSSARY->search_matches as $glossary_id => $term) {
414-
$URL->update(['gl' => $glossary_id]);
415-
?><a
416-
href="<?php echo $URL->generate(); ?>"><strong><?php echo htmlentities($term['title']); ?></strong></a>
417-
<?php
418-
if ($n < $GLOSSARY->num_search_matches) {
419-
print ", ";
420-
}
421-
$n++;
422-
}
423-
?>
424-
</p>
425-
<?php
426-
}
427-
}

0 commit comments

Comments
 (0)