| 1 |
<?php |
| 2 |
// a bunch of helper functions |
| 3 |
function watu_define_newline() { |
| 4 |
// credit to http://yoast.com/wordpress/users-to-csv/ |
| 5 |
$unewline = "\r\n"; |
| 6 |
if (strstr(strtolower($_SERVER["HTTP_USER_AGENT"]), 'win')) { |
| 7 |
$unewline = "\r\n"; |
| 8 |
} else if (strstr(strtolower($_SERVER["HTTP_USER_AGENT"]), 'mac')) { |
| 9 |
$unewline = "\r"; |
| 10 |
} else { |
| 11 |
$unewline = "\n"; |
| 12 |
} |
| 13 |
return $unewline; |
| 14 |
} |
| 15 |
|
| 16 |
function watu_get_mime_type() { |
| 17 |
// credit to http://yoast.com/wordpress/users-to-csv/ |
| 18 |
$USER_BROWSER_AGENT=""; |
| 19 |
|
| 20 |
if (preg_match('/OPERA(\/| )([0-9].[0-9]{1,2})/', strtoupper($_SERVER["HTTP_USER_AGENT"]), $log_version)) { |
| 21 |
$USER_BROWSER_AGENT='OPERA'; |
| 22 |
} else if (preg_match('/MSIE ([0-9].[0-9]{1,2})/',strtoupper($_SERVER["HTTP_USER_AGENT"]), $log_version)) { |
| 23 |
$USER_BROWSER_AGENT='IE'; |
| 24 |
} else if (preg_match('/OMNIWEB\/([0-9].[0-9]{1,2})/', strtoupper($_SERVER["HTTP_USER_AGENT"]), $log_version)) { |
| 25 |
$USER_BROWSER_AGENT='OMNIWEB'; |
| 26 |
} else if (preg_match('/MOZILLA\/([0-9].[0-9]{1,2})/', strtoupper($_SERVER["HTTP_USER_AGENT"]), $log_version)) { |
| 27 |
$USER_BROWSER_AGENT='MOZILLA'; |
| 28 |
} else if (preg_match('/KONQUEROR\/([0-9].[0-9]{1,2})/', strtoupper($_SERVER["HTTP_USER_AGENT"]), $log_version)) { |
| 29 |
$USER_BROWSER_AGENT='KONQUEROR'; |
| 30 |
} else { |
| 31 |
$USER_BROWSER_AGENT='OTHER'; |
| 32 |
} |
| 33 |
|
| 34 |
$mime_type = ($USER_BROWSER_AGENT == 'IE' || $USER_BROWSER_AGENT == 'OPERA') |
| 35 |
? 'application/octetstream' |
| 36 |
: 'application/octet-stream'; |
| 37 |
return $mime_type; |
| 38 |
} |
| 39 |
|
| 40 |
function watu_redirect($url) { |
| 41 |
echo "<meta http-equiv='refresh' content='0;url=$url' />"; |
| 42 |
exit; |
| 43 |
} |
| 44 |
|
| 45 |
// escapes user input to be usable in preg_replace & other preg functions |
| 46 |
function watu_preg_escape($input) { |
| 47 |
return str_replace(array('^', '.', '|', '(', ')', '[', ']', '*', '+', '?', '{', '}', '$', '/'), |
| 48 |
array('\^', '\.', '\|', '\(', '\)', '\[', '\]', '\*', '\+', '\?', '\{', '\}', '\$', '\/' ), $input); |
| 49 |
} |
| 50 |
|
| 51 |
// notify admin / user about taken quiz |
| 52 |
function watu_notify($exam, $uid, $output, $who = 'admin') { |
| 53 |
global $user_email; |
| 54 |
|
| 55 |
// $exam->user_name is set in controllers/submit_exam.php. In case this function is called elsehwere, avoid php notice: |
| 56 |
if(empty($exam->user_name)) $exam->user_name = ''; |
| 57 |
|
| 58 |
if(empty($uid) and !empty($_POST['watu_taker_email'])) { |
| 59 |
$user_email = $_POST['watu_taker_email']; |
| 60 |
} |
| 61 |
|
| 62 |
$admin_email = watu_admin_email(); |
| 63 |
if(strstr($admin_email, '<')) { |
| 64 |
$parts = explode('<', $admin_email); |
| 65 |
$admin_email = trim(str_replace('>', '', $parts[1])); |
| 66 |
} |
| 67 |
$admin_emails = array(); |
| 68 |
|
| 69 |
if(!empty($exam->notify_email)) { |
| 70 |
$emails = explode(',', $exam->notify_email); |
| 71 |
foreach($emails as $email) $admin_emails[] = trim($email); |
| 72 |
} |
| 73 |
else $admin_emails[] = $admin_email; |
| 74 |
|
| 75 |
// different output for user / admin? |
| 76 |
if(strstr($output, '{{{split}}}')) { |
| 77 |
$parts = explode('{{{split}}}', $output); |
| 78 |
if($who == 'admin') $output = $parts[1]; |
| 79 |
else $output = $parts[0]; |
| 80 |
} |
| 81 |
|
| 82 |
// replace styles in the snapshot with the images |
| 83 |
$correct_style=' style="padding-right:20px;background:url('.WATU_URL.'correct.png) no-repeat right top;" '; |
| 84 |
$wrong_style=' style="padding-right:20px;background:url('.WATU_URL.'wrong.png) no-repeat right top;" '; |
| 85 |
$user_answer_style = ' style="font-weight:bold;" '; |
| 86 |
|
| 87 |
|
| 88 |
$output=str_replace('><!--WATUEMAILanswerWATUEMAIL--','',$output); |
| 89 |
$output=str_replace('><!--WATUEMAILanswer correct-answer user-answerWATUEMAIL--', $correct_style, $output); |
| 90 |
$output=str_replace('><!--WATUEMAILanswer correct-answeruser-answerWATUEMAIL--', $correct_style, $output); |
| 91 |
$output=str_replace('><!--WATUEMAILanswer correct-answerWATUEMAIL--',$correct_style,$output); |
| 92 |
$output=str_replace('><!--WATUEMAILanswer user-answerWATUEMAIL--', $wrong_style,$output); |
| 93 |
|
| 94 |
$output = str_replace("<li class='answer user-answer'>", "<li ".$user_answer_style.">", $output); |
| 95 |
$output = str_replace("<li class='answer user-answer correct-answer'>", "<li ".$user_answer_style.">", $output); |
| 96 |
$output = str_replace("<li class='answer correct-answer user-answer'>", "<li ".$user_answer_style.">", $output); |
| 97 |
|
| 98 |
$headers = 'MIME-Version: 1.0' . "\r\n"; |
| 99 |
$headers .= 'Content-type: text/html; charset=utf-8' . "\r\n"; |
| 100 |
$headers .= 'From: '. watu_admin_email() . "\r\n"; |
| 101 |
|
| 102 |
$admin_subject = sprintf(__('User results on "%s"', 'watu'), stripslashes($exam->name)); |
| 103 |
$user_subject = sprintf(__('Your results on "%s"', 'watu'), stripslashes($exam->name)); |
| 104 |
|
| 105 |
if(!empty($exam->email_subject)) { |
| 106 |
$email_subject = stripslashes($exam->email_subject); |
| 107 |
if(strstr($email_subject, '{{{split}}}')) { |
| 108 |
list($user_subject, $admin_subject) = explode('{{{split}}}', $email_subject); |
| 109 |
} |
| 110 |
else $user_subject = $admin_subject = $email_subject; |
| 111 |
} |
| 112 |
|
| 113 |
if($who == 'admin') { |
| 114 |
|
| 115 |
$user_data = empty($user_email) ? __('Guest', 'watu') : $user_email; |
| 116 |
|
| 117 |
$admin_subject = str_replace('%%QUIZ_NAME%%', stripslashes($exam->name), $admin_subject); |
| 118 |
$admin_subject = str_replace('%%USER-NAME%%', $exam->user_name, $admin_subject); |
| 119 |
|
| 120 |
$message = "Details of $user_data:<br><br>".$output; |
| 121 |
// echo $message; |
| 122 |
//echo $admin_subject."<br>"; |
| 123 |
foreach($admin_emails as $admin_email) { |
| 124 |
wp_mail($admin_email, $admin_subject, $message, $headers); |
| 125 |
} |
| 126 |
} |
| 127 |
else { |
| 128 |
// email user |
| 129 |
if(empty($user_email)) return true; |
| 130 |
|
| 131 |
$user_subject = str_replace('%%QUIZ_NAME%%', stripslashes($exam->name), $user_subject); |
| 132 |
$user_subject = str_replace('%%USER-NAME%%', $exam->user_name, $user_subject); |
| 133 |
|
| 134 |
$message = $output; |
| 135 |
|
| 136 |
//echo $user_subject."<br>"; |
| 137 |
wp_mail($user_email, $user_subject, $message, $headers); |
| 138 |
} |
| 139 |
// echo $message; |
| 140 |
} // end watu_notify |
| 141 |
|
| 142 |
// replace user email in the quiz output / email output |
| 143 |
// replace also %%USER-NAME%% var |
| 144 |
function watu_replace_email($email, $output) { |
| 145 |
global $user_ID; |
| 146 |
if(strstr($output, '%%EMAIL%%')) { |
| 147 |
if(empty($email) and is_user_logged_in()) { |
| 148 |
$current_user = wp_get_current_user(); |
| 149 |
$email = $current_user->user_email; |
| 150 |
} |
| 151 |
|
| 152 |
$output = str_replace('%%EMAIL%%', $email, $output); |
| 153 |
} |
| 154 |
|
| 155 |
if(strstr($output, '%%USER-NAME%%')) { |
| 156 |
if(!is_user_logged_in()) $user_name = __('Guest', 'watu'); |
| 157 |
else { |
| 158 |
$user = get_userdata($user_ID); |
| 159 |
$user_name = $user->display_name; |
| 160 |
} |
| 161 |
|
| 162 |
$output = str_replace('%%USER-NAME%%', $user_name, $output); |
| 163 |
} |
| 164 |
|
| 165 |
return $output; |
| 166 |
} |
| 167 |
|
| 168 |
// get admin email. This overwrites the global setting with the Watu setting. |
| 169 |
function watu_admin_email() { |
| 170 |
$admin_email = get_option('watu_admin_email'); |
| 171 |
if(empty($admin_email)) $admin_email = get_option('admin_email'); |
| 172 |
|
| 173 |
return $admin_email; |
| 174 |
} |
| 175 |
|
| 176 |
// strip tags when user is not allowed to use unfiltered HTML |
| 177 |
// keep some safe tags on |
| 178 |
function watu_strip_tags($content) { |
| 179 |
if(!current_user_can('unfiltered_html')) { |
| 180 |
$content = strip_tags($content, '<b><i><em><u><a><p><br><div><span><hr><font><img>'); |
| 181 |
} |
| 182 |
|
| 183 |
return wp_kses_post($content); |
| 184 |
} |
| 185 |
|
| 186 |
// makes sure all values in array are ints. Typically used to sanitize POST data from multiple checkboxes |
| 187 |
function watu_int_array($value) { |
| 188 |
if(empty($value) or !is_array($value)) return array(); |
| 189 |
$value = array_filter($value, 'is_numeric'); |
| 190 |
return $value; |
| 191 |
} |
| 192 |
|
| 193 |
// returns clickable URL of a published quiz if found |
| 194 |
function watu_exam_url($exam_id, $target="_blank") { |
| 195 |
global $wpdb; |
| 196 |
|
| 197 |
$exam = $wpdb->get_row($wpdb->prepare("SELECT name, ID FROM ".WATU_EXAMS." WHERE ID=%d", $exam_id)); |
| 198 |
|
| 199 |
$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_status='publish' |
| 200 |
AND post_content LIKE '%[watu ".$exam->ID."]%' ORDER BY ID DESC LIMIT 1"); |
| 201 |
|
| 202 |
if(empty($post_id)) return stripslashes($exam->name); |
| 203 |
else return '<a href="'.get_permalink($post_id).'" target="'.$target.'">'.stripslashes($exam->name).'</a>'; |
| 204 |
} |
| 205 |
|
| 206 |
// returns non-clickable URL of a published quiz if found |
| 207 |
function watu_exam_url_raw($exam_id) { |
| 208 |
global $wpdb; |
| 209 |
|
| 210 |
$exam = $wpdb->get_row($wpdb->prepare("SELECT name, ID FROM ".WATU_EXAMS." WHERE ID=%d", $exam_id)); |
| 211 |
|
| 212 |
$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_status='publish' |
| 213 |
AND post_content LIKE '%[watu ".$exam->ID."]%' ORDER BY ID DESC LIMIT 1"); |
| 214 |
|
| 215 |
if(empty($post_id)) return ''; |
| 216 |
else return get_permalink($post_id); |
| 217 |
} |
| 218 |
|
| 219 |
// output responsive table CSS in admin pages (and not only) |
| 220 |
function watu_resp_table_css($screen_width = 600, $print_out = true) { |
| 221 |
$output = ' |
| 222 |
/* Credits: |
| 223 |
This bit of code: Exis | exisweb.net/responsive-tables-in-wordpress |
| 224 |
Original idea: Dudley Storey | codepen.io/dudleystorey/pen/Geprd */ |
| 225 |
|
| 226 |
@media screen and (max-width: '.$screen_width.'px) { |
| 227 |
table.watu-table {width:100%;} |
| 228 |
table.watu-table thead {display: none;} |
| 229 |
table.watu-table tr:nth-of-type(2n) {background-color: inherit;} |
| 230 |
table.watu-table tr td:first-child {background: #f0f0f0; font-weight:bold;font-size:1.3em;} |
| 231 |
table.watu-table tbody td {display: block; text-align:center;} |
| 232 |
table.watu-table tbody td:before { |
| 233 |
content: attr(data-th); |
| 234 |
display: block; |
| 235 |
text-align:center; |
| 236 |
} |
| 237 |
}'; |
| 238 |
|
| 239 |
if($print_out) echo $output; |
| 240 |
else return $output; |
| 241 |
} // end bftpro_resp_table_css() |
| 242 |
|
| 243 |
function watu_resp_table_js($print_out = true) { |
| 244 |
$output = ' |
| 245 |
/* Credits: |
| 246 |
This bit of code: Exis | exisweb.net/responsive-tables-in-wordpress |
| 247 |
Original idea: Dudley Storey | codepen.io/dudleystorey/pen/Geprd */ |
| 248 |
|
| 249 |
var headertext = []; |
| 250 |
var headers = document.querySelectorAll("thead"); |
| 251 |
var tablebody = document.querySelectorAll("tbody"); |
| 252 |
|
| 253 |
for (var i = 0; i < headers.length; i++) { |
| 254 |
headertext[i]=[]; |
| 255 |
for (var j = 0, headrow; headrow = headers[i].rows[0].cells[j]; j++) { |
| 256 |
var current = headrow; |
| 257 |
headertext[i].push(current.textContent); |
| 258 |
} |
| 259 |
} |
| 260 |
|
| 261 |
for (var h = 0, tbody; tbody = tablebody[h]; h++) { |
| 262 |
for (var i = 0, row; row = tbody.rows[i]; i++) { |
| 263 |
for (var j = 0, col; col = row.cells[j]; j++) { |
| 264 |
col.setAttribute("data-th", headertext[h][j]); |
| 265 |
} |
| 266 |
} |
| 267 |
}'; |
| 268 |
if($print_out) echo $output; |
| 269 |
else return $output; |
| 270 |
} // end bftpro_resp_table_js |
| 271 |
|
| 272 |
// credit to normadize at http://php.net/manual/en/function.str-getcsv.php |
| 273 |
function watu_parse_csv ($csv_string, $delimiter = ",", $skip_empty_lines = true, $trim_fields = true) { |
| 274 |
$enc = preg_replace('/(?<!")""/', '!!Q!!', $csv_string); |
| 275 |
$enc = preg_replace_callback( |
| 276 |
'/"(.*?)"/s', |
| 277 |
'watu_parse_csv_field', |
| 278 |
$enc |
| 279 |
); |
| 280 |
$lines = preg_split($skip_empty_lines ? ($trim_fields ? '/( *\R)+/s' : '/\R+/s') : '/\R/s', $enc); |
| 281 |
return array_map( |
| 282 |
'watu_parse_csv_line', |
| 283 |
$lines |
| 284 |
); |
| 285 |
} |
| 286 |
|
| 287 |
function watu_parse_csv_field($field) { |
| 288 |
return urlencode(utf8_encode($field[1])); |
| 289 |
} |
| 290 |
|
| 291 |
function watu_parse_csv_line($line) { |
| 292 |
$delimiter=$_POST['delimiter']; |
| 293 |
if($delimiter=="tab") $delimiter="\t"; |
| 294 |
|
| 295 |
// convert encoding? |
| 296 |
if(!mb_detect_encoding($line, 'UTF-8', true)) $line = mb_convert_encoding($line, "UTF-8"); |
| 297 |
|
| 298 |
$fields = true ? array_map('trim', explode($delimiter, $line)) : explode($delimiter, $line); |
| 299 |
return array_map( |
| 300 |
'watu_urlencode_csv_field', |
| 301 |
$fields |
| 302 |
); |
| 303 |
} |
| 304 |
|
| 305 |
function watu_urlencode_csv_field($field) { |
| 306 |
return str_replace('!!Q!!', '"', urldecode($field)); |
| 307 |
} |
| 308 |
|
| 309 |
// enqueue the localized and themed datepicker |
| 310 |
function watu_enqueue_datepicker() { |
| 311 |
$locale_url = get_option('watu_locale_url'); |
| 312 |
wp_enqueue_script('jquery-ui-datepicker'); |
| 313 |
if(!empty($locale_url)) { |
| 314 |
// extract the locale |
| 315 |
$parts = explode("datepicker-", $locale_url); |
| 316 |
$sparts = explode(".js", $parts[1]); |
| 317 |
$locale = $sparts[0]; |
| 318 |
wp_enqueue_script('jquery-ui-i18n-'.$locale, $locale_url, array('jquery-ui-datepicker')); |
| 319 |
} |
| 320 |
$css_url = get_option('watu_datepicker_css'); |
| 321 |
if(empty($css_url)) $css_url = WATU_URL.'lib/jquery-ui.css'; |
| 322 |
wp_enqueue_style('jquery-style', $css_url); |
| 323 |
} |
| 324 |
|