PluginProbe
WP Job Manager / 1.31.2
WP Job Manager v1.31.2
2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.1.0 1.1.1 1.1.2 1.1.3 1.10.0 1.11.0 1.11.1 1.12.0 1.12.1 1.13.0 1.14.0 1.15.0 All 154 releases
wp-job-manager / wp-job-manager.php
wp-job-manager.php
469 lines 17.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: WP Job Manager
4 * Plugin URI: https://wpjobmanager.com/
5 * Description: Manage job listings from the WordPress admin panel, and allow users to post jobs directly to your site.
6 * Version: 1.31.2
7 * Author: Automattic
8 * Author URI: https://wpjobmanager.com/
9 * Requires at least: 4.7.0
10 * Tested up to: 4.9
11 * Text Domain: wp-job-manager
12 * Domain Path: /languages/
13 * License: GPL2+
14 *
15 * @package wp-job-manager
16 */
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit;
20 }
21
22 /**
23 * Handles core plugin hooks and action setup.
24 *
25 * @package wp-job-manager
26 * @since 1.0.0
27 */
28 class WP_Job_Manager {
29 /**
30 * The single instance of the class.
31 *
32 * @var self
33 * @since 1.26.0
34 */
35 private static $_instance = null;
36
37 /**
38 * REST API instance.
39 *
40 * @var WP_Job_Manager_REST_API
41 */
42 private $rest_api = null;
43
44 /**
45 * Main WP Job Manager Instance.
46 *
47 * Ensures only one instance of WP Job Manager is loaded or can be loaded.
48 *
49 * @since 1.26.0
50 * @static
51 * @see WPJM()
52 * @return self Main instance.
53 */
54 public static function instance() {
55 if ( is_null( self::$_instance ) ) {
56 self::$_instance = new self();
57 }
58 return self::$_instance;
59 }
60
61 /**
62 * Constructor.
63 */
64 public function __construct() {
65 // Define constants.
66 define( 'JOB_MANAGER_VERSION', '1.31.2' );
67 define( 'JOB_MANAGER_MINIMUM_WP_VERSION', '4.7.0' );
68 define( 'JOB_MANAGER_PLUGIN_DIR', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
69 define( 'JOB_MANAGER_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
70 define( 'JOB_MANAGER_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
71
72 // Includes.
73 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-install.php';
74 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-post-types.php';
75 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-ajax.php';
76 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-shortcodes.php';
77 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-api.php';
78 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-forms.php';
79 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-geocode.php';
80 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-cache-helper.php';
81 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/helper/class-wp-job-manager-helper.php';
82 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/abstracts/abstract-wp-job-manager-email.php';
83 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/abstracts/abstract-wp-job-manager-email-template.php';
84 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-email-notifications.php';
85 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-data-exporter.php';
86
87 add_action( 'rest_api_init', array( $this, 'rest_api' ) );
88
89 if ( is_admin() ) {
90 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/admin/class-wp-job-manager-admin.php';
91 }
92
93 // Load 3rd party customizations.
94 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/3rd-party.php';
95
96 // Init classes.
97 $this->forms = WP_Job_Manager_Forms::instance();
98 $this->post_types = WP_Job_Manager_Post_Types::instance();
99
100 // Schedule cron jobs.
101 self::maybe_schedule_cron_jobs();
102
103 // Activation - works with symlinks.
104 register_activation_hook( basename( dirname( __FILE__ ) ) . '/' . basename( __FILE__ ), array( $this, 'activate' ) );
105
106 // Switch theme.
107 add_action( 'after_switch_theme', array( 'WP_Job_Manager_Ajax', 'add_endpoint' ), 10 );
108 add_action( 'after_switch_theme', array( $this->post_types, 'register_post_types' ), 11 );
109 add_action( 'after_switch_theme', 'flush_rewrite_rules', 15 );
110
111 // Actions.
112 add_action( 'after_setup_theme', array( $this, 'load_plugin_textdomain' ) );
113 add_action( 'after_setup_theme', array( $this, 'include_template_functions' ), 11 );
114 add_action( 'widgets_init', array( $this, 'widgets_init' ) );
115 add_action( 'wp_loaded', array( $this, 'register_shared_assets' ) );
116 add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
117 add_action( 'admin_init', array( $this, 'updater' ) );
118 add_action( 'admin_init', array( $this, 'add_privacy_policy_content' ) );
119 add_action( 'wp_logout', array( $this, 'cleanup_job_posting_cookies' ) );
120 add_action( 'init', array( 'WP_Job_Manager_Email_Notifications', 'init' ) );
121
122 // Filters.
123 add_filter( 'wp_privacy_personal_data_exporters', array( 'WP_Job_Manager_Data_Exporter', 'register_wpjm_user_data_exporter' ) );
124
125 add_action( 'init', array( $this, 'usage_tracking_init' ) );
126 register_deactivation_hook( __FILE__, array( $this, 'usage_tracking_cleanup' ) );
127
128 // Other cleanup.
129 register_deactivation_hook( __FILE__, array( $this, 'unschedule_cron_jobs' ) );
130
131 // Defaults for WPJM core actions.
132 add_action( 'wpjm_notify_new_user', 'wp_job_manager_notify_new_user', 10, 2 );
133 }
134
135 /**
136 * Performs plugin activation steps.
137 */
138 public function activate() {
139 WP_Job_Manager_Ajax::add_endpoint();
140 unregister_post_type( 'job_listing' );
141 add_filter( 'pre_option_job_manager_enable_types', '__return_true' );
142 $this->post_types->register_post_types();
143 remove_filter( 'pre_option_job_manager_enable_types', '__return_true' );
144 WP_Job_Manager_Install::install();
145 flush_rewrite_rules();
146 }
147
148 /**
149 * Handles tasks after plugin is updated.
150 */
151 public function updater() {
152 if ( version_compare( JOB_MANAGER_VERSION, get_option( 'wp_job_manager_version' ), '>' ) ) {
153 WP_Job_Manager_Install::install();
154 flush_rewrite_rules();
155 }
156 }
157
158 /**
159 * Adds Privacy Policy suggested content.
160 */
161 public function add_privacy_policy_content() {
162 if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) {
163 return;
164 }
165
166 $content = sprintf(
167 // translators: Placeholders %1$s and %2$s are the names of the two cookies used in WP Job Manager.
168 __( 'This site adds the following cookies to help users resume job submissions that they
169 have started but have not completed: %1$s and %2$s', 'wp-job-manager'
170 ),
171 '<code>wp-job-manager-submitting-job-id</code>', '<code>wp-job-manager-submitting-job-key</code>'
172 );
173
174 wp_add_privacy_policy_content(
175 'WP Job Manager',
176 wp_kses_post( wpautop( $content, false ) )
177 );
178 }
179
180 /**
181 * Loads textdomain for plugin.
182 */
183 public function load_plugin_textdomain() {
184 load_textdomain( 'wp-job-manager', WP_LANG_DIR . '/wp-job-manager/wp-job-manager-' . apply_filters( 'plugin_locale', get_locale(), 'wp-job-manager' ) . '.mo' );
185 load_plugin_textdomain( 'wp-job-manager', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
186 }
187
188 /**
189 * Initialize our REST API.
190 *
191 * @return WP_Job_Manager_REST_API|WP_Error
192 */
193 public function rest_api() {
194 if ( null === $this->rest_api ) {
195 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/rest-api/class-wp-job-manager-rest-api.php';
196 $this->rest_api = new WP_Job_Manager_REST_API( dirname( __FILE__ ) );
197 }
198 return $this->rest_api;
199 }
200
201 /**
202 * Loads plugin's core helper template functions.
203 */
204 public function include_template_functions() {
205 include_once JOB_MANAGER_PLUGIN_DIR . '/wp-job-manager-deprecated.php';
206 include_once JOB_MANAGER_PLUGIN_DIR . '/wp-job-manager-functions.php';
207 include_once JOB_MANAGER_PLUGIN_DIR . '/wp-job-manager-template.php';
208 }
209
210 /**
211 * Loads plugin's widgets.
212 */
213 public function widgets_init() {
214 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-widget.php';
215 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/widgets/class-wp-job-manager-widget-recent-jobs.php';
216 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/widgets/class-wp-job-manager-widget-featured-jobs.php';
217 }
218
219 /**
220 * Initialize the Usage Tracking system.
221 */
222 public function usage_tracking_init() {
223 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-usage-tracking.php';
224 include_once JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-usage-tracking-data.php';
225
226 WP_Job_Manager_Usage_Tracking::get_instance()->set_callback(
227 array( 'WP_Job_Manager_Usage_Tracking_Data', 'get_usage_data' )
228 );
229 WP_Job_Manager_Usage_Tracking::get_instance()->schedule_tracking_task();
230 }
231
232 /**
233 * Cleanup the Usage Tracking system for plugin deactivation.
234 */
235 public function usage_tracking_cleanup() {
236 WP_Job_Manager_Usage_Tracking::get_instance()->unschedule_tracking_task();
237 }
238
239 /**
240 * Schedule cron jobs for WPJM events.
241 */
242 public static function maybe_schedule_cron_jobs() {
243 if ( ! wp_next_scheduled( 'job_manager_check_for_expired_jobs' ) ) {
244 wp_schedule_event( time(), 'hourly', 'job_manager_check_for_expired_jobs' );
245 }
246 if ( ! wp_next_scheduled( 'job_manager_delete_old_previews' ) ) {
247 wp_schedule_event( time(), 'daily', 'job_manager_delete_old_previews' );
248 }
249 if ( ! wp_next_scheduled( 'job_manager_clear_expired_transients' ) ) {
250 wp_schedule_event( time(), 'twicedaily', 'job_manager_clear_expired_transients' );
251 }
252 if ( ! wp_next_scheduled( 'job_manager_email_daily_notices' ) ) {
253 wp_schedule_event( time(), 'daily', 'job_manager_email_daily_notices' );
254 }
255 }
256
257 /**
258 * Unschedule cron jobs. This is run on plugin deactivation.
259 */
260 public static function unschedule_cron_jobs() {
261 wp_clear_scheduled_hook( 'job_manager_check_for_expired_jobs' );
262 wp_clear_scheduled_hook( 'job_manager_delete_old_previews' );
263 wp_clear_scheduled_hook( 'job_manager_clear_expired_transients' );
264 wp_clear_scheduled_hook( 'job_manager_email_daily_notices' );
265 }
266
267 /**
268 * Cleanup job posting cookies.
269 */
270 public function cleanup_job_posting_cookies() {
271 if ( isset( $_COOKIE['wp-job-manager-submitting-job-id'] ) ) {
272 setcookie( 'wp-job-manager-submitting-job-id', '', 0, COOKIEPATH, COOKIE_DOMAIN, false );
273 }
274 if ( isset( $_COOKIE['wp-job-manager-submitting-job-key'] ) ) {
275 setcookie( 'wp-job-manager-submitting-job-key', '', 0, COOKIEPATH, COOKIE_DOMAIN, false );
276 }
277 }
278
279 /**
280 * Registers assets used in both the frontend and WP admin.
281 */
282 public function register_shared_assets() {
283 global $wp_scripts;
284
285 $jquery_version = isset( $wp_scripts->registered['jquery-ui-core']->ver ) ? $wp_scripts->registered['jquery-ui-core']->ver : '1.9.2';
286 wp_register_style( 'jquery-ui', '//code.jquery.com/ui/' . $jquery_version . '/themes/smoothness/jquery-ui.css', array(), $jquery_version );
287 }
288
289 /**
290 * Registers and enqueues scripts and CSS.
291 */
292 public function frontend_scripts() {
293 global $post;
294
295 /**
296 * Starting in WP Job Manager 1.32.0, the chosen JS library and core frontend WPJM CSS will only be enqueued
297 * when used on a particular page. Theme and plugin authors as well as people who have overloaded WPJM's default
298 * template files should test this upcoming behavior.
299 *
300 * To test this behavior before 1.32.0, add this to your `wp-config.php`:
301 * define( 'JOB_MANAGER_TEST_NEW_ASSET_BEHAVIOR', true );
302 *
303 * Unless this constant is defined, WP Job Manager will default to its old behavior: chosen JS library and
304 * frontend styles are always enqueued.
305 *
306 * If your theme or plugin depend on the `frontend.css` or chosen JS library from WPJM core, you can use the
307 * `job_manager_chosen_enabled` and `job_manager_enqueue_frontend_style` filters.
308 *
309 * Example code for a custom shortcode that depends on the chosen library:
310 *
311 * add_filter( 'job_manager_chosen_enabled', function( $chosen_used_on_page ) {
312 * global $post;
313 * if ( is_singular()
314 * && is_a( $post, 'WP_Post' )
315 * && has_shortcode( $post->post_content, 'resumes' )
316 * ) {
317 * $chosen_used_on_page = true;
318 * }
319 * return $chosen_used_on_page;
320 * } );
321 */
322 if ( ! defined( 'JOB_MANAGER_TEST_NEW_ASSET_BEHAVIOR' ) || true !== JOB_MANAGER_TEST_NEW_ASSET_BEHAVIOR ) {
323 add_filter( 'job_manager_chosen_enabled', '__return_true' );
324 add_filter( 'job_manager_enqueue_frontend_style', '__return_true' );
325 }
326
327 $ajax_url = WP_Job_Manager_Ajax::get_endpoint();
328 $ajax_filter_deps = array( 'jquery', 'jquery-deserialize' );
329 $ajax_data = array(
330 'ajax_url' => $ajax_url,
331 'is_rtl' => is_rtl() ? 1 : 0,
332 'i18n_load_prev_listings' => __( 'Load previous listings', 'wp-job-manager' ),
333 );
334
335 /**
336 * Retrieves the current language for use when caching requests.
337 *
338 * @since 1.26.0
339 *
340 * @param string|null $lang
341 */
342 $ajax_data['lang'] = apply_filters( 'wpjm_lang', null );
343
344 $chosen_shortcodes = array( 'submit_job_form', 'job_dashboard', 'jobs' );
345 $chosen_used_on_page = has_wpjm_shortcode( null, $chosen_shortcodes );
346
347 /**
348 * Filter the use of the chosen library.
349 *
350 * NOTE: See above. Before WP Job Manager 1.32.0 is released, `job_manager_enqueue_frontend_style` will be filtered to `true` by default.
351 *
352 * @since 1.19.0
353 *
354 * @param bool $chosen_used_on_page Defaults to only when there are known shortcodes on the page.
355 */
356 if ( apply_filters( 'job_manager_chosen_enabled', $chosen_used_on_page ) ) {
357 wp_register_script( 'chosen', JOB_MANAGER_PLUGIN_URL . '/assets/js/jquery-chosen/chosen.jquery.min.js', array( 'jquery' ), '1.1.0', true );
358 wp_register_script( 'wp-job-manager-term-multiselect', JOB_MANAGER_PLUGIN_URL . '/assets/js/term-multiselect.min.js', array( 'jquery', 'chosen' ), JOB_MANAGER_VERSION, true );
359 wp_register_script( 'wp-job-manager-multiselect', JOB_MANAGER_PLUGIN_URL . '/assets/js/multiselect.min.js', array( 'jquery', 'chosen' ), JOB_MANAGER_VERSION, true );
360 wp_enqueue_style( 'chosen', JOB_MANAGER_PLUGIN_URL . '/assets/css/chosen.css', array(), '1.1.0' );
361 $ajax_filter_deps[] = 'chosen';
362
363 wp_localize_script(
364 'chosen', 'job_manager_chosen_multiselect_args',
365 apply_filters(
366 'job_manager_chosen_multiselect_args', array(
367 'search_contains' => true,
368 )
369 )
370 );
371 }
372
373 if ( job_manager_user_can_upload_file_via_ajax() ) {
374 wp_register_script( 'jquery-iframe-transport', JOB_MANAGER_PLUGIN_URL . '/assets/js/jquery-fileupload/jquery.iframe-transport.js', array( 'jquery' ), '1.8.3', true );
375 wp_register_script( 'jquery-fileupload', JOB_MANAGER_PLUGIN_URL . '/assets/js/jquery-fileupload/jquery.fileupload.js', array( 'jquery', 'jquery-iframe-transport', 'jquery-ui-widget' ), '9.11.2', true );
376 wp_register_script( 'wp-job-manager-ajax-file-upload', JOB_MANAGER_PLUGIN_URL . '/assets/js/ajax-file-upload.min.js', array( 'jquery', 'jquery-fileupload' ), JOB_MANAGER_VERSION, true );
377
378 ob_start();
379 get_job_manager_template(
380 'form-fields/uploaded-file-html.php',
381 array(
382 'name' => '',
383 'value' => '',
384 'extension' => 'jpg',
385 )
386 );
387 $js_field_html_img = ob_get_clean();
388
389 ob_start();
390 get_job_manager_template(
391 'form-fields/uploaded-file-html.php',
392 array(
393 'name' => '',
394 'value' => '',
395 'extension' => 'zip',
396 )
397 );
398 $js_field_html = ob_get_clean();
399
400 wp_localize_script(
401 'wp-job-manager-ajax-file-upload',
402 'job_manager_ajax_file_upload',
403 array(
404 'ajax_url' => $ajax_url,
405 'js_field_html_img' => esc_js( str_replace( "\n", '', $js_field_html_img ) ),
406 'js_field_html' => esc_js( str_replace( "\n", '', $js_field_html ) ),
407 'i18n_invalid_file_type' => __( 'Invalid file type. Accepted types:', 'wp-job-manager' ),
408 )
409 );
410 }
411
412 wp_register_script( 'jquery-deserialize', JOB_MANAGER_PLUGIN_URL . '/assets/js/jquery-deserialize/jquery.deserialize.js', array( 'jquery' ), '1.2.1', true );
413 wp_register_script( 'wp-job-manager-ajax-filters', JOB_MANAGER_PLUGIN_URL . '/assets/js/ajax-filters.min.js', $ajax_filter_deps, JOB_MANAGER_VERSION, true );
414 wp_register_script( 'wp-job-manager-job-dashboard', JOB_MANAGER_PLUGIN_URL . '/assets/js/job-dashboard.min.js', array( 'jquery' ), JOB_MANAGER_VERSION, true );
415 wp_register_script( 'wp-job-manager-job-application', JOB_MANAGER_PLUGIN_URL . '/assets/js/job-application.min.js', array( 'jquery' ), JOB_MANAGER_VERSION, true );
416 wp_register_script( 'wp-job-manager-job-submission', JOB_MANAGER_PLUGIN_URL . '/assets/js/job-submission.min.js', array( 'jquery' ), JOB_MANAGER_VERSION, true );
417 wp_localize_script( 'wp-job-manager-ajax-filters', 'job_manager_ajax_filters', $ajax_data );
418 wp_localize_script(
419 'wp-job-manager-job-dashboard',
420 'job_manager_job_dashboard',
421 array(
422 'i18n_confirm_delete' => __( 'Are you sure you want to delete this listing?', 'wp-job-manager' ),
423 )
424 );
425
426 /**
427 * Filter whether to enqueue WPJM core's frontend scripts. By default, they will only be enqueued on WPJM related
428 * pages.
429 *
430 * NOTE: See above. Before WP Job Manager 1.32.0 is released, `job_manager_enqueue_frontend_style` will be filtered to `true` by default.
431 *
432 * @since 1.30.0
433 *
434 * @param bool $is_frontend_style_enabled
435 */
436 if ( apply_filters( 'job_manager_enqueue_frontend_style', is_wpjm() ) ) {
437 wp_enqueue_style( 'wp-job-manager-frontend', JOB_MANAGER_PLUGIN_URL . '/assets/css/frontend.css', array(), JOB_MANAGER_VERSION );
438 } else {
439 wp_register_style( 'wp-job-manager-job-listings', JOB_MANAGER_PLUGIN_URL . '/assets/css/job-listings.css', array(), JOB_MANAGER_VERSION );
440 }
441 }
442 }
443
444 /**
445 * Add post type for Job Manager.
446 *
447 * @param array $types
448 * @return array
449 */
450 function job_manager_add_post_types( $types ) {
451 $types[] = 'job_listing';
452 return $types;
453 }
454 add_filter( 'post_types_to_delete_with_user', 'job_manager_add_post_types', 10 );
455
456 /**
457 * Main instance of WP Job Manager.
458 *
459 * Returns the main instance of WP Job Manager to prevent the need to use globals.
460 *
461 * @since 1.26
462 * @return WP_Job_Manager
463 */
464 function WPJM() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
465 return WP_Job_Manager::instance();
466 }
467
468 $GLOBALS['job_manager'] = WPJM();
469