Textpattern | PHP Cross Reference | Content Management Systems |
Description: Preferences panel user interface and interaction.
1 <?php 2 3 /* 4 * Textpattern Content Management System 5 * http://textpattern.com 6 * 7 * Copyright (C) 2005 Dean Allen 8 * Copyright (C) 2016 The Textpattern Development Team 9 * 10 * This file is part of Textpattern. 11 * 12 * Textpattern is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation, version 2. 15 * 16 * Textpattern is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with Textpattern. If not, see <http://www.gnu.org/licenses/>. 23 */ 24 25 /** 26 * Preferences panel user interface and interaction. 27 * 28 * @package Admin\Prefs 29 */ 30 31 if (!defined('txpinterface')) { 32 die('txpinterface is undefined.'); 33 } 34 35 if ($event == 'prefs') { 36 require_privs('prefs'); 37 38 bouncer($step, array( 39 'prefs_save' => true, 40 'prefs_list' => false, 41 )); 42 43 switch (strtolower($step)) { 44 case '': 45 case 'prefs_list': 46 prefs_list(); 47 break; 48 case 'prefs_save': 49 prefs_save(); 50 break; 51 } 52 } 53 54 /** 55 * Commits prefs to the database. 56 */ 57 58 function prefs_save() 59 { 60 global $prefs, $gmtoffset, $is_dst, $auto_dst, $timezone_key, $txp_user; 61 62 // Update custom fields count from database schema and cache it as a hidden pref. 63 // TODO: move this when custom fields are refactored. 64 $max_custom_fields = count(preg_grep('/^custom_\d+/', getThings("DESCRIBE ".safe_pfx('textpattern')))); 65 set_pref('max_custom_fields', $max_custom_fields, 'publish', 2); 66 67 $sql = array(); 68 $sql[] = "prefs_id = 1 AND event != '' AND type IN (".PREF_CORE.", ".PREF_PLUGIN.", ".PREF_HIDDEN.")"; 69 $sql[] = "(user_name = '' OR (user_name = '".doSlash($txp_user)."' AND name NOT IN ( 70 SELECT name FROM ".safe_pfx('txp_prefs')." WHERE user_name = '' 71 )))"; 72 73 if (!get_pref('use_comments', 1, 1)) { 74 $sql[] = "event != 'comments'"; 75 } 76 77 $prefnames = safe_rows_start( 78 "name, event, user_name, val", 79 'txp_prefs', 80 join(" AND ", $sql) 81 ); 82 83 $post = stripPost(); 84 85 if (isset($post['tempdir']) && empty($post['tempdir'])) { 86 $post['tempdir'] = find_temp_dir(); 87 } 88 89 if (!empty($post['file_max_upload_size'])) { 90 $post['file_max_upload_size'] = real_max_upload_size($post['file_max_upload_size']); 91 } 92 93 if (isset($post['auto_dst'])) { 94 $prefs['auto_dst'] = $auto_dst = $post['auto_dst']; 95 96 if (isset($post['is_dst']) && !$post['auto_dst']) { 97 $is_dst = $post['is_dst']; 98 } 99 } 100 101 // Forge $gmtoffset and $is_dst from $timezone_key if present. 102 if (!empty($post['timezone_key'])) { 103 $key = $post['timezone_key']; 104 $tzd = Txp::get('\Textpattern\Date\Timezone')->getTimeZones(); 105 106 if (isset($tzd[$key])) { 107 $prefs['timezone_key'] = $timezone_key = $key; 108 109 if ($auto_dst) { 110 $post['gmtoffset'] = $prefs['gmtoffset'] = $gmtoffset = $tzd[$key]['offset']; 111 $post['is_dst'] = $prefs['is_dst'] = $is_dst = (int)Txp::get('\Textpattern\Date\Timezone')->isDst(null, $key); 112 } 113 } 114 } 115 116 if (isset($post['siteurl'])) { 117 $post['siteurl'] = preg_replace('#^https?://#', '', rtrim($post['siteurl'], '/ ')); 118 } 119 120 while ($a = nextRow($prefnames)) { 121 extract($a); 122 123 if (!isset($post[$name]) || !has_privs('prefs.'.$event)) { 124 continue; 125 } 126 127 if (is_array($post[$name])) { 128 $post[$name] = implode(',', array_diff($post[$name], array(''))); 129 } 130 131 if ($name === 'logging' && $post[$name] === 'none' && $post[$name] !== $val) { 132 safe_truncate('txp_log'); 133 } 134 135 if ($name === 'expire_logs_after' && (int) $post[$name] !== (int) $val) { 136 safe_delete('txp_log', "time < DATE_SUB(NOW(), INTERVAL ".intval($post[$name])." DAY)"); 137 } 138 139 update_pref($name, (string) $post[$name], null, null, null, null, (string) $user_name); 140 } 141 142 update_lastmod('preferences_saved'); 143 144 prefs_list(gTxt('preferences_saved')); 145 } 146 147 /** 148 * Renders the list of preferences. 149 * 150 * Plugins may add their own prefs, for example by using plugin lifecycle events 151 * or raising a (pre) callback on event=admin / step=prefs_list so they are 152 * installed or updated when accessing the Preferences panel. Access to the 153 * prefs can be controlled by using add_privs() on 'prefs.your-prefs-event-name'. 154 * 155 * @param string $message The feedback / error string to display 156 */ 157 158 function prefs_list($message = '') 159 { 160 global $prefs, $txp_user; 161 162 extract($prefs); 163 164 pagetop(gTxt('tab_preferences'), $message); 165 166 $locale = setlocale(LC_ALL, $locale); 167 168 echo n.'<form class="prefs-form" id="prefs_form" method="post" action="index.php">'; 169 170 // TODO: remove 'custom' when custom fields are refactored. 171 $core_events = array('site', 'admin', 'publish', 'feeds', 'comments', 'custom'); 172 $joined_core = join(',', quote_list($core_events)); 173 174 $sql = array(); 175 $sql[] = 'prefs_id = 1 and event != "" and type in('.PREF_CORE.', '.PREF_PLUGIN.')'; 176 $sql[] = "(user_name = '' OR (user_name = '".doSlash($txp_user)."' AND name NOT IN ( 177 SELECT name FROM ".safe_pfx('txp_prefs')." WHERE user_name = '' 178 )))"; 179 180 if (!get_pref('use_comments', 1, 1)) { 181 $sql[] = "event != 'comments'"; 182 } 183 184 $rs = safe_rows_start( 185 "*, FIELD(event, $joined_core) AS sort_value", 186 'txp_prefs', 187 join(" AND ", $sql)." ORDER BY sort_value = 0, sort_value, event, position" 188 ); 189 190 $last_event = null; 191 $out = array(); 192 $build = array(); 193 $groupOut = array(); 194 $tabCount = $tabActive = 0; 195 $selected = get_pref('pane_prefs_visible'); 196 197 if (numRows($rs)) { 198 while ($a = nextRow($rs)) { 199 if (!has_privs('prefs.'.$a['event'])) { 200 continue; 201 } 202 203 if ($a['event'] !== $last_event) { 204 if ($last_event !== null) { 205 $build[] = tag( 206 hed(gTxt($last_event), 2, array('id' => 'prefs_group_'.$last_event.'-label')). 207 join(n, $out), 'section', array( 208 'class' => 'txp-prefs-group', 209 'id' => 'prefs_group_'.$last_event, 210 'aria-labelledby' => 'prefs_group_'.$last_event.'-label', 211 ) 212 ); 213 214 $groupOut[] = n.tag(href( 215 gTxt($last_event), 216 '#prefs_group_'.$last_event, 217 array( 218 'data-txp-pane' => $last_event, 219 'data-txp-token' => md5($last_event.'prefs'.form_token().get_pref('blog_uid')), 220 )), 221 'li', array( 222 'class' => (($last_event === $selected) ? 'ui-tabs-active ui-state-active' : '') 223 )); 224 } 225 226 if ($last_event === $selected) { 227 $tabActive = $tabCount - 1; 228 } 229 230 $last_event = $a['event']; 231 $out = array(); 232 $tabCount++; 233 } 234 235 $label = ''; 236 237 if (!in_array($a['html'], array('yesnoradio', 'is_dst'))) { 238 $label = $a['name']; 239 } 240 241 // TODO: remove exception when custom fields move to meta store. 242 $help = ''; 243 if (strpos($a['name'], 'custom_') === false) { 244 $help = $a['name']; 245 } 246 247 if ($a['html'] == 'text_input') { 248 $size = INPUT_REGULAR; 249 } else { 250 $size = ''; 251 } 252 253 $out[] = inputLabel( 254 $a['name'], 255 pref_func($a['html'], $a['name'], $a['val'], $size), 256 $label, 257 $help, 258 array( 259 'class' => 'txp-form-field', 260 'id' => 'prefs-'.$a['name'], 261 ) 262 ); 263 } 264 } 265 266 if ($last_event === null) { 267 echo graf( 268 span(null, array('class' => 'ui-icon ui-icon-info')).' '. 269 gTxt('no_preferences'), 270 array('class' => 'alert-block information') 271 ); 272 } else { 273 $build[] = tag( 274 hed(gTxt($last_event), 2, array('id' => 'prefs_group_'.$last_event.'-label')). 275 join(n, $out), 'section', array( 276 'class' => 'txp-prefs-group', 277 'id' => 'prefs_group_'.$last_event, 278 'aria-labelledby' => 'prefs_group_'.$last_event.'-label', 279 ) 280 ); 281 282 $groupOut[] = n.tag(href( 283 gTxt($last_event), 284 '#prefs_group_'.$last_event, 285 array( 286 'data-txp-pane' => $last_event, 287 'data-txp-token' => md5($last_event.'prefs'.form_token().get_pref('blog_uid')), 288 )), 289 'li', array( 290 'class' => (($last_event === $selected) ? 'ui-tabs-active ui-state-active' : '') 291 )).n; 292 293 if ($last_event === $selected) { 294 $tabActive = $tabCount - 1; 295 } 296 297 echo n.'<div class="txp-layout">'. 298 n.tag( 299 hed(gTxt('tab_preferences'), 1, array('class' => 'txp-heading')), 300 'div', array('class' => 'txp-layout-1col') 301 ). 302 n.tag_start('div', array('class' => 'txp-layout-4col-alt')). 303 wrapGroup( 304 'all_preferences', 305 n.tag(join($groupOut), 'ul', array('class' => 'switcher-list')), 306 'all_preferences' 307 ); 308 309 if ($last_event !== null) { 310 echo graf(fInput('submit', 'Submit', gTxt('save'), 'publish'), array('class' => 'txp-save')); 311 } 312 313 echo n.tag_end('div'). // End of .txp-layout-4col-alt. 314 n.tag_start('div', array('class' => 'txp-layout-4col-3span')). 315 join(n, $build). 316 n.tag_end('div'). // End of .txp-layout-4col-3span. 317 sInput('prefs_save'). 318 eInput('prefs'). 319 hInput('prefs_id', '1'). 320 tInput(); 321 } 322 323 echo n.'</div>'. // End of .txp-layout. 324 n.'</form>'. 325 script_js('var selectedTab = "' . $tabActive . '";'); 326 } 327 328 /** 329 * Calls a core or custom function to render a preference input widget. 330 * 331 * @param string $func Callable in a string presentation 332 * @param string $name HTML name/id of the input control 333 * @param string $val Initial (or current) value of the input control 334 * @param int $size Size of the input control (width or depth, dependent on control) 335 * @return string HTML 336 */ 337 338 function pref_func($func, $name, $val, $size = '') 339 { 340 if ($func != 'func' && is_callable('pref_'.$func)) { 341 $func = 'pref_'.$func; 342 } else { 343 $string = new \Textpattern\Type\StringType($func); 344 $func = $string->toCallback(); 345 346 if (!is_callable($func)) { 347 $func = 'text_input'; 348 } 349 } 350 351 return call_user_func($func, $name, $val, $size); 352 } 353 354 /** 355 * Renders a HTML <input> element. 356 * 357 * @param string $name HTML name and id of the text box 358 * @param string $val Initial (or current) content of the text box 359 * @param int $size Width of the textbox. Options are INPUT_MEDIUM | INPUT_SMALL | INPUT_XSMALL 360 * @return string HTML 361 */ 362 363 function text_input($name, $val, $size = 0) 364 { 365 $class = ''; 366 switch ($size) { 367 case INPUT_MEDIUM: 368 $class = 'input-medium'; 369 break; 370 case INPUT_SMALL: 371 $class = 'input-small'; 372 break; 373 case INPUT_XSMALL: 374 $class = 'input-xsmall'; 375 break; 376 } 377 378 return fInput('text', $name, $val, $class, '', '', $size, '', $name); 379 } 380 381 /** 382 * Renders a HTML <textarea> element. 383 * 384 * @param string $name HTML name of the textarea 385 * @param string $val Initial (or current) content of the textarea 386 * @param int $size Number of rows the textarea has 387 * @return string HTML 388 */ 389 390 function pref_longtext_input($name, $val, $size = '') 391 { 392 return text_area($name, '', '', $val, '', $size); 393 } 394 395 /** 396 * Renders a HTML <select> list of cities for timezone selection. 397 * 398 * Can be altered by plugins via the 'prefs_ui > gmtoffset' 399 * pluggable UI callback event. 400 * 401 * @param string $name HTML name of the list 402 * @param string $val Initial (or current) selected option 403 * @return string HTML 404 */ 405 406 function gmtoffset_select($name, $val) 407 { 408 // Fetch *hidden* pref 409 $key = get_pref('timezone_key', '', true); 410 411 if ($key === '') { 412 $key = (string) Txp::get('\Textpattern\Date\Timezone')->getTimezone(); 413 } 414 415 $tz = new timezone; 416 $ui = $tz->selectInput('timezone_key', $key, false, '', 'gmtoffset'); 417 418 return pluggable_ui('prefs_ui', 'gmtoffset', $ui, $name, $val); 419 } 420 421 /** 422 * Renders a HTML choice for whether Daylight Savings Time is in effect. 423 * 424 * Can be altered by plugins via the 'prefs_ui > is_dst' 425 * pluggable UI callback event. 426 * 427 * @param string $name HTML name of the widget 428 * @param string $val Initial (or current) selected item 429 * @return string HTML 430 */ 431 432 function is_dst($name, $val) 433 { 434 global $timezone_key, $auto_dst; 435 436 if ($auto_dst) { 437 $val = (int)Txp::get('\Textpattern\Date\Timezone')->isDst(null, $timezone_key); 438 } 439 440 $ui = yesnoRadio($name, $val). 441 script_js(<<<EOS 442 $(document).ready(function () 443 { 444 var radio = $("#prefs-is_dst"); 445 var radioInput = radio.find('input'); 446 var radioLabel = radio.find('.txp-form-field-label'); 447 var dstOn = $("#auto_dst-1"); 448 var dstOff = $("#auto_dst-0"); 449 450 if (radio) { 451 if (dstOn.prop("checked")) { 452 radioInput.prop("disabled", "disabled"); 453 radioLabel.addClass('disabled'); 454 } 455 456 dstOff.click(function () { 457 radioInput.removeProp("disabled"); 458 radioLabel.removeClass('disabled'); 459 }); 460 461 dstOn.click(function () { 462 radioInput.prop("disabled", "disabled"); 463 radioLabel.addClass('disabled'); 464 }); 465 } 466 }); 467 EOS 468 ); 469 470 return pluggable_ui('prefs_ui', 'is_dst', $ui, $name, $val); 471 } 472 473 /** 474 * Renders a HTML <select> list of hit logging options. 475 * 476 * @param string $name HTML name and id of the list 477 * @param string $val Initial (or current) selected item 478 * @return string HTML 479 */ 480 481 function logging($name, $val) 482 { 483 $vals = array( 484 'all' => gTxt('all_hits'), 485 'refer' => gTxt('referrers_only'), 486 'none' => gTxt('none'), 487 ); 488 489 return selectInput($name, $vals, $val, '', '', $name); 490 } 491 492 /** 493 * Renders a HTML <select> list of supported permanent link URL formats. 494 * 495 * @param string $name HTML name and id of the list 496 * @param string $val Initial (or current) selected item 497 * @return string HTML 498 */ 499 500 function permlinkmodes($name, $val) 501 { 502 $vals = array( 503 'messy' => gTxt('messy'), 504 'id_title' => gTxt('id_title'), 505 'section_id_title' => gTxt('section_id_title'), 506 'year_month_day_title' => gTxt('year_month_day_title'), 507 'section_title' => gTxt('section_title'), 508 'title_only' => gTxt('title_only'), 509 //'category_subcategory' => gTxt('category_subcategory'), 510 ); 511 512 return selectInput($name, $vals, $val, '', '', $name); 513 } 514 515 /** 516 * Renders a HTML choice of comment popup modes. 517 * 518 * @param string $name HTML name and id of the widget 519 * @param string $val Initial (or current) selected item 520 * @return string HTML 521 */ 522 523 function commentmode($name, $val) 524 { 525 $vals = array( 526 '0' => gTxt('nopopup'), 527 '1' => gTxt('popup'), 528 ); 529 530 return selectInput($name, $vals, $val, '', '', $name); 531 } 532 533 /** 534 * Renders a HTML <select> list of comment popup modes. 535 * 536 * Can be altered by plugins via the 'prefs_ui > weeks' 537 * pluggable UI callback event. 538 * 539 * @param string $name HTML name and id of the widget 540 * @param string $val Initial (or current) selected item 541 * @return string HTML 542 */ 543 544 function weeks($name, $val) 545 { 546 $weeks = gTxt('weeks'); 547 548 $vals = array( 549 '0' => gTxt('never'), 550 7 => '1 '.gTxt('week'), 551 14 => '2 '.$weeks, 552 21 => '3 '.$weeks, 553 28 => '4 '.$weeks, 554 35 => '5 '.$weeks, 555 42 => '6 '.$weeks, 556 ); 557 558 return pluggable_ui('prefs_ui', 'weeks', selectInput($name, $vals, $val, '', '', $name), $name, $val); 559 } 560 561 /** 562 * Renders a HTML <select> list of available ways to display the date. 563 * 564 * Can be altered by plugins via the 'prefs_ui > dateformats' 565 * pluggable UI callback event. 566 * 567 * @param string $name HTML name and id of the widget 568 * @param string $val Initial (or current) selected item 569 * @return string HTML 570 */ 571 572 function dateformats($name, $val) 573 { 574 $dayname = '%A'; 575 $dayshort = '%a'; 576 $daynum = is_numeric(@strftime('%e')) ? '%e' : '%d'; 577 $daynumlead = '%d'; 578 $daynumord = is_numeric(substr(trim(@strftime('%Oe')), 0, 1)) ? '%Oe' : $daynum; 579 $monthname = '%B'; 580 $monthshort = '%b'; 581 $monthnum = '%m'; 582 $year = '%Y'; 583 $yearshort = '%y'; 584 $time24 = '%H:%M'; 585 $time12 = @strftime('%p') ? '%I:%M %p' : $time24; 586 $date = @strftime('%x') ? '%x' : '%Y-%m-%d'; 587 588 $formats = array( 589 "$monthshort $daynumord, $time12", 590 "$daynum.$monthnum.$yearshort", 591 "$daynumord $monthname, $time12", 592 "$yearshort.$monthnum.$daynumlead, $time12", 593 "$dayshort $monthshort $daynumord, $time12", 594 "$dayname $monthname $daynumord, $year", 595 "$monthshort $daynumord", 596 "$daynumord $monthname $yearshort", 597 "$daynumord $monthnum $year - $time24", 598 "$daynumord $monthname $year", 599 "$daynumord $monthname $year, $time24", 600 "$daynumord. $monthname $year", 601 "$daynumord. $monthname $year, $time24", 602 "$year-$monthnum-$daynumlead", 603 "$year-$daynumlead-$monthnum", 604 "$date $time12", 605 "$date", 606 "$time24", 607 "$time12", 608 "$year-$monthnum-$daynumlead $time24", 609 ); 610 611 $ts = time(); 612 613 $vals = array(); 614 615 foreach ($formats as $f) { 616 if ($d = safe_strftime($f, $ts)) { 617 $vals[$f] = $d; 618 } 619 } 620 621 $vals['since'] = gTxt('hours_days_ago'); 622 623 return pluggable_ui('prefs_ui', 'dateformats', selectInput($name, array_unique($vals), $val, '', '', $name), compact('vals', 'name', 'val', 'ts')); 624 } 625 626 /** 627 * Renders a HTML <select> list of content permlink options. 628 * 629 * @param string $name HTML name and id of the widget 630 * @param string $val Initial (or current) selected item 631 * @return string HTML 632 */ 633 634 function permlink_format($name, $val) 635 { 636 $vals = array( 637 '0' => gTxt('permlink_intercapped'), 638 '1' => gTxt('permlink_hyphenated'), 639 ); 640 641 return selectInput($name, $vals, $val, '', '', $name); 642 } 643 644 /** 645 * Renders a HTML <select> list of site production status. 646 * 647 * @param string $name HTML name and id of the widget 648 * @param string $val Initial (or current) selected item 649 * @return string HTML 650 */ 651 652 function prod_levels($name, $val) 653 { 654 $vals = array( 655 'debug' => gTxt('production_debug'), 656 'testing' => gTxt('production_test'), 657 'live' => gTxt('production_live'), 658 ); 659 660 return selectInput($name, $vals, $val, '', '', $name); 661 } 662 663 /** 664 * Renders a HTML <select> list of available panels to show immediately 665 * after login. 666 * 667 * @param string $name HTML name of the widget 668 * @param string $val Initial (or current) selected item 669 * @return string HTML 670 */ 671 672 function default_event($name, $val) 673 { 674 $vals = areas(); 675 676 $out = array(); 677 678 foreach ($vals as $a => $b) { 679 if (count($b) > 0) { 680 $out[] = n.'<optgroup label="'.gTxt('tab_'.$a).'">'; 681 682 foreach ($b as $c => $d) { 683 $out[] = n.'<option value="'.$d.'"'.($val == $d ? ' selected="selected"' : '').'>'.$c.'</option>'; 684 } 685 686 $out[] = n.'</optgroup>'; 687 } 688 } 689 690 return n.'<select class="default-events" id="default_event" name="'.$name.'">'. 691 join('', $out). 692 n.'</select>'; 693 } 694 695 /** 696 * Renders a HTML <select> list of sendmail options. 697 * 698 * @param string $name HTML name and id of the widget 699 * @param string $val Initial (or current) selected item 700 * @return string HTML 701 */ 702 703 function commentsendmail($name, $val) 704 { 705 $vals = array( 706 '1' => gTxt('all'), 707 '0' => gTxt('none'), 708 '2' => gTxt('ham'), 709 ); 710 711 return selectInput($name, $vals, $val, '', '', $name); 712 } 713 714 /** 715 * Renders a HTML custom field. 716 * 717 * Can be altered by plugins via the 'prefs_ui > custom_set' 718 * pluggable UI callback event. 719 * 720 * @param string $name HTML name of the widget 721 * @param string $val Initial (or current) content 722 * @return string HTML 723 * @todo deprecate or move this when CFs are migrated to the meta store 724 */ 725 726 function custom_set($name, $val) 727 { 728 return pluggable_ui('prefs_ui', 'custom_set', text_input($name, $val, INPUT_REGULAR), $name, $val); 729 } 730 731 /** 732 * Renders a HTML <select> list of installed admin-side themes. 733 * 734 * Can be altered by plugins via the 'prefs_ui > theme_name' 735 * pluggable UI callback event. 736 * 737 * @param string $name HTML name and id of the widget 738 * @param string $val Initial (or current) selected item 739 * @return string HTML 740 */ 741 742 function themename($name, $val) 743 { 744 $themes = \Textpattern\Admin\Theme::names(); 745 foreach ($themes as $t) { 746 $theme = \Textpattern\Admin\Theme::factory($t); 747 if ($theme) { 748 $m = $theme->manifest(); 749 $title = empty($m['title']) ? ucwords($theme->name) : $m['title']; 750 $vals[$t] = $title; 751 unset($theme); 752 } 753 } 754 asort($vals, SORT_STRING); 755 756 return pluggable_ui('prefs_ui', 'theme_name', 757 selectInput($name, $vals, $val, '', '', $name)); 758 } 759 760 /** 761 * Renders a HTML <select> list of available public site markup schemes to 762 * adhere to. 763 * 764 * @param string $name HTML name and id of the widget 765 * @param string $val Initial (or current) selected item 766 * @return string HTML 767 */ 768 769 function doctypes($name, $val) 770 { 771 $vals = array( 772 'xhtml' => gTxt('XHTML'), 773 'html5' => gTxt('HTML5'), 774 ); 775 776 return selectInput($name, $vals, $val, '', '', $name); 777 } 778 779 /** 780 * Renders a HTML <select> list of available publishing 781 * status values. 782 * 783 * @param string $name HTML name and id of the widget 784 * @param string $val Initial (or current) selected item 785 * @return string HTML 786 */ 787 788 function defaultPublishStatus($name, $val) 789 { 790 return selectInput($name, status_list(), $val, '', '', $name); 791 } 792 793 /** 794 * Gets the maximum allowed file upload size. 795 * 796 * Computes the maximum acceptable file size to the application if the 797 * user-selected value is larger than the maximum allowed by the current PHP 798 * configuration. 799 * 800 * @param int $user_max Desired upload size supplied by the administrator 801 * @return int Actual value; the lower of user-supplied value or system-defined value 802 */ 803 804 function real_max_upload_size($user_max) 805 { 806 // The minimum of the candidates, is the real max. possible size 807 $candidates = array($user_max, 808 ini_get('post_max_size'), 809 ini_get('upload_max_filesize'), ); 810 $real_max = null; 811 foreach ($candidates as $item) { 812 $val = trim($item); 813 $modifier = strtolower(substr($val, -1)); 814 switch ($modifier) { 815 // The 'G' modifier is available since PHP 5.1.0 816 case 'g': 817 $val *= 1024; 818 case 'm': 819 $val *= 1024; 820 case 'k': 821 $val *= 1024; 822 } 823 if ($val > 1) { 824 if (is_null($real_max)) { 825 $real_max = $val; 826 } elseif ($val < $real_max) { 827 $real_max = $val; 828 } 829 } 830 } 831 832 return $real_max; 833 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title