MC4WP_Form

Class MC4WP_Form.

Defined (1)

The class is defined in the following location(s).

/includes/class-form.php  
  1. class MC4WP_Form { 
  2.  
  3. /** 
  4. * @var MC4WP_Form 
  5. */ 
  6. private static $instance; 
  7.  
  8. /** 
  9. * @param iMC4WP_Request $request 
  10. * @return MC4WP_Form|null 
  11. */ 
  12. public static function get( iMC4WP_Request $request = null ) { 
  13.  
  14. // has instance been created already? 
  15. if( self::$instance ) { 
  16. $form = self::$instance; 
  17. } else { 
  18. // create a new instance 
  19. $form = new MC4WP_Form( $request ); 
  20. self::$instance = $form; 
  21.  
  22. // attach request to form 
  23. if( $request && ! $form->has_request( $request ) ) { 
  24. $form->attach_request( $request ); 
  25.  
  26. return $form; 
  27.  
  28.  
  29. /** 
  30. * @var int 
  31. */ 
  32. public $ID = 0; 
  33.  
  34. /** 
  35. * @var string 
  36. */ 
  37. public $content = ''; 
  38.  
  39. /** 
  40. * @var array 
  41. */ 
  42. public $settings = array(); 
  43.  
  44. /** 
  45. * @var iMC4WP_Request 
  46. */ 
  47. public $request; 
  48.  
  49. /** 
  50. * @param iMC4WP_Request $request 
  51. */ 
  52. private function __construct( iMC4WP_Request $request = null ) { 
  53. $this->ID = 0; 
  54. $this->name = 'Default Form'; 
  55. $this->settings = $this->load_settings(); 
  56. $this->content = $this->settings['markup']; 
  57. $this->request = $request; 
  58.  
  59. /** 
  60. * Simple check to see if form contains a given field type 
  61. * @param $field_type 
  62. * @return bool 
  63. */ 
  64. public function contains_field_type( $field_type ) { 
  65. $html = sprintf( ' type="%s" ', $field_type ); 
  66. return stristr( $this->content, $html ) !== false; 
  67.  
  68.  
  69. /** 
  70. * @param string $element_id 
  71. * @param array $attributes 
  72. * @param string $response_html 
  73. * @return string 
  74. */ 
  75. public function get_visible_fields( $element_id, array $attributes = array(), $response_html = '' ) { 
  76.  
  77. $replacements = array( 
  78. '{n}' => $element_id,  
  79. '{response}' => $response_html,  
  80. ); 
  81.  
  82. $visible_fields = MC4WP_Tools::replace_variables( $this->content, $replacements, array_values( $this->settings['lists'] ) ); 
  83.  
  84. // insert captcha 
  85. if( function_exists( 'cptch_display_captcha_custom' ) ) { 
  86. $captcha_fields = '<input type="hidden" name="_mc4wp_has_captcha" value="1" /><input type="hidden" name="cntctfrm_contact_action" value="true" />' . cptch_display_captcha_custom(); 
  87. $visible_fields = str_ireplace( array( '{captcha}', '[captcha]' ), $captcha_fields, $visible_fields ); 
  88.  
  89. /** 
  90. * @filter mc4wp_form_content 
  91. * @param int $form_id The ID of the form that is being shown 
  92. * @expects string 
  93. * Can be used to customize the content of the form mark-up, eg adding additional fields. 
  94. */ 
  95. $visible_fields = (string) apply_filters( 'mc4wp_form_content', $visible_fields, $this->ID ); 
  96.  
  97. return $visible_fields; 
  98.  
  99. /** 
  100. * @param string $element_id 
  101. * @param array $attributes Attributes passed to the shortcode 
  102. * @return string 
  103. */ 
  104. public function get_hidden_fields( $element_id, $attributes = array() ) { 
  105.  
  106. // hidden fields 
  107. $hidden_fields = '<div style="position: absolute; left:-5000px;"><input type="text" name="_mc4wp_required_but_not_really" value="" tabindex="-1" /></div>'; 
  108. $hidden_fields .= '<input type="hidden" name="_mc4wp_timestamp" value="'. time() . '" />'; 
  109. $hidden_fields .= '<input type="hidden" name="_mc4wp_form_id" value="'. $this->ID .'" />'; 
  110. $hidden_fields .= '<input type="hidden" name="_mc4wp_form_element_id" value="'. esc_attr( $element_id ) .'" />'; 
  111. $hidden_fields .= '<input type="hidden" name="_mc4wp_form_submit" value="1" />'; 
  112. $hidden_fields .= '<input type="hidden" name="_mc4wp_form_nonce" value="'. wp_create_nonce( '_mc4wp_form_nonce' ) .'" />'; 
  113.  
  114.  
  115. // was "lists" parameter passed in shortcode arguments? 
  116. if( isset( $attributes['lists'] ) && ! empty( $attributes['lists'] ) ) { 
  117. $lists_string = ( is_array( $attributes['lists'] ) ) ? join( ', ', $attributes['lists'] ) : $attributes['lists']; 
  118. $hidden_fields .= '<input type="hidden" name="_mc4wp_lists" value="'. $lists_string . '" />'; 
  119.  
  120. return (string) $hidden_fields; 
  121.  
  122. /** 
  123. * Is this form submitted? 
  124. * @param string $element_id 
  125. * @return bool 
  126. */ 
  127. public function is_submitted( $element_id = null ) { 
  128.  
  129. // is this form (any instance) submitted) 
  130. $form_submitted = $this->request instanceof iMC4WP_Request; 
  131.  
  132. // if an element ID is given, only return true if that specific element is submitted 
  133. if( $element_id ) { 
  134. return ( $form_submitted && $this->request->form_element_id == $element_id ); 
  135.  
  136. return $form_submitted; 
  137.  
  138. /** 
  139. * @return string 
  140. */ 
  141. protected function get_response_position() { 
  142.  
  143. /** 
  144. * @deprecated 
  145. * @use `mc4wp_form_response_position` instead 
  146. */ 
  147. $message_position = (string) apply_filters( 'mc4wp_form_message_position', 'after' ); 
  148.  
  149. /** 
  150. * @filter mc4wp_form_message_position 
  151. * @expects string before|after 
  152. * Can be used to change the position of the form success & error messages. 
  153. * Valid options are 'before' or 'after' 
  154. */ 
  155. $response_position = (string) apply_filters( 'mc4wp_form_response_position', $message_position ); 
  156.  
  157. // check if content contains {response} tag 
  158. if( stripos( $this->content, '{response}' ) !== false ) { 
  159. $response_position = ''; 
  160.  
  161. return $response_position; 
  162.  
  163. /** 
  164. * @param string $response_html 
  165. * @return string 
  166. */ 
  167. protected function get_html_before_fields( $response_html = '' ) { 
  168. $before_fields = (string) apply_filters( 'mc4wp_form_before_fields', '' ); 
  169.  
  170. if( $this->get_response_position() === 'before' ) { 
  171. $before_fields = $response_html . $response_html; 
  172.  
  173. return $before_fields; 
  174.  
  175. /** 
  176. * @param string $response_html 
  177. * @return string 
  178. */ 
  179. protected function get_html_after_fields( $response_html = '' ) { 
  180. $after_fields = (string) apply_filters( 'mc4wp_form_after_fields', '' ); 
  181.  
  182. if( $this->get_response_position() === 'after' ) { 
  183. $after_fields = $response_html . $after_fields; 
  184.  
  185. return $after_fields; 
  186.  
  187. /** 
  188. * @param string $element_id 
  189. * @param array $attributes 
  190. * @return string 
  191. */ 
  192. public function generate_html( $element_id = 'mc4wp-form', array $attributes = array() ) { 
  193.  
  194. // generate response html 
  195. $response_html = ( $this->is_submitted( $element_id ) ) ? $this->request->get_response_html() : ''; 
  196.  
  197. // Some vars we might fill later on 
  198. $form_opening_html = ''; 
  199. $form_closing_html = ''; 
  200. $visible_fields = ''; 
  201. $hidden_fields = ''; 
  202.  
  203. // Start building content string 
  204. $opening_html = '<!-- MailChimp for WordPress v' . MC4WP_LITE_VERSION . ' - https://wordpress.org/plugins/mailchimp-for-wp/ -->'; 
  205. $opening_html .= '<div id="' . esc_attr( $element_id ) . '" class="' . esc_attr( $this->get_css_classes( $element_id ) ) . '">'; 
  206. $before_fields = apply_filters( 'mc4wp_form_before_fields', '' ); 
  207. $after_fields = apply_filters( 'mc4wp_form_after_fields', '' ); 
  208. $before_form = $this->get_html_before_fields( $response_html ); 
  209. $after_form = $this->get_html_after_fields( $response_html ); 
  210. $closing_html = '</div><!-- / MailChimp for WordPress Plugin -->'; 
  211.  
  212. // only generate form & fields HTML if necessary 
  213. if( ! $this->is_submitted( $element_id ) 
  214. || ! $this->settings['hide_after_success'] 
  215. || ! $this->request->success ) { 
  216.  
  217. $form_opening_html = '<form method="post">'; 
  218. $visible_fields = $this->get_visible_fields( $element_id, $attributes, $response_html ); 
  219. $hidden_fields = $this->get_hidden_fields( $element_id, $attributes ); 
  220. $form_closing_html = '</form>'; 
  221.  
  222. ob_start(); 
  223.  
  224. // echo HTML parts of form 
  225. echo $opening_html; 
  226. echo $before_form; 
  227. echo $form_opening_html; 
  228. echo $before_fields; 
  229. echo $visible_fields; 
  230. echo $hidden_fields; 
  231. echo $after_fields; 
  232. echo $form_closing_html; 
  233. echo $after_form; 
  234. echo $closing_html; 
  235.  
  236. $output = ob_get_contents(); 
  237. ob_end_clean(); 
  238.  
  239. return $output; 
  240.  
  241. /** 
  242. * @param string $element_id 
  243. * @param array $attributes 
  244. * @param bool $echo 
  245. * @return string 
  246. */ 
  247. public function output( $element_id = 'mc4wp-form', array $attributes = array(), $echo = true ) { 
  248.  
  249. $html = $this->generate_html( $element_id, $attributes ); 
  250.  
  251. if( $echo ) { 
  252. echo $html; 
  253.  
  254. return $html; 
  255.  
  256.  
  257. /** 
  258. * Get a space separated list of CSS classes for this form 
  259. * @param string $element_id 
  260. * @return string 
  261. */ 
  262. public function get_css_classes( $element_id ) { 
  263.  
  264. /** 
  265. * @filter mc4wp_form_css_classes 
  266. * @expects array 
  267. * Can be used to add additional CSS classes to the form container 
  268. */ 
  269. $css_classes = apply_filters( 'mc4wp_form_css_classes', array( 'form' ), $this ); 
  270.  
  271. // the following classes MUST be used 
  272. $css_classes[] = 'mc4wp-form'; 
  273.  
  274. // Add form classes if this specific form instance was submitted 
  275. if( $this->is_submitted( $element_id ) ) { 
  276.  
  277. $css_classes[] = 'mc4wp-form-submitted'; 
  278.  
  279. if( $this->request->success ) { 
  280. $css_classes[] = 'mc4wp-form-success'; 
  281. } else { 
  282. $css_classes[] = 'mc4wp-form-error'; 
  283.  
  284.  
  285. return implode( ' ', $css_classes ); 
  286.  
  287. /** 
  288. * @return array 
  289. */ 
  290. public function load_settings() { 
  291. return mc4wp_get_options( 'form' ); 
  292.  
  293. /** 
  294. * Returns the various error and success messages in array format 
  295. * Example: 
  296. * array( 
  297. * 'invalid_email' => array( 
  298. * 'type' => 'css-class',  
  299. * 'text' => 'Message text' 
  300. * ),  
  301. * ... 
  302. * ); 
  303. * @return array 
  304. */ 
  305. public function get_messages() { 
  306.  
  307. $messages = array( 
  308.  
  309. // email was successfully subscribed to the selected list(s) 
  310. 'subscribed' => array( 
  311. 'type' => 'success',  
  312. 'text' => $this->settings['text_subscribed'],  
  313. ),  
  314.  
  315. // email was successfully unsubscribed from the selected list(s) 
  316. 'unsubscribed' => array( 
  317. 'type' => 'success',  
  318. 'text' => $this->settings['text_unsubscribed'],  
  319. ),  
  320.  
  321. // a general (unknown) error occurred 
  322. 'error' => array( 
  323. 'type' => 'error',  
  324. 'text' => $this->settings['text_error'],  
  325. ),  
  326.  
  327. // an invalid email was given 
  328. 'invalid_email' => array( 
  329. 'type' => 'error',  
  330. 'text' => $this->settings['text_invalid_email'],  
  331. ),  
  332.  
  333. // the captcha was not filled correctly 
  334. 'invalid_captcha' => array( 
  335. 'type' => 'error',  
  336. 'text' => $this->settings['text_invalid_captcha'],  
  337. ),  
  338.  
  339. // a required field is missing for the selected list(s) 
  340. 'required_field_missing' => array( 
  341. 'type' => 'error',  
  342. 'text' => $this->settings['text_required_field_missing'],  
  343. ),  
  344.  
  345. // email is already subscribed to the selected list(s) 
  346. 'already_subscribed' => array( 
  347. 'type' => 'notice',  
  348. 'text' => $this->settings['text_already_subscribed'],  
  349. ),  
  350.  
  351. // email is not subscribed on the selected list(s) 
  352. 'not_subscribed' => array( 
  353. 'type' => 'notice',  
  354. 'text' => $this->settings['text_not_subscribed'],  
  355. ),  
  356. ); 
  357.  
  358. /** 
  359. * @filter mc4wp_form_messages 
  360. * @expects array 
  361. * Allows registering custom form messages, useful if you're using custom validation using the `mc4wp_valid_form_request` filter. 
  362. */ 
  363. $messages = apply_filters( 'mc4wp_form_messages', $messages, $this->ID ); 
  364.  
  365. return (array) $messages; 
  366.  
  367. /** 
  368. * @param iMC4WP_Request $request 
  369. * @return bool 
  370. */ 
  371. protected function has_request( iMC4WP_Request $request ) { 
  372. return $this->request === $request; 
  373.  
  374. /** 
  375. * @param iMC4WP_Request $request 
  376. */ 
  377. protected function attach_request( iMC4WP_Request $request ) { 
  378. $this->request = $request; 
  379.