|
1
|
|
|
<?php |
|
|
|
|
|
|
2
|
|
|
|
|
3
|
|
|
/* |
|
4
|
|
|
General utility functions v1.1 (well, it was). |
|
5
|
|
|
|
|
6
|
|
|
*/ |
|
7
|
|
|
|
|
8
|
|
|
include_once INCLUDESPATH . '../../commonlib/phplib/email.php'; |
|
|
|
|
|
|
9
|
|
|
include_once INCLUDESPATH . '../../commonlib/phplib/datetime.php'; |
|
10
|
|
|
|
|
11
|
|
|
# Pass it a brief header word and some debug text and it'll be output. |
|
12
|
|
|
# If TEXT is an array, call the user function, assuming it's a class. |
|
13
|
|
|
function twfy_debug($header, $text="") { |
|
14
|
|
|
|
|
15
|
|
|
// We set ?DEBUGTAG=n in the URL. |
|
16
|
|
|
// (DEBUGTAG is set in config.php). |
|
17
|
|
|
// n is a number from (currently) 1 to 4. |
|
18
|
|
|
// This sets what amount of debug information is shown. |
|
19
|
|
|
// For level '1' we show anything that is passed to this function |
|
20
|
|
|
// with a $header in $levels[1]. |
|
|
|
|
|
|
21
|
|
|
// For level '2', anything with a $header in $levels[1] AND $levels[2]. |
|
|
|
|
|
|
22
|
|
|
// Level '4' shows everything. |
|
23
|
|
|
|
|
24
|
74 |
|
$debug_level = get_http_var(DEBUGTAG); |
|
|
|
|
|
|
25
|
|
|
#$debug_level = 1; |
|
|
|
|
|
|
26
|
|
|
|
|
27
|
74 |
|
if ($debug_level != '') { |
|
28
|
|
|
|
|
29
|
|
|
// Set which level shows which types of debug info. |
|
30
|
|
|
$levels = array ( |
|
31
|
|
|
1 => array ('THEUSER', 'TIME', 'SQLERROR', 'PAGE', 'TEMPLATE', 'SEARCH', 'ALERTS', 'MP'), |
|
32
|
|
|
2 => array ('SQL', 'EMAIL', 'WIKIPEDIA', 'hansardlist', 'debatelist', 'wranslist', 'whalllist'), |
|
33
|
|
|
3 => array ('SQLRESULT') |
|
34
|
|
|
// Higher than this: 'DATA', etc. |
|
35
|
|
|
); |
|
36
|
|
|
|
|
37
|
|
|
// Store which headers we are allowed to show. |
|
38
|
|
|
$allowed_headers = array(); |
|
39
|
|
|
|
|
40
|
|
|
if ($debug_level > count($levels)) { |
|
41
|
|
|
$max_level_to_show = count($levels); |
|
42
|
|
|
} else { |
|
43
|
|
|
$max_level_to_show = $debug_level; |
|
44
|
|
|
} |
|
45
|
|
|
|
|
46
|
|
|
for ($n = 1; $n <= $max_level_to_show; $n++) { |
|
47
|
|
|
$allowed_headers = array_merge ($allowed_headers, $levels[$n] ); |
|
48
|
|
|
} |
|
49
|
|
|
|
|
50
|
|
|
// If we can show this header, then, er, show it. |
|
51
|
|
|
if ( in_array($header, $allowed_headers) || $debug_level >= 4) { |
|
52
|
|
|
if (is_array($text)) $text = call_user_func($text); |
|
53
|
|
|
print "<p><span style=\"color:#039;\"><strong>$header</strong></span> $text</p>\n"; |
|
54
|
|
|
} |
|
55
|
|
|
} |
|
56
|
74 |
|
} |
|
57
|
|
|
|
|
58
|
|
|
function exception_handler($e) { |
|
59
|
|
|
trigger_error($e->getMessage(), E_USER_ERROR); |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
function error_handler($errno, $errmsg, $filename, $linenum, $vars) { |
|
|
|
|
|
|
63
|
|
|
// Custom error-handling function. |
|
64
|
|
|
// Sends an email to BUGSLIST. |
|
65
|
|
|
global $PAGE; |
|
|
|
|
|
|
66
|
|
|
|
|
67
|
|
|
# Ignore errors we've asked to ignore |
|
68
|
|
|
if (error_reporting()==0) return; |
|
69
|
|
|
|
|
70
|
|
|
// define an assoc array of error string |
|
71
|
|
|
// in reality the only entries we should |
|
72
|
|
|
// consider are E_WARNING, E_NOTICE, E_USER_ERROR, |
|
73
|
|
|
// E_USER_WARNING and E_USER_NOTICE |
|
74
|
|
|
# Commented out are ones that a user function cannot handle. |
|
75
|
|
|
$errortype = array ( |
|
76
|
|
|
#E_ERROR => "Error", |
|
|
|
|
|
|
77
|
|
|
E_WARNING => "Warning", |
|
78
|
|
|
#E_PARSE => "Parsing Error", |
|
|
|
|
|
|
79
|
|
|
E_NOTICE => "Notice", |
|
80
|
|
|
#E_CORE_ERROR => "Core Error", |
|
|
|
|
|
|
81
|
|
|
#E_CORE_WARNING => "Core Warning", |
|
|
|
|
|
|
82
|
|
|
#E_COMPILE_ERROR => "Compile Error", |
|
|
|
|
|
|
83
|
|
|
#E_COMPILE_WARNING => "Compile Warning", |
|
|
|
|
|
|
84
|
|
|
E_USER_ERROR => "User Error", |
|
85
|
|
|
E_USER_WARNING => "User Warning", |
|
86
|
|
|
E_USER_NOTICE => "User Notice", |
|
87
|
|
|
E_STRICT => "Runtime Notice", |
|
88
|
|
|
# 5.3 introduced E_DEPRECATED |
|
89
|
|
|
8192 => 'Deprecated', |
|
90
|
|
|
); |
|
91
|
|
|
|
|
92
|
|
|
$err = ''; |
|
93
|
|
|
if (isset($_SERVER['REQUEST_URI'])) { |
|
94
|
|
|
$err .= "URL:\t\thttps://" . DOMAIN . $_SERVER['REQUEST_URI'] . "\n"; |
|
|
|
|
|
|
95
|
|
|
} else { |
|
96
|
|
|
$err .= "URL:\t\tNone - running from command line?\n"; |
|
97
|
|
|
} |
|
98
|
|
|
if (isset($_SERVER['HTTP_REFERER'])) { |
|
99
|
|
|
$err .= "Referer:\t" . $_SERVER['HTTP_REFERER'] . "\n"; |
|
100
|
|
|
} else { |
|
101
|
|
|
$err .= "Referer:\tNone\n"; |
|
102
|
|
|
} |
|
103
|
|
|
if (isset($_SERVER['HTTP_USER_AGENT'])) { |
|
104
|
|
|
$err .= "User-Agent:\t" . $_SERVER['HTTP_USER_AGENT'] . "\n"; |
|
105
|
|
|
} else { |
|
106
|
|
|
$err .= "User-Agent:\tNone\n"; |
|
107
|
|
|
} |
|
108
|
|
|
$err .= "Number:\t\t$errno\n"; |
|
109
|
|
|
$err .= "Type:\t\t" . $errortype[$errno] . "\n"; |
|
110
|
|
|
$err .= "Message:\t$errmsg\n"; |
|
111
|
|
|
$err .= "File:\t\t$filename\n"; |
|
112
|
|
|
$err .= "Line:\t\t$linenum\n"; |
|
113
|
|
|
if (count($_POST)) { |
|
114
|
|
|
$err .= "_POST:"; |
|
115
|
|
|
foreach ($_POST as $k => $v) { |
|
116
|
|
|
$err .= "\t\t$k => $v\n"; |
|
117
|
|
|
} |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
// I'm not sure this bit is actually any use! |
|
121
|
|
|
|
|
122
|
|
|
// set of errors for which a var trace will be saved. |
|
123
|
|
|
// $user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE); |
|
124
|
|
|
// if (in_array($errno, $user_errors)) { |
|
125
|
|
|
// $err .= "Variables:\t" . serialize($vars) . "\n"; |
|
126
|
|
|
// } |
|
127
|
|
|
|
|
128
|
|
|
|
|
129
|
|
|
// Add the problematic line if possible. |
|
130
|
|
|
if (is_readable($filename)) { |
|
131
|
|
|
$source = file($filename); |
|
132
|
|
|
$err .= "\nSource:\n\n"; |
|
133
|
|
|
// Show the line, plus prev and next, with line numbers. |
|
134
|
|
|
$err .= $linenum-2 . " " . $source[$linenum-3]; |
|
135
|
|
|
$err .= $linenum-1 . " " . $source[$linenum-2]; |
|
136
|
|
|
$err .= $linenum . " " . $source[$linenum-1]; |
|
137
|
|
|
$err .= $linenum+1 . " " . $source[$linenum]; |
|
138
|
|
|
$err .= $linenum+2 . " " . $source[$linenum+1]; |
|
139
|
|
|
} |
|
140
|
|
|
|
|
141
|
|
|
|
|
142
|
|
|
// Will we need to exit after this error? |
|
143
|
|
|
$fatal_errors = array(E_ERROR, E_USER_ERROR); |
|
144
|
|
|
if (in_array($errno, $fatal_errors)) { |
|
145
|
|
|
$fatal = true; |
|
146
|
|
|
} else { |
|
147
|
|
|
$fatal = false; |
|
148
|
|
|
} |
|
149
|
|
|
|
|
150
|
|
|
// Finally, display errors and stuff... |
|
151
|
|
|
|
|
152
|
|
|
if (DEVSITE || get_http_var(DEBUGTAG)) { |
|
|
|
|
|
|
153
|
|
|
// On a devsite we just display the problem. |
|
154
|
|
|
$errtxt = nl2br($err) . "\n"; |
|
155
|
|
|
if (!strstr($errmsg, 'mysql_connect')) { |
|
156
|
|
|
$errtxt .= "<br><br>Backtrace:<br>" . nl2br(adodb_backtrace(false)); |
|
157
|
|
|
} |
|
158
|
|
|
$message = array( |
|
159
|
|
|
'title' => "Error", |
|
160
|
|
|
'text' => $errtxt |
|
161
|
|
|
); |
|
162
|
|
|
if (is_object($PAGE)) { |
|
163
|
|
|
$PAGE->error_message($message, $fatal); |
|
164
|
|
|
} else { |
|
165
|
|
|
vardump($message); |
|
166
|
|
|
} |
|
167
|
|
|
|
|
168
|
|
|
} else { |
|
169
|
|
|
// On live sites we display a nice message and email the problem. |
|
170
|
|
|
|
|
171
|
|
|
$message = array( |
|
172
|
|
|
'title' => "Sorry, an error has occurred", |
|
173
|
|
|
'text' => "We've been notified by email and will try to fix the problem soon!" |
|
174
|
|
|
); |
|
175
|
|
|
|
|
176
|
|
|
if (is_object($PAGE)) { |
|
177
|
|
|
$PAGE->error_message($message, $fatal); |
|
178
|
|
|
} else { |
|
179
|
|
|
header('HTTP/1.0 500 Internal Server Error'); |
|
180
|
|
|
print "<p>Oops, sorry, an error has occurred!</p>\n"; |
|
181
|
|
|
} |
|
182
|
|
|
if (!($errno & E_USER_NOTICE) && strpos($errmsg, 'pg_connect')===false && strpos($errmsg, 'mysql_connect')===false) { |
|
183
|
|
|
mail(BUGSLIST, "[TWFYBUG]: $errmsg", $err, "From: Bug <" . CONTACTEMAIL . ">\n". "X-Mailer: PHP/" . phpversion() ); |
|
|
|
|
|
|
184
|
|
|
} |
|
185
|
|
|
} |
|
186
|
|
|
|
|
187
|
|
|
// Do we need to exit? |
|
188
|
|
|
if ($fatal) { |
|
189
|
|
|
exit(1); |
|
|
|
|
|
|
190
|
|
|
} |
|
191
|
|
|
} |
|
192
|
|
|
|
|
193
|
|
|
// Replacement for var_dump() |
|
|
|
|
|
|
194
|
|
|
function vardump($blah) { |
|
195
|
|
|
print "<pre>\n"; |
|
196
|
|
|
var_dump($blah); |
|
|
|
|
|
|
197
|
|
|
print "</pre>\n"; |
|
198
|
|
|
} |
|
199
|
|
|
|
|
200
|
|
|
// pretty prints the backtrace, copied from http://uk.php.net/manual/en/function.debug-backtrace.php |
|
201
|
|
|
function adodb_backtrace($print=true) |
|
202
|
|
|
{ |
|
203
|
|
|
$s = ''; |
|
204
|
|
|
if (PHPVERSION() >= 4.3) { |
|
205
|
|
|
|
|
206
|
|
|
$MAXSTRLEN = 64; |
|
207
|
|
|
|
|
208
|
|
|
$traceArr = debug_backtrace(); |
|
209
|
|
|
array_shift($traceArr); |
|
210
|
|
|
$tabs = sizeof($traceArr)-1; |
|
211
|
|
|
foreach ($traceArr as $arr) { |
|
212
|
|
|
for ($i=0; $i < $tabs; $i++) $s .= ' '; |
|
213
|
|
|
$tabs -= 1; |
|
214
|
|
|
if (isset($arr['class'])) $s .= $arr['class'].'.'; |
|
215
|
|
|
$args = array(); |
|
216
|
|
|
if (isset($arr['args'])) foreach ($arr['args'] as $v) { |
|
217
|
|
|
if (is_null($v)) $args[] = 'null'; |
|
218
|
|
|
elseif (is_array($v)) $args[] = 'Array['.sizeof($v).']'; |
|
219
|
|
|
elseif (is_object($v)) $args[] = 'Object:'.get_class($v); |
|
220
|
|
|
elseif (is_bool($v)) $args[] = $v ? 'true' : 'false'; |
|
221
|
|
|
else { |
|
222
|
|
|
$v = (string) @$v; |
|
223
|
|
|
$str = _htmlspecialchars(substr($v,0,$MAXSTRLEN)); |
|
224
|
|
|
if (strlen($v) > $MAXSTRLEN) $str .= '...'; |
|
225
|
|
|
$args[] = $str; |
|
226
|
|
|
} |
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
|
$s .= $arr['function'].'('.implode(', ',$args).')'; |
|
230
|
|
|
// $s .= sprintf("</font><font color=#808080 size=-1> # line %4d,". |
|
231
|
|
|
// " file: <a href=\"file:/%s\">%s</a></font>", |
|
|
|
|
|
|
232
|
|
|
// $arr['line'],$arr['file'],$arr['file']); |
|
|
|
|
|
|
233
|
|
|
$s .= "\n"; |
|
234
|
|
|
} |
|
235
|
|
|
if ($print) print $s; |
|
236
|
|
|
} |
|
237
|
|
|
|
|
238
|
|
|
return $s; |
|
239
|
|
|
} |
|
240
|
|
|
|
|
241
|
|
|
// Far from foolproof, but better than nothing. |
|
242
|
|
|
function validate_email($string) { |
|
243
|
|
|
if (!preg_match('/^[-!#$%&\'*+\\.\/0-9=?A-Z^_`a-z{|}~]+'. |
|
244
|
|
|
'@'. |
|
245
|
|
|
'[-!#$%&\'*.\\+\/0-9=?A-Z^_`a-z{|}~]+\.'. |
|
246
|
|
|
'[-!#$%&\'*+\\.\/0-9=?A-Z^_`a-z{|}~]+$/', $string)) { |
|
247
|
|
|
return false; |
|
248
|
|
|
} else { |
|
249
|
|
|
return true; |
|
250
|
|
|
} |
|
251
|
|
|
} |
|
252
|
|
|
|
|
253
|
|
|
function validate_postcode($postcode) { |
|
254
|
|
|
// See http://www.govtalk.gov.uk/gdsc/html/noframes/PostCode-2-1-Release.htm |
|
255
|
|
|
|
|
256
|
4 |
|
$postcode = trim($postcode); |
|
257
|
|
|
|
|
258
|
4 |
|
$in = 'ABDEFGHJLNPQRSTUWXYZ'; |
|
259
|
4 |
|
$fst = 'ABCDEFGHIJKLMNOPRSTUWYZ'; |
|
260
|
4 |
|
$sec = 'ABCDEFGHJKLMNOPQRSTUVWXY'; |
|
261
|
4 |
|
$thd = 'ABCDEFGHJKSTUW'; |
|
262
|
4 |
|
$fth = 'ABEHMNPRVWXY'; |
|
263
|
4 |
|
$num = '0123456789'; |
|
264
|
4 |
|
$nom = '0123456789'; |
|
265
|
4 |
|
$gap = '\s\.'; |
|
266
|
|
|
|
|
267
|
4 |
|
if ( preg_match("/^[$fst][$num][$gap]*[$nom][$in][$in]$/i", $postcode) || |
|
268
|
4 |
|
preg_match("/^[$fst][$num][$num][$gap]*[$nom][$in][$in]$/i", $postcode) || |
|
269
|
4 |
|
preg_match("/^[$fst][$sec][$num][$gap]*[$nom][$in][$in]$/i", $postcode) || |
|
270
|
4 |
|
preg_match("/^[$fst][$sec][$num][$num][$gap]*[$nom][$in][$in]$/i", $postcode) || |
|
271
|
3 |
|
preg_match("/^[$fst][$num][$thd][$gap]*[$nom][$in][$in]$/i", $postcode) || |
|
272
|
3 |
|
preg_match("/^[$fst][$sec][$num][$fth][$gap]*[$nom][$in][$in]$/i", $postcode) |
|
273
|
4 |
|
) { |
|
274
|
2 |
|
return true; |
|
275
|
|
|
} else { |
|
276
|
2 |
|
return false; |
|
277
|
|
|
} |
|
278
|
|
|
} |
|
279
|
|
|
|
|
280
|
|
|
// Returns the unixtime in microseconds. |
|
281
|
|
|
function getmicrotime() { |
|
282
|
74 |
|
$mtime = microtime(); |
|
283
|
74 |
|
$mtime = explode(" ",$mtime); |
|
284
|
74 |
|
$mtime = $mtime[1] + $mtime[0]; |
|
285
|
|
|
|
|
286
|
74 |
|
return $mtime; |
|
287
|
|
|
} |
|
288
|
|
|
|
|
289
|
|
|
/* twfy_debug_timestamp |
|
290
|
|
|
* Output a timestamp since the page was started. */ |
|
291
|
|
|
$timestamp_last = $timestamp_start = getmicrotime(); |
|
292
|
|
|
function twfy_debug_timestamp($label = "") { |
|
293
|
|
|
global $timestamp_last, $timestamp_start; |
|
|
|
|
|
|
294
|
|
|
$t = getmicrotime(); |
|
295
|
|
|
twfy_debug("TIME", sprintf("%f msecs since start; %f msecs since last; %s", |
|
296
|
|
|
($t - $timestamp_start)*1000.0, ($t - $timestamp_last)*1000.0, $label)); |
|
297
|
|
|
$timestamp_last = $t; |
|
298
|
|
|
} |
|
299
|
|
|
|
|
300
|
|
|
function format_timestamp($timestamp, $format) { |
|
301
|
|
|
// Pass it a MYSQL TIMESTAMP (YYYYMMDDHHMMSS) and a |
|
302
|
|
|
// PHP date format string (eg, "Y-m-d H:i:s") |
|
303
|
|
|
// and it returns a nicely formatted string according to requirements. |
|
304
|
|
|
|
|
305
|
|
|
// Because strtotime can't handle TIMESTAMPS. |
|
306
|
|
|
|
|
307
|
|
|
if (preg_match("/^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/", $timestamp, $matches)) { |
|
308
|
|
|
list($string, $year, $month, $day, $hour, $min, $sec) = $matches; |
|
309
|
|
|
|
|
310
|
|
|
return gmdate ($format, gmmktime($hour, $min, $sec, $month, $day, $year)); |
|
311
|
|
|
} else { |
|
312
|
|
|
return ""; |
|
313
|
|
|
} |
|
314
|
|
|
|
|
315
|
|
|
} |
|
316
|
|
|
|
|
317
|
|
|
|
|
318
|
|
|
$format_date_months = array('', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'); |
|
319
|
|
|
$format_date_months_short = array('', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'); |
|
320
|
|
|
|
|
321
|
|
|
function format_date($date, $format) { |
|
322
|
16 |
|
global $format_date_months, $format_date_months_short; |
|
|
|
|
|
|
323
|
|
|
// Pass it a date (YYYY-MM-DD) and a |
|
324
|
|
|
// PHP date format string (eg, "Y-m-d H:i:s") |
|
325
|
|
|
// and it returns a nicely formatted string according to requirements. |
|
326
|
|
|
|
|
327
|
16 |
|
if (preg_match("/^(\d\d\d\d)-(\d\d?)-(\d\d?)$/", $date, $matches)) { |
|
328
|
16 |
|
list($string, $year, $month, $day) = $matches; |
|
329
|
16 |
|
if ($year < 1902) { # gmdate fns only go back to Dec. 1901 |
|
330
|
|
|
if ($format == SHORTDATEFORMAT) { |
|
331
|
|
|
return ($day+0) . ' ' . $format_date_months_short[$month+0] . " $year"; |
|
332
|
|
|
} else { |
|
333
|
|
|
return ($day+0) . ' ' . $format_date_months[$month+0] . " $year"; |
|
334
|
|
|
} |
|
335
|
|
|
} |
|
336
|
|
|
|
|
337
|
16 |
|
return gmdate ($format, gmmktime(0, 0, 0, $month, $day, $year)); |
|
338
|
|
|
} else { |
|
339
|
|
|
return ""; |
|
340
|
|
|
} |
|
341
|
|
|
|
|
342
|
|
|
} |
|
343
|
|
|
|
|
344
|
|
|
|
|
345
|
|
|
function format_time($time, $format) { |
|
346
|
|
|
// Pass it a time (HH:MM:SS) and a |
|
347
|
|
|
// PHP date format string (eg, "H:i") |
|
348
|
|
|
// and it returns a nicely formatted string according to requirements. |
|
349
|
|
|
|
|
350
|
|
|
if (preg_match("/^(\d\d):(\d\d):(\d\d)$/", $time, $matches)) { |
|
351
|
|
|
list($string, $hour, $min, $sec) = $matches; |
|
352
|
|
|
|
|
353
|
|
|
return gmdate ($format, gmmktime($hour, $min, $sec)); |
|
354
|
|
|
} else { |
|
355
|
|
|
return ""; |
|
356
|
|
|
} |
|
357
|
|
|
} |
|
358
|
|
|
|
|
359
|
|
|
|
|
360
|
|
|
|
|
361
|
|
|
function relative_time($datetime) { |
|
362
|
|
|
// Pass it a 'YYYY-MM-DD HH:MM:SS' and it will return something |
|
363
|
|
|
// like "Two hours ago", "Last week", etc. |
|
|
|
|
|
|
364
|
|
|
|
|
365
|
|
|
// http://maniacalrage.net/projects/relative/ |
|
366
|
|
|
|
|
367
|
|
|
if (!preg_match("/\d\d\d\d-\d\d-\d\d \d\d\:\d\d\:\d\d/", $datetime)) { |
|
368
|
|
|
return ''; |
|
369
|
|
|
} |
|
370
|
|
|
|
|
371
|
|
|
$in_seconds = strtotime($datetime); |
|
372
|
|
|
$now = time(); |
|
373
|
|
|
|
|
374
|
|
|
$diff = $now - $in_seconds; |
|
375
|
|
|
$months = floor($diff/2419200); |
|
376
|
|
|
$diff -= $months * 2419200; |
|
377
|
|
|
$weeks = floor($diff/604800); |
|
378
|
|
|
$diff -= $weeks*604800; |
|
379
|
|
|
$days = floor($diff/86400); |
|
380
|
|
|
$diff -= $days * 86400; |
|
381
|
|
|
$hours = floor($diff/3600); |
|
382
|
|
|
$diff -= $hours * 3600; |
|
383
|
|
|
$minutes = floor($diff/60); |
|
384
|
|
|
$diff -= $minutes * 60; |
|
385
|
|
|
$seconds = $diff; |
|
386
|
|
|
|
|
387
|
|
|
|
|
388
|
|
|
if ($months > 0) { |
|
389
|
|
|
// Over a month old, just show the actual date. |
|
390
|
|
|
$date = substr($datetime, 0, 10); |
|
391
|
|
|
return format_date($date, LONGDATEFORMAT); |
|
392
|
|
|
|
|
393
|
|
|
} else { |
|
394
|
|
|
$relative_date = ''; |
|
395
|
|
|
if ($weeks > 0) { |
|
396
|
|
|
// Weeks and days |
|
397
|
|
|
$relative_date .= ($relative_date?', ':'').$weeks.' week'.($weeks>1?'s':''); |
|
398
|
|
|
$relative_date .= $days>0?($relative_date?', ':'').$days.' day'.($days>1?'s':''):''; |
|
399
|
|
|
} elseif ($days > 0) { |
|
400
|
|
|
// days and hours |
|
401
|
|
|
$relative_date .= ($relative_date?', ':'').$days.' day'.($days>1?'s':''); |
|
402
|
|
|
$relative_date .= $hours>0?($relative_date?', ':'').$hours.' hour'.($hours>1?'s':''):''; |
|
403
|
|
|
} elseif ($hours > 0) { |
|
404
|
|
|
// hours and minutes |
|
405
|
|
|
$relative_date .= ($relative_date?', ':'').$hours.' hour'.($hours>1?'s':''); |
|
406
|
|
|
$relative_date .= $minutes>0?($relative_date?', ':'').$minutes.' minute'.($minutes>1?'s':''):''; |
|
407
|
|
|
} elseif ($minutes > 0) { |
|
408
|
|
|
// minutes only |
|
409
|
|
|
$relative_date .= ($relative_date?', ':'').$minutes.' minute'.($minutes>1?'s':''); |
|
410
|
|
|
} else { |
|
411
|
|
|
// seconds only |
|
412
|
|
|
$relative_date .= ($relative_date?', ':'').$seconds.' second'.($seconds>1?'s':''); |
|
413
|
|
|
} |
|
414
|
|
|
} |
|
415
|
|
|
|
|
416
|
|
|
// Return relative date and add proper verbiage |
|
417
|
|
|
return $relative_date.' ago'; |
|
418
|
|
|
|
|
419
|
|
|
} |
|
420
|
|
|
|
|
421
|
|
|
function parse_date($date) { |
|
422
|
|
|
return datetime_parse_local_date($date, time(), 'en', 'gb'); |
|
423
|
|
|
} |
|
424
|
|
|
|
|
425
|
|
|
/* strip_tags_tospaces TEXT |
|
426
|
|
|
* Return a copy of TEXT in which certain block-level HTML tags have been |
|
427
|
|
|
* replaced by single spaces, and other HTML tags have been removed. */ |
|
428
|
|
|
function strip_tags_tospaces($text) { |
|
429
|
8 |
|
$text = preg_replace("#\<(p|br|div|td|tr|th|table)[^>]*\>#i", " ", $text); |
|
430
|
|
|
|
|
431
|
8 |
|
return strip_tags(trim($text)); |
|
432
|
|
|
} |
|
433
|
|
|
|
|
434
|
|
|
function trim_characters($text, $start, $length, $url_length = 60) { |
|
435
|
|
|
// Pass it a string, a numeric start position and a numeric length. |
|
436
|
|
|
// If the start position is > 0, the string will be trimmed to start at the |
|
437
|
|
|
// nearest word boundary after (or at) that position. |
|
438
|
|
|
// If the string is then longer than $length, it will be trimmed to the nearest |
|
439
|
|
|
// word boundary below (or at) that length. |
|
440
|
|
|
// If either end is trimmed, ellipses will be added. |
|
441
|
|
|
// The modified string is then returned - its *maximum* length is $length. |
|
442
|
|
|
// HTML is always stripped (must be for trimming to prevent broken tags). |
|
443
|
|
|
|
|
444
|
8 |
|
$text = strip_tags_tospaces($text); |
|
445
|
|
|
|
|
446
|
|
|
// Split long strings up so they don't go too long. |
|
447
|
|
|
// Mainly for URLs which are displayed, but aren't links when trimmed. |
|
448
|
8 |
|
$text = preg_replace('/(\S{' . $url_length . '})/', "\$1 ", $text); |
|
449
|
|
|
|
|
450
|
|
|
// Otherwise the word boundary matching goes odd... |
|
451
|
8 |
|
$text = preg_replace("/[\n\r]/", " ", $text); |
|
452
|
|
|
|
|
453
|
|
|
// Trim start. |
|
454
|
8 |
|
if ($start > 0) { |
|
455
|
|
|
$text = substr($text, $start); |
|
456
|
|
|
|
|
457
|
|
|
// Word boundary. |
|
458
|
|
|
if (preg_match ("/.+?\b(.*)/", $text, $matches)) { |
|
459
|
|
|
$text = $matches[1]; |
|
460
|
|
|
// Strip spare space at the start. |
|
461
|
|
|
$text = preg_replace ("/^\s/", '', $text); |
|
462
|
|
|
} |
|
463
|
|
|
$text = '...' . $text; |
|
464
|
|
|
} |
|
465
|
|
|
|
|
466
|
|
|
// Trim end. |
|
467
|
8 |
|
if (strlen($text) > $length) { |
|
468
|
|
|
|
|
469
|
|
|
// Allow space for ellipsis. |
|
470
|
8 |
|
$text = substr($text, 0, $length - 3); |
|
471
|
|
|
|
|
472
|
|
|
// Word boundary. |
|
473
|
8 |
|
if (preg_match ("/(.*)\s.+/", $text, $matches)) { |
|
474
|
8 |
|
$text = $matches[1]; |
|
475
|
|
|
// Strip spare space at the end. |
|
476
|
8 |
|
$text = preg_replace ("/\s$/", '', $text); |
|
477
|
8 |
|
} |
|
478
|
|
|
// We don't want to use the HTML entity for an ellipsis (…), because then |
|
479
|
|
|
// it screws up when we subsequently use htmlentities() to print the returned |
|
480
|
|
|
// string! |
|
481
|
8 |
|
$text .= '...'; |
|
482
|
8 |
|
} |
|
483
|
|
|
|
|
484
|
8 |
|
return $text; |
|
485
|
|
|
} |
|
486
|
|
|
|
|
487
|
|
|
/** |
|
488
|
|
|
* Filters user input to remove unwanted HTML tags etc |
|
489
|
|
|
*/ |
|
490
|
|
|
function filter_user_input($text, $filter_type) { |
|
491
|
|
|
// We use this to filter any major user input, especially comments. |
|
492
|
|
|
// Gets rid of bad HTML, basically. |
|
493
|
|
|
// Uses iamcal.com's lib_filter class. |
|
494
|
|
|
|
|
495
|
|
|
// $filter_type is the level of filtering we want: |
|
496
|
|
|
// 'comment' allows <b> and <i> tags. |
|
497
|
|
|
// 'strict' strips all tags. |
|
498
|
|
|
|
|
499
|
1 |
|
global $filter; |
|
|
|
|
|
|
500
|
|
|
|
|
501
|
1 |
|
$text = trim($text); |
|
502
|
|
|
|
|
503
|
|
|
// Replace 3 or more newlines with just two newlines. |
|
504
|
|
|
//$text = preg_replace("/(\n){3,}/", "\n\n", $text); |
|
|
|
|
|
|
505
|
|
|
|
|
506
|
1 |
|
if ($filter_type == 'strict') { |
|
507
|
|
|
// No tags allowed at all! |
|
508
|
|
|
$filter->allowed = array (); |
|
509
|
|
|
} else { |
|
510
|
|
|
// Comment. |
|
511
|
|
|
// Only allowing <a href>, <b>, <strong>, <i> and <em> |
|
512
|
1 |
|
$filter->allowed = array ( |
|
513
|
1 |
|
'a' => array('href'), |
|
514
|
1 |
|
'strong' => array(), |
|
515
|
1 |
|
'em' => array(), |
|
516
|
1 |
|
'b' => array(), |
|
517
|
1 |
|
'i' => array() |
|
518
|
1 |
|
); |
|
519
|
|
|
// turning this on means that stray angle brackets |
|
520
|
|
|
// are not turned in to tags |
|
521
|
1 |
|
$filter->always_make_tags = 0; |
|
522
|
|
|
} |
|
523
|
|
|
|
|
524
|
1 |
|
$text = $filter->go($text); |
|
525
|
|
|
|
|
526
|
1 |
|
return $text; |
|
527
|
|
|
} |
|
528
|
|
|
|
|
529
|
|
|
function prepare_comment_for_display($text) { |
|
530
|
|
|
// Makes any URLs into HTML links. |
|
531
|
|
|
// Turns \n's into <br> |
|
532
|
|
|
|
|
533
|
|
|
// Encode HTML entities. |
|
534
|
|
|
// Can't do htmlentities() because it'll turn the few tags we allow into < |
|
535
|
|
|
// Must go before the URL stuff. |
|
536
|
3 |
|
$text = htmlentities_notags($text); |
|
537
|
|
|
|
|
538
|
3 |
|
$link_length = 60; |
|
539
|
3 |
|
$text = preg_replace_callback( |
|
540
|
3 |
|
"/(?<!\"|\/)((http(s?):\/\/)|(www\.))([a-zA-Z\d_.+,;:?%~\-\/#='*$!()&[\]]+)([a-zA-Z\d_?%~\-\/#='*$!&])/", |
|
541
|
|
|
function($matches) use ($link_length) { |
|
542
|
2 |
|
if (strlen($matches[0]) > $link_length) { |
|
543
|
1 |
|
return '<a href="' . $matches[0] . '" rel="nofollow">' . substr($matches[0], 0, $link_length) . "...</a>"; |
|
544
|
|
|
} else { |
|
545
|
1 |
|
return '<a href="' . $matches[0] . '" rel="nofollow">' . $matches[0] . '</a>'; |
|
546
|
|
|
} |
|
547
|
3 |
|
}, |
|
548
|
3 |
|
$text); |
|
549
|
3 |
|
$text = str_replace('<a href="www', '<a href="http://www', $text); |
|
550
|
3 |
|
$text = preg_replace("/([\w\.]+)(@)([\w\.\-]+)/i", "<a href=\"mailto:$0\">$0</a>", $text); |
|
551
|
3 |
|
$text = str_replace("\n", "<br>\n", $text); |
|
552
|
|
|
|
|
553
|
3 |
|
return $text; |
|
554
|
|
|
} |
|
555
|
|
|
|
|
556
|
|
|
function htmlentities_notags($text) { |
|
557
|
|
|
// If you want to do htmlentities() on some text that has HTML tags |
|
558
|
|
|
// in it, then you need this function. |
|
559
|
|
|
|
|
560
|
3 |
|
$tbl = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES, 'UTF-8'); |
|
561
|
|
|
|
|
562
|
|
|
// You could encode extra stuff... |
|
563
|
|
|
//$tbl["“"] = """; |
|
|
|
|
|
|
564
|
|
|
//$tbl["”"] = """; |
|
|
|
|
|
|
565
|
|
|
//$tbl["…"] = "..."; |
|
|
|
|
|
|
566
|
|
|
//$tbl["—"] = "-"; |
|
|
|
|
|
|
567
|
|
|
//$tbl["»"] = "»"; |
|
|
|
|
|
|
568
|
|
|
//$tbl["«"] = "«"; |
|
|
|
|
|
|
569
|
|
|
|
|
570
|
|
|
// lib_filter will replace unmatched < and > with entities so |
|
571
|
|
|
// we abuse strtr's only replace once behaviour to not double |
|
572
|
|
|
// encode them. May not be robust. |
|
573
|
|
|
// This does mean if anyone actually wants to put > or < |
|
574
|
|
|
// in a comment they can't but that's a lot less likely than |
|
575
|
|
|
// < or > for less than and greater than. |
|
576
|
3 |
|
$tbl['<'] = "<"; |
|
577
|
3 |
|
$tbl['>'] = ">"; |
|
578
|
|
|
|
|
579
|
|
|
// Don't want to encode these things |
|
580
|
3 |
|
unset ($tbl["<"]); |
|
581
|
3 |
|
unset ($tbl[">"]); |
|
582
|
3 |
|
unset ($tbl["'"]); |
|
583
|
3 |
|
unset ($tbl['"']); |
|
584
|
|
|
|
|
585
|
|
|
# strtr "will *NOT* try to replace stuff that it has already worked on." |
|
586
|
3 |
|
$text = strtr($text, $tbl); |
|
587
|
|
|
|
|
588
|
3 |
|
return $text; |
|
589
|
|
|
} |
|
590
|
|
|
|
|
591
|
|
|
/* |
|
592
|
|
|
* PHP 5.4 changes the default encoding for htmlentities and htmlspecialchars |
|
593
|
|
|
* to be UTF-8, not using the php.ini character encoding until PHP 5.6. So |
|
594
|
|
|
* we have to wrap all uses of these two functions. |
|
595
|
|
|
*/ |
|
596
|
|
|
function _htmlentities($s) { |
|
597
|
8 |
|
return htmlentities($s, ENT_COMPAT, 'UTF-8'); |
|
598
|
|
|
} |
|
599
|
|
|
function _htmlspecialchars($s) { |
|
600
|
|
|
return htmlspecialchars($s, ENT_COMPAT, 'UTF-8'); |
|
601
|
|
|
} |
|
602
|
|
|
|
|
603
|
|
|
function get_canonical_gid($gid) { |
|
604
|
|
|
$db = new ParlDB; |
|
605
|
|
|
$might_be_redirected = true; |
|
606
|
|
|
while ($might_be_redirected) { |
|
607
|
|
|
$q = $db->query("SELECT gid_to FROM gidredirect WHERE gid_from = :gid", array(':gid' => $gid)); |
|
608
|
|
|
if ($q->rows() > 0) { |
|
609
|
|
|
$gid = $q->field(0, 'gid_to'); |
|
610
|
|
|
} else { |
|
611
|
|
|
$might_be_redirected = false; |
|
612
|
|
|
} |
|
613
|
|
|
} |
|
614
|
|
|
|
|
615
|
|
|
return $gid; |
|
616
|
|
|
} |
|
617
|
|
|
|
|
618
|
|
|
|
|
619
|
|
|
function fix_gid_from_db($gid, $keepmajor = false) { |
|
620
|
|
|
// The gids in the database are longer than we use in the site. |
|
621
|
|
|
// Feed this a gid from the db and it will be returned truncated. |
|
622
|
|
|
|
|
623
|
|
|
// $gid will be like 'uk.org.publicwhip/debate/2003-02-28.475.3'. |
|
624
|
|
|
|
|
625
|
|
|
// You will almost always want $keepmajor to be false. |
|
626
|
|
|
// This returns '2003-02-28.475.3' which is used for URLs. |
|
627
|
|
|
|
|
628
|
|
|
// However, trackbacks want a bit more info, so we can tell what |
|
629
|
|
|
// kind of thing they link to. So they need $keepmajor to be true. |
|
630
|
|
|
// This returns 'debate_2003-02-28.475.3'. |
|
631
|
|
|
|
|
632
|
4 |
|
if ($keepmajor) { |
|
633
|
|
|
$newgid = substr($gid, strpos($gid, '/')+1 ); |
|
634
|
|
|
$newgid = str_replace('/', '_', $newgid); |
|
635
|
|
|
} else { |
|
636
|
4 |
|
$newgid = substr($gid, strrpos($gid, '/')+1 ); |
|
637
|
|
|
} |
|
638
|
|
|
|
|
639
|
4 |
|
return $newgid; |
|
640
|
|
|
|
|
641
|
|
|
} |
|
642
|
|
|
|
|
643
|
|
|
function gid_to_anchor($gid) { |
|
644
|
|
|
// For trimming gids to be used as #anchors in pages. |
|
645
|
|
|
// Extracted here so we keep it consistent. |
|
646
|
|
|
// The gid should already be truncated using fix_gid_from_db(), so it |
|
647
|
|
|
// will be like 2003-11-20.966.0 |
|
648
|
|
|
// This function returns 966.0 |
|
649
|
|
|
|
|
650
|
|
|
return substr( $gid, (strpos($gid, '.') + 1) ); |
|
651
|
|
|
} |
|
652
|
|
|
|
|
653
|
|
|
function preg_replacement_quote($s) { |
|
654
|
|
|
// This returns $s but with every $ and \ backslash-escaped. |
|
655
|
|
|
// This is to create a string that can be safely used in a |
|
656
|
|
|
// preg_replace replacement string. This function was suggested here: |
|
657
|
|
|
// http://www.procata.com/blog/archives/2005/11/13/two-preg_replace-escaping-gotchas/ |
|
658
|
1 |
|
return preg_replace('/(\$|\\\\)(?=\d)/', '\\\\\1', $s); |
|
659
|
|
|
} |
|
660
|
|
|
|
|
661
|
|
|
function send_template_email($data, $merge, $bulk = false, $want_bounces = false) { |
|
662
|
|
|
// We should have some email templates in INCLUDESPATH/easyparliament/templates/emails/. |
|
663
|
|
|
|
|
664
|
|
|
// $data is like: |
|
665
|
|
|
// array ( |
|
666
|
|
|
// 'template' => 'send_confirmation', |
|
|
|
|
|
|
667
|
|
|
// 'to' => '[email protected]', |
|
|
|
|
|
|
668
|
|
|
// 'subject' => 'Your confirmation email' |
|
|
|
|
|
|
669
|
|
|
// ); |
|
670
|
|
|
|
|
671
|
|
|
// $merge is like: |
|
672
|
|
|
// array ( |
|
673
|
|
|
// 'FIRSTNAME' => 'Phil', |
|
|
|
|
|
|
674
|
|
|
// 'LATNAME' => 'Gyford' |
|
|
|
|
|
|
675
|
|
|
// etc... |
|
676
|
|
|
// ); |
|
677
|
|
|
|
|
678
|
|
|
// In $data, 'template' and 'to' are mandatory. 'template' is the |
|
679
|
|
|
// name of the file (when it has '.txt' added to it). |
|
680
|
|
|
|
|
681
|
|
|
// We'll get the text of the template and replace all the $merge |
|
682
|
|
|
// keys with their tokens. eg, if '{FIRSTNAME}' in the template will |
|
683
|
|
|
// be replaced with 'Phil'. |
|
684
|
|
|
|
|
685
|
|
|
// Additionally, the first line of a template may start with |
|
686
|
|
|
// 'Subject:'. Any text immediately following that, on the same line |
|
687
|
|
|
// will be the subject of the email (it will also have its tokens merged). |
|
688
|
|
|
// But this subject can be overridden by sending including a 'subject' |
|
689
|
|
|
// pair in $data. |
|
690
|
|
|
|
|
691
|
|
|
global $PAGE; |
|
|
|
|
|
|
692
|
|
|
|
|
693
|
|
|
if (!isset($data['to']) || $data['to'] == '') { |
|
694
|
|
|
$PAGE->error_message ("We need an email address to send to."); |
|
695
|
|
|
return false; |
|
696
|
|
|
} |
|
697
|
|
|
|
|
698
|
|
|
$filename = INCLUDESPATH . "easyparliament/templates/emails/" . $data['template'] . ".txt"; |
|
|
|
|
|
|
699
|
|
|
|
|
700
|
|
|
if (!file_exists($filename)) { |
|
701
|
|
|
$PAGE->error_message("Sorry, we could not find the email template '" . _htmlentities($data['template']) . "'."); |
|
702
|
|
|
return false; |
|
703
|
|
|
} |
|
704
|
|
|
|
|
705
|
|
|
// Get the text from the template. |
|
706
|
|
|
$handle = fopen($filename, "r"); |
|
707
|
|
|
$emailtext = fread($handle, filesize($filename)); |
|
|
|
|
|
|
708
|
|
|
fclose($handle); |
|
|
|
|
|
|
709
|
|
|
|
|
710
|
|
|
// See if there's a default subject in the template. |
|
711
|
|
|
$firstline = substr($emailtext, 0, strpos($emailtext, "\n")); |
|
712
|
|
|
|
|
713
|
|
|
// Work out what the subject line is. |
|
714
|
|
|
if (preg_match("/Subject:/", $firstline)) { |
|
715
|
|
|
if (isset($data['subject'])) { |
|
716
|
|
|
$subject = trim($data['subject']); |
|
717
|
|
|
} else { |
|
718
|
|
|
$subject = trim( substr($firstline, 8) ); |
|
719
|
|
|
} |
|
720
|
|
|
|
|
721
|
|
|
// Either way, remove this subject line from the template. |
|
722
|
|
|
$emailtext = substr($emailtext, strpos($emailtext, "\n")); |
|
723
|
|
|
|
|
724
|
|
|
} elseif (isset($data['subject'])) { |
|
725
|
|
|
$subject = $data['subject']; |
|
726
|
|
|
} else { |
|
727
|
|
|
$PAGE->error_message ("We don't have a subject line for the email, so it wasn't sent."); |
|
728
|
|
|
return false; |
|
729
|
|
|
} |
|
730
|
|
|
|
|
731
|
|
|
|
|
732
|
|
|
// Now merge all the tokens from $merge into $emailtext... |
|
733
|
|
|
$search = array(); |
|
734
|
|
|
$replace = array(); |
|
735
|
|
|
|
|
736
|
|
|
foreach ($merge as $key => $val) { |
|
737
|
|
|
$search[] = '/{'.$key.'}/'; |
|
738
|
|
|
$replace[] = preg_replacement_quote($val); |
|
739
|
|
|
} |
|
740
|
|
|
|
|
741
|
|
|
$emailtext = preg_replace($search, $replace, $emailtext); |
|
742
|
|
|
|
|
743
|
|
|
// Send it! |
|
744
|
|
|
$success = send_email ($data['to'], $subject, $emailtext, $bulk, 'twfy-DO-NOT-REPLY@' . EMAILDOMAIN, $want_bounces); |
|
|
|
|
|
|
745
|
|
|
|
|
746
|
|
|
return $success; |
|
747
|
|
|
|
|
748
|
|
|
} |
|
749
|
|
|
|
|
750
|
|
|
/* verp_envelope_sender RECIPIENT |
|
751
|
|
|
* Construct a VERP envelope sender for an email to RECIPIENT |
|
752
|
|
|
*/ |
|
753
|
|
|
function twfy_verp_envelope_sender($recipient) { |
|
754
|
|
|
$envelope_sender = verp_envelope_sender($recipient, 'twfy', EMAILDOMAIN); |
|
|
|
|
|
|
755
|
|
|
|
|
756
|
|
|
return $envelope_sender; |
|
757
|
|
|
} |
|
758
|
|
|
|
|
759
|
|
|
function send_email($to, $subject, $message, $bulk = false, $from = '', $want_bounces = false) { |
|
760
|
|
|
// Use this rather than PHP's mail() direct, so we can make alterations |
|
761
|
|
|
// easily to all the emails we send out from the site. |
|
762
|
|
|
// eg, we might want to add a .sig to everything here... |
|
763
|
|
|
|
|
764
|
|
|
if (!$from) $from = CONTACTEMAIL; |
|
|
|
|
|
|
765
|
|
|
|
|
766
|
|
|
$headers = |
|
767
|
|
|
"From: TheyWorkForYou <$from>\r\n" . |
|
768
|
|
|
"Content-Type: text/plain; charset=utf-8\r\n" . |
|
769
|
|
|
"MIME-Version: 1.0\r\n" . |
|
770
|
|
|
"Content-Transfer-Encoding: 8bit\r\n" . |
|
771
|
|
|
($bulk ? "Precedence: bulk\r\nAuto-Submitted: auto-generated\r\n" : "" ). |
|
772
|
|
|
"X-Mailer: PHP/" . phpversion(); |
|
773
|
|
|
twfy_debug('EMAIL', "Sending email to $to with subject of '$subject'"); |
|
774
|
|
|
|
|
775
|
|
|
if ($want_bounces) { |
|
776
|
|
|
$envelope_sender = twfy_verp_envelope_sender($to); |
|
777
|
|
|
$success = mail ($to, $subject, $message, $headers, '-f ' . $envelope_sender); |
|
778
|
|
|
} else { |
|
779
|
|
|
$success = mail ($to, $subject, $message, $headers); |
|
780
|
|
|
} |
|
781
|
|
|
|
|
782
|
|
|
return $success; |
|
783
|
|
|
} |
|
784
|
|
|
|
|
785
|
|
|
|
|
786
|
|
|
/////////////////////////////// |
|
787
|
|
|
// Cal's functions from |
|
788
|
|
|
// http://www.iamcal.com/publish/article.php?id=13 |
|
789
|
|
|
|
|
790
|
|
|
// Call this with a key name to get a GET or POST variable. |
|
791
|
|
|
function get_http_var($name, $default='') { |
|
792
|
74 |
|
if (array_key_exists($name, $_GET)) { |
|
793
|
|
|
return clean_var($_GET[$name]); |
|
794
|
|
|
} |
|
795
|
74 |
|
if (array_key_exists($name, $_POST)) { |
|
796
|
|
|
return clean_var($_POST[$name]); |
|
797
|
|
|
} |
|
798
|
74 |
|
return $default; |
|
799
|
|
|
} |
|
800
|
|
|
|
|
801
|
|
|
function clean_var($a) { |
|
802
|
3 |
|
return (ini_get("magic_quotes_gpc") == 1) ? recursive_strip($a) : $a; |
|
803
|
|
|
} |
|
804
|
|
|
|
|
805
|
|
|
function recursive_strip($a) { |
|
806
|
|
|
if (is_array($a)) { |
|
807
|
|
|
while (list($key, $val) = each($a)) { |
|
|
|
|
|
|
808
|
|
|
$a[$key] = recursive_strip($val); |
|
809
|
|
|
} |
|
810
|
|
|
} else { |
|
811
|
|
|
$a = StripSlashes($a); |
|
812
|
|
|
} |
|
813
|
|
|
return $a; |
|
814
|
|
|
} |
|
815
|
|
|
|
|
816
|
|
|
// Call this with a key name to get a COOKIE variable. |
|
817
|
|
|
function get_cookie_var($name, $default='') { |
|
818
|
3 |
|
if (array_key_exists($name, $_COOKIE)) { |
|
819
|
3 |
|
return clean_var($_COOKIE[$name]); |
|
820
|
|
|
} |
|
821
|
3 |
|
return $default; |
|
822
|
|
|
} |
|
823
|
|
|
/////////////////////////////// |
|
824
|
|
|
|
|
825
|
|
|
// Pass it an array of key names that should not be generated as |
|
826
|
|
|
// hidden form variables. It then outputs hidden form variables |
|
827
|
|
|
// based on the session_vars for this page. |
|
828
|
|
|
function hidden_form_vars ($omit = array()) { |
|
829
|
|
|
global $DATA, $this_page; |
|
|
|
|
|
|
830
|
|
|
|
|
831
|
|
|
$session_vars = $DATA->page_metadata($this_page, "session_vars"); |
|
832
|
|
|
|
|
833
|
|
|
foreach ($session_vars as $n => $key) { |
|
834
|
|
|
if (!in_array($key, $omit)) { |
|
835
|
|
|
print "<input type=\"hidden\" name=\"$key\" value=\"" . _htmlentities(get_http_var($key)) . "\">\n"; |
|
836
|
|
|
} |
|
837
|
|
|
} |
|
838
|
|
|
} |
|
839
|
|
|
|
|
840
|
|
|
// Deprecated. Use hidden_form_vars, above, instead. |
|
841
|
|
|
function hidden_vars ($omit = array()) { |
|
842
|
|
|
global $DATA; |
|
|
|
|
|
|
843
|
|
|
|
|
844
|
|
|
foreach ($args as $key => $val) { |
|
|
|
|
|
|
845
|
|
|
if (!in_array($key, $omit)) { |
|
846
|
|
|
print "<input type=\"hidden\" name=\"$key\" value=\"" . _htmlspecialchars($val) . "\">\n"; |
|
847
|
|
|
} |
|
848
|
|
|
} |
|
849
|
|
|
} |
|
850
|
|
|
|
|
851
|
|
|
function make_ranking($rank) |
|
852
|
|
|
{ |
|
853
|
|
|
$rank = $rank + 0; |
|
854
|
|
|
|
|
855
|
|
|
# 11th, 12th, 13th use "th" not "st", "nd", "rd" |
|
|
|
|
|
|
856
|
|
|
if (floor(($rank % 100) / 10) == 1) |
|
857
|
|
|
return $rank . "th"; |
|
858
|
|
|
# 1st |
|
859
|
|
|
if ($rank % 10 == 1) |
|
860
|
|
|
return $rank . "st"; |
|
861
|
|
|
# 2nd |
|
862
|
|
|
if ($rank % 10 == 2) |
|
863
|
|
|
return $rank . "nd"; |
|
864
|
|
|
# 3rd |
|
865
|
|
|
if ($rank % 10 == 3) |
|
866
|
|
|
return $rank . "rd"; |
|
867
|
|
|
# Everything else use th |
|
868
|
|
|
|
|
869
|
|
|
return $rank . "th"; |
|
870
|
|
|
} |
|
871
|
|
|
|
|
872
|
|
|
function make_plural($word, $number) |
|
873
|
|
|
{ |
|
874
|
|
|
if ($number == 1) |
|
875
|
|
|
return $word; |
|
876
|
|
|
return $word . "s"; |
|
877
|
|
|
} |
|
878
|
|
|
|
|
879
|
|
|
# Can't have the entities in XML so replace all theones we currently have with numerical entities |
|
880
|
|
|
# This is yucky. XXX |
|
881
|
|
|
function entities_to_numbers($string) { |
|
882
|
|
|
$string = str_replace( |
|
883
|
|
|
array('Ö', 'â', 'ú', 'á', 'í', 'ô', 'é'), |
|
884
|
|
|
array('Ö', 'â', 'ú', 'á', 'í', 'ô', 'é' ), |
|
885
|
|
|
$string |
|
886
|
|
|
); |
|
887
|
|
|
return $string; |
|
888
|
|
|
} |
|
889
|
|
|
|
|
890
|
|
|
function make_member_url($name, $const = '', $house = HOUSE_TYPE_COMMONS, $pid = NULL) { |
|
891
|
|
|
|
|
892
|
|
|
// Case for Elizabeth II |
|
893
|
10 |
|
if ($house == HOUSE_TYPE_ROYAL) |
|
894
|
10 |
|
{ |
|
895
|
1 |
|
return 'elizabeth_the_second'; |
|
896
|
|
|
} |
|
897
|
|
|
|
|
898
|
9 |
|
$s = array(' ', '&', 'ô', 'Ö', 'ö', 'â', 'í', 'á', 'ú', 'é', 'ó', 'Ó'); |
|
899
|
9 |
|
$s2 = array(" ", "&", "\xc3\xb4", "\xc3\96", "\xc3\xb6", "\xc3\xa5", "\xc3\xad", "\xc3\xa1", "\xc3\xba", "\xc3\xa9", "\xc3\xb3", "\xc3\x93"); |
|
900
|
9 |
|
$r = array('_', 'and', 'o', 'o', 'o', 'a', 'i', 'a', 'u', 'e', 'o', 'o'); |
|
901
|
9 |
|
$name = preg_replace('#^the #', '', strtolower($name)); |
|
902
|
|
|
|
|
903
|
9 |
|
$out = ''; |
|
904
|
|
|
|
|
905
|
|
|
// Insert the Person ID if known. |
|
906
|
9 |
|
if ($pid !== NULL) |
|
907
|
9 |
|
{ |
|
908
|
9 |
|
$out .= $pid . '/'; |
|
909
|
9 |
|
} |
|
910
|
|
|
|
|
911
|
|
|
// Always inject the person's name |
|
912
|
9 |
|
$out .= urlencode(str_replace($s2, $r, str_replace($s, $r, $name))); |
|
913
|
|
|
|
|
914
|
|
|
// If there is a constituency, inject that too |
|
915
|
9 |
|
if ($const && $house == HOUSE_TYPE_COMMONS) |
|
916
|
9 |
|
{ |
|
917
|
3 |
|
$out .= '/' . urlencode(str_replace($s2, $r, str_replace($s, $r, strtolower($const)))); |
|
918
|
3 |
|
} |
|
919
|
|
|
|
|
920
|
9 |
|
return $out; |
|
921
|
|
|
} |
|
922
|
|
|
|
|
923
|
|
|
function member_full_name($house, $title, $given_name, $family_name, $lordofname) { |
|
924
|
14 |
|
$s = 'ERROR'; |
|
925
|
14 |
|
if ($house == HOUSE_TYPE_COMMONS || $house == HOUSE_TYPE_NI || $house == HOUSE_TYPE_SCOTLAND) { |
|
926
|
11 |
|
$s = "$given_name $family_name"; |
|
927
|
11 |
|
if ($title) { |
|
928
|
7 |
|
$s = $title . ' ' . $s; |
|
929
|
7 |
|
} |
|
930
|
14 |
|
} elseif ($house == HOUSE_TYPE_LORDS) { |
|
931
|
2 |
|
$s = ''; |
|
932
|
2 |
|
if (!$family_name) $s = 'the '; |
|
933
|
2 |
|
$s .= $title; |
|
934
|
2 |
|
if ($family_name) $s .= ' ' . $family_name; |
|
935
|
2 |
|
if ($lordofname) $s .= ' of ' . $lordofname; |
|
936
|
3 |
|
} elseif ($house == HOUSE_TYPE_ROYAL) { # Queen |
|
937
|
1 |
|
$s = "$given_name $family_name"; |
|
938
|
1 |
|
} |
|
939
|
14 |
|
return $s; |
|
940
|
|
|
} |
|
941
|
|
|
|
|
942
|
|
|
function prettify_office($pos, $dept) { |
|
943
|
|
|
$lookup = array( |
|
944
|
|
|
'Prime Minister, HM Treasury' => 'Prime Minister', |
|
945
|
|
|
'Secretary of State, Foreign & Commonwealth Office' => 'Foreign Secretary', |
|
946
|
|
|
'Secretary of State, Home Office' => 'Home Secretary', |
|
947
|
|
|
'Minister of State (Energy), Department of Trade and Industry' |
|
948
|
|
|
=> 'Minister for energy, Department of Trade and Industry', |
|
949
|
|
|
'Minister of State (Pensions), Department for Work and Pensions' |
|
950
|
|
|
=> 'Minister for pensions, Department for Work and Pensions', |
|
951
|
|
|
'Parliamentary Secretary to the Treasury, HM Treasury' => 'Chief Whip', |
|
952
|
|
|
'The Parliamentary Secretary to the Treasury' => 'Chief Whip', |
|
953
|
|
|
"Treasurer of Her Majesty's Household, HM Household" => "Deputy Chief Whip", |
|
954
|
|
|
"The Treasurer of Her Majesty's Household, HM Household" => "Deputy Chief Whip", |
|
955
|
|
|
'Comptroller, HM Household' => 'Government Whip', |
|
956
|
|
|
'Vice Chamberlain, HM Household' => 'Government Whip', |
|
957
|
|
|
"The Vice-Chamberlain of Her Majesty's Household" => 'Government Whip', |
|
958
|
|
|
'Lords Commissioner, HM Treasury' => 'Government Whip', |
|
959
|
|
|
"The Lord Commissioner of Her Majesty's Treasury" => 'Government Whip', |
|
960
|
|
|
'Assistant Whip, HM Treasury' => 'Assistant Whip', |
|
961
|
|
|
'Lords in Waiting, HM Household' => 'Government Whip', |
|
962
|
|
|
'Lords in Waiting (HM Household)' => 'Government Whip', |
|
963
|
|
|
'Baronesses in Waiting, HM Household' => 'Government Whip', |
|
964
|
|
|
); |
|
965
|
|
|
if ($pos) { # Government post, or Chairman of Select Committee |
|
966
|
|
|
$pretty = $pos; |
|
967
|
|
|
if ($dept && $dept != 'No Department') $pretty .= ", $dept"; |
|
968
|
|
|
if (array_key_exists($pretty, $lookup)) |
|
969
|
|
|
$pretty = $lookup[$pretty]; |
|
970
|
|
|
} else { # Member of Select Committee |
|
971
|
|
|
$pretty = "Member, $dept"; |
|
972
|
|
|
} |
|
973
|
|
|
return $pretty; |
|
974
|
|
|
} |
|
975
|
|
|
|
|
976
|
|
|
function major_summary($data, $echo = true) { |
|
977
|
|
|
global $hansardmajors; |
|
|
|
|
|
|
978
|
|
|
$html = ''; |
|
979
|
|
|
$db = new ParlDB; |
|
980
|
|
|
$one_date = false; |
|
981
|
|
|
|
|
982
|
|
|
//if no printed majors passed, default to all |
|
983
|
|
|
if (!isset($printed_majors)) { |
|
|
|
|
|
|
984
|
|
|
$printed_majors = array(1, 2, 4, 3, 5, 101, 7); # 8 |
|
985
|
|
|
} |
|
986
|
|
|
|
|
987
|
|
|
// single date? |
|
988
|
|
|
if (isset($data['date'])) $one_date = true; |
|
989
|
|
|
|
|
990
|
|
|
// remove empty entries, so they don't produce errors |
|
991
|
|
|
foreach (array_keys($hansardmajors) as $major) { |
|
992
|
|
|
if (array_key_exists($major, $data)) { |
|
993
|
|
|
if (count($data[$major]) == 0) |
|
994
|
|
|
unset($data[$major]); |
|
995
|
|
|
} |
|
996
|
|
|
} |
|
997
|
|
|
|
|
998
|
|
|
//work out the date text to be displaid |
|
999
|
|
|
$daytext = array(); |
|
1000
|
|
|
if (!$one_date) { |
|
1001
|
|
|
$todaystime = gmmktime(0, 0, 0, date('m'), date('d'), date('Y')); |
|
|
|
|
|
|
1002
|
|
|
foreach ($data as $major => $array) { |
|
1003
|
|
|
if (!in_array('timestamp', $array)) $daytext[$major] = "The most recent "; |
|
1004
|
|
|
elseif ($todaystime - $array['timestamp'] == 86400) $daytext[$major] = "Yesterday’s"; |
|
1005
|
|
|
elseif ($todaystime - $array['timestamp'] <= (6 * 86400)) $daytext[$major] = gmdate('l', $array['timestamp']) . "’s"; |
|
1006
|
|
|
else $daytext[$major] = "The most recent "; |
|
1007
|
|
|
} |
|
1008
|
|
|
} |
|
1009
|
|
|
|
|
1010
|
|
|
//build html |
|
1011
|
|
|
foreach ($printed_majors as $p_major) { |
|
1012
|
|
|
if (!array_key_exists($p_major, $data)) |
|
1013
|
|
|
continue; |
|
1014
|
|
|
|
|
1015
|
|
|
if ($one_date) |
|
1016
|
|
|
$date = $data['date']; |
|
1017
|
|
|
else |
|
1018
|
|
|
$date = $data[$p_major]['hdate']; |
|
1019
|
|
|
$q = $db->query('SELECT section_id, body, gid |
|
1020
|
|
|
FROM hansard, epobject |
|
1021
|
|
|
WHERE hansard.epobject_id = epobject.epobject_id ' |
|
1022
|
|
|
. ($p_major == 4 ? 'AND subsection_id=0' : 'AND section_id=0') . |
|
1023
|
|
|
' AND hdate = "' . $date . '" |
|
1024
|
|
|
AND major = ' . $p_major . ' |
|
1025
|
|
|
ORDER BY hpos'); |
|
1026
|
|
|
$out = ''; |
|
1027
|
|
|
$LISTURL = new \MySociety\TheyWorkForYou\Url($hansardmajors[$p_major]['page_all']); |
|
1028
|
|
|
$current_sid = 0; |
|
1029
|
|
|
for ($i = 0; $i < $q->rows(); $i++) { |
|
1030
|
|
|
$gid = fix_gid_from_db($q->field($i, 'gid')); |
|
1031
|
|
|
$body = $q->field($i, 'body'); |
|
1032
|
|
|
$section_id = $q->field($i, 'section_id'); |
|
1033
|
|
|
//if (strstr($body, 'Chair]')) continue; |
|
|
|
|
|
|
1034
|
|
|
if ($p_major == 4 && !$section_id) { |
|
1035
|
|
|
if ($current_sid++) { |
|
1036
|
|
|
$out .= '</ul>'; |
|
1037
|
|
|
} |
|
1038
|
|
|
$out .= '<li>' . $body . '<ul>'; |
|
1039
|
|
|
} else { |
|
1040
|
|
|
$LISTURL->insert( array( 'id' => $gid ) ); |
|
1041
|
|
|
$out .= '<li><a href="'.$LISTURL->generate().'">'; |
|
1042
|
|
|
$out .= $body . '</a>'; |
|
1043
|
|
|
} |
|
1044
|
|
|
} |
|
1045
|
|
|
if ($out) { |
|
1046
|
|
|
$html .= _major_summary_title($p_major, $data, $LISTURL, $daytext); |
|
1047
|
|
|
$html .= '<ul class="hansard-day">'; |
|
1048
|
|
|
$html .= $out; |
|
1049
|
|
|
$html .= '</ul>'; |
|
1050
|
|
|
} |
|
1051
|
|
|
} |
|
1052
|
|
|
$html .= '</ul>'; |
|
1053
|
|
|
|
|
1054
|
|
|
if ($echo) { |
|
1055
|
|
|
print $html; |
|
1056
|
|
|
} else { |
|
1057
|
|
|
return $html; |
|
1058
|
|
|
} |
|
1059
|
|
|
} |
|
1060
|
|
|
|
|
1061
|
|
|
function _major_summary_title($major, $data, $LISTURL, $daytext) { |
|
1062
|
|
|
global $hansardmajors; |
|
|
|
|
|
|
1063
|
|
|
|
|
1064
|
|
|
$return = '<h4>'; |
|
1065
|
|
|
if (isset($daytext[$major])) { |
|
1066
|
|
|
$return .= $daytext[$major] . ' '; |
|
1067
|
|
|
} |
|
1068
|
|
|
|
|
1069
|
|
|
$return .= '<a href="'; |
|
1070
|
|
|
if (isset($data[$major]['listurl'])) |
|
1071
|
|
|
$return .= $data[$major]['listurl']; |
|
1072
|
|
|
else { |
|
1073
|
|
|
$LISTURL->reset(); |
|
1074
|
|
|
$return .= $LISTURL->generate(); |
|
1075
|
|
|
} |
|
1076
|
|
|
$return .= '">' . $hansardmajors[$major]['title'] . '</a>'; |
|
1077
|
|
|
if (isset($daytext[$major])) $return; |
|
1078
|
|
|
$return .= '</h4>'; |
|
1079
|
|
|
|
|
1080
|
|
|
return $return; |
|
1081
|
|
|
} |
|
1082
|
|
|
|
|
1083
|
|
|
function score_to_strongly($dmpscore) { |
|
1084
|
4 |
|
$dmpdesc = "unknown about"; |
|
1085
|
4 |
|
if ($dmpscore > 0.95 && $dmpscore <= 1.0) |
|
1086
|
4 |
|
$dmpdesc = "consistently voted against"; |
|
1087
|
4 |
|
elseif ($dmpscore > 0.85) |
|
1088
|
1 |
|
$dmpdesc = "almost always voted against"; |
|
1089
|
3 |
|
elseif ($dmpscore > 0.6) |
|
1090
|
|
|
$dmpdesc = "generally voted against"; |
|
1091
|
3 |
|
elseif ($dmpscore > 0.4) |
|
1092
|
2 |
|
$dmpdesc = "voted a mixture of for and against"; |
|
1093
|
1 |
|
elseif ($dmpscore > 0.15) |
|
1094
|
|
|
$dmpdesc = "generally voted for"; |
|
1095
|
1 |
|
elseif ($dmpscore > 0.05) |
|
1096
|
|
|
$dmpdesc = "almost always voted for"; |
|
1097
|
1 |
|
elseif ($dmpscore >= 0.0) |
|
1098
|
|
|
$dmpdesc = "consistently voted for"; |
|
1099
|
4 |
|
return $dmpdesc; |
|
1100
|
|
|
} |
|
1101
|
|
|
|
|
1102
|
|
|
function valid_url($url) { |
|
1103
|
|
|
$return = false; |
|
1104
|
|
|
if (preg_match("/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?/i", $url)) { |
|
1105
|
|
|
$return = true; |
|
1106
|
|
|
} |
|
1107
|
|
|
return $return; |
|
1108
|
|
|
} |
|
1109
|
|
|
|
|
1110
|
|
|
function redirect($url) { |
|
1111
|
|
|
if (defined('TESTING')) { |
|
1112
|
|
|
print "Location: $url"; |
|
1113
|
|
|
} else { |
|
1114
|
|
|
header("Location: $url", true, 301); |
|
1115
|
|
|
} |
|
1116
|
|
|
exit; |
|
|
|
|
|
|
1117
|
|
|
} |
|
1118
|
|
|
|
|
1119
|
|
|
function cache_version($file) { |
|
1120
|
|
|
static $version_hash = array(); |
|
1121
|
|
|
$path = BASEDIR . "/$file"; |
|
1122
|
|
|
if (is_file($path) && (!isset($version_hash[$file]) || DEVSITE)) { |
|
|
|
|
|
|
1123
|
|
|
$version_hash[$file] = stat($path)[9]; |
|
1124
|
|
|
$file .= '?' . $version_hash[$file]; |
|
1125
|
|
|
} |
|
1126
|
|
|
return WEBPATH . $file; |
|
|
|
|
|
|
1127
|
|
|
} |
|
1128
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.