class-simple-job-board-ajax.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. <?php if (!defined('ABSPATH')) { exit; } // Exit if accessed directly
  2. /**
  3. * Simple_Job_Board_Ajax class
  4. *
  5. * This file includes the ajax call for:
  6. *
  7. * - Uploading resume validation
  8. * - Storing applicant data on job submit.
  9. *
  10. * @link https://wordpress.org/plugins/simple-job-board
  11. * @since 2.1.0
  12. * @since 2.2.3 Code Optimization
  13. * @since 2.4.0 Revised the Nonce Field Checks & Revised the Input/Output Sanitization & Escaping
  14. * @since 2.5.0 Added "new" status for job application.
  15. *
  16. * @package Simple_Job_Board
  17. * @subpackage Simple_Job_Board/includes
  18. * @author PressTigers <support@presstigers.com>
  19. */
  20. class Simple_Job_Board_Ajax {
  21. /**
  22. * Base directory of uploaded resume.
  23. *
  24. * @since 2.2.3
  25. * @access private
  26. * @var Simple_Job_Board_Ajax $upload_basedir Store the base directory of uploaded resume.
  27. */
  28. private $upload_basedir;
  29. /**
  30. * Base url of uploaded resume.
  31. *
  32. * @since 2.2.3
  33. * @access private
  34. * @var Simple_Job_Board_Ajax $upload_baseurl Store the base url of uploaded resume.
  35. */
  36. private $upload_baseurl;
  37. /**
  38. * Flag to indicate the error while uploading file
  39. *
  40. * @since 2.2.3
  41. * @access private
  42. * @var Simple_Job_Board_Ajax $upload_file_error Store error indicator during file upload.
  43. */
  44. private $upload_file_error_indicator;
  45. /**
  46. * Uploaded file error message
  47. *
  48. * @since 2.2.3
  49. * @access private
  50. * @var Simple_Job_Board_Ajax $upload_file_error Store error message of file upload.
  51. */
  52. private $upload_file_error = array();
  53. /**
  54. * The name of uploaded file
  55. *
  56. * @since 2.2.3
  57. * @access private
  58. * @var Simple_Job_Board_Ajax $upload_file_name Store the name of uploaded file.
  59. */
  60. private $upload_file_name = array();
  61. /**
  62. * Constructor
  63. */
  64. public function __construct() {
  65. $this->upload_file_error_indicator = 0;
  66. // Hook - Entertain Applicant Request From Job Apply Form
  67. add_action( 'wp_ajax_nopriv_process_applicant_form', array($this, 'process_applicant_form') );
  68. add_action( 'wp_ajax_process_applicant_form', array($this, 'process_applicant_form') );
  69. // Hook - Uploaded Resume Validation
  70. add_action( 'sjb_uploaded_resume_validation', array($this, 'uploaded_resume_validation') );
  71. }
  72. /**
  73. * Entertain Applicant Request From Job Apply Form
  74. *
  75. * @access public
  76. * @return void
  77. */
  78. public function process_applicant_form() {
  79. check_ajax_referer( 'jobpost_security_nonce', 'wp_nonce' );
  80. /**
  81. * Fires on job submission
  82. *
  83. * @since 2.2.3
  84. */
  85. do_action('sjb_uploaded_resume_validation');
  86. if ( 1 == $this->upload_file_error_indicator ) {
  87. $errors = '<div class="clearfix"></div><div class="alert alert-danger" role="alert">';
  88. foreach ( $this->upload_file_error as $error_value ) {
  89. $errors .= esc_html__($error_value, 'simple-job-board');
  90. }
  91. $response = json_encode(apply_filters( 'sjb_job_submission_validation_error' , array('success' => FALSE, 'error' => $errors), $errors));
  92. header( "Content-Type: application/json" );
  93. echo apply_filters( 'sjb_job_submit_validation_errors', $response );
  94. die();
  95. }
  96. /**
  97. * Fires before inserting applicant's post.
  98. *
  99. * @since 2.2.3
  100. */
  101. do_action( 'sjb_applicants_insert_post_before' );
  102. $parent_id = filter_input( INPUT_POST, 'job_id' );
  103. $args = apply_filters('sjb_applicant_insert_post_args', array(
  104. 'post_type' => 'jobpost_applicants',
  105. 'post_content' => '',
  106. 'post_parent' => intval( $parent_id ),
  107. 'post_title' => trim( esc_html( strip_tags( get_the_title( $parent_id ) ) ) ),
  108. 'post_status' => 'publish',
  109. ));
  110. $pid = wp_insert_post($args);
  111. /**
  112. * Fires before inserting applicant's post meta.
  113. *
  114. * @since 2.2.3
  115. */
  116. do_action( 'sjb_applicants_insert_post_meta_start', $pid );
  117. /**
  118. * Attachment's Manipulation:
  119. *
  120. * - Prepend Applicant Id with File Name
  121. * - Rename File
  122. * - Store File's Meta in DB
  123. */
  124. if ( !empty( $_FILES ) ) {
  125. $upload_files_name = array();
  126. $count = 0;
  127. // Rename File
  128. foreach ( $_FILES as $key => $val ) {
  129. // Prepend Applicant Id with File Name
  130. $resume_name = $pid . '_' . sanitize_file_name( $this->upload_file_name[$count]);
  131. $resume_path = $this->upload_basedir . '/' . $resume_name;
  132. rename($this->upload_basedir. '/' . $this->upload_file_name[$count], $resume_path);
  133. $upload_files_name[] = ( '' != $val['name'] ) ? $resume_name : '';
  134. $count++;
  135. }
  136. // Keep Resume Meta for Backward Compatibility
  137. if( !empty( $_FILES['applicant_resume'] ) ) {
  138. // Get Resume Attachment
  139. $resume_name = array_pop( $upload_files_name );
  140. if( $resume_name ) {
  141. $resume_url = $this->upload_baseurl . '/' . $resume_name;
  142. $resume_path = $this->upload_basedir . '/' . $resume_name;
  143. /* Replace single backslash with double for DB Storage */
  144. $resume_path = str_replace("\\", "\\\\", $resume_path);
  145. add_post_meta($pid, 'resume', $resume_url);
  146. add_post_meta($pid, 'resume_path', $resume_path);
  147. }
  148. }
  149. // Store Meta if Multiple Attachments
  150. if( !empty( $upload_files_name ) ) {
  151. // Replace single backslash with double for DB Storage
  152. $file_path = str_replace( "\\", "\\\\", $this->upload_basedir );
  153. $file_meta = array (
  154. 'base_dir' => $file_path,
  155. 'base_url' => $this->upload_baseurl,
  156. 'file_name' => $upload_files_name,
  157. );
  158. // Store Attachments' Meta
  159. add_post_meta( $pid, 'attachments_meta', $file_meta );
  160. }
  161. }
  162. // Add post meta with for application status
  163. add_post_meta( $pid, 'sjb_jobapp_status', 'new' );
  164. $POST_data = filter_input_array( INPUT_POST );
  165. // Save Applicant Details
  166. foreach ( $POST_data as $key => $val ):
  167. if (substr($key, 0, 7) == 'jobapp_'):
  168. $val = is_array( $val ) ? serialize( $val ) : $val;
  169. add_post_meta( $pid, $key, sanitize_text_field( $val ) );
  170. endif;
  171. endforeach;
  172. /**
  173. * Fires after inserting applicant's post meta.
  174. *
  175. * @since 2.2.3
  176. */
  177. do_action( 'sjb_applicants_insert_post_meta_end', $pid );
  178. $success_alert = '<div class="clearfix"></div><div class="alert alert-success" role="alert">'. apply_filters( 'sjb_job_submission_alert', __('Your application has been received. We will get back to you soon.', 'simple-job-board') ) .'</div>';
  179. // Generate Response
  180. $response = ( $pid > 0 ) ? json_encode( array( 'success' => TRUE, 'success_alert' => $success_alert) ) : json_encode( array( 'success' => FALSE ) );
  181. // Output Response
  182. header("Content-Type: application/json");
  183. echo $response;
  184. // Admin Notification
  185. if ( 'yes' === get_option( 'job_board_admin_notification' ) )
  186. Simple_Job_Board_Notifications::admin_notification( $pid );
  187. // HR Notification
  188. if ( ('yes' === get_option( 'job_board_hr_notification' ) ) )
  189. Simple_Job_Board_Notifications::hr_notification( $pid );
  190. // Applicant Notification
  191. if ( 'yes' === get_option( 'job_board_applicant_notification' ) )
  192. Simple_Job_Board_Notifications::applicant_notification( $pid );
  193. /**
  194. * Fires after sending notifications on job submission page.
  195. *
  196. * @since 2.2.3
  197. */
  198. do_action( 'sjb_admin_notices_after', $pid );
  199. exit();
  200. }
  201. /**
  202. * Uploaded Resume Validation
  203. *
  204. * @since 2.2.3
  205. */
  206. public function uploaded_resume_validation() {
  207. /**
  208. * Fires before uploaded resume validation.
  209. *
  210. * @since 2.2.3
  211. */
  212. do_action('sjb_uploaded_resume_validation_before');
  213. if(isset($_FILES)) {
  214. foreach ( $_FILES as $file ) {
  215. // Check the File Existance
  216. if (strlen($file['name']) > 3) {
  217. if (is_array( $file )) {
  218. // WP Upload Directory
  219. $upload_dir = wp_upload_dir();
  220. // Allowable File Size
  221. $assignment_upload_size = 200;
  222. $time = (!empty($_SERVER['REQUEST_TIME'])) ? $_SERVER['REQUEST_TIME'] : (time() + (get_option('gmt_offset') * 3600)); // Fallback of now
  223. $post_type = 'jobpost';
  224. // Getting Current Date
  225. $date = explode(" ", date('Y m d H i s', $time));
  226. $timestamp = strtotime(date('Y m d H i s'));
  227. if ($post_type) {
  228. $upload_dir = array(
  229. 'path' => $upload_dir['basedir'] . '/' . $post_type . '/' . $date[0],
  230. 'url' => $upload_dir['baseurl'] . '/' . $post_type . '/' . $date[0],
  231. 'subdir' => '',
  232. 'error' => FALSE,
  233. );
  234. }
  235. // Make Upload Directory
  236. if (!is_dir($upload_dir['path'])) {
  237. wp_mkdir_p($upload_dir['path']);
  238. }
  239. // Uploaded File Parameters
  240. $uploadfiles = array(
  241. 'name' => $file['name'],
  242. 'type' => $file['type'],
  243. 'tmp_name' => $file['tmp_name'],
  244. 'error' => $file['error'],
  245. 'size' => $file['size'],
  246. );
  247. // Look only for uploded files
  248. if ( 0 == $uploadfiles['error'] ) {
  249. $filetmp = $uploadfiles['tmp_name'];
  250. $filesize = $uploadfiles['size'];
  251. $max_upload_size = $assignment_upload_size * 1048576; // Megabytes to Bytes conversion
  252. // Check Uploaded File Size
  253. if ( $max_upload_size < $filesize ) {
  254. $this->upload_file_error[] = esc_html__('Maximum upload File size allowed ' . $assignment_upload_size . 'MB.', 'simple-job-board');
  255. $this->upload_file_error_indicator = 1;
  256. }
  257. /** Get file info
  258. * @fixme: wp checks the file extension
  259. */
  260. $filetype = wp_check_filetype(basename($uploadfiles['name']), NULL);
  261. $file_ext = strtolower($filetype['ext']);
  262. $filetitle = preg_replace('/\.[^.]+$/', '', basename($uploadfiles['name']));
  263. $uploadfiles['name'] = $filetitle . $timestamp . '.' . $file_ext;
  264. /**
  265. * Check if the filename already exist in the directory & rename
  266. * the file if necessary
  267. */
  268. $i = 0;
  269. while ( file_exists( $upload_dir['path'] . '/' . $uploadfiles['name'] ) ) {
  270. $uploadfiles['name'] = $filetitle . $timestamp . '_' . $i . '.' . $file_ext;
  271. $i++;
  272. }
  273. $filedest = $upload_dir['path'] . '/' . $uploadfiles['name'];
  274. // Check Write Permissions
  275. if (!is_writeable($upload_dir['path'])) {
  276. $this->upload_file_error[] = 'Unable to write to directory %s. Is this directory writable by the server?';
  277. $this->upload_file_error_indicator = 1;
  278. }
  279. // Check valid file extensions
  280. $allowed_file_exts = get_option('job_board_allowed_extensions');
  281. $settings_file_exts = get_option('job_board_upload_file_ext');
  282. // Selection of Setting Extension
  283. $file_extension = ( ( 'yes' === get_option('job_board_all_extensions_check') ) || ( NULL == $settings_file_exts ) ) ? $allowed_file_exts : $settings_file_exts;
  284. if (!in_array($file_ext, $file_extension)) {
  285. $this->upload_file_error[] = esc_html__( $uploadfiles['name'] . ' is not an allowed file type.', 'simple-job-board');
  286. $this->upload_file_error_indicator = 1;
  287. }
  288. // Save Temporary File to Uploads Dir
  289. if ($this->upload_file_error_indicator <> 1) {
  290. if (!@move_uploaded_file($filetmp, $filedest)) {
  291. $this->upload_file_error[] = 'Error, the file $filetmp could not moved to : $filedest .';
  292. $this->upload_file_error_indicator = 1;
  293. }
  294. // Upload Base Path & URL
  295. $this->upload_baseurl = $upload_dir['url'];
  296. $this->upload_basedir = $upload_dir['path'];
  297. }
  298. }
  299. }
  300. }
  301. $this->upload_file_name[] = $uploadfiles['name'];
  302. }
  303. }
  304. /**
  305. * Fires after uploaded resume validation.
  306. *
  307. * @since 2.2.3
  308. */
  309. do_action('sjb_uploaded_resume_validation_after');
  310. }
  311. }
  312. new Simple_Job_Board_Ajax();