Textpattern | PHP Cross Reference | Content Management Systems |
Description: Forms panel.
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 * Forms panel. 26 * 27 * @package Admin\Form 28 */ 29 30 use Textpattern\Skin\Skin; 31 use Textpattern\Skin\Form; 32 33 if (!defined('txpinterface')) { 34 die('txpinterface is undefined.'); 35 } 36 37 if ($event == 'form') { 38 require_privs('form'); 39 40 $instance = Txp::get('Textpattern\Skin\Form'); 41 42 /** 43 * List of essential forms. 44 * 45 * @global array $essential_forms 46 */ 47 48 $essential_forms = $instance->getEssential('name'); 49 50 /** 51 * List of form types. 52 * 53 * @global array $form_types 54 */ 55 56 $form_types = array(); 57 58 foreach ($instance->getTypes() as $type) { 59 $form_types[$type] = gTxt($type); 60 } 61 62 bouncer($step, array( 63 'form_edit' => false, 64 'form_create' => false, 65 'form_multi_edit' => true, 66 'form_save' => true, 67 'form_skin_change' => true, 68 'tagbuild' => false, 69 )); 70 71 switch (strtolower($step)) { 72 case '': 73 case 'form_edit': 74 case 'form_create': 75 form_edit(); 76 break; 77 case 'form_multi_edit': 78 form_multi_edit(); 79 break; 80 case 'form_save': 81 form_save(); 82 break; 83 case 'form_skin_change': 84 $instance->selectEdit(); 85 form_edit(); 86 break; 87 case 'tagbuild': 88 echo form_tagbuild(); 89 break; 90 } 91 } 92 93 /** 94 * Renders a list of form templates. 95 * 96 * This function returns a list of form templates, wrapped in a multi-edit 97 * form widget. 98 * 99 * @param array $current The selected form info 100 * @return string HTML 101 */ 102 103 function form_list($current) 104 { 105 global $essential_forms, $form_types, $txp_sections; 106 107 $criteria = "skin = '" . doSlash($current['skin']) . "'"; 108 $criteria .= callback_event('admin_criteria', 'form_list', 0, $criteria); 109 110 $rs = safe_rows_start( 111 "name, type", 112 'txp_form', 113 "$criteria ORDER BY FIELD(type, ".quote_list(array_keys($form_types), ',').") ASC, name ASC" 114 ); 115 116 if ($rs) { 117 $sections = array_keys(array_filter(array_column($txp_sections, 'skin', 'name'), function($v) use ($current) {return $v === $current['skin'];})); 118 $sections = quote_list($sections, ','); 119 $forms_in_use = !$sections ? array() : safe_column('override_form', 'textpattern', "override_form != '' AND Section IN($sections) GROUP BY override_form"); 120 $prev_type = null; 121 122 // Add a hidden field, in case only one skin is in use and multi-edit is the 123 // first action performed. This way, the value is propagated and saved, even 124 // if the skin select list is not rendered or a Form is not saved first. 125 $out[] = hInput('skin', $current['skin']); 126 127 while ($a = nextRow($rs)) { 128 extract($a); 129 $active = ($current['name'] === $name); 130 131 if ($prev_type !== $type) { 132 if ($prev_type !== null) { 133 $group_out = tag(n.join(n, $group_out).n, 'ul', array('class' => 'switcher-list')); 134 135 $label = isset($form_types[$prev_type]) ? $form_types[$prev_type] : $prev_type; 136 $out[] = wrapRegion($prev_type.'_forms_group', $group_out, 'form_'.$prev_type, $label, 'form_'.$prev_type); 137 } 138 139 $prev_type = $type; 140 $group_out = array(); 141 } 142 143 $editlink = eLink('form', 'form_edit', 'name', $name, $name); 144 $in_use = isset($forms_in_use[$name]) ? sp.tag(gTxt('status_in_use'), 'small', array('class' => 'alert-block alert-pill success')) : ''; 145 146 if (!in_array($name, $essential_forms)) { 147 $modbox = span( 148 checkbox('selected_forms[]', txpspecialchars($name), false), array('class' => 'switcher-action')); 149 } else { 150 $modbox = ''; 151 } 152 153 $group_out[] = tag(n.$modbox.$editlink.$in_use.n, 'li', array('class' => $active ? 'active' : '')); 154 } 155 156 if ($prev_type !== null) { 157 $group_out = tag(n.join(n, $group_out).n, 'ul', array('class' => 'switcher-list')); 158 159 $out[] = wrapRegion($prev_type.'_forms_group', $group_out, 'form_'.$prev_type, $form_types[$prev_type], 'form_'.$prev_type); 160 } 161 162 $out = tag(implode('', $out), 'div', array( 163 'id' => 'allforms_form_sections', 164 'role' => 'region', 165 )); 166 167 $methods = array( 168 'changetype' => array( 169 'label' => gTxt('changetype'), 170 'html' => formTypes('', false, 'changetype'), 171 ), 172 'replace' => array( 173 'label' => gTxt('override'), 174 'html' => tag(gTxt('form'), 'label', array('for' => 'changeform')). 175 form_pop($current['skin'], 'changeform'), 176 ), 177 'delete' => gTxt('delete') 178 ); 179 180 $out .= multi_edit($methods, 'form', 'form_multi_edit'); 181 182 return form($out, '', '', 'post', '', '', 'allforms_form'); 183 } 184 } 185 186 /** 187 * Processes multi-edit actions. 188 */ 189 190 function form_multi_edit() 191 { 192 $method = ps('edit_method'); 193 $forms = ps('selected_forms'); 194 $skin = ps('skin'); 195 $affected = array(); 196 $message = ''; 197 198 $skin = Txp::get('Textpattern\Skin\Skin')->setName($skin)->setEditing(); 199 200 if ($forms && is_array($forms)) { 201 if ($method == 'delete') { 202 $affected = form_delete($forms, $skin); 203 callback_event('forms_deleted', '', 0, compact('affected', 'skin')); 204 update_lastmod('form_deleted', $affected); 205 206 $message = gTxt('form_deleted', array('{list}' => join(', ', $affected))); 207 } elseif ($method == 'changetype') { 208 $new_type = ps('type'); 209 210 foreach ($forms as $name) { 211 if (form_set_type($name, $new_type)) { 212 $affected[] = $name; 213 } 214 } 215 } elseif ($method == 'replace' && form_replace($forms, $skin, ps('override_form'))) { 216 callback_event('forms_replaced', '', 0, compact('forms', 'skin')); 217 update_lastmod('form_replaced', $forms); 218 219 $message = gTxt('form_updated', array('{list}' => join(', ', $forms))); 220 } 221 } 222 223 form_edit($message); 224 } 225 226 /** 227 * Creates a new form. 228 * 229 * Directs requests back to the main editor panel, armed with a 230 * 'form_create' step. 231 */ 232 233 function form_create() 234 { 235 form_edit(); 236 } 237 238 /** 239 * Renders the main Form editor panel. 240 * 241 * @param string|array $message The activity message 242 * @param bool $refresh_partials Whether to refresh partial contents 243 */ 244 245 function form_edit($message = '', $refresh_partials = false) 246 { 247 global $instance, $event, $step; 248 249 /* 250 $partials is an array of: 251 $key => array ( 252 'mode' => {PARTIAL_STATIC | PARTIAL_VOLATILE | PARTIAL_VOLATILE_VALUE}, 253 'selector' => $DOM_selector or array($selector, $fragment, $script) of $DOM_selectors, 254 'cb' => $callback_function, 255 'html' => $return_value_of_callback_function (need not be initialised here) 256 ) 257 */ 258 $partials = array( 259 // Form list. 260 'list' => array( 261 'mode' => PARTIAL_VOLATILE, 262 'selector' => '#allforms_form_sections', 263 'cb' => 'form_list', 264 ), 265 // Name field. 266 'name' => array( 267 'mode' => PARTIAL_VOLATILE, 268 'selector' => 'div.name', 269 'cb' => 'form_partial_name', 270 ), 271 // Name value. 272 'name_value' => array( 273 'mode' => PARTIAL_VOLATILE_VALUE, 274 'selector' => '#new_form,input[name=name]', 275 'cb' => 'form_partial_name_value', 276 ), 277 // Type field. 278 'type' => array( 279 'mode' => PARTIAL_VOLATILE, 280 'selector' => '.type', 281 'cb' => 'form_partial_type', 282 ), 283 // Type value. 284 'type_value' => array( 285 'mode' => PARTIAL_VOLATILE_VALUE, 286 'selector' => '[name=type]', 287 'cb' => 'form_partial_type_value', 288 ), 289 // Textarea. 290 'template' => array( 291 'mode' => PARTIAL_STATIC, 292 'selector' => 'div.template', 293 'cb' => 'form_partial_template', 294 ), 295 ); 296 297 extract(array_map('assert_string', gpsa(array( 298 'copy', 299 'save_error', 300 'savenew', 301 'skin', 302 )))); 303 304 $name = assert_string(gps('name')); 305 $type = assert_string(gps('type')); 306 $newname = Form::sanitize(assert_string(gps('newname'))); 307 $skin = ($skin !== '') ? $skin : null; 308 $class = 'async'; 309 310 $thisSkin = Txp::get('Textpattern\Skin\Skin'); 311 $skin = $thisSkin->setName($skin)->setEditing(); 312 313 if ($step == 'form_delete' || empty($name) && $step != 'form_create' && !$savenew) { 314 $name = get_pref('last_form_saved', 'default'); 315 } elseif ((($copy || $savenew) && $newname) && !$save_error) { 316 $name = $newname; 317 } elseif ((($newname && ($newname != $name)) || $step === 'form_create') && !$save_error) { 318 $name = $newname; 319 $class = ''; 320 } elseif ($savenew && $save_error) { 321 $class = ''; 322 } 323 324 $Form = gps('Form'); 325 326 if (!$save_error) { 327 if (!extract(safe_row('*', 'txp_form', "name = '".doSlash($name)."' AND skin = '" . doSlash($skin) . "'"))) { 328 $name = ''; 329 } 330 } 331 332 $actionsExtras = ''; 333 334 if ($name) { 335 $actionsExtras .= sLink('form', 'form_create', '<span class="ui-icon ui-extra-icon-new-document"></span> '.gTxt('create_form'), 'txp-new') 336 .href('<span class="ui-icon ui-icon-copy"></span> '.gTxt('duplicate'), '#', array( 337 'class' => 'txp-clone', 338 'data-form' => 'form_form', 339 )); 340 } 341 342 $actions = graf( 343 $actionsExtras, 344 array('class' => 'txp-actions txp-actions-inline') 345 ); 346 347 $skinBlock = n.$instance->setSkin($thisSkin)->getSelectEdit(); 348 349 $buttons = graf( 350 (!is_writable($instance->getDirPath()) ? '' : 351 span( 352 checkbox2('export', gps('export'), 0, 'export'). 353 n.tag(gTxt('export_to_disk'), 'label', array('for' => 'export')) 354 , array('class' => 'txp-save-export')) 355 ). 356 n.tag_void('input', array( 357 'class' => 'publish', 358 'type' => 'submit', 359 'method' => 'post', 360 'value' => gTxt('save'), 361 )), ' class="txp-save"' 362 ); 363 364 $listActions = graf( 365 href('<span class="ui-icon ui-icon-arrowthickstop-1-s"></span> '.gTxt('expand_all'), '#', array( 366 'class' => 'txp-expand-all', 367 'aria-controls' => 'allforms_form', 368 )). 369 href('<span class="ui-icon ui-icon-arrowthickstop-1-n"></span> '.gTxt('collapse_all'), '#', array( 370 'class' => 'txp-collapse-all', 371 'aria-controls' => 'allforms_form', 372 )), array('class' => 'txp-actions') 373 ); 374 375 $rs = array( 376 'name' => $name, 377 'newname' => $newname, 378 'type' => $type, 379 'skin' => $skin, 380 'form' => $Form, 381 ); 382 383 // Get content for volatile partials. 384 $partials = updatePartials($partials, $rs, array(PARTIAL_VOLATILE, PARTIAL_VOLATILE_VALUE)); 385 386 if ($refresh_partials) { 387 $response[] = announce($message); 388 $response = array_merge($response, updateVolatilePartials($partials)); 389 send_script_response(join(";\n", $response)); 390 391 // Bail out. 392 return; 393 } 394 395 // Get content for static partials. 396 $partials = updatePartials($partials, $rs, PARTIAL_STATIC); 397 398 pagetop(gTxt('tab_forms'), $message); 399 400 echo n.'<div class="txp-layout">'. 401 n.tag( 402 hed(gTxt('tab_forms').popHelp('forms_overview'), 1, array('class' => 'txp-heading')), 403 'div', array('class' => 'txp-layout-1col') 404 ); 405 406 // Forms create/switcher column. 407 echo n.tag( 408 $skinBlock.$listActions.n. 409 $partials['list']['html'].n, 410 'div', array( 411 'class' => 'txp-layout-4col-alt', 412 'id' => 'content_switcher', 413 'role' => 'region', 414 ) 415 ); 416 417 // Forms code column. 418 echo n.tag( 419 form( 420 $actions. 421 $partials['name']['html']. 422 $partials['type']['html']. 423 $partials['template']['html']. 424 $buttons, '', '', 'post', $class, '', 'form_form'), 425 'div', array( 426 'class' => 'txp-layout-4col-3span', 427 'id' => 'main_content', 428 'role' => 'region', 429 ) 430 ); 431 432 // Tag builder dialog placeholder. 433 echo n.tag( 434 ' ', 435 'div', array( 436 'class' => 'txp-tagbuilder-content', 437 'id' => 'tagbuild_links', 438 'aria-label' => gTxt('tagbuilder'), 439 'title' => gTxt('tagbuilder'), 440 )); 441 442 echo n.'</div>'; // End of .txp-layout. 443 } 444 445 /** 446 * Saves a form template. 447 */ 448 449 function form_save() 450 { 451 global $essential_forms, $form_types, $app_mode, $instance; 452 453 extract(doSlash(array_map('assert_string', psa(array( 454 'savenew', 455 'Form', 456 'type', 457 'copy', 458 'skin', 459 ))))); 460 461 $passedName = assert_string(ps('name')); 462 $name = Form::sanitize($passedName); 463 $newname = Form::sanitize(assert_string(ps('newname'))); 464 465 $skin = Txp::get('Textpattern\Skin\Skin')->setName($skin)->setEditing(); 466 467 $save_error = false; 468 $message = ''; 469 470 if (in_array($name, $essential_forms)) { 471 $newname = $passedName = $name; 472 $type = safe_field('type', 'txp_form', "name = '".doSlash($newname)."' AND skin = '".doSlash($skin)."'"); 473 $_POST['newname'] = $newname; 474 } 475 476 if (!$newname) { 477 $message = array(gTxt('form_name_invalid'), E_ERROR); 478 $save_error = true; 479 } else { 480 if (!isset($form_types[$type])) { 481 $message = array(gTxt('form_type_missing'), E_ERROR); 482 $save_error = true; 483 } else { 484 if ($copy && $name === $newname) { 485 $newname .= '_copy'; 486 $passedName = $name; 487 $_POST['newname'] = $newname; 488 } 489 490 $exists = safe_field("name", 'txp_form', "name = '".doSlash($newname)."' AND skin = '".doSlash($skin)."'"); 491 492 if ($newname !== $name && $exists !== false) { 493 $message = array(gTxt('form_already_exists', array('{name}' => $newname)), E_ERROR); 494 495 if ($savenew) { 496 $_POST['newname'] = ''; 497 } 498 499 $save_error = true; 500 } else { 501 $safe_skin = doSlash($skin); 502 503 if ($savenew or $copy) { 504 if ($newname) { 505 if (safe_insert( 506 'txp_form', 507 "Form = '$Form', 508 type = '$type', 509 skin = '$safe_skin', 510 name = '".doSlash($newname)."'" 511 )) { 512 update_lastmod('form_created', compact('newname', 'name', 'type', 'Form')); 513 514 $message = gTxt('form_created', array('{list}' => $newname)); 515 516 // If form name has been auto-sanitized, throw a warning. 517 if ($passedName !== $name) { 518 $message = array($message, E_WARNING); 519 } 520 521 callback_event($copy ? 'form_duplicated' : 'form_created', '', 0, $name, $newname); 522 } else { 523 $message = array(gTxt('form_save_failed'), E_ERROR); 524 $save_error = true; 525 } 526 } else { 527 $message = array(gTxt('form_name_invalid'), E_ERROR); 528 $save_error = true; 529 } 530 } else { 531 if (safe_update( 532 'txp_form', 533 "Form = '$Form', 534 type = '$type', 535 skin = '$safe_skin', 536 name = '".doSlash($newname)."'", 537 "name = '".doSlash($passedName)."' AND skin = '$safe_skin'" 538 )) { 539 update_lastmod('form_saved', compact('newname', 'name', 'type', 'Form')); 540 541 $message = gTxt('form_updated', array('{list}' => $newname)); 542 543 // If form name has been auto-sanitized, throw a warning. 544 if ($passedName !== $name) { 545 $message = array($message, E_WARNING); 546 } 547 548 callback_event('form_updated', '', 0, $name, $newname); 549 } else { 550 $message = array(gTxt('form_save_failed'), E_ERROR); 551 $save_error = true; 552 } 553 } 554 } 555 } 556 } 557 558 if ($save_error === true) { 559 $_POST['save_error'] = '1'; 560 } else { 561 if (gps('export')) { 562 $instance->setNames(array($newname))->export()->getMessage(); 563 } 564 565 set_pref('last_form_saved', $newname, 'form', PREF_HIDDEN, 'text_input', 0, PREF_PRIVATE); 566 callback_event('form_saved', '', 0, $name, $newname); 567 } 568 569 form_edit($message, ($app_mode === 'async') ? true : false); 570 } 571 572 /** 573 * Deletes a form template with the given name. 574 * 575 * @param string $name The form template 576 * @param string $skin The form skin in use 577 * @return bool FALSE on error 578 */ 579 580 function form_delete($name, $skin) 581 { 582 global $prefs, $essential_forms, $txp_sections; 583 584 $sections = quote_list(array_keys(array_filter(array_column($txp_sections, 'skin', 'name'), function($v) use ($skin) {return $v === $skin;})), ','); 585 $last_form = get_pref('last_form_saved'); 586 $skin = doSlash($skin); 587 $deleted = array(); 588 589 foreach ((array)$name as $form) { 590 if ($form == '' || in_array($form, $essential_forms)) { 591 continue; 592 } elseif ($form === $last_form) { 593 unset($prefs['last_form_saved']); 594 remove_pref('last_form_saved', 'form'); 595 } 596 597 $safe_form = doSlash($form); 598 599 if (safe_delete("txp_form", "name = '$safe_form' AND skin = '$skin'")) { 600 $deleted[] = $form; 601 } 602 } 603 604 if ($sections && $deleted) { 605 $safe_form = quote_list($deleted, ','); 606 safe_update('textpattern', "override_form=''", "override_form IN($safe_form) AND Section IN($sections)"); 607 } 608 609 return is_array($name) ? $deleted : !empty($deleted); 610 } 611 612 /** 613 * Replaces a form template in articles. 614 * 615 * @param string $name The form template 616 * @param string $skin The form skin in use 617 * @param string $newform The form skin in use 618 * @return bool FALSE on error 619 */ 620 621 function form_replace($name, $skin, $newform = '') 622 { 623 global $txp_sections; 624 625 $sections = quote_list(array_keys(array_filter(array_column($txp_sections, 'skin', 'name'), function($v) use ($skin) {return $v === $skin;})), ','); 626 627 if (!$sections) { 628 return; 629 } 630 631 $forms = quote_list((array)$name, ','); 632 $newform = doSlash($newform); 633 634 return safe_update('textpattern', "override_form='$newform'", "override_form IN($forms) AND Section IN($sections)"); 635 } 636 637 /** 638 * Changes the skin in which styles are being edited. 639 * 640 * Keeps track of which skin is being edited from panel to panel. 641 * 642 * @param string $skin Optional skin name. Read from GET/POST otherwise 643 * @deprecated in 4.7.0 644 */ 645 646 function form_skin_change($skin = null) 647 { 648 Txp::get('Textpattern\Skin\Form')->selectEdit($skin); 649 650 return true; 651 } 652 653 /** 654 * Changes a form template's type. 655 * 656 * @param string $name The form template 657 * @param string $type The new type 658 * @return bool FALSE on error 659 */ 660 661 function form_set_type($name, $type) 662 { 663 global $essential_forms, $form_types; 664 665 if (in_array($name, $essential_forms) || !isset($form_types[$type])) { 666 return false; 667 } 668 669 $name = doSlash($name); 670 $type = doSlash($type); 671 $skin = doSlash(get_pref('skin_editing', 'default')); 672 673 return safe_update('txp_form', "type = '$type'", "name = '$name' AND skin = '$skin'"); 674 } 675 676 /** 677 * Renders a <select> input listing all form types. 678 * 679 * @param string $type The selected option 680 * @param bool $blank_first If TRUE, the list defaults to an empty selection 681 * @param string $id HTML id attribute value 682 * @param bool $disabled If TRUE renders the select disabled 683 * @return string HTML 684 * @access private 685 */ 686 687 function formTypes($type, $blank_first = true, $id = 'type', $disabled = false) 688 { 689 global $form_types; 690 691 return selectInput('type', $form_types, $type, $blank_first, '', $id, false, $disabled); 692 } 693 694 /** 695 * Renders 'override form' field. 696 * 697 * @param string $id HTML id to apply to the input control 698 * @param string $skin The theme that is currently in use 699 * @return string HTML <select> input 700 */ 701 702 function form_pop($skin, $id) 703 { 704 static $skinforms = null; 705 706 if (!isset($skinforms)) { 707 $form_types = get_pref('override_form_types', 'article'); 708 $safe_skin = doSlash($skin); 709 710 $rs = safe_column('name', 'txp_form', "type IN ('".implode("','", do_list($form_types))."') AND name != 'default' AND skin='$safe_skin' ORDER BY name"); 711 $skinforms = $rs ? array_combine($rs, $rs) : false; 712 } 713 714 if ($skinforms) { 715 return selectInput('override_form', $skinforms, '', true, '', $id); 716 } 717 } 718 719 /** 720 * Renders form name field. 721 * 722 * @param array $rs Record set 723 * @return string HTML 724 */ 725 726 function form_partial_name($rs) 727 { 728 global $essential_forms, $form_types; 729 730 $name = $rs['name']; 731 $skin = $rs['skin']; 732 $type = $rs['type']; 733 $nameRegex = '^(?=[^.\s])[^\x00-\x1f\x22\x26\x27\x2a\x2f\x3a\x3c\x3e\x3f\x5c\x7c\x7f]+'; 734 735 if (in_array($name, $essential_forms) || $type && !isset($form_types[$type])) { 736 $nameInput = fInput('text', array('name' => 'newname', 'pattern' => $nameRegex), $name, 'input-medium', '', '', INPUT_MEDIUM, '', 'new_form', true); 737 } else { 738 $nameInput = fInput('text', array('name' => 'newname', 'pattern' => $nameRegex), $name, 'input-medium', '', '', INPUT_MEDIUM, '', 'new_form', false, true); 739 } 740 741 $name_widgets = inputLabel( 742 'new_form', 743 $nameInput, 744 'form_name', 745 array('', 'instructions_form_name'), 746 array('class' => 'txp-form-field name') 747 ); 748 749 if ($name === '') { 750 $name_widgets .= hInput('savenew', 'savenew'); 751 } else { 752 $name_widgets .= hInput('name', $name); 753 } 754 755 $name_widgets .= hInput('skin', $skin). 756 eInput('form').sInput('form_save'); 757 758 return $name_widgets; 759 } 760 761 /** 762 * Renders form type field. 763 * 764 * @param array $rs Record set 765 * @return string HTML 766 */ 767 768 function form_partial_type($rs) 769 { 770 global $essential_forms, $form_types; 771 772 $name = $rs['name']; 773 $type = $rs['type']; 774 $type_widgets = ''; 775 776 if ($type && !isset($form_types[$type])) { 777 $typeInput = tag_void('input', array( 778 'id' => 'types', 779 'name' => 'type', 780 'type' => 'text', 781 'value' => $type, 782 'disabled' => true 783 )); 784 $type_widgets .= hInput('type', $type); 785 } elseif (in_array($name, $essential_forms)) { 786 $typeInput = formTypes($type, false, 'type', true); 787 $type_widgets .= hInput('type', $type); 788 } else { 789 $typeInput = formTypes($type, false); 790 } 791 792 $type_widgets .= inputLabel( 793 'type', 794 $typeInput, 795 'form_type', 796 array('', 'instructions_form_type'), 797 array('class' => 'txp-form-field type') 798 ); 799 800 return $type_widgets; 801 } 802 803 /** 804 * Renders form name value. 805 * 806 * @param array $rs Record set 807 * @return string HTML 808 */ 809 810 function form_partial_name_value($rs) 811 { 812 return $rs['name']; 813 } 814 815 /** 816 * Renders form type value. 817 * 818 * @param array $rs Record set 819 * @return string HTML 820 */ 821 822 function form_partial_type_value($rs) 823 { 824 return $rs['type']; 825 } 826 827 /** 828 * Renders form textarea field. 829 * 830 * @param array $rs Record set 831 * @return string HTML 832 */ 833 834 function form_partial_template($rs) 835 { 836 global $event; 837 838 $out = inputLabel( 839 'form', 840 '<textarea class="code" id="form" name="Form" cols="'.INPUT_LARGE.'" rows="'.TEXTAREA_HEIGHT_LARGE.'" dir="ltr">'.txpspecialchars($rs['form']).'</textarea>', 841 array( 842 'form_code', 843 n.span( 844 (has_privs('tag') 845 ? href( 846 span(null, array('class' => 'ui-icon ui-extra-icon-code')).' '.gTxt('tagbuilder'), 847 array('event' => 'tag', 'panel' => $event), 848 array('class' => 'txp-tagbuilder-dialog') 849 ) 850 : '' 851 ), 852 array('class' => 'txp-textarea-options') 853 ) 854 ), 855 array('', 'instructions_form_code'), 856 array('class' => 'txp-form-field template'), 857 array('div', 'div') 858 ); 859 860 return $out; 861 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title