Textpattern PHP Cross Reference Content Management Systems

Source: /textpattern/include/txp_form.php - 861 lines - 26074 bytes - Summary - Text - Print

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          '&nbsp;',
 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 &lt;select&gt; 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 &lt;select&gt; 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

title

Description

title

Description

title

title

Body