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