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

/wp-content/plugins/posts-to-posts/scb/Forms.php

https://gitlab.com/blueprintmrk/bladencountyrecords
PHP | 483 lines | 324 code | 116 blank | 43 comment | 53 complexity | 4d1cbb25eb7d0f766b0aad0acfc14f04 MD5 | raw file
  1. <?php
  2. // Data-aware form generator
  3. class scbForms {
  4. const TOKEN = '%input%';
  5. protected static $cur_name;
  6. static function input( $args, $formdata = false ) {
  7. if ( !empty( $formdata ) ) {
  8. $form = new scbForm( $formdata );
  9. return $form->input( $args );
  10. }
  11. if ( empty( $args['name'] ) ) {
  12. return trigger_error( 'Empty name', E_USER_WARNING );
  13. }
  14. $args = wp_parse_args( $args, array(
  15. 'desc' => '',
  16. 'desc_pos' => 'after',
  17. 'wrap' => self::TOKEN,
  18. ) );
  19. if ( isset( $args['value'] ) && is_array( $args['value'] ) ) {
  20. $args['values'] = $args['value'];
  21. unset( $args['value'] );
  22. }
  23. if ( isset( $args['extra'] ) && !is_array( $args['extra'] ) )
  24. $args['extra'] = shortcode_parse_atts( $args['extra'] );
  25. self::$cur_name = self::get_name( $args['name'] );
  26. switch ( $args['type'] ) {
  27. case 'select':
  28. case 'radio':
  29. $input = self::_single_choice( $args );
  30. break;
  31. case 'checkbox':
  32. if ( isset( $args['values'] ) )
  33. $input = self::_multiple_choice( $args );
  34. else
  35. $input = self::_checkbox( $args );
  36. break;
  37. default:
  38. $input = self::_input( $args );
  39. }
  40. return str_replace( self::TOKEN, $input, $args['wrap'] );
  41. }
  42. // ____________UTILITIES____________
  43. // Generates a table wrapped in a form
  44. static function form_table( $rows, $formdata = NULL ) {
  45. $output = '';
  46. foreach ( $rows as $row )
  47. $output .= self::table_row( $row, $formdata );
  48. $output = self::form_table_wrap( $output );
  49. return $output;
  50. }
  51. // Generates a form
  52. static function form( $inputs, $formdata = NULL, $nonce ) {
  53. $output = '';
  54. foreach ( $inputs as $input )
  55. $output .= self::input( $input, $formdata );
  56. $output = self::form_wrap( $output, $nonce );
  57. return $output;
  58. }
  59. // Generates a table
  60. static function table( $rows, $formdata = NULL ) {
  61. $output = '';
  62. foreach ( $rows as $row )
  63. $output .= self::table_row( $row, $formdata );
  64. $output = self::table_wrap( $output );
  65. return $output;
  66. }
  67. // Generates a table row
  68. static function table_row( $args, $formdata = NULL ) {
  69. return self::row_wrap( $args['title'], self::input( $args, $formdata ) );
  70. }
  71. // ____________WRAPPERS____________
  72. // Wraps the given content in a <form><table>
  73. static function form_table_wrap( $content, $nonce = 'update_options' ) {
  74. $output = self::table_wrap( $content );
  75. $output = self::form_wrap( $output, $nonce );
  76. return $output;
  77. }
  78. // Wraps the given content in a <form> tag
  79. static function form_wrap( $content, $nonce = 'update_options' ) {
  80. $output = "\n<form method='post' action=''>\n";
  81. $output .= $content;
  82. $output .= wp_nonce_field( $action = $nonce, $name = "_wpnonce", $referer = true , $echo = false );
  83. $output .= "\n</form>\n";
  84. return $output;
  85. }
  86. // Wraps the given content in a <table>
  87. static function table_wrap( $content ) {
  88. $output = "\n<table class='form-table'>\n" . $content . "\n</table>\n";
  89. return $output;
  90. }
  91. // Wraps the given content in a <tr><td>
  92. static function row_wrap( $title, $content ) {
  93. return "\n<tr>\n\t<th scope='row'>" . $title . "</th>\n\t<td>\n\t\t" . $content . "\t</td>\n\n</tr>";
  94. }
  95. // ____________PRIVATE METHODS____________
  96. private static function _single_choice( $args ) {
  97. $args = wp_parse_args( $args, array(
  98. 'numeric' => false, // use numeric array instead of associative
  99. 'selected' => array( 'foo' ), // hack to make default blank
  100. ) );
  101. self::_expand_values( $args );
  102. if ( 'select' == $args['type'] )
  103. return self::_select( $args );
  104. else
  105. return self::_radio( $args );
  106. }
  107. private static function _multiple_choice( $args ) {
  108. $args = wp_parse_args( $args, array(
  109. 'numeric' => false, // use numeric array instead of associative
  110. 'checked' => null,
  111. ) );
  112. self::$cur_name .= '[]';
  113. self::_expand_values( $args );
  114. extract( $args );
  115. if ( !is_array( $checked ) )
  116. $checked = array();
  117. $opts = '';
  118. foreach ( $values as $value => $title ) {
  119. if ( empty( $value ) || empty( $title ) )
  120. continue;
  121. $opts .= self::_checkbox( array(
  122. 'type' => 'checkbox',
  123. 'value' => $value,
  124. 'checked' => in_array( $value, $checked ),
  125. 'desc' => $title,
  126. 'desc_pos' => 'after'
  127. ) );
  128. }
  129. return self::add_desc( $opts, $desc, $desc_pos );
  130. }
  131. private static function _expand_values( &$args ) {
  132. $values =& $args['values'];
  133. if ( !empty( $values ) && !self::is_associative( $values ) ) {
  134. if ( is_array( $args['desc'] ) ) {
  135. $values = array_combine( $values, $args['desc'] ); // back-compat
  136. $args['desc'] = false;
  137. } elseif ( !$args['numeric'] ) {
  138. $values = array_combine( $values, $values );
  139. }
  140. }
  141. }
  142. private static function _radio( $args ) {
  143. extract( $args );
  144. if ( array( 'foo' ) == $selected ) {
  145. // radio buttons should always have one option selected
  146. $selected = key( $values );
  147. }
  148. $opts = '';
  149. foreach ( $values as $value => $title ) {
  150. if ( empty( $value ) || empty( $title ) )
  151. continue;
  152. $opts .= self::_checkbox( array(
  153. 'type' => 'radio',
  154. 'value' => $value,
  155. 'checked' => ( (string) $value == (string) $selected ),
  156. 'desc' => $title,
  157. 'desc_pos' => 'after'
  158. ) );
  159. }
  160. return self::add_desc( $opts, $desc, $desc_pos );
  161. }
  162. private static function _select( $args ) {
  163. extract( wp_parse_args( $args, array(
  164. 'text' => '',
  165. 'extra' => array()
  166. ) ) );
  167. $options = array();
  168. if ( false !== $text ) {
  169. $options[] = array(
  170. 'value' => '',
  171. 'selected' => ( $selected == array( 'foo' ) ),
  172. 'title' => $text
  173. );
  174. }
  175. foreach ( $values as $value => $title ) {
  176. if ( empty( $value ) || empty( $title ) )
  177. continue;
  178. $options[] = array(
  179. 'value' => $value,
  180. 'selected' => ( (string) $value == (string) $selected ),
  181. 'title' => $title
  182. );
  183. }
  184. $opts = '';
  185. foreach ( $options as $option ) {
  186. extract( $option );
  187. $opts .= html( 'option', compact( 'value', 'selected' ), $title );
  188. }
  189. $extra['name'] = self::$cur_name;
  190. $input = html( 'select', $extra, $opts );
  191. return self::add_label( $input, $desc, $desc_pos );
  192. }
  193. // Handle args for a single checkbox or radio input
  194. private static function _checkbox( $args ) {
  195. $args = wp_parse_args( $args, array(
  196. 'value' => true,
  197. 'desc' => NULL,
  198. 'checked' => false,
  199. 'extra' => array(),
  200. ) );
  201. foreach ( $args as $key => &$val )
  202. $$key = &$val;
  203. unset( $val );
  204. $extra['checked'] = $checked;
  205. if ( is_null( $desc ) && !is_bool( $value ) )
  206. $desc = str_replace( '[]', '', $value );
  207. return self::_input_gen( $args );
  208. }
  209. // Handle args for text inputs
  210. private static function _input( $args ) {
  211. $args = wp_parse_args( $args, array(
  212. 'value' => '',
  213. 'desc_pos' => 'after',
  214. 'extra' => array( 'class' => 'regular-text' ),
  215. ) );
  216. foreach ( $args as $key => &$val )
  217. $$key = &$val;
  218. unset( $val );
  219. if ( !isset( $extra['id'] ) && !is_array( $name ) && false === strpos( $name, '[' ) )
  220. $extra['id'] = $name;
  221. return self::_input_gen( $args );
  222. }
  223. // Generate html with the final args
  224. private static function _input_gen( $args ) {
  225. extract( wp_parse_args( $args, array(
  226. 'value' => NULL,
  227. 'desc' => NULL,
  228. 'extra' => array()
  229. ) ) );
  230. $extra['name'] = self::$cur_name;
  231. if ( 'textarea' == $type ) {
  232. $input = html( 'textarea', $extra, esc_textarea( $value ) );
  233. } else {
  234. $extra['value'] = $value;
  235. $extra['type'] = $type;
  236. $input = html( 'input', $extra );
  237. }
  238. return self::add_label( $input, $desc, $desc_pos );
  239. }
  240. private static function add_label( $input, $desc, $desc_pos ) {
  241. return html( 'label', self::add_desc( $input, $desc, $desc_pos ) ) . "\n";
  242. }
  243. private static function add_desc( $input, $desc, $desc_pos ) {
  244. if ( empty( $desc ) )
  245. return $input;
  246. if ( 'before' == $desc_pos )
  247. return $desc . ' ' . $input;
  248. else
  249. return $input . ' ' . $desc;
  250. }
  251. // Utilities
  252. /**
  253. * Generates the proper string for a name attribute.
  254. *
  255. * @param array|string $name The raw name
  256. *
  257. * @return string
  258. */
  259. static function get_name( $name ) {
  260. $name = (array) $name;
  261. $name_str = array_shift( $name );
  262. foreach ( $name as $key ) {
  263. $name_str .= '[' . esc_attr( $key ) . ']';
  264. }
  265. return $name_str;
  266. }
  267. /**
  268. * Traverses the formdata and retrieves the correct value.
  269. *
  270. * @param array|string $name The name of the value
  271. * @param array $value The data that will be traversed
  272. * @param mixed $fallback The value returned when the key is not found
  273. *
  274. * @return mixed
  275. */
  276. static function get_value( $name, $value, $fallback = null ) {
  277. foreach ( (array) $name as $key ) {
  278. if ( !isset( $value[ $key ] ) )
  279. return $fallback;
  280. $value = $value[$key];
  281. }
  282. return $value;
  283. }
  284. /**
  285. * Given a list of fields, extract the appropriate POST data and return it.
  286. *
  287. * @param array $fields List of args that would be sent to scbForms::input()
  288. *
  289. * @return array
  290. */
  291. static function validate_post_data( $fields ) {
  292. foreach ( $fields as $field ) {
  293. $value = scbForms::get_value( $field['name'], $_POST );
  294. $value = stripslashes_deep( $value );
  295. switch ( $field['type'] ) {
  296. case 'checkbox':
  297. if ( isset( $field['values'] ) && is_array( $field['values'] ) )
  298. $value = array_intersect( $field['values'], (array) $value );
  299. else
  300. $value = (bool) $value;
  301. break;
  302. case 'radio':
  303. case 'select':
  304. if ( !isset( $field['values'][ $value ] ) )
  305. continue 2;
  306. }
  307. self::set_value( $to_update, $field['name'], $value );
  308. }
  309. return $to_update;
  310. }
  311. private static function set_value( &$arr, $name, $value ) {
  312. $name = (array) $name;
  313. $final_key = array_pop( $name );
  314. while ( !empty( $name ) ) {
  315. $key = array_shift( $name );
  316. if ( !isset( $arr[ $key ] ) )
  317. $arr[ $key ] = array();
  318. $arr =& $arr[ $key ];
  319. }
  320. $arr[ $final_key ] = $value;
  321. }
  322. private static function is_associative( $array ) {
  323. $keys = array_keys( $array );
  324. return array_keys( $keys ) !== $keys;
  325. }
  326. }
  327. /**
  328. * A wrapper for scbForms, containing the formdata
  329. */
  330. class scbForm {
  331. protected $data = array();
  332. protected $prefix = array();
  333. function __construct( $data, $prefix = false ) {
  334. if ( is_array( $data ) )
  335. $this->data = $data;
  336. if ( $prefix )
  337. $this->prefix = (array) $prefix;
  338. }
  339. function traverse_to( $path ) {
  340. $data = scbForms::get_value( $path, $this->data );
  341. $prefix = array_merge( $this->prefix, (array) $path );
  342. return new scbForm( $data, $prefix );
  343. }
  344. function input( $args ) {
  345. $value = scbForms::get_value( $args['name'], $this->data );
  346. if ( !is_null( $value ) ) {
  347. switch ( $args['type'] ) {
  348. case 'select':
  349. case 'radio':
  350. $args['selected'] = $value;
  351. break;
  352. case 'checkbox':
  353. if ( is_array( $value ) )
  354. $args['checked'] = $value;
  355. else
  356. $args['checked'] = ( $value || ( isset( $args['value'] ) && $value == $args['value'] ) );
  357. break;
  358. default:
  359. $args['value'] = $value;
  360. }
  361. }
  362. if ( !empty( $this->prefix ) ) {
  363. $args['name'] = array_merge( $this->prefix, (array) $args['name'] );
  364. }
  365. return scbForms::input( $args );
  366. }
  367. }