@@ -3031,8 +3031,7 @@ |
||
3031 | 3031 | <div class="roundframe"> |
3032 | 3032 | <div> |
3033 | 3033 | ', !empty($context['tfa_backup']) ? ' |
3034 | - <div class="smalltext error">' . $txt['tfa_backup_used_desc'] . '</div>' : |
|
3035 | - ($modSettings['tfa_mode'] == 2 ? ' |
|
3034 | + <div class="smalltext error">' . $txt['tfa_backup_used_desc'] . '</div>' : ($modSettings['tfa_mode'] == 2 ? ' |
|
3036 | 3035 | <div class="smalltext"><strong>' . $txt['tfa_forced_desc'] . '</strong></div>' : ''), ' |
3037 | 3036 | <div class="smalltext">', $txt['tfa_desc'], '</div> |
3038 | 3037 | <div id="basicinfo" style="width: 60%"> |
@@ -18,23 +18,25 @@ discard block |
||
18 | 18 | global $context; |
19 | 19 | |
20 | 20 | // Prevent Chrome from auto completing fields when viewing/editing other members profiles |
21 | - if (isBrowser('is_chrome') && !$context['user']['is_owner']) |
|
22 | - echo ' |
|
21 | + if (isBrowser('is_chrome') && !$context['user']['is_owner']) { |
|
22 | + echo ' |
|
23 | 23 | <script> |
24 | 24 | disableAutoComplete(); |
25 | 25 | </script>'; |
26 | + } |
|
26 | 27 | |
27 | 28 | // If an error occurred while trying to save previously, give the user a clue! |
28 | 29 | echo ' |
29 | 30 | ', template_error_message(); |
30 | 31 | |
31 | 32 | // If the profile was update successfully, let the user know this. |
32 | - if (!empty($context['profile_updated'])) |
|
33 | - echo ' |
|
33 | + if (!empty($context['profile_updated'])) { |
|
34 | + echo ' |
|
34 | 35 | <div class="infobox"> |
35 | 36 | ', $context['profile_updated'], ' |
36 | 37 | </div>'; |
37 | -} |
|
38 | + } |
|
39 | + } |
|
38 | 40 | |
39 | 41 | /** |
40 | 42 | * Template for any HTML needed below the profile (closing off divs/tables, etc.) |
@@ -102,8 +104,7 @@ discard block |
||
102 | 104 | if (empty($context['unread_alerts'])) |
103 | 105 | { |
104 | 106 | template_alerts_all_read(); |
105 | - } |
|
106 | - else |
|
107 | + } else |
|
107 | 108 | { |
108 | 109 | foreach ($context['unread_alerts'] as $id_alert => $details) |
109 | 110 | { |
@@ -164,10 +165,11 @@ discard block |
||
164 | 165 | <div class="custom_fields_above_name"> |
165 | 166 | <ul >'; |
166 | 167 | |
167 | - foreach ($context['print_custom_fields']['above_member'] as $field) |
|
168 | - if (!empty($field['output_html'])) |
|
168 | + foreach ($context['print_custom_fields']['above_member'] as $field) { |
|
169 | + if (!empty($field['output_html'])) |
|
169 | 170 | echo ' |
170 | 171 | <li>', $field['output_html'], '</li>'; |
172 | + } |
|
171 | 173 | |
172 | 174 | echo ' |
173 | 175 | </ul> |
@@ -188,10 +190,11 @@ discard block |
||
188 | 190 | <div class="custom_fields_below_avatar"> |
189 | 191 | <ul >'; |
190 | 192 | |
191 | - foreach ($context['print_custom_fields']['below_avatar'] as $field) |
|
192 | - if (!empty($field['output_html'])) |
|
193 | + foreach ($context['print_custom_fields']['below_avatar'] as $field) { |
|
194 | + if (!empty($field['output_html'])) |
|
193 | 195 | echo ' |
194 | 196 | <li>', $field['output_html'], '</li>'; |
197 | + } |
|
195 | 198 | |
196 | 199 | echo ' |
197 | 200 | </ul> |
@@ -202,22 +205,25 @@ discard block |
||
202 | 205 | echo ' |
203 | 206 | <ul class="clear">'; |
204 | 207 | // Email is only visible if it's your profile or you have the moderate_forum permission |
205 | - if ($context['member']['show_email']) |
|
206 | - echo ' |
|
208 | + if ($context['member']['show_email']) { |
|
209 | + echo ' |
|
207 | 210 | <li><a href="mailto:', $context['member']['email'], '" title="', $context['member']['email'], '" rel="nofollow"><span class="generic_icons mail" title="' . $txt['email'] . '"></span></a></li>'; |
211 | + } |
|
208 | 212 | |
209 | 213 | // Don't show an icon if they haven't specified a website. |
210 | - if ($context['member']['website']['url'] !== '' && !isset($context['disabled_fields']['website'])) |
|
211 | - echo ' |
|
214 | + if ($context['member']['website']['url'] !== '' && !isset($context['disabled_fields']['website'])) { |
|
215 | + echo ' |
|
212 | 216 | <li><a href="', $context['member']['website']['url'], '" title="' . $context['member']['website']['title'] . '" target="_blank" class="new_win">', ($settings['use_image_buttons'] ? '<span class="generic_icons www" title="' . $context['member']['website']['title'] . '"></span>' : $txt['www']), '</a></li>'; |
217 | + } |
|
213 | 218 | |
214 | 219 | // Are there any custom profile fields as icons? |
215 | 220 | if (!empty($context['print_custom_fields']['icons'])) |
216 | 221 | { |
217 | - foreach ($context['print_custom_fields']['icons'] as $field) |
|
218 | - if (!empty($field['output_html'])) |
|
222 | + foreach ($context['print_custom_fields']['icons'] as $field) { |
|
223 | + if (!empty($field['output_html'])) |
|
219 | 224 | echo ' |
220 | 225 | <li class="custom_field">', $field['output_html'], '</li>'; |
226 | + } |
|
221 | 227 | } |
222 | 228 | |
223 | 229 | echo ' |
@@ -225,23 +231,26 @@ discard block |
||
225 | 231 | <span id="userstatus">', $context['can_send_pm'] ? '<a href="' . $context['member']['online']['href'] . '" title="' . $context['member']['online']['text'] . '" rel="nofollow">' : '', $settings['use_image_buttons'] ? '<span class="' . ($context['member']['online']['is_online'] == 1 ? 'on' : 'off') . '" title="' . $context['member']['online']['text'] . '"></span>' : $context['member']['online']['label'], $context['can_send_pm'] ? '</a>' : '', $settings['use_image_buttons'] ? '<span class="smalltext"> ' . $context['member']['online']['label'] . '</span>' : ''; |
226 | 232 | |
227 | 233 | // Can they add this member as a buddy? |
228 | - if (!empty($context['can_have_buddy']) && !$context['user']['is_owner']) |
|
229 | - echo ' |
|
234 | + if (!empty($context['can_have_buddy']) && !$context['user']['is_owner']) { |
|
235 | + echo ' |
|
230 | 236 | <br><a href="', $scripturl, '?action=buddy;u=', $context['id_member'], ';', $context['session_var'], '=', $context['session_id'], '">[', $txt['buddy_' . ($context['member']['is_buddy'] ? 'remove' : 'add')], ']</a>'; |
237 | + } |
|
231 | 238 | |
232 | 239 | echo ' |
233 | 240 | </span>'; |
234 | 241 | |
235 | - if (!$context['user']['is_owner'] && $context['can_send_pm']) |
|
236 | - echo ' |
|
242 | + if (!$context['user']['is_owner'] && $context['can_send_pm']) { |
|
243 | + echo ' |
|
237 | 244 | <a href="', $scripturl, '?action=pm;sa=send;u=', $context['id_member'], '" class="infolinks">', $txt['profile_sendpm_short'], '</a>'; |
245 | + } |
|
238 | 246 | |
239 | 247 | echo ' |
240 | 248 | <a href="', $scripturl, '?action=profile;area=showposts;u=', $context['id_member'], '" class="infolinks">', $txt['showPosts'], '</a>'; |
241 | 249 | |
242 | - if ($context['user']['is_owner'] && !empty($modSettings['drafts_post_enabled'])) |
|
243 | - echo ' |
|
250 | + if ($context['user']['is_owner'] && !empty($modSettings['drafts_post_enabled'])) { |
|
251 | + echo ' |
|
244 | 252 | <a href="', $scripturl, '?action=profile;area=showdrafts;u=', $context['id_member'], '" class="infolinks">', $txt['drafts_show'], '</a>'; |
253 | + } |
|
245 | 254 | |
246 | 255 | echo ' |
247 | 256 | <a href="', $scripturl, '?action=profile;area=statistics;u=', $context['id_member'], '" class="infolinks">', $txt['statPanel'], '</a>'; |
@@ -253,10 +262,11 @@ discard block |
||
253 | 262 | <div class="custom_fields_bottom"> |
254 | 263 | <ul class="nolist">'; |
255 | 264 | |
256 | - foreach ($context['print_custom_fields']['bottom_poster'] as $field) |
|
257 | - if (!empty($field['output_html'])) |
|
265 | + foreach ($context['print_custom_fields']['bottom_poster'] as $field) { |
|
266 | + if (!empty($field['output_html'])) |
|
258 | 267 | echo ' |
259 | 268 | <li>', $field['output_html'], '</li>'; |
269 | + } |
|
260 | 270 | |
261 | 271 | echo ' |
262 | 272 | </ul> |
@@ -270,15 +280,17 @@ discard block |
||
270 | 280 | <div id="detailedinfo"> |
271 | 281 | <dl class="settings">'; |
272 | 282 | |
273 | - if ($context['user']['is_owner'] || $context['user']['is_admin']) |
|
274 | - echo ' |
|
283 | + if ($context['user']['is_owner'] || $context['user']['is_admin']) { |
|
284 | + echo ' |
|
275 | 285 | <dt>', $txt['username'], ': </dt> |
276 | 286 | <dd>', $context['member']['username'], '</dd>'; |
287 | + } |
|
277 | 288 | |
278 | - if (!isset($context['disabled_fields']['posts'])) |
|
279 | - echo ' |
|
289 | + if (!isset($context['disabled_fields']['posts'])) { |
|
290 | + echo ' |
|
280 | 291 | <dt>', $txt['profile_posts'], ': </dt> |
281 | 292 | <dd>', $context['member']['posts'], ' (', $context['member']['posts_per_day'], ' ', $txt['posts_per_day'], ')</dd>'; |
293 | + } |
|
282 | 294 | |
283 | 295 | if ($context['member']['show_email']) |
284 | 296 | { |
@@ -287,15 +299,17 @@ discard block |
||
287 | 299 | <dd><a href="mailto:', $context['member']['email'], '">', $context['member']['email'], '</a></dd>'; |
288 | 300 | } |
289 | 301 | |
290 | - if (!empty($modSettings['titlesEnable']) && !empty($context['member']['title'])) |
|
291 | - echo ' |
|
302 | + if (!empty($modSettings['titlesEnable']) && !empty($context['member']['title'])) { |
|
303 | + echo ' |
|
292 | 304 | <dt>', $txt['custom_title'], ': </dt> |
293 | 305 | <dd>', $context['member']['title'], '</dd>'; |
306 | + } |
|
294 | 307 | |
295 | - if (!empty($context['member']['blurb'])) |
|
296 | - echo ' |
|
308 | + if (!empty($context['member']['blurb'])) { |
|
309 | + echo ' |
|
297 | 310 | <dt>', $txt['personal_text'], ': </dt> |
298 | 311 | <dd>', $context['member']['blurb'], '</dd>'; |
312 | + } |
|
299 | 313 | |
300 | 314 | echo ' |
301 | 315 | <dt>', $txt['age'], ':</dt> |
@@ -310,11 +324,12 @@ discard block |
||
310 | 324 | echo ' |
311 | 325 | <dl class="settings">'; |
312 | 326 | |
313 | - foreach ($context['print_custom_fields']['standard'] as $field) |
|
314 | - if (!empty($field['output_html'])) |
|
327 | + foreach ($context['print_custom_fields']['standard'] as $field) { |
|
328 | + if (!empty($field['output_html'])) |
|
315 | 329 | echo ' |
316 | 330 | <dt>', $field['name'], ':</dt> |
317 | 331 | <dd>', $field['output_html'], '</dd>'; |
332 | + } |
|
318 | 333 | |
319 | 334 | echo ' |
320 | 335 | </dl>'; |
@@ -332,9 +347,10 @@ discard block |
||
332 | 347 | <a href="', $scripturl, '?action=profile;u=', $context['id_member'], ';area=', ($context['can_issue_warning'] && !$context['user']['is_owner'] ? 'issuewarning' : 'viewwarning'), '">', $context['member']['warning'], '%</a>'; |
333 | 348 | |
334 | 349 | // Can we provide information on what this means? |
335 | - if (!empty($context['warning_status'])) |
|
336 | - echo ' |
|
350 | + if (!empty($context['warning_status'])) { |
|
351 | + echo ' |
|
337 | 352 | <span class="smalltext">(', $context['warning_status'], ')</span>'; |
353 | + } |
|
338 | 354 | |
339 | 355 | echo ' |
340 | 356 | </dd>'; |
@@ -345,9 +361,10 @@ discard block |
||
345 | 361 | { |
346 | 362 | |
347 | 363 | // If the person looking at the summary has permission, and the account isn't activated, give the viewer the ability to do it themselves. |
348 | - if (!empty($context['activate_message'])) |
|
349 | - echo ' |
|
364 | + if (!empty($context['activate_message'])) { |
|
365 | + echo ' |
|
350 | 366 | <dt class="clear"><span class="alert">', $context['activate_message'], '</span> (<a href="', $context['activate_link'], '"', ($context['activate_type'] == 4 ? ' class="you_sure" data-confirm="' . $txt['profileConfirm'] . '"' : ''), '>', $context['activate_link_text'], '</a>)</dt>'; |
367 | + } |
|
351 | 368 | |
352 | 369 | // If the current member is banned, show a message and possibly a link to the ban. |
353 | 370 | if (!empty($context['member']['bans'])) |
@@ -357,9 +374,10 @@ discard block |
||
357 | 374 | <dt class="clear" id="ban_info" style="display: none;"> |
358 | 375 | <strong>', $txt['user_banned_by_following'], ':</strong>'; |
359 | 376 | |
360 | - foreach ($context['member']['bans'] as $ban) |
|
361 | - echo ' |
|
377 | + foreach ($context['member']['bans'] as $ban) { |
|
378 | + echo ' |
|
362 | 379 | <br><span class="smalltext">', $ban['explanation'], '</span>'; |
380 | + } |
|
363 | 381 | |
364 | 382 | echo ' |
365 | 383 | </dt>'; |
@@ -373,30 +391,34 @@ discard block |
||
373 | 391 | // If the person looking is allowed, they can check the members IP address and hostname. |
374 | 392 | if ($context['can_see_ip']) |
375 | 393 | { |
376 | - if (!empty($context['member']['ip'])) |
|
377 | - echo ' |
|
394 | + if (!empty($context['member']['ip'])) { |
|
395 | + echo ' |
|
378 | 396 | <dt>', $txt['ip'], ': </dt> |
379 | 397 | <dd><a href="', $scripturl, '?action=profile;area=tracking;sa=ip;searchip=', $context['member']['ip'], ';u=', $context['member']['id'], '">', $context['member']['ip'], '</a></dd>'; |
398 | + } |
|
380 | 399 | |
381 | - if (empty($modSettings['disableHostnameLookup']) && !empty($context['member']['ip'])) |
|
382 | - echo ' |
|
400 | + if (empty($modSettings['disableHostnameLookup']) && !empty($context['member']['ip'])) { |
|
401 | + echo ' |
|
383 | 402 | <dt>', $txt['hostname'], ': </dt> |
384 | 403 | <dd>', $context['member']['hostname'], '</dd>'; |
404 | + } |
|
385 | 405 | } |
386 | 406 | |
387 | 407 | echo ' |
388 | 408 | <dt>', $txt['local_time'], ':</dt> |
389 | 409 | <dd>', $context['member']['local_time'], '</dd>'; |
390 | 410 | |
391 | - if (!empty($modSettings['userLanguage']) && !empty($context['member']['language'])) |
|
392 | - echo ' |
|
411 | + if (!empty($modSettings['userLanguage']) && !empty($context['member']['language'])) { |
|
412 | + echo ' |
|
393 | 413 | <dt>', $txt['language'], ':</dt> |
394 | 414 | <dd>', $context['member']['language'], '</dd>'; |
415 | + } |
|
395 | 416 | |
396 | - if ($context['member']['show_last_login']) |
|
397 | - echo ' |
|
417 | + if ($context['member']['show_last_login']) { |
|
418 | + echo ' |
|
398 | 419 | <dt>', $txt['lastLoggedIn'], ': </dt> |
399 | 420 | <dd>', $context['member']['last_login'], (!empty($context['member']['is_hidden']) ? ' (' . $txt['hidden'] . ')' : ''), '</dd>'; |
421 | + } |
|
400 | 422 | |
401 | 423 | echo ' |
402 | 424 | </dl>'; |
@@ -408,10 +430,11 @@ discard block |
||
408 | 430 | <div class="custom_fields_above_signature"> |
409 | 431 | <ul class="nolist">'; |
410 | 432 | |
411 | - foreach ($context['print_custom_fields']['above_signature'] as $field) |
|
412 | - if (!empty($field['output_html'])) |
|
433 | + foreach ($context['print_custom_fields']['above_signature'] as $field) { |
|
434 | + if (!empty($field['output_html'])) |
|
413 | 435 | echo ' |
414 | 436 | <li>', $field['output_html'], '</li>'; |
437 | + } |
|
415 | 438 | |
416 | 439 | echo ' |
417 | 440 | </ul> |
@@ -419,12 +442,13 @@ discard block |
||
419 | 442 | } |
420 | 443 | |
421 | 444 | // Show the users signature. |
422 | - if ($context['signature_enabled'] && !empty($context['member']['signature'])) |
|
423 | - echo ' |
|
445 | + if ($context['signature_enabled'] && !empty($context['member']['signature'])) { |
|
446 | + echo ' |
|
424 | 447 | <div class="signature"> |
425 | 448 | <h5>', $txt['signature'], ':</h5> |
426 | 449 | ', $context['member']['signature'], ' |
427 | 450 | </div>'; |
451 | + } |
|
428 | 452 | |
429 | 453 | // Are there any custom profile fields for below the signature? |
430 | 454 | if (!empty($context['print_custom_fields']['below_signature'])) |
@@ -433,10 +457,11 @@ discard block |
||
433 | 457 | <div class="custom_fields_below_signature"> |
434 | 458 | <ul class="nolist">'; |
435 | 459 | |
436 | - foreach ($context['print_custom_fields']['below_signature'] as $field) |
|
437 | - if (!empty($field['output_html'])) |
|
460 | + foreach ($context['print_custom_fields']['below_signature'] as $field) { |
|
461 | + if (!empty($field['output_html'])) |
|
438 | 462 | echo ' |
439 | 463 | <li>', $field['output_html'], '</li>'; |
464 | + } |
|
440 | 465 | |
441 | 466 | echo ' |
442 | 467 | </ul> |
@@ -481,62 +506,70 @@ discard block |
||
481 | 506 | </div> |
482 | 507 | <div class="list_posts">'; |
483 | 508 | |
484 | - if (!$post['approved']) |
|
485 | - echo ' |
|
509 | + if (!$post['approved']) { |
|
510 | + echo ' |
|
486 | 511 | <div class="approve_post"> |
487 | 512 | <em>', $txt['post_awaiting_approval'], '</em> |
488 | 513 | </div>'; |
514 | + } |
|
489 | 515 | |
490 | 516 | echo ' |
491 | 517 | ', $post['body'], ' |
492 | 518 | </div>'; |
493 | 519 | |
494 | - if ($post['can_reply'] || $post['can_quote'] || $post['can_delete']) |
|
495 | - echo ' |
|
520 | + if ($post['can_reply'] || $post['can_quote'] || $post['can_delete']) { |
|
521 | + echo ' |
|
496 | 522 | <div class="floatright"> |
497 | 523 | <ul class="quickbuttons">'; |
524 | + } |
|
498 | 525 | |
499 | 526 | // If they *can* reply? |
500 | - if ($post['can_reply']) |
|
501 | - echo ' |
|
527 | + if ($post['can_reply']) { |
|
528 | + echo ' |
|
502 | 529 | <li><a href="', $scripturl, '?action=post;topic=', $post['topic'], '.', $post['start'], '"><span class="generic_icons reply_button"></span>', $txt['reply'], '</a></li>'; |
530 | + } |
|
503 | 531 | |
504 | 532 | // If they *can* quote? |
505 | - if ($post['can_quote']) |
|
506 | - echo ' |
|
533 | + if ($post['can_quote']) { |
|
534 | + echo ' |
|
507 | 535 | <li><a href="', $scripturl . '?action=post;topic=', $post['topic'], '.', $post['start'], ';quote=', $post['id'], '"><span class="generic_icons quote"></span>', $txt['quote_action'], '</a></li>'; |
536 | + } |
|
508 | 537 | |
509 | 538 | // How about... even... remove it entirely?! |
510 | - if ($post['can_delete']) |
|
511 | - echo ' |
|
539 | + if ($post['can_delete']) { |
|
540 | + echo ' |
|
512 | 541 | <li><a href="', $scripturl, '?action=deletemsg;msg=', $post['id'], ';topic=', $post['topic'], ';profile;u=', $context['member']['id'], ';start=', $context['start'], ';', $context['session_var'], '=', $context['session_id'], '" data-confirm="', $txt['remove_message'], '" class="you_sure"><span class="generic_icons remove_button"></span>', $txt['remove'], '</a></li>'; |
542 | + } |
|
513 | 543 | |
514 | - if ($post['can_reply'] || $post['can_quote'] || $post['can_delete']) |
|
515 | - echo ' |
|
544 | + if ($post['can_reply'] || $post['can_quote'] || $post['can_delete']) { |
|
545 | + echo ' |
|
516 | 546 | </ul> |
517 | 547 | </div>'; |
548 | + } |
|
518 | 549 | |
519 | 550 | echo ' |
520 | 551 | </div>'; |
521 | 552 | } |
553 | + } else { |
|
554 | + template_show_list('attachments'); |
|
522 | 555 | } |
523 | - else |
|
524 | - template_show_list('attachments'); |
|
525 | 556 | |
526 | 557 | // No posts? Just end with a informative message. |
527 | - if ((isset($context['attachments']) && empty($context['attachments'])) || (!isset($context['attachments']) && empty($context['posts']))) |
|
528 | - echo ' |
|
558 | + if ((isset($context['attachments']) && empty($context['attachments'])) || (!isset($context['attachments']) && empty($context['posts']))) { |
|
559 | + echo ' |
|
529 | 560 | <div class="windowbg2"> |
530 | 561 | ', isset($context['attachments']) ? $txt['show_attachments_none'] : ($context['is_topics'] ? $txt['show_topics_none'] : $txt['show_posts_none']), ' |
531 | 562 | </div>'; |
563 | + } |
|
532 | 564 | |
533 | 565 | // Show more page numbers. |
534 | - if (!empty($context['page_index'])) |
|
535 | - echo ' |
|
566 | + if (!empty($context['page_index'])) { |
|
567 | + echo ' |
|
536 | 568 | <div class="pagesection"> |
537 | 569 | <div class="pagelinks">', $context['page_index'], '</div> |
538 | 570 | </div>'; |
539 | -} |
|
571 | + } |
|
572 | + } |
|
540 | 573 | |
541 | 574 | /** |
542 | 575 | * Template for showing alerts within the alerts popup |
@@ -546,11 +579,12 @@ discard block |
||
546 | 579 | global $context, $txt, $scripturl; |
547 | 580 | |
548 | 581 | // Do we have an update message? |
549 | - if (!empty($context['update_message'])) |
|
550 | - echo ' |
|
582 | + if (!empty($context['update_message'])) { |
|
583 | + echo ' |
|
551 | 584 | <div class="infobox"> |
552 | 585 | ', $context['update_message'], '. |
553 | 586 | </div>'; |
587 | + } |
|
554 | 588 | |
555 | 589 | echo ' |
556 | 590 | <div class="cat_bar"> |
@@ -559,13 +593,12 @@ discard block |
||
559 | 593 | </h3> |
560 | 594 | </div>'; |
561 | 595 | |
562 | - if (empty($context['alerts'])) |
|
563 | - echo ' |
|
596 | + if (empty($context['alerts'])) { |
|
597 | + echo ' |
|
564 | 598 | <div class="information"> |
565 | 599 | ', $txt['alerts_none'], ' |
566 | 600 | </div>'; |
567 | - |
|
568 | - else |
|
601 | + } else |
|
569 | 602 | { |
570 | 603 | // Start the form. |
571 | 604 | echo ' |
@@ -627,12 +660,12 @@ discard block |
||
627 | 660 | </div>' : ''; |
628 | 661 | |
629 | 662 | // No drafts? Just show an informative message. |
630 | - if (empty($context['drafts'])) |
|
631 | - echo ' |
|
663 | + if (empty($context['drafts'])) { |
|
664 | + echo ' |
|
632 | 665 | <div class="windowbg2 centertext"> |
633 | 666 | ', $txt['draft_none'], ' |
634 | 667 | </div>'; |
635 | - else |
|
668 | + } else |
|
636 | 669 | { |
637 | 670 | // For every draft to be displayed, give it its own div, and show the important details of the draft. |
638 | 671 | foreach ($context['drafts'] as $draft) |
@@ -643,11 +676,13 @@ discard block |
||
643 | 676 | <div class="topic_details"> |
644 | 677 | <h5><strong><a href="', $scripturl, '?board=', $draft['board']['id'], '.0">', $draft['board']['name'], '</a> / ', $draft['topic']['link'], '</strong> '; |
645 | 678 | |
646 | - if (!empty($draft['sticky'])) |
|
647 | - echo '<span class="generic_icons sticky" title="', $txt['sticky_topic'], '"></span>'; |
|
679 | + if (!empty($draft['sticky'])) { |
|
680 | + echo '<span class="generic_icons sticky" title="', $txt['sticky_topic'], '"></span>'; |
|
681 | + } |
|
648 | 682 | |
649 | - if (!empty($draft['locked'])) |
|
650 | - echo '<span class="generic_icons lock" title="', $txt['locked_topic'], '"></span>'; |
|
683 | + if (!empty($draft['locked'])) { |
|
684 | + echo '<span class="generic_icons lock" title="', $txt['locked_topic'], '"></span>'; |
|
685 | + } |
|
651 | 686 | |
652 | 687 | echo ' |
653 | 688 | </h5> |
@@ -680,12 +715,13 @@ discard block |
||
680 | 715 | { |
681 | 716 | global $context, $scripturl, $txt; |
682 | 717 | |
683 | - if (!empty($context['saved_successful'])) |
|
684 | - echo ' |
|
718 | + if (!empty($context['saved_successful'])) { |
|
719 | + echo ' |
|
685 | 720 | <div class="infobox">', $context['user']['is_owner'] ? $txt['profile_updated_own'] : sprintf($txt['profile_updated_else'], $context['member']['name']), '</div>'; |
686 | - elseif (!empty($context['saved_failed'])) |
|
687 | - echo ' |
|
721 | + } elseif (!empty($context['saved_failed'])) { |
|
722 | + echo ' |
|
688 | 723 | <div class="errorbox">', $context['saved_failed'], '</div>'; |
724 | + } |
|
689 | 725 | |
690 | 726 | echo ' |
691 | 727 | <div id="edit_buddies"> |
@@ -699,24 +735,27 @@ discard block |
||
699 | 735 | <th scope="col" class="quarter_table">', $txt['name'], '</th> |
700 | 736 | <th scope="col">', $txt['status'], '</th>'; |
701 | 737 | |
702 | - if (allowedTo('moderate_forum')) |
|
703 | - echo ' |
|
738 | + if (allowedTo('moderate_forum')) { |
|
739 | + echo ' |
|
704 | 740 | <th scope="col">', $txt['email'], '</th>'; |
741 | + } |
|
705 | 742 | |
706 | - if (!empty($context['custom_pf'])) |
|
707 | - foreach ($context['custom_pf'] as $column) |
|
743 | + if (!empty($context['custom_pf'])) { |
|
744 | + foreach ($context['custom_pf'] as $column) |
|
708 | 745 | echo '<th scope="col">', $column['label'], '</th>'; |
746 | + } |
|
709 | 747 | |
710 | 748 | echo ' |
711 | 749 | <th scope="col">', $txt['remove'], '</th> |
712 | 750 | </tr>'; |
713 | 751 | |
714 | 752 | // If they don't have any buddies don't list them! |
715 | - if (empty($context['buddies'])) |
|
716 | - echo ' |
|
753 | + if (empty($context['buddies'])) { |
|
754 | + echo ' |
|
717 | 755 | <tr class="windowbg"> |
718 | 756 | <td colspan="', allowedTo('moderate_forum') ? '10' : '9', '"><strong>', $txt['no_buddies'], '</strong></td> |
719 | 757 | </tr>'; |
758 | + } |
|
720 | 759 | |
721 | 760 | // Now loop through each buddy showing info on each. |
722 | 761 | else |
@@ -728,15 +767,17 @@ discard block |
||
728 | 767 | <td>', $buddy['link'], '</td> |
729 | 768 | <td><a href="', $buddy['online']['href'], '"><span class="' . ($buddy['online']['is_online'] == 1 ? 'on' : 'off') . '" title="' . $buddy['online']['text'] . '"></span></a></td>'; |
730 | 769 | |
731 | - if ($buddy['show_email']) |
|
732 | - echo ' |
|
770 | + if ($buddy['show_email']) { |
|
771 | + echo ' |
|
733 | 772 | <td><a href="mailto:' . $buddy['email'] . '" rel="nofollow"><span class="generic_icons mail icon" title="' . $txt['email'] . ' ' . $buddy['name'] . '"></span></a></td>'; |
773 | + } |
|
734 | 774 | |
735 | 775 | // Show the custom profile fields for this user. |
736 | - if (!empty($context['custom_pf'])) |
|
737 | - foreach ($context['custom_pf'] as $key => $column) |
|
776 | + if (!empty($context['custom_pf'])) { |
|
777 | + foreach ($context['custom_pf'] as $key => $column) |
|
738 | 778 | echo ' |
739 | 779 | <td class="lefttext">', $buddy['options'][$key], '</td>'; |
780 | + } |
|
740 | 781 | |
741 | 782 | echo ' |
742 | 783 | <td><a href="', $scripturl, '?action=profile;area=lists;sa=buddies;u=', $context['id_member'], ';remove=', $buddy['id'], ';', $context['session_var'], '=', $context['session_id'], '"><span class="generic_icons delete" title="', $txt['buddy_remove'], '"></span></a></td> |
@@ -766,9 +807,10 @@ discard block |
||
766 | 807 | </dl> |
767 | 808 | </div>'; |
768 | 809 | |
769 | - if (!empty($context['token_check'])) |
|
770 | - echo ' |
|
810 | + if (!empty($context['token_check'])) { |
|
811 | + echo ' |
|
771 | 812 | <input type="hidden" name="', $context[$context['token_check'] . '_token_var'], '" value="', $context[$context['token_check'] . '_token'], '">'; |
813 | + } |
|
772 | 814 | |
773 | 815 | echo ' |
774 | 816 | <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '"> |
@@ -794,12 +836,13 @@ discard block |
||
794 | 836 | { |
795 | 837 | global $context, $scripturl, $txt; |
796 | 838 | |
797 | - if (!empty($context['saved_successful'])) |
|
798 | - echo ' |
|
839 | + if (!empty($context['saved_successful'])) { |
|
840 | + echo ' |
|
799 | 841 | <div class="infobox">', $context['user']['is_owner'] ? $txt['profile_updated_own'] : sprintf($txt['profile_updated_else'], $context['member']['name']), '</div>'; |
800 | - elseif (!empty($context['saved_failed'])) |
|
801 | - echo ' |
|
842 | + } elseif (!empty($context['saved_failed'])) { |
|
843 | + echo ' |
|
802 | 844 | <div class="errorbox">', $context['saved_failed'], '</div>'; |
845 | + } |
|
803 | 846 | |
804 | 847 | echo ' |
805 | 848 | <div id="edit_buddies"> |
@@ -813,20 +856,22 @@ discard block |
||
813 | 856 | <th scope="col" class="quarter_table">', $txt['name'], '</th> |
814 | 857 | <th scope="col">', $txt['status'], '</th>'; |
815 | 858 | |
816 | - if (allowedTo('moderate_forum')) |
|
817 | - echo ' |
|
859 | + if (allowedTo('moderate_forum')) { |
|
860 | + echo ' |
|
818 | 861 | <th scope="col">', $txt['email'], '</th>'; |
862 | + } |
|
819 | 863 | |
820 | 864 | echo ' |
821 | 865 | <th scope="col">', $txt['ignore_remove'], '</th> |
822 | 866 | </tr>'; |
823 | 867 | |
824 | 868 | // If they don't have anyone on their ignore list, don't list it! |
825 | - if (empty($context['ignore_list'])) |
|
826 | - echo ' |
|
869 | + if (empty($context['ignore_list'])) { |
|
870 | + echo ' |
|
827 | 871 | <tr class="windowbg"> |
828 | 872 | <td colspan="', allowedTo('moderate_forum') ? '4' : '3', '"><strong>', $txt['no_ignore'], '</strong></td> |
829 | 873 | </tr>'; |
874 | + } |
|
830 | 875 | |
831 | 876 | // Now loop through each buddy showing info on each. |
832 | 877 | foreach ($context['ignore_list'] as $member) |
@@ -836,9 +881,10 @@ discard block |
||
836 | 881 | <td>', $member['link'], '</td> |
837 | 882 | <td><a href="', $member['online']['href'], '"><span class="' . ($member['online']['is_online'] == 1 ? 'on' : 'off') . '" title="' . $member['online']['text'] . '"></span></a></td>'; |
838 | 883 | |
839 | - if ($member['show_email']) |
|
840 | - echo ' |
|
884 | + if ($member['show_email']) { |
|
885 | + echo ' |
|
841 | 886 | <td><a href="mailto:' . $member['email'] . '" rel="nofollow"><span class="generic_icons mail icon" title="' . $txt['email'] . ' ' . $member['name'] . '"></span></a></td>'; |
887 | + } |
|
842 | 888 | echo ' |
843 | 889 | <td><a href="', $scripturl, '?action=profile;u=', $context['id_member'], ';area=lists;sa=ignore;remove=', $member['id'], ';', $context['session_var'], '=', $context['session_id'], '"><span class="generic_icons delete" title="', $txt['ignore_remove'], '"></span></a></td> |
844 | 890 | </tr>'; |
@@ -865,9 +911,10 @@ discard block |
||
865 | 911 | </dl> |
866 | 912 | </div>'; |
867 | 913 | |
868 | - if (!empty($context['token_check'])) |
|
869 | - echo ' |
|
914 | + if (!empty($context['token_check'])) { |
|
915 | + echo ' |
|
870 | 916 | <input type="hidden" name="', $context[$context['token_check'] . '_token_var'], '" value="', $context[$context['token_check'] . '_token'], '">'; |
917 | + } |
|
871 | 918 | |
872 | 919 | echo ' |
873 | 920 | <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '"> |
@@ -912,9 +959,10 @@ discard block |
||
912 | 959 | <a href="', $scripturl, '?action=profile;area=tracking;sa=ip;searchip=', $context['last_ip'], ';u=', $context['member']['id'], '">', $context['last_ip'], '</a>'; |
913 | 960 | |
914 | 961 | // Second address detected? |
915 | - if (!empty($context['last_ip2'])) |
|
916 | - echo ' |
|
962 | + if (!empty($context['last_ip2'])) { |
|
963 | + echo ' |
|
917 | 964 | , <a href="', $scripturl, '?action=profile;area=tracking;sa=ip;searchip=', $context['last_ip2'], ';u=', $context['member']['id'], '">', $context['last_ip2'], '</a>'; |
965 | + } |
|
918 | 966 | |
919 | 967 | echo ' |
920 | 968 | </dd>'; |
@@ -979,9 +1027,10 @@ discard block |
||
979 | 1027 | <h3 class="catbg">', $txt['whois_title'], ' ', $context['ip'], '</h3> |
980 | 1028 | </div> |
981 | 1029 | <div class="windowbg2 noup">'; |
982 | - foreach ($context['whois_servers'] as $server) |
|
983 | - echo ' |
|
1030 | + foreach ($context['whois_servers'] as $server) { |
|
1031 | + echo ' |
|
984 | 1032 | <a href="', $server['url'], '" target="_blank" class="new_win"', isset($context['auto_whois_server']) && $context['auto_whois_server']['name'] == $server['name'] ? ' style="font-weight: bold;"' : '', '>', $server['name'], '</a><br>'; |
1033 | + } |
|
985 | 1034 | echo ' |
986 | 1035 | </div> |
987 | 1036 | <br>'; |
@@ -992,10 +1041,10 @@ discard block |
||
992 | 1041 | <div class="cat_bar"> |
993 | 1042 | <h3 class="catbg">', $txt['members_from_ip'], ' ', $context['ip'], '</h3> |
994 | 1043 | </div>'; |
995 | - if (empty($context['ips'])) |
|
996 | - echo ' |
|
1044 | + if (empty($context['ips'])) { |
|
1045 | + echo ' |
|
997 | 1046 | <p class="windowbg2 description"><em>', $txt['no_members_from_ip'], '</em></p>'; |
998 | - else |
|
1047 | + } else |
|
999 | 1048 | { |
1000 | 1049 | echo ' |
1001 | 1050 | <table class="table_grid"> |
@@ -1008,12 +1057,13 @@ discard block |
||
1008 | 1057 | <tbody>'; |
1009 | 1058 | |
1010 | 1059 | // Loop through each of the members and display them. |
1011 | - foreach ($context['ips'] as $ip => $memberlist) |
|
1012 | - echo ' |
|
1060 | + foreach ($context['ips'] as $ip => $memberlist) { |
|
1061 | + echo ' |
|
1013 | 1062 | <tr class="windowbg"> |
1014 | 1063 | <td><a href="', $context['base_url'], ';searchip=', $ip, '">', $ip, '</a></td> |
1015 | 1064 | <td>', implode(', ', $memberlist), '</td> |
1016 | 1065 | </tr>'; |
1066 | + } |
|
1017 | 1067 | |
1018 | 1068 | echo ' |
1019 | 1069 | </tbody> |
@@ -1059,8 +1109,7 @@ discard block |
||
1059 | 1109 | { |
1060 | 1110 | echo ' |
1061 | 1111 | <div class="information">', $txt['showPermissions_all'], '</div>'; |
1062 | - } |
|
1063 | - else |
|
1112 | + } else |
|
1064 | 1113 | { |
1065 | 1114 | echo ' |
1066 | 1115 | <div class="information">',$txt['showPermissions_help'], '</div> |
@@ -1074,9 +1123,10 @@ discard block |
||
1074 | 1123 | </div> |
1075 | 1124 | <div class="windowbg smalltext"> |
1076 | 1125 | ', $txt['showPermissions_restricted_boards_desc'], ':<br>'; |
1077 | - foreach ($context['no_access_boards'] as $no_access_board) |
|
1078 | - echo ' |
|
1126 | + foreach ($context['no_access_boards'] as $no_access_board) { |
|
1127 | + echo ' |
|
1079 | 1128 | <a href="', $scripturl, '?board=', $no_access_board['id'], '.0">', $no_access_board['name'], '</a>', $no_access_board['is_last'] ? '' : ', '; |
1129 | + } |
|
1080 | 1130 | echo ' |
1081 | 1131 | </div>'; |
1082 | 1132 | } |
@@ -1108,12 +1158,13 @@ discard block |
||
1108 | 1158 | </td> |
1109 | 1159 | <td class="smalltext">'; |
1110 | 1160 | |
1111 | - if ($permission['is_denied']) |
|
1112 | - echo ' |
|
1161 | + if ($permission['is_denied']) { |
|
1162 | + echo ' |
|
1113 | 1163 | <span class="alert">', $txt['showPermissions_denied'], ': ', implode(', ', $permission['groups']['denied']), '</span>'; |
1114 | - else |
|
1115 | - echo ' |
|
1164 | + } else { |
|
1165 | + echo ' |
|
1116 | 1166 | ', $txt['showPermissions_given'], ': ', implode(', ', $permission['groups']['allowed']); |
1167 | + } |
|
1117 | 1168 | |
1118 | 1169 | echo ' |
1119 | 1170 | </td> |
@@ -1123,10 +1174,10 @@ discard block |
||
1123 | 1174 | </tbody> |
1124 | 1175 | </table> |
1125 | 1176 | </div><br>'; |
1126 | - } |
|
1127 | - else |
|
1128 | - echo ' |
|
1177 | + } else { |
|
1178 | + echo ' |
|
1129 | 1179 | <p class="windowbg2">', $txt['showPermissions_none_general'], '</p>'; |
1180 | + } |
|
1130 | 1181 | |
1131 | 1182 | // Board permission section. |
1132 | 1183 | echo ' |
@@ -1136,14 +1187,16 @@ discard block |
||
1136 | 1187 | <a id="board_permissions"></a>', $txt['showPermissions_select'], ': |
1137 | 1188 | <select name="board" onchange="if (this.options[this.selectedIndex].value) this.form.submit();"> |
1138 | 1189 | <option value="0"', $context['board'] == 0 ? ' selected' : '', '>', $txt['showPermissions_global'], ' </option>'; |
1139 | - if (!empty($context['boards'])) |
|
1140 | - echo ' |
|
1190 | + if (!empty($context['boards'])) { |
|
1191 | + echo ' |
|
1141 | 1192 | <option value="" disabled>---------------------------</option>'; |
1193 | + } |
|
1142 | 1194 | |
1143 | 1195 | // Fill the box with any local permission boards. |
1144 | - foreach ($context['boards'] as $board) |
|
1145 | - echo ' |
|
1196 | + foreach ($context['boards'] as $board) { |
|
1197 | + echo ' |
|
1146 | 1198 | <option value="', $board['id'], '"', $board['selected'] ? ' selected' : '', '>', $board['name'], ' (', $board['profile_name'], ')</option>'; |
1199 | + } |
|
1147 | 1200 | |
1148 | 1201 | echo ' |
1149 | 1202 | </select> |
@@ -1174,8 +1227,7 @@ discard block |
||
1174 | 1227 | { |
1175 | 1228 | echo ' |
1176 | 1229 | <span class="alert">', $txt['showPermissions_denied'], ': ', implode(', ', $permission['groups']['denied']), '</span>'; |
1177 | - } |
|
1178 | - else |
|
1230 | + } else |
|
1179 | 1231 | { |
1180 | 1232 | echo ' |
1181 | 1233 | ', $txt['showPermissions_given'], ': ', implode(', ', $permission['groups']['allowed']); |
@@ -1187,10 +1239,10 @@ discard block |
||
1187 | 1239 | echo ' |
1188 | 1240 | </tbody> |
1189 | 1241 | </table>'; |
1190 | - } |
|
1191 | - else |
|
1192 | - echo ' |
|
1242 | + } else { |
|
1243 | + echo ' |
|
1193 | 1244 | <p class="windowbg2">', $txt['showPermissions_none_board'], '</p>'; |
1245 | + } |
|
1194 | 1246 | echo ' |
1195 | 1247 | </div> |
1196 | 1248 | </div>'; |
@@ -1232,9 +1284,10 @@ discard block |
||
1232 | 1284 | </div>'; |
1233 | 1285 | |
1234 | 1286 | // If they haven't post at all, don't draw the graph. |
1235 | - if (empty($context['posts_by_time'])) |
|
1236 | - echo ' |
|
1287 | + if (empty($context['posts_by_time'])) { |
|
1288 | + echo ' |
|
1237 | 1289 | <p class="centertext padding">', $txt['statPanel_noPosts'], '</p>'; |
1290 | + } |
|
1238 | 1291 | // Otherwise do! |
1239 | 1292 | else |
1240 | 1293 | { |
@@ -1273,11 +1326,10 @@ discard block |
||
1273 | 1326 | </h3> |
1274 | 1327 | </div>'; |
1275 | 1328 | |
1276 | - if (empty($context['popular_boards'])) |
|
1277 | - echo ' |
|
1329 | + if (empty($context['popular_boards'])) { |
|
1330 | + echo ' |
|
1278 | 1331 | <p class="centertext padding">', $txt['statPanel_noPosts'], '</p>'; |
1279 | - |
|
1280 | - else |
|
1332 | + } else |
|
1281 | 1333 | { |
1282 | 1334 | echo ' |
1283 | 1335 | <dl class="stats">'; |
@@ -1308,10 +1360,10 @@ discard block |
||
1308 | 1360 | </h3> |
1309 | 1361 | </div>'; |
1310 | 1362 | |
1311 | - if (empty($context['board_activity'])) |
|
1312 | - echo ' |
|
1363 | + if (empty($context['board_activity'])) { |
|
1364 | + echo ' |
|
1313 | 1365 | <p class="centertext padding">', $txt['statPanel_noPosts'], '</p>'; |
1314 | - else |
|
1366 | + } else |
|
1315 | 1367 | { |
1316 | 1368 | echo ' |
1317 | 1369 | <dl class="stats">'; |
@@ -1359,41 +1411,46 @@ discard block |
||
1359 | 1411 | <h3 class="catbg profile_hd">'; |
1360 | 1412 | |
1361 | 1413 | // Don't say "Profile" if this isn't the profile... |
1362 | - if (!empty($context['profile_header_text'])) |
|
1363 | - echo ' |
|
1414 | + if (!empty($context['profile_header_text'])) { |
|
1415 | + echo ' |
|
1364 | 1416 | ', $context['profile_header_text']; |
1365 | - else |
|
1366 | - echo ' |
|
1417 | + } else { |
|
1418 | + echo ' |
|
1367 | 1419 | ', $txt['profile']; |
1420 | + } |
|
1368 | 1421 | |
1369 | 1422 | echo ' |
1370 | 1423 | </h3> |
1371 | 1424 | </div>'; |
1372 | 1425 | |
1373 | 1426 | // Have we some description? |
1374 | - if ($context['page_desc']) |
|
1375 | - echo ' |
|
1427 | + if ($context['page_desc']) { |
|
1428 | + echo ' |
|
1376 | 1429 | <p class="information">', $context['page_desc'], '</p>'; |
1430 | + } |
|
1377 | 1431 | |
1378 | 1432 | echo ' |
1379 | 1433 | <div class="roundframe">'; |
1380 | 1434 | |
1381 | 1435 | // Any bits at the start? |
1382 | - if (!empty($context['profile_prehtml'])) |
|
1383 | - echo ' |
|
1436 | + if (!empty($context['profile_prehtml'])) { |
|
1437 | + echo ' |
|
1384 | 1438 | <div>', $context['profile_prehtml'], '</div>'; |
1439 | + } |
|
1385 | 1440 | |
1386 | - if (!empty($context['profile_fields'])) |
|
1387 | - echo ' |
|
1441 | + if (!empty($context['profile_fields'])) { |
|
1442 | + echo ' |
|
1388 | 1443 | <dl class="settings">'; |
1444 | + } |
|
1389 | 1445 | |
1390 | 1446 | // Start the big old loop 'of love. |
1391 | 1447 | $lastItem = 'hr'; |
1392 | 1448 | foreach ($context['profile_fields'] as $key => $field) |
1393 | 1449 | { |
1394 | 1450 | // We add a little hack to be sure we never get more than one hr in a row! |
1395 | - if ($lastItem == 'hr' && $field['type'] == 'hr') |
|
1396 | - continue; |
|
1451 | + if ($lastItem == 'hr' && $field['type'] == 'hr') { |
|
1452 | + continue; |
|
1453 | + } |
|
1397 | 1454 | |
1398 | 1455 | $lastItem = $field['type']; |
1399 | 1456 | if ($field['type'] == 'hr') |
@@ -1402,48 +1459,50 @@ discard block |
||
1402 | 1459 | </dl> |
1403 | 1460 | <hr> |
1404 | 1461 | <dl class="settings">'; |
1405 | - } |
|
1406 | - elseif ($field['type'] == 'callback') |
|
1462 | + } elseif ($field['type'] == 'callback') |
|
1407 | 1463 | { |
1408 | 1464 | if (isset($field['callback_func']) && function_exists('template_profile_' . $field['callback_func'])) |
1409 | 1465 | { |
1410 | 1466 | $callback_func = 'template_profile_' . $field['callback_func']; |
1411 | 1467 | $callback_func(); |
1412 | 1468 | } |
1413 | - } |
|
1414 | - else |
|
1469 | + } else |
|
1415 | 1470 | { |
1416 | 1471 | echo ' |
1417 | 1472 | <dt> |
1418 | 1473 | <strong', !empty($field['is_error']) ? ' class="error"' : '', '>', $field['type'] !== 'label' ? '<label for="' . $key . '">' : '', $field['label'], $field['type'] !== 'label' ? '</label>' : '', '</strong>'; |
1419 | 1474 | |
1420 | 1475 | // Does it have any subtext to show? |
1421 | - if (!empty($field['subtext'])) |
|
1422 | - echo ' |
|
1476 | + if (!empty($field['subtext'])) { |
|
1477 | + echo ' |
|
1423 | 1478 | <br> |
1424 | 1479 | <span class="smalltext">', $field['subtext'], '</span>'; |
1480 | + } |
|
1425 | 1481 | |
1426 | 1482 | echo ' |
1427 | 1483 | </dt> |
1428 | 1484 | <dd>'; |
1429 | 1485 | |
1430 | 1486 | // Want to put something infront of the box? |
1431 | - if (!empty($field['preinput'])) |
|
1432 | - echo ' |
|
1487 | + if (!empty($field['preinput'])) { |
|
1488 | + echo ' |
|
1433 | 1489 | ', $field['preinput']; |
1490 | + } |
|
1434 | 1491 | |
1435 | 1492 | // What type of data are we showing? |
1436 | - if ($field['type'] == 'label') |
|
1437 | - echo ' |
|
1493 | + if ($field['type'] == 'label') { |
|
1494 | + echo ' |
|
1438 | 1495 | ', $field['value']; |
1496 | + } |
|
1439 | 1497 | |
1440 | 1498 | // Maybe it's a text box - very likely! |
1441 | 1499 | elseif (in_array($field['type'], array('int', 'float', 'text', 'password', 'color', 'date', 'datetime', 'datetime-local', 'email', 'month', 'number', 'time', 'url'))) |
1442 | 1500 | { |
1443 | - if ($field['type'] == 'int' || $field['type'] == 'float') |
|
1444 | - $type = 'number'; |
|
1445 | - else |
|
1446 | - $type = $field['type']; |
|
1501 | + if ($field['type'] == 'int' || $field['type'] == 'float') { |
|
1502 | + $type = 'number'; |
|
1503 | + } else { |
|
1504 | + $type = $field['type']; |
|
1505 | + } |
|
1447 | 1506 | $step = $field['type'] == 'float' ? ' step="0.1"' : ''; |
1448 | 1507 | |
1449 | 1508 | |
@@ -1451,9 +1510,10 @@ discard block |
||
1451 | 1510 | <input type="', $type, '" name="', $key, '" id="', $key, '" size="', empty($field['size']) ? 30 : $field['size'], '" value="', $field['value'], '" ', $field['input_attr'], ' class="input_', $field['type'] == 'password' ? 'password' : 'text', '"', $step, '>'; |
1452 | 1511 | } |
1453 | 1512 | // You "checking" me out? ;) |
1454 | - elseif ($field['type'] == 'check') |
|
1455 | - echo ' |
|
1513 | + elseif ($field['type'] == 'check') { |
|
1514 | + echo ' |
|
1456 | 1515 | <input type="hidden" name="', $key, '" value="0"><input type="checkbox" name="', $key, '" id="', $key, '"', !empty($field['value']) ? ' checked' : '', ' value="1" class="input_check" ', $field['input_attr'], '>'; |
1516 | + } |
|
1457 | 1517 | |
1458 | 1518 | // Always fun - select boxes! |
1459 | 1519 | elseif ($field['type'] == 'select') |
@@ -1464,13 +1524,15 @@ discard block |
||
1464 | 1524 | if (isset($field['options'])) |
1465 | 1525 | { |
1466 | 1526 | // Is this some code to generate the options? |
1467 | - if (!is_array($field['options'])) |
|
1468 | - $field['options'] = $field['options'](); |
|
1527 | + if (!is_array($field['options'])) { |
|
1528 | + $field['options'] = $field['options'](); |
|
1529 | + } |
|
1469 | 1530 | // Assuming we now have some! |
1470 | - if (is_array($field['options'])) |
|
1471 | - foreach ($field['options'] as $value => $name) |
|
1531 | + if (is_array($field['options'])) { |
|
1532 | + foreach ($field['options'] as $value => $name) |
|
1472 | 1533 | echo ' |
1473 | 1534 | <option value="', $value, '"', $value == $field['value'] ? ' selected' : '', '>', $name, '</option>'; |
1535 | + } |
|
1474 | 1536 | } |
1475 | 1537 | |
1476 | 1538 | echo ' |
@@ -1478,25 +1540,28 @@ discard block |
||
1478 | 1540 | } |
1479 | 1541 | |
1480 | 1542 | // Something to end with? |
1481 | - if (!empty($field['postinput'])) |
|
1482 | - echo ' |
|
1543 | + if (!empty($field['postinput'])) { |
|
1544 | + echo ' |
|
1483 | 1545 | ', $field['postinput']; |
1546 | + } |
|
1484 | 1547 | |
1485 | 1548 | echo ' |
1486 | 1549 | </dd>'; |
1487 | 1550 | } |
1488 | 1551 | } |
1489 | 1552 | |
1490 | - if (!empty($context['profile_fields'])) |
|
1491 | - echo ' |
|
1553 | + if (!empty($context['profile_fields'])) { |
|
1554 | + echo ' |
|
1492 | 1555 | </dl>'; |
1556 | + } |
|
1493 | 1557 | |
1494 | 1558 | // Are there any custom profile fields - if so print them! |
1495 | 1559 | if (!empty($context['custom_fields'])) |
1496 | 1560 | { |
1497 | - if ($lastItem != 'hr') |
|
1498 | - echo ' |
|
1561 | + if ($lastItem != 'hr') { |
|
1562 | + echo ' |
|
1499 | 1563 | <hr>'; |
1564 | + } |
|
1500 | 1565 | |
1501 | 1566 | echo ' |
1502 | 1567 | <dl class="settings">'; |
@@ -1519,13 +1584,14 @@ discard block |
||
1519 | 1584 | } |
1520 | 1585 | |
1521 | 1586 | // Any closing HTML? |
1522 | - if (!empty($context['profile_posthtml'])) |
|
1523 | - echo ' |
|
1587 | + if (!empty($context['profile_posthtml'])) { |
|
1588 | + echo ' |
|
1524 | 1589 | <div>', $context['profile_posthtml'], '</div>'; |
1590 | + } |
|
1525 | 1591 | |
1526 | 1592 | // Only show the password box if it's actually needed. |
1527 | - if ($context['require_password']) |
|
1528 | - echo ' |
|
1593 | + if ($context['require_password']) { |
|
1594 | + echo ' |
|
1529 | 1595 | <dl class="settings"> |
1530 | 1596 | <dt> |
1531 | 1597 | <strong', isset($context['modify_error']['bad_password']) || isset($context['modify_error']['no_password']) ? ' class="error"' : '', '><label for="oldpasswrd">', $txt['current_password'], ': </label></strong><br> |
@@ -1535,18 +1601,21 @@ discard block |
||
1535 | 1601 | <input type="password" name="oldpasswrd" id="oldpasswrd" size="20" style="margin-right: 4ex;" class="input_password"> |
1536 | 1602 | </dd> |
1537 | 1603 | </dl>'; |
1604 | + } |
|
1538 | 1605 | |
1539 | 1606 | // The button shouldn't say "Change profile" unless we're changing the profile... |
1540 | - if (!empty($context['submit_button_text'])) |
|
1541 | - echo ' |
|
1607 | + if (!empty($context['submit_button_text'])) { |
|
1608 | + echo ' |
|
1542 | 1609 | <input type="submit" name="save" value="', $context['submit_button_text'], '" class="button_submit">'; |
1543 | - else |
|
1544 | - echo ' |
|
1610 | + } else { |
|
1611 | + echo ' |
|
1545 | 1612 | <input type="submit" name="save" value="', $txt['change_profile'], '" class="button_submit">'; |
1613 | + } |
|
1546 | 1614 | |
1547 | - if (!empty($context['token_check'])) |
|
1548 | - echo ' |
|
1615 | + if (!empty($context['token_check'])) { |
|
1616 | + echo ' |
|
1549 | 1617 | <input type="hidden" name="', $context[$context['token_check'] . '_token_var'], '" value="', $context[$context['token_check'] . '_token'], '">'; |
1618 | + } |
|
1550 | 1619 | |
1551 | 1620 | echo ' |
1552 | 1621 | <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '"> |
@@ -1556,10 +1625,11 @@ discard block |
||
1556 | 1625 | </form>'; |
1557 | 1626 | |
1558 | 1627 | // Any final spellchecking stuff? |
1559 | - if (!empty($context['show_spellchecking'])) |
|
1560 | - echo ' |
|
1628 | + if (!empty($context['show_spellchecking'])) { |
|
1629 | + echo ' |
|
1561 | 1630 | <form name="spell_form" id="spell_form" method="post" accept-charset="', $context['character_set'], '" target="spellWindow" action="', $scripturl, '?action=spellcheck"><input type="hidden" name="spellstring" value=""></form>'; |
1562 | -} |
|
1631 | + } |
|
1632 | + } |
|
1563 | 1633 | |
1564 | 1634 | /** |
1565 | 1635 | * Personal Message settings. |
@@ -1596,10 +1666,11 @@ discard block |
||
1596 | 1666 | <select name="pm_receive_from" id="pm_receive_from"> |
1597 | 1667 | <option value="0"', empty($context['receive_from']) || (empty($modSettings['enable_buddylist']) && $context['receive_from'] < 3) ? ' selected' : '', '>', $txt['pm_receive_from_everyone'], '</option>'; |
1598 | 1668 | |
1599 | - if (!empty($modSettings['enable_buddylist'])) |
|
1600 | - echo ' |
|
1669 | + if (!empty($modSettings['enable_buddylist'])) { |
|
1670 | + echo ' |
|
1601 | 1671 | <option value="1"', !empty($context['receive_from']) && $context['receive_from'] == 1 ? ' selected' : '', '>', $txt['pm_receive_from_ignore'], '</option> |
1602 | 1672 | <option value="2"', !empty($context['receive_from']) && $context['receive_from'] == 2 ? ' selected' : '', '>', $txt['pm_receive_from_buddies'], '</option>'; |
1673 | + } |
|
1603 | 1674 | |
1604 | 1675 | echo ' |
1605 | 1676 | <option value="3"', !empty($context['receive_from']) && $context['receive_from'] > 2 ? ' selected' : '', '>', $txt['pm_receive_from_admins'], '</option> |
@@ -1641,11 +1712,12 @@ discard block |
||
1641 | 1712 | if (empty($setting) || !is_array($setting)) |
1642 | 1713 | { |
1643 | 1714 | // Insert a separator (unless this is the first item in the list) |
1644 | - if ($i !== $first_option_key) |
|
1645 | - echo ' |
|
1715 | + if ($i !== $first_option_key) { |
|
1716 | + echo ' |
|
1646 | 1717 | </dl> |
1647 | 1718 | <hr> |
1648 | 1719 | <dl class="settings">'; |
1720 | + } |
|
1649 | 1721 | |
1650 | 1722 | // Should we give a name to this section? |
1651 | 1723 | if (is_string($setting) && !empty($setting)) |
@@ -1653,48 +1725,52 @@ discard block |
||
1653 | 1725 | $titled_section = true; |
1654 | 1726 | echo ' |
1655 | 1727 | <dt><b>' . $setting . '</b></dt><dd></dd>'; |
1728 | + } else { |
|
1729 | + $titled_section = false; |
|
1656 | 1730 | } |
1657 | - else |
|
1658 | - $titled_section = false; |
|
1659 | 1731 | |
1660 | 1732 | continue; |
1661 | 1733 | } |
1662 | 1734 | |
1663 | 1735 | // Is this disabled? |
1664 | - if ($setting['id'] == 'calendar_start_day' && empty($modSettings['cal_enabled'])) |
|
1665 | - continue; |
|
1666 | - elseif (($setting['id'] == 'topics_per_page' || $setting['id'] == 'messages_per_page') && !empty($modSettings['disableCustomPerPage'])) |
|
1667 | - continue; |
|
1668 | - elseif ($setting['id'] == 'show_no_censored' && empty($modSettings['allow_no_censored'])) |
|
1669 | - continue; |
|
1670 | - elseif ($setting['id'] == 'posts_apply_ignore_list' && empty($modSettings['enable_buddylist'])) |
|
1671 | - continue; |
|
1672 | - elseif ($setting['id'] == 'wysiwyg_default' && !empty($modSettings['disable_wysiwyg'])) |
|
1673 | - continue; |
|
1674 | - elseif ($setting['id'] == 'topics_per_page' && !empty($modSettings['disableCustomPerPage'])) |
|
1675 | - continue; |
|
1676 | - elseif ($setting['id'] == 'drafts_autosave_enabled' && (empty($modSettings['drafts_autosave_enabled']) || (empty($modSettings['drafts_post_enabled']) && empty($modSettings['drafts_pm_enabled'])))) |
|
1677 | - continue; |
|
1678 | - elseif ($setting['id'] == 'drafts_show_saved_enabled' && (empty($modSettings['drafts_show_saved_enabled']) || (empty($modSettings['drafts_post_enabled']) && empty($modSettings['drafts_pm_enabled'])))) |
|
1679 | - continue; |
|
1736 | + if ($setting['id'] == 'calendar_start_day' && empty($modSettings['cal_enabled'])) { |
|
1737 | + continue; |
|
1738 | + } elseif (($setting['id'] == 'topics_per_page' || $setting['id'] == 'messages_per_page') && !empty($modSettings['disableCustomPerPage'])) { |
|
1739 | + continue; |
|
1740 | + } elseif ($setting['id'] == 'show_no_censored' && empty($modSettings['allow_no_censored'])) { |
|
1741 | + continue; |
|
1742 | + } elseif ($setting['id'] == 'posts_apply_ignore_list' && empty($modSettings['enable_buddylist'])) { |
|
1743 | + continue; |
|
1744 | + } elseif ($setting['id'] == 'wysiwyg_default' && !empty($modSettings['disable_wysiwyg'])) { |
|
1745 | + continue; |
|
1746 | + } elseif ($setting['id'] == 'topics_per_page' && !empty($modSettings['disableCustomPerPage'])) { |
|
1747 | + continue; |
|
1748 | + } elseif ($setting['id'] == 'drafts_autosave_enabled' && (empty($modSettings['drafts_autosave_enabled']) || (empty($modSettings['drafts_post_enabled']) && empty($modSettings['drafts_pm_enabled'])))) { |
|
1749 | + continue; |
|
1750 | + } elseif ($setting['id'] == 'drafts_show_saved_enabled' && (empty($modSettings['drafts_show_saved_enabled']) || (empty($modSettings['drafts_post_enabled']) && empty($modSettings['drafts_pm_enabled'])))) { |
|
1751 | + continue; |
|
1752 | + } |
|
1680 | 1753 | |
1681 | - if (!isset($setting['type']) || $setting['type'] == 'bool') |
|
1682 | - $setting['type'] = 'checkbox'; |
|
1683 | - elseif ($setting['type'] == 'int' || $setting['type'] == 'integer') |
|
1684 | - $setting['type'] = 'number'; |
|
1685 | - elseif ($setting['type'] == 'string') |
|
1686 | - $setting['type'] = 'text'; |
|
1754 | + if (!isset($setting['type']) || $setting['type'] == 'bool') { |
|
1755 | + $setting['type'] = 'checkbox'; |
|
1756 | + } elseif ($setting['type'] == 'int' || $setting['type'] == 'integer') { |
|
1757 | + $setting['type'] = 'number'; |
|
1758 | + } elseif ($setting['type'] == 'string') { |
|
1759 | + $setting['type'] = 'text'; |
|
1760 | + } |
|
1687 | 1761 | |
1688 | - if (isset($setting['options'])) |
|
1689 | - $setting['type'] = 'list'; |
|
1762 | + if (isset($setting['options'])) { |
|
1763 | + $setting['type'] = 'list'; |
|
1764 | + } |
|
1690 | 1765 | |
1691 | 1766 | echo ' |
1692 | 1767 | <dt> |
1693 | 1768 | <label for="', $setting['id'], '">', !$titled_section ? '<b>' : '', $setting['label'], !$titled_section ? '</b>' : '', '</label>'; |
1694 | 1769 | |
1695 | - if (isset($setting['description'])) |
|
1696 | - echo ' |
|
1770 | + if (isset($setting['description'])) { |
|
1771 | + echo ' |
|
1697 | 1772 | <br><span class="smalltext">', $setting['description'], '</span>'; |
1773 | + } |
|
1698 | 1774 | echo ' |
1699 | 1775 | </dt> |
1700 | 1776 | <dd>'; |
@@ -1732,13 +1808,11 @@ discard block |
||
1732 | 1808 | |
1733 | 1809 | echo ' |
1734 | 1810 | <input type="number"', $min . $max . $step; |
1735 | - } |
|
1736 | - else if (isset($setting['type']) && $setting['type'] == 'url') |
|
1811 | + } else if (isset($setting['type']) && $setting['type'] == 'url') |
|
1737 | 1812 | { |
1738 | 1813 | echo' |
1739 | 1814 | <input type="url"'; |
1740 | - } |
|
1741 | - else |
|
1815 | + } else |
|
1742 | 1816 | { |
1743 | 1817 | echo ' |
1744 | 1818 | <input type="text"'; |
@@ -1777,8 +1851,8 @@ discard block |
||
1777 | 1851 | <dl class="settings">'; |
1778 | 1852 | |
1779 | 1853 | // Allow notification on announcements to be disabled? |
1780 | - if (!empty($modSettings['allow_disableAnnounce'])) |
|
1781 | - echo ' |
|
1854 | + if (!empty($modSettings['allow_disableAnnounce'])) { |
|
1855 | + echo ' |
|
1782 | 1856 | <dt> |
1783 | 1857 | <label for="notify_announcements">', $txt['notify_important_email'], '</label> |
1784 | 1858 | </dt> |
@@ -1786,9 +1860,10 @@ discard block |
||
1786 | 1860 | <input type="hidden" name="notify_announcements" value="0"> |
1787 | 1861 | <input type="checkbox" id="notify_announcements" name="notify_announcements" value="1"', !empty($context['member']['notify_announcements']) ? ' checked' : '', ' class="input_check"> |
1788 | 1862 | </dd>'; |
1863 | + } |
|
1789 | 1864 | |
1790 | - if (!empty($modSettings['enable_ajax_alerts'])) |
|
1791 | - echo ' |
|
1865 | + if (!empty($modSettings['enable_ajax_alerts'])) { |
|
1866 | + echo ' |
|
1792 | 1867 | <dt> |
1793 | 1868 | <label for="notify_send_body">', $txt['notify_alert_timeout'], '</label> |
1794 | 1869 | </dt> |
@@ -1796,6 +1871,7 @@ discard block |
||
1796 | 1871 | <input type="number" size="4" id="notify_alert_timeout" name="opt_alert_timeout" min="0" value="', $context['member']['alert_timeout'], '" class="input_text"> |
1797 | 1872 | </dd> |
1798 | 1873 | '; |
1874 | + } |
|
1799 | 1875 | |
1800 | 1876 | echo ' |
1801 | 1877 | </dl> |
@@ -1825,9 +1901,10 @@ discard block |
||
1825 | 1901 | <td colspan="3">'; |
1826 | 1902 | $label = $txt['alert_opt_' . $opts[1]]; |
1827 | 1903 | $label_pos = isset($opts['label']) ? $opts['label'] : ''; |
1828 | - if ($label_pos == 'before') |
|
1829 | - echo ' |
|
1904 | + if ($label_pos == 'before') { |
|
1905 | + echo ' |
|
1830 | 1906 | <label for="opt_', $opts[1], '">', $label, '</label>'; |
1907 | + } |
|
1831 | 1908 | |
1832 | 1909 | $this_value = isset($context['alert_prefs'][$opts[1]]) ? $context['alert_prefs'][$opts[1]] : 0; |
1833 | 1910 | switch ($opts[0]) |
@@ -1839,17 +1916,19 @@ discard block |
||
1839 | 1916 | case 'select': |
1840 | 1917 | echo ' |
1841 | 1918 | <select name="opt_', $opts[1], '" id="opt_', $opts[1], '">'; |
1842 | - foreach ($opts['opts'] as $k => $v) |
|
1843 | - echo ' |
|
1919 | + foreach ($opts['opts'] as $k => $v) { |
|
1920 | + echo ' |
|
1844 | 1921 | <option value="', $k, '"', $this_value == $k ? ' selected' : '', '>', $v, '</option>'; |
1922 | + } |
|
1845 | 1923 | echo ' |
1846 | 1924 | </select>'; |
1847 | 1925 | break; |
1848 | 1926 | } |
1849 | 1927 | |
1850 | - if ($label_pos == 'after') |
|
1851 | - echo ' |
|
1928 | + if ($label_pos == 'after') { |
|
1929 | + echo ' |
|
1852 | 1930 | <label for="opt_', $opts[1], '">', $label, '</label>'; |
1931 | + } |
|
1853 | 1932 | |
1854 | 1933 | echo ' |
1855 | 1934 | </td> |
@@ -1963,11 +2042,12 @@ discard block |
||
1963 | 2042 | <p class="information">', $txt['groupMembership_info'], '</p>'; |
1964 | 2043 | |
1965 | 2044 | // Do we have an update message? |
1966 | - if (!empty($context['update_message'])) |
|
1967 | - echo ' |
|
2045 | + if (!empty($context['update_message'])) { |
|
2046 | + echo ' |
|
1968 | 2047 | <div class="infobox"> |
1969 | 2048 | ', $context['update_message'], '. |
1970 | 2049 | </div>'; |
2050 | + } |
|
1971 | 2051 | |
1972 | 2052 | echo ' |
1973 | 2053 | <div id="groups">'; |
@@ -1989,8 +2069,7 @@ discard block |
||
1989 | 2069 | </div> |
1990 | 2070 | </div> |
1991 | 2071 | </div>'; |
1992 | - } |
|
1993 | - else |
|
2072 | + } else |
|
1994 | 2073 | { |
1995 | 2074 | echo ' |
1996 | 2075 | <div class="title_bar"> |
@@ -2002,27 +2081,30 @@ discard block |
||
2002 | 2081 | echo ' |
2003 | 2082 | <div class="windowbg" id="primdiv_', $group['id'], '">'; |
2004 | 2083 | |
2005 | - if ($context['can_edit_primary']) |
|
2006 | - echo ' |
|
2084 | + if ($context['can_edit_primary']) { |
|
2085 | + echo ' |
|
2007 | 2086 | <input type="radio" name="primary" id="primary_', $group['id'], '" value="', $group['id'], '"', $group['is_primary'] ? ' checked' : '', ' onclick="highlightSelected(\'primdiv_' . $group['id'] . '\');"', $group['can_be_primary'] ? '' : ' disabled', ' class="input_radio">'; |
2087 | + } |
|
2008 | 2088 | |
2009 | 2089 | echo ' |
2010 | 2090 | <label for="primary_', $group['id'], '"><strong>', (empty($group['color']) ? $group['name'] : '<span style="color: ' . $group['color'] . '">' . $group['name'] . '</span>'), '</strong>', (!empty($group['desc']) ? '<br><span class="smalltext">' . $group['desc'] . '</span>' : ''), '</label>'; |
2011 | 2091 | |
2012 | 2092 | // Can they leave their group? |
2013 | - if ($group['can_leave']) |
|
2014 | - echo ' |
|
2093 | + if ($group['can_leave']) { |
|
2094 | + echo ' |
|
2015 | 2095 | <a href="' . $scripturl . '?action=profile;save;u=' . $context['id_member'] . ';area=groupmembership;' . $context['session_var'] . '=' . $context['session_id'] . ';gid=' . $group['id'] . ';', $context[$context['token_check'] . '_token_var'], '=', $context[$context['token_check'] . '_token'], '">' . $txt['leave_group'] . '</a>'; |
2096 | + } |
|
2016 | 2097 | |
2017 | 2098 | echo ' |
2018 | 2099 | </div>'; |
2019 | 2100 | } |
2020 | 2101 | |
2021 | - if ($context['can_edit_primary']) |
|
2022 | - echo ' |
|
2102 | + if ($context['can_edit_primary']) { |
|
2103 | + echo ' |
|
2023 | 2104 | <div class="padding righttext"> |
2024 | 2105 | <input type="submit" value="', $txt['make_primary'], '" class="button_submit"> |
2025 | 2106 | </div>'; |
2107 | + } |
|
2026 | 2108 | |
2027 | 2109 | // Any groups they can join? |
2028 | 2110 | if (!empty($context['groups']['available'])) |
@@ -2038,15 +2120,16 @@ discard block |
||
2038 | 2120 | <div class="windowbg"> |
2039 | 2121 | <strong>', (empty($group['color']) ? $group['name'] : '<span style="color: ' . $group['color'] . '">' . $group['name'] . '</span>'), '</strong>', (!empty($group['desc']) ? '<br><span class="smalltext">' . $group['desc'] . '</span>' : ''), ''; |
2040 | 2122 | |
2041 | - if ($group['type'] == 3) |
|
2042 | - echo ' |
|
2123 | + if ($group['type'] == 3) { |
|
2124 | + echo ' |
|
2043 | 2125 | <a href="', $scripturl, '?action=profile;save;u=', $context['id_member'], ';area=groupmembership;', $context['session_var'], '=', $context['session_id'], ';gid=', $group['id'], ';', $context[$context['token_check'] . '_token_var'], '=', $context[$context['token_check'] . '_token'], '" class="button floatright">', $txt['join_group'], '</a>'; |
2044 | - elseif ($group['type'] == 2 && $group['pending']) |
|
2045 | - echo ' |
|
2126 | + } elseif ($group['type'] == 2 && $group['pending']) { |
|
2127 | + echo ' |
|
2046 | 2128 | <span class="floatright">', $txt['approval_pending'], '</span>'; |
2047 | - elseif ($group['type'] == 2) |
|
2048 | - echo ' |
|
2129 | + } elseif ($group['type'] == 2) { |
|
2130 | + echo ' |
|
2049 | 2131 | <a href="', $scripturl, '?action=profile;u=', $context['id_member'], ';area=groupmembership;request=', $group['id'], '" class="button floatright">', $txt['request_group'], '</a>'; |
2132 | + } |
|
2050 | 2133 | |
2051 | 2134 | echo ' |
2052 | 2135 | </div>'; |
@@ -2069,9 +2152,10 @@ discard block |
||
2069 | 2152 | |
2070 | 2153 | prevDiv.className = "windowbg"; |
2071 | 2154 | }'; |
2072 | - if (isset($context['groups']['member'][$context['primary_group']])) |
|
2073 | - echo ' |
|
2155 | + if (isset($context['groups']['member'][$context['primary_group']])) { |
|
2156 | + echo ' |
|
2074 | 2157 | highlightSelected("primdiv_' . $context['primary_group'] . '");'; |
2158 | + } |
|
2075 | 2159 | echo ' |
2076 | 2160 | </script>'; |
2077 | 2161 | } |
@@ -2079,9 +2163,10 @@ discard block |
||
2079 | 2163 | echo ' |
2080 | 2164 | </div>'; |
2081 | 2165 | |
2082 | - if (!empty($context['token_check'])) |
|
2083 | - echo ' |
|
2166 | + if (!empty($context['token_check'])) { |
|
2167 | + echo ' |
|
2084 | 2168 | <input type="hidden" name="', $context[$context['token_check'] . '_token_var'], '" value="', $context[$context['token_check'] . '_token'], '">'; |
2169 | + } |
|
2085 | 2170 | |
2086 | 2171 | echo ' |
2087 | 2172 | <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '"> |
@@ -2128,14 +2213,15 @@ discard block |
||
2128 | 2213 | |
2129 | 2214 | foreach ($category['boards'] as $board) |
2130 | 2215 | { |
2131 | - if ($i == $limit) |
|
2132 | - echo ' |
|
2216 | + if ($i == $limit) { |
|
2217 | + echo ' |
|
2133 | 2218 | </ul> |
2134 | 2219 | </li> |
2135 | 2220 | </ul> |
2136 | 2221 | <ul class="ignoreboards floatright"> |
2137 | 2222 | <li class="category"> |
2138 | 2223 | <ul>'; |
2224 | + } |
|
2139 | 2225 | |
2140 | 2226 | echo ' |
2141 | 2227 | <li class="board" style="margin-', $context['right_to_left'] ? 'right' : 'left', ': ', $board['child_level'], 'em;"> |
@@ -2181,10 +2267,11 @@ discard block |
||
2181 | 2267 | |
2182 | 2268 | // Work out the starting color. |
2183 | 2269 | $context['current_color'] = $context['colors'][0]; |
2184 | - foreach ($context['colors'] as $limit => $color) |
|
2185 | - if ($context['member']['warning'] >= $limit) |
|
2270 | + foreach ($context['colors'] as $limit => $color) { |
|
2271 | + if ($context['member']['warning'] >= $limit) |
|
2186 | 2272 | $context['current_color'] = $color; |
2187 | -} |
|
2273 | + } |
|
2274 | + } |
|
2188 | 2275 | |
2189 | 2276 | // Show all warnings of a user? |
2190 | 2277 | function template_viewWarning() |
@@ -2223,14 +2310,15 @@ discard block |
||
2223 | 2310 | </dd>'; |
2224 | 2311 | |
2225 | 2312 | // There's some impact of this? |
2226 | - if (!empty($context['level_effects'][$context['current_level']])) |
|
2227 | - echo ' |
|
2313 | + if (!empty($context['level_effects'][$context['current_level']])) { |
|
2314 | + echo ' |
|
2228 | 2315 | <dt> |
2229 | 2316 | <strong>', $txt['profile_viewwarning_impact'], ':</strong> |
2230 | 2317 | </dt> |
2231 | 2318 | <dd> |
2232 | 2319 | ', $context['level_effects'][$context['current_level']], ' |
2233 | 2320 | </dd>'; |
2321 | + } |
|
2234 | 2322 | |
2235 | 2323 | echo ' |
2236 | 2324 | </dl> |
@@ -2268,10 +2356,11 @@ discard block |
||
2268 | 2356 | |
2269 | 2357 | // Otherwise see what we can do...'; |
2270 | 2358 | |
2271 | - foreach ($context['notification_templates'] as $k => $type) |
|
2272 | - echo ' |
|
2359 | + foreach ($context['notification_templates'] as $k => $type) { |
|
2360 | + echo ' |
|
2273 | 2361 | if (index == ', $k, ') |
2274 | 2362 | document.getElementById(\'warn_body\').value = "', strtr($type['body'], array('"' => "'", "\n" => '\\n', "\r" => '')), '";'; |
2363 | + } |
|
2275 | 2364 | |
2276 | 2365 | echo ' |
2277 | 2366 | } |
@@ -2281,10 +2370,11 @@ discard block |
||
2281 | 2370 | // Also set the right effect. |
2282 | 2371 | effectText = "";'; |
2283 | 2372 | |
2284 | - foreach ($context['level_effects'] as $limit => $text) |
|
2285 | - echo ' |
|
2373 | + foreach ($context['level_effects'] as $limit => $text) { |
|
2374 | + echo ' |
|
2286 | 2375 | if (slideAmount >= ', $limit, ') |
2287 | 2376 | effectText = "', $text, '";'; |
2377 | + } |
|
2288 | 2378 | |
2289 | 2379 | echo ' |
2290 | 2380 | setInnerHTML(document.getElementById(\'cur_level_div\'), slideAmount + \'% (\' + effectText + \')\'); |
@@ -2299,31 +2389,34 @@ discard block |
||
2299 | 2389 | </h3> |
2300 | 2390 | </div>'; |
2301 | 2391 | |
2302 | - if (!$context['user']['is_owner']) |
|
2303 | - echo ' |
|
2392 | + if (!$context['user']['is_owner']) { |
|
2393 | + echo ' |
|
2304 | 2394 | <p class="information">', $txt['profile_warning_desc'], '</p>'; |
2395 | + } |
|
2305 | 2396 | |
2306 | 2397 | echo ' |
2307 | 2398 | <div class="windowbg"> |
2308 | 2399 | <dl class="settings">'; |
2309 | 2400 | |
2310 | - if (!$context['user']['is_owner']) |
|
2311 | - echo ' |
|
2401 | + if (!$context['user']['is_owner']) { |
|
2402 | + echo ' |
|
2312 | 2403 | <dt> |
2313 | 2404 | <strong>', $txt['profile_warning_name'], ':</strong> |
2314 | 2405 | </dt> |
2315 | 2406 | <dd> |
2316 | 2407 | <strong>', $context['member']['name'], '</strong> |
2317 | 2408 | </dd>'; |
2409 | + } |
|
2318 | 2410 | |
2319 | 2411 | echo ' |
2320 | 2412 | <dt> |
2321 | 2413 | <strong>', $txt['profile_warning_level'], ':</strong>'; |
2322 | 2414 | |
2323 | 2415 | // Is there only so much they can apply? |
2324 | - if ($context['warning_limit']) |
|
2325 | - echo ' |
|
2416 | + if ($context['warning_limit']) { |
|
2417 | + echo ' |
|
2326 | 2418 | <br><span class="smalltext">', sprintf($txt['profile_warning_limit_attribute'], $context['warning_limit']), '</span>'; |
2419 | + } |
|
2327 | 2420 | |
2328 | 2421 | echo ' |
2329 | 2422 | </dt> |
@@ -2376,9 +2469,10 @@ discard block |
||
2376 | 2469 | <option value="-1">', $txt['profile_warning_notify_template'], '</option> |
2377 | 2470 | <option value="-1" disabled>------------------------------</option>'; |
2378 | 2471 | |
2379 | - foreach ($context['notification_templates'] as $id_template => $template) |
|
2380 | - echo ' |
|
2472 | + foreach ($context['notification_templates'] as $id_template => $template) { |
|
2473 | + echo ' |
|
2381 | 2474 | <option value="', $id_template, '">', $template['title'], '</option>'; |
2475 | + } |
|
2382 | 2476 | |
2383 | 2477 | echo ' |
2384 | 2478 | </select> |
@@ -2390,9 +2484,10 @@ discard block |
||
2390 | 2484 | </dl> |
2391 | 2485 | <div class="righttext">'; |
2392 | 2486 | |
2393 | - if (!empty($context['token_check'])) |
|
2394 | - echo ' |
|
2487 | + if (!empty($context['token_check'])) { |
|
2488 | + echo ' |
|
2395 | 2489 | <input type="hidden" name="', $context[$context['token_check'] . '_token_var'], '" value="', $context[$context['token_check'] . '_token'], '">'; |
2490 | + } |
|
2396 | 2491 | |
2397 | 2492 | echo ' |
2398 | 2493 | <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '"> |
@@ -2408,8 +2503,8 @@ discard block |
||
2408 | 2503 | echo ' |
2409 | 2504 | <script>'; |
2410 | 2505 | |
2411 | - if (!$context['user']['is_owner']) |
|
2412 | - echo ' |
|
2506 | + if (!$context['user']['is_owner']) { |
|
2507 | + echo ' |
|
2413 | 2508 | modifyWarnNotify(); |
2414 | 2509 | $(document).ready(function() { |
2415 | 2510 | $("#preview_button").click(function() { |
@@ -2448,6 +2543,7 @@ discard block |
||
2448 | 2543 | }); |
2449 | 2544 | return false; |
2450 | 2545 | }'; |
2546 | + } |
|
2451 | 2547 | |
2452 | 2548 | echo ' |
2453 | 2549 | </script>'; |
@@ -2470,16 +2566,18 @@ discard block |
||
2470 | 2566 | </div>'; |
2471 | 2567 | |
2472 | 2568 | // If deleting another account give them a lovely info box. |
2473 | - if (!$context['user']['is_owner']) |
|
2474 | - echo ' |
|
2569 | + if (!$context['user']['is_owner']) { |
|
2570 | + echo ' |
|
2475 | 2571 | <p class="information">', $txt['deleteAccount_desc'], '</p>'; |
2572 | + } |
|
2476 | 2573 | echo ' |
2477 | 2574 | <div class="windowbg2">'; |
2478 | 2575 | |
2479 | 2576 | // If they are deleting their account AND the admin needs to approve it - give them another piece of info ;) |
2480 | - if ($context['needs_approval']) |
|
2481 | - echo ' |
|
2577 | + if ($context['needs_approval']) { |
|
2578 | + echo ' |
|
2482 | 2579 | <div class="errorbox">', $txt['deleteAccount_approval'], '</div>'; |
2580 | + } |
|
2483 | 2581 | |
2484 | 2582 | // If the user is deleting their own account warn them first - and require a password! |
2485 | 2583 | if ($context['user']['is_owner']) |
@@ -2491,9 +2589,10 @@ discard block |
||
2491 | 2589 | <input type="password" name="oldpasswrd" size="20" class="input_password"> |
2492 | 2590 | <input type="submit" value="', $txt['yes'], '" class="button_submit">'; |
2493 | 2591 | |
2494 | - if (!empty($context['token_check'])) |
|
2495 | - echo ' |
|
2592 | + if (!empty($context['token_check'])) { |
|
2593 | + echo ' |
|
2496 | 2594 | <input type="hidden" name="', $context[$context['token_check'] . '_token_var'], '" value="', $context[$context['token_check'] . '_token'], '">'; |
2595 | + } |
|
2497 | 2596 | |
2498 | 2597 | echo ' |
2499 | 2598 | <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '"> |
@@ -2519,9 +2618,10 @@ discard block |
||
2519 | 2618 | <option value="topics">', $txt['deleteAccount_topics'], '</option> |
2520 | 2619 | </select>'; |
2521 | 2620 | |
2522 | - if ($context['show_perma_delete']) |
|
2523 | - echo ' |
|
2621 | + if ($context['show_perma_delete']) { |
|
2622 | + echo ' |
|
2524 | 2623 | <br><label for="perma_delete"><input type="checkbox" name="perma_delete" id="perma_delete" value="1" class="input_check">', $txt['deleteAccount_permanent'], ':</label>'; |
2624 | + } |
|
2525 | 2625 | |
2526 | 2626 | echo ' |
2527 | 2627 | </div>'; |
@@ -2534,9 +2634,10 @@ discard block |
||
2534 | 2634 | <div> |
2535 | 2635 | <input type="submit" value="', $txt['delete'], '" class="button_submit">'; |
2536 | 2636 | |
2537 | - if (!empty($context['token_check'])) |
|
2538 | - echo ' |
|
2637 | + if (!empty($context['token_check'])) { |
|
2638 | + echo ' |
|
2539 | 2639 | <input type="hidden" name="', $context[$context['token_check'] . '_token_var'], '" value="', $context[$context['token_check'] . '_token'], '">'; |
2640 | + } |
|
2540 | 2641 | |
2541 | 2642 | echo ' |
2542 | 2643 | <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '"> |
@@ -2562,8 +2663,8 @@ discard block |
||
2562 | 2663 | <hr>'; |
2563 | 2664 | |
2564 | 2665 | // Only show the password box if it's actually needed. |
2565 | - if ($context['require_password']) |
|
2566 | - echo ' |
|
2666 | + if ($context['require_password']) { |
|
2667 | + echo ' |
|
2567 | 2668 | <dl class="settings"> |
2568 | 2669 | <dt> |
2569 | 2670 | <strong', isset($context['modify_error']['bad_password']) || isset($context['modify_error']['no_password']) ? ' class="error"' : '', '>', $txt['current_password'], ': </strong><br> |
@@ -2573,13 +2674,15 @@ discard block |
||
2573 | 2674 | <input type="password" name="oldpasswrd" size="20" style="margin-right: 4ex;" class="input_password"> |
2574 | 2675 | </dd> |
2575 | 2676 | </dl>'; |
2677 | + } |
|
2576 | 2678 | |
2577 | 2679 | echo ' |
2578 | 2680 | <div class="righttext">'; |
2579 | 2681 | |
2580 | - if (!empty($context['token_check'])) |
|
2581 | - echo ' |
|
2682 | + if (!empty($context['token_check'])) { |
|
2683 | + echo ' |
|
2582 | 2684 | <input type="hidden" name="', $context[$context['token_check'] . '_token_var'], '" value="', $context[$context['token_check'] . '_token'], '">'; |
2685 | + } |
|
2583 | 2686 | |
2584 | 2687 | echo ' |
2585 | 2688 | <input type="submit" value="', $txt['change_profile'], '" class="button_submit"> |
@@ -2606,9 +2709,10 @@ discard block |
||
2606 | 2709 | <ul id="list_errors">'; |
2607 | 2710 | |
2608 | 2711 | // Cycle through each error and display an error message. |
2609 | - foreach ($context['post_errors'] as $error) |
|
2610 | - echo ' |
|
2712 | + foreach ($context['post_errors'] as $error) { |
|
2713 | + echo ' |
|
2611 | 2714 | <li>', isset($txt['profile_error_' . $error]) ? $txt['profile_error_' . $error] : $error, '</li>'; |
2715 | + } |
|
2612 | 2716 | |
2613 | 2717 | echo ' |
2614 | 2718 | </ul>'; |
@@ -2634,12 +2738,13 @@ discard block |
||
2634 | 2738 | <select name="id_group" ', ($context['user']['is_owner'] && $context['member']['group_id'] == 1 ? 'onchange="if (this.value != 1 && !confirm(\'' . $txt['deadmin_confirm'] . '\')) this.value = 1;"' : ''), '>'; |
2635 | 2739 | |
2636 | 2740 | // Fill the select box with all primary member groups that can be assigned to a member. |
2637 | - foreach ($context['member_groups'] as $member_group) |
|
2638 | - if (!empty($member_group['can_be_primary'])) |
|
2741 | + foreach ($context['member_groups'] as $member_group) { |
|
2742 | + if (!empty($member_group['can_be_primary'])) |
|
2639 | 2743 | echo ' |
2640 | 2744 | <option value="', $member_group['id'], '"', $member_group['is_primary'] ? ' selected' : '', '> |
2641 | 2745 | ', $member_group['name'], ' |
2642 | 2746 | </option>'; |
2747 | + } |
|
2643 | 2748 | echo ' |
2644 | 2749 | </select> |
2645 | 2750 | </dd> |
@@ -2651,10 +2756,11 @@ discard block |
||
2651 | 2756 | <input type="hidden" name="additional_groups[]" value="0">'; |
2652 | 2757 | |
2653 | 2758 | // For each membergroup show a checkbox so members can be assigned to more than one group. |
2654 | - foreach ($context['member_groups'] as $member_group) |
|
2655 | - if ($member_group['can_be_additional']) |
|
2759 | + foreach ($context['member_groups'] as $member_group) { |
|
2760 | + if ($member_group['can_be_additional']) |
|
2656 | 2761 | echo ' |
2657 | 2762 | <label for="additional_groups-', $member_group['id'], '"><input type="checkbox" name="additional_groups[]" value="', $member_group['id'], '" id="additional_groups-', $member_group['id'], '"', $member_group['is_additional'] ? ' checked' : '', ' class="input_check"> ', $member_group['name'], '</label><br>'; |
2763 | + } |
|
2658 | 2764 | echo ' |
2659 | 2765 | </span> |
2660 | 2766 | <a href="javascript:void(0);" onclick="document.getElementById(\'additional_groupsList\').style.display = \'block\'; document.getElementById(\'additional_groupsLink\').style.display = \'none\'; return false;" id="additional_groupsLink" style="display: none;" class="toggle_down">', $txt['additional_membergroups_show'], '</a> |
@@ -2714,9 +2820,10 @@ discard block |
||
2714 | 2820 | <span class="smalltext">', $txt['sig_info'], '</span><br> |
2715 | 2821 | <br>'; |
2716 | 2822 | |
2717 | - if ($context['show_spellchecking']) |
|
2718 | - echo ' |
|
2823 | + if ($context['show_spellchecking']) { |
|
2824 | + echo ' |
|
2719 | 2825 | <input type="button" value="', $txt['spell_check'], '" onclick="spellCheck(\'creator\', \'signature\');" class="button_submit">'; |
2826 | + } |
|
2720 | 2827 | |
2721 | 2828 | echo ' |
2722 | 2829 | </dt> |
@@ -2724,17 +2831,20 @@ discard block |
||
2724 | 2831 | <textarea class="editor" onkeyup="calcCharLeft();" id="signature" name="signature" rows="5" cols="50" style="min-width: 50%; max-width: 99%;">', $context['member']['signature'], '</textarea><br>'; |
2725 | 2832 | |
2726 | 2833 | // If there is a limit at all! |
2727 | - if (!empty($context['signature_limits']['max_length'])) |
|
2728 | - echo ' |
|
2834 | + if (!empty($context['signature_limits']['max_length'])) { |
|
2835 | + echo ' |
|
2729 | 2836 | <span class="smalltext">', sprintf($txt['max_sig_characters'], $context['signature_limits']['max_length']), ' <span id="signatureLeft">', $context['signature_limits']['max_length'], '</span></span><br>'; |
2837 | + } |
|
2730 | 2838 | |
2731 | - if (!empty($context['show_preview_button'])) |
|
2732 | - echo ' |
|
2839 | + if (!empty($context['show_preview_button'])) { |
|
2840 | + echo ' |
|
2733 | 2841 | <input type="button" name="preview_signature" id="preview_button" value="', $txt['preview_signature'], '" class="button_submit">'; |
2842 | + } |
|
2734 | 2843 | |
2735 | - if ($context['signature_warning']) |
|
2736 | - echo ' |
|
2844 | + if ($context['signature_warning']) { |
|
2845 | + echo ' |
|
2737 | 2846 | <span class="smalltext">', $context['signature_warning'], '</span>'; |
2847 | + } |
|
2738 | 2848 | |
2739 | 2849 | // Some javascript used to count how many characters have been used so far in the signature. |
2740 | 2850 | echo ' |
@@ -2778,9 +2888,10 @@ discard block |
||
2778 | 2888 | <div> |
2779 | 2889 | <select name="cat" id="cat" size="10" onchange="changeSel(\'\');" onfocus="selectRadioByName(document.forms.creator.avatar_choice, \'server_stored\');">'; |
2780 | 2890 | // This lists all the file categories. |
2781 | - foreach ($context['avatars'] as $avatar) |
|
2782 | - echo ' |
|
2891 | + foreach ($context['avatars'] as $avatar) { |
|
2892 | + echo ' |
|
2783 | 2893 | <option value="', $avatar['filename'] . ($avatar['is_dir'] ? '/' : ''), '"', ($avatar['checked'] ? ' selected' : ''), '>', $avatar['name'], '</option>'; |
2894 | + } |
|
2784 | 2895 | echo ' |
2785 | 2896 | </select> |
2786 | 2897 | </div> |
@@ -2835,16 +2946,17 @@ discard block |
||
2835 | 2946 | <div id="avatar_gravatar"> |
2836 | 2947 | <img src="' . $context['member']['avatar']['href'] . '" alt="" />'; |
2837 | 2948 | |
2838 | - if (empty($modSettings['gravatarAllowExtraEmail'])) |
|
2839 | - echo ' |
|
2949 | + if (empty($modSettings['gravatarAllowExtraEmail'])) { |
|
2950 | + echo ' |
|
2840 | 2951 | <div class="smalltext">', $txt['gravatar_noAlternateEmail'], '</div>'; |
2841 | - else |
|
2952 | + } else |
|
2842 | 2953 | { |
2843 | 2954 | // Depending on other stuff, the stored value here might have some odd things in it from other areas. |
2844 | - if ($context['member']['avatar']['external'] == $context['member']['email']) |
|
2845 | - $textbox_value = ''; |
|
2846 | - else |
|
2847 | - $textbox_value = $context['member']['avatar']['external']; |
|
2955 | + if ($context['member']['avatar']['external'] == $context['member']['email']) { |
|
2956 | + $textbox_value = ''; |
|
2957 | + } else { |
|
2958 | + $textbox_value = $context['member']['avatar']['external']; |
|
2959 | + } |
|
2848 | 2960 | |
2849 | 2961 | echo ' |
2850 | 2962 | <div class="smalltext">', $txt['gravatar_alternateEmail'], '</div> |
@@ -2916,8 +3028,9 @@ discard block |
||
2916 | 3028 | $h = !empty($modSettings['avatar_max_height_' . $type]) ? comma_format($modSettings['avatar_max_height_' . $type]) : 0; |
2917 | 3029 | |
2918 | 3030 | $suffix = (!empty($w) ? 'w' : '') . (!empty($h) ? 'h' : ''); |
2919 | - if (empty($suffix)) |
|
2920 | - return; |
|
3031 | + if (empty($suffix)) { |
|
3032 | + return; |
|
3033 | + } |
|
2921 | 3034 | |
2922 | 3035 | echo ' |
2923 | 3036 | <div class="smalltext">', sprintf($txt['avatar_max_size_' . $suffix], $w, $h), '</div>'; |
@@ -2939,9 +3052,10 @@ discard block |
||
2939 | 3052 | <dd> |
2940 | 3053 | <select name="easyformat" id="easyformat" onchange="document.forms.creator.time_format.value = this.options[this.selectedIndex].value;" style="margin-bottom: 4px;">'; |
2941 | 3054 | // Help the user by showing a list of common time formats. |
2942 | - foreach ($context['easy_timeformats'] as $time_format) |
|
2943 | - echo ' |
|
3055 | + foreach ($context['easy_timeformats'] as $time_format) { |
|
3056 | + echo ' |
|
2944 | 3057 | <option value="', $time_format['format'], '"', $time_format['format'] == $context['member']['time_format'] ? ' selected' : '', '>', $time_format['title'], '</option>'; |
3058 | + } |
|
2945 | 3059 | echo ' |
2946 | 3060 | </select><br> |
2947 | 3061 | <input type="text" name="time_format" id="time_format" value="', $context['member']['time_format'], '" size="30" class="input_text"> |
@@ -2977,9 +3091,10 @@ discard block |
||
2977 | 3091 | </dt> |
2978 | 3092 | <dd> |
2979 | 3093 | <select name="smiley_set" id="smiley_set" onchange="document.getElementById(\'smileypr\').src = this.selectedIndex == 0 ? \'', $settings['images_url'], '/blank.png\' : \'', $modSettings['smileys_url'], '/\' + (this.selectedIndex != 1 ? this.options[this.selectedIndex].value : \'', !empty($settings['smiley_sets_default']) ? $settings['smiley_sets_default'] : $modSettings['smiley_sets_default'], '\') + \'/smiley.gif\';">'; |
2980 | - foreach ($context['smiley_sets'] as $set) |
|
2981 | - echo ' |
|
3094 | + foreach ($context['smiley_sets'] as $set) { |
|
3095 | + echo ' |
|
2982 | 3096 | <option value="', $set['id'], '"', $set['selected'] ? ' selected' : '', '>', $set['name'], '</option>'; |
3097 | + } |
|
2983 | 3098 | echo ' |
2984 | 3099 | </select> <img id="smileypr" class="centericon" src="', $context['member']['smiley_set']['id'] != 'none' ? $modSettings['smileys_url'] . '/' . ($context['member']['smiley_set']['id'] != '' ? $context['member']['smiley_set']['id'] : (!empty($settings['smiley_sets_default']) ? $settings['smiley_sets_default'] : $modSettings['smiley_sets_default'])) . '/smiley.gif' : $settings['images_url'] . '/blank.png', '" alt=":)" style="padding-left: 20px;"> |
2985 | 3100 | </dd>'; |
@@ -3030,10 +3145,11 @@ discard block |
||
3030 | 3145 | </div> |
3031 | 3146 | <div class="clear"></div>'; |
3032 | 3147 | |
3033 | - if (!empty($context['from_ajax'])) |
|
3034 | - echo ' |
|
3148 | + if (!empty($context['from_ajax'])) { |
|
3149 | + echo ' |
|
3035 | 3150 | <br> |
3036 | 3151 | <a href="javascript:self.close();"></a>'; |
3152 | + } |
|
3037 | 3153 | |
3038 | 3154 | echo ' |
3039 | 3155 | </div> |
@@ -3072,15 +3188,16 @@ discard block |
||
3072 | 3188 | <br /><div class="smalltext">', $txt['tfa_profile_desc'], '</div> |
3073 | 3189 | </dt> |
3074 | 3190 | <dd>'; |
3075 | - if (!$context['tfa_enabled'] && $context['user']['is_owner']) |
|
3076 | - echo ' |
|
3191 | + if (!$context['tfa_enabled'] && $context['user']['is_owner']) { |
|
3192 | + echo ' |
|
3077 | 3193 | <a href="', !empty($modSettings['force_ssl']) && $modSettings['force_ssl'] < 2 ? strtr($scripturl, array('http://' => 'https://')) : $scripturl, '?action=profile;area=tfasetup" id="enable_tfa">', $txt['tfa_profile_enable'], '</a>'; |
3078 | - elseif (!$context['tfa_enabled']) |
|
3079 | - echo ' |
|
3194 | + } elseif (!$context['tfa_enabled']) { |
|
3195 | + echo ' |
|
3080 | 3196 | ', $txt['tfa_profile_disabled']; |
3081 | - else |
|
3082 | - echo ' |
|
3197 | + } else { |
|
3198 | + echo ' |
|
3083 | 3199 | ', sprintf($txt['tfa_profile_enabled'], $scripturl . '?action=profile;u=' . $context['id_member'] . ';area=tfasetup;disable'); |
3200 | + } |
|
3084 | 3201 | echo ' |
3085 | 3202 | </dd>'; |
3086 | 3203 | } |
@@ -21,7 +21,7 @@ |
||
21 | 21 | <div id="recent" class="main_section"> |
22 | 22 | <div class="cat_bar"> |
23 | 23 | <h3 class="catbg"> |
24 | - <span class="xx"></span>',$txt['recent_posts'],' |
|
24 | + <span class="xx"></span>',$txt['recent_posts'], ' |
|
25 | 25 | </h3> |
26 | 26 | </div> |
27 | 27 | <div class="pagesection">', $context['page_index'], '</div>'; |
@@ -43,28 +43,33 @@ discard block |
||
43 | 43 | </div> |
44 | 44 | <div class="list_posts">', $post['message'], '</div>'; |
45 | 45 | |
46 | - if ($post['can_reply'] || $post['can_quote'] || $post['can_delete']) |
|
47 | - echo ' |
|
46 | + if ($post['can_reply'] || $post['can_quote'] || $post['can_delete']) { |
|
47 | + echo ' |
|
48 | 48 | <ul class="quickbuttons">'; |
49 | + } |
|
49 | 50 | |
50 | 51 | // If they *can* reply? |
51 | - if ($post['can_reply']) |
|
52 | - echo ' |
|
52 | + if ($post['can_reply']) { |
|
53 | + echo ' |
|
53 | 54 | <li><a href="', $scripturl, '?action=post;topic=', $post['topic'], '.', $post['start'], '"><span class="generic_icons reply_button"></span>', $txt['reply'], '</a></li>'; |
55 | + } |
|
54 | 56 | |
55 | 57 | // If they *can* quote? |
56 | - if ($post['can_quote']) |
|
57 | - echo ' |
|
58 | + if ($post['can_quote']) { |
|
59 | + echo ' |
|
58 | 60 | <li><a href="', $scripturl, '?action=post;topic=', $post['topic'], '.', $post['start'], ';quote=', $post['id'], '"><span class="generic_icons quote"></span>', $txt['quote_action'], '</a></li>'; |
61 | + } |
|
59 | 62 | |
60 | 63 | // How about... even... remove it entirely?! |
61 | - if ($post['can_delete']) |
|
62 | - echo ' |
|
64 | + if ($post['can_delete']) { |
|
65 | + echo ' |
|
63 | 66 | <li><a href="', $scripturl, '?action=deletemsg;msg=', $post['id'], ';topic=', $post['topic'], ';recent;', $context['session_var'], '=', $context['session_id'], '" data-confirm="', $txt['remove_message'], '" class="you_sure"><span class="generic_icons remove_button"></span>', $txt['remove'], '</a></li>'; |
67 | + } |
|
64 | 68 | |
65 | - if ($post['can_reply'] || $post['can_quote'] || $post['can_delete']) |
|
66 | - echo ' |
|
69 | + if ($post['can_reply'] || $post['can_quote'] || $post['can_delete']) { |
|
70 | + echo ' |
|
67 | 71 | </ul>'; |
72 | + } |
|
68 | 73 | |
69 | 74 | echo ' |
70 | 75 | </div>'; |
@@ -86,12 +91,13 @@ discard block |
||
86 | 91 | echo ' |
87 | 92 | <div id="recent" class="main_content">'; |
88 | 93 | |
89 | - if ($context['showCheckboxes']) |
|
90 | - echo ' |
|
94 | + if ($context['showCheckboxes']) { |
|
95 | + echo ' |
|
91 | 96 | <form action="', $scripturl, '?action=quickmod" method="post" accept-charset="', $context['character_set'], '" name="quickModForm" id="quickModForm" style="margin: 0;"> |
92 | 97 | <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '"> |
93 | 98 | <input type="hidden" name="qaction" value="markread"> |
94 | 99 | <input type="hidden" name="redirect_url" value="action=unread', (!empty($context['showing_all_topics']) ? ';all' : ''), $context['querystring_board_limits'], '">'; |
100 | + } |
|
95 | 101 | |
96 | 102 | if (!empty($context['topics'])) |
97 | 103 | { |
@@ -117,11 +123,12 @@ discard block |
||
117 | 123 | </div>'; |
118 | 124 | |
119 | 125 | // Show a "select all" box for quick moderation? |
120 | - if ($context['showCheckboxes']) |
|
121 | - echo ' |
|
126 | + if ($context['showCheckboxes']) { |
|
127 | + echo ' |
|
122 | 128 | <div class="moderation"> |
123 | 129 | <input type="checkbox" onclick="invertAll(this, this.form, \'topics[]\');" class="input_check"> |
124 | 130 | </div>'; |
131 | + } |
|
125 | 132 | |
126 | 133 | echo ' |
127 | 134 | </div> |
@@ -140,15 +147,18 @@ discard block |
||
140 | 147 | // Now we handle the icons |
141 | 148 | echo ' |
142 | 149 | <div class="icons floatright">'; |
143 | - if ($topic['is_locked']) |
|
144 | - echo ' |
|
150 | + if ($topic['is_locked']) { |
|
151 | + echo ' |
|
145 | 152 | <span class="generic_icons lock"></span>'; |
146 | - if ($topic['is_sticky']) |
|
147 | - echo ' |
|
153 | + } |
|
154 | + if ($topic['is_sticky']) { |
|
155 | + echo ' |
|
148 | 156 | <span class="generic_icons sticky"></span>'; |
149 | - if ($topic['is_poll']) |
|
150 | - echo ' |
|
157 | + } |
|
158 | + if ($topic['is_poll']) { |
|
159 | + echo ' |
|
151 | 160 | <span class="generic_icons poll"></span>'; |
161 | + } |
|
152 | 162 | echo ' |
153 | 163 | </div>'; |
154 | 164 | |
@@ -173,19 +183,21 @@ discard block |
||
173 | 183 | ', sprintf($txt['last_post_topic'], '<a href="' . $topic['last_post']['href'] . '">' . $topic['last_post']['time'] . '</a>', $topic['last_post']['member']['link']), ' |
174 | 184 | </div>'; |
175 | 185 | |
176 | - if ($context['showCheckboxes']) |
|
177 | - echo ' |
|
186 | + if ($context['showCheckboxes']) { |
|
187 | + echo ' |
|
178 | 188 | <div class="moderation"> |
179 | 189 | <input type="checkbox" name="topics[]" value="', $topic['id'], '" class="input_check"> |
180 | 190 | </div>'; |
191 | + } |
|
181 | 192 | |
182 | 193 | echo ' |
183 | 194 | </div>'; |
184 | 195 | } |
185 | 196 | |
186 | - if (empty($context['topics'])) |
|
187 | - echo ' |
|
197 | + if (empty($context['topics'])) { |
|
198 | + echo ' |
|
188 | 199 | <div style="display: none;"></div>'; |
200 | + } |
|
189 | 201 | |
190 | 202 | echo ' |
191 | 203 | </div> |
@@ -197,25 +209,27 @@ discard block |
||
197 | 209 | ', $context['menu_separator'], '<a href="#recent" class="topbottom floatleft">', $txt['go_up'], '</a> |
198 | 210 | <div class="pagelinks">', $context['page_index'], '</div> |
199 | 211 | </div>'; |
200 | - } |
|
201 | - else |
|
202 | - echo ' |
|
212 | + } else { |
|
213 | + echo ' |
|
203 | 214 | <div class="cat_bar"> |
204 | 215 | <h3 class="catbg centertext"> |
205 | 216 | ', $context['showing_all_topics'] ? $txt['topic_alert_none'] : $txt['unread_topics_visit_none'], ' |
206 | 217 | </h3> |
207 | 218 | </div>'; |
219 | + } |
|
208 | 220 | |
209 | - if ($context['showCheckboxes']) |
|
210 | - echo ' |
|
221 | + if ($context['showCheckboxes']) { |
|
222 | + echo ' |
|
211 | 223 | </form>'; |
224 | + } |
|
212 | 225 | |
213 | 226 | echo ' |
214 | 227 | </div>'; |
215 | 228 | |
216 | - if (empty($context['no_topic_listing'])) |
|
217 | - template_topic_legend(); |
|
218 | -} |
|
229 | + if (empty($context['no_topic_listing'])) { |
|
230 | + template_topic_legend(); |
|
231 | + } |
|
232 | + } |
|
219 | 233 | |
220 | 234 | /** |
221 | 235 | * Template for showing unread replies (eg new replies to topics you've posted in) |
@@ -227,12 +241,13 @@ discard block |
||
227 | 241 | echo ' |
228 | 242 | <div id="recent">'; |
229 | 243 | |
230 | - if ($context['showCheckboxes']) |
|
231 | - echo ' |
|
244 | + if ($context['showCheckboxes']) { |
|
245 | + echo ' |
|
232 | 246 | <form action="', $scripturl, '?action=quickmod" method="post" accept-charset="', $context['character_set'], '" name="quickModForm" id="quickModForm" style="margin: 0;"> |
233 | 247 | <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '"> |
234 | 248 | <input type="hidden" name="qaction" value="markread"> |
235 | 249 | <input type="hidden" name="redirect_url" value="action=unreadreplies', (!empty($context['showing_all_topics']) ? ';all' : ''), $context['querystring_board_limits'], '">'; |
250 | + } |
|
236 | 251 | |
237 | 252 | if (!empty($context['topics'])) |
238 | 253 | { |
@@ -258,11 +273,12 @@ discard block |
||
258 | 273 | </div>'; |
259 | 274 | |
260 | 275 | // Show a "select all" box for quick moderation? |
261 | - if ($context['showCheckboxes']) |
|
262 | - echo ' |
|
276 | + if ($context['showCheckboxes']) { |
|
277 | + echo ' |
|
263 | 278 | <div class="moderation"> |
264 | 279 | <input type="checkbox" onclick="invertAll(this, this.form, \'topics[]\');" class="input_check"> |
265 | 280 | </div>'; |
281 | + } |
|
266 | 282 | |
267 | 283 | echo ' |
268 | 284 | </div> |
@@ -281,15 +297,18 @@ discard block |
||
281 | 297 | // Now we handle the icons |
282 | 298 | echo ' |
283 | 299 | <div class="icons floatright">'; |
284 | - if ($topic['is_locked']) |
|
285 | - echo ' |
|
300 | + if ($topic['is_locked']) { |
|
301 | + echo ' |
|
286 | 302 | <span class="generic_icons lock"></span>'; |
287 | - if ($topic['is_sticky']) |
|
288 | - echo ' |
|
303 | + } |
|
304 | + if ($topic['is_sticky']) { |
|
305 | + echo ' |
|
289 | 306 | <span class="generic_icons sticky"></span>'; |
290 | - if ($topic['is_poll']) |
|
291 | - echo ' |
|
307 | + } |
|
308 | + if ($topic['is_poll']) { |
|
309 | + echo ' |
|
292 | 310 | <span class="generic_icons poll"></span>'; |
311 | + } |
|
293 | 312 | echo ' |
294 | 313 | </div>'; |
295 | 314 | |
@@ -314,11 +333,12 @@ discard block |
||
314 | 333 | ', sprintf($txt['last_post_topic'], '<a href="' . $topic['last_post']['href'] . '">' . $topic['last_post']['time'] . '</a>', $topic['last_post']['member']['link']), ' |
315 | 334 | </div>'; |
316 | 335 | |
317 | - if ($context['showCheckboxes']) |
|
318 | - echo ' |
|
336 | + if ($context['showCheckboxes']) { |
|
337 | + echo ' |
|
319 | 338 | <div class="moderation"> |
320 | 339 | <input type="checkbox" name="topics[]" value="', $topic['id'], '" class="input_check"> |
321 | 340 | </div>'; |
341 | + } |
|
322 | 342 | echo ' |
323 | 343 | </div>'; |
324 | 344 | } |
@@ -331,24 +351,26 @@ discard block |
||
331 | 351 | ', $context['menu_separator'], '<a href="#recent" class="topbottom floatleft">', $txt['go_up'], '</a> |
332 | 352 | <div class="pagelinks">', $context['page_index'], '</div> |
333 | 353 | </div>'; |
334 | - } |
|
335 | - else |
|
336 | - echo ' |
|
354 | + } else { |
|
355 | + echo ' |
|
337 | 356 | <div class="cat_bar"> |
338 | 357 | <h3 class="catbg centertext"> |
339 | 358 | ', $context['showing_all_topics'] ? $txt['topic_alert_none'] : $txt['unread_topics_visit_none'], ' |
340 | 359 | </h3> |
341 | 360 | </div>'; |
361 | + } |
|
342 | 362 | |
343 | - if ($context['showCheckboxes']) |
|
344 | - echo ' |
|
363 | + if ($context['showCheckboxes']) { |
|
364 | + echo ' |
|
345 | 365 | </form>'; |
366 | + } |
|
346 | 367 | |
347 | 368 | echo ' |
348 | 369 | </div>'; |
349 | 370 | |
350 | - if (empty($context['no_topic_listing'])) |
|
351 | - template_topic_legend(); |
|
352 | -} |
|
371 | + if (empty($context['no_topic_listing'])) { |
|
372 | + template_topic_legend(); |
|
373 | + } |
|
374 | + } |
|
353 | 375 | |
354 | 376 | ?> |
355 | 377 | \ No newline at end of file |
@@ -89,8 +89,9 @@ discard block |
||
89 | 89 | foreach ($section['areas'] as $i => $area) |
90 | 90 | { |
91 | 91 | // Not supposed to be printed? |
92 | - if (empty($area['label'])) |
|
93 | - continue; |
|
92 | + if (empty($area['label'])) { |
|
93 | + continue; |
|
94 | + } |
|
94 | 95 | |
95 | 96 | echo ' |
96 | 97 | <li', !empty($area['subsections']) ? ' class="subsections"' : '', '>'; |
@@ -99,8 +100,9 @@ discard block |
||
99 | 100 | <a class="', $area['icon_class'], !empty($area['selected']) ? ' chosen ' : '', '" href="', (isset($area['url']) ? $area['url'] : $menu_context['base_url'] . ';area=' . $i), $menu_context['extra_parameters'], '">', $area['icon'], $area['label'], '</a>'; |
100 | 101 | |
101 | 102 | // Is this the current area, or just some area? |
102 | - if (!empty($area['selected']) && empty($context['tabs'])) |
|
103 | - $context['tabs'] = isset($area['subsections']) ? $area['subsections'] : array(); |
|
103 | + if (!empty($area['selected']) && empty($context['tabs'])) { |
|
104 | + $context['tabs'] = isset($area['subsections']) ? $area['subsections'] : array(); |
|
105 | + } |
|
104 | 106 | |
105 | 107 | // Are there any subsections? |
106 | 108 | if (!empty($area['subsections'])) |
@@ -110,8 +112,9 @@ discard block |
||
110 | 112 | |
111 | 113 | foreach ($area['subsections'] as $sa => $sub) |
112 | 114 | { |
113 | - if (!empty($sub['disabled'])) |
|
114 | - continue; |
|
115 | + if (!empty($sub['disabled'])) { |
|
116 | + continue; |
|
117 | + } |
|
115 | 118 | |
116 | 119 | $url = isset($sub['url']) ? $sub['url'] : (isset($area['url']) ? $area['url'] : $menu_context['base_url'] . ';area=' . $i) . ';sa=' . $sa; |
117 | 120 | |
@@ -158,8 +161,9 @@ discard block |
||
158 | 161 | <h3 class="catbg">'; |
159 | 162 | |
160 | 163 | // The function is in Admin.template.php, but since this template is used elsewhere too better check if the function is available |
161 | - if (function_exists('template_admin_quick_search')) |
|
162 | - template_admin_quick_search(); |
|
164 | + if (function_exists('template_admin_quick_search')) { |
|
165 | + template_admin_quick_search(); |
|
166 | + } |
|
163 | 167 | |
164 | 168 | // Exactly how many tabs do we have? |
165 | 169 | if (!empty($context['tabs'])) |
@@ -174,30 +178,36 @@ discard block |
||
174 | 178 | } |
175 | 179 | |
176 | 180 | // Did this not even exist - or do we not have a label? |
177 | - if (!isset($tab_context['tabs'][$id])) |
|
178 | - $tab_context['tabs'][$id] = array('label' => $tab['label']); |
|
179 | - elseif (!isset($tab_context['tabs'][$id]['label'])) |
|
180 | - $tab_context['tabs'][$id]['label'] = $tab['label']; |
|
181 | + if (!isset($tab_context['tabs'][$id])) { |
|
182 | + $tab_context['tabs'][$id] = array('label' => $tab['label']); |
|
183 | + } elseif (!isset($tab_context['tabs'][$id]['label'])) { |
|
184 | + $tab_context['tabs'][$id]['label'] = $tab['label']; |
|
185 | + } |
|
181 | 186 | |
182 | 187 | // Has a custom URL defined in the main admin structure? |
183 | - if (isset($tab['url']) && !isset($tab_context['tabs'][$id]['url'])) |
|
184 | - $tab_context['tabs'][$id]['url'] = $tab['url']; |
|
188 | + if (isset($tab['url']) && !isset($tab_context['tabs'][$id]['url'])) { |
|
189 | + $tab_context['tabs'][$id]['url'] = $tab['url']; |
|
190 | + } |
|
185 | 191 | |
186 | 192 | // Any additional paramaters for the url? |
187 | - if (isset($tab['add_params']) && !isset($tab_context['tabs'][$id]['add_params'])) |
|
188 | - $tab_context['tabs'][$id]['add_params'] = $tab['add_params']; |
|
193 | + if (isset($tab['add_params']) && !isset($tab_context['tabs'][$id]['add_params'])) { |
|
194 | + $tab_context['tabs'][$id]['add_params'] = $tab['add_params']; |
|
195 | + } |
|
189 | 196 | |
190 | 197 | // Has it been deemed selected? |
191 | - if (!empty($tab['is_selected'])) |
|
192 | - $tab_context['tabs'][$id]['is_selected'] = true; |
|
198 | + if (!empty($tab['is_selected'])) { |
|
199 | + $tab_context['tabs'][$id]['is_selected'] = true; |
|
200 | + } |
|
193 | 201 | |
194 | 202 | // Does it have its own help? |
195 | - if (!empty($tab['help'])) |
|
196 | - $tab_context['tabs'][$id]['help'] = $tab['help']; |
|
203 | + if (!empty($tab['help'])) { |
|
204 | + $tab_context['tabs'][$id]['help'] = $tab['help']; |
|
205 | + } |
|
197 | 206 | |
198 | 207 | // Is this the last one? |
199 | - if (!empty($tab['is_last']) && !isset($tab_context['override_last'])) |
|
200 | - $tab_context['tabs'][$id]['is_last'] = true; |
|
208 | + if (!empty($tab['is_last']) && !isset($tab_context['override_last'])) { |
|
209 | + $tab_context['tabs'][$id]['is_last'] = true; |
|
210 | + } |
|
201 | 211 | } |
202 | 212 | |
203 | 213 | // Find the selected tab |
@@ -214,17 +224,18 @@ discard block |
||
214 | 224 | // Show an icon and/or a help item? |
215 | 225 | if (!empty($selected_tab['icon_class']) || !empty($tab_context['icon_class']) || !empty($selected_tab['icon']) || !empty($tab_context['icon']) || !empty($selected_tab['help']) || !empty($tab_context['help'])) |
216 | 226 | { |
217 | - if (!empty($selected_tab['icon_class']) || !empty($tab_context['icon_class'])) |
|
218 | - echo '<span class="', !empty($selected_tab['icon_class']) ? $selected_tab['icon_class'] : $tab_context['icon_class'], ' icon"></span>'; |
|
219 | - elseif (!empty($selected_tab['icon']) || !empty($tab_context['icon'])) |
|
220 | - echo '<img src="', $settings['images_url'], '/icons/', !empty($selected_tab['icon']) ? $selected_tab['icon'] : $tab_context['icon'], '" alt="" class="icon">'; |
|
227 | + if (!empty($selected_tab['icon_class']) || !empty($tab_context['icon_class'])) { |
|
228 | + echo '<span class="', !empty($selected_tab['icon_class']) ? $selected_tab['icon_class'] : $tab_context['icon_class'], ' icon"></span>'; |
|
229 | + } elseif (!empty($selected_tab['icon']) || !empty($tab_context['icon'])) { |
|
230 | + echo '<img src="', $settings['images_url'], '/icons/', !empty($selected_tab['icon']) ? $selected_tab['icon'] : $tab_context['icon'], '" alt="" class="icon">'; |
|
231 | + } |
|
221 | 232 | |
222 | - if (!empty($selected_tab['help']) || !empty($tab_context['help'])) |
|
223 | - echo '<a href="', $scripturl, '?action=helpadmin;help=', !empty($selected_tab['help']) ? $selected_tab['help'] : $tab_context['help'], '" onclick="return reqOverlayDiv(this.href);" class="help"><span class="generic_icons help" title="', $txt['help'], '"></span></a>'; |
|
233 | + if (!empty($selected_tab['help']) || !empty($tab_context['help'])) { |
|
234 | + echo '<a href="', $scripturl, '?action=helpadmin;help=', !empty($selected_tab['help']) ? $selected_tab['help'] : $tab_context['help'], '" onclick="return reqOverlayDiv(this.href);" class="help"><span class="generic_icons help" title="', $txt['help'], '"></span></a>'; |
|
235 | + } |
|
224 | 236 | |
225 | 237 | echo $tab_context['title']; |
226 | - } |
|
227 | - else |
|
238 | + } else |
|
228 | 239 | { |
229 | 240 | echo ' |
230 | 241 | ', $tab_context['title']; |
@@ -237,11 +248,12 @@ discard block |
||
237 | 248 | } |
238 | 249 | |
239 | 250 | // Shall we use the tabs? Yes, it's the only known way! |
240 | - if (!empty($selected_tab['description']) || !empty($tab_context['description'])) |
|
241 | - echo ' |
|
251 | + if (!empty($selected_tab['description']) || !empty($tab_context['description'])) { |
|
252 | + echo ' |
|
242 | 253 | <p class="information"> |
243 | 254 | ', !empty($selected_tab['description']) ? $selected_tab['description'] : $tab_context['description'], ' |
244 | 255 | </p>'; |
256 | + } |
|
245 | 257 | |
246 | 258 | // Print out all the items in this tab (if any). |
247 | 259 | if (!empty($context['tabs'])) |
@@ -253,8 +265,9 @@ discard block |
||
253 | 265 | |
254 | 266 | foreach ($tab_context['tabs'] as $sa => $tab) |
255 | 267 | { |
256 | - if (!empty($tab['disabled'])) |
|
257 | - continue; |
|
268 | + if (!empty($tab['disabled'])) { |
|
269 | + continue; |
|
270 | + } |
|
258 | 271 | |
259 | 272 | if (!empty($tab['is_selected'])) |
260 | 273 | { |
@@ -262,12 +275,12 @@ discard block |
||
262 | 275 | <li> |
263 | 276 | <a class="active" href="', isset($tab['url']) ? $tab['url'] : $menu_context['base_url'] . ';area=' . $menu_context['current_area'] . ';sa=' . $sa, $menu_context['extra_parameters'], isset($tab['add_params']) ? $tab['add_params'] : '', '">', $tab['label'], '</a> |
264 | 277 | </li>'; |
265 | - } |
|
266 | - else |
|
267 | - echo ' |
|
278 | + } else { |
|
279 | + echo ' |
|
268 | 280 | <li> |
269 | 281 | <a href="', isset($tab['url']) ? $tab['url'] : $menu_context['base_url'] . ';area=' . $menu_context['current_area'] . ';sa=' . $sa, $menu_context['extra_parameters'], isset($tab['add_params']) ? $tab['add_params'] : '', '">', $tab['label'], '</a> |
270 | 282 | </li>'; |
283 | + } |
|
271 | 284 | } |
272 | 285 | |
273 | 286 | // the end of tabs |
@@ -673,7 +673,7 @@ |
||
673 | 673 | 'Nikola "Dzonny" Novaković', |
674 | 674 | // Localizers |
675 | 675 | 'Dr. Deejay', |
676 | - 'd3vcho', |
|
676 | + 'd3vcho', |
|
677 | 677 | // Former Localizers |
678 | 678 | 'Relyana', |
679 | 679 | ), |
@@ -590,7 +590,7 @@ discard block |
||
590 | 590 | 'Shitiz "Dragooon" Garg', |
591 | 591 | 'Karl "RegularExpression" Benson', |
592 | 592 | 'Matthew "Labradoodle-360" Kerle', |
593 | - $user_info['is_admin'] ? 'Matt "Grudge" Wolf': 'Grudge', |
|
593 | + $user_info['is_admin'] ? 'Matt "Grudge" Wolf' : 'Grudge', |
|
594 | 594 | 'Michael "Thantos" Miller', |
595 | 595 | 'Norv', |
596 | 596 | 'Peter "Arantor" Spicer', |
@@ -814,13 +814,13 @@ discard block |
||
814 | 814 | $credit_info = $smcFunc['json_decode']($row['credits'], true); |
815 | 815 | |
816 | 816 | $copyright = empty($credit_info['copyright']) ? '' : $txt['credits_copyright'] . ' © ' . $smcFunc['htmlspecialchars']($credit_info['copyright']); |
817 | - $license = empty($credit_info['license']) ? '' : $txt['credits_license'] . ': ' . (!empty($credit_info['licenseurl']) ? '<a href="'. $smcFunc['htmlspecialchars']($credit_info['licenseurl']) .'">'. $smcFunc['htmlspecialchars']($credit_info['license']) .'</a>' : $smcFunc['htmlspecialchars']($credit_info['license'])); |
|
817 | + $license = empty($credit_info['license']) ? '' : $txt['credits_license'] . ': ' . (!empty($credit_info['licenseurl']) ? '<a href="' . $smcFunc['htmlspecialchars']($credit_info['licenseurl']) . '">' . $smcFunc['htmlspecialchars']($credit_info['license']) . '</a>' : $smcFunc['htmlspecialchars']($credit_info['license'])); |
|
818 | 818 | $version = $txt['credits_version'] . ' ' . $row['version']; |
819 | 819 | $title = (empty($credit_info['title']) ? $row['name'] : $smcFunc['htmlspecialchars']($credit_info['title'])) . ': ' . $version; |
820 | 820 | |
821 | 821 | // build this one out and stash it away |
822 | 822 | $mod_name = empty($credit_info['url']) ? $title : '<a href="' . $credit_info['url'] . '">' . $title . '</a>'; |
823 | - $mods[] = $mod_name . (!empty($license) ? ' | ' . $license : '') . (!empty($copyright) ? ' | ' . $copyright : ''); |
|
823 | + $mods[] = $mod_name . (!empty($license) ? ' | ' . $license : '') . (!empty($copyright) ? ' | ' . $copyright : ''); |
|
824 | 824 | } |
825 | 825 | cache_put_data('mods_credits', $mods, 86400); |
826 | 826 | } |
@@ -14,8 +14,9 @@ discard block |
||
14 | 14 | * @version 2.1 Beta 4 |
15 | 15 | */ |
16 | 16 | |
17 | -if (!defined('SMF')) |
|
17 | +if (!defined('SMF')) { |
|
18 | 18 | die('No direct access...'); |
19 | +} |
|
19 | 20 | |
20 | 21 | /** |
21 | 22 | * Who's online, and what are they doing? |
@@ -35,8 +36,9 @@ discard block |
||
35 | 36 | isAllowedTo('who_view'); |
36 | 37 | |
37 | 38 | // You can't do anything if this is off. |
38 | - if (empty($modSettings['who_enabled'])) |
|
39 | - fatal_lang_error('who_off', false); |
|
39 | + if (empty($modSettings['who_enabled'])) { |
|
40 | + fatal_lang_error('who_off', false); |
|
41 | + } |
|
40 | 42 | |
41 | 43 | // Load the 'Who' template. |
42 | 44 | loadTemplate('Who'); |
@@ -71,9 +73,9 @@ discard block |
||
71 | 73 | $show_methods['spiders'] = '(lo.id_member = 0 AND lo.id_spider > 0)'; |
72 | 74 | $show_methods['guests'] = '(lo.id_member = 0 AND lo.id_spider = 0)'; |
73 | 75 | $context['show_methods']['spiders'] = $txt['who_show_spiders_only']; |
76 | + } elseif (empty($modSettings['show_spider_online']) && isset($_SESSION['who_online_filter']) && $_SESSION['who_online_filter'] == 'spiders') { |
|
77 | + unset($_SESSION['who_online_filter']); |
|
74 | 78 | } |
75 | - elseif (empty($modSettings['show_spider_online']) && isset($_SESSION['who_online_filter']) && $_SESSION['who_online_filter'] == 'spiders') |
|
76 | - unset($_SESSION['who_online_filter']); |
|
77 | 79 | |
78 | 80 | // Does the user prefer a different sort direction? |
79 | 81 | if (isset($_REQUEST['sort']) && isset($sort_methods[$_REQUEST['sort']])) |
@@ -97,20 +99,24 @@ discard block |
||
97 | 99 | $context['sort_direction'] = isset($_REQUEST['asc']) || (isset($_REQUEST['sort_dir']) && $_REQUEST['sort_dir'] == 'asc') ? 'up' : 'down'; |
98 | 100 | |
99 | 101 | $conditions = array(); |
100 | - if (!allowedTo('moderate_forum')) |
|
101 | - $conditions[] = '(COALESCE(mem.show_online, 1) = 1)'; |
|
102 | + if (!allowedTo('moderate_forum')) { |
|
103 | + $conditions[] = '(COALESCE(mem.show_online, 1) = 1)'; |
|
104 | + } |
|
102 | 105 | |
103 | 106 | // Fallback to top filter? |
104 | - if (isset($_REQUEST['submit_top']) && isset($_REQUEST['show_top'])) |
|
105 | - $_REQUEST['show'] = $_REQUEST['show_top']; |
|
107 | + if (isset($_REQUEST['submit_top']) && isset($_REQUEST['show_top'])) { |
|
108 | + $_REQUEST['show'] = $_REQUEST['show_top']; |
|
109 | + } |
|
106 | 110 | // Does the user wish to apply a filter? |
107 | - if (isset($_REQUEST['show']) && isset($show_methods[$_REQUEST['show']])) |
|
108 | - $context['show_by'] = $_SESSION['who_online_filter'] = $_REQUEST['show']; |
|
111 | + if (isset($_REQUEST['show']) && isset($show_methods[$_REQUEST['show']])) { |
|
112 | + $context['show_by'] = $_SESSION['who_online_filter'] = $_REQUEST['show']; |
|
113 | + } |
|
109 | 114 | // Perhaps we saved a filter earlier in the session? |
110 | - elseif (isset($_SESSION['who_online_filter'])) |
|
111 | - $context['show_by'] = $_SESSION['who_online_filter']; |
|
112 | - else |
|
113 | - $context['show_by'] = 'members'; |
|
115 | + elseif (isset($_SESSION['who_online_filter'])) { |
|
116 | + $context['show_by'] = $_SESSION['who_online_filter']; |
|
117 | + } else { |
|
118 | + $context['show_by'] = 'members'; |
|
119 | + } |
|
114 | 120 | |
115 | 121 | $conditions[] = $show_methods[$context['show_by']]; |
116 | 122 | |
@@ -156,8 +162,9 @@ discard block |
||
156 | 162 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
157 | 163 | { |
158 | 164 | $actions = $smcFunc['json_decode']($row['url'], true); |
159 | - if ($actions === false) |
|
160 | - continue; |
|
165 | + if ($actions === false) { |
|
166 | + continue; |
|
167 | + } |
|
161 | 168 | |
162 | 169 | // Send the information to the template. |
163 | 170 | $context['members'][$row['session']] = array( |
@@ -195,8 +202,8 @@ discard block |
||
195 | 202 | $spiderContext = array(); |
196 | 203 | if (!empty($modSettings['show_spider_online']) && ($modSettings['show_spider_online'] == 2 || allowedTo('admin_forum')) && !empty($modSettings['spider_name_cache'])) |
197 | 204 | { |
198 | - foreach ($smcFunc['json_decode']($modSettings['spider_name_cache'], true) as $id => $name) |
|
199 | - $spiderContext[$id] = array( |
|
205 | + foreach ($smcFunc['json_decode']($modSettings['spider_name_cache'], true) as $id => $name) { |
|
206 | + $spiderContext[$id] = array( |
|
200 | 207 | 'id' => 0, |
201 | 208 | 'name' => $name, |
202 | 209 | 'group' => $txt['spiders'], |
@@ -205,6 +212,7 @@ discard block |
||
205 | 212 | 'email' => $name, |
206 | 213 | 'is_guest' => true |
207 | 214 | ); |
215 | + } |
|
208 | 216 | } |
209 | 217 | |
210 | 218 | $url_data = determineActions($url_data); |
@@ -219,16 +227,18 @@ discard block |
||
219 | 227 | // Put it in the context variables. |
220 | 228 | foreach ($context['members'] as $i => $member) |
221 | 229 | { |
222 | - if ($member['id'] != 0) |
|
223 | - $member['id'] = loadMemberContext($member['id']) ? $member['id'] : 0; |
|
230 | + if ($member['id'] != 0) { |
|
231 | + $member['id'] = loadMemberContext($member['id']) ? $member['id'] : 0; |
|
232 | + } |
|
224 | 233 | |
225 | 234 | // Keep the IP that came from the database. |
226 | 235 | $memberContext[$member['id']]['ip'] = $member['ip']; |
227 | 236 | $context['members'][$i]['action'] = isset($url_data[$i]) ? $url_data[$i] : $txt['who_hidden']; |
228 | - if ($member['id'] == 0 && isset($spiderContext[$member['id_spider']])) |
|
229 | - $context['members'][$i] += $spiderContext[$member['id_spider']]; |
|
230 | - else |
|
231 | - $context['members'][$i] += $memberContext[$member['id']]; |
|
237 | + if ($member['id'] == 0 && isset($spiderContext[$member['id_spider']])) { |
|
238 | + $context['members'][$i] += $spiderContext[$member['id_spider']]; |
|
239 | + } else { |
|
240 | + $context['members'][$i] += $memberContext[$member['id']]; |
|
241 | + } |
|
232 | 242 | } |
233 | 243 | |
234 | 244 | // Some people can't send personal messages... |
@@ -263,8 +273,9 @@ discard block |
||
263 | 273 | { |
264 | 274 | global $txt, $user_info, $modSettings, $smcFunc; |
265 | 275 | |
266 | - if (!allowedTo('who_view')) |
|
267 | - return array(); |
|
276 | + if (!allowedTo('who_view')) { |
|
277 | + return array(); |
|
278 | + } |
|
268 | 279 | loadLanguage('Who'); |
269 | 280 | |
270 | 281 | // Actions that require a specific permission level. |
@@ -292,10 +303,11 @@ discard block |
||
292 | 303 | ); |
293 | 304 | call_integration_hook('who_allowed', array(&$allowedActions)); |
294 | 305 | |
295 | - if (!is_array($urls)) |
|
296 | - $url_list = array(array($urls, $user_info['id'])); |
|
297 | - else |
|
298 | - $url_list = $urls; |
|
306 | + if (!is_array($urls)) { |
|
307 | + $url_list = array(array($urls, $user_info['id'])); |
|
308 | + } else { |
|
309 | + $url_list = $urls; |
|
310 | + } |
|
299 | 311 | |
300 | 312 | // These are done to later query these in large chunks. (instead of one by one.) |
301 | 313 | $topic_ids = array(); |
@@ -307,12 +319,14 @@ discard block |
||
307 | 319 | { |
308 | 320 | // Get the request parameters.. |
309 | 321 | $actions = $smcFunc['json_decode']($url[0], true); |
310 | - if ($actions === false) |
|
311 | - continue; |
|
322 | + if ($actions === false) { |
|
323 | + continue; |
|
324 | + } |
|
312 | 325 | |
313 | 326 | // If it's the admin or moderation center, and there is an area set, use that instead. |
314 | - if (isset($actions['action']) && ($actions['action'] == 'admin' || $actions['action'] == 'moderate') && isset($actions['area'])) |
|
315 | - $actions['action'] = $actions['area']; |
|
327 | + if (isset($actions['action']) && ($actions['action'] == 'admin' || $actions['action'] == 'moderate') && isset($actions['area'])) { |
|
328 | + $actions['action'] = $actions['area']; |
|
329 | + } |
|
316 | 330 | |
317 | 331 | // Check if there was no action or the action is display. |
318 | 332 | if (!isset($actions['action']) || $actions['action'] == 'display') |
@@ -332,12 +346,14 @@ discard block |
||
332 | 346 | $board_ids[$actions['board']][$k] = $txt['who_board']; |
333 | 347 | } |
334 | 348 | // It's the board index!! It must be! |
335 | - else |
|
336 | - $data[$k] = $txt['who_index']; |
|
349 | + else { |
|
350 | + $data[$k] = $txt['who_index']; |
|
351 | + } |
|
337 | 352 | } |
338 | 353 | // Probably an error or some goon? |
339 | - elseif ($actions['action'] == '') |
|
340 | - $data[$k] = $txt['who_index']; |
|
354 | + elseif ($actions['action'] == '') { |
|
355 | + $data[$k] = $txt['who_index']; |
|
356 | + } |
|
341 | 357 | // Some other normal action...? |
342 | 358 | else |
343 | 359 | { |
@@ -345,23 +361,25 @@ discard block |
||
345 | 361 | if ($actions['action'] == 'profile') |
346 | 362 | { |
347 | 363 | // Whose? Their own? |
348 | - if (empty($actions['u'])) |
|
349 | - $actions['u'] = $url[1]; |
|
364 | + if (empty($actions['u'])) { |
|
365 | + $actions['u'] = $url[1]; |
|
366 | + } |
|
350 | 367 | |
351 | 368 | $data[$k] = $txt['who_hidden']; |
352 | 369 | $profile_ids[(int) $actions['u']][$k] = $actions['u'] == $url[1] ? $txt['who_viewownprofile'] : $txt['who_viewprofile']; |
353 | - } |
|
354 | - elseif (($actions['action'] == 'post' || $actions['action'] == 'post2') && empty($actions['topic']) && isset($actions['board'])) |
|
370 | + } elseif (($actions['action'] == 'post' || $actions['action'] == 'post2') && empty($actions['topic']) && isset($actions['board'])) |
|
355 | 371 | { |
356 | 372 | $data[$k] = $txt['who_hidden']; |
357 | 373 | $board_ids[(int) $actions['board']][$k] = isset($actions['poll']) ? $txt['who_poll'] : $txt['who_post']; |
358 | 374 | } |
359 | 375 | // A subaction anyone can view... if the language string is there, show it. |
360 | - elseif (isset($actions['sa']) && isset($txt['whoall_' . $actions['action'] . '_' . $actions['sa']])) |
|
361 | - $data[$k] = $preferred_prefix && isset($txt[$preferred_prefix . $actions['action'] . '_' . $actions['sa']]) ? $txt[$preferred_prefix . $actions['action'] . '_' . $actions['sa']] : $txt['whoall_' . $actions['action'] . '_' . $actions['sa']]; |
|
376 | + elseif (isset($actions['sa']) && isset($txt['whoall_' . $actions['action'] . '_' . $actions['sa']])) { |
|
377 | + $data[$k] = $preferred_prefix && isset($txt[$preferred_prefix . $actions['action'] . '_' . $actions['sa']]) ? $txt[$preferred_prefix . $actions['action'] . '_' . $actions['sa']] : $txt['whoall_' . $actions['action'] . '_' . $actions['sa']]; |
|
378 | + } |
|
362 | 379 | // An action any old fellow can look at. (if ['whoall_' . $action] exists, we know everyone can see it.) |
363 | - elseif (isset($txt['whoall_' . $actions['action']])) |
|
364 | - $data[$k] = $preferred_prefix && isset($txt[$preferred_prefix . $actions['action']]) ? $txt[$preferred_prefix . $actions['action']] : $txt['whoall_' . $actions['action']]; |
|
380 | + elseif (isset($txt['whoall_' . $actions['action']])) { |
|
381 | + $data[$k] = $preferred_prefix && isset($txt[$preferred_prefix . $actions['action']]) ? $txt[$preferred_prefix . $actions['action']] : $txt['whoall_' . $actions['action']]; |
|
382 | + } |
|
365 | 383 | // Viewable if and only if they can see the board... |
366 | 384 | elseif (isset($txt['whotopic_' . $actions['action']])) |
367 | 385 | { |
@@ -370,8 +388,7 @@ discard block |
||
370 | 388 | |
371 | 389 | $data[$k] = $txt['who_hidden']; |
372 | 390 | $topic_ids[$topic][$k] = $txt['whotopic_' . $actions['action']]; |
373 | - } |
|
374 | - elseif (isset($txt['whopost_' . $actions['action']])) |
|
391 | + } elseif (isset($txt['whopost_' . $actions['action']])) |
|
375 | 392 | { |
376 | 393 | // Find out what message they are accessing. |
377 | 394 | $msgid = (int) (isset($actions['msg']) ? $actions['msg'] : (isset($actions['quote']) ? $actions['quote'] : 0)); |
@@ -394,41 +411,46 @@ discard block |
||
394 | 411 | $data[$k] = sprintf($txt['whopost_' . $actions['action']], $id_topic, $subject); |
395 | 412 | $smcFunc['db_free_result']($result); |
396 | 413 | |
397 | - if (empty($id_topic)) |
|
398 | - $data[$k] = $txt['who_hidden']; |
|
414 | + if (empty($id_topic)) { |
|
415 | + $data[$k] = $txt['who_hidden']; |
|
416 | + } |
|
399 | 417 | } |
400 | 418 | // Viewable only by administrators.. (if it starts with whoadmin, it's admin only!) |
401 | - elseif (allowedTo('moderate_forum') && isset($txt['whoadmin_' . $actions['action']])) |
|
402 | - $data[$k] = $txt['whoadmin_' . $actions['action']]; |
|
419 | + elseif (allowedTo('moderate_forum') && isset($txt['whoadmin_' . $actions['action']])) { |
|
420 | + $data[$k] = $txt['whoadmin_' . $actions['action']]; |
|
421 | + } |
|
403 | 422 | // Viewable by permission level. |
404 | 423 | elseif (isset($allowedActions[$actions['action']])) |
405 | 424 | { |
406 | - if (allowedTo($allowedActions[$actions['action']])) |
|
407 | - $data[$k] = $txt['whoallow_' . $actions['action']]; |
|
408 | - elseif (in_array('moderate_forum', $allowedActions[$actions['action']])) |
|
409 | - $data[$k] = $txt['who_moderate']; |
|
410 | - elseif (in_array('admin_forum', $allowedActions[$actions['action']])) |
|
411 | - $data[$k] = $txt['who_admin']; |
|
412 | - else |
|
413 | - $data[$k] = $txt['who_hidden']; |
|
425 | + if (allowedTo($allowedActions[$actions['action']])) { |
|
426 | + $data[$k] = $txt['whoallow_' . $actions['action']]; |
|
427 | + } elseif (in_array('moderate_forum', $allowedActions[$actions['action']])) { |
|
428 | + $data[$k] = $txt['who_moderate']; |
|
429 | + } elseif (in_array('admin_forum', $allowedActions[$actions['action']])) { |
|
430 | + $data[$k] = $txt['who_admin']; |
|
431 | + } else { |
|
432 | + $data[$k] = $txt['who_hidden']; |
|
433 | + } |
|
434 | + } elseif (!empty($actions['action'])) { |
|
435 | + $data[$k] = $txt['who_generic'] . ' ' . $actions['action']; |
|
436 | + } else { |
|
437 | + $data[$k] = $txt['who_unknown']; |
|
414 | 438 | } |
415 | - elseif (!empty($actions['action'])) |
|
416 | - $data[$k] = $txt['who_generic'] . ' ' . $actions['action']; |
|
417 | - else |
|
418 | - $data[$k] = $txt['who_unknown']; |
|
419 | 439 | } |
420 | 440 | |
421 | 441 | if (isset($actions['error'])) |
422 | 442 | { |
423 | - if (isset($txt[$actions['error']])) |
|
424 | - $error_message = str_replace('"', '"', empty($actions['who_error_params']) ? $txt[$actions['error']] : vsprintf($txt[$actions['error']], $actions['who_error_params'])); |
|
425 | - elseif ($actions['error'] == 'guest_login') |
|
426 | - $error_message = str_replace('"', '"', $txt['who_guest_login']); |
|
427 | - else |
|
428 | - $error_message = str_replace('"', '"', $actions['error']); |
|
429 | - |
|
430 | - if (!empty($error_message)) |
|
431 | - $data[$k] .= ' <span class="generic_icons error" title="' . $error_message . '"></span>'; |
|
443 | + if (isset($txt[$actions['error']])) { |
|
444 | + $error_message = str_replace('"', '"', empty($actions['who_error_params']) ? $txt[$actions['error']] : vsprintf($txt[$actions['error']], $actions['who_error_params'])); |
|
445 | + } elseif ($actions['error'] == 'guest_login') { |
|
446 | + $error_message = str_replace('"', '"', $txt['who_guest_login']); |
|
447 | + } else { |
|
448 | + $error_message = str_replace('"', '"', $actions['error']); |
|
449 | + } |
|
450 | + |
|
451 | + if (!empty($error_message)) { |
|
452 | + $data[$k] .= ' <span class="generic_icons error" title="' . $error_message . '"></span>'; |
|
453 | + } |
|
432 | 454 | } |
433 | 455 | |
434 | 456 | // Maybe the action is integrated into another system? |
@@ -439,12 +461,15 @@ discard block |
||
439 | 461 | if (!empty($integrate_action)) |
440 | 462 | { |
441 | 463 | $data[$k] = $integrate_action; |
442 | - if (isset($actions['topic']) && isset($topic_ids[(int) $actions['topic']][$k])) |
|
443 | - $topic_ids[(int) $actions['topic']][$k] = $integrate_action; |
|
444 | - if (isset($actions['board']) && isset($board_ids[(int) $actions['board']][$k])) |
|
445 | - $board_ids[(int) $actions['board']][$k] = $integrate_action; |
|
446 | - if (isset($actions['u']) && isset($profile_ids[(int) $actions['u']][$k])) |
|
447 | - $profile_ids[(int) $actions['u']][$k] = $integrate_action; |
|
464 | + if (isset($actions['topic']) && isset($topic_ids[(int) $actions['topic']][$k])) { |
|
465 | + $topic_ids[(int) $actions['topic']][$k] = $integrate_action; |
|
466 | + } |
|
467 | + if (isset($actions['board']) && isset($board_ids[(int) $actions['board']][$k])) { |
|
468 | + $board_ids[(int) $actions['board']][$k] = $integrate_action; |
|
469 | + } |
|
470 | + if (isset($actions['u']) && isset($profile_ids[(int) $actions['u']][$k])) { |
|
471 | + $profile_ids[(int) $actions['u']][$k] = $integrate_action; |
|
472 | + } |
|
448 | 473 | break; |
449 | 474 | } |
450 | 475 | } |
@@ -472,8 +497,9 @@ discard block |
||
472 | 497 | while ($row = $smcFunc['db_fetch_assoc']($result)) |
473 | 498 | { |
474 | 499 | // Show the topic's subject for each of the actions. |
475 | - foreach ($topic_ids[$row['id_topic']] as $k => $session_text) |
|
476 | - $data[$k] = sprintf($session_text, $row['id_topic'], censorText($row['subject'])); |
|
500 | + foreach ($topic_ids[$row['id_topic']] as $k => $session_text) { |
|
501 | + $data[$k] = sprintf($session_text, $row['id_topic'], censorText($row['subject'])); |
|
502 | + } |
|
477 | 503 | } |
478 | 504 | $smcFunc['db_free_result']($result); |
479 | 505 | } |
@@ -495,8 +521,9 @@ discard block |
||
495 | 521 | while ($row = $smcFunc['db_fetch_assoc']($result)) |
496 | 522 | { |
497 | 523 | // Put the board name into the string for each member... |
498 | - foreach ($board_ids[$row['id_board']] as $k => $session_text) |
|
499 | - $data[$k] = sprintf($session_text, $row['id_board'], $row['name']); |
|
524 | + foreach ($board_ids[$row['id_board']] as $k => $session_text) { |
|
525 | + $data[$k] = sprintf($session_text, $row['id_board'], $row['name']); |
|
526 | + } |
|
500 | 527 | } |
501 | 528 | $smcFunc['db_free_result']($result); |
502 | 529 | } |
@@ -518,23 +545,26 @@ discard block |
||
518 | 545 | while ($row = $smcFunc['db_fetch_assoc']($result)) |
519 | 546 | { |
520 | 547 | // If they aren't allowed to view this person's profile, skip it. |
521 | - if (!$allow_view_any && ($user_info['id'] != $row['id_member'])) |
|
522 | - continue; |
|
548 | + if (!$allow_view_any && ($user_info['id'] != $row['id_member'])) { |
|
549 | + continue; |
|
550 | + } |
|
523 | 551 | |
524 | 552 | // Set their action on each - session/text to sprintf. |
525 | - foreach ($profile_ids[$row['id_member']] as $k => $session_text) |
|
526 | - $data[$k] = sprintf($session_text, $row['id_member'], $row['real_name']); |
|
553 | + foreach ($profile_ids[$row['id_member']] as $k => $session_text) { |
|
554 | + $data[$k] = sprintf($session_text, $row['id_member'], $row['real_name']); |
|
555 | + } |
|
527 | 556 | } |
528 | 557 | $smcFunc['db_free_result']($result); |
529 | 558 | } |
530 | 559 | |
531 | 560 | call_integration_hook('whos_online_after', array(&$urls, &$data)); |
532 | 561 | |
533 | - if (!is_array($urls)) |
|
534 | - return isset($data[0]) ? $data[0] : false; |
|
535 | - else |
|
536 | - return $data; |
|
537 | -} |
|
562 | + if (!is_array($urls)) { |
|
563 | + return isset($data[0]) ? $data[0] : false; |
|
564 | + } else { |
|
565 | + return $data; |
|
566 | + } |
|
567 | + } |
|
538 | 568 | |
539 | 569 | /** |
540 | 570 | * It prepares credit and copyright information for the credits page or the admin page |
@@ -710,8 +740,8 @@ discard block |
||
710 | 740 | ); |
711 | 741 | |
712 | 742 | // Give the translators some credit for their hard work. |
713 | - if (!empty($txt['translation_credits'])) |
|
714 | - $context['credits'][] = array( |
|
743 | + if (!empty($txt['translation_credits'])) { |
|
744 | + $context['credits'][] = array( |
|
715 | 745 | 'title' => $txt['credits_groups_translation'], |
716 | 746 | 'groups' => array( |
717 | 747 | array( |
@@ -720,6 +750,7 @@ discard block |
||
720 | 750 | ), |
721 | 751 | ), |
722 | 752 | ); |
753 | + } |
|
723 | 754 | |
724 | 755 | $context['credits'][] = array( |
725 | 756 | 'title' => $txt['credits_special'], |
@@ -104,7 +104,7 @@ |
||
104 | 104 | * |
105 | 105 | * @param string $class The fully-qualified class name. |
106 | 106 | */ |
107 | -spl_autoload_register(function ($class) use ($sourcedir) |
|
107 | +spl_autoload_register(function($class) use ($sourcedir) |
|
108 | 108 | { |
109 | 109 | $classMap = array( |
110 | 110 | 'ReCaptcha\\' => 'ReCaptcha/', |
@@ -32,16 +32,18 @@ discard block |
||
32 | 32 | ob_start(); |
33 | 33 | |
34 | 34 | // Do some cleaning, just in case. |
35 | -foreach (array('db_character_set', 'cachedir') as $variable) |
|
35 | +foreach (array('db_character_set', 'cachedir') as $variable) { |
|
36 | 36 | if (isset($GLOBALS[$variable])) |
37 | 37 | unset($GLOBALS[$variable], $GLOBALS[$variable]); |
38 | +} |
|
38 | 39 | |
39 | 40 | // Load the settings... |
40 | 41 | require_once(dirname(__FILE__) . '/Settings.php'); |
41 | 42 | |
42 | 43 | // Make absolutely sure the cache directory is defined. |
43 | -if ((empty($cachedir) || !file_exists($cachedir)) && file_exists($boarddir . '/cache')) |
|
44 | +if ((empty($cachedir) || !file_exists($cachedir)) && file_exists($boarddir . '/cache')) { |
|
44 | 45 | $cachedir = $boarddir . '/cache'; |
46 | +} |
|
45 | 47 | |
46 | 48 | // Without those we can't go anywhere |
47 | 49 | require_once($sourcedir . '/QueryString.php'); |
@@ -51,8 +53,9 @@ discard block |
||
51 | 53 | require_once($sourcedir . '/Load.php'); |
52 | 54 | |
53 | 55 | // If $maintenance is set specifically to 2, then we're upgrading or something. |
54 | -if (!empty($maintenance) && $maintenance == 2) |
|
56 | +if (!empty($maintenance) && $maintenance == 2) { |
|
55 | 57 | display_maintenance_message(); |
58 | +} |
|
56 | 59 | |
57 | 60 | // Create a variable to store some SMF specific functions in. |
58 | 61 | $smcFunc = array(); |
@@ -67,8 +70,9 @@ discard block |
||
67 | 70 | cleanRequest(); |
68 | 71 | |
69 | 72 | // Seed the random generator. |
70 | -if (empty($modSettings['rand_seed']) || mt_rand(1, 250) == 69) |
|
73 | +if (empty($modSettings['rand_seed']) || mt_rand(1, 250) == 69) { |
|
71 | 74 | smf_seed_generator(); |
75 | +} |
|
72 | 76 | |
73 | 77 | // Before we get carried away, are we doing a scheduled task? If so save CPU cycles by jumping out! |
74 | 78 | if (isset($_GET['scheduled'])) |
@@ -88,9 +92,9 @@ discard block |
||
88 | 92 | if (!empty($modSettings['enableCompressedOutput']) && !headers_sent()) |
89 | 93 | { |
90 | 94 | // If zlib is being used, turn off output compression. |
91 | - if (ini_get('zlib.output_compression') >= 1 || ini_get('output_handler') == 'ob_gzhandler') |
|
92 | - $modSettings['enableCompressedOutput'] = '0'; |
|
93 | - else |
|
95 | + if (ini_get('zlib.output_compression') >= 1 || ini_get('output_handler') == 'ob_gzhandler') { |
|
96 | + $modSettings['enableCompressedOutput'] = '0'; |
|
97 | + } else |
|
94 | 98 | { |
95 | 99 | ob_end_clean(); |
96 | 100 | ob_start('ob_gzhandler'); |
@@ -182,18 +186,21 @@ discard block |
||
182 | 186 | loadPermissions(); |
183 | 187 | |
184 | 188 | // Attachments don't require the entire theme to be loaded. |
185 | - if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'dlattach') |
|
186 | - detectBrowser(); |
|
189 | + if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'dlattach') { |
|
190 | + detectBrowser(); |
|
191 | + } |
|
187 | 192 | // Load the current theme. (note that ?theme=1 will also work, may be used for guest theming.) |
188 | - else |
|
189 | - loadTheme(); |
|
193 | + else { |
|
194 | + loadTheme(); |
|
195 | + } |
|
190 | 196 | |
191 | 197 | // Check if the user should be disallowed access. |
192 | 198 | is_not_banned(); |
193 | 199 | |
194 | 200 | // If we are in a topic and don't have permission to approve it then duck out now. |
195 | - if (!empty($topic) && empty($board_info['cur_topic_approved']) && !allowedTo('approve_posts') && ($user_info['id'] != $board_info['cur_topic_starter'] || $user_info['is_guest'])) |
|
196 | - fatal_lang_error('not_a_topic', false); |
|
201 | + if (!empty($topic) && empty($board_info['cur_topic_approved']) && !allowedTo('approve_posts') && ($user_info['id'] != $board_info['cur_topic_starter'] || $user_info['is_guest'])) { |
|
202 | + fatal_lang_error('not_a_topic', false); |
|
203 | + } |
|
197 | 204 | |
198 | 205 | $no_stat_actions = array('clock', 'dlattach', 'findmember', 'jsoption', 'likes', 'loadeditorlocale', 'modifycat', 'requestmembers', 'smstats', 'suggest', 'about:unknown', '.xml', 'xmlhttp', 'verificationcode', 'viewquery', 'viewsmfile'); |
199 | 206 | call_integration_hook('integrate_pre_log_stats', array(&$no_stat_actions)); |
@@ -204,8 +211,9 @@ discard block |
||
204 | 211 | writeLog(); |
205 | 212 | |
206 | 213 | // Track forum statistics and hits...? |
207 | - if (!empty($modSettings['hitStats'])) |
|
208 | - trackStats(array('hits' => '+')); |
|
214 | + if (!empty($modSettings['hitStats'])) { |
|
215 | + trackStats(array('hits' => '+')); |
|
216 | + } |
|
209 | 217 | } |
210 | 218 | unset($no_stat_actions); |
211 | 219 | |
@@ -219,13 +227,14 @@ discard block |
||
219 | 227 | return ($_REQUEST['action'] == 'login2' ? 'Login2' : ($_REQUEST['action'] == 'logintfa' ? 'LoginTFA' : 'Logout')); |
220 | 228 | } |
221 | 229 | // Don't even try it, sonny. |
222 | - else |
|
223 | - return 'InMaintenance'; |
|
230 | + else { |
|
231 | + return 'InMaintenance'; |
|
232 | + } |
|
224 | 233 | } |
225 | 234 | // If guest access is off, a guest can only do one of the very few following actions. |
226 | - elseif (empty($modSettings['allow_guestAccess']) && $user_info['is_guest'] && (!isset($_REQUEST['action']) || !in_array($_REQUEST['action'], array('coppa', 'login', 'login2', 'logintfa', 'reminder', 'activate', 'help', 'helpadmin', 'smstats', 'verificationcode', 'signup', 'signup2')))) |
|
227 | - return 'KickGuest'; |
|
228 | - elseif (empty($_REQUEST['action'])) |
|
235 | + elseif (empty($modSettings['allow_guestAccess']) && $user_info['is_guest'] && (!isset($_REQUEST['action']) || !in_array($_REQUEST['action'], array('coppa', 'login', 'login2', 'logintfa', 'reminder', 'activate', 'help', 'helpadmin', 'smstats', 'verificationcode', 'signup', 'signup2')))) { |
|
236 | + return 'KickGuest'; |
|
237 | + } elseif (empty($_REQUEST['action'])) |
|
229 | 238 | { |
230 | 239 | // Action and board are both empty... BoardIndex! Unless someone else wants to do something different. |
231 | 240 | if (empty($board) && empty($topic)) |
@@ -239,8 +248,9 @@ discard block |
||
239 | 248 | |
240 | 249 | $call = call_helper($defaultAction, true); |
241 | 250 | |
242 | - if (!empty($call)) |
|
243 | - return $call; |
|
251 | + if (!empty($call)) { |
|
252 | + return $call; |
|
253 | + } |
|
244 | 254 | } |
245 | 255 | |
246 | 256 | // No default action huh? then go to our good old BoardIndex. |
@@ -370,8 +380,9 @@ discard block |
||
370 | 380 | |
371 | 381 | $call = call_helper($fallbackAction, true); |
372 | 382 | |
373 | - if (!empty($call)) |
|
374 | - return $call; |
|
383 | + if (!empty($call)) { |
|
384 | + return $call; |
|
385 | + } |
|
375 | 386 | } |
376 | 387 | |
377 | 388 | // No fallback action, huh? |
@@ -18,178 +18,178 @@ |
||
18 | 18 | */ |
19 | 19 | class Converter |
20 | 20 | { |
21 | - /** |
|
22 | - * @var string |
|
23 | - */ |
|
24 | - protected $from; |
|
25 | - |
|
26 | - /** |
|
27 | - * @var string |
|
28 | - */ |
|
29 | - protected $to; |
|
30 | - |
|
31 | - /** |
|
32 | - * @param string $from The original base path (directory, not file!) |
|
33 | - * @param string $to The new base path (directory, not file!) |
|
34 | - */ |
|
35 | - public function __construct($from, $to) |
|
36 | - { |
|
37 | - $shared = $this->shared($from, $to); |
|
38 | - if ($shared === '') { |
|
39 | - // when both paths have nothing in common, one of them is probably |
|
40 | - // absolute while the other is relative |
|
41 | - $cwd = getcwd(); |
|
42 | - $from = strpos($from, $cwd) === 0 ? $from : $cwd.'/'.$from; |
|
43 | - $to = strpos($to, $cwd) === 0 ? $to : $cwd.'/'.$to; |
|
44 | - |
|
45 | - // or traveling the tree via `..` |
|
46 | - // attempt to resolve path, or assume it's fine if it doesn't exist |
|
47 | - $from = realpath($from) ?: $from; |
|
48 | - $to = realpath($to) ?: $to; |
|
49 | - } |
|
50 | - |
|
51 | - $from = $this->dirname($from); |
|
52 | - $to = $this->dirname($to); |
|
53 | - |
|
54 | - $from = $this->normalize($from); |
|
55 | - $to = $this->normalize($to); |
|
56 | - |
|
57 | - $this->from = $from; |
|
58 | - $this->to = $to; |
|
59 | - } |
|
60 | - |
|
61 | - /** |
|
62 | - * Normalize path. |
|
63 | - * |
|
64 | - * @param string $path |
|
65 | - * |
|
66 | - * @return string |
|
67 | - */ |
|
68 | - protected function normalize($path) |
|
69 | - { |
|
70 | - // deal with different operating systems' directory structure |
|
71 | - $path = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '/'); |
|
72 | - |
|
73 | - /* |
|
21 | + /** |
|
22 | + * @var string |
|
23 | + */ |
|
24 | + protected $from; |
|
25 | + |
|
26 | + /** |
|
27 | + * @var string |
|
28 | + */ |
|
29 | + protected $to; |
|
30 | + |
|
31 | + /** |
|
32 | + * @param string $from The original base path (directory, not file!) |
|
33 | + * @param string $to The new base path (directory, not file!) |
|
34 | + */ |
|
35 | + public function __construct($from, $to) |
|
36 | + { |
|
37 | + $shared = $this->shared($from, $to); |
|
38 | + if ($shared === '') { |
|
39 | + // when both paths have nothing in common, one of them is probably |
|
40 | + // absolute while the other is relative |
|
41 | + $cwd = getcwd(); |
|
42 | + $from = strpos($from, $cwd) === 0 ? $from : $cwd.'/'.$from; |
|
43 | + $to = strpos($to, $cwd) === 0 ? $to : $cwd.'/'.$to; |
|
44 | + |
|
45 | + // or traveling the tree via `..` |
|
46 | + // attempt to resolve path, or assume it's fine if it doesn't exist |
|
47 | + $from = realpath($from) ?: $from; |
|
48 | + $to = realpath($to) ?: $to; |
|
49 | + } |
|
50 | + |
|
51 | + $from = $this->dirname($from); |
|
52 | + $to = $this->dirname($to); |
|
53 | + |
|
54 | + $from = $this->normalize($from); |
|
55 | + $to = $this->normalize($to); |
|
56 | + |
|
57 | + $this->from = $from; |
|
58 | + $this->to = $to; |
|
59 | + } |
|
60 | + |
|
61 | + /** |
|
62 | + * Normalize path. |
|
63 | + * |
|
64 | + * @param string $path |
|
65 | + * |
|
66 | + * @return string |
|
67 | + */ |
|
68 | + protected function normalize($path) |
|
69 | + { |
|
70 | + // deal with different operating systems' directory structure |
|
71 | + $path = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '/'); |
|
72 | + |
|
73 | + /* |
|
74 | 74 | * Example: |
75 | 75 | * /home/forkcms/frontend/cache/compiled_templates/../../core/layout/css/../images/img.gif |
76 | 76 | * to |
77 | 77 | * /home/forkcms/frontend/core/layout/images/img.gif |
78 | 78 | */ |
79 | - do { |
|
80 | - $path = preg_replace('/[^\/]+(?<!\.\.)\/\.\.\//', '', $path, -1, $count); |
|
81 | - } while ($count); |
|
82 | - |
|
83 | - return $path; |
|
84 | - } |
|
85 | - |
|
86 | - /** |
|
87 | - * Figure out the shared path of 2 locations. |
|
88 | - * |
|
89 | - * Example: |
|
90 | - * /home/forkcms/frontend/core/layout/images/img.gif |
|
91 | - * and |
|
92 | - * /home/forkcms/frontend/cache/minified_css |
|
93 | - * share |
|
94 | - * /home/forkcms/frontend |
|
95 | - * |
|
96 | - * @param string $path1 |
|
97 | - * @param string $path2 |
|
98 | - * |
|
99 | - * @return string |
|
100 | - */ |
|
101 | - protected function shared($path1, $path2) |
|
102 | - { |
|
103 | - // $path could theoretically be empty (e.g. no path is given), in which |
|
104 | - // case it shouldn't expand to array(''), which would compare to one's |
|
105 | - // root / |
|
106 | - $path1 = $path1 ? explode('/', $path1) : array(); |
|
107 | - $path2 = $path2 ? explode('/', $path2) : array(); |
|
108 | - |
|
109 | - $shared = array(); |
|
110 | - |
|
111 | - // compare paths & strip identical ancestors |
|
112 | - foreach ($path1 as $i => $chunk) { |
|
113 | - if (isset($path2[$i]) && $path1[$i] == $path2[$i]) { |
|
114 | - $shared[] = $chunk; |
|
115 | - } else { |
|
116 | - break; |
|
117 | - } |
|
118 | - } |
|
119 | - |
|
120 | - return implode('/', $shared); |
|
121 | - } |
|
122 | - |
|
123 | - /** |
|
124 | - * Convert paths relative from 1 file to another. |
|
125 | - * |
|
126 | - * E.g. |
|
127 | - * ../images/img.gif relative to /home/forkcms/frontend/core/layout/css |
|
128 | - * should become: |
|
129 | - * ../../core/layout/images/img.gif relative to |
|
130 | - * /home/forkcms/frontend/cache/minified_css |
|
131 | - * |
|
132 | - * @param string $path The relative path that needs to be converted. |
|
133 | - * |
|
134 | - * @return string The new relative path. |
|
135 | - */ |
|
136 | - public function convert($path) |
|
137 | - { |
|
138 | - // quit early if conversion makes no sense |
|
139 | - if ($this->from === $this->to) { |
|
140 | - return $path; |
|
141 | - } |
|
142 | - |
|
143 | - $path = $this->normalize($path); |
|
144 | - // if we're not dealing with a relative path, just return absolute |
|
145 | - if (strpos($path, '/') === 0) { |
|
146 | - return $path; |
|
147 | - } |
|
148 | - |
|
149 | - // normalize paths |
|
150 | - $path = $this->normalize($this->from.'/'.$path); |
|
151 | - |
|
152 | - // strip shared ancestor paths |
|
153 | - $shared = $this->shared($path, $this->to); |
|
154 | - $path = mb_substr($path, mb_strlen($shared)); |
|
155 | - $to = mb_substr($this->to, mb_strlen($shared)); |
|
156 | - |
|
157 | - // add .. for every directory that needs to be traversed to new path |
|
158 | - $to = str_repeat('../', mb_substr_count($to, '/')); |
|
159 | - |
|
160 | - return $to.ltrim($path, '/'); |
|
161 | - } |
|
162 | - |
|
163 | - /** |
|
164 | - * Attempt to get the directory name from a path. |
|
165 | - * |
|
166 | - * @param string $path |
|
167 | - * |
|
168 | - * @return string |
|
169 | - */ |
|
170 | - public function dirname($path) |
|
171 | - { |
|
172 | - if (is_file($path)) { |
|
173 | - return dirname($path); |
|
174 | - } |
|
175 | - |
|
176 | - if (is_dir($path)) { |
|
177 | - return rtrim($path, '/'); |
|
178 | - } |
|
179 | - |
|
180 | - // no known file/dir, start making assumptions |
|
181 | - |
|
182 | - // ends in / = dir |
|
183 | - if (mb_substr($path, -1) === '/') { |
|
184 | - return rtrim($path, '/'); |
|
185 | - } |
|
186 | - |
|
187 | - // has a dot in the name, likely a file |
|
188 | - if (preg_match('/.*\..*$/', basename($path)) !== 0) { |
|
189 | - return dirname($path); |
|
190 | - } |
|
191 | - |
|
192 | - // you're on your own here! |
|
193 | - return $path; |
|
194 | - } |
|
79 | + do { |
|
80 | + $path = preg_replace('/[^\/]+(?<!\.\.)\/\.\.\//', '', $path, -1, $count); |
|
81 | + } while ($count); |
|
82 | + |
|
83 | + return $path; |
|
84 | + } |
|
85 | + |
|
86 | + /** |
|
87 | + * Figure out the shared path of 2 locations. |
|
88 | + * |
|
89 | + * Example: |
|
90 | + * /home/forkcms/frontend/core/layout/images/img.gif |
|
91 | + * and |
|
92 | + * /home/forkcms/frontend/cache/minified_css |
|
93 | + * share |
|
94 | + * /home/forkcms/frontend |
|
95 | + * |
|
96 | + * @param string $path1 |
|
97 | + * @param string $path2 |
|
98 | + * |
|
99 | + * @return string |
|
100 | + */ |
|
101 | + protected function shared($path1, $path2) |
|
102 | + { |
|
103 | + // $path could theoretically be empty (e.g. no path is given), in which |
|
104 | + // case it shouldn't expand to array(''), which would compare to one's |
|
105 | + // root / |
|
106 | + $path1 = $path1 ? explode('/', $path1) : array(); |
|
107 | + $path2 = $path2 ? explode('/', $path2) : array(); |
|
108 | + |
|
109 | + $shared = array(); |
|
110 | + |
|
111 | + // compare paths & strip identical ancestors |
|
112 | + foreach ($path1 as $i => $chunk) { |
|
113 | + if (isset($path2[$i]) && $path1[$i] == $path2[$i]) { |
|
114 | + $shared[] = $chunk; |
|
115 | + } else { |
|
116 | + break; |
|
117 | + } |
|
118 | + } |
|
119 | + |
|
120 | + return implode('/', $shared); |
|
121 | + } |
|
122 | + |
|
123 | + /** |
|
124 | + * Convert paths relative from 1 file to another. |
|
125 | + * |
|
126 | + * E.g. |
|
127 | + * ../images/img.gif relative to /home/forkcms/frontend/core/layout/css |
|
128 | + * should become: |
|
129 | + * ../../core/layout/images/img.gif relative to |
|
130 | + * /home/forkcms/frontend/cache/minified_css |
|
131 | + * |
|
132 | + * @param string $path The relative path that needs to be converted. |
|
133 | + * |
|
134 | + * @return string The new relative path. |
|
135 | + */ |
|
136 | + public function convert($path) |
|
137 | + { |
|
138 | + // quit early if conversion makes no sense |
|
139 | + if ($this->from === $this->to) { |
|
140 | + return $path; |
|
141 | + } |
|
142 | + |
|
143 | + $path = $this->normalize($path); |
|
144 | + // if we're not dealing with a relative path, just return absolute |
|
145 | + if (strpos($path, '/') === 0) { |
|
146 | + return $path; |
|
147 | + } |
|
148 | + |
|
149 | + // normalize paths |
|
150 | + $path = $this->normalize($this->from.'/'.$path); |
|
151 | + |
|
152 | + // strip shared ancestor paths |
|
153 | + $shared = $this->shared($path, $this->to); |
|
154 | + $path = mb_substr($path, mb_strlen($shared)); |
|
155 | + $to = mb_substr($this->to, mb_strlen($shared)); |
|
156 | + |
|
157 | + // add .. for every directory that needs to be traversed to new path |
|
158 | + $to = str_repeat('../', mb_substr_count($to, '/')); |
|
159 | + |
|
160 | + return $to.ltrim($path, '/'); |
|
161 | + } |
|
162 | + |
|
163 | + /** |
|
164 | + * Attempt to get the directory name from a path. |
|
165 | + * |
|
166 | + * @param string $path |
|
167 | + * |
|
168 | + * @return string |
|
169 | + */ |
|
170 | + public function dirname($path) |
|
171 | + { |
|
172 | + if (is_file($path)) { |
|
173 | + return dirname($path); |
|
174 | + } |
|
175 | + |
|
176 | + if (is_dir($path)) { |
|
177 | + return rtrim($path, '/'); |
|
178 | + } |
|
179 | + |
|
180 | + // no known file/dir, start making assumptions |
|
181 | + |
|
182 | + // ends in / = dir |
|
183 | + if (mb_substr($path, -1) === '/') { |
|
184 | + return rtrim($path, '/'); |
|
185 | + } |
|
186 | + |
|
187 | + // has a dot in the name, likely a file |
|
188 | + if (preg_match('/.*\..*$/', basename($path)) !== 0) { |
|
189 | + return dirname($path); |
|
190 | + } |
|
191 | + |
|
192 | + // you're on your own here! |
|
193 | + return $path; |
|
194 | + } |
|
195 | 195 | } |
@@ -39,8 +39,8 @@ discard block |
||
39 | 39 | // when both paths have nothing in common, one of them is probably |
40 | 40 | // absolute while the other is relative |
41 | 41 | $cwd = getcwd(); |
42 | - $from = strpos($from, $cwd) === 0 ? $from : $cwd.'/'.$from; |
|
43 | - $to = strpos($to, $cwd) === 0 ? $to : $cwd.'/'.$to; |
|
42 | + $from = strpos($from, $cwd) === 0 ? $from : $cwd . '/' . $from; |
|
43 | + $to = strpos($to, $cwd) === 0 ? $to : $cwd . '/' . $to; |
|
44 | 44 | |
45 | 45 | // or traveling the tree via `..` |
46 | 46 | // attempt to resolve path, or assume it's fine if it doesn't exist |
@@ -147,7 +147,7 @@ discard block |
||
147 | 147 | } |
148 | 148 | |
149 | 149 | // normalize paths |
150 | - $path = $this->normalize($this->from.'/'.$path); |
|
150 | + $path = $this->normalize($this->from . '/' . $path); |
|
151 | 151 | |
152 | 152 | // strip shared ancestor paths |
153 | 153 | $shared = $this->shared($path, $this->to); |
@@ -157,7 +157,7 @@ discard block |
||
157 | 157 | // add .. for every directory that needs to be traversed to new path |
158 | 158 | $to = str_repeat('../', mb_substr_count($to, '/')); |
159 | 159 | |
160 | - return $to.ltrim($path, '/'); |
|
160 | + return $to . ltrim($path, '/'); |
|
161 | 161 | } |
162 | 162 | |
163 | 163 | /** |
@@ -17,96 +17,96 @@ discard block |
||
17 | 17 | */ |
18 | 18 | class CSS extends Minify |
19 | 19 | { |
20 | - /** |
|
21 | - * @var int |
|
22 | - */ |
|
23 | - protected $maxImportSize = 5; |
|
24 | - |
|
25 | - /** |
|
26 | - * @var string[] |
|
27 | - */ |
|
28 | - protected $importExtensions = array( |
|
29 | - 'gif' => 'data:image/gif', |
|
30 | - 'png' => 'data:image/png', |
|
31 | - 'jpe' => 'data:image/jpeg', |
|
32 | - 'jpg' => 'data:image/jpeg', |
|
33 | - 'jpeg' => 'data:image/jpeg', |
|
34 | - 'svg' => 'data:image/svg+xml', |
|
35 | - 'woff' => 'data:application/x-font-woff', |
|
36 | - 'tif' => 'image/tiff', |
|
37 | - 'tiff' => 'image/tiff', |
|
38 | - 'xbm' => 'image/x-xbitmap', |
|
39 | - ); |
|
40 | - |
|
41 | - /** |
|
42 | - * Set the maximum size if files to be imported. |
|
43 | - * |
|
44 | - * Files larger than this size (in kB) will not be imported into the CSS. |
|
45 | - * Importing files into the CSS as data-uri will save you some connections, |
|
46 | - * but we should only import relatively small decorative images so that our |
|
47 | - * CSS file doesn't get too bulky. |
|
48 | - * |
|
49 | - * @param int $size Size in kB |
|
50 | - */ |
|
51 | - public function setMaxImportSize($size) |
|
52 | - { |
|
53 | - $this->maxImportSize = $size; |
|
54 | - } |
|
55 | - |
|
56 | - /** |
|
57 | - * Set the type of extensions to be imported into the CSS (to save network |
|
58 | - * connections). |
|
59 | - * Keys of the array should be the file extensions & respective values |
|
60 | - * should be the data type. |
|
61 | - * |
|
62 | - * @param string[] $extensions Array of file extensions |
|
63 | - */ |
|
64 | - public function setImportExtensions(array $extensions) |
|
65 | - { |
|
66 | - $this->importExtensions = $extensions; |
|
67 | - } |
|
68 | - |
|
69 | - /** |
|
70 | - * Move any import statements to the top. |
|
71 | - * |
|
72 | - * @param string $content Nearly finished CSS content |
|
73 | - * |
|
74 | - * @return string |
|
75 | - */ |
|
76 | - protected function moveImportsToTop($content) |
|
77 | - { |
|
78 | - if (preg_match_all('/@import[^;]+;/', $content, $matches)) { |
|
79 | - // remove from content |
|
80 | - foreach ($matches[0] as $import) { |
|
81 | - $content = str_replace($import, '', $content); |
|
82 | - } |
|
83 | - |
|
84 | - // add to top |
|
85 | - $content = implode('', $matches[0]).$content; |
|
86 | - } |
|
87 | - |
|
88 | - return $content; |
|
89 | - } |
|
90 | - |
|
91 | - /** |
|
92 | - * Combine CSS from import statements. |
|
93 | - * |
|
94 | - * @import's will be loaded and their content merged into the original file, |
|
95 | - * to save HTTP requests. |
|
96 | - * |
|
97 | - * @param string $source The file to combine imports for |
|
98 | - * @param string $content The CSS content to combine imports for |
|
99 | - * @param string[] $parents Parent paths, for circular reference checks |
|
100 | - * |
|
101 | - * @return string |
|
102 | - * |
|
103 | - * @throws FileImportException |
|
104 | - */ |
|
105 | - protected function combineImports($source, $content, $parents) |
|
106 | - { |
|
107 | - $importRegexes = array( |
|
108 | - // @import url(xxx) |
|
109 | - '/ |
|
20 | + /** |
|
21 | + * @var int |
|
22 | + */ |
|
23 | + protected $maxImportSize = 5; |
|
24 | + |
|
25 | + /** |
|
26 | + * @var string[] |
|
27 | + */ |
|
28 | + protected $importExtensions = array( |
|
29 | + 'gif' => 'data:image/gif', |
|
30 | + 'png' => 'data:image/png', |
|
31 | + 'jpe' => 'data:image/jpeg', |
|
32 | + 'jpg' => 'data:image/jpeg', |
|
33 | + 'jpeg' => 'data:image/jpeg', |
|
34 | + 'svg' => 'data:image/svg+xml', |
|
35 | + 'woff' => 'data:application/x-font-woff', |
|
36 | + 'tif' => 'image/tiff', |
|
37 | + 'tiff' => 'image/tiff', |
|
38 | + 'xbm' => 'image/x-xbitmap', |
|
39 | + ); |
|
40 | + |
|
41 | + /** |
|
42 | + * Set the maximum size if files to be imported. |
|
43 | + * |
|
44 | + * Files larger than this size (in kB) will not be imported into the CSS. |
|
45 | + * Importing files into the CSS as data-uri will save you some connections, |
|
46 | + * but we should only import relatively small decorative images so that our |
|
47 | + * CSS file doesn't get too bulky. |
|
48 | + * |
|
49 | + * @param int $size Size in kB |
|
50 | + */ |
|
51 | + public function setMaxImportSize($size) |
|
52 | + { |
|
53 | + $this->maxImportSize = $size; |
|
54 | + } |
|
55 | + |
|
56 | + /** |
|
57 | + * Set the type of extensions to be imported into the CSS (to save network |
|
58 | + * connections). |
|
59 | + * Keys of the array should be the file extensions & respective values |
|
60 | + * should be the data type. |
|
61 | + * |
|
62 | + * @param string[] $extensions Array of file extensions |
|
63 | + */ |
|
64 | + public function setImportExtensions(array $extensions) |
|
65 | + { |
|
66 | + $this->importExtensions = $extensions; |
|
67 | + } |
|
68 | + |
|
69 | + /** |
|
70 | + * Move any import statements to the top. |
|
71 | + * |
|
72 | + * @param string $content Nearly finished CSS content |
|
73 | + * |
|
74 | + * @return string |
|
75 | + */ |
|
76 | + protected function moveImportsToTop($content) |
|
77 | + { |
|
78 | + if (preg_match_all('/@import[^;]+;/', $content, $matches)) { |
|
79 | + // remove from content |
|
80 | + foreach ($matches[0] as $import) { |
|
81 | + $content = str_replace($import, '', $content); |
|
82 | + } |
|
83 | + |
|
84 | + // add to top |
|
85 | + $content = implode('', $matches[0]).$content; |
|
86 | + } |
|
87 | + |
|
88 | + return $content; |
|
89 | + } |
|
90 | + |
|
91 | + /** |
|
92 | + * Combine CSS from import statements. |
|
93 | + * |
|
94 | + * @import's will be loaded and their content merged into the original file, |
|
95 | + * to save HTTP requests. |
|
96 | + * |
|
97 | + * @param string $source The file to combine imports for |
|
98 | + * @param string $content The CSS content to combine imports for |
|
99 | + * @param string[] $parents Parent paths, for circular reference checks |
|
100 | + * |
|
101 | + * @return string |
|
102 | + * |
|
103 | + * @throws FileImportException |
|
104 | + */ |
|
105 | + protected function combineImports($source, $content, $parents) |
|
106 | + { |
|
107 | + $importRegexes = array( |
|
108 | + // @import url(xxx) |
|
109 | + '/ |
|
110 | 110 | # import statement |
111 | 111 | @import |
112 | 112 | |
@@ -151,8 +151,8 @@ discard block |
||
151 | 151 | |
152 | 152 | /ix', |
153 | 153 | |
154 | - // @import 'xxx' |
|
155 | - '/ |
|
154 | + // @import 'xxx' |
|
155 | + '/ |
|
156 | 156 | |
157 | 157 | # import statement |
158 | 158 | @import |
@@ -191,173 +191,173 @@ discard block |
||
191 | 191 | ;? |
192 | 192 | |
193 | 193 | /ix', |
194 | - ); |
|
195 | - |
|
196 | - // find all relative imports in css |
|
197 | - $matches = array(); |
|
198 | - foreach ($importRegexes as $importRegex) { |
|
199 | - if (preg_match_all($importRegex, $content, $regexMatches, PREG_SET_ORDER)) { |
|
200 | - $matches = array_merge($matches, $regexMatches); |
|
201 | - } |
|
202 | - } |
|
203 | - |
|
204 | - $search = array(); |
|
205 | - $replace = array(); |
|
206 | - |
|
207 | - // loop the matches |
|
208 | - foreach ($matches as $match) { |
|
209 | - // get the path for the file that will be imported |
|
210 | - $importPath = dirname($source).'/'.$match['path']; |
|
211 | - |
|
212 | - // only replace the import with the content if we can grab the |
|
213 | - // content of the file |
|
214 | - if ($this->canImportFile($importPath)) { |
|
215 | - // check if current file was not imported previously in the same |
|
216 | - // import chain. |
|
217 | - if (in_array($importPath, $parents)) { |
|
218 | - throw new FileImportException('Failed to import file "'.$importPath.'": circular reference detected.'); |
|
219 | - } |
|
220 | - |
|
221 | - // grab referenced file & minify it (which may include importing |
|
222 | - // yet other @import statements recursively) |
|
223 | - $minifier = new static($importPath); |
|
224 | - $importContent = $minifier->execute($source, $parents); |
|
225 | - |
|
226 | - // check if this is only valid for certain media |
|
227 | - if (!empty($match['media'])) { |
|
228 | - $importContent = '@media '.$match['media'].'{'.$importContent.'}'; |
|
229 | - } |
|
230 | - |
|
231 | - // add to replacement array |
|
232 | - $search[] = $match[0]; |
|
233 | - $replace[] = $importContent; |
|
234 | - } |
|
235 | - } |
|
236 | - |
|
237 | - // replace the import statements |
|
238 | - $content = str_replace($search, $replace, $content); |
|
239 | - |
|
240 | - return $content; |
|
241 | - } |
|
242 | - |
|
243 | - /** |
|
244 | - * Import files into the CSS, base64-ized. |
|
245 | - * |
|
246 | - * @url(image.jpg) images will be loaded and their content merged into the |
|
247 | - * original file, to save HTTP requests. |
|
248 | - * |
|
249 | - * @param string $source The file to import files for |
|
250 | - * @param string $content The CSS content to import files for |
|
251 | - * |
|
252 | - * @return string |
|
253 | - */ |
|
254 | - protected function importFiles($source, $content) |
|
255 | - { |
|
256 | - $extensions = array_keys($this->importExtensions); |
|
257 | - $regex = '/url\((["\']?)((?!["\']?data:).*?\.('.implode('|', $extensions).'))\\1\)/i'; |
|
258 | - if ($extensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) { |
|
259 | - $search = array(); |
|
260 | - $replace = array(); |
|
261 | - |
|
262 | - // loop the matches |
|
263 | - foreach ($matches as $match) { |
|
264 | - // get the path for the file that will be imported |
|
265 | - $path = $match[2]; |
|
266 | - $path = dirname($source).'/'.$path; |
|
267 | - $extension = $match[3]; |
|
268 | - |
|
269 | - // only replace the import with the content if we're able to get |
|
270 | - // the content of the file, and it's relatively small |
|
271 | - if ($this->canImportFile($path) && $this->canImportBySize($path)) { |
|
272 | - // grab content && base64-ize |
|
273 | - $importContent = $this->load($path); |
|
274 | - $importContent = base64_encode($importContent); |
|
275 | - |
|
276 | - // build replacement |
|
277 | - $search[] = $match[0]; |
|
278 | - $replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')'; |
|
279 | - } |
|
280 | - } |
|
281 | - |
|
282 | - // replace the import statements |
|
283 | - $content = str_replace($search, $replace, $content); |
|
284 | - } |
|
285 | - |
|
286 | - return $content; |
|
287 | - } |
|
288 | - |
|
289 | - /** |
|
290 | - * Minify the data. |
|
291 | - * Perform CSS optimizations. |
|
292 | - * |
|
293 | - * @param string[optional] $path Path to write the data to |
|
294 | - * @param string[] $parents Parent paths, for circular reference checks |
|
295 | - * |
|
296 | - * @return string The minified data |
|
297 | - */ |
|
298 | - public function execute($path = null, $parents = array()) |
|
299 | - { |
|
300 | - $content = ''; |
|
301 | - |
|
302 | - // loop css data (raw data and files) |
|
303 | - foreach ($this->data as $source => $css) { |
|
304 | - /* |
|
194 | + ); |
|
195 | + |
|
196 | + // find all relative imports in css |
|
197 | + $matches = array(); |
|
198 | + foreach ($importRegexes as $importRegex) { |
|
199 | + if (preg_match_all($importRegex, $content, $regexMatches, PREG_SET_ORDER)) { |
|
200 | + $matches = array_merge($matches, $regexMatches); |
|
201 | + } |
|
202 | + } |
|
203 | + |
|
204 | + $search = array(); |
|
205 | + $replace = array(); |
|
206 | + |
|
207 | + // loop the matches |
|
208 | + foreach ($matches as $match) { |
|
209 | + // get the path for the file that will be imported |
|
210 | + $importPath = dirname($source).'/'.$match['path']; |
|
211 | + |
|
212 | + // only replace the import with the content if we can grab the |
|
213 | + // content of the file |
|
214 | + if ($this->canImportFile($importPath)) { |
|
215 | + // check if current file was not imported previously in the same |
|
216 | + // import chain. |
|
217 | + if (in_array($importPath, $parents)) { |
|
218 | + throw new FileImportException('Failed to import file "'.$importPath.'": circular reference detected.'); |
|
219 | + } |
|
220 | + |
|
221 | + // grab referenced file & minify it (which may include importing |
|
222 | + // yet other @import statements recursively) |
|
223 | + $minifier = new static($importPath); |
|
224 | + $importContent = $minifier->execute($source, $parents); |
|
225 | + |
|
226 | + // check if this is only valid for certain media |
|
227 | + if (!empty($match['media'])) { |
|
228 | + $importContent = '@media '.$match['media'].'{'.$importContent.'}'; |
|
229 | + } |
|
230 | + |
|
231 | + // add to replacement array |
|
232 | + $search[] = $match[0]; |
|
233 | + $replace[] = $importContent; |
|
234 | + } |
|
235 | + } |
|
236 | + |
|
237 | + // replace the import statements |
|
238 | + $content = str_replace($search, $replace, $content); |
|
239 | + |
|
240 | + return $content; |
|
241 | + } |
|
242 | + |
|
243 | + /** |
|
244 | + * Import files into the CSS, base64-ized. |
|
245 | + * |
|
246 | + * @url(image.jpg) images will be loaded and their content merged into the |
|
247 | + * original file, to save HTTP requests. |
|
248 | + * |
|
249 | + * @param string $source The file to import files for |
|
250 | + * @param string $content The CSS content to import files for |
|
251 | + * |
|
252 | + * @return string |
|
253 | + */ |
|
254 | + protected function importFiles($source, $content) |
|
255 | + { |
|
256 | + $extensions = array_keys($this->importExtensions); |
|
257 | + $regex = '/url\((["\']?)((?!["\']?data:).*?\.('.implode('|', $extensions).'))\\1\)/i'; |
|
258 | + if ($extensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) { |
|
259 | + $search = array(); |
|
260 | + $replace = array(); |
|
261 | + |
|
262 | + // loop the matches |
|
263 | + foreach ($matches as $match) { |
|
264 | + // get the path for the file that will be imported |
|
265 | + $path = $match[2]; |
|
266 | + $path = dirname($source).'/'.$path; |
|
267 | + $extension = $match[3]; |
|
268 | + |
|
269 | + // only replace the import with the content if we're able to get |
|
270 | + // the content of the file, and it's relatively small |
|
271 | + if ($this->canImportFile($path) && $this->canImportBySize($path)) { |
|
272 | + // grab content && base64-ize |
|
273 | + $importContent = $this->load($path); |
|
274 | + $importContent = base64_encode($importContent); |
|
275 | + |
|
276 | + // build replacement |
|
277 | + $search[] = $match[0]; |
|
278 | + $replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')'; |
|
279 | + } |
|
280 | + } |
|
281 | + |
|
282 | + // replace the import statements |
|
283 | + $content = str_replace($search, $replace, $content); |
|
284 | + } |
|
285 | + |
|
286 | + return $content; |
|
287 | + } |
|
288 | + |
|
289 | + /** |
|
290 | + * Minify the data. |
|
291 | + * Perform CSS optimizations. |
|
292 | + * |
|
293 | + * @param string[optional] $path Path to write the data to |
|
294 | + * @param string[] $parents Parent paths, for circular reference checks |
|
295 | + * |
|
296 | + * @return string The minified data |
|
297 | + */ |
|
298 | + public function execute($path = null, $parents = array()) |
|
299 | + { |
|
300 | + $content = ''; |
|
301 | + |
|
302 | + // loop css data (raw data and files) |
|
303 | + foreach ($this->data as $source => $css) { |
|
304 | + /* |
|
305 | 305 | * Let's first take out strings & comments, since we can't just remove |
306 | 306 | * whitespace anywhere. If whitespace occurs inside a string, we should |
307 | 307 | * leave it alone. E.g.: |
308 | 308 | * p { content: "a test" } |
309 | 309 | */ |
310 | - $this->extractStrings(); |
|
311 | - $this->stripComments(); |
|
312 | - $css = $this->replace($css); |
|
310 | + $this->extractStrings(); |
|
311 | + $this->stripComments(); |
|
312 | + $css = $this->replace($css); |
|
313 | 313 | |
314 | - $css = $this->stripWhitespace($css); |
|
315 | - $css = $this->shortenHex($css); |
|
316 | - $css = $this->shortenZeroes($css); |
|
317 | - $css = $this->shortenFontWeights($css); |
|
318 | - $css = $this->stripEmptyTags($css); |
|
314 | + $css = $this->stripWhitespace($css); |
|
315 | + $css = $this->shortenHex($css); |
|
316 | + $css = $this->shortenZeroes($css); |
|
317 | + $css = $this->shortenFontWeights($css); |
|
318 | + $css = $this->stripEmptyTags($css); |
|
319 | 319 | |
320 | - // restore the string we've extracted earlier |
|
321 | - $css = $this->restoreExtractedData($css); |
|
320 | + // restore the string we've extracted earlier |
|
321 | + $css = $this->restoreExtractedData($css); |
|
322 | 322 | |
323 | - $source = is_int($source) ? '' : $source; |
|
324 | - $parents = $source ? array_merge($parents, array($source)) : $parents; |
|
325 | - $css = $this->combineImports($source, $css, $parents); |
|
326 | - $css = $this->importFiles($source, $css); |
|
323 | + $source = is_int($source) ? '' : $source; |
|
324 | + $parents = $source ? array_merge($parents, array($source)) : $parents; |
|
325 | + $css = $this->combineImports($source, $css, $parents); |
|
326 | + $css = $this->importFiles($source, $css); |
|
327 | 327 | |
328 | - /* |
|
328 | + /* |
|
329 | 329 | * If we'll save to a new path, we'll have to fix the relative paths |
330 | 330 | * to be relative no longer to the source file, but to the new path. |
331 | 331 | * If we don't write to a file, fall back to same path so no |
332 | 332 | * conversion happens (because we still want it to go through most |
333 | 333 | * of the move code...) |
334 | 334 | */ |
335 | - $converter = new Converter($source, $path ?: $source); |
|
336 | - $css = $this->move($converter, $css); |
|
337 | - |
|
338 | - // combine css |
|
339 | - $content .= $css; |
|
340 | - } |
|
341 | - |
|
342 | - $content = $this->moveImportsToTop($content); |
|
343 | - |
|
344 | - return $content; |
|
345 | - } |
|
346 | - |
|
347 | - /** |
|
348 | - * Moving a css file should update all relative urls. |
|
349 | - * Relative references (e.g. ../images/image.gif) in a certain css file, |
|
350 | - * will have to be updated when a file is being saved at another location |
|
351 | - * (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper). |
|
352 | - * |
|
353 | - * @param Converter $converter Relative path converter |
|
354 | - * @param string $content The CSS content to update relative urls for |
|
355 | - * |
|
356 | - * @return string |
|
357 | - */ |
|
358 | - protected function move(Converter $converter, $content) |
|
359 | - { |
|
360 | - /* |
|
335 | + $converter = new Converter($source, $path ?: $source); |
|
336 | + $css = $this->move($converter, $css); |
|
337 | + |
|
338 | + // combine css |
|
339 | + $content .= $css; |
|
340 | + } |
|
341 | + |
|
342 | + $content = $this->moveImportsToTop($content); |
|
343 | + |
|
344 | + return $content; |
|
345 | + } |
|
346 | + |
|
347 | + /** |
|
348 | + * Moving a css file should update all relative urls. |
|
349 | + * Relative references (e.g. ../images/image.gif) in a certain css file, |
|
350 | + * will have to be updated when a file is being saved at another location |
|
351 | + * (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper). |
|
352 | + * |
|
353 | + * @param Converter $converter Relative path converter |
|
354 | + * @param string $content The CSS content to update relative urls for |
|
355 | + * |
|
356 | + * @return string |
|
357 | + */ |
|
358 | + protected function move(Converter $converter, $content) |
|
359 | + { |
|
360 | + /* |
|
361 | 361 | * Relative path references will usually be enclosed by url(). @import |
362 | 362 | * is an exception, where url() is not necessary around the path (but is |
363 | 363 | * allowed). |
@@ -368,9 +368,9 @@ discard block |
||
368 | 368 | * recent PCRE version. That's why I'm doing 2 separate regular |
369 | 369 | * expressions & combining the matches after executing of both. |
370 | 370 | */ |
371 | - $relativeRegexes = array( |
|
372 | - // url(xxx) |
|
373 | - '/ |
|
371 | + $relativeRegexes = array( |
|
372 | + // url(xxx) |
|
373 | + '/ |
|
374 | 374 | # open url() |
375 | 375 | url\( |
376 | 376 | |
@@ -402,8 +402,8 @@ discard block |
||
402 | 402 | |
403 | 403 | /ix', |
404 | 404 | |
405 | - // @import "xxx" |
|
406 | - '/ |
|
405 | + // @import "xxx" |
|
406 | + '/ |
|
407 | 407 | # import statement |
408 | 408 | @import |
409 | 409 | |
@@ -432,243 +432,243 @@ discard block |
||
432 | 432 | (?P=quotes) |
433 | 433 | |
434 | 434 | /ix', |
435 | - ); |
|
436 | - |
|
437 | - // find all relative urls in css |
|
438 | - $matches = array(); |
|
439 | - foreach ($relativeRegexes as $relativeRegex) { |
|
440 | - if (preg_match_all($relativeRegex, $content, $regexMatches, PREG_SET_ORDER)) { |
|
441 | - $matches = array_merge($matches, $regexMatches); |
|
442 | - } |
|
443 | - } |
|
444 | - |
|
445 | - $search = array(); |
|
446 | - $replace = array(); |
|
447 | - |
|
448 | - // loop all urls |
|
449 | - foreach ($matches as $match) { |
|
450 | - // determine if it's a url() or an @import match |
|
451 | - $type = (strpos($match[0], '@import') === 0 ? 'import' : 'url'); |
|
452 | - |
|
453 | - // attempting to interpret GET-params makes no sense, so let's discard them for awhile |
|
454 | - $params = strrchr($match['path'], '?'); |
|
455 | - $url = $params ? substr($match['path'], 0, -strlen($params)) : $match['path']; |
|
456 | - |
|
457 | - // fix relative url |
|
458 | - $url = $converter->convert($url); |
|
459 | - |
|
460 | - // now that the path has been converted, re-apply GET-params |
|
461 | - $url .= $params; |
|
462 | - |
|
463 | - // build replacement |
|
464 | - $search[] = $match[0]; |
|
465 | - if ($type == 'url') { |
|
466 | - $replace[] = 'url('.$url.')'; |
|
467 | - } elseif ($type == 'import') { |
|
468 | - $replace[] = '@import "'.$url.'"'; |
|
469 | - } |
|
470 | - } |
|
471 | - |
|
472 | - // replace urls |
|
473 | - $content = str_replace($search, $replace, $content); |
|
474 | - |
|
475 | - return $content; |
|
476 | - } |
|
477 | - |
|
478 | - /** |
|
479 | - * Shorthand hex color codes. |
|
480 | - * #FF0000 -> #F00. |
|
481 | - * |
|
482 | - * @param string $content The CSS content to shorten the hex color codes for |
|
483 | - * |
|
484 | - * @return string |
|
485 | - */ |
|
486 | - protected function shortenHex($content) |
|
487 | - { |
|
488 | - $content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?=[; }])/i', '#$1$2$3', $content); |
|
489 | - |
|
490 | - // we can shorten some even more by replacing them with their color name |
|
491 | - $colors = array( |
|
492 | - '#F0FFFF' => 'azure', |
|
493 | - '#F5F5DC' => 'beige', |
|
494 | - '#A52A2A' => 'brown', |
|
495 | - '#FF7F50' => 'coral', |
|
496 | - '#FFD700' => 'gold', |
|
497 | - '#808080' => 'gray', |
|
498 | - '#008000' => 'green', |
|
499 | - '#4B0082' => 'indigo', |
|
500 | - '#FFFFF0' => 'ivory', |
|
501 | - '#F0E68C' => 'khaki', |
|
502 | - '#FAF0E6' => 'linen', |
|
503 | - '#800000' => 'maroon', |
|
504 | - '#000080' => 'navy', |
|
505 | - '#808000' => 'olive', |
|
506 | - '#CD853F' => 'peru', |
|
507 | - '#FFC0CB' => 'pink', |
|
508 | - '#DDA0DD' => 'plum', |
|
509 | - '#800080' => 'purple', |
|
510 | - '#F00' => 'red', |
|
511 | - '#FA8072' => 'salmon', |
|
512 | - '#A0522D' => 'sienna', |
|
513 | - '#C0C0C0' => 'silver', |
|
514 | - '#FFFAFA' => 'snow', |
|
515 | - '#D2B48C' => 'tan', |
|
516 | - '#FF6347' => 'tomato', |
|
517 | - '#EE82EE' => 'violet', |
|
518 | - '#F5DEB3' => 'wheat', |
|
519 | - ); |
|
520 | - |
|
521 | - return preg_replace_callback( |
|
522 | - '/(?<=[: ])('.implode(array_keys($colors), '|').')(?=[; }])/i', |
|
523 | - function ($match) use ($colors) { |
|
524 | - return $colors[strtoupper($match[0])]; |
|
525 | - }, |
|
526 | - $content |
|
527 | - ); |
|
528 | - } |
|
529 | - |
|
530 | - /** |
|
531 | - * Shorten CSS font weights. |
|
532 | - * |
|
533 | - * @param string $content The CSS content to shorten the font weights for |
|
534 | - * |
|
535 | - * @return string |
|
536 | - */ |
|
537 | - protected function shortenFontWeights($content) |
|
538 | - { |
|
539 | - $weights = array( |
|
540 | - 'normal' => 400, |
|
541 | - 'bold' => 700, |
|
542 | - ); |
|
543 | - |
|
544 | - $callback = function ($match) use ($weights) { |
|
545 | - return $match[1].$weights[$match[2]]; |
|
546 | - }; |
|
547 | - |
|
548 | - return preg_replace_callback('/(font-weight\s*:\s*)('.implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content); |
|
549 | - } |
|
550 | - |
|
551 | - /** |
|
552 | - * Shorthand 0 values to plain 0, instead of e.g. -0em. |
|
553 | - * |
|
554 | - * @param string $content The CSS content to shorten the zero values for |
|
555 | - * |
|
556 | - * @return string |
|
557 | - */ |
|
558 | - protected function shortenZeroes($content) |
|
559 | - { |
|
560 | - // reusable bits of code throughout these regexes: |
|
561 | - // before & after are used to make sure we don't match lose unintended |
|
562 | - // 0-like values (e.g. in #000, or in http://url/1.0) |
|
563 | - // units can be stripped from 0 values, or used to recognize non 0 |
|
564 | - // values (where wa may be able to strip a .0 suffix) |
|
565 | - $before = '(?<=[:(, ])'; |
|
566 | - $after = '(?=[ ,);}])'; |
|
567 | - $units = '(em|ex|%|px|cm|mm|in|pt|pc|ch|rem|vh|vw|vmin|vmax|vm)'; |
|
568 | - |
|
569 | - // strip units after zeroes (0px -> 0) |
|
570 | - // NOTE: it should be safe to remove all units for a 0 value, but in |
|
571 | - // practice, Webkit (especially Safari) seems to stumble over at least |
|
572 | - // 0%, potentially other units as well. Only stripping 'px' for now. |
|
573 | - // @see https://github.com/matthiasmullie/minify/issues/60 |
|
574 | - $content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content); |
|
575 | - |
|
576 | - // strip 0-digits (.0 -> 0) |
|
577 | - $content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content); |
|
578 | - // strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px |
|
579 | - $content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content); |
|
580 | - // strip trailing 0: 50.00 -> 50, 50.00px -> 50px |
|
581 | - $content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content); |
|
582 | - // strip leading 0: 0.1 -> .1, 01.1 -> 1.1 |
|
583 | - $content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content); |
|
584 | - |
|
585 | - // strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0) |
|
586 | - $content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content); |
|
587 | - |
|
588 | - // remove zeroes where they make no sense in calc: e.g. calc(100px - 0) |
|
589 | - // the 0 doesn't have any effect, and this isn't even valid without unit |
|
590 | - // strip all `+ 0` or `- 0` occurrences: calc(10% + 0) -> calc(10%) |
|
591 | - // looped because there may be multiple 0s inside 1 group of parentheses |
|
592 | - do { |
|
593 | - $previous = $content; |
|
594 | - $content = preg_replace('/\(([^\(\)]+)\s+[\+\-]\s+0(\s+[^\(\)]+)?\)/', '(\\1\\2)', $content); |
|
595 | - } while ($content !== $previous); |
|
596 | - // strip all `0 +` occurrences: calc(0 + 10%) -> calc(10%) |
|
597 | - $content = preg_replace('/\(\s*0\s+\+\s+([^\(\)]+)\)/', '(\\1)', $content); |
|
598 | - // strip all `0 -` occurrences: calc(0 - 10%) -> calc(-10%) |
|
599 | - $content = preg_replace('/\(\s*0\s+\-\s+([^\(\)]+)\)/', '(-\\1)', $content); |
|
600 | - // I'm not going to attempt to optimize away `x * 0` instances: |
|
601 | - // it's dumb enough code already that it likely won't occur, and it's |
|
602 | - // too complex to do right (order of operations would have to be |
|
603 | - // respected etc) |
|
604 | - // what I cared about most here was fixing incorrectly truncated units |
|
605 | - |
|
606 | - return $content; |
|
607 | - } |
|
608 | - |
|
609 | - /** |
|
610 | - * Strip comments from source code. |
|
611 | - * |
|
612 | - * @param string $content |
|
613 | - * |
|
614 | - * @return string |
|
615 | - */ |
|
616 | - protected function stripEmptyTags($content) |
|
617 | - { |
|
618 | - return preg_replace('/(^|\}|;)[^\{\};]+\{\s*\}/', '\\1', $content); |
|
619 | - } |
|
620 | - |
|
621 | - /** |
|
622 | - * Strip comments from source code. |
|
623 | - */ |
|
624 | - protected function stripComments() |
|
625 | - { |
|
626 | - $this->registerPattern('/\/\*.*?\*\//s', ''); |
|
627 | - } |
|
628 | - |
|
629 | - /** |
|
630 | - * Strip whitespace. |
|
631 | - * |
|
632 | - * @param string $content The CSS content to strip the whitespace for |
|
633 | - * |
|
634 | - * @return string |
|
635 | - */ |
|
636 | - protected function stripWhitespace($content) |
|
637 | - { |
|
638 | - // remove leading & trailing whitespace |
|
639 | - $content = preg_replace('/^\s*/m', '', $content); |
|
640 | - $content = preg_replace('/\s*$/m', '', $content); |
|
641 | - |
|
642 | - // replace newlines with a single space |
|
643 | - $content = preg_replace('/\s+/', ' ', $content); |
|
644 | - |
|
645 | - // remove whitespace around meta characters |
|
646 | - // inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex |
|
647 | - $content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content); |
|
648 | - $content = preg_replace('/([\[(:])\s+/', '$1', $content); |
|
649 | - $content = preg_replace('/\s+([\]\)])/', '$1', $content); |
|
650 | - $content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content); |
|
651 | - |
|
652 | - // whitespace around + and - can only be stripped in selectors, like |
|
653 | - // :nth-child(3+2n), not in things like calc(3px + 2px) or shorthands |
|
654 | - // like 3px -2px |
|
655 | - $content = preg_replace('/\s*([+-])\s*(?=[^}]*{)/', '$1', $content); |
|
656 | - |
|
657 | - // remove semicolon/whitespace followed by closing bracket |
|
658 | - $content = str_replace(';}', '}', $content); |
|
659 | - |
|
660 | - return trim($content); |
|
661 | - } |
|
662 | - |
|
663 | - /** |
|
664 | - * Check if file is small enough to be imported. |
|
665 | - * |
|
666 | - * @param string $path The path to the file |
|
667 | - * |
|
668 | - * @return bool |
|
669 | - */ |
|
670 | - protected function canImportBySize($path) |
|
671 | - { |
|
672 | - return ($size = @filesize($path)) && $size <= $this->maxImportSize * 1024; |
|
673 | - } |
|
435 | + ); |
|
436 | + |
|
437 | + // find all relative urls in css |
|
438 | + $matches = array(); |
|
439 | + foreach ($relativeRegexes as $relativeRegex) { |
|
440 | + if (preg_match_all($relativeRegex, $content, $regexMatches, PREG_SET_ORDER)) { |
|
441 | + $matches = array_merge($matches, $regexMatches); |
|
442 | + } |
|
443 | + } |
|
444 | + |
|
445 | + $search = array(); |
|
446 | + $replace = array(); |
|
447 | + |
|
448 | + // loop all urls |
|
449 | + foreach ($matches as $match) { |
|
450 | + // determine if it's a url() or an @import match |
|
451 | + $type = (strpos($match[0], '@import') === 0 ? 'import' : 'url'); |
|
452 | + |
|
453 | + // attempting to interpret GET-params makes no sense, so let's discard them for awhile |
|
454 | + $params = strrchr($match['path'], '?'); |
|
455 | + $url = $params ? substr($match['path'], 0, -strlen($params)) : $match['path']; |
|
456 | + |
|
457 | + // fix relative url |
|
458 | + $url = $converter->convert($url); |
|
459 | + |
|
460 | + // now that the path has been converted, re-apply GET-params |
|
461 | + $url .= $params; |
|
462 | + |
|
463 | + // build replacement |
|
464 | + $search[] = $match[0]; |
|
465 | + if ($type == 'url') { |
|
466 | + $replace[] = 'url('.$url.')'; |
|
467 | + } elseif ($type == 'import') { |
|
468 | + $replace[] = '@import "'.$url.'"'; |
|
469 | + } |
|
470 | + } |
|
471 | + |
|
472 | + // replace urls |
|
473 | + $content = str_replace($search, $replace, $content); |
|
474 | + |
|
475 | + return $content; |
|
476 | + } |
|
477 | + |
|
478 | + /** |
|
479 | + * Shorthand hex color codes. |
|
480 | + * #FF0000 -> #F00. |
|
481 | + * |
|
482 | + * @param string $content The CSS content to shorten the hex color codes for |
|
483 | + * |
|
484 | + * @return string |
|
485 | + */ |
|
486 | + protected function shortenHex($content) |
|
487 | + { |
|
488 | + $content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?=[; }])/i', '#$1$2$3', $content); |
|
489 | + |
|
490 | + // we can shorten some even more by replacing them with their color name |
|
491 | + $colors = array( |
|
492 | + '#F0FFFF' => 'azure', |
|
493 | + '#F5F5DC' => 'beige', |
|
494 | + '#A52A2A' => 'brown', |
|
495 | + '#FF7F50' => 'coral', |
|
496 | + '#FFD700' => 'gold', |
|
497 | + '#808080' => 'gray', |
|
498 | + '#008000' => 'green', |
|
499 | + '#4B0082' => 'indigo', |
|
500 | + '#FFFFF0' => 'ivory', |
|
501 | + '#F0E68C' => 'khaki', |
|
502 | + '#FAF0E6' => 'linen', |
|
503 | + '#800000' => 'maroon', |
|
504 | + '#000080' => 'navy', |
|
505 | + '#808000' => 'olive', |
|
506 | + '#CD853F' => 'peru', |
|
507 | + '#FFC0CB' => 'pink', |
|
508 | + '#DDA0DD' => 'plum', |
|
509 | + '#800080' => 'purple', |
|
510 | + '#F00' => 'red', |
|
511 | + '#FA8072' => 'salmon', |
|
512 | + '#A0522D' => 'sienna', |
|
513 | + '#C0C0C0' => 'silver', |
|
514 | + '#FFFAFA' => 'snow', |
|
515 | + '#D2B48C' => 'tan', |
|
516 | + '#FF6347' => 'tomato', |
|
517 | + '#EE82EE' => 'violet', |
|
518 | + '#F5DEB3' => 'wheat', |
|
519 | + ); |
|
520 | + |
|
521 | + return preg_replace_callback( |
|
522 | + '/(?<=[: ])('.implode(array_keys($colors), '|').')(?=[; }])/i', |
|
523 | + function ($match) use ($colors) { |
|
524 | + return $colors[strtoupper($match[0])]; |
|
525 | + }, |
|
526 | + $content |
|
527 | + ); |
|
528 | + } |
|
529 | + |
|
530 | + /** |
|
531 | + * Shorten CSS font weights. |
|
532 | + * |
|
533 | + * @param string $content The CSS content to shorten the font weights for |
|
534 | + * |
|
535 | + * @return string |
|
536 | + */ |
|
537 | + protected function shortenFontWeights($content) |
|
538 | + { |
|
539 | + $weights = array( |
|
540 | + 'normal' => 400, |
|
541 | + 'bold' => 700, |
|
542 | + ); |
|
543 | + |
|
544 | + $callback = function ($match) use ($weights) { |
|
545 | + return $match[1].$weights[$match[2]]; |
|
546 | + }; |
|
547 | + |
|
548 | + return preg_replace_callback('/(font-weight\s*:\s*)('.implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content); |
|
549 | + } |
|
550 | + |
|
551 | + /** |
|
552 | + * Shorthand 0 values to plain 0, instead of e.g. -0em. |
|
553 | + * |
|
554 | + * @param string $content The CSS content to shorten the zero values for |
|
555 | + * |
|
556 | + * @return string |
|
557 | + */ |
|
558 | + protected function shortenZeroes($content) |
|
559 | + { |
|
560 | + // reusable bits of code throughout these regexes: |
|
561 | + // before & after are used to make sure we don't match lose unintended |
|
562 | + // 0-like values (e.g. in #000, or in http://url/1.0) |
|
563 | + // units can be stripped from 0 values, or used to recognize non 0 |
|
564 | + // values (where wa may be able to strip a .0 suffix) |
|
565 | + $before = '(?<=[:(, ])'; |
|
566 | + $after = '(?=[ ,);}])'; |
|
567 | + $units = '(em|ex|%|px|cm|mm|in|pt|pc|ch|rem|vh|vw|vmin|vmax|vm)'; |
|
568 | + |
|
569 | + // strip units after zeroes (0px -> 0) |
|
570 | + // NOTE: it should be safe to remove all units for a 0 value, but in |
|
571 | + // practice, Webkit (especially Safari) seems to stumble over at least |
|
572 | + // 0%, potentially other units as well. Only stripping 'px' for now. |
|
573 | + // @see https://github.com/matthiasmullie/minify/issues/60 |
|
574 | + $content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content); |
|
575 | + |
|
576 | + // strip 0-digits (.0 -> 0) |
|
577 | + $content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content); |
|
578 | + // strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px |
|
579 | + $content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content); |
|
580 | + // strip trailing 0: 50.00 -> 50, 50.00px -> 50px |
|
581 | + $content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content); |
|
582 | + // strip leading 0: 0.1 -> .1, 01.1 -> 1.1 |
|
583 | + $content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content); |
|
584 | + |
|
585 | + // strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0) |
|
586 | + $content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content); |
|
587 | + |
|
588 | + // remove zeroes where they make no sense in calc: e.g. calc(100px - 0) |
|
589 | + // the 0 doesn't have any effect, and this isn't even valid without unit |
|
590 | + // strip all `+ 0` or `- 0` occurrences: calc(10% + 0) -> calc(10%) |
|
591 | + // looped because there may be multiple 0s inside 1 group of parentheses |
|
592 | + do { |
|
593 | + $previous = $content; |
|
594 | + $content = preg_replace('/\(([^\(\)]+)\s+[\+\-]\s+0(\s+[^\(\)]+)?\)/', '(\\1\\2)', $content); |
|
595 | + } while ($content !== $previous); |
|
596 | + // strip all `0 +` occurrences: calc(0 + 10%) -> calc(10%) |
|
597 | + $content = preg_replace('/\(\s*0\s+\+\s+([^\(\)]+)\)/', '(\\1)', $content); |
|
598 | + // strip all `0 -` occurrences: calc(0 - 10%) -> calc(-10%) |
|
599 | + $content = preg_replace('/\(\s*0\s+\-\s+([^\(\)]+)\)/', '(-\\1)', $content); |
|
600 | + // I'm not going to attempt to optimize away `x * 0` instances: |
|
601 | + // it's dumb enough code already that it likely won't occur, and it's |
|
602 | + // too complex to do right (order of operations would have to be |
|
603 | + // respected etc) |
|
604 | + // what I cared about most here was fixing incorrectly truncated units |
|
605 | + |
|
606 | + return $content; |
|
607 | + } |
|
608 | + |
|
609 | + /** |
|
610 | + * Strip comments from source code. |
|
611 | + * |
|
612 | + * @param string $content |
|
613 | + * |
|
614 | + * @return string |
|
615 | + */ |
|
616 | + protected function stripEmptyTags($content) |
|
617 | + { |
|
618 | + return preg_replace('/(^|\}|;)[^\{\};]+\{\s*\}/', '\\1', $content); |
|
619 | + } |
|
620 | + |
|
621 | + /** |
|
622 | + * Strip comments from source code. |
|
623 | + */ |
|
624 | + protected function stripComments() |
|
625 | + { |
|
626 | + $this->registerPattern('/\/\*.*?\*\//s', ''); |
|
627 | + } |
|
628 | + |
|
629 | + /** |
|
630 | + * Strip whitespace. |
|
631 | + * |
|
632 | + * @param string $content The CSS content to strip the whitespace for |
|
633 | + * |
|
634 | + * @return string |
|
635 | + */ |
|
636 | + protected function stripWhitespace($content) |
|
637 | + { |
|
638 | + // remove leading & trailing whitespace |
|
639 | + $content = preg_replace('/^\s*/m', '', $content); |
|
640 | + $content = preg_replace('/\s*$/m', '', $content); |
|
641 | + |
|
642 | + // replace newlines with a single space |
|
643 | + $content = preg_replace('/\s+/', ' ', $content); |
|
644 | + |
|
645 | + // remove whitespace around meta characters |
|
646 | + // inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex |
|
647 | + $content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content); |
|
648 | + $content = preg_replace('/([\[(:])\s+/', '$1', $content); |
|
649 | + $content = preg_replace('/\s+([\]\)])/', '$1', $content); |
|
650 | + $content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content); |
|
651 | + |
|
652 | + // whitespace around + and - can only be stripped in selectors, like |
|
653 | + // :nth-child(3+2n), not in things like calc(3px + 2px) or shorthands |
|
654 | + // like 3px -2px |
|
655 | + $content = preg_replace('/\s*([+-])\s*(?=[^}]*{)/', '$1', $content); |
|
656 | + |
|
657 | + // remove semicolon/whitespace followed by closing bracket |
|
658 | + $content = str_replace(';}', '}', $content); |
|
659 | + |
|
660 | + return trim($content); |
|
661 | + } |
|
662 | + |
|
663 | + /** |
|
664 | + * Check if file is small enough to be imported. |
|
665 | + * |
|
666 | + * @param string $path The path to the file |
|
667 | + * |
|
668 | + * @return bool |
|
669 | + */ |
|
670 | + protected function canImportBySize($path) |
|
671 | + { |
|
672 | + return ($size = @filesize($path)) && $size <= $this->maxImportSize * 1024; |
|
673 | + } |
|
674 | 674 | } |
@@ -82,7 +82,7 @@ discard block |
||
82 | 82 | } |
83 | 83 | |
84 | 84 | // add to top |
85 | - $content = implode('', $matches[0]).$content; |
|
85 | + $content = implode('', $matches[0]) . $content; |
|
86 | 86 | } |
87 | 87 | |
88 | 88 | return $content; |
@@ -207,7 +207,7 @@ discard block |
||
207 | 207 | // loop the matches |
208 | 208 | foreach ($matches as $match) { |
209 | 209 | // get the path for the file that will be imported |
210 | - $importPath = dirname($source).'/'.$match['path']; |
|
210 | + $importPath = dirname($source) . '/' . $match['path']; |
|
211 | 211 | |
212 | 212 | // only replace the import with the content if we can grab the |
213 | 213 | // content of the file |
@@ -215,7 +215,7 @@ discard block |
||
215 | 215 | // check if current file was not imported previously in the same |
216 | 216 | // import chain. |
217 | 217 | if (in_array($importPath, $parents)) { |
218 | - throw new FileImportException('Failed to import file "'.$importPath.'": circular reference detected.'); |
|
218 | + throw new FileImportException('Failed to import file "' . $importPath . '": circular reference detected.'); |
|
219 | 219 | } |
220 | 220 | |
221 | 221 | // grab referenced file & minify it (which may include importing |
@@ -225,7 +225,7 @@ discard block |
||
225 | 225 | |
226 | 226 | // check if this is only valid for certain media |
227 | 227 | if (!empty($match['media'])) { |
228 | - $importContent = '@media '.$match['media'].'{'.$importContent.'}'; |
|
228 | + $importContent = '@media ' . $match['media'] . '{' . $importContent . '}'; |
|
229 | 229 | } |
230 | 230 | |
231 | 231 | // add to replacement array |
@@ -254,7 +254,7 @@ discard block |
||
254 | 254 | protected function importFiles($source, $content) |
255 | 255 | { |
256 | 256 | $extensions = array_keys($this->importExtensions); |
257 | - $regex = '/url\((["\']?)((?!["\']?data:).*?\.('.implode('|', $extensions).'))\\1\)/i'; |
|
257 | + $regex = '/url\((["\']?)((?!["\']?data:).*?\.(' . implode('|', $extensions) . '))\\1\)/i'; |
|
258 | 258 | if ($extensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) { |
259 | 259 | $search = array(); |
260 | 260 | $replace = array(); |
@@ -263,7 +263,7 @@ discard block |
||
263 | 263 | foreach ($matches as $match) { |
264 | 264 | // get the path for the file that will be imported |
265 | 265 | $path = $match[2]; |
266 | - $path = dirname($source).'/'.$path; |
|
266 | + $path = dirname($source) . '/' . $path; |
|
267 | 267 | $extension = $match[3]; |
268 | 268 | |
269 | 269 | // only replace the import with the content if we're able to get |
@@ -275,7 +275,7 @@ discard block |
||
275 | 275 | |
276 | 276 | // build replacement |
277 | 277 | $search[] = $match[0]; |
278 | - $replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')'; |
|
278 | + $replace[] = 'url(' . $this->importExtensions[$extension] . ';base64,' . $importContent . ')'; |
|
279 | 279 | } |
280 | 280 | } |
281 | 281 | |
@@ -463,9 +463,9 @@ discard block |
||
463 | 463 | // build replacement |
464 | 464 | $search[] = $match[0]; |
465 | 465 | if ($type == 'url') { |
466 | - $replace[] = 'url('.$url.')'; |
|
466 | + $replace[] = 'url(' . $url . ')'; |
|
467 | 467 | } elseif ($type == 'import') { |
468 | - $replace[] = '@import "'.$url.'"'; |
|
468 | + $replace[] = '@import "' . $url . '"'; |
|
469 | 469 | } |
470 | 470 | } |
471 | 471 | |
@@ -519,8 +519,8 @@ discard block |
||
519 | 519 | ); |
520 | 520 | |
521 | 521 | return preg_replace_callback( |
522 | - '/(?<=[: ])('.implode(array_keys($colors), '|').')(?=[; }])/i', |
|
523 | - function ($match) use ($colors) { |
|
522 | + '/(?<=[: ])(' . implode(array_keys($colors), '|') . ')(?=[; }])/i', |
|
523 | + function($match) use ($colors) { |
|
524 | 524 | return $colors[strtoupper($match[0])]; |
525 | 525 | }, |
526 | 526 | $content |
@@ -541,11 +541,11 @@ discard block |
||
541 | 541 | 'bold' => 700, |
542 | 542 | ); |
543 | 543 | |
544 | - $callback = function ($match) use ($weights) { |
|
545 | - return $match[1].$weights[$match[2]]; |
|
544 | + $callback = function($match) use ($weights) { |
|
545 | + return $match[1] . $weights[$match[2]]; |
|
546 | 546 | }; |
547 | 547 | |
548 | - return preg_replace_callback('/(font-weight\s*:\s*)('.implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content); |
|
548 | + return preg_replace_callback('/(font-weight\s*:\s*)(' . implode('|', array_keys($weights)) . ')(?=[;}])/', $callback, $content); |
|
549 | 549 | } |
550 | 550 | |
551 | 551 | /** |
@@ -571,19 +571,19 @@ discard block |
||
571 | 571 | // practice, Webkit (especially Safari) seems to stumble over at least |
572 | 572 | // 0%, potentially other units as well. Only stripping 'px' for now. |
573 | 573 | // @see https://github.com/matthiasmullie/minify/issues/60 |
574 | - $content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content); |
|
574 | + $content = preg_replace('/' . $before . '(-?0*(\.0+)?)(?<=0)px' . $after . '/', '\\1', $content); |
|
575 | 575 | |
576 | 576 | // strip 0-digits (.0 -> 0) |
577 | - $content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content); |
|
577 | + $content = preg_replace('/' . $before . '\.0+' . $units . '?' . $after . '/', '0\\1', $content); |
|
578 | 578 | // strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px |
579 | - $content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content); |
|
579 | + $content = preg_replace('/' . $before . '(-?[0-9]+\.[0-9]+)0+' . $units . '?' . $after . '/', '\\1\\2', $content); |
|
580 | 580 | // strip trailing 0: 50.00 -> 50, 50.00px -> 50px |
581 | - $content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content); |
|
581 | + $content = preg_replace('/' . $before . '(-?[0-9]+)\.0+' . $units . '?' . $after . '/', '\\1\\2', $content); |
|
582 | 582 | // strip leading 0: 0.1 -> .1, 01.1 -> 1.1 |
583 | - $content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content); |
|
583 | + $content = preg_replace('/' . $before . '(-?)0+([0-9]*\.[0-9]+)' . $units . '?' . $after . '/', '\\1\\2\\3', $content); |
|
584 | 584 | |
585 | 585 | // strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0) |
586 | - $content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content); |
|
586 | + $content = preg_replace('/' . $before . '-?0+' . $units . '?' . $after . '/', '0\\1', $content); |
|
587 | 587 | |
588 | 588 | // remove zeroes where they make no sense in calc: e.g. calc(100px - 0) |
589 | 589 | // the 0 doesn't have any effect, and this isn't even valid without unit |
@@ -117,14 +117,14 @@ discard block |
||
117 | 117 | { |
118 | 118 | call_user_func_array(array('parent', '__construct'), func_get_args()); |
119 | 119 | |
120 | - $dataDir = __DIR__.'/../data/js/'; |
|
120 | + $dataDir = __DIR__ . '/../data/js/'; |
|
121 | 121 | $options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES; |
122 | - $this->keywordsReserved = file($dataDir.'keywords_reserved.txt', $options); |
|
123 | - $this->keywordsBefore = file($dataDir.'keywords_before.txt', $options); |
|
124 | - $this->keywordsAfter = file($dataDir.'keywords_after.txt', $options); |
|
125 | - $this->operators = file($dataDir.'operators.txt', $options); |
|
126 | - $this->operatorsBefore = file($dataDir.'operators_before.txt', $options); |
|
127 | - $this->operatorsAfter = file($dataDir.'operators_after.txt', $options); |
|
122 | + $this->keywordsReserved = file($dataDir . 'keywords_reserved.txt', $options); |
|
123 | + $this->keywordsBefore = file($dataDir . 'keywords_before.txt', $options); |
|
124 | + $this->keywordsAfter = file($dataDir . 'keywords_after.txt', $options); |
|
125 | + $this->operators = file($dataDir . 'operators.txt', $options); |
|
126 | + $this->operatorsBefore = file($dataDir . 'operators_before.txt', $options); |
|
127 | + $this->operatorsAfter = file($dataDir . 'operators_after.txt', $options); |
|
128 | 128 | } |
129 | 129 | |
130 | 130 | /** |
@@ -149,7 +149,7 @@ discard block |
||
149 | 149 | * singe-line comment on the last line (in which case it would also |
150 | 150 | * be seen as part of that comment) |
151 | 151 | */ |
152 | - $content .= $js."\n;"; |
|
152 | + $content .= $js . "\n;"; |
|
153 | 153 | } |
154 | 154 | |
155 | 155 | /* |
@@ -214,9 +214,9 @@ discard block |
||
214 | 214 | { |
215 | 215 | // PHP only supports $this inside anonymous functions since 5.4 |
216 | 216 | $minifier = $this; |
217 | - $callback = function ($match) use ($minifier) { |
|
217 | + $callback = function($match) use ($minifier) { |
|
218 | 218 | $count = count($minifier->extracted); |
219 | - $placeholder = '/'.$count.'/'; |
|
219 | + $placeholder = '/' . $count . '/'; |
|
220 | 220 | $minifier->extracted[$placeholder] = $match[0]; |
221 | 221 | |
222 | 222 | return $placeholder; |
@@ -229,7 +229,7 @@ discard block |
||
229 | 229 | // likely part of a division, not a regex) |
230 | 230 | $after = '[\.,;\)\}]'; |
231 | 231 | $methods = '\.(exec|test|match|search|replace|split)\('; |
232 | - $this->registerPattern('/'.$pattern.'(?=\s*('.$after.'|'.$methods.'))/', $callback); |
|
232 | + $this->registerPattern('/' . $pattern . '(?=\s*(' . $after . '|' . $methods . '))/', $callback); |
|
233 | 233 | |
234 | 234 | // 1 more edge case: a regex can be followed by a lot more operators or |
235 | 235 | // keywords if there's a newline (ASI) in between, where the operator |
@@ -237,7 +237,7 @@ discard block |
||
237 | 237 | // (https://github.com/matthiasmullie/minify/issues/56) |
238 | 238 | $operators = $this->getOperatorsForRegex($this->operatorsBefore, '/'); |
239 | 239 | $operators += $this->getOperatorsForRegex($this->keywordsReserved, '/'); |
240 | - $this->registerPattern('/'.$pattern.'\s*\n(?=\s*('.implode('|', $operators).'))/', $callback); |
|
240 | + $this->registerPattern('/' . $pattern . '\s*\n(?=\s*(' . implode('|', $operators) . '))/', $callback); |
|
241 | 241 | } |
242 | 242 | |
243 | 243 | /** |
@@ -281,8 +281,8 @@ discard block |
||
281 | 281 | unset($operatorsBefore['+'], $operatorsBefore['-'], $operatorsAfter['+'], $operatorsAfter['-']); |
282 | 282 | $content = preg_replace( |
283 | 283 | array( |
284 | - '/('.implode('|', $operatorsBefore).')\s+/', |
|
285 | - '/\s+('.implode('|', $operatorsAfter).')/', |
|
284 | + '/(' . implode('|', $operatorsBefore) . ')\s+/', |
|
285 | + '/\s+(' . implode('|', $operatorsAfter) . ')/', |
|
286 | 286 | ), '\\1', $content |
287 | 287 | ); |
288 | 288 | |
@@ -295,8 +295,8 @@ discard block |
||
295 | 295 | ); |
296 | 296 | |
297 | 297 | // collapse whitespace around reserved words into single space |
298 | - $content = preg_replace('/(^|[;\}\s])\K('.implode('|', $keywordsBefore).')\s+/', '\\2 ', $content); |
|
299 | - $content = preg_replace('/\s+('.implode('|', $keywordsAfter).')(?=([;\{\s]|$))/', ' \\1', $content); |
|
298 | + $content = preg_replace('/(^|[;\}\s])\K(' . implode('|', $keywordsBefore) . ')\s+/', '\\2 ', $content); |
|
299 | + $content = preg_replace('/\s+(' . implode('|', $keywordsAfter) . ')(?=([;\{\s]|$))/', ' \\1', $content); |
|
300 | 300 | |
301 | 301 | /* |
302 | 302 | * We didn't strip whitespace after a couple of operators because they |
@@ -306,8 +306,8 @@ discard block |
||
306 | 306 | */ |
307 | 307 | $operatorsDiffBefore = array_diff($operators, $operatorsBefore); |
308 | 308 | $operatorsDiffAfter = array_diff($operators, $operatorsAfter); |
309 | - $content = preg_replace('/('.implode('|', $operatorsDiffBefore).')[^\S\n]+/', '\\1', $content); |
|
310 | - $content = preg_replace('/[^\S\n]+('.implode('|', $operatorsDiffAfter).')/', '\\1', $content); |
|
309 | + $content = preg_replace('/(' . implode('|', $operatorsDiffBefore) . ')[^\S\n]+/', '\\1', $content); |
|
310 | + $content = preg_replace('/[^\S\n]+(' . implode('|', $operatorsDiffAfter) . ')/', '\\1', $content); |
|
311 | 311 | |
312 | 312 | /* |
313 | 313 | * Get rid of double semicolons, except where they can be used like: |
@@ -381,7 +381,7 @@ discard block |
||
381 | 381 | |
382 | 382 | // don't confuse = with other assignment shortcuts (e.g. +=) |
383 | 383 | $chars = preg_quote('+-*\=<>%&|'); |
384 | - $operators['='] = '(?<!['.$chars.'])\='; |
|
384 | + $operators['='] = '(?<![' . $chars . '])\='; |
|
385 | 385 | |
386 | 386 | return $operators; |
387 | 387 | } |
@@ -402,8 +402,8 @@ discard block |
||
402 | 402 | $escaped = array_map('preg_quote', $keywords, $delimiter); |
403 | 403 | |
404 | 404 | // add word boundaries |
405 | - array_walk($keywords, function ($value) { |
|
406 | - return '\b'.$value.'\b'; |
|
405 | + array_walk($keywords, function($value) { |
|
406 | + return '\b' . $value . '\b'; |
|
407 | 407 | }); |
408 | 408 | |
409 | 409 | $keywords = array_combine($keywords, $escaped); |
@@ -423,7 +423,7 @@ discard block |
||
423 | 423 | // PHP only supports $this inside anonymous functions since 5.4 |
424 | 424 | $minifier = $this; |
425 | 425 | $keywords = $this->keywordsReserved; |
426 | - $callback = function ($match) use ($minifier, $keywords) { |
|
426 | + $callback = function($match) use ($minifier, $keywords) { |
|
427 | 427 | $property = trim($minifier->extracted[$match[1]], '\'"'); |
428 | 428 | |
429 | 429 | /* |
@@ -440,11 +440,11 @@ discard block |
||
440 | 440 | * array['key-here'] can't be replaced by array.key-here since '-' |
441 | 441 | * is not a valid character there. |
442 | 442 | */ |
443 | - if (!preg_match('/^'.$minifier::REGEX_VARIABLE.'$/u', $property)) { |
|
443 | + if (!preg_match('/^' . $minifier::REGEX_VARIABLE . '$/u', $property)) { |
|
444 | 444 | return $match[0]; |
445 | 445 | } |
446 | 446 | |
447 | - return '.'.$property; |
|
447 | + return '.' . $property; |
|
448 | 448 | }; |
449 | 449 | |
450 | 450 | /* |
@@ -465,9 +465,9 @@ discard block |
||
465 | 465 | * separate look-behind assertions, one for each keyword. |
466 | 466 | */ |
467 | 467 | $keywords = $this->getKeywordsForRegex($keywords); |
468 | - $keywords = '(?<!'.implode(')(?<!', $keywords).')'; |
|
468 | + $keywords = '(?<!' . implode(')(?<!', $keywords) . ')'; |
|
469 | 469 | |
470 | - return preg_replace_callback('/(?<='.$previousChar.'|\])'.$keywords.'\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content); |
|
470 | + return preg_replace_callback('/(?<=' . $previousChar . '|\])' . $keywords . '\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content); |
|
471 | 471 | } |
472 | 472 | |
473 | 473 | /** |
@@ -14,134 +14,134 @@ discard block |
||
14 | 14 | */ |
15 | 15 | class JS extends Minify |
16 | 16 | { |
17 | - /** |
|
18 | - * Var-matching regex based on https://stackoverflow.com/a/9337047/802993. |
|
19 | - * |
|
20 | - * Note that regular expressions using that bit must have the PCRE_UTF8 |
|
21 | - * pattern modifier (/u) set. |
|
22 | - * |
|
23 | - * @var string |
|
24 | - */ |
|
25 | - const REGEX_VARIABLE = '\b[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}0-9\x{0300}-\x{036f}\x{0483}-\x{0487}\x{0591}-\x{05bd}\x{05bf}\x{05c1}\x{05c2}\x{05c4}\x{05c5}\x{05c7}\x{0610}-\x{061a}\x{064b}-\x{0669}\x{0670}\x{06d6}-\x{06dc}\x{06df}-\x{06e4}\x{06e7}\x{06e8}\x{06ea}-\x{06ed}\x{06f0}-\x{06f9}\x{0711}\x{0730}-\x{074a}\x{07a6}-\x{07b0}\x{07c0}-\x{07c9}\x{07eb}-\x{07f3}\x{0816}-\x{0819}\x{081b}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082d}\x{0859}-\x{085b}\x{08e4}-\x{08fe}\x{0900}-\x{0903}\x{093a}-\x{093c}\x{093e}-\x{094f}\x{0951}-\x{0957}\x{0962}\x{0963}\x{0966}-\x{096f}\x{0981}-\x{0983}\x{09bc}\x{09be}-\x{09c4}\x{09c7}\x{09c8}\x{09cb}-\x{09cd}\x{09d7}\x{09e2}\x{09e3}\x{09e6}-\x{09ef}\x{0a01}-\x{0a03}\x{0a3c}\x{0a3e}-\x{0a42}\x{0a47}\x{0a48}\x{0a4b}-\x{0a4d}\x{0a51}\x{0a66}-\x{0a71}\x{0a75}\x{0a81}-\x{0a83}\x{0abc}\x{0abe}-\x{0ac5}\x{0ac7}-\x{0ac9}\x{0acb}-\x{0acd}\x{0ae2}\x{0ae3}\x{0ae6}-\x{0aef}\x{0b01}-\x{0b03}\x{0b3c}\x{0b3e}-\x{0b44}\x{0b47}\x{0b48}\x{0b4b}-\x{0b4d}\x{0b56}\x{0b57}\x{0b62}\x{0b63}\x{0b66}-\x{0b6f}\x{0b82}\x{0bbe}-\x{0bc2}\x{0bc6}-\x{0bc8}\x{0bca}-\x{0bcd}\x{0bd7}\x{0be6}-\x{0bef}\x{0c01}-\x{0c03}\x{0c3e}-\x{0c44}\x{0c46}-\x{0c48}\x{0c4a}-\x{0c4d}\x{0c55}\x{0c56}\x{0c62}\x{0c63}\x{0c66}-\x{0c6f}\x{0c82}\x{0c83}\x{0cbc}\x{0cbe}-\x{0cc4}\x{0cc6}-\x{0cc8}\x{0cca}-\x{0ccd}\x{0cd5}\x{0cd6}\x{0ce2}\x{0ce3}\x{0ce6}-\x{0cef}\x{0d02}\x{0d03}\x{0d3e}-\x{0d44}\x{0d46}-\x{0d48}\x{0d4a}-\x{0d4d}\x{0d57}\x{0d62}\x{0d63}\x{0d66}-\x{0d6f}\x{0d82}\x{0d83}\x{0dca}\x{0dcf}-\x{0dd4}\x{0dd6}\x{0dd8}-\x{0ddf}\x{0df2}\x{0df3}\x{0e31}\x{0e34}-\x{0e3a}\x{0e47}-\x{0e4e}\x{0e50}-\x{0e59}\x{0eb1}\x{0eb4}-\x{0eb9}\x{0ebb}\x{0ebc}\x{0ec8}-\x{0ecd}\x{0ed0}-\x{0ed9}\x{0f18}\x{0f19}\x{0f20}-\x{0f29}\x{0f35}\x{0f37}\x{0f39}\x{0f3e}\x{0f3f}\x{0f71}-\x{0f84}\x{0f86}\x{0f87}\x{0f8d}-\x{0f97}\x{0f99}-\x{0fbc}\x{0fc6}\x{102b}-\x{103e}\x{1040}-\x{1049}\x{1056}-\x{1059}\x{105e}-\x{1060}\x{1062}-\x{1064}\x{1067}-\x{106d}\x{1071}-\x{1074}\x{1082}-\x{108d}\x{108f}-\x{109d}\x{135d}-\x{135f}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}\x{1753}\x{1772}\x{1773}\x{17b4}-\x{17d3}\x{17dd}\x{17e0}-\x{17e9}\x{180b}-\x{180d}\x{1810}-\x{1819}\x{18a9}\x{1920}-\x{192b}\x{1930}-\x{193b}\x{1946}-\x{194f}\x{19b0}-\x{19c0}\x{19c8}\x{19c9}\x{19d0}-\x{19d9}\x{1a17}-\x{1a1b}\x{1a55}-\x{1a5e}\x{1a60}-\x{1a7c}\x{1a7f}-\x{1a89}\x{1a90}-\x{1a99}\x{1b00}-\x{1b04}\x{1b34}-\x{1b44}\x{1b50}-\x{1b59}\x{1b6b}-\x{1b73}\x{1b80}-\x{1b82}\x{1ba1}-\x{1bad}\x{1bb0}-\x{1bb9}\x{1be6}-\x{1bf3}\x{1c24}-\x{1c37}\x{1c40}-\x{1c49}\x{1c50}-\x{1c59}\x{1cd0}-\x{1cd2}\x{1cd4}-\x{1ce8}\x{1ced}\x{1cf2}-\x{1cf4}\x{1dc0}-\x{1de6}\x{1dfc}-\x{1dff}\x{200c}\x{200d}\x{203f}\x{2040}\x{2054}\x{20d0}-\x{20dc}\x{20e1}\x{20e5}-\x{20f0}\x{2cef}-\x{2cf1}\x{2d7f}\x{2de0}-\x{2dff}\x{302a}-\x{302f}\x{3099}\x{309a}\x{a620}-\x{a629}\x{a66f}\x{a674}-\x{a67d}\x{a69f}\x{a6f0}\x{a6f1}\x{a802}\x{a806}\x{a80b}\x{a823}-\x{a827}\x{a880}\x{a881}\x{a8b4}-\x{a8c4}\x{a8d0}-\x{a8d9}\x{a8e0}-\x{a8f1}\x{a900}-\x{a909}\x{a926}-\x{a92d}\x{a947}-\x{a953}\x{a980}-\x{a983}\x{a9b3}-\x{a9c0}\x{a9d0}-\x{a9d9}\x{aa29}-\x{aa36}\x{aa43}\x{aa4c}\x{aa4d}\x{aa50}-\x{aa59}\x{aa7b}\x{aab0}\x{aab2}-\x{aab4}\x{aab7}\x{aab8}\x{aabe}\x{aabf}\x{aac1}\x{aaeb}-\x{aaef}\x{aaf5}\x{aaf6}\x{abe3}-\x{abea}\x{abec}\x{abed}\x{abf0}-\x{abf9}\x{fb1e}\x{fe00}-\x{fe0f}\x{fe20}-\x{fe26}\x{fe33}\x{fe34}\x{fe4d}-\x{fe4f}\x{ff10}-\x{ff19}\x{ff3f}]*\b'; |
|
26 | - |
|
27 | - /** |
|
28 | - * Full list of JavaScript reserved words. |
|
29 | - * Will be loaded from /data/js/keywords_reserved.txt. |
|
30 | - * |
|
31 | - * @see https://mathiasbynens.be/notes/reserved-keywords |
|
32 | - * |
|
33 | - * @var string[] |
|
34 | - */ |
|
35 | - protected $keywordsReserved = array(); |
|
36 | - |
|
37 | - /** |
|
38 | - * List of JavaScript reserved words that accept a <variable, value, ...> |
|
39 | - * after them. Some end of lines are not the end of a statement, like with |
|
40 | - * these keywords. |
|
41 | - * |
|
42 | - * E.g.: we shouldn't insert a ; after this else |
|
43 | - * else |
|
44 | - * console.log('this is quite fine') |
|
45 | - * |
|
46 | - * Will be loaded from /data/js/keywords_before.txt |
|
47 | - * |
|
48 | - * @var string[] |
|
49 | - */ |
|
50 | - protected $keywordsBefore = array(); |
|
51 | - |
|
52 | - /** |
|
53 | - * List of JavaScript reserved words that accept a <variable, value, ...> |
|
54 | - * before them. Some end of lines are not the end of a statement, like when |
|
55 | - * continued by one of these keywords on the newline. |
|
56 | - * |
|
57 | - * E.g.: we shouldn't insert a ; before this instanceof |
|
58 | - * variable |
|
59 | - * instanceof String |
|
60 | - * |
|
61 | - * Will be loaded from /data/js/keywords_after.txt |
|
62 | - * |
|
63 | - * @var string[] |
|
64 | - */ |
|
65 | - protected $keywordsAfter = array(); |
|
66 | - |
|
67 | - /** |
|
68 | - * List of all JavaScript operators. |
|
69 | - * |
|
70 | - * Will be loaded from /data/js/operators.txt |
|
71 | - * |
|
72 | - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators |
|
73 | - * |
|
74 | - * @var string[] |
|
75 | - */ |
|
76 | - protected $operators = array(); |
|
77 | - |
|
78 | - /** |
|
79 | - * List of JavaScript operators that accept a <variable, value, ...> after |
|
80 | - * them. Some end of lines are not the end of a statement, like with these |
|
81 | - * operators. |
|
82 | - * |
|
83 | - * Note: Most operators are fine, we've only removed !, ++ and --. |
|
84 | - * There can't be a newline separating ! and whatever it is negating. |
|
85 | - * ++ & -- have to be joined with the value they're in-/decrementing. |
|
86 | - * |
|
87 | - * Will be loaded from /data/js/operators_before.txt |
|
88 | - * |
|
89 | - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators |
|
90 | - * |
|
91 | - * @var string[] |
|
92 | - */ |
|
93 | - protected $operatorsBefore = array(); |
|
94 | - |
|
95 | - /** |
|
96 | - * List of JavaScript operators that accept a <variable, value, ...> before |
|
97 | - * them. Some end of lines are not the end of a statement, like when |
|
98 | - * continued by one of these operators on the newline. |
|
99 | - * |
|
100 | - * Note: Most operators are fine, we've only removed ), ], ++ and --. |
|
101 | - * ++ & -- have to be joined with the value they're in-/decrementing. |
|
102 | - * ) & ] are "special" in that they have lots or usecases. () for example |
|
103 | - * is used for function calls, for grouping, in if () and for (), ... |
|
104 | - * |
|
105 | - * Will be loaded from /data/js/operators_after.txt |
|
106 | - * |
|
107 | - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators |
|
108 | - * |
|
109 | - * @var string[] |
|
110 | - */ |
|
111 | - protected $operatorsAfter = array(); |
|
112 | - |
|
113 | - /** |
|
114 | - * {@inheritdoc} |
|
115 | - */ |
|
116 | - public function __construct() |
|
117 | - { |
|
118 | - call_user_func_array(array('parent', '__construct'), func_get_args()); |
|
119 | - |
|
120 | - $dataDir = __DIR__.'/../data/js/'; |
|
121 | - $options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES; |
|
122 | - $this->keywordsReserved = file($dataDir.'keywords_reserved.txt', $options); |
|
123 | - $this->keywordsBefore = file($dataDir.'keywords_before.txt', $options); |
|
124 | - $this->keywordsAfter = file($dataDir.'keywords_after.txt', $options); |
|
125 | - $this->operators = file($dataDir.'operators.txt', $options); |
|
126 | - $this->operatorsBefore = file($dataDir.'operators_before.txt', $options); |
|
127 | - $this->operatorsAfter = file($dataDir.'operators_after.txt', $options); |
|
128 | - } |
|
129 | - |
|
130 | - /** |
|
131 | - * Minify the data. |
|
132 | - * Perform JS optimizations. |
|
133 | - * |
|
134 | - * @param string[optional] $path Path to write the data to |
|
135 | - * |
|
136 | - * @return string The minified data |
|
137 | - */ |
|
138 | - public function execute($path = null) |
|
139 | - { |
|
140 | - $content = ''; |
|
141 | - |
|
142 | - // loop files |
|
143 | - foreach ($this->data as $source => $js) { |
|
144 | - /* |
|
17 | + /** |
|
18 | + * Var-matching regex based on https://stackoverflow.com/a/9337047/802993. |
|
19 | + * |
|
20 | + * Note that regular expressions using that bit must have the PCRE_UTF8 |
|
21 | + * pattern modifier (/u) set. |
|
22 | + * |
|
23 | + * @var string |
|
24 | + */ |
|
25 | + const REGEX_VARIABLE = '\b[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}0-9\x{0300}-\x{036f}\x{0483}-\x{0487}\x{0591}-\x{05bd}\x{05bf}\x{05c1}\x{05c2}\x{05c4}\x{05c5}\x{05c7}\x{0610}-\x{061a}\x{064b}-\x{0669}\x{0670}\x{06d6}-\x{06dc}\x{06df}-\x{06e4}\x{06e7}\x{06e8}\x{06ea}-\x{06ed}\x{06f0}-\x{06f9}\x{0711}\x{0730}-\x{074a}\x{07a6}-\x{07b0}\x{07c0}-\x{07c9}\x{07eb}-\x{07f3}\x{0816}-\x{0819}\x{081b}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082d}\x{0859}-\x{085b}\x{08e4}-\x{08fe}\x{0900}-\x{0903}\x{093a}-\x{093c}\x{093e}-\x{094f}\x{0951}-\x{0957}\x{0962}\x{0963}\x{0966}-\x{096f}\x{0981}-\x{0983}\x{09bc}\x{09be}-\x{09c4}\x{09c7}\x{09c8}\x{09cb}-\x{09cd}\x{09d7}\x{09e2}\x{09e3}\x{09e6}-\x{09ef}\x{0a01}-\x{0a03}\x{0a3c}\x{0a3e}-\x{0a42}\x{0a47}\x{0a48}\x{0a4b}-\x{0a4d}\x{0a51}\x{0a66}-\x{0a71}\x{0a75}\x{0a81}-\x{0a83}\x{0abc}\x{0abe}-\x{0ac5}\x{0ac7}-\x{0ac9}\x{0acb}-\x{0acd}\x{0ae2}\x{0ae3}\x{0ae6}-\x{0aef}\x{0b01}-\x{0b03}\x{0b3c}\x{0b3e}-\x{0b44}\x{0b47}\x{0b48}\x{0b4b}-\x{0b4d}\x{0b56}\x{0b57}\x{0b62}\x{0b63}\x{0b66}-\x{0b6f}\x{0b82}\x{0bbe}-\x{0bc2}\x{0bc6}-\x{0bc8}\x{0bca}-\x{0bcd}\x{0bd7}\x{0be6}-\x{0bef}\x{0c01}-\x{0c03}\x{0c3e}-\x{0c44}\x{0c46}-\x{0c48}\x{0c4a}-\x{0c4d}\x{0c55}\x{0c56}\x{0c62}\x{0c63}\x{0c66}-\x{0c6f}\x{0c82}\x{0c83}\x{0cbc}\x{0cbe}-\x{0cc4}\x{0cc6}-\x{0cc8}\x{0cca}-\x{0ccd}\x{0cd5}\x{0cd6}\x{0ce2}\x{0ce3}\x{0ce6}-\x{0cef}\x{0d02}\x{0d03}\x{0d3e}-\x{0d44}\x{0d46}-\x{0d48}\x{0d4a}-\x{0d4d}\x{0d57}\x{0d62}\x{0d63}\x{0d66}-\x{0d6f}\x{0d82}\x{0d83}\x{0dca}\x{0dcf}-\x{0dd4}\x{0dd6}\x{0dd8}-\x{0ddf}\x{0df2}\x{0df3}\x{0e31}\x{0e34}-\x{0e3a}\x{0e47}-\x{0e4e}\x{0e50}-\x{0e59}\x{0eb1}\x{0eb4}-\x{0eb9}\x{0ebb}\x{0ebc}\x{0ec8}-\x{0ecd}\x{0ed0}-\x{0ed9}\x{0f18}\x{0f19}\x{0f20}-\x{0f29}\x{0f35}\x{0f37}\x{0f39}\x{0f3e}\x{0f3f}\x{0f71}-\x{0f84}\x{0f86}\x{0f87}\x{0f8d}-\x{0f97}\x{0f99}-\x{0fbc}\x{0fc6}\x{102b}-\x{103e}\x{1040}-\x{1049}\x{1056}-\x{1059}\x{105e}-\x{1060}\x{1062}-\x{1064}\x{1067}-\x{106d}\x{1071}-\x{1074}\x{1082}-\x{108d}\x{108f}-\x{109d}\x{135d}-\x{135f}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}\x{1753}\x{1772}\x{1773}\x{17b4}-\x{17d3}\x{17dd}\x{17e0}-\x{17e9}\x{180b}-\x{180d}\x{1810}-\x{1819}\x{18a9}\x{1920}-\x{192b}\x{1930}-\x{193b}\x{1946}-\x{194f}\x{19b0}-\x{19c0}\x{19c8}\x{19c9}\x{19d0}-\x{19d9}\x{1a17}-\x{1a1b}\x{1a55}-\x{1a5e}\x{1a60}-\x{1a7c}\x{1a7f}-\x{1a89}\x{1a90}-\x{1a99}\x{1b00}-\x{1b04}\x{1b34}-\x{1b44}\x{1b50}-\x{1b59}\x{1b6b}-\x{1b73}\x{1b80}-\x{1b82}\x{1ba1}-\x{1bad}\x{1bb0}-\x{1bb9}\x{1be6}-\x{1bf3}\x{1c24}-\x{1c37}\x{1c40}-\x{1c49}\x{1c50}-\x{1c59}\x{1cd0}-\x{1cd2}\x{1cd4}-\x{1ce8}\x{1ced}\x{1cf2}-\x{1cf4}\x{1dc0}-\x{1de6}\x{1dfc}-\x{1dff}\x{200c}\x{200d}\x{203f}\x{2040}\x{2054}\x{20d0}-\x{20dc}\x{20e1}\x{20e5}-\x{20f0}\x{2cef}-\x{2cf1}\x{2d7f}\x{2de0}-\x{2dff}\x{302a}-\x{302f}\x{3099}\x{309a}\x{a620}-\x{a629}\x{a66f}\x{a674}-\x{a67d}\x{a69f}\x{a6f0}\x{a6f1}\x{a802}\x{a806}\x{a80b}\x{a823}-\x{a827}\x{a880}\x{a881}\x{a8b4}-\x{a8c4}\x{a8d0}-\x{a8d9}\x{a8e0}-\x{a8f1}\x{a900}-\x{a909}\x{a926}-\x{a92d}\x{a947}-\x{a953}\x{a980}-\x{a983}\x{a9b3}-\x{a9c0}\x{a9d0}-\x{a9d9}\x{aa29}-\x{aa36}\x{aa43}\x{aa4c}\x{aa4d}\x{aa50}-\x{aa59}\x{aa7b}\x{aab0}\x{aab2}-\x{aab4}\x{aab7}\x{aab8}\x{aabe}\x{aabf}\x{aac1}\x{aaeb}-\x{aaef}\x{aaf5}\x{aaf6}\x{abe3}-\x{abea}\x{abec}\x{abed}\x{abf0}-\x{abf9}\x{fb1e}\x{fe00}-\x{fe0f}\x{fe20}-\x{fe26}\x{fe33}\x{fe34}\x{fe4d}-\x{fe4f}\x{ff10}-\x{ff19}\x{ff3f}]*\b'; |
|
26 | + |
|
27 | + /** |
|
28 | + * Full list of JavaScript reserved words. |
|
29 | + * Will be loaded from /data/js/keywords_reserved.txt. |
|
30 | + * |
|
31 | + * @see https://mathiasbynens.be/notes/reserved-keywords |
|
32 | + * |
|
33 | + * @var string[] |
|
34 | + */ |
|
35 | + protected $keywordsReserved = array(); |
|
36 | + |
|
37 | + /** |
|
38 | + * List of JavaScript reserved words that accept a <variable, value, ...> |
|
39 | + * after them. Some end of lines are not the end of a statement, like with |
|
40 | + * these keywords. |
|
41 | + * |
|
42 | + * E.g.: we shouldn't insert a ; after this else |
|
43 | + * else |
|
44 | + * console.log('this is quite fine') |
|
45 | + * |
|
46 | + * Will be loaded from /data/js/keywords_before.txt |
|
47 | + * |
|
48 | + * @var string[] |
|
49 | + */ |
|
50 | + protected $keywordsBefore = array(); |
|
51 | + |
|
52 | + /** |
|
53 | + * List of JavaScript reserved words that accept a <variable, value, ...> |
|
54 | + * before them. Some end of lines are not the end of a statement, like when |
|
55 | + * continued by one of these keywords on the newline. |
|
56 | + * |
|
57 | + * E.g.: we shouldn't insert a ; before this instanceof |
|
58 | + * variable |
|
59 | + * instanceof String |
|
60 | + * |
|
61 | + * Will be loaded from /data/js/keywords_after.txt |
|
62 | + * |
|
63 | + * @var string[] |
|
64 | + */ |
|
65 | + protected $keywordsAfter = array(); |
|
66 | + |
|
67 | + /** |
|
68 | + * List of all JavaScript operators. |
|
69 | + * |
|
70 | + * Will be loaded from /data/js/operators.txt |
|
71 | + * |
|
72 | + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators |
|
73 | + * |
|
74 | + * @var string[] |
|
75 | + */ |
|
76 | + protected $operators = array(); |
|
77 | + |
|
78 | + /** |
|
79 | + * List of JavaScript operators that accept a <variable, value, ...> after |
|
80 | + * them. Some end of lines are not the end of a statement, like with these |
|
81 | + * operators. |
|
82 | + * |
|
83 | + * Note: Most operators are fine, we've only removed !, ++ and --. |
|
84 | + * There can't be a newline separating ! and whatever it is negating. |
|
85 | + * ++ & -- have to be joined with the value they're in-/decrementing. |
|
86 | + * |
|
87 | + * Will be loaded from /data/js/operators_before.txt |
|
88 | + * |
|
89 | + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators |
|
90 | + * |
|
91 | + * @var string[] |
|
92 | + */ |
|
93 | + protected $operatorsBefore = array(); |
|
94 | + |
|
95 | + /** |
|
96 | + * List of JavaScript operators that accept a <variable, value, ...> before |
|
97 | + * them. Some end of lines are not the end of a statement, like when |
|
98 | + * continued by one of these operators on the newline. |
|
99 | + * |
|
100 | + * Note: Most operators are fine, we've only removed ), ], ++ and --. |
|
101 | + * ++ & -- have to be joined with the value they're in-/decrementing. |
|
102 | + * ) & ] are "special" in that they have lots or usecases. () for example |
|
103 | + * is used for function calls, for grouping, in if () and for (), ... |
|
104 | + * |
|
105 | + * Will be loaded from /data/js/operators_after.txt |
|
106 | + * |
|
107 | + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators |
|
108 | + * |
|
109 | + * @var string[] |
|
110 | + */ |
|
111 | + protected $operatorsAfter = array(); |
|
112 | + |
|
113 | + /** |
|
114 | + * {@inheritdoc} |
|
115 | + */ |
|
116 | + public function __construct() |
|
117 | + { |
|
118 | + call_user_func_array(array('parent', '__construct'), func_get_args()); |
|
119 | + |
|
120 | + $dataDir = __DIR__.'/../data/js/'; |
|
121 | + $options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES; |
|
122 | + $this->keywordsReserved = file($dataDir.'keywords_reserved.txt', $options); |
|
123 | + $this->keywordsBefore = file($dataDir.'keywords_before.txt', $options); |
|
124 | + $this->keywordsAfter = file($dataDir.'keywords_after.txt', $options); |
|
125 | + $this->operators = file($dataDir.'operators.txt', $options); |
|
126 | + $this->operatorsBefore = file($dataDir.'operators_before.txt', $options); |
|
127 | + $this->operatorsAfter = file($dataDir.'operators_after.txt', $options); |
|
128 | + } |
|
129 | + |
|
130 | + /** |
|
131 | + * Minify the data. |
|
132 | + * Perform JS optimizations. |
|
133 | + * |
|
134 | + * @param string[optional] $path Path to write the data to |
|
135 | + * |
|
136 | + * @return string The minified data |
|
137 | + */ |
|
138 | + public function execute($path = null) |
|
139 | + { |
|
140 | + $content = ''; |
|
141 | + |
|
142 | + // loop files |
|
143 | + foreach ($this->data as $source => $js) { |
|
144 | + /* |
|
145 | 145 | * Combine js: separating the scripts by a ; |
146 | 146 | * I'm also adding a newline: it will be eaten when whitespace is |
147 | 147 | * stripped, but we need to make sure we're not just appending |
@@ -149,10 +149,10 @@ discard block |
||
149 | 149 | * singe-line comment on the last line (in which case it would also |
150 | 150 | * be seen as part of that comment) |
151 | 151 | */ |
152 | - $content .= $js."\n;"; |
|
153 | - } |
|
152 | + $content .= $js."\n;"; |
|
153 | + } |
|
154 | 154 | |
155 | - /* |
|
155 | + /* |
|
156 | 156 | * Let's first take out strings, comments and regular expressions. |
157 | 157 | * All of these can contain JS code-like characters, and we should make |
158 | 158 | * sure any further magic ignores anything inside of these. |
@@ -163,164 +163,164 @@ discard block |
||
163 | 163 | * Comments will be removed altogether, strings and regular expressions |
164 | 164 | * will be replaced by placeholder text, which we'll restore later. |
165 | 165 | */ |
166 | - $this->extractStrings('\'"`'); |
|
167 | - $this->stripComments(); |
|
168 | - $this->extractRegex(); |
|
169 | - $content = $this->replace($content); |
|
166 | + $this->extractStrings('\'"`'); |
|
167 | + $this->stripComments(); |
|
168 | + $this->extractRegex(); |
|
169 | + $content = $this->replace($content); |
|
170 | 170 | |
171 | - $content = $this->propertyNotation($content); |
|
172 | - $content = $this->shortenBools($content); |
|
173 | - $content = $this->stripWhitespace($content); |
|
171 | + $content = $this->propertyNotation($content); |
|
172 | + $content = $this->shortenBools($content); |
|
173 | + $content = $this->stripWhitespace($content); |
|
174 | 174 | |
175 | - /* |
|
175 | + /* |
|
176 | 176 | * Earlier, we extracted strings & regular expressions and replaced them |
177 | 177 | * with placeholder text. This will restore them. |
178 | 178 | */ |
179 | - $content = $this->restoreExtractedData($content); |
|
180 | - |
|
181 | - return $content; |
|
182 | - } |
|
183 | - |
|
184 | - /** |
|
185 | - * Strip comments from source code. |
|
186 | - */ |
|
187 | - protected function stripComments() |
|
188 | - { |
|
189 | - // single-line comments |
|
190 | - $this->registerPattern('/\/\/.*$/m', ''); |
|
191 | - |
|
192 | - // multi-line comments |
|
193 | - $this->registerPattern('/\/\*.*?\*\//s', ''); |
|
194 | - } |
|
195 | - |
|
196 | - /** |
|
197 | - * JS can have /-delimited regular expressions, like: /ab+c/.match(string). |
|
198 | - * |
|
199 | - * The content inside the regex can contain characters that may be confused |
|
200 | - * for JS code: e.g. it could contain whitespace it needs to match & we |
|
201 | - * don't want to strip whitespace in there. |
|
202 | - * |
|
203 | - * The regex can be pretty simple: we don't have to care about comments, |
|
204 | - * (which also use slashes) because stripComments() will have stripped those |
|
205 | - * already. |
|
206 | - * |
|
207 | - * This method will replace all string content with simple REGEX# |
|
208 | - * placeholder text, so we've rid all regular expressions from characters |
|
209 | - * that may be misinterpreted. Original regex content will be saved in |
|
210 | - * $this->extracted and after doing all other minifying, we can restore the |
|
211 | - * original content via restoreRegex() |
|
212 | - */ |
|
213 | - protected function extractRegex() |
|
214 | - { |
|
215 | - // PHP only supports $this inside anonymous functions since 5.4 |
|
216 | - $minifier = $this; |
|
217 | - $callback = function ($match) use ($minifier) { |
|
218 | - $count = count($minifier->extracted); |
|
219 | - $placeholder = '/'.$count.'/'; |
|
220 | - $minifier->extracted[$placeholder] = $match[0]; |
|
221 | - |
|
222 | - return $placeholder; |
|
223 | - }; |
|
224 | - |
|
225 | - $pattern = '\/.+?(?<!\\\\)(\\\\\\\\)*\/[gimy]*(?![0-9a-zA-Z\/])'; |
|
226 | - |
|
227 | - // a regular expression can only be followed by a few operators or some |
|
228 | - // of the RegExp methods (a `\` followed by a variable or value is |
|
229 | - // likely part of a division, not a regex) |
|
230 | - $after = '[\.,;\)\}]'; |
|
231 | - $methods = '\.(exec|test|match|search|replace|split)\('; |
|
232 | - $this->registerPattern('/'.$pattern.'(?=\s*('.$after.'|'.$methods.'))/', $callback); |
|
233 | - |
|
234 | - // 1 more edge case: a regex can be followed by a lot more operators or |
|
235 | - // keywords if there's a newline (ASI) in between, where the operator |
|
236 | - // actually starts a new statement |
|
237 | - // (https://github.com/matthiasmullie/minify/issues/56) |
|
238 | - $operators = $this->getOperatorsForRegex($this->operatorsBefore, '/'); |
|
239 | - $operators += $this->getOperatorsForRegex($this->keywordsReserved, '/'); |
|
240 | - $this->registerPattern('/'.$pattern.'\s*\n(?=\s*('.implode('|', $operators).'))/', $callback); |
|
241 | - } |
|
242 | - |
|
243 | - /** |
|
244 | - * Strip whitespace. |
|
245 | - * |
|
246 | - * We won't strip *all* whitespace, but as much as possible. The thing that |
|
247 | - * we'll preserve are newlines we're unsure about. |
|
248 | - * JavaScript doesn't require statements to be terminated with a semicolon. |
|
249 | - * It will automatically fix missing semicolons with ASI (automatic semi- |
|
250 | - * colon insertion) at the end of line causing errors (without semicolon.) |
|
251 | - * |
|
252 | - * Because it's sometimes hard to tell if a newline is part of a statement |
|
253 | - * that should be terminated or not, we'll just leave some of them alone. |
|
254 | - * |
|
255 | - * @param string $content The content to strip the whitespace for |
|
256 | - * |
|
257 | - * @return string |
|
258 | - */ |
|
259 | - protected function stripWhitespace($content) |
|
260 | - { |
|
261 | - // uniform line endings, make them all line feed |
|
262 | - $content = str_replace(array("\r\n", "\r"), "\n", $content); |
|
263 | - |
|
264 | - // collapse all non-line feed whitespace into a single space |
|
265 | - $content = preg_replace('/[^\S\n]+/', ' ', $content); |
|
266 | - |
|
267 | - // strip leading & trailing whitespace |
|
268 | - $content = str_replace(array(" \n", "\n "), "\n", $content); |
|
269 | - |
|
270 | - // collapse consecutive line feeds into just 1 |
|
271 | - $content = preg_replace('/\n+/', "\n", $content); |
|
272 | - |
|
273 | - $operatorsBefore = $this->getOperatorsForRegex($this->operatorsBefore, '/'); |
|
274 | - $operatorsAfter = $this->getOperatorsForRegex($this->operatorsAfter, '/'); |
|
275 | - $operators = $this->getOperatorsForRegex($this->operators, '/'); |
|
276 | - $keywordsBefore = $this->getKeywordsForRegex($this->keywordsBefore, '/'); |
|
277 | - $keywordsAfter = $this->getKeywordsForRegex($this->keywordsAfter, '/'); |
|
278 | - |
|
279 | - // strip whitespace that ends in (or next line begin with) an operator |
|
280 | - // that allows statements to be broken up over multiple lines |
|
281 | - unset($operatorsBefore['+'], $operatorsBefore['-'], $operatorsAfter['+'], $operatorsAfter['-']); |
|
282 | - $content = preg_replace( |
|
283 | - array( |
|
284 | - '/('.implode('|', $operatorsBefore).')\s+/', |
|
285 | - '/\s+('.implode('|', $operatorsAfter).')/', |
|
286 | - ), '\\1', $content |
|
287 | - ); |
|
288 | - |
|
289 | - // make sure + and - can't be mistaken for, or joined into ++ and -- |
|
290 | - $content = preg_replace( |
|
291 | - array( |
|
292 | - '/(?<![\+\-])\s*([\+\-])(?![\+\-])/', |
|
293 | - '/(?<![\+\-])([\+\-])\s*(?![\+\-])/', |
|
294 | - ), '\\1', $content |
|
295 | - ); |
|
296 | - |
|
297 | - // collapse whitespace around reserved words into single space |
|
298 | - $content = preg_replace('/(^|[;\}\s])\K('.implode('|', $keywordsBefore).')\s+/', '\\2 ', $content); |
|
299 | - $content = preg_replace('/\s+('.implode('|', $keywordsAfter).')(?=([;\{\s]|$))/', ' \\1', $content); |
|
300 | - |
|
301 | - /* |
|
179 | + $content = $this->restoreExtractedData($content); |
|
180 | + |
|
181 | + return $content; |
|
182 | + } |
|
183 | + |
|
184 | + /** |
|
185 | + * Strip comments from source code. |
|
186 | + */ |
|
187 | + protected function stripComments() |
|
188 | + { |
|
189 | + // single-line comments |
|
190 | + $this->registerPattern('/\/\/.*$/m', ''); |
|
191 | + |
|
192 | + // multi-line comments |
|
193 | + $this->registerPattern('/\/\*.*?\*\//s', ''); |
|
194 | + } |
|
195 | + |
|
196 | + /** |
|
197 | + * JS can have /-delimited regular expressions, like: /ab+c/.match(string). |
|
198 | + * |
|
199 | + * The content inside the regex can contain characters that may be confused |
|
200 | + * for JS code: e.g. it could contain whitespace it needs to match & we |
|
201 | + * don't want to strip whitespace in there. |
|
202 | + * |
|
203 | + * The regex can be pretty simple: we don't have to care about comments, |
|
204 | + * (which also use slashes) because stripComments() will have stripped those |
|
205 | + * already. |
|
206 | + * |
|
207 | + * This method will replace all string content with simple REGEX# |
|
208 | + * placeholder text, so we've rid all regular expressions from characters |
|
209 | + * that may be misinterpreted. Original regex content will be saved in |
|
210 | + * $this->extracted and after doing all other minifying, we can restore the |
|
211 | + * original content via restoreRegex() |
|
212 | + */ |
|
213 | + protected function extractRegex() |
|
214 | + { |
|
215 | + // PHP only supports $this inside anonymous functions since 5.4 |
|
216 | + $minifier = $this; |
|
217 | + $callback = function ($match) use ($minifier) { |
|
218 | + $count = count($minifier->extracted); |
|
219 | + $placeholder = '/'.$count.'/'; |
|
220 | + $minifier->extracted[$placeholder] = $match[0]; |
|
221 | + |
|
222 | + return $placeholder; |
|
223 | + }; |
|
224 | + |
|
225 | + $pattern = '\/.+?(?<!\\\\)(\\\\\\\\)*\/[gimy]*(?![0-9a-zA-Z\/])'; |
|
226 | + |
|
227 | + // a regular expression can only be followed by a few operators or some |
|
228 | + // of the RegExp methods (a `\` followed by a variable or value is |
|
229 | + // likely part of a division, not a regex) |
|
230 | + $after = '[\.,;\)\}]'; |
|
231 | + $methods = '\.(exec|test|match|search|replace|split)\('; |
|
232 | + $this->registerPattern('/'.$pattern.'(?=\s*('.$after.'|'.$methods.'))/', $callback); |
|
233 | + |
|
234 | + // 1 more edge case: a regex can be followed by a lot more operators or |
|
235 | + // keywords if there's a newline (ASI) in between, where the operator |
|
236 | + // actually starts a new statement |
|
237 | + // (https://github.com/matthiasmullie/minify/issues/56) |
|
238 | + $operators = $this->getOperatorsForRegex($this->operatorsBefore, '/'); |
|
239 | + $operators += $this->getOperatorsForRegex($this->keywordsReserved, '/'); |
|
240 | + $this->registerPattern('/'.$pattern.'\s*\n(?=\s*('.implode('|', $operators).'))/', $callback); |
|
241 | + } |
|
242 | + |
|
243 | + /** |
|
244 | + * Strip whitespace. |
|
245 | + * |
|
246 | + * We won't strip *all* whitespace, but as much as possible. The thing that |
|
247 | + * we'll preserve are newlines we're unsure about. |
|
248 | + * JavaScript doesn't require statements to be terminated with a semicolon. |
|
249 | + * It will automatically fix missing semicolons with ASI (automatic semi- |
|
250 | + * colon insertion) at the end of line causing errors (without semicolon.) |
|
251 | + * |
|
252 | + * Because it's sometimes hard to tell if a newline is part of a statement |
|
253 | + * that should be terminated or not, we'll just leave some of them alone. |
|
254 | + * |
|
255 | + * @param string $content The content to strip the whitespace for |
|
256 | + * |
|
257 | + * @return string |
|
258 | + */ |
|
259 | + protected function stripWhitespace($content) |
|
260 | + { |
|
261 | + // uniform line endings, make them all line feed |
|
262 | + $content = str_replace(array("\r\n", "\r"), "\n", $content); |
|
263 | + |
|
264 | + // collapse all non-line feed whitespace into a single space |
|
265 | + $content = preg_replace('/[^\S\n]+/', ' ', $content); |
|
266 | + |
|
267 | + // strip leading & trailing whitespace |
|
268 | + $content = str_replace(array(" \n", "\n "), "\n", $content); |
|
269 | + |
|
270 | + // collapse consecutive line feeds into just 1 |
|
271 | + $content = preg_replace('/\n+/', "\n", $content); |
|
272 | + |
|
273 | + $operatorsBefore = $this->getOperatorsForRegex($this->operatorsBefore, '/'); |
|
274 | + $operatorsAfter = $this->getOperatorsForRegex($this->operatorsAfter, '/'); |
|
275 | + $operators = $this->getOperatorsForRegex($this->operators, '/'); |
|
276 | + $keywordsBefore = $this->getKeywordsForRegex($this->keywordsBefore, '/'); |
|
277 | + $keywordsAfter = $this->getKeywordsForRegex($this->keywordsAfter, '/'); |
|
278 | + |
|
279 | + // strip whitespace that ends in (or next line begin with) an operator |
|
280 | + // that allows statements to be broken up over multiple lines |
|
281 | + unset($operatorsBefore['+'], $operatorsBefore['-'], $operatorsAfter['+'], $operatorsAfter['-']); |
|
282 | + $content = preg_replace( |
|
283 | + array( |
|
284 | + '/('.implode('|', $operatorsBefore).')\s+/', |
|
285 | + '/\s+('.implode('|', $operatorsAfter).')/', |
|
286 | + ), '\\1', $content |
|
287 | + ); |
|
288 | + |
|
289 | + // make sure + and - can't be mistaken for, or joined into ++ and -- |
|
290 | + $content = preg_replace( |
|
291 | + array( |
|
292 | + '/(?<![\+\-])\s*([\+\-])(?![\+\-])/', |
|
293 | + '/(?<![\+\-])([\+\-])\s*(?![\+\-])/', |
|
294 | + ), '\\1', $content |
|
295 | + ); |
|
296 | + |
|
297 | + // collapse whitespace around reserved words into single space |
|
298 | + $content = preg_replace('/(^|[;\}\s])\K('.implode('|', $keywordsBefore).')\s+/', '\\2 ', $content); |
|
299 | + $content = preg_replace('/\s+('.implode('|', $keywordsAfter).')(?=([;\{\s]|$))/', ' \\1', $content); |
|
300 | + |
|
301 | + /* |
|
302 | 302 | * We didn't strip whitespace after a couple of operators because they |
303 | 303 | * could be used in different contexts and we can't be sure it's ok to |
304 | 304 | * strip the newlines. However, we can safely strip any non-line feed |
305 | 305 | * whitespace that follows them. |
306 | 306 | */ |
307 | - $operatorsDiffBefore = array_diff($operators, $operatorsBefore); |
|
308 | - $operatorsDiffAfter = array_diff($operators, $operatorsAfter); |
|
309 | - $content = preg_replace('/('.implode('|', $operatorsDiffBefore).')[^\S\n]+/', '\\1', $content); |
|
310 | - $content = preg_replace('/[^\S\n]+('.implode('|', $operatorsDiffAfter).')/', '\\1', $content); |
|
307 | + $operatorsDiffBefore = array_diff($operators, $operatorsBefore); |
|
308 | + $operatorsDiffAfter = array_diff($operators, $operatorsAfter); |
|
309 | + $content = preg_replace('/('.implode('|', $operatorsDiffBefore).')[^\S\n]+/', '\\1', $content); |
|
310 | + $content = preg_replace('/[^\S\n]+('.implode('|', $operatorsDiffAfter).')/', '\\1', $content); |
|
311 | 311 | |
312 | - /* |
|
312 | + /* |
|
313 | 313 | * Get rid of double semicolons, except where they can be used like: |
314 | 314 | * "for(v=1,_=b;;)", "for(v=1;;v++)" or "for(;;ja||(ja=true))". |
315 | 315 | * I'll safeguard these double semicolons inside for-loops by |
316 | 316 | * temporarily replacing them with an invalid condition: they won't have |
317 | 317 | * a double semicolon and will be easy to spot to restore afterwards. |
318 | 318 | */ |
319 | - $content = preg_replace('/\bfor\(([^;]*);;([^;]*)\)/', 'for(\\1;-;\\2)', $content); |
|
320 | - $content = preg_replace('/;+/', ';', $content); |
|
321 | - $content = preg_replace('/\bfor\(([^;]*);-;([^;]*)\)/', 'for(\\1;;\\2)', $content); |
|
319 | + $content = preg_replace('/\bfor\(([^;]*);;([^;]*)\)/', 'for(\\1;-;\\2)', $content); |
|
320 | + $content = preg_replace('/;+/', ';', $content); |
|
321 | + $content = preg_replace('/\bfor\(([^;]*);-;([^;]*)\)/', 'for(\\1;;\\2)', $content); |
|
322 | 322 | |
323 | - /* |
|
323 | + /* |
|
324 | 324 | * Next, we'll be removing all semicolons where ASI kicks in. |
325 | 325 | * for-loops however, can have an empty body (ending in only a |
326 | 326 | * semicolon), like: `for(i=1;i<3;i++);` |
@@ -330,9 +330,9 @@ discard block |
||
330 | 330 | * I'm going to double that semicolon (if any) so after the next line, |
331 | 331 | * which strips semicolons here & there, we're still left with this one. |
332 | 332 | */ |
333 | - $content = preg_replace('/(for\([^;]*;[^;]*;[^;\{]*\));(\}|$)/s', '\\1;;\\2', $content); |
|
333 | + $content = preg_replace('/(for\([^;]*;[^;]*;[^;\{]*\));(\}|$)/s', '\\1;;\\2', $content); |
|
334 | 334 | |
335 | - /* |
|
335 | + /* |
|
336 | 336 | * We also can't strip empty else-statements. Even though they're |
337 | 337 | * useless and probably shouldn't be in the code in the first place, we |
338 | 338 | * shouldn't be stripping the `;` that follows it as it breaks the code. |
@@ -340,114 +340,114 @@ discard block |
||
340 | 340 | * |
341 | 341 | * @see https://github.com/matthiasmullie/minify/issues/91 |
342 | 342 | */ |
343 | - $content = preg_replace('/else;/s', '', $content); |
|
343 | + $content = preg_replace('/else;/s', '', $content); |
|
344 | 344 | |
345 | - /* |
|
345 | + /* |
|
346 | 346 | * We also don't really want to terminate statements followed by closing |
347 | 347 | * curly braces (which we've ignored completely up until now) or end-of- |
348 | 348 | * script: ASI will kick in here & we're all about minifying. |
349 | 349 | * Semicolons at beginning of the file don't make any sense either. |
350 | 350 | */ |
351 | - $content = preg_replace('/;(\}|$)/s', '\\1', $content); |
|
352 | - $content = ltrim($content, ';'); |
|
353 | - |
|
354 | - // get rid of remaining whitespace af beginning/end |
|
355 | - return trim($content); |
|
356 | - } |
|
357 | - |
|
358 | - /** |
|
359 | - * We'll strip whitespace around certain operators with regular expressions. |
|
360 | - * This will prepare the given array by escaping all characters. |
|
361 | - * |
|
362 | - * @param string[] $operators |
|
363 | - * @param string $delimiter |
|
364 | - * |
|
365 | - * @return string[] |
|
366 | - */ |
|
367 | - protected function getOperatorsForRegex(array $operators, $delimiter = '/') |
|
368 | - { |
|
369 | - // escape operators for use in regex |
|
370 | - $delimiter = array_fill(0, count($operators), $delimiter); |
|
371 | - $escaped = array_map('preg_quote', $operators, $delimiter); |
|
372 | - |
|
373 | - $operators = array_combine($operators, $escaped); |
|
374 | - |
|
375 | - // ignore + & - for now, they'll get special treatment |
|
376 | - unset($operators['+'], $operators['-']); |
|
377 | - |
|
378 | - // dot can not just immediately follow a number; it can be confused for |
|
379 | - // decimal point, or calling a method on it, e.g. 42 .toString() |
|
380 | - $operators['.'] = '(?<![0-9]\s)\.'; |
|
381 | - |
|
382 | - // don't confuse = with other assignment shortcuts (e.g. +=) |
|
383 | - $chars = preg_quote('+-*\=<>%&|'); |
|
384 | - $operators['='] = '(?<!['.$chars.'])\='; |
|
385 | - |
|
386 | - return $operators; |
|
387 | - } |
|
388 | - |
|
389 | - /** |
|
390 | - * We'll strip whitespace around certain keywords with regular expressions. |
|
391 | - * This will prepare the given array by escaping all characters. |
|
392 | - * |
|
393 | - * @param string[] $keywords |
|
394 | - * @param string $delimiter |
|
395 | - * |
|
396 | - * @return string[] |
|
397 | - */ |
|
398 | - protected function getKeywordsForRegex(array $keywords, $delimiter = '/') |
|
399 | - { |
|
400 | - // escape keywords for use in regex |
|
401 | - $delimiter = array_fill(0, count($keywords), $delimiter); |
|
402 | - $escaped = array_map('preg_quote', $keywords, $delimiter); |
|
403 | - |
|
404 | - // add word boundaries |
|
405 | - array_walk($keywords, function ($value) { |
|
406 | - return '\b'.$value.'\b'; |
|
407 | - }); |
|
408 | - |
|
409 | - $keywords = array_combine($keywords, $escaped); |
|
410 | - |
|
411 | - return $keywords; |
|
412 | - } |
|
413 | - |
|
414 | - /** |
|
415 | - * Replaces all occurrences of array['key'] by array.key. |
|
416 | - * |
|
417 | - * @param string $content |
|
418 | - * |
|
419 | - * @return string |
|
420 | - */ |
|
421 | - protected function propertyNotation($content) |
|
422 | - { |
|
423 | - // PHP only supports $this inside anonymous functions since 5.4 |
|
424 | - $minifier = $this; |
|
425 | - $keywords = $this->keywordsReserved; |
|
426 | - $callback = function ($match) use ($minifier, $keywords) { |
|
427 | - $property = trim($minifier->extracted[$match[1]], '\'"'); |
|
428 | - |
|
429 | - /* |
|
351 | + $content = preg_replace('/;(\}|$)/s', '\\1', $content); |
|
352 | + $content = ltrim($content, ';'); |
|
353 | + |
|
354 | + // get rid of remaining whitespace af beginning/end |
|
355 | + return trim($content); |
|
356 | + } |
|
357 | + |
|
358 | + /** |
|
359 | + * We'll strip whitespace around certain operators with regular expressions. |
|
360 | + * This will prepare the given array by escaping all characters. |
|
361 | + * |
|
362 | + * @param string[] $operators |
|
363 | + * @param string $delimiter |
|
364 | + * |
|
365 | + * @return string[] |
|
366 | + */ |
|
367 | + protected function getOperatorsForRegex(array $operators, $delimiter = '/') |
|
368 | + { |
|
369 | + // escape operators for use in regex |
|
370 | + $delimiter = array_fill(0, count($operators), $delimiter); |
|
371 | + $escaped = array_map('preg_quote', $operators, $delimiter); |
|
372 | + |
|
373 | + $operators = array_combine($operators, $escaped); |
|
374 | + |
|
375 | + // ignore + & - for now, they'll get special treatment |
|
376 | + unset($operators['+'], $operators['-']); |
|
377 | + |
|
378 | + // dot can not just immediately follow a number; it can be confused for |
|
379 | + // decimal point, or calling a method on it, e.g. 42 .toString() |
|
380 | + $operators['.'] = '(?<![0-9]\s)\.'; |
|
381 | + |
|
382 | + // don't confuse = with other assignment shortcuts (e.g. +=) |
|
383 | + $chars = preg_quote('+-*\=<>%&|'); |
|
384 | + $operators['='] = '(?<!['.$chars.'])\='; |
|
385 | + |
|
386 | + return $operators; |
|
387 | + } |
|
388 | + |
|
389 | + /** |
|
390 | + * We'll strip whitespace around certain keywords with regular expressions. |
|
391 | + * This will prepare the given array by escaping all characters. |
|
392 | + * |
|
393 | + * @param string[] $keywords |
|
394 | + * @param string $delimiter |
|
395 | + * |
|
396 | + * @return string[] |
|
397 | + */ |
|
398 | + protected function getKeywordsForRegex(array $keywords, $delimiter = '/') |
|
399 | + { |
|
400 | + // escape keywords for use in regex |
|
401 | + $delimiter = array_fill(0, count($keywords), $delimiter); |
|
402 | + $escaped = array_map('preg_quote', $keywords, $delimiter); |
|
403 | + |
|
404 | + // add word boundaries |
|
405 | + array_walk($keywords, function ($value) { |
|
406 | + return '\b'.$value.'\b'; |
|
407 | + }); |
|
408 | + |
|
409 | + $keywords = array_combine($keywords, $escaped); |
|
410 | + |
|
411 | + return $keywords; |
|
412 | + } |
|
413 | + |
|
414 | + /** |
|
415 | + * Replaces all occurrences of array['key'] by array.key. |
|
416 | + * |
|
417 | + * @param string $content |
|
418 | + * |
|
419 | + * @return string |
|
420 | + */ |
|
421 | + protected function propertyNotation($content) |
|
422 | + { |
|
423 | + // PHP only supports $this inside anonymous functions since 5.4 |
|
424 | + $minifier = $this; |
|
425 | + $keywords = $this->keywordsReserved; |
|
426 | + $callback = function ($match) use ($minifier, $keywords) { |
|
427 | + $property = trim($minifier->extracted[$match[1]], '\'"'); |
|
428 | + |
|
429 | + /* |
|
430 | 430 | * Check if the property is a reserved keyword. In this context (as |
431 | 431 | * property of an object literal/array) it shouldn't matter, but IE8 |
432 | 432 | * freaks out with "Expected identifier". |
433 | 433 | */ |
434 | - if (in_array($property, $keywords)) { |
|
435 | - return $match[0]; |
|
436 | - } |
|
434 | + if (in_array($property, $keywords)) { |
|
435 | + return $match[0]; |
|
436 | + } |
|
437 | 437 | |
438 | - /* |
|
438 | + /* |
|
439 | 439 | * See if the property is in a variable-like format (e.g. |
440 | 440 | * array['key-here'] can't be replaced by array.key-here since '-' |
441 | 441 | * is not a valid character there. |
442 | 442 | */ |
443 | - if (!preg_match('/^'.$minifier::REGEX_VARIABLE.'$/u', $property)) { |
|
444 | - return $match[0]; |
|
445 | - } |
|
443 | + if (!preg_match('/^'.$minifier::REGEX_VARIABLE.'$/u', $property)) { |
|
444 | + return $match[0]; |
|
445 | + } |
|
446 | 446 | |
447 | - return '.'.$property; |
|
448 | - }; |
|
447 | + return '.'.$property; |
|
448 | + }; |
|
449 | 449 | |
450 | - /* |
|
450 | + /* |
|
451 | 451 | * Figure out if previous character is a variable name (of the array |
452 | 452 | * we want to use property notation on) - this is to make sure |
453 | 453 | * standalone ['value'] arrays aren't confused for keys-of-an-array. |
@@ -455,61 +455,61 @@ discard block |
||
455 | 455 | * regex implementation doesn't allow unfixed-length look-behind |
456 | 456 | * assertions. |
457 | 457 | */ |
458 | - preg_match('/(\[[^\]]+\])[^\]]*$/', static::REGEX_VARIABLE, $previousChar); |
|
459 | - $previousChar = $previousChar[1]; |
|
458 | + preg_match('/(\[[^\]]+\])[^\]]*$/', static::REGEX_VARIABLE, $previousChar); |
|
459 | + $previousChar = $previousChar[1]; |
|
460 | 460 | |
461 | - /* |
|
461 | + /* |
|
462 | 462 | * Make sure word preceding the ['value'] is not a keyword, e.g. |
463 | 463 | * return['x']. Because -again- PHP's regex implementation doesn't allow |
464 | 464 | * unfixed-length look-behind assertions, I'm just going to do a lot of |
465 | 465 | * separate look-behind assertions, one for each keyword. |
466 | 466 | */ |
467 | - $keywords = $this->getKeywordsForRegex($keywords); |
|
468 | - $keywords = '(?<!'.implode(')(?<!', $keywords).')'; |
|
469 | - |
|
470 | - return preg_replace_callback('/(?<='.$previousChar.'|\])'.$keywords.'\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content); |
|
471 | - } |
|
472 | - |
|
473 | - /** |
|
474 | - * Replaces true & false by !0 and !1. |
|
475 | - * |
|
476 | - * @param string $content |
|
477 | - * |
|
478 | - * @return string |
|
479 | - */ |
|
480 | - protected function shortenBools($content) |
|
481 | - { |
|
482 | - $content = preg_replace('/\btrue\b(?!:)/', '!0', $content); |
|
483 | - $content = preg_replace('/\bfalse\b(?!:)/', '!1', $content); |
|
484 | - |
|
485 | - // for(;;) is exactly the same as while(true) |
|
486 | - $content = preg_replace('/\bwhile\(!0\){/', 'for(;;){', $content); |
|
487 | - |
|
488 | - // now make sure we didn't turn any do ... while(true) into do ... for(;;) |
|
489 | - preg_match_all('/\bdo\b/', $content, $dos, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); |
|
490 | - |
|
491 | - // go backward to make sure positional offsets aren't altered when $content changes |
|
492 | - $dos = array_reverse($dos); |
|
493 | - foreach ($dos as $do) { |
|
494 | - $offsetDo = $do[0][1]; |
|
495 | - |
|
496 | - // find all `while` (now `for`) following `do`: one of those must be |
|
497 | - // associated with the `do` and be turned back into `while` |
|
498 | - preg_match_all('/\bfor\(;;\)/', $content, $whiles, PREG_OFFSET_CAPTURE | PREG_SET_ORDER, $offsetDo); |
|
499 | - foreach ($whiles as $while) { |
|
500 | - $offsetWhile = $while[0][1]; |
|
501 | - |
|
502 | - $open = substr_count($content, '{', $offsetDo, $offsetWhile - $offsetDo); |
|
503 | - $close = substr_count($content, '}', $offsetDo, $offsetWhile - $offsetDo); |
|
504 | - if ($open === $close) { |
|
505 | - // only restore `while` if amount of `{` and `}` are the same; |
|
506 | - // otherwise, that `for` isn't associated with this `do` |
|
507 | - $content = substr_replace($content, 'while(!0)', $offsetWhile, strlen('for(;;)')); |
|
508 | - break; |
|
509 | - } |
|
510 | - } |
|
511 | - } |
|
512 | - |
|
513 | - return $content; |
|
514 | - } |
|
467 | + $keywords = $this->getKeywordsForRegex($keywords); |
|
468 | + $keywords = '(?<!'.implode(')(?<!', $keywords).')'; |
|
469 | + |
|
470 | + return preg_replace_callback('/(?<='.$previousChar.'|\])'.$keywords.'\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content); |
|
471 | + } |
|
472 | + |
|
473 | + /** |
|
474 | + * Replaces true & false by !0 and !1. |
|
475 | + * |
|
476 | + * @param string $content |
|
477 | + * |
|
478 | + * @return string |
|
479 | + */ |
|
480 | + protected function shortenBools($content) |
|
481 | + { |
|
482 | + $content = preg_replace('/\btrue\b(?!:)/', '!0', $content); |
|
483 | + $content = preg_replace('/\bfalse\b(?!:)/', '!1', $content); |
|
484 | + |
|
485 | + // for(;;) is exactly the same as while(true) |
|
486 | + $content = preg_replace('/\bwhile\(!0\){/', 'for(;;){', $content); |
|
487 | + |
|
488 | + // now make sure we didn't turn any do ... while(true) into do ... for(;;) |
|
489 | + preg_match_all('/\bdo\b/', $content, $dos, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); |
|
490 | + |
|
491 | + // go backward to make sure positional offsets aren't altered when $content changes |
|
492 | + $dos = array_reverse($dos); |
|
493 | + foreach ($dos as $do) { |
|
494 | + $offsetDo = $do[0][1]; |
|
495 | + |
|
496 | + // find all `while` (now `for`) following `do`: one of those must be |
|
497 | + // associated with the `do` and be turned back into `while` |
|
498 | + preg_match_all('/\bfor\(;;\)/', $content, $whiles, PREG_OFFSET_CAPTURE | PREG_SET_ORDER, $offsetDo); |
|
499 | + foreach ($whiles as $while) { |
|
500 | + $offsetWhile = $while[0][1]; |
|
501 | + |
|
502 | + $open = substr_count($content, '{', $offsetDo, $offsetWhile - $offsetDo); |
|
503 | + $close = substr_count($content, '}', $offsetDo, $offsetWhile - $offsetDo); |
|
504 | + if ($open === $close) { |
|
505 | + // only restore `while` if amount of `{` and `}` are the same; |
|
506 | + // otherwise, that `for` isn't associated with this `do` |
|
507 | + $content = substr_replace($content, 'while(!0)', $offsetWhile, strlen('for(;;)')); |
|
508 | + break; |
|
509 | + } |
|
510 | + } |
|
511 | + } |
|
512 | + |
|
513 | + return $content; |
|
514 | + } |
|
515 | 515 | } |
@@ -16,335 +16,335 @@ discard block |
||
16 | 16 | */ |
17 | 17 | abstract class Minify |
18 | 18 | { |
19 | - /** |
|
20 | - * The data to be minified. |
|
21 | - * |
|
22 | - * @var string[] |
|
23 | - */ |
|
24 | - protected $data = array(); |
|
25 | - |
|
26 | - /** |
|
27 | - * Array of patterns to match. |
|
28 | - * |
|
29 | - * @var string[] |
|
30 | - */ |
|
31 | - protected $patterns = array(); |
|
32 | - |
|
33 | - /** |
|
34 | - * This array will hold content of strings and regular expressions that have |
|
35 | - * been extracted from the JS source code, so we can reliably match "code", |
|
36 | - * without having to worry about potential "code-like" characters inside. |
|
37 | - * |
|
38 | - * @var string[] |
|
39 | - */ |
|
40 | - public $extracted = array(); |
|
41 | - |
|
42 | - /** |
|
43 | - * Init the minify class - optionally, code may be passed along already. |
|
44 | - */ |
|
45 | - public function __construct(/* $data = null, ... */) |
|
46 | - { |
|
47 | - // it's possible to add the source through the constructor as well ;) |
|
48 | - if (func_num_args()) { |
|
49 | - call_user_func_array(array($this, 'add'), func_get_args()); |
|
50 | - } |
|
51 | - } |
|
52 | - |
|
53 | - /** |
|
54 | - * Add a file or straight-up code to be minified. |
|
55 | - * |
|
56 | - * @param string|string[] $data |
|
57 | - */ |
|
58 | - public function add($data /* $data = null, ... */) |
|
59 | - { |
|
60 | - // bogus "usage" of parameter $data: scrutinizer warns this variable is |
|
61 | - // not used (we're using func_get_args instead to support overloading), |
|
62 | - // but it still needs to be defined because it makes no sense to have |
|
63 | - // this function without argument :) |
|
64 | - $args = array($data) + func_get_args(); |
|
65 | - |
|
66 | - // this method can be overloaded |
|
67 | - foreach ($args as $data) { |
|
68 | - if (is_array($data)) { |
|
69 | - call_user_func_array(array($this, 'add'), $data); |
|
70 | - continue; |
|
71 | - } |
|
72 | - |
|
73 | - // redefine var |
|
74 | - $data = (string) $data; |
|
75 | - |
|
76 | - // load data |
|
77 | - $value = $this->load($data); |
|
78 | - $key = ($data != $value) ? $data : count($this->data); |
|
79 | - |
|
80 | - // replace CR linefeeds etc. |
|
81 | - // @see https://github.com/matthiasmullie/minify/pull/139 |
|
82 | - $value = str_replace(array("\r\n", "\r"), "\n", $value); |
|
83 | - |
|
84 | - // store data |
|
85 | - $this->data[$key] = $value; |
|
86 | - } |
|
87 | - } |
|
88 | - |
|
89 | - /** |
|
90 | - * Minify the data & (optionally) saves it to a file. |
|
91 | - * |
|
92 | - * @param string[optional] $path Path to write the data to |
|
93 | - * |
|
94 | - * @return string The minified data |
|
95 | - */ |
|
96 | - public function minify($path = null) |
|
97 | - { |
|
98 | - $content = $this->execute($path); |
|
99 | - |
|
100 | - // save to path |
|
101 | - if ($path !== null) { |
|
102 | - $this->save($content, $path); |
|
103 | - } |
|
104 | - |
|
105 | - return $content; |
|
106 | - } |
|
107 | - |
|
108 | - /** |
|
109 | - * Minify & gzip the data & (optionally) saves it to a file. |
|
110 | - * |
|
111 | - * @param string[optional] $path Path to write the data to |
|
112 | - * @param int[optional] $level Compression level, from 0 to 9 |
|
113 | - * |
|
114 | - * @return string The minified & gzipped data |
|
115 | - */ |
|
116 | - public function gzip($path = null, $level = 9) |
|
117 | - { |
|
118 | - $content = $this->execute($path); |
|
119 | - $content = gzencode($content, $level, FORCE_GZIP); |
|
120 | - |
|
121 | - // save to path |
|
122 | - if ($path !== null) { |
|
123 | - $this->save($content, $path); |
|
124 | - } |
|
125 | - |
|
126 | - return $content; |
|
127 | - } |
|
128 | - |
|
129 | - /** |
|
130 | - * Minify the data & write it to a CacheItemInterface object. |
|
131 | - * |
|
132 | - * @param CacheItemInterface $item Cache item to write the data to |
|
133 | - * |
|
134 | - * @return CacheItemInterface Cache item with the minifier data |
|
135 | - */ |
|
136 | - public function cache(CacheItemInterface $item) |
|
137 | - { |
|
138 | - $content = $this->execute(); |
|
139 | - $item->set($content); |
|
140 | - |
|
141 | - return $item; |
|
142 | - } |
|
143 | - |
|
144 | - /** |
|
145 | - * Minify the data. |
|
146 | - * |
|
147 | - * @param string[optional] $path Path to write the data to |
|
148 | - * |
|
149 | - * @return string The minified data |
|
150 | - */ |
|
151 | - abstract public function execute($path = null); |
|
152 | - |
|
153 | - /** |
|
154 | - * Load data. |
|
155 | - * |
|
156 | - * @param string $data Either a path to a file or the content itself |
|
157 | - * |
|
158 | - * @return string |
|
159 | - */ |
|
160 | - protected function load($data) |
|
161 | - { |
|
162 | - // check if the data is a file |
|
163 | - if ($this->canImportFile($data)) { |
|
164 | - $data = file_get_contents($data); |
|
165 | - |
|
166 | - // strip BOM, if any |
|
167 | - if (substr($data, 0, 3) == "\xef\xbb\xbf") { |
|
168 | - $data = substr($data, 3); |
|
169 | - } |
|
170 | - } |
|
171 | - |
|
172 | - return $data; |
|
173 | - } |
|
174 | - |
|
175 | - /** |
|
176 | - * Save to file. |
|
177 | - * |
|
178 | - * @param string $content The minified data |
|
179 | - * @param string $path The path to save the minified data to |
|
180 | - * |
|
181 | - * @throws IOException |
|
182 | - */ |
|
183 | - protected function save($content, $path) |
|
184 | - { |
|
185 | - $handler = $this->openFileForWriting($path); |
|
186 | - |
|
187 | - $this->writeToFile($handler, $content); |
|
188 | - |
|
189 | - @fclose($handler); |
|
190 | - } |
|
191 | - |
|
192 | - /** |
|
193 | - * Register a pattern to execute against the source content. |
|
194 | - * |
|
195 | - * @param string $pattern PCRE pattern |
|
196 | - * @param string|callable $replacement Replacement value for matched pattern |
|
197 | - */ |
|
198 | - protected function registerPattern($pattern, $replacement = '') |
|
199 | - { |
|
200 | - // study the pattern, we'll execute it more than once |
|
201 | - $pattern .= 'S'; |
|
202 | - |
|
203 | - $this->patterns[] = array($pattern, $replacement); |
|
204 | - } |
|
205 | - |
|
206 | - /** |
|
207 | - * We can't "just" run some regular expressions against JavaScript: it's a |
|
208 | - * complex language. E.g. having an occurrence of // xyz would be a comment, |
|
209 | - * unless it's used within a string. Of you could have something that looks |
|
210 | - * like a 'string', but inside a comment. |
|
211 | - * The only way to accurately replace these pieces is to traverse the JS one |
|
212 | - * character at a time and try to find whatever starts first. |
|
213 | - * |
|
214 | - * @param string $content The content to replace patterns in |
|
215 | - * |
|
216 | - * @return string The (manipulated) content |
|
217 | - */ |
|
218 | - protected function replace($content) |
|
219 | - { |
|
220 | - $processed = ''; |
|
221 | - $positions = array_fill(0, count($this->patterns), -1); |
|
222 | - $matches = array(); |
|
223 | - |
|
224 | - while ($content) { |
|
225 | - // find first match for all patterns |
|
226 | - foreach ($this->patterns as $i => $pattern) { |
|
227 | - list($pattern, $replacement) = $pattern; |
|
228 | - |
|
229 | - // no need to re-run matches that are still in the part of the |
|
230 | - // content that hasn't been processed |
|
231 | - if ($positions[$i] >= 0) { |
|
232 | - continue; |
|
233 | - } |
|
234 | - |
|
235 | - $match = null; |
|
236 | - if (preg_match($pattern, $content, $match)) { |
|
237 | - $matches[$i] = $match; |
|
238 | - |
|
239 | - // we'll store the match position as well; that way, we |
|
240 | - // don't have to redo all preg_matches after changing only |
|
241 | - // the first (we'll still know where those others are) |
|
242 | - $positions[$i] = strpos($content, $match[0]); |
|
243 | - } else { |
|
244 | - // if the pattern couldn't be matched, there's no point in |
|
245 | - // executing it again in later runs on this same content; |
|
246 | - // ignore this one until we reach end of content |
|
247 | - unset($matches[$i]); |
|
248 | - $positions[$i] = strlen($content); |
|
249 | - } |
|
250 | - } |
|
251 | - |
|
252 | - // no more matches to find: everything's been processed, break out |
|
253 | - if (!$matches) { |
|
254 | - $processed .= $content; |
|
255 | - break; |
|
256 | - } |
|
257 | - |
|
258 | - // see which of the patterns actually found the first thing (we'll |
|
259 | - // only want to execute that one, since we're unsure if what the |
|
260 | - // other found was not inside what the first found) |
|
261 | - $discardLength = min($positions); |
|
262 | - $firstPattern = array_search($discardLength, $positions); |
|
263 | - $match = $matches[$firstPattern][0]; |
|
264 | - |
|
265 | - // execute the pattern that matches earliest in the content string |
|
266 | - list($pattern, $replacement) = $this->patterns[$firstPattern]; |
|
267 | - $replacement = $this->replacePattern($pattern, $replacement, $content); |
|
268 | - |
|
269 | - // figure out which part of the string was unmatched; that's the |
|
270 | - // part we'll execute the patterns on again next |
|
271 | - $content = substr($content, $discardLength); |
|
272 | - $unmatched = (string) substr($content, strpos($content, $match) + strlen($match)); |
|
273 | - |
|
274 | - // move the replaced part to $processed and prepare $content to |
|
275 | - // again match batch of patterns against |
|
276 | - $processed .= substr($replacement, 0, strlen($replacement) - strlen($unmatched)); |
|
277 | - $content = $unmatched; |
|
278 | - |
|
279 | - // first match has been replaced & that content is to be left alone, |
|
280 | - // the next matches will start after this replacement, so we should |
|
281 | - // fix their offsets |
|
282 | - foreach ($positions as $i => $position) { |
|
283 | - $positions[$i] -= $discardLength + strlen($match); |
|
284 | - } |
|
285 | - } |
|
286 | - |
|
287 | - return $processed; |
|
288 | - } |
|
289 | - |
|
290 | - /** |
|
291 | - * This is where a pattern is matched against $content and the matches |
|
292 | - * are replaced by their respective value. |
|
293 | - * This function will be called plenty of times, where $content will always |
|
294 | - * move up 1 character. |
|
295 | - * |
|
296 | - * @param string $pattern Pattern to match |
|
297 | - * @param string|callable $replacement Replacement value |
|
298 | - * @param string $content Content to match pattern against |
|
299 | - * |
|
300 | - * @return string |
|
301 | - */ |
|
302 | - protected function replacePattern($pattern, $replacement, $content) |
|
303 | - { |
|
304 | - if (is_callable($replacement)) { |
|
305 | - return preg_replace_callback($pattern, $replacement, $content, 1, $count); |
|
306 | - } else { |
|
307 | - return preg_replace($pattern, $replacement, $content, 1, $count); |
|
308 | - } |
|
309 | - } |
|
310 | - |
|
311 | - /** |
|
312 | - * Strings are a pattern we need to match, in order to ignore potential |
|
313 | - * code-like content inside them, but we just want all of the string |
|
314 | - * content to remain untouched. |
|
315 | - * |
|
316 | - * This method will replace all string content with simple STRING# |
|
317 | - * placeholder text, so we've rid all strings from characters that may be |
|
318 | - * misinterpreted. Original string content will be saved in $this->extracted |
|
319 | - * and after doing all other minifying, we can restore the original content |
|
320 | - * via restoreStrings(). |
|
321 | - * |
|
322 | - * @param string[optional] $chars |
|
323 | - */ |
|
324 | - protected function extractStrings($chars = '\'"') |
|
325 | - { |
|
326 | - // PHP only supports $this inside anonymous functions since 5.4 |
|
327 | - $minifier = $this; |
|
328 | - $callback = function ($match) use ($minifier) { |
|
329 | - // check the second index here, because the first always contains a quote |
|
330 | - if ($match[2] === '') { |
|
331 | - /* |
|
19 | + /** |
|
20 | + * The data to be minified. |
|
21 | + * |
|
22 | + * @var string[] |
|
23 | + */ |
|
24 | + protected $data = array(); |
|
25 | + |
|
26 | + /** |
|
27 | + * Array of patterns to match. |
|
28 | + * |
|
29 | + * @var string[] |
|
30 | + */ |
|
31 | + protected $patterns = array(); |
|
32 | + |
|
33 | + /** |
|
34 | + * This array will hold content of strings and regular expressions that have |
|
35 | + * been extracted from the JS source code, so we can reliably match "code", |
|
36 | + * without having to worry about potential "code-like" characters inside. |
|
37 | + * |
|
38 | + * @var string[] |
|
39 | + */ |
|
40 | + public $extracted = array(); |
|
41 | + |
|
42 | + /** |
|
43 | + * Init the minify class - optionally, code may be passed along already. |
|
44 | + */ |
|
45 | + public function __construct(/* $data = null, ... */) |
|
46 | + { |
|
47 | + // it's possible to add the source through the constructor as well ;) |
|
48 | + if (func_num_args()) { |
|
49 | + call_user_func_array(array($this, 'add'), func_get_args()); |
|
50 | + } |
|
51 | + } |
|
52 | + |
|
53 | + /** |
|
54 | + * Add a file or straight-up code to be minified. |
|
55 | + * |
|
56 | + * @param string|string[] $data |
|
57 | + */ |
|
58 | + public function add($data /* $data = null, ... */) |
|
59 | + { |
|
60 | + // bogus "usage" of parameter $data: scrutinizer warns this variable is |
|
61 | + // not used (we're using func_get_args instead to support overloading), |
|
62 | + // but it still needs to be defined because it makes no sense to have |
|
63 | + // this function without argument :) |
|
64 | + $args = array($data) + func_get_args(); |
|
65 | + |
|
66 | + // this method can be overloaded |
|
67 | + foreach ($args as $data) { |
|
68 | + if (is_array($data)) { |
|
69 | + call_user_func_array(array($this, 'add'), $data); |
|
70 | + continue; |
|
71 | + } |
|
72 | + |
|
73 | + // redefine var |
|
74 | + $data = (string) $data; |
|
75 | + |
|
76 | + // load data |
|
77 | + $value = $this->load($data); |
|
78 | + $key = ($data != $value) ? $data : count($this->data); |
|
79 | + |
|
80 | + // replace CR linefeeds etc. |
|
81 | + // @see https://github.com/matthiasmullie/minify/pull/139 |
|
82 | + $value = str_replace(array("\r\n", "\r"), "\n", $value); |
|
83 | + |
|
84 | + // store data |
|
85 | + $this->data[$key] = $value; |
|
86 | + } |
|
87 | + } |
|
88 | + |
|
89 | + /** |
|
90 | + * Minify the data & (optionally) saves it to a file. |
|
91 | + * |
|
92 | + * @param string[optional] $path Path to write the data to |
|
93 | + * |
|
94 | + * @return string The minified data |
|
95 | + */ |
|
96 | + public function minify($path = null) |
|
97 | + { |
|
98 | + $content = $this->execute($path); |
|
99 | + |
|
100 | + // save to path |
|
101 | + if ($path !== null) { |
|
102 | + $this->save($content, $path); |
|
103 | + } |
|
104 | + |
|
105 | + return $content; |
|
106 | + } |
|
107 | + |
|
108 | + /** |
|
109 | + * Minify & gzip the data & (optionally) saves it to a file. |
|
110 | + * |
|
111 | + * @param string[optional] $path Path to write the data to |
|
112 | + * @param int[optional] $level Compression level, from 0 to 9 |
|
113 | + * |
|
114 | + * @return string The minified & gzipped data |
|
115 | + */ |
|
116 | + public function gzip($path = null, $level = 9) |
|
117 | + { |
|
118 | + $content = $this->execute($path); |
|
119 | + $content = gzencode($content, $level, FORCE_GZIP); |
|
120 | + |
|
121 | + // save to path |
|
122 | + if ($path !== null) { |
|
123 | + $this->save($content, $path); |
|
124 | + } |
|
125 | + |
|
126 | + return $content; |
|
127 | + } |
|
128 | + |
|
129 | + /** |
|
130 | + * Minify the data & write it to a CacheItemInterface object. |
|
131 | + * |
|
132 | + * @param CacheItemInterface $item Cache item to write the data to |
|
133 | + * |
|
134 | + * @return CacheItemInterface Cache item with the minifier data |
|
135 | + */ |
|
136 | + public function cache(CacheItemInterface $item) |
|
137 | + { |
|
138 | + $content = $this->execute(); |
|
139 | + $item->set($content); |
|
140 | + |
|
141 | + return $item; |
|
142 | + } |
|
143 | + |
|
144 | + /** |
|
145 | + * Minify the data. |
|
146 | + * |
|
147 | + * @param string[optional] $path Path to write the data to |
|
148 | + * |
|
149 | + * @return string The minified data |
|
150 | + */ |
|
151 | + abstract public function execute($path = null); |
|
152 | + |
|
153 | + /** |
|
154 | + * Load data. |
|
155 | + * |
|
156 | + * @param string $data Either a path to a file or the content itself |
|
157 | + * |
|
158 | + * @return string |
|
159 | + */ |
|
160 | + protected function load($data) |
|
161 | + { |
|
162 | + // check if the data is a file |
|
163 | + if ($this->canImportFile($data)) { |
|
164 | + $data = file_get_contents($data); |
|
165 | + |
|
166 | + // strip BOM, if any |
|
167 | + if (substr($data, 0, 3) == "\xef\xbb\xbf") { |
|
168 | + $data = substr($data, 3); |
|
169 | + } |
|
170 | + } |
|
171 | + |
|
172 | + return $data; |
|
173 | + } |
|
174 | + |
|
175 | + /** |
|
176 | + * Save to file. |
|
177 | + * |
|
178 | + * @param string $content The minified data |
|
179 | + * @param string $path The path to save the minified data to |
|
180 | + * |
|
181 | + * @throws IOException |
|
182 | + */ |
|
183 | + protected function save($content, $path) |
|
184 | + { |
|
185 | + $handler = $this->openFileForWriting($path); |
|
186 | + |
|
187 | + $this->writeToFile($handler, $content); |
|
188 | + |
|
189 | + @fclose($handler); |
|
190 | + } |
|
191 | + |
|
192 | + /** |
|
193 | + * Register a pattern to execute against the source content. |
|
194 | + * |
|
195 | + * @param string $pattern PCRE pattern |
|
196 | + * @param string|callable $replacement Replacement value for matched pattern |
|
197 | + */ |
|
198 | + protected function registerPattern($pattern, $replacement = '') |
|
199 | + { |
|
200 | + // study the pattern, we'll execute it more than once |
|
201 | + $pattern .= 'S'; |
|
202 | + |
|
203 | + $this->patterns[] = array($pattern, $replacement); |
|
204 | + } |
|
205 | + |
|
206 | + /** |
|
207 | + * We can't "just" run some regular expressions against JavaScript: it's a |
|
208 | + * complex language. E.g. having an occurrence of // xyz would be a comment, |
|
209 | + * unless it's used within a string. Of you could have something that looks |
|
210 | + * like a 'string', but inside a comment. |
|
211 | + * The only way to accurately replace these pieces is to traverse the JS one |
|
212 | + * character at a time and try to find whatever starts first. |
|
213 | + * |
|
214 | + * @param string $content The content to replace patterns in |
|
215 | + * |
|
216 | + * @return string The (manipulated) content |
|
217 | + */ |
|
218 | + protected function replace($content) |
|
219 | + { |
|
220 | + $processed = ''; |
|
221 | + $positions = array_fill(0, count($this->patterns), -1); |
|
222 | + $matches = array(); |
|
223 | + |
|
224 | + while ($content) { |
|
225 | + // find first match for all patterns |
|
226 | + foreach ($this->patterns as $i => $pattern) { |
|
227 | + list($pattern, $replacement) = $pattern; |
|
228 | + |
|
229 | + // no need to re-run matches that are still in the part of the |
|
230 | + // content that hasn't been processed |
|
231 | + if ($positions[$i] >= 0) { |
|
232 | + continue; |
|
233 | + } |
|
234 | + |
|
235 | + $match = null; |
|
236 | + if (preg_match($pattern, $content, $match)) { |
|
237 | + $matches[$i] = $match; |
|
238 | + |
|
239 | + // we'll store the match position as well; that way, we |
|
240 | + // don't have to redo all preg_matches after changing only |
|
241 | + // the first (we'll still know where those others are) |
|
242 | + $positions[$i] = strpos($content, $match[0]); |
|
243 | + } else { |
|
244 | + // if the pattern couldn't be matched, there's no point in |
|
245 | + // executing it again in later runs on this same content; |
|
246 | + // ignore this one until we reach end of content |
|
247 | + unset($matches[$i]); |
|
248 | + $positions[$i] = strlen($content); |
|
249 | + } |
|
250 | + } |
|
251 | + |
|
252 | + // no more matches to find: everything's been processed, break out |
|
253 | + if (!$matches) { |
|
254 | + $processed .= $content; |
|
255 | + break; |
|
256 | + } |
|
257 | + |
|
258 | + // see which of the patterns actually found the first thing (we'll |
|
259 | + // only want to execute that one, since we're unsure if what the |
|
260 | + // other found was not inside what the first found) |
|
261 | + $discardLength = min($positions); |
|
262 | + $firstPattern = array_search($discardLength, $positions); |
|
263 | + $match = $matches[$firstPattern][0]; |
|
264 | + |
|
265 | + // execute the pattern that matches earliest in the content string |
|
266 | + list($pattern, $replacement) = $this->patterns[$firstPattern]; |
|
267 | + $replacement = $this->replacePattern($pattern, $replacement, $content); |
|
268 | + |
|
269 | + // figure out which part of the string was unmatched; that's the |
|
270 | + // part we'll execute the patterns on again next |
|
271 | + $content = substr($content, $discardLength); |
|
272 | + $unmatched = (string) substr($content, strpos($content, $match) + strlen($match)); |
|
273 | + |
|
274 | + // move the replaced part to $processed and prepare $content to |
|
275 | + // again match batch of patterns against |
|
276 | + $processed .= substr($replacement, 0, strlen($replacement) - strlen($unmatched)); |
|
277 | + $content = $unmatched; |
|
278 | + |
|
279 | + // first match has been replaced & that content is to be left alone, |
|
280 | + // the next matches will start after this replacement, so we should |
|
281 | + // fix their offsets |
|
282 | + foreach ($positions as $i => $position) { |
|
283 | + $positions[$i] -= $discardLength + strlen($match); |
|
284 | + } |
|
285 | + } |
|
286 | + |
|
287 | + return $processed; |
|
288 | + } |
|
289 | + |
|
290 | + /** |
|
291 | + * This is where a pattern is matched against $content and the matches |
|
292 | + * are replaced by their respective value. |
|
293 | + * This function will be called plenty of times, where $content will always |
|
294 | + * move up 1 character. |
|
295 | + * |
|
296 | + * @param string $pattern Pattern to match |
|
297 | + * @param string|callable $replacement Replacement value |
|
298 | + * @param string $content Content to match pattern against |
|
299 | + * |
|
300 | + * @return string |
|
301 | + */ |
|
302 | + protected function replacePattern($pattern, $replacement, $content) |
|
303 | + { |
|
304 | + if (is_callable($replacement)) { |
|
305 | + return preg_replace_callback($pattern, $replacement, $content, 1, $count); |
|
306 | + } else { |
|
307 | + return preg_replace($pattern, $replacement, $content, 1, $count); |
|
308 | + } |
|
309 | + } |
|
310 | + |
|
311 | + /** |
|
312 | + * Strings are a pattern we need to match, in order to ignore potential |
|
313 | + * code-like content inside them, but we just want all of the string |
|
314 | + * content to remain untouched. |
|
315 | + * |
|
316 | + * This method will replace all string content with simple STRING# |
|
317 | + * placeholder text, so we've rid all strings from characters that may be |
|
318 | + * misinterpreted. Original string content will be saved in $this->extracted |
|
319 | + * and after doing all other minifying, we can restore the original content |
|
320 | + * via restoreStrings(). |
|
321 | + * |
|
322 | + * @param string[optional] $chars |
|
323 | + */ |
|
324 | + protected function extractStrings($chars = '\'"') |
|
325 | + { |
|
326 | + // PHP only supports $this inside anonymous functions since 5.4 |
|
327 | + $minifier = $this; |
|
328 | + $callback = function ($match) use ($minifier) { |
|
329 | + // check the second index here, because the first always contains a quote |
|
330 | + if ($match[2] === '') { |
|
331 | + /* |
|
332 | 332 | * Empty strings need no placeholder; they can't be confused for |
333 | 333 | * anything else anyway. |
334 | 334 | * But we still needed to match them, for the extraction routine |
335 | 335 | * to skip over this particular string. |
336 | 336 | */ |
337 | - return $match[0]; |
|
338 | - } |
|
337 | + return $match[0]; |
|
338 | + } |
|
339 | 339 | |
340 | - $count = count($minifier->extracted); |
|
341 | - $placeholder = $match[1].$count.$match[1]; |
|
342 | - $minifier->extracted[$placeholder] = $match[1].$match[2].$match[1]; |
|
340 | + $count = count($minifier->extracted); |
|
341 | + $placeholder = $match[1].$count.$match[1]; |
|
342 | + $minifier->extracted[$placeholder] = $match[1].$match[2].$match[1]; |
|
343 | 343 | |
344 | - return $placeholder; |
|
345 | - }; |
|
344 | + return $placeholder; |
|
345 | + }; |
|
346 | 346 | |
347 | - /* |
|
347 | + /* |
|
348 | 348 | * The \\ messiness explained: |
349 | 349 | * * Don't count ' or " as end-of-string if it's escaped (has backslash |
350 | 350 | * in front of it) |
@@ -356,75 +356,75 @@ discard block |
||
356 | 356 | * considered as escape-char (times 2) and to get it in the regex, |
357 | 357 | * escaped (times 2) |
358 | 358 | */ |
359 | - $this->registerPattern('/(['.$chars.'])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback); |
|
360 | - } |
|
361 | - |
|
362 | - /** |
|
363 | - * This method will restore all extracted data (strings, regexes) that were |
|
364 | - * replaced with placeholder text in extract*(). The original content was |
|
365 | - * saved in $this->extracted. |
|
366 | - * |
|
367 | - * @param string $content |
|
368 | - * |
|
369 | - * @return string |
|
370 | - */ |
|
371 | - protected function restoreExtractedData($content) |
|
372 | - { |
|
373 | - if (!$this->extracted) { |
|
374 | - // nothing was extracted, nothing to restore |
|
375 | - return $content; |
|
376 | - } |
|
377 | - |
|
378 | - $content = strtr($content, $this->extracted); |
|
379 | - |
|
380 | - $this->extracted = array(); |
|
381 | - |
|
382 | - return $content; |
|
383 | - } |
|
384 | - |
|
385 | - /** |
|
386 | - * Check if the path is a regular file and can be read. |
|
387 | - * |
|
388 | - * @param string $path |
|
389 | - * |
|
390 | - * @return bool |
|
391 | - */ |
|
392 | - protected function canImportFile($path) |
|
393 | - { |
|
394 | - return strlen($path) < PHP_MAXPATHLEN && @is_file($path) && is_readable($path); |
|
395 | - } |
|
396 | - |
|
397 | - /** |
|
398 | - * Attempts to open file specified by $path for writing. |
|
399 | - * |
|
400 | - * @param string $path The path to the file |
|
401 | - * |
|
402 | - * @return resource Specifier for the target file |
|
403 | - * |
|
404 | - * @throws IOException |
|
405 | - */ |
|
406 | - protected function openFileForWriting($path) |
|
407 | - { |
|
408 | - if (($handler = @fopen($path, 'w')) === false) { |
|
409 | - throw new IOException('The file "'.$path.'" could not be opened for writing. Check if PHP has enough permissions.'); |
|
410 | - } |
|
411 | - |
|
412 | - return $handler; |
|
413 | - } |
|
414 | - |
|
415 | - /** |
|
416 | - * Attempts to write $content to the file specified by $handler. $path is used for printing exceptions. |
|
417 | - * |
|
418 | - * @param resource $handler The resource to write to |
|
419 | - * @param string $content The content to write |
|
420 | - * @param string $path The path to the file (for exception printing only) |
|
421 | - * |
|
422 | - * @throws IOException |
|
423 | - */ |
|
424 | - protected function writeToFile($handler, $content, $path = '') |
|
425 | - { |
|
426 | - if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) { |
|
427 | - throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.'); |
|
428 | - } |
|
429 | - } |
|
359 | + $this->registerPattern('/(['.$chars.'])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback); |
|
360 | + } |
|
361 | + |
|
362 | + /** |
|
363 | + * This method will restore all extracted data (strings, regexes) that were |
|
364 | + * replaced with placeholder text in extract*(). The original content was |
|
365 | + * saved in $this->extracted. |
|
366 | + * |
|
367 | + * @param string $content |
|
368 | + * |
|
369 | + * @return string |
|
370 | + */ |
|
371 | + protected function restoreExtractedData($content) |
|
372 | + { |
|
373 | + if (!$this->extracted) { |
|
374 | + // nothing was extracted, nothing to restore |
|
375 | + return $content; |
|
376 | + } |
|
377 | + |
|
378 | + $content = strtr($content, $this->extracted); |
|
379 | + |
|
380 | + $this->extracted = array(); |
|
381 | + |
|
382 | + return $content; |
|
383 | + } |
|
384 | + |
|
385 | + /** |
|
386 | + * Check if the path is a regular file and can be read. |
|
387 | + * |
|
388 | + * @param string $path |
|
389 | + * |
|
390 | + * @return bool |
|
391 | + */ |
|
392 | + protected function canImportFile($path) |
|
393 | + { |
|
394 | + return strlen($path) < PHP_MAXPATHLEN && @is_file($path) && is_readable($path); |
|
395 | + } |
|
396 | + |
|
397 | + /** |
|
398 | + * Attempts to open file specified by $path for writing. |
|
399 | + * |
|
400 | + * @param string $path The path to the file |
|
401 | + * |
|
402 | + * @return resource Specifier for the target file |
|
403 | + * |
|
404 | + * @throws IOException |
|
405 | + */ |
|
406 | + protected function openFileForWriting($path) |
|
407 | + { |
|
408 | + if (($handler = @fopen($path, 'w')) === false) { |
|
409 | + throw new IOException('The file "'.$path.'" could not be opened for writing. Check if PHP has enough permissions.'); |
|
410 | + } |
|
411 | + |
|
412 | + return $handler; |
|
413 | + } |
|
414 | + |
|
415 | + /** |
|
416 | + * Attempts to write $content to the file specified by $handler. $path is used for printing exceptions. |
|
417 | + * |
|
418 | + * @param resource $handler The resource to write to |
|
419 | + * @param string $content The content to write |
|
420 | + * @param string $path The path to the file (for exception printing only) |
|
421 | + * |
|
422 | + * @throws IOException |
|
423 | + */ |
|
424 | + protected function writeToFile($handler, $content, $path = '') |
|
425 | + { |
|
426 | + if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) { |
|
427 | + throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.'); |
|
428 | + } |
|
429 | + } |
|
430 | 430 | } |
@@ -325,7 +325,7 @@ discard block |
||
325 | 325 | { |
326 | 326 | // PHP only supports $this inside anonymous functions since 5.4 |
327 | 327 | $minifier = $this; |
328 | - $callback = function ($match) use ($minifier) { |
|
328 | + $callback = function($match) use ($minifier) { |
|
329 | 329 | // check the second index here, because the first always contains a quote |
330 | 330 | if ($match[2] === '') { |
331 | 331 | /* |
@@ -338,8 +338,8 @@ discard block |
||
338 | 338 | } |
339 | 339 | |
340 | 340 | $count = count($minifier->extracted); |
341 | - $placeholder = $match[1].$count.$match[1]; |
|
342 | - $minifier->extracted[$placeholder] = $match[1].$match[2].$match[1]; |
|
341 | + $placeholder = $match[1] . $count . $match[1]; |
|
342 | + $minifier->extracted[$placeholder] = $match[1] . $match[2] . $match[1]; |
|
343 | 343 | |
344 | 344 | return $placeholder; |
345 | 345 | }; |
@@ -356,7 +356,7 @@ discard block |
||
356 | 356 | * considered as escape-char (times 2) and to get it in the regex, |
357 | 357 | * escaped (times 2) |
358 | 358 | */ |
359 | - $this->registerPattern('/(['.$chars.'])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback); |
|
359 | + $this->registerPattern('/([' . $chars . '])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback); |
|
360 | 360 | } |
361 | 361 | |
362 | 362 | /** |
@@ -406,7 +406,7 @@ discard block |
||
406 | 406 | protected function openFileForWriting($path) |
407 | 407 | { |
408 | 408 | if (($handler = @fopen($path, 'w')) === false) { |
409 | - throw new IOException('The file "'.$path.'" could not be opened for writing. Check if PHP has enough permissions.'); |
|
409 | + throw new IOException('The file "' . $path . '" could not be opened for writing. Check if PHP has enough permissions.'); |
|
410 | 410 | } |
411 | 411 | |
412 | 412 | return $handler; |
@@ -424,7 +424,7 @@ discard block |
||
424 | 424 | protected function writeToFile($handler, $content, $path = '') |
425 | 425 | { |
426 | 426 | if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) { |
427 | - throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.'); |
|
427 | + throw new IOException('The file "' . $path . '" could not be written to. Check your disk space and file permissions.'); |
|
428 | 428 | } |
429 | 429 | } |
430 | 430 | } |