form.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  1. <?php
  2. /**
  3. * DokuWiki XHTML Form
  4. *
  5. * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
  6. * @author Tom N Harris <tnharris@whoopdedo.org>
  7. */
  8. // phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
  9. // phpcs:disable PSR2.Classes.PropertyDeclaration.Underscore
  10. /**
  11. * Class for creating simple HTML forms.
  12. *
  13. * The forms is built from a list of pseudo-tags (arrays with expected keys).
  14. * Every pseudo-tag must have the key '_elem' set to the name of the element.
  15. * When printed, the form class calls functions named 'form_$type' for each
  16. * element it contains.
  17. *
  18. * Standard practice is for non-attribute keys in a pseudo-element to start
  19. * with '_'. Other keys are HTML attributes that will be included in the element
  20. * tag. That way, the element output functions can pass the pseudo-element
  21. * directly to buildAttributes.
  22. *
  23. * See the form_make* functions later in this file.
  24. *
  25. * Please note that even though this class is technically deprecated (use dokuwiki\Form instead),
  26. * it is still widely used in the core and the related form events. Until those have been rewritten,
  27. * this will continue to be used
  28. *
  29. * @deprecated 2019-07-14
  30. * @author Tom N Harris <tnharris@whoopdedo.org>
  31. */
  32. class Doku_Form
  33. {
  34. // Form id attribute
  35. public $params = array();
  36. // Draw a border around form fields.
  37. // Adds <fieldset></fieldset> around the elements
  38. public $_infieldset = false;
  39. // Hidden form fields.
  40. public $_hidden = array();
  41. // Array of pseudo-tags
  42. public $_content = array();
  43. /**
  44. * Constructor
  45. *
  46. * Sets parameters and autoadds a security token. The old calling convention
  47. * with up to four parameters is deprecated, instead the first parameter
  48. * should be an array with parameters.
  49. *
  50. * @param mixed $params Parameters for the HTML form element; Using the deprecated
  51. * calling convention this is the ID attribute of the form
  52. * @param bool|string $action (optional, deprecated) submit URL, defaults to current page
  53. * @param bool|string $method (optional, deprecated) 'POST' or 'GET', default is POST
  54. * @param bool|string $enctype (optional, deprecated) Encoding type of the data
  55. *
  56. * @author Tom N Harris <tnharris@whoopdedo.org>
  57. */
  58. public function __construct($params, $action=false, $method=false, $enctype=false)
  59. {
  60. if (!is_array($params)) {
  61. $this->params = array('id' => $params);
  62. if ($action !== false) $this->params['action'] = $action;
  63. if ($method !== false) $this->params['method'] = strtolower($method);
  64. if ($enctype !== false) $this->params['enctype'] = $enctype;
  65. } else {
  66. $this->params = $params;
  67. }
  68. if (!isset($this->params['method'])) {
  69. $this->params['method'] = 'post';
  70. } else {
  71. $this->params['method'] = strtolower($this->params['method']);
  72. }
  73. if (!isset($this->params['action'])) {
  74. $this->params['action'] = '';
  75. }
  76. $this->addHidden('sectok', getSecurityToken());
  77. }
  78. /**
  79. * startFieldset
  80. *
  81. * Add <fieldset></fieldset> tags around fields.
  82. * Usually results in a border drawn around the form.
  83. *
  84. * @param string $legend Label that will be printed with the border.
  85. *
  86. * @author Tom N Harris <tnharris@whoopdedo.org>
  87. */
  88. public function startFieldset($legend)
  89. {
  90. if ($this->_infieldset) {
  91. $this->addElement(array('_elem'=>'closefieldset'));
  92. }
  93. $this->addElement(array('_elem'=>'openfieldset', '_legend'=>$legend));
  94. $this->_infieldset = true;
  95. }
  96. /**
  97. * endFieldset
  98. *
  99. * @author Tom N Harris <tnharris@whoopdedo.org>
  100. */
  101. public function endFieldset()
  102. {
  103. if ($this->_infieldset) {
  104. $this->addElement(array('_elem'=>'closefieldset'));
  105. }
  106. $this->_infieldset = false;
  107. }
  108. /**
  109. * addHidden
  110. *
  111. * Adds a name/value pair as a hidden field.
  112. * The value of the field (but not the name) will be passed to
  113. * formText() before printing.
  114. *
  115. * @param string $name Field name.
  116. * @param string $value Field value. If null, remove a previously added field.
  117. *
  118. * @author Tom N Harris <tnharris@whoopdedo.org>
  119. */
  120. public function addHidden($name, $value)
  121. {
  122. if (is_null($value))
  123. unset($this->_hidden[$name]);
  124. else
  125. $this->_hidden[$name] = $value;
  126. }
  127. /**
  128. * addElement
  129. *
  130. * Appends a content element to the form.
  131. * The element can be either a pseudo-tag or string.
  132. * If string, it is printed without escaping special chars. *
  133. *
  134. * @param string|array $elem Pseudo-tag or string to add to the form.
  135. *
  136. * @author Tom N Harris <tnharris@whoopdedo.org>
  137. */
  138. public function addElement($elem)
  139. {
  140. $this->_content[] = $elem;
  141. }
  142. /**
  143. * insertElement
  144. *
  145. * Inserts a content element at a position.
  146. *
  147. * @param string $pos 0-based index where the element will be inserted.
  148. * @param string|array $elem Pseudo-tag or string to add to the form.
  149. *
  150. * @author Tom N Harris <tnharris@whoopdedo.org>
  151. */
  152. public function insertElement($pos, $elem)
  153. {
  154. array_splice($this->_content, $pos, 0, array($elem));
  155. }
  156. /**
  157. * replaceElement
  158. *
  159. * Replace with NULL to remove an element.
  160. *
  161. * @param int $pos 0-based index the element will be placed at.
  162. * @param string|array $elem Pseudo-tag or string to add to the form.
  163. *
  164. * @author Tom N Harris <tnharris@whoopdedo.org>
  165. */
  166. public function replaceElement($pos, $elem)
  167. {
  168. $rep = array();
  169. if (!is_null($elem)) $rep[] = $elem;
  170. array_splice($this->_content, $pos, 1, $rep);
  171. }
  172. /**
  173. * findElementByType
  174. *
  175. * Gets the position of the first of a type of element.
  176. *
  177. * @param string $type Element type to look for.
  178. * @return int|false position of element if found, otherwise false
  179. *
  180. * @author Tom N Harris <tnharris@whoopdedo.org>
  181. */
  182. public function findElementByType($type)
  183. {
  184. foreach ($this->_content as $pos => $elem) {
  185. if (is_array($elem) && $elem['_elem'] == $type)
  186. return $pos;
  187. }
  188. return false;
  189. }
  190. /**
  191. * findElementById
  192. *
  193. * Gets the position of the element with an ID attribute.
  194. *
  195. * @param string $id ID of the element to find.
  196. * @return int|false position of element if found, otherwise false
  197. *
  198. * @author Tom N Harris <tnharris@whoopdedo.org>
  199. */
  200. public function findElementById($id)
  201. {
  202. foreach ($this->_content as $pos => $elem) {
  203. if (is_array($elem) && isset($elem['id']) && $elem['id'] == $id)
  204. return $pos;
  205. }
  206. return false;
  207. }
  208. /**
  209. * findElementByAttribute
  210. *
  211. * Gets the position of the first element with a matching attribute value.
  212. *
  213. * @param string $name Attribute name.
  214. * @param string $value Attribute value.
  215. * @return int|false position of element if found, otherwise false
  216. *
  217. * @author Tom N Harris <tnharris@whoopdedo.org>
  218. */
  219. public function findElementByAttribute($name, $value)
  220. {
  221. foreach ($this->_content as $pos => $elem) {
  222. if (is_array($elem) && isset($elem[$name]) && $elem[$name] == $value)
  223. return $pos;
  224. }
  225. return false;
  226. }
  227. /**
  228. * getElementAt
  229. *
  230. * Returns a reference to the element at a position.
  231. * A position out-of-bounds will return either the
  232. * first (underflow) or last (overflow) element.
  233. *
  234. * @param int $pos 0-based index
  235. * @return array reference pseudo-element
  236. *
  237. * @author Tom N Harris <tnharris@whoopdedo.org>
  238. */
  239. public function &getElementAt($pos)
  240. {
  241. if ($pos < 0) $pos = count($this->_content) + $pos;
  242. if ($pos < 0) $pos = 0;
  243. if ($pos >= count($this->_content)) $pos = count($this->_content) - 1;
  244. return $this->_content[$pos];
  245. }
  246. /**
  247. * Return the assembled HTML for the form.
  248. *
  249. * Each element in the form will be passed to a function named
  250. * 'form_$type'. The function should return the HTML to be printed.
  251. *
  252. * @author Tom N Harris <tnharris@whoopdedo.org>
  253. *
  254. * @return string html of the form
  255. */
  256. public function getForm()
  257. {
  258. global $lang;
  259. $form = '';
  260. $this->params['accept-charset'] = $lang['encoding'];
  261. $form .= '<form '. buildAttributes($this->params,false) .'><div class="no">'. DOKU_LF;
  262. if (!empty($this->_hidden)) {
  263. foreach ($this->_hidden as $name => $value)
  264. $form .= form_hidden(array('name'=>$name, 'value'=>$value));
  265. }
  266. foreach ($this->_content as $element) {
  267. if (is_array($element)) {
  268. $elem_type = $element['_elem'];
  269. if (function_exists('form_'.$elem_type)) {
  270. $form .= call_user_func('form_'.$elem_type, $element).DOKU_LF;
  271. }
  272. } else {
  273. $form .= $element;
  274. }
  275. }
  276. if ($this->_infieldset) $form .= form_closefieldset().DOKU_LF;
  277. $form .= '</div></form>'.DOKU_LF;
  278. return $form;
  279. }
  280. /**
  281. * Print the assembled form
  282. *
  283. * wraps around getForm()
  284. */
  285. public function printForm()
  286. {
  287. echo $this->getForm();
  288. }
  289. /**
  290. * Add a radio set
  291. *
  292. * This function adds a set of radio buttons to the form. If $_POST[$name]
  293. * is set, this radio is preselected, else the first radio button.
  294. *
  295. * @param string $name The HTML field name
  296. * @param array $entries An array of entries $value => $caption
  297. *
  298. * @author Adrian Lang <lang@cosmocode.de>
  299. */
  300. public function addRadioSet($name, $entries)
  301. {
  302. global $INPUT;
  303. $value = (array_key_exists($INPUT->post->str($name), $entries)) ?
  304. $INPUT->str($name) : key($entries);
  305. foreach($entries as $val => $cap) {
  306. $data = ($value === $val) ? array('checked' => 'checked') : array();
  307. $this->addElement(form_makeRadioField($name, $val, $cap, '', '', $data));
  308. }
  309. }
  310. }
  311. /**
  312. * form_makeTag
  313. *
  314. * Create a form element for a non-specific empty tag.
  315. *
  316. * @param string $tag Tag name.
  317. * @param array $attrs Optional attributes.
  318. * @return array pseudo-tag
  319. *
  320. * @author Tom N Harris <tnharris@whoopdedo.org>
  321. */
  322. function form_makeTag($tag, $attrs=array()) {
  323. $elem = array('_elem'=>'tag', '_tag'=>$tag);
  324. return array_merge($elem, $attrs);
  325. }
  326. /**
  327. * form_makeOpenTag
  328. *
  329. * Create a form element for a non-specific opening tag.
  330. * Remember to put a matching close tag after this as well.
  331. *
  332. * @param string $tag Tag name.
  333. * @param array $attrs Optional attributes.
  334. * @return array pseudo-tag
  335. *
  336. * @author Tom N Harris <tnharris@whoopdedo.org>
  337. */
  338. function form_makeOpenTag($tag, $attrs=array()) {
  339. $elem = array('_elem'=>'opentag', '_tag'=>$tag);
  340. return array_merge($elem, $attrs);
  341. }
  342. /**
  343. * form_makeCloseTag
  344. *
  345. * Create a form element for a non-specific closing tag.
  346. * Careless use of this will result in invalid XHTML.
  347. *
  348. * @param string $tag Tag name.
  349. * @return array pseudo-tag
  350. *
  351. * @author Tom N Harris <tnharris@whoopdedo.org>
  352. */
  353. function form_makeCloseTag($tag) {
  354. return array('_elem'=>'closetag', '_tag'=>$tag);
  355. }
  356. /**
  357. * form_makeWikiText
  358. *
  359. * Create a form element for a textarea containing wiki text.
  360. * Only one wikitext element is allowed on a page. It will have
  361. * a name of 'wikitext' and id 'wiki__text'. The text will
  362. * be passed to formText() before printing.
  363. *
  364. * @param string $text Text to fill the field with.
  365. * @param array $attrs Optional attributes.
  366. * @return array pseudo-tag
  367. *
  368. * @author Tom N Harris <tnharris@whoopdedo.org>
  369. */
  370. function form_makeWikiText($text, $attrs=array()) {
  371. $elem = array('_elem'=>'wikitext', '_text'=>$text,
  372. 'class'=>'edit', 'cols'=>'80', 'rows'=>'10');
  373. return array_merge($elem, $attrs);
  374. }
  375. /**
  376. * form_makeButton
  377. *
  378. * Create a form element for an action button.
  379. * A title will automatically be generated using the value and
  380. * accesskey attributes, unless you provide one.
  381. *
  382. * @param string $type Type attribute. 'submit' or 'cancel'
  383. * @param string $act Wiki action of the button, will be used as the do= parameter
  384. * @param string $value (optional) Displayed label. Uses $act if not provided.
  385. * @param array $attrs Optional attributes.
  386. * @return array pseudo-tag
  387. *
  388. * @author Tom N Harris <tnharris@whoopdedo.org>
  389. */
  390. function form_makeButton($type, $act, $value='', $attrs=array()) {
  391. if ($value == '') $value = $act;
  392. $elem = array('_elem'=>'button', 'type'=>$type, '_action'=>$act,
  393. 'value'=>$value);
  394. if (!empty($attrs['accesskey']) && empty($attrs['title'])) {
  395. $attrs['title'] = $value .' ['. strtoupper($attrs['accesskey']) .']';
  396. }
  397. return array_merge($elem, $attrs);
  398. }
  399. /**
  400. * form_makeField
  401. *
  402. * Create a form element for a labelled input element.
  403. * The label text will be printed before the input.
  404. *
  405. * @param string $type Type attribute of input.
  406. * @param string $name Name attribute of the input.
  407. * @param string $value (optional) Default value.
  408. * @param string $class Class attribute of the label. If this is 'block',
  409. * then a line break will be added after the field.
  410. * @param string $label Label that will be printed before the input.
  411. * @param string $id ID attribute of the input. If set, the label will
  412. * reference it with a 'for' attribute.
  413. * @param array $attrs Optional attributes.
  414. * @return array pseudo-tag
  415. *
  416. * @author Tom N Harris <tnharris@whoopdedo.org>
  417. */
  418. function form_makeField($type, $name, $value='', $label=null, $id='', $class='', $attrs=array()) {
  419. if (is_null($label)) $label = $name;
  420. $elem = array('_elem'=>'field', '_text'=>$label, '_class'=>$class,
  421. 'type'=>$type, 'id'=>$id, 'name'=>$name, 'value'=>$value);
  422. return array_merge($elem, $attrs);
  423. }
  424. /**
  425. * form_makeFieldRight
  426. *
  427. * Create a form element for a labelled input element.
  428. * The label text will be printed after the input.
  429. *
  430. * @see form_makeField
  431. * @author Tom N Harris <tnharris@whoopdedo.org>
  432. *
  433. * @param string $type
  434. * @param string $name
  435. * @param string $value
  436. * @param null|string $label
  437. * @param string $id
  438. * @param string $class
  439. * @param array $attrs
  440. *
  441. * @return array
  442. */
  443. function form_makeFieldRight($type, $name, $value='', $label=null, $id='', $class='', $attrs=array()) {
  444. if (is_null($label)) $label = $name;
  445. $elem = array('_elem'=>'fieldright', '_text'=>$label, '_class'=>$class,
  446. 'type'=>$type, 'id'=>$id, 'name'=>$name, 'value'=>$value);
  447. return array_merge($elem, $attrs);
  448. }
  449. /**
  450. * form_makeTextField
  451. *
  452. * Create a form element for a text input element with label.
  453. *
  454. * @see form_makeField
  455. * @author Tom N Harris <tnharris@whoopdedo.org>
  456. *
  457. * @param string $name
  458. * @param string $value
  459. * @param null|string $label
  460. * @param string $id
  461. * @param string $class
  462. * @param array $attrs
  463. *
  464. * @return array
  465. */
  466. function form_makeTextField($name, $value='', $label=null, $id='', $class='', $attrs=array()) {
  467. if (is_null($label)) $label = $name;
  468. $elem = array('_elem'=>'textfield', '_text'=>$label, '_class'=>$class,
  469. 'id'=>$id, 'name'=>$name, 'value'=>$value, 'class'=>'edit');
  470. return array_merge($elem, $attrs);
  471. }
  472. /**
  473. * form_makePasswordField
  474. *
  475. * Create a form element for a password input element with label.
  476. * Password elements have no default value, for obvious reasons.
  477. *
  478. * @see form_makeField
  479. * @author Tom N Harris <tnharris@whoopdedo.org>
  480. *
  481. * @param string $name
  482. * @param null|string $label
  483. * @param string $id
  484. * @param string $class
  485. * @param array $attrs
  486. *
  487. * @return array
  488. */
  489. function form_makePasswordField($name, $label=null, $id='', $class='', $attrs=array()) {
  490. if (is_null($label)) $label = $name;
  491. $elem = array('_elem'=>'passwordfield', '_text'=>$label, '_class'=>$class,
  492. 'id'=>$id, 'name'=>$name, 'class'=>'edit');
  493. return array_merge($elem, $attrs);
  494. }
  495. /**
  496. * form_makeFileField
  497. *
  498. * Create a form element for a file input element with label
  499. *
  500. * @see form_makeField
  501. * @author Michael Klier <chi@chimeric.de>
  502. *
  503. * @param string $name
  504. * @param null|string $label
  505. * @param string $id
  506. * @param string $class
  507. * @param array $attrs
  508. *
  509. * @return array
  510. */
  511. function form_makeFileField($name, $label=null, $id='', $class='', $attrs=array()) {
  512. if (is_null($label)) $label = $name;
  513. $elem = array('_elem'=>'filefield', '_text'=>$label, '_class'=>$class,
  514. 'id'=>$id, 'name'=>$name, 'class'=>'edit');
  515. return array_merge($elem, $attrs);
  516. }
  517. /**
  518. * form_makeCheckboxField
  519. *
  520. * Create a form element for a checkbox input element with label.
  521. * If $value is an array, a hidden field with the same name and the value
  522. * $value[1] is constructed as well.
  523. *
  524. * @see form_makeFieldRight
  525. * @author Tom N Harris <tnharris@whoopdedo.org>
  526. *
  527. * @param string $name
  528. * @param string $value
  529. * @param null|string $label
  530. * @param string $id
  531. * @param string $class
  532. * @param array $attrs
  533. *
  534. * @return array
  535. */
  536. function form_makeCheckboxField($name, $value='1', $label=null, $id='', $class='', $attrs=array()) {
  537. if (is_null($label)) $label = $name;
  538. if (is_null($value) || $value=='') $value='0';
  539. $elem = array('_elem'=>'checkboxfield', '_text'=>$label, '_class'=>$class,
  540. 'id'=>$id, 'name'=>$name, 'value'=>$value);
  541. return array_merge($elem, $attrs);
  542. }
  543. /**
  544. * form_makeRadioField
  545. *
  546. * Create a form element for a radio button input element with label.
  547. *
  548. * @see form_makeFieldRight
  549. * @author Tom N Harris <tnharris@whoopdedo.org>
  550. *
  551. * @param string $name
  552. * @param string $value
  553. * @param null|string $label
  554. * @param string $id
  555. * @param string $class
  556. * @param array $attrs
  557. *
  558. * @return array
  559. */
  560. function form_makeRadioField($name, $value='1', $label=null, $id='', $class='', $attrs=array()) {
  561. if (is_null($label)) $label = $name;
  562. if (is_null($value) || $value=='') $value='0';
  563. $elem = array('_elem'=>'radiofield', '_text'=>$label, '_class'=>$class,
  564. 'id'=>$id, 'name'=>$name, 'value'=>$value);
  565. return array_merge($elem, $attrs);
  566. }
  567. /**
  568. * form_makeMenuField
  569. *
  570. * Create a form element for a drop-down menu with label.
  571. * The list of values can be strings, arrays of (value,text),
  572. * or an associative array with the values as keys and labels as values.
  573. * An item is selected by supplying its value or integer index.
  574. * If the list of values is an associative array, the selected item must be
  575. * a string.
  576. *
  577. * @author Tom N Harris <tnharris@whoopdedo.org>
  578. *
  579. * @param string $name Name attribute of the input.
  580. * @param string[]|array[] $values The list of values can be strings, arrays of (value,text),
  581. * or an associative array with the values as keys and labels as values.
  582. * @param string|int $selected default selected value, string or index number
  583. * @param string $class Class attribute of the label. If this is 'block',
  584. * then a line break will be added after the field.
  585. * @param string $label Label that will be printed before the input.
  586. * @param string $id ID attribute of the input. If set, the label will
  587. * reference it with a 'for' attribute.
  588. * @param array $attrs Optional attributes.
  589. * @return array pseudo-tag
  590. */
  591. function form_makeMenuField($name, $values, $selected='', $label=null, $id='', $class='', $attrs=array()) {
  592. if (is_null($label)) $label = $name;
  593. $options = array();
  594. reset($values);
  595. // FIXME: php doesn't know the difference between a string and an integer
  596. if (is_string(key($values))) {
  597. foreach ($values as $val => $text) {
  598. $options[] = array($val, $text, (!is_null($selected) && $val==$selected));
  599. }
  600. } else {
  601. if (is_integer($selected)) $selected = $values[$selected];
  602. foreach ($values as $val) {
  603. if (is_array($val))
  604. @list($val, $text) = $val;
  605. else
  606. $text = null;
  607. $options[] = array($val, $text, $val===$selected);
  608. }
  609. }
  610. $elem = array('_elem'=>'menufield', '_options'=>$options, '_text'=>$label, '_class'=>$class,
  611. 'id'=>$id, 'name'=>$name);
  612. return array_merge($elem, $attrs);
  613. }
  614. /**
  615. * form_makeListboxField
  616. *
  617. * Create a form element for a list box with label.
  618. * The list of values can be strings, arrays of (value,text),
  619. * or an associative array with the values as keys and labels as values.
  620. * Items are selected by supplying its value or an array of values.
  621. *
  622. * @author Tom N Harris <tnharris@whoopdedo.org>
  623. *
  624. * @param string $name Name attribute of the input.
  625. * @param string[]|array[] $values The list of values can be strings, arrays of (value,text),
  626. * or an associative array with the values as keys and labels as values.
  627. * @param array|string $selected value or array of values of the items that need to be selected
  628. * @param string $class Class attribute of the label. If this is 'block',
  629. * then a line break will be added after the field.
  630. * @param string $label Label that will be printed before the input.
  631. * @param string $id ID attribute of the input. If set, the label will
  632. * reference it with a 'for' attribute.
  633. * @param array $attrs Optional attributes.
  634. * @return array pseudo-tag
  635. */
  636. function form_makeListboxField($name, $values, $selected='', $label=null, $id='', $class='', $attrs=array()) {
  637. if (is_null($label)) $label = $name;
  638. $options = array();
  639. reset($values);
  640. if (is_null($selected) || $selected == '') {
  641. $selected = array();
  642. } elseif (!is_array($selected)) {
  643. $selected = array($selected);
  644. }
  645. // FIXME: php doesn't know the difference between a string and an integer
  646. if (is_string(key($values))) {
  647. foreach ($values as $val => $text) {
  648. $options[] = array($val, $text, in_array($val,$selected));
  649. }
  650. } else {
  651. foreach ($values as $val) {
  652. $disabled = false;
  653. if (is_array($val)) {
  654. @list($val, $text, $disabled) = $val;
  655. } else {
  656. $text = null;
  657. }
  658. $options[] = array($val, $text, in_array($val, $selected), $disabled);
  659. }
  660. }
  661. $elem = array('_elem'=>'listboxfield', '_options'=>$options, '_text'=>$label, '_class'=>$class,
  662. 'id'=>$id, 'name'=>$name);
  663. return array_merge($elem, $attrs);
  664. }
  665. /**
  666. * form_tag
  667. *
  668. * Print the HTML for a generic empty tag.
  669. * Requires '_tag' key with name of the tag.
  670. * Attributes are passed to buildAttributes()
  671. *
  672. * @author Tom N Harris <tnharris@whoopdedo.org>
  673. *
  674. * @param array $attrs attributes
  675. * @return string html of tag
  676. */
  677. function form_tag($attrs) {
  678. return '<'.$attrs['_tag'].' '. buildAttributes($attrs,true) .'/>';
  679. }
  680. /**
  681. * form_opentag
  682. *
  683. * Print the HTML for a generic opening tag.
  684. * Requires '_tag' key with name of the tag.
  685. * Attributes are passed to buildAttributes()
  686. *
  687. * @author Tom N Harris <tnharris@whoopdedo.org>
  688. *
  689. * @param array $attrs attributes
  690. * @return string html of tag
  691. */
  692. function form_opentag($attrs) {
  693. return '<'.$attrs['_tag'].' '. buildAttributes($attrs,true) .'>';
  694. }
  695. /**
  696. * form_closetag
  697. *
  698. * Print the HTML for a generic closing tag.
  699. * Requires '_tag' key with name of the tag.
  700. * There are no attributes.
  701. *
  702. * @author Tom N Harris <tnharris@whoopdedo.org>
  703. *
  704. * @param array $attrs attributes
  705. * @return string html of tag
  706. */
  707. function form_closetag($attrs) {
  708. return '</'.$attrs['_tag'].'>';
  709. }
  710. /**
  711. * form_openfieldset
  712. *
  713. * Print the HTML for an opening fieldset tag.
  714. * Uses the '_legend' key.
  715. * Attributes are passed to buildAttributes()
  716. *
  717. * @author Tom N Harris <tnharris@whoopdedo.org>
  718. *
  719. * @param array $attrs attributes
  720. * @return string html
  721. */
  722. function form_openfieldset($attrs) {
  723. $s = '<fieldset '. buildAttributes($attrs,true) .'>';
  724. if (!is_null($attrs['_legend'])) $s .= '<legend>'.$attrs['_legend'].'</legend>';
  725. return $s;
  726. }
  727. /**
  728. * form_closefieldset
  729. *
  730. * Print the HTML for a closing fieldset tag.
  731. * There are no attributes.
  732. *
  733. * @author Tom N Harris <tnharris@whoopdedo.org>
  734. *
  735. * @return string html
  736. */
  737. function form_closefieldset() {
  738. return '</fieldset>';
  739. }
  740. /**
  741. * form_hidden
  742. *
  743. * Print the HTML for a hidden input element.
  744. * Uses only 'name' and 'value' attributes.
  745. * Value is passed to formText()
  746. *
  747. * @author Tom N Harris <tnharris@whoopdedo.org>
  748. *
  749. * @param array $attrs attributes
  750. * @return string html
  751. */
  752. function form_hidden($attrs) {
  753. return '<input type="hidden" name="'.$attrs['name'].'" value="'. formText($attrs['value']) .'" />';
  754. }
  755. /**
  756. * form_wikitext
  757. *
  758. * Print the HTML for the wiki textarea.
  759. * Requires '_text' with default text of the field.
  760. * Text will be passed to formText(), attributes to buildAttributes()
  761. *
  762. * @author Tom N Harris <tnharris@whoopdedo.org>
  763. *
  764. * @param array $attrs attributes
  765. * @return string html
  766. */
  767. function form_wikitext($attrs) {
  768. // mandatory attributes
  769. unset($attrs['name']);
  770. unset($attrs['id']);
  771. return '<textarea name="wikitext" id="wiki__text" dir="auto" '
  772. . buildAttributes($attrs,true).'>'.DOKU_LF
  773. . formText($attrs['_text'])
  774. .'</textarea>';
  775. }
  776. /**
  777. * form_button
  778. *
  779. * Print the HTML for a form button.
  780. * If '_action' is set, the button name will be "do[_action]".
  781. * Other attributes are passed to buildAttributes()
  782. *
  783. * @author Tom N Harris <tnharris@whoopdedo.org>
  784. *
  785. * @param array $attrs attributes
  786. * @return string html
  787. */
  788. function form_button($attrs) {
  789. $p = (!empty($attrs['_action'])) ? 'name="do['.$attrs['_action'].']" ' : '';
  790. $value = $attrs['value'];
  791. unset($attrs['value']);
  792. return '<button '.$p. buildAttributes($attrs,true) .'>'.$value.'</button>';
  793. }
  794. /**
  795. * form_field
  796. *
  797. * Print the HTML for a form input field.
  798. * _class : class attribute used on the label tag
  799. * _text : Text to display before the input. Not escaped.
  800. * Other attributes are passed to buildAttributes() for the input tag.
  801. *
  802. * @author Tom N Harris <tnharris@whoopdedo.org>
  803. *
  804. * @param array $attrs attributes
  805. * @return string html
  806. */
  807. function form_field($attrs) {
  808. $s = '<label';
  809. if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
  810. if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
  811. $s .= '><span>'.$attrs['_text'].'</span>';
  812. $s .= ' <input '. buildAttributes($attrs,true) .' /></label>';
  813. if (preg_match('/(^| )block($| )/', $attrs['_class']))
  814. $s .= '<br />';
  815. return $s;
  816. }
  817. /**
  818. * form_fieldright
  819. *
  820. * Print the HTML for a form input field. (right-aligned)
  821. * _class : class attribute used on the label tag
  822. * _text : Text to display after the input. Not escaped.
  823. * Other attributes are passed to buildAttributes() for the input tag.
  824. *
  825. * @author Tom N Harris <tnharris@whoopdedo.org>
  826. *
  827. * @param array $attrs attributes
  828. * @return string html
  829. */
  830. function form_fieldright($attrs) {
  831. $s = '<label';
  832. if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
  833. if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
  834. $s .= '><input '. buildAttributes($attrs,true) .' />';
  835. $s .= ' <span>'.$attrs['_text'].'</span></label>';
  836. if (preg_match('/(^| )block($| )/', $attrs['_class']))
  837. $s .= '<br />';
  838. return $s;
  839. }
  840. /**
  841. * form_textfield
  842. *
  843. * Print the HTML for a text input field.
  844. * _class : class attribute used on the label tag
  845. * _text : Text to display before the input. Not escaped.
  846. * Other attributes are passed to buildAttributes() for the input tag.
  847. *
  848. * @author Tom N Harris <tnharris@whoopdedo.org>
  849. *
  850. * @param array $attrs attributes
  851. * @return string html
  852. */
  853. function form_textfield($attrs) {
  854. // mandatory attributes
  855. unset($attrs['type']);
  856. $s = '<label';
  857. if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
  858. if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
  859. $s .= '><span>'.$attrs['_text'].'</span> ';
  860. $s .= '<input type="text" '. buildAttributes($attrs,true) .' /></label>';
  861. if (preg_match('/(^| )block($| )/', $attrs['_class']))
  862. $s .= '<br />';
  863. return $s;
  864. }
  865. /**
  866. * form_passwordfield
  867. *
  868. * Print the HTML for a password input field.
  869. * _class : class attribute used on the label tag
  870. * _text : Text to display before the input. Not escaped.
  871. * Other attributes are passed to buildAttributes() for the input tag.
  872. *
  873. * @author Tom N Harris <tnharris@whoopdedo.org>
  874. *
  875. * @param array $attrs attributes
  876. * @return string html
  877. */
  878. function form_passwordfield($attrs) {
  879. // mandatory attributes
  880. unset($attrs['type']);
  881. $s = '<label';
  882. if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
  883. if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
  884. $s .= '><span>'.$attrs['_text'].'</span> ';
  885. $s .= '<input type="password" '. buildAttributes($attrs,true) .' /></label>';
  886. if (preg_match('/(^| )block($| )/', $attrs['_class']))
  887. $s .= '<br />';
  888. return $s;
  889. }
  890. /**
  891. * form_filefield
  892. *
  893. * Print the HTML for a file input field.
  894. * _class : class attribute used on the label tag
  895. * _text : Text to display before the input. Not escaped
  896. * _maxlength : Allowed size in byte
  897. * _accept : Accepted mime-type
  898. * Other attributes are passed to buildAttributes() for the input tag
  899. *
  900. * @author Michael Klier <chi@chimeric.de>
  901. *
  902. * @param array $attrs attributes
  903. * @return string html
  904. */
  905. function form_filefield($attrs) {
  906. $s = '<label';
  907. if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
  908. if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
  909. $s .= '><span>'.$attrs['_text'].'</span> ';
  910. $s .= '<input type="file" '. buildAttributes($attrs,true);
  911. if (!empty($attrs['_maxlength'])) $s .= ' maxlength="'.$attrs['_maxlength'].'"';
  912. if (!empty($attrs['_accept'])) $s .= ' accept="'.$attrs['_accept'].'"';
  913. $s .= ' /></label>';
  914. if (preg_match('/(^| )block($| )/', $attrs['_class']))
  915. $s .= '<br />';
  916. return $s;
  917. }
  918. /**
  919. * form_checkboxfield
  920. *
  921. * Print the HTML for a checkbox input field.
  922. * _class : class attribute used on the label tag
  923. * _text : Text to display after the input. Not escaped.
  924. * Other attributes are passed to buildAttributes() for the input tag.
  925. * If value is an array, a hidden field with the same name and the value
  926. * $attrs['value'][1] is constructed as well.
  927. *
  928. * @author Tom N Harris <tnharris@whoopdedo.org>
  929. *
  930. * @param array $attrs attributes
  931. * @return string html
  932. */
  933. function form_checkboxfield($attrs) {
  934. // mandatory attributes
  935. unset($attrs['type']);
  936. $s = '<label';
  937. if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
  938. if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
  939. $s .= '>';
  940. if (is_array($attrs['value'])) {
  941. echo '<input type="hidden" name="'. hsc($attrs['name']) .'"'
  942. .' value="'. hsc($attrs['value'][1]) .'" />';
  943. $attrs['value'] = $attrs['value'][0];
  944. }
  945. $s .= '<input type="checkbox" '. buildAttributes($attrs,true) .' />';
  946. $s .= ' <span>'.$attrs['_text'].'</span></label>';
  947. if (preg_match('/(^| )block($| )/', $attrs['_class']))
  948. $s .= '<br />';
  949. return $s;
  950. }
  951. /**
  952. * form_radiofield
  953. *
  954. * Print the HTML for a radio button input field.
  955. * _class : class attribute used on the label tag
  956. * _text : Text to display after the input. Not escaped.
  957. * Other attributes are passed to buildAttributes() for the input tag.
  958. *
  959. * @author Tom N Harris <tnharris@whoopdedo.org>
  960. *
  961. * @param array $attrs attributes
  962. * @return string html
  963. */
  964. function form_radiofield($attrs) {
  965. // mandatory attributes
  966. unset($attrs['type']);
  967. $s = '<label';
  968. if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
  969. if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
  970. $s .= '><input type="radio" '. buildAttributes($attrs,true) .' />';
  971. $s .= ' <span>'.$attrs['_text'].'</span></label>';
  972. if (preg_match('/(^| )block($| )/', $attrs['_class']))
  973. $s .= '<br />';
  974. return $s;
  975. }
  976. /**
  977. * form_menufield
  978. *
  979. * Print the HTML for a drop-down menu.
  980. * _options : Array of (value,text,selected) for the menu.
  981. * Text can be omitted. Text and value are passed to formText()
  982. * Only one item can be selected.
  983. * _class : class attribute used on the label tag
  984. * _text : Text to display before the menu. Not escaped.
  985. * Other attributes are passed to buildAttributes() for the input tag.
  986. *
  987. * @author Tom N Harris <tnharris@whoopdedo.org>
  988. *
  989. * @param array $attrs attributes
  990. * @return string html
  991. */
  992. function form_menufield($attrs) {
  993. $attrs['size'] = '1';
  994. $s = '<label';
  995. if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
  996. if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
  997. $s .= '><span>'.$attrs['_text'].'</span>';
  998. $s .= ' <select '. buildAttributes($attrs,true) .'>'.DOKU_LF;
  999. if (!empty($attrs['_options'])) {
  1000. $selected = false;
  1001. $cnt = count($attrs['_options']);
  1002. for($n=0; $n < $cnt; $n++){
  1003. @list($value,$text,$select) = $attrs['_options'][$n];
  1004. $p = '';
  1005. if (!is_null($text))
  1006. $p .= ' value="'. formText($value) .'"';
  1007. else
  1008. $text = $value;
  1009. if (!empty($select) && !$selected) {
  1010. $p .= ' selected="selected"';
  1011. $selected = true;
  1012. }
  1013. $s .= '<option'.$p.'>'. formText($text) .'</option>';
  1014. }
  1015. } else {
  1016. $s .= '<option></option>';
  1017. }
  1018. $s .= DOKU_LF.'</select></label>';
  1019. if (preg_match('/(^| )block($| )/', $attrs['_class']))
  1020. $s .= '<br />';
  1021. return $s;
  1022. }
  1023. /**
  1024. * form_listboxfield
  1025. *
  1026. * Print the HTML for a list box.
  1027. * _options : Array of (value,text,selected) for the list.
  1028. * Text can be omitted. Text and value are passed to formText()
  1029. * _class : class attribute used on the label tag
  1030. * _text : Text to display before the menu. Not escaped.
  1031. * Other attributes are passed to buildAttributes() for the input tag.
  1032. *
  1033. * @author Tom N Harris <tnharris@whoopdedo.org>
  1034. *
  1035. * @param array $attrs attributes
  1036. * @return string html
  1037. */
  1038. function form_listboxfield($attrs) {
  1039. $s = '<label';
  1040. if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
  1041. if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
  1042. $s .= '><span>'.$attrs['_text'].'</span> ';
  1043. $s .= '<select '. buildAttributes($attrs,true) .'>'.DOKU_LF;
  1044. if (!empty($attrs['_options'])) {
  1045. foreach ($attrs['_options'] as $opt) {
  1046. @list($value, $text, $select, $disabled) = $opt;
  1047. $p = '';
  1048. if (is_null($text)) $text = $value;
  1049. $p .= ' value="'. formText($value) .'"';
  1050. if (!empty($select)) $p .= ' selected="selected"';
  1051. if ($disabled) $p .= ' disabled="disabled"';
  1052. $s .= '<option'.$p.'>'. formText($text) .'</option>';
  1053. }
  1054. } else {
  1055. $s .= '<option></option>';
  1056. }
  1057. $s .= DOKU_LF.'</select></label>';
  1058. if (preg_match('/(^| )block($| )/', $attrs['_class']))
  1059. $s .= '<br />';
  1060. return $s;
  1061. }