PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/classes/PodsForm.php

https://github.com/BenjaminNolan/pods
PHP | 1165 lines | 606 code | 233 blank | 326 comment | 139 complexity | 883c129f27c3e1c2730a4005507400bf MD5 | raw file
Possible License(s): Apache-2.0
  1. <?php
  2. /**
  3. * @package Pods
  4. */
  5. class PodsForm {
  6. /**
  7. * @var PodsForm
  8. */
  9. protected static $instance = null;
  10. /**
  11. * @var string
  12. */
  13. static $field = null;
  14. /**
  15. * @var string
  16. */
  17. static $field_group = null;
  18. /**
  19. * @var string
  20. */
  21. static $field_type = null;
  22. /**
  23. * @var array
  24. */
  25. static $field_types = array();
  26. /**
  27. * @var array
  28. */
  29. static $loaded = array();
  30. /**
  31. * @var int
  32. */
  33. static $form_counter = 0;
  34. /**
  35. * Master handler for all field / form methods
  36. *
  37. * @return \PodsForm
  38. *
  39. * @license http://www.gnu.org/licenses/gpl-2.0.html
  40. * @since 2.0
  41. */
  42. private function __construct () {
  43. add_action( 'admin_init', array( $this, 'admin_init' ), 14 );
  44. }
  45. /**
  46. * Prevent clones
  47. *
  48. * @since 2.3
  49. */
  50. private function __clone () {
  51. // Hulk smash
  52. }
  53. /**
  54. * Setup / get PodsForm instance
  55. *
  56. * @return PodsForm
  57. *
  58. * @since 2.3
  59. */
  60. public static function instance () {
  61. if ( empty( self::$instance ) )
  62. self::$instance = new PodsForm;
  63. return self::$instance;
  64. }
  65. /**
  66. * Output a field's label
  67. *
  68. * @since 2.0
  69. */
  70. public static function label ( $name, $label, $help = '', $options = null ) {
  71. if ( is_array( $label ) ) {
  72. $options = $label;
  73. $label = $options[ 'label' ];
  74. if ( empty( $label ) )
  75. $label = ucwords( str_replace( '_', ' ', $name ) );
  76. $help = $options[ 'help' ];
  77. }
  78. else
  79. $options = self::options( null, $options );
  80. $label = apply_filters( 'pods_form_ui_label_text', $label, $name, $help, $options );
  81. $help = apply_filters( 'pods_form_ui_label_help', $help, $name, $label, $options );
  82. ob_start();
  83. $name_clean = self::clean( $name );
  84. $name_more_clean = self::clean( $name, true );
  85. $type = 'label';
  86. $attributes = array();
  87. $attributes[ 'class' ] = 'pods-form-ui-' . $type . ' pods-form-ui-' . $type . '-' . $name_more_clean;
  88. $attributes[ 'for' ] = ( false === strpos( $name_clean, 'pods-form-ui-' ) ? 'pods-form-ui-' : '' ) . $name_clean;
  89. $attributes = self::merge_attributes( $attributes, $name, $type, $options, false );
  90. pods_view( PODS_DIR . 'ui/fields/_label.php', compact( array_keys( get_defined_vars() ) ) );
  91. $output = ob_get_clean();
  92. return apply_filters( 'pods_form_ui_' . $type, $output, $name, $label, $help, $attributes, $options );
  93. }
  94. /**
  95. * Output a Field Comment Paragraph
  96. */
  97. public static function comment ( $name, $message = null, $options = null ) {
  98. $options = self::options( null, $options );
  99. $name_more_clean = self::clean( $name, true );
  100. if ( isset( $options[ 'description' ] ) && !empty( $options[ 'description' ] ) )
  101. $message = $options[ 'description' ];
  102. elseif ( empty( $message ) )
  103. return;
  104. $message = apply_filters( 'pods_form_ui_comment_text', $message, $name, $options );
  105. ob_start();
  106. $type = 'comment';
  107. $attributes = array();
  108. $attributes[ 'class' ] = 'pods-form-ui-' . $type . ' pods-form-ui-' . $type . '-' . $name_more_clean;
  109. $attributes = self::merge_attributes( $attributes, $name, $type, $options, false );
  110. pods_view( PODS_DIR . 'ui/fields/_comment.php', compact( array_keys( get_defined_vars() ) ) );
  111. $output = ob_get_clean();
  112. return apply_filters( 'pods_form_ui_' . $type, $output, $name, $message, $attributes, $options );
  113. }
  114. /**
  115. * Output a field
  116. *
  117. * @since 2.0
  118. */
  119. public static function field ( $name, $value, $type = 'text', $options = null, $pod = null, $id = null ) {
  120. $options = self::options( $type, $options );
  121. if ( null === $value || ( '' === $value && 'boolean' == $type ) || ( !empty( $pod ) && empty( $id ) ) )
  122. $value = self::default_value( $value, $type, $name, $options, $pod, $id );
  123. if ( false === self::permission( $type, $name, $options, null, $pod, $id ) )
  124. return false;
  125. $value = apply_filters( 'pods_form_ui_field_' . $type . '_value', $value, $name, $options, $pod, $id );
  126. $form_field_type = self::$field_type;
  127. ob_start();
  128. $helper = false;
  129. if ( 0 < strlen( pods_var_raw( 'input_helper', $options ) ) )
  130. $helper = pods_api()->load_helper( array( 'name' => $options[ 'input_helper' ] ) );
  131. if ( ( !isset( $options[ 'data' ] ) || empty( $options[ 'data' ] ) ) && is_object( self::$loaded[ $type ] ) && method_exists( self::$loaded[ $type ], 'data' ) )
  132. $data = $options[ 'data' ] = self::$loaded[ $type ]->data( $name, $value, $options, $pod, $id, true );
  133. if ( true === apply_filters( 'pods_form_ui_field_' . $type . '_override', false, $name, $value, $options, $pod, $id ) )
  134. do_action( 'pods_form_ui_field_' . $type, $name, $value, $options, $pod, $id );
  135. elseif ( !empty( $helper ) && 0 < strlen( pods_var_raw( 'code', $helper ) ) && ( !defined( 'PODS_DISABLE_EVAL' ) || !PODS_DISABLE_EVAL ) )
  136. eval( '?>' . $helper[ 'code' ] );
  137. elseif ( method_exists( get_class(), 'field_' . $type ) )
  138. echo call_user_func( array( get_class(), 'field_' . $type ), $name, $value, $options );
  139. elseif ( is_object( self::$loaded[ $type ] ) && method_exists( self::$loaded[ $type ], 'input' ) )
  140. self::$loaded[ $type ]->input( $name, $value, $options, $pod, $id );
  141. else
  142. do_action( 'pods_form_ui_field_' . $type, $name, $value, $options, $pod, $id );
  143. $output = ob_get_clean();
  144. return apply_filters( 'pods_form_ui_field_' . $type, $output, $name, $value, $options, $pod, $id );
  145. }
  146. /**
  147. * Output field type 'db'
  148. *
  149. * Used for field names and other places where only [a-z0-9_] is accepted
  150. *
  151. * @since 2.0
  152. */
  153. protected static function field_db ( $name, $value = null, $options = null ) {
  154. $form_field_type = self::$field_type;
  155. ob_start();
  156. pods_view( PODS_DIR . 'ui/fields/_db.php', compact( array_keys( get_defined_vars() ) ) );
  157. $output = ob_get_clean();
  158. return apply_filters( 'pods_form_ui_field_db', $output, $name, $value, $options );
  159. }
  160. /**
  161. * Output a hidden field
  162. */
  163. protected static function field_hidden ( $name, $value = null, $options = null ) {
  164. $form_field_type = self::$field_type;
  165. ob_start();
  166. pods_view( PODS_DIR . 'ui/fields/_hidden.php', compact( array_keys( get_defined_vars() ) ) );
  167. $output = ob_get_clean();
  168. return apply_filters( 'pods_form_ui_field_hidden', $output, $name, $value, $options );
  169. }
  170. /**
  171. * Output a row (label, field, and comment)
  172. */
  173. public static function row ( $name, $value, $type = 'text', $options = null, $pod = null, $id = null ) {
  174. $options = self::options( null, $options );
  175. ob_start();
  176. pods_view( PODS_DIR . 'ui/fields/_row.php', compact( array_keys( get_defined_vars() ) ) );
  177. $output = ob_get_clean();
  178. return apply_filters( 'pods_form_ui_field_row', $output, $name, $value, $options, $pod, $id );
  179. }
  180. /**
  181. * Output a field's attributes
  182. *
  183. * @since 2.0
  184. */
  185. public static function attributes ( $attributes, $name = null, $type = null, $options = null ) {
  186. $attributes = (array) apply_filters( 'pods_form_ui_field_' . $type . '_attributes', $attributes, $name, $options );
  187. foreach ( $attributes as $attribute => $value ) {
  188. if ( null === $value )
  189. continue;
  190. echo ' ' . esc_attr( (string) $attribute ) . '="' . esc_attr( (string) $value ) . '"';
  191. }
  192. }
  193. /**
  194. * Output a field's data (for use with jQuery)
  195. *
  196. * @since 2.0
  197. */
  198. public static function data ( $data, $name = null, $type = null, $options = null ) {
  199. $data = (array) apply_filters( 'pods_form_ui_field_' . $type . '_data', $data, $name, $options );
  200. foreach ( $data as $key => $value ) {
  201. if ( null === $value )
  202. continue;
  203. $key = sanitize_title( $key );
  204. if ( is_array( $value ) )
  205. $value = implode( ',', $value );
  206. echo ' data-' . esc_attr( (string) $key ) . '="' . esc_attr( (string) $value ) . '"';
  207. }
  208. }
  209. /**
  210. * Merge attributes and handle classes
  211. *
  212. * @since 2.0
  213. */
  214. public static function merge_attributes ( $attributes, $name = null, $type = null, $options = null, $classes = '' ) {
  215. $options = (array) $options;
  216. if ( !in_array( $type, array( 'label', 'comment' ) ) ) {
  217. $name_clean = self::clean( $name );
  218. $name_more_clean = self::clean( $name, true );
  219. $_attributes = array();
  220. $_attributes[ 'name' ] = $name;
  221. $_attributes[ 'data-name-clean' ] = $name_more_clean;
  222. if ( 0 < strlen( pods_var_raw( 'label', $options, '' ) ) )
  223. $_attributes[ 'data-label' ] = strip_tags( pods_var_raw( 'label', $options ) );
  224. $_attributes[ 'id' ] = 'pods-form-ui-' . $name_clean;
  225. $_attributes[ 'class' ] = 'pods-form-ui-field-type-' . $type . ' pods-form-ui-field-name-' . $name_more_clean;
  226. if ( isset( $options[ 'dependency' ] ) && false !== $options[ 'dependency' ] )
  227. $_attributes[ 'class' ] .= ' pods-dependent-toggle';
  228. $attributes = array_merge( $_attributes, (array) $attributes );
  229. if ( isset( $options[ 'attributes' ] ) && is_array( $options[ 'attributes' ] ) && !empty( $options[ 'attributes' ] ) )
  230. $attributes = array_merge( $attributes, $options[ 'attributes' ] );
  231. }
  232. elseif ( isset( $options[ $type . '_attributes' ] ) && is_array( $options[ $type . '_attributes' ] ) && !empty( $options[ $type . '_attributes' ] ) )
  233. $attributes = array_merge( $attributes, $options[ $type . '_attributes' ] );
  234. if ( isset( $options[ 'class' ] ) && !empty( $options[ 'class' ] ) ) {
  235. if ( is_array( $options[ 'class' ] ) )
  236. $options[ 'class' ] = implode( ' ', $options[ 'class' ] );
  237. $options[ 'class' ] = (string) $options[ 'class' ];
  238. if ( isset( $attributes[ 'class' ] ) )
  239. $attributes[ 'class' ] = $attributes[ 'class' ] . ' ' . $options[ 'class' ];
  240. else
  241. $attributes[ 'class' ] = $options[ 'class' ];
  242. $attributes[ 'class' ] = trim( $attributes[ 'class' ] );
  243. }
  244. if ( !empty( $classes ) ) {
  245. if ( isset( $attributes[ 'class' ] ) )
  246. $attributes[ 'class' ] = $attributes[ 'class' ] . ' ' . $classes;
  247. else
  248. $attributes[ 'class' ] = $classes;
  249. }
  250. if ( 1 == pods_var( 'required', $options, 0 ) )
  251. $attributes[ 'class' ] .= ' pods-validate pods-validate-required';
  252. $max_length = (int) pods_var( 'maxlength', $options, pods_var( $type . '_max_length', $options, 0 ), null, true );
  253. if ( 0 < $max_length )
  254. $attributes[ 'maxlength' ] = $max_length;
  255. $attributes = (array) apply_filters( 'pods_form_ui_field_' . $type . '_merge_attributes', $attributes, $name, $options );
  256. return $attributes;
  257. }
  258. /*
  259. * Setup options for a field and store them for later use
  260. *
  261. * @since 2.0
  262. */
  263. /**
  264. * @static
  265. *
  266. * @param $type
  267. * @param $options
  268. *
  269. * @return array
  270. */
  271. public static function options ( $type, $options ) {
  272. $options = (array) $options;
  273. if ( isset( $options[ 'options' ] ) ) {
  274. $options_temp = $options[ 'options' ];
  275. unset( $options[ 'options' ] );
  276. $options = array_merge( $options_temp, $options );
  277. $override = array(
  278. 'class'
  279. );
  280. foreach ( $override as $check ) {
  281. if ( isset( $options_temp[ $check ] ) )
  282. $options[ $check ] = $options_temp[ $check ];
  283. }
  284. }
  285. $defaults = self::options_setup( $type, $options );
  286. $core_defaults = array(
  287. 'id' => 0,
  288. 'label' => '',
  289. 'description' => '',
  290. 'help' => '',
  291. 'default' => null,
  292. 'attributes' => array(),
  293. 'class' => '',
  294. 'grouped' => 0,
  295. );
  296. $defaults = array_merge( $core_defaults, $defaults );
  297. foreach ( $defaults as $option => $settings ) {
  298. $default = $settings;
  299. if ( is_array( $settings ) && isset( $settings[ 'default' ] ) )
  300. $default = $settings[ 'default' ];
  301. if ( !isset( $options[ $option ] ) )
  302. $options[ $option ] = $default;
  303. }
  304. return $options;
  305. }
  306. /*
  307. * Get options for a field type and setup defaults
  308. *
  309. * @since 2.0
  310. */
  311. /**
  312. * @static
  313. *
  314. * @param $type
  315. *
  316. * @return array|null
  317. */
  318. public static function options_setup ( $type = null ) {
  319. $core_defaults = array(
  320. 'id' => 0,
  321. 'name' => '',
  322. 'label' => '',
  323. 'description' => '',
  324. 'help' => '',
  325. 'default' => null,
  326. 'attributes' => array(),
  327. 'class' => '',
  328. 'type' => 'text',
  329. 'group' => 0,
  330. 'grouped' => 0,
  331. 'developer_mode' => false,
  332. 'dependency' => false,
  333. 'depends-on' => array(),
  334. 'excludes-on' => array(),
  335. 'options' => array()
  336. );
  337. if ( null === $type )
  338. return $core_defaults;
  339. else
  340. self::field_loader( $type );
  341. $options = apply_filters( 'pods_field_' . $type . '_options', (array) self::$loaded[ $type ]->options(), $type, $core_defaults );
  342. return self::fields_setup( $options, $core_defaults );
  343. }
  344. /*
  345. * Get options for a field and setup defaults
  346. *
  347. * @since 2.0
  348. */
  349. /**
  350. * @static
  351. *
  352. * @param null $fields
  353. * @param null $core_defaults
  354. * @param bool $single
  355. *
  356. * @return array|null
  357. */
  358. public static function fields_setup ( $fields = null, $core_defaults = null, $single = false ) {
  359. if ( empty( $core_defaults ) ) {
  360. $core_defaults = array(
  361. 'id' => 0,
  362. 'name' => '',
  363. 'label' => '',
  364. 'description' => '',
  365. 'help' => '',
  366. 'default' => null,
  367. 'attributes' => array(),
  368. 'class' => '',
  369. 'type' => 'text',
  370. 'group' => 0,
  371. 'grouped' => 0,
  372. 'developer_mode' => false,
  373. 'dependency' => false,
  374. 'depends-on' => array(),
  375. 'excludes-on' => array(),
  376. 'options' => array()
  377. );
  378. }
  379. if ( $single )
  380. $fields = array( $fields );
  381. foreach ( $fields as $f => $field ) {
  382. $fields[ $f ] = self::field_setup( $field, $core_defaults, pods_var( 'type', $field, 'text' ) );
  383. }
  384. if ( $single )
  385. $fields = $fields[ 0 ];
  386. return $fields;
  387. }
  388. /*
  389. * Get options for a field and setup defaults
  390. *
  391. * @since 2.0
  392. */
  393. /**
  394. * @static
  395. *
  396. * @param null $field
  397. * @param null $core_defaults
  398. * @param null $type
  399. *
  400. * @return array|null
  401. */
  402. public static function field_setup ( $field = null, $core_defaults = null, $type = null ) {
  403. $options = array();
  404. if ( empty( $core_defaults ) ) {
  405. $core_defaults = array(
  406. 'id' => 0,
  407. 'name' => '',
  408. 'label' => '',
  409. 'description' => '',
  410. 'help' => '',
  411. 'default' => null,
  412. 'attributes' => array(),
  413. 'class' => '',
  414. 'type' => 'text',
  415. 'group' => 0,
  416. 'grouped' => 0,
  417. 'developer_mode' => false,
  418. 'dependency' => false,
  419. 'depends-on' => array(),
  420. 'excludes-on' => array(),
  421. 'options' => array()
  422. );
  423. if ( null !== $type ) {
  424. self::field_loader( $type );
  425. if ( method_exists( self::$loaded[ $type ], 'options' ) )
  426. $options = apply_filters( 'pods_field_' . $type . '_options', (array) self::$loaded[ $type ]->options(), $type );
  427. }
  428. }
  429. if ( !is_array( $field ) )
  430. $field = array( 'default' => $field );
  431. if ( isset( $field[ 'group' ] ) && is_array( $field[ 'group' ] ) ) {
  432. foreach ( $field[ 'group' ] as $g => $group_option ) {
  433. $field[ 'group' ][ $g ] = array_merge( $core_defaults, $group_option );
  434. }
  435. }
  436. $field = array_merge( $core_defaults, $field );
  437. foreach ( $options as $option => $settings ) {
  438. $v = null;
  439. if ( isset( $settings[ 'default' ] ) )
  440. $v = $settings[ 'default' ];
  441. if ( !isset( $field[ 'options' ][ $option ] ) )
  442. $field[ 'options' ][ $option ] = $v;
  443. }
  444. return $field;
  445. }
  446. /**
  447. * Setup dependency / exclusion classes
  448. *
  449. * @param array $options array( 'depends-on' => ..., 'excludes-on' => ...)
  450. * @param string $prefix
  451. *
  452. * @return string
  453. * @static
  454. * @since 2.0
  455. */
  456. public static function dependencies ( $options, $prefix = '' ) {
  457. $options = (array) $options;
  458. $depends_on = $excludes_on = array();
  459. if ( isset( $options[ 'depends-on' ] ) )
  460. $depends_on = (array) $options[ 'depends-on' ];
  461. if ( isset( $options[ 'excludes-on' ] ) )
  462. $excludes_on = (array) $options[ 'excludes-on' ];
  463. $classes = array();
  464. if ( !empty( $depends_on ) ) {
  465. $classes[] = 'pods-depends-on';
  466. foreach ( $depends_on as $depends => $on ) {
  467. $classes[] = 'pods-depends-on-' . $prefix . self::clean( $depends, true );
  468. if ( !is_bool( $on ) ) {
  469. $on = (array) $on;
  470. foreach ( $on as $o ) {
  471. $classes[] = 'pods-depends-on-' . $prefix . self::clean( $depends, true ) . '-' . self::clean( $o, true );
  472. }
  473. }
  474. }
  475. }
  476. if ( !empty( $excludes_on ) ) {
  477. $classes[] = 'pods-excludes-on';
  478. foreach ( $excludes_on as $excludes => $on ) {
  479. $classes[] = 'pods-excludes-on-' . $prefix . self::clean( $excludes, true );
  480. $on = (array) $on;
  481. foreach ( $on as $o ) {
  482. $classes[] = 'pods-excludes-on-' . $prefix . self::clean( $excludes, true ) . '-' . self::clean( $o, true );
  483. }
  484. }
  485. }
  486. $classes = implode( ' ', $classes );
  487. return $classes;
  488. }
  489. /**
  490. * Change the value of the field
  491. *
  492. * @param mixed $value
  493. * @param string $name
  494. * @param array $options
  495. * @param array $fields
  496. * @param array $pod
  497. * @param int $id
  498. * @param array $traverse
  499. *
  500. * @since 2.3
  501. */
  502. public static function value ( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
  503. self::field_loader( $type );
  504. $tableless_field_types = self::tableless_field_types();
  505. $repeatable_field_types = self::repeatable_field_types();
  506. if ( in_array( $type, $repeatable_field_types ) && 1 == pods_var( $type . '_repeatable', $options, 0 ) && !is_array( $value ) ) {
  507. if ( 0 < strlen( $value ) ) {
  508. $simple = @json_decode( $value, true );
  509. if ( is_array( $simple ) )
  510. $value = $simple;
  511. else
  512. $value = (array) $value;
  513. }
  514. else
  515. $value = array();
  516. }
  517. if ( method_exists( self::$loaded[ $type ], 'value' ) ) {
  518. if ( is_array( $value ) && in_array( $type, $tableless_field_types ) ) {
  519. foreach ( $value as &$display_value ) {
  520. $display_value = call_user_func_array( array( self::$loaded[ $type ], 'value' ), array( $display_value, $name, $options, $pod, $id, $traverse ) );
  521. }
  522. }
  523. else
  524. $value = call_user_func_array( array( self::$loaded[ $type ], 'value' ), array( $value, $name, $options, $pod, $id, $traverse ) );
  525. }
  526. return $value;
  527. }
  528. /**
  529. * Change the way the value of the field is displayed with Pods::get
  530. *
  531. * @param mixed $value
  532. * @param string $name
  533. * @param array $options
  534. * @param array $fields
  535. * @param array $pod
  536. * @param int $id
  537. * @param array $traverse
  538. *
  539. * @since 2.0
  540. */
  541. public static function display ( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
  542. self::field_loader( $type );
  543. $tableless_field_types = self::tableless_field_types();
  544. if ( method_exists( self::$loaded[ $type ], 'display' ) ) {
  545. if ( is_array( $value ) && !in_array( $type, $tableless_field_types ) ) {
  546. foreach ( $value as $k => $display_value ) {
  547. $value[ $k ] = call_user_func_array( array( self::$loaded[ $type ], 'display' ), array( $display_value, $name, $options, $pod, $id, $traverse ) );
  548. }
  549. }
  550. else
  551. $value = call_user_func_array( array( self::$loaded[ $type ], 'display' ), array( $value, $name, $options, $pod, $id, $traverse ) );
  552. }
  553. $value = apply_filters( 'pods_form_display_' . $type, $value, $name, $options, $pod, $id, $traverse );
  554. return $value;
  555. }
  556. /**
  557. * Setup regex for JS / PHP
  558. *
  559. * @static
  560. *
  561. * @param $type
  562. * @param $options
  563. *
  564. * @return mixed|void
  565. * @since 2.0
  566. */
  567. public static function regex ( $type, $options ) {
  568. self::field_loader( $type );
  569. $regex = false;
  570. if ( method_exists( self::$loaded[ $type ], 'regex' ) )
  571. $regex = self::$loaded[ $type ]->regex( $options );
  572. $regex = apply_filters( 'pods_field_' . $type . '_regex', $regex, $options, $type );
  573. return $regex;
  574. }
  575. /**
  576. * Setup value preparation for sprintf
  577. *
  578. * @static
  579. *
  580. * @param $type
  581. * @param $options
  582. *
  583. * @return mixed|void
  584. * @since 2.0
  585. */
  586. public static function prepare ( $type, $options ) {
  587. self::field_loader( $type );
  588. $prepare = '%s';
  589. if ( method_exists( self::$loaded[ $type ], 'prepare' ) )
  590. $prepare = self::$loaded[ $type ]->prepare( $options );
  591. $prepare = apply_filters( 'pods_field_' . $type . '_prepare', $prepare, $options, $type );
  592. return $prepare;
  593. }
  594. /**
  595. * Validate a value before it's saved
  596. *
  597. * @param string $type
  598. * @param mixed $value
  599. * @param string $name
  600. * @param array $options
  601. * @param array $fields
  602. * @param array $pod
  603. * @param int $id
  604. * @param array|object $params
  605. *
  606. * @static
  607. *
  608. * @since 2.0
  609. */
  610. public static function validate ( $type, &$value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
  611. self::field_loader( $type );
  612. $validate = true;
  613. if ( 1 == pods_var( 'pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'validate' ) )
  614. $validate = self::$loaded[ $type ]->validate( $value, $name, $options, $fields, $pod, $id, $params );
  615. $validate = apply_filters( 'pods_field_' . $type . '_validate', $validate, $value, $name, $options, $fields, $pod, $id, $type, $params );
  616. return $validate;
  617. }
  618. /**
  619. * Change the value or perform actions after validation but before saving to the DB
  620. *
  621. * @param string $type
  622. * @param mixed $value
  623. * @param int $id
  624. * @param string $name
  625. * @param array $options
  626. * @param array $fields
  627. * @param array $pod
  628. * @param object $params
  629. *
  630. * @static
  631. *
  632. * @since 2.0
  633. */
  634. public static function pre_save ( $type, $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
  635. self::field_loader( $type );
  636. if ( 1 == pods_var( 'field_pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'pre_save' ) )
  637. $value = self::$loaded[ $type ]->pre_save( $value, $id, $name, $options, $fields, $pod, $params );
  638. return $value;
  639. }
  640. /**
  641. * Save the value to the DB
  642. *
  643. * @param string $type
  644. * @param mixed $value
  645. * @param int $id
  646. * @param string $name
  647. * @param array $options
  648. * @param array $fields
  649. * @param array $pod
  650. * @param object $params
  651. *
  652. * @static
  653. *
  654. * @since 2.3
  655. */
  656. public static function save ( $type, $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
  657. self::field_loader( $type );
  658. $saved = null;
  659. if ( 1 == pods_var( 'field_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'save' ) )
  660. $saved = self::$loaded[ $type ]->save( $value, $id, $name, $options, $fields, $pod, $params );
  661. return $saved;
  662. }
  663. /**
  664. * Delete the value from the DB
  665. *
  666. * @param string $type
  667. * @param int $id
  668. * @param string $name
  669. * @param array $options
  670. * @param array $pod
  671. *
  672. * @static
  673. *
  674. * @since 2.3
  675. */
  676. public static function delete ( $type, $id = null, $name = null, $options = null, $pod = null ) {
  677. self::field_loader( $type );
  678. $deleted = null;
  679. if ( 1 == pods_var( 'field_delete', $options, 1 ) && method_exists( self::$loaded[ $type ], 'delete' ) )
  680. $deleted = self::$loaded[ $type ]->delete( $id, $name, $options, $pod );
  681. return $deleted;
  682. }
  683. /**
  684. * Check if a user has permission to be editing a field
  685. *
  686. * @param $type
  687. * @param null $name
  688. * @param null $options
  689. * @param null $fields
  690. * @param null $pod
  691. * @param null $id
  692. * @param null $params
  693. *
  694. * @static
  695. *
  696. * @since 2.0
  697. */
  698. public static function permission ( $type, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
  699. $permission = pods_permission( $options );
  700. $permission = (boolean) apply_filters( 'pods_form_field_permission', $permission, $type, $name, $options, $fields, $pod, $id, $params );
  701. return $permission;
  702. }
  703. /**
  704. * Parse the default the value
  705. *
  706. * @since 2.0
  707. */
  708. public static function default_value ( $value, $type = 'text', $name = null, $options = null, $pod = null, $id = null ) {
  709. $default_value = pods_var_raw( 'default_value', $options, $value, null, true );
  710. $default = pods_var_raw( 'default', $options, $default_value, null, true );
  711. $default_value = str_replace( array( '{@', '}' ), '', trim( $default ) );
  712. if ( $default != $default_value && 1 == (int) pods_var_raw( 'default_evaluate_tags', $options, 1 ) )
  713. $default = pods_evaluate_tags( $default );
  714. $default = pods_var_raw( pods_var_raw( 'default_value_parameter', $options ), 'request', $default, null, true );
  715. if ( $default != $value )
  716. $value = $default;
  717. if ( is_array( $value ) )
  718. $value = pods_serial_comma( $value );
  719. return apply_filters( 'pods_form_field_default_value', $value, $default, $type, $options, $pod, $id );
  720. }
  721. /**
  722. * Clean a value for use in class / id
  723. *
  724. * @since 2.0
  725. */
  726. public static function clean ( $input, $noarray = false, $db_field = false ) {
  727. $input = str_replace( array( '--1', '__1' ), '00000', (string) $input );
  728. if ( false !== $noarray )
  729. $input = preg_replace( '/\[\d*\]/', '-', $input );
  730. $output = str_replace( array( '[', ']' ), '-', strtolower( $input ) );
  731. $output = preg_replace( '/([^a-z0-9-_])/', '', $output );
  732. $output = trim( str_replace( array( '__', '_', '--' ), '-', $output ), '-' );
  733. $output = str_replace( '00000', '--1', $output );
  734. if ( false !== $db_field )
  735. $output = str_replace( '-', '_', $output );
  736. return $output;
  737. }
  738. /**
  739. * Run admin_init methods for each field type
  740. *
  741. * @since 2.3
  742. */
  743. public function admin_init () {
  744. $admin_field_types = pods_transient_get( 'pods_form_admin_init_field_types' );
  745. if ( empty( $admin_field_types ) ) {
  746. $admin_field_types = array();
  747. $field_types = self::field_types();
  748. foreach ( $field_types as $field_type => $field_type_data ) {
  749. $has_ajax = self::field_method( $field_type_data[ 'type' ], 'admin_init' );
  750. if ( false !== $has_ajax )
  751. $admin_field_types[] = $field_type;
  752. }
  753. pods_transient_set( 'pods_form_admin_init_field_types', $admin_field_types );
  754. }
  755. else {
  756. foreach ( $admin_field_types as $field_type ) {
  757. self::field_method( $field_type, 'admin_init' );
  758. }
  759. }
  760. }
  761. /**
  762. * Autoload a Field Type's class
  763. *
  764. * @param string $field_type Field Type indentifier
  765. * @param string $file The Field Type class file location
  766. *
  767. * @return string
  768. * @access public
  769. * @static
  770. * @since 2.0
  771. */
  772. public static function field_loader ( $field_type, $file = '' ) {
  773. if ( isset( self::$loaded[ $field_type ] ) ) {
  774. $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) ); // PHP 5.2.x workaround
  775. self::$field_group = ( isset( $class_vars[ 'group' ] ) ? $class_vars[ 'group' ] : '' );
  776. self::$field_type = $class_vars[ 'type' ];
  777. if ( 'Unknown' != $class_vars[ 'label' ] )
  778. return self::$loaded[ $field_type ];
  779. }
  780. include_once PODS_DIR . 'classes/PodsField.php';
  781. $field_type = self::clean( $field_type, true, true );
  782. $class_name = ucfirst( $field_type );
  783. $class_name = "PodsField_{$class_name}";
  784. if ( !class_exists( $class_name ) ) {
  785. if ( isset( self::$field_types[ $field_type ] ) && !empty( self::$field_types[ $field_type ][ 'file' ] ) )
  786. $file = self::$field_types[ $field_type ][ 'file' ];
  787. if ( !empty( $file ) && 0 < strlen( untrailingslashit( ABSPATH ) ) && 0 === strpos( $file, untrailingslashit( ABSPATH ) ) && file_exists( $file ) )
  788. include_once $file;
  789. else {
  790. $file = str_replace( '../', '', apply_filters( 'pods_form_field_include', PODS_DIR . 'classes/fields/' . basename( $field_type ) . '.php', $field_type ) );
  791. if ( 0 < strlen( untrailingslashit( WP_CONTENT_DIR ) ) && 0 === strpos( $file, untrailingslashit( WP_CONTENT_DIR ) ) && file_exists( $file ) )
  792. include_once $file;
  793. if ( 0 < strlen( untrailingslashit( ABSPATH ) ) && 0 === strpos( $file, untrailingslashit( ABSPATH ) ) && file_exists( $file ) )
  794. include_once $file;
  795. }
  796. }
  797. if ( class_exists( $class_name ) )
  798. $class = new $class_name();
  799. else {
  800. $class = new PodsField();
  801. $class_name = 'PodsField';
  802. }
  803. $class_vars = get_class_vars( $class_name ); // PHP 5.2.x workaround
  804. self::$field_group = ( isset( $class_vars[ 'group' ] ) ? $class_vars[ 'group' ] : '' );
  805. self::$field_type = $class_vars[ 'type' ];
  806. self::$loaded[ $field_type ] =& $class;
  807. return self::$loaded[ $field_type ];
  808. }
  809. /**
  810. * Run a method from a Field Type's class
  811. *
  812. * @param string $field_type Field Type indentifier
  813. * @param string $method Method name
  814. * @param mixed $arg More arguments
  815. *
  816. * @return mixed
  817. * @access public
  818. * @static
  819. * @since 2.0
  820. */
  821. public static function field_method () {
  822. $args = func_get_args();
  823. if ( empty( $args ) && count( $args ) < 2 )
  824. return false;
  825. $field_type = array_shift( $args );
  826. $method = array_shift( $args );
  827. $class = self::field_loader( $field_type );
  828. if ( method_exists( $class, $method ) )
  829. return call_user_func_array( array( $class, $method ), $args );
  830. return false;
  831. }
  832. /**
  833. * Add a new Pod field type
  834. *
  835. * @param string $type The new field type identifier
  836. * @param string $file The new field type class file location
  837. *
  838. * @since 2.3
  839. */
  840. public static function register_field_type ( $type, $file = null ) {
  841. $field_type = pods_transient_get( 'pods_field_type_' . $type );
  842. if ( empty( $field_type ) || $field_type[ 'type' ] != $type || $field_type[ 'file' ] != $file ) {
  843. self::field_loader( $type, $file );
  844. $class_vars = get_class_vars( get_class( self::$loaded[ $type ] ) ); // PHP 5.2.x workaround
  845. self::$field_types[ $type ] = $class_vars;
  846. self::$field_types[ $type ][ 'file' ] = $file;
  847. pods_transient_set( 'pods_field_type_' . $type, self::$field_types[ $type ] );
  848. }
  849. else
  850. self::$field_types[ $type ] = $field_type;
  851. return self::$field_types[ $type ];
  852. }
  853. /**
  854. * Get a list of all available field types and include
  855. *
  856. * @return array
  857. *
  858. * @since 2.3
  859. */
  860. public static function field_types () {
  861. $field_types = array(
  862. 'text',
  863. 'website',
  864. 'phone',
  865. 'email',
  866. 'password',
  867. 'paragraph',
  868. 'wysiwyg',
  869. 'code',
  870. 'datetime',
  871. 'date',
  872. 'time',
  873. 'number',
  874. 'currency',
  875. 'file',
  876. 'avatar',
  877. 'pick',
  878. 'boolean',
  879. 'color',
  880. 'slug'
  881. );
  882. if ( pods_developer() && 1 == 0 ) // Disable for now
  883. $field_types[] = 'loop';
  884. $field_types = array_merge( $field_types, array_keys( self::$field_types ) );
  885. $field_types = array_filter( array_unique( $field_types ) );
  886. $types = apply_filters( 'pods_api_field_types', $field_types );
  887. $field_types = pods_transient_get( 'pods_field_types' );
  888. if ( empty( $field_types ) || count( $types ) != count( $field_types ) ) {
  889. $field_types = array();
  890. foreach ( $types as $field_type ) {
  891. $file = null;
  892. if ( isset( self::$field_types[ $field_type ] ) )
  893. $file = self::$field_types[ $field_type ][ 'file' ];
  894. self::field_loader( $field_type, $file );
  895. if ( !isset( self::$loaded[ $field_type ] ) || !is_object( self::$loaded[ $field_type ] ) )
  896. continue;
  897. $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) ); // PHP 5.2.x workaround
  898. $field_types[ $field_type ] = $class_vars;
  899. $field_types[ $field_type ][ 'file' ] = $file;
  900. }
  901. self::$field_types = $field_types;
  902. pods_transient_set( 'pods_field_types', self::$field_types );
  903. }
  904. else
  905. self::$field_types = array_merge( $field_types, self::$field_types );
  906. return self::$field_types;
  907. }
  908. public static function tableless_field_types () {
  909. $field_types = array( 'pick', 'file', 'avatar', 'taxonomy' );
  910. return apply_filters( 'pods_tableless_field_types', $field_types );
  911. }
  912. public static function file_field_types () {
  913. $field_types = array( 'file', 'avatar' );
  914. return apply_filters( 'pods_file_field_types', $field_types );
  915. }
  916. public static function repeatable_field_types () {
  917. $field_types = array( 'code', 'color', 'currency', 'date', 'datetime', 'email', 'number', 'paragraph', 'phone', 'text', 'time', 'website', 'wysiwyg' );
  918. return apply_filters( 'pods_repeatable_field_types', $field_types );
  919. }
  920. public static function number_field_types () {
  921. $field_types = array( 'currency', 'number' );
  922. return apply_filters( 'pods_tableless_field_types', $field_types );
  923. }
  924. public static function date_field_types () {
  925. $field_types = array( 'date', 'datetime', 'time' );
  926. return apply_filters( 'pods_tableless_field_types', $field_types );
  927. }
  928. public static function text_field_types () {
  929. $field_types = array( 'code', 'paragraph', 'slug','password', 'text', 'wysiwyg' );
  930. return apply_filters( 'pods_text_field_types', $field_types );
  931. }
  932. }