PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/FormCreator.php

https://bitbucket.org/afrosoft/form-manager
PHP | 777 lines | 479 code | 65 blank | 233 comment | 74 complexity | 78d532f9231c928dfc90a86cf7e176a1 MD5 | raw file
  1. <?php
  2. /**
  3. * AfroSoft Form Manager
  4. *
  5. * @author AfroSoft
  6. * @version @build.version@ (Build @build.number@)
  7. * @license http://www.mozilla.org/MPL/MPL-1.1.txt MPL 1.1
  8. * @copyright Copyright (c) AfroSoft
  9. *
  10. /* * **** BEGIN LICENSE BLOCK *****
  11. * Version: MPL 1.1
  12. *
  13. * The contents of this file are subject to the Mozilla Public License Version
  14. * 1.1 (the "License"); you may not use this file except in compliance with
  15. * the License. You may obtain a copy of the License at
  16. * http://www.mozilla.org/MPL/
  17. *
  18. * Software distributed under the License is distributed on an "AS IS" basis,
  19. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  20. * for the specific language governing rights and limitations under the
  21. * License.
  22. *
  23. * The Original Code is the AfroSoft Form Manager.
  24. *
  25. * The Initial Developer of the Original Code is AfroSoft.
  26. * Portions created by the Initial Developer are Copyright (C) 2011 the Initial
  27. * Developer. All Rights Reserved.
  28. *
  29. * Contributors are provided in the CONTRIB file, located at the root of the package.
  30. * ***** END LICENSE BLOCK ***** */
  31. /**
  32. * Constants defining the different fields available.
  33. */
  34. class FormField {
  35. // regular input
  36. const TEXT = 0;
  37. const PASSWORD = 1;
  38. const FILE = 2;
  39. const RADIO = 3;
  40. const CHECKBOX = 4;
  41. const HIDDEN = 5;
  42. const EMAIL = 14;
  43. const TEL = 15;
  44. const URL = 16;
  45. const SEARCH = 20;
  46. const NUMBER = 19;
  47. const DATE = 17;
  48. const TIME = 18;
  49. const DATETIME = 21;
  50. const WEEK = 22;
  51. const MONTH = 23;
  52. const RANGE = 24;
  53. const COLOR = 25;
  54. // other
  55. const TEXTAREA = 7;
  56. const LABEL = 8;
  57. const SELECT = 13;
  58. // buttons
  59. const IMAGE = 6;
  60. const SUBMIT = 9;
  61. const RESET = 10;
  62. const BUTTON = 11;
  63. const BUTTON_TAG = 12;
  64. // special
  65. const RECAPTCHA = 26;
  66. }
  67. /**
  68. * Constants defining the different field templates available.
  69. */
  70. class FormTemplate {
  71. const FIELD = 1;
  72. const FIELD_LABEL = 5;
  73. const HIDDEN = 2;
  74. const BUTTON = 3;
  75. const RADIO = 4;
  76. }
  77. /**
  78. * The form creator class.
  79. */
  80. class FormCreator {
  81. private $fields = array();
  82. private $form = array();
  83. private $template = array(
  84. FormTemplate::FIELD => '<p class="input">%s</p>',
  85. FormTemplate::FIELD_LABEL => '<p class="input">%s: %s</p>',
  86. FormTemplate::HIDDEN => '%s',
  87. FormTemplate::BUTTON => '<p class="button">%s</p>',
  88. FormTemplate::RADIO => '<p class="input radio">%s %s</p>',
  89. );
  90. private $secret = null;
  91. public function __construct($secret) {
  92. $this->secret = $secret;
  93. }
  94. public function __toString() {
  95. return $this->process();
  96. }
  97. public function display() {
  98. echo $this->process();
  99. }
  100. public function process() {
  101. $timestamp = time();
  102. $spinner = $this->_calculate_spinner($timestamp);
  103. $form = $this->_form_start() . "\n";
  104. $form .= $this->_field_hidden(array('name' => 'spinner', 'value' => $spinner)) . "\n";
  105. $form .= $this->_field_hidden(array('name' => ($this->_hash_name('timestamp', $spinner)), 'value' => $timestamp)) . "\n";
  106. foreach ($this->fields as $index => $field) {
  107. if (!isset($field['name'])) {
  108. $field['name'] = $field['id'];
  109. }
  110. $field['name'] = ($this->_hash_name($field['name'], $spinner));
  111. switch ($field['field_type']) {
  112. case FormField::TEXT:
  113. $form .= $this->_field_text($field);
  114. break;
  115. case FormField::PASSWORD:
  116. $form .= $this->_field_password($field);
  117. break;
  118. case FormField::FILE:
  119. $form .= $this->_field_file($field);
  120. break;
  121. case FormField::RADIO:
  122. $form .= $this->_field_radio($field);
  123. break;
  124. case FormField::CHECKBOX:
  125. $form .= $this->_field_checkbox($field);
  126. break;
  127. case FormField::HIDDEN:
  128. $form .= $this->_field_hidden($field);
  129. break;
  130. case FormField::IMAGE:
  131. $form .= $this->_field_image($field);
  132. break;
  133. case FormField::TEXTAREA:
  134. $form .= $this->_field_textarea($field);
  135. break;
  136. case FormField::LABEL:
  137. $form .= $this->_field_label($field);
  138. break;
  139. case FormField::SELECT:
  140. //$form .= $this->_field_file($field);
  141. break;
  142. case FormField::SUBMIT:
  143. $form .= $this->_field_submit($field);
  144. break;
  145. case FormField::RESET:
  146. $form .= $this->_field_reset($field);
  147. break;
  148. case FormField::BUTTON:
  149. $form .= $this->_field_button($field);
  150. break;
  151. case FormField::BUTTON_TAG:
  152. $form .= $this->_field_button_tag($field);
  153. break;
  154. case FormField::EMAIL:
  155. $form .= $this->_field_email($field);
  156. break;
  157. case FormField::TEL:
  158. $form .= $this->_field_tel($field);
  159. break;
  160. case FormField::URL:
  161. $form .= $this->_field_url($field);
  162. break;
  163. case FormField::SEARCH:
  164. $form .= $this->_field_search($field);
  165. break;
  166. case FormField::NUMBER:
  167. $form .= $this->_field_number($field);
  168. break;
  169. case FormField::DATE:
  170. $form .= $this->_field_date($field);
  171. break;
  172. case FormField::DATETIME:
  173. $form .= $this->_field_datetime($field);
  174. break;
  175. case FormField::TIME:
  176. $form .= $this->_field_time($field);
  177. break;
  178. case FormField::WEEK:
  179. $form .= $this->_field_week($field);
  180. break;
  181. case FormField::MONTH:
  182. $form .= $this->_field_month($field);
  183. break;
  184. case FormField::RANGE:
  185. $form .= $this->_field_range($field);
  186. break;
  187. case FormField::COLOR:
  188. $form .= $this->_field_color($field);
  189. break;
  190. case FormField::RECAPTCHA:
  191. $form .= $this->_field_recaptacha($field);
  192. break;
  193. default:
  194. throw new Exception('Unknown field type: ' . $field['field_type']);
  195. }
  196. $form .= "\n";
  197. }
  198. $form .= $this->_form_end();
  199. return $form;
  200. }
  201. public function setTemplate($template, $string) {
  202. $this->template[$template] = $string;
  203. }
  204. public function form($options) {
  205. $default = array(
  206. 'id' => null,
  207. 'class' => null,
  208. 'style' => null,
  209. 'name' => null,
  210. 'action' => '#',
  211. 'method' => 'get',
  212. 'enctype' => null,
  213. );
  214. $this->form = array_merge($default, $options);
  215. return $this;
  216. }
  217. public function add($field, $id, $options = array()) {
  218. $default = array(
  219. 'value' => null,
  220. 'name' => null,
  221. );
  222. $this->fields[] = array_merge($default, $options, array('id' => $id, 'field_type' => $field));
  223. return $this;
  224. }
  225. public function remove($field, $id) {
  226. $delete = array();
  227. foreach($this->fields as $index => $data) {
  228. if ($data['id'] == $id && $data['field_type'] == $field) {
  229. $delete[] = $index;
  230. }
  231. }
  232. foreach($delete as $dIndex) {
  233. unset($this->fields[$dIndex]);
  234. }
  235. return $this;
  236. }
  237. private function _calculate_spinner($timestamp) {
  238. return hash('sha256', $timestamp . $this->secret);
  239. }
  240. private function _hash_name($name, $spinner) {
  241. require_once 'Encryption\TW_Encryption.php';
  242. $array = false;
  243. if (strstr($name, '[]')) {
  244. $array = true;
  245. }
  246. $crypt = new TW_Encryption();
  247. $encoded = $this->_encode_name($crypt->encrypt($spinner, $name . $this->secret));
  248. return $encoded;
  249. }
  250. private function _encode_name($name) {
  251. return strtr(base64_encode($name), array('+' => '-', '/' => '_', '=' => ''));
  252. }
  253. private function _form_start() {
  254. $html = '<form';
  255. $html .= (isset($this->form['id'])) ? $this->_add_attrib('id', $this->form['id']): '';
  256. $html .= (isset($this->form['class'])) ? $this->_add_attrib('class', $this->form['class']): '';
  257. $html .= (isset($this->form['style'])) ? $this->_add_attrib('style', $this->form['style']): '';
  258. $html .= (isset($this->form['name'])) ? $this->_add_attrib('name', $this->form['name']): '';
  259. $html .= (isset($this->form['enctype'])) ? $this->_add_attrib('enctype', $this->form['enctype']): '';
  260. $html .= $this->_add_attrib('action', $this->form['action']);
  261. $html .= $this->_add_attrib('method', $this->form['method']);
  262. $html .= '>';
  263. return $html;
  264. }
  265. private function _form_end() {
  266. return '</form>';
  267. }
  268. /**
  269. * Creates a text input field.
  270. *
  271. * @param array $data
  272. * @return string
  273. */
  274. private function _field_text($data) {
  275. if (isset($data['label'])) {
  276. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('text', $data));
  277. } else {
  278. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('text', $data));
  279. }
  280. }
  281. /**
  282. * Creates a password input field.
  283. *
  284. * @param array $data
  285. * @return string
  286. */
  287. private function _field_password($data) {
  288. if (isset($data['label'])) {
  289. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('password', $data));
  290. } else {
  291. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('password', $data));
  292. }
  293. }
  294. /**
  295. * Creates a file input field.
  296. *
  297. * @param array $data
  298. * @return string
  299. */
  300. private function _field_file($data) {
  301. if (isset($data['label'])) {
  302. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('file', $data));
  303. } else {
  304. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('file', $data));
  305. }
  306. }
  307. /**
  308. * Creates a radio button input field.
  309. *
  310. * @param array $data
  311. * @return string
  312. */
  313. private function _field_radio($data) {
  314. if (isset($data['label'])) {
  315. return sprintf($this->template[FormTemplate::RADIO], $this->_do_field_input('radio', $data), $this->_do_field_label($data));
  316. } else {
  317. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('radio', $data));
  318. }
  319. }
  320. /**
  321. * Creates a checkbox input field.
  322. *
  323. * @param array $data
  324. * @return string
  325. */
  326. private function _field_checkbox($data) {
  327. if (isset($data['label'])) {
  328. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('checkbox', $data));
  329. } else {
  330. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('checkbox', $data));
  331. }
  332. }
  333. /**
  334. * Creates a hidden input field.
  335. *
  336. * @param array $data
  337. * @return string
  338. */
  339. private function _field_hidden($data) {
  340. return sprintf($this->template[FormTemplate::HIDDEN], $this->_do_field_input('hidden', $data));
  341. }
  342. /**
  343. * Creates an image input field.
  344. *
  345. * @param array $data
  346. * @return string
  347. */
  348. private function _field_image($data) {
  349. if (isset($data['label'])) {
  350. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('image', $data));
  351. } else {
  352. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('image', $data));
  353. }
  354. }
  355. /**
  356. * Creates an textarea field.
  357. *
  358. * @param array $data
  359. * @return string
  360. */
  361. private function _field_textarea($data) {
  362. $input = '<textarea';
  363. foreach ($data as $key => $value) {
  364. if ($key == 'value') {
  365. continue;
  366. }
  367. if ($value === true) {
  368. $input .= $this->_add_param($key);
  369. continue;
  370. }
  371. if ($key == 'id') {
  372. $input .= $this->_add_attrib('id', 'field_' . $value);
  373. continue;
  374. }
  375. $input .= $this->_add_attrib($key, $value);
  376. }
  377. $input .= '>';
  378. $input .= (isset($data['value'])) ? $data['value']: '';
  379. $input .= '</textarea>';
  380. if (isset($data['label'])) {
  381. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $input);
  382. } else {
  383. return sprintf($this->template[FormTemplate::FIELD], $input);
  384. }
  385. }
  386. /**
  387. * Creates a label field.
  388. *
  389. * @param array $data
  390. * @return string
  391. */
  392. private function _field_label($data) {
  393. unset($data['field_type']);
  394. $input = '<label';
  395. foreach ($data as $key => $value) {
  396. if ($key == 'value' || $key == 'label') {
  397. continue;
  398. }
  399. if ($value === true) {
  400. $input .= $this->_add_param($key);
  401. continue;
  402. }
  403. if ($key == 'id') {
  404. $input .= $this->_add_attrib('id', 'field_' . $value);
  405. continue;
  406. }
  407. $input .= $this->_add_attrib($key, $value);
  408. }
  409. $input .= '>';
  410. $input .= $data['value'];
  411. $input .= '</label>';
  412. return sprintf($this->template[FormTemplate::FIELD], $input);
  413. }
  414. /**
  415. * Creates a select field.
  416. *
  417. * @param array $data
  418. * @return string
  419. */
  420. private function _field_select($data) { }
  421. /**
  422. * Creates a submit button.
  423. *
  424. * @param array $data
  425. * @return string
  426. */
  427. private function _field_submit($data) {
  428. return sprintf($this->template[FormTemplate::BUTTON], $this->_do_field_input('submit', $data));
  429. }
  430. /**
  431. * Creates a reset button.
  432. *
  433. * @param array $data
  434. * @return string
  435. */
  436. private function _field_reset($data) {
  437. return sprintf($this->template[FormTemplate::BUTTON], $this->_do_field_input('reset', $data));
  438. }
  439. /**
  440. * Creates a standard button.
  441. *
  442. * @param array $data
  443. * @return string
  444. */
  445. private function _field_button($data) {
  446. return sprintf($this->template[FormTemplate::BUTTON], $this->_do_field_input('button', $data));
  447. }
  448. /**
  449. * Creates a button tag.
  450. *
  451. * @param array $data
  452. * @return string
  453. */
  454. private function _field_button_tag($data) {
  455. unset($data['field_type']);
  456. unset($data['label']);
  457. $input = '<button';
  458. foreach ($data as $key => $value) {
  459. if ($key == 'content') {
  460. continue;
  461. }
  462. if ($value === true) {
  463. $input .= $this->_add_param($key);
  464. continue;
  465. }
  466. if ($key == 'id') {
  467. $input .= $this->_add_attrib('id', 'field_' . $value);
  468. continue;
  469. }
  470. $input .= $this->_add_attrib($key, $value);
  471. }
  472. $input .= '>';
  473. $input .= (isset($data['content'])) ? $data['content'] : '';
  474. $input .= '</button>';
  475. return sprintf($this->template[FormTemplate::FIELD], $input);
  476. }
  477. /**
  478. * Create email input field.
  479. *
  480. * @param array $data
  481. * @return string
  482. */
  483. private function _field_email($data) {
  484. if (isset($data['label'])) {
  485. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('email', $data));
  486. } else {
  487. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('email', $data));
  488. }
  489. }
  490. /**
  491. * Create telephone input field.
  492. *
  493. * @param array $data
  494. * @return string
  495. */
  496. private function _field_tel($data) {
  497. if (isset($data['label'])) {
  498. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('tel', $data));
  499. } else {
  500. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('tel', $data));
  501. }
  502. }
  503. /**
  504. * Create URL input field.
  505. *
  506. * @param array $data
  507. * @return string
  508. */
  509. private function _field_url($data) {
  510. if (isset($data['label'])) {
  511. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('url', $data));
  512. } else {
  513. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('url', $data));
  514. }
  515. }
  516. /**
  517. * Create search input field.
  518. *
  519. * @param array $data
  520. * @return string
  521. */
  522. private function _field_search($data) {
  523. if (isset($data['label'])) {
  524. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('search', $data));
  525. } else {
  526. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('search', $data));
  527. }
  528. }
  529. /**
  530. * Create number field.
  531. *
  532. * @param array $data
  533. * @return string
  534. */
  535. private function _field_number($data) {
  536. if (isset($data['label'])) {
  537. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('number', $data));
  538. } else {
  539. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('number', $data));
  540. }
  541. }
  542. /**
  543. * Create date input field.
  544. *
  545. * @param array $data
  546. * @return string
  547. */
  548. private function _field_date($data) {
  549. if (isset($data['label'])) {
  550. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('date', $data));
  551. } else {
  552. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('date', $data));
  553. }
  554. }
  555. /**
  556. * Create time field.
  557. *
  558. * @param array $data
  559. * @return string
  560. */
  561. private function _field_time($data) {
  562. if (isset($data['label'])) {
  563. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('time', $data));
  564. } else {
  565. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('time', $data));
  566. }
  567. }
  568. /**
  569. * Create datetime input field.
  570. *
  571. * @param array $data
  572. * @return string
  573. */
  574. private function _field_datetime($data) {
  575. if (isset($data['label'])) {
  576. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('datetime', $data));
  577. } else {
  578. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('datetime', $data));
  579. }
  580. }
  581. /**
  582. * Create week input field.
  583. *
  584. * @param array $data
  585. * @return string
  586. */
  587. private function _field_week($data) {
  588. if (isset($data['label'])) {
  589. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('week', $data));
  590. } else {
  591. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('week', $data));
  592. }
  593. }
  594. /**
  595. * Create month input field.
  596. *
  597. * @param array $data
  598. * @return string
  599. */
  600. private function _field_month($data) {
  601. if (isset($data['label'])) {
  602. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('month', $data));
  603. } else {
  604. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('month', $data));
  605. }
  606. }
  607. /**
  608. * Create color input field.
  609. *
  610. * @param array $data
  611. * @return string
  612. */
  613. private function _field_color($data) {
  614. if (isset($data['label'])) {
  615. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('color', $data));
  616. } else {
  617. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('color', $data));
  618. }
  619. }
  620. /**
  621. * Create range input field.
  622. *
  623. * @param array $data
  624. * @return string
  625. */
  626. private function _field_range($data) {
  627. if (isset($data['label'])) {
  628. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($data), $this->_do_field_input('range', $data));
  629. } else {
  630. return sprintf($this->template[FormTemplate::FIELD], $this->_do_field_input('range', $data));
  631. }
  632. }
  633. /**
  634. * Create a recaptcha field.
  635. *
  636. * @param array $data
  637. * @return string
  638. */
  639. private function _field_recaptacha($data) {
  640. require_once 'ReCAPTCHA\recaptchalib.php';
  641. if (isset($data['label'])) {
  642. $clean = $data;
  643. unset($clean['key']);
  644. return sprintf($this->template[FormTemplate::FIELD_LABEL], $this->_do_field_label($clean), recaptcha_get_html($data['key']));
  645. } else {
  646. return sprintf($this->template[FormTemplate::FIELD], recaptcha_get_html($data['key']));
  647. }
  648. }
  649. /**
  650. * Builds a standard input field from an array.
  651. *
  652. * @param string $type
  653. * @param array $data
  654. * @return string
  655. */
  656. private function _do_field_input($type, $data) {
  657. $input = '<input type="' . $type . '"';
  658. unset($data['field_type']);
  659. unset($data['label']);
  660. foreach ($data as $key => $value) {
  661. //no empty value param for buttons
  662. if (($type == 'reset' || $type == 'submit') && $key == 'value' && empty($value)) {
  663. continue;
  664. }
  665. if ($value === true) {
  666. $input .= $this->_add_param($key);
  667. continue;
  668. }
  669. if ($key == 'id') {
  670. $input .= $this->_add_attrib('id', 'field_' . $value);
  671. continue;
  672. }
  673. $input .= $this->_add_attrib($key, $value);
  674. }
  675. $input .= '>';
  676. return $input;
  677. }
  678. /**
  679. * Builds a standard label from an array.
  680. *
  681. * @param array $data
  682. * @return string
  683. */
  684. private function _do_field_label($data) {
  685. $label = '<label';
  686. $label .= $this->_add_attrib('for', $data['name']);
  687. $label .= $this->_add_attrib('id', 'label_' . $data['id']);
  688. $label .= (isset($data['class'])) ? $this->_add_attrib('class', $data['class']): '';
  689. $label .= '>' . $data['label'] . '</label>';
  690. return $label;
  691. }
  692. /**
  693. * Creates an attribute pair (key=value).
  694. *
  695. * @param string $name
  696. * @param mixed $value
  697. * @return string
  698. */
  699. private function _add_attrib($name, $value) {
  700. return " {$name}=\"{$value}\"";
  701. }
  702. /**
  703. * Creates an parameter entry (key).
  704. *
  705. * @param string $name
  706. * @return string
  707. */
  708. private function _add_param($name) {
  709. return " {$name}";
  710. }
  711. }