WP Job Manager - Version 1.28.0

Version Description

  • Enhancement: Improves support for Google Job Search by adding JobListing structured data. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1115)
  • Enhancement: Adds ability for job types to be mapped to an employment type as defined for Google Job Search. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1112)
  • Enhancement: Requests search engines no longer index expired and filled job listings. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1120)
  • Enhancement: Improves support with third-party sitemap generation in Jetpack, Yoast SEO, and All in One SEO. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1119)
  • Enhancement: Updated descriptions and help text on settings page. (@donnapep; Props to @michelleweber for updated copy; https://github.com/Automattic/WP-Job-Manager/pull/1107)
  • Enhancement: Lower cache expiration times across plugin and limit use of autoloaded cache transients. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1101/files)
  • Fix: Localization issue with WPML in the [jobs] shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1129)
  • Fix: Show job listings' published date in localized format. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1118)
  • Fix: Job submission form allows users to select multiple job types when they go back a step. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1099)
  • Fix: Some themes that overloaded functions would break in previous release. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1104)
  • Dev: Adds versions to template files so it is easier to tell when they are updated. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1116)
  • Dev: Adds a new wpjm_notify_new_user action that allows you to override default behavior. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1125)
  • Dev: Early version of REST API is bundled but disabled by default. Requires PHP 5.3+ and WPJM_REST_API_ENABLED constant must be set to true. Do not use in production; endpoints may change. (@pkg)
Download this release

Release Info

Developer jakeom
Plugin Icon 128x128 WP Job Manager
Version 1.28.0
Comparing to
See all releases

Code changes from version 1.27.0 to 1.28.0

Files changed (109) hide show
  1. changelog.txt +15 -0
  2. includes/3rd-party/3rd-party.php +3 -0
  3. includes/3rd-party/all_in_one_seo_pack.php +23 -0
  4. includes/3rd-party/jetpack.php +36 -0
  5. includes/3rd-party/wpml.php +5 -0
  6. includes/3rd-party/yoast.php +27 -0
  7. includes/admin/class-wp-job-manager-admin.php +8 -0
  8. includes/admin/class-wp-job-manager-permalink-settings.php +1 -1
  9. includes/admin/class-wp-job-manager-settings.php +82 -47
  10. includes/admin/class-wp-job-manager-taxonomy-meta.php +156 -0
  11. includes/admin/class-wp-job-manager-writepanels.php +1 -1
  12. includes/class-wp-job-manager-cache-helper.php +1 -1
  13. includes/class-wp-job-manager-geocode.php +1 -1
  14. includes/class-wp-job-manager-install.php +60 -13
  15. includes/class-wp-job-manager-post-types.php +89 -7
  16. includes/forms/class-wp-job-manager-form-submit-job.php +4 -2
  17. includes/rest-api/class-wp-job-manager-controllers-status.php +130 -0
  18. includes/rest-api/class-wp-job-manager-data-stores-status.php +69 -0
  19. includes/rest-api/class-wp-job-manager-filters-status.php +46 -0
  20. includes/rest-api/class-wp-job-manager-models-settings.php +107 -0
  21. includes/rest-api/class-wp-job-manager-models-status.php +47 -0
  22. includes/rest-api/class-wp-job-manager-rest-api.php +118 -0
  23. languages/wp-job-manager.pot +346 -278
  24. lib/wpjm_rest/class-wp-job-manager-rest-bootstrap.php +171 -0
  25. lib/wpjm_rest/class-wp-job-manager-rest-classloader.php +145 -0
  26. lib/wpjm_rest/class-wp-job-manager-rest-controller.php +285 -0
  27. lib/wpjm_rest/class-wp-job-manager-rest-environment.php +400 -0
  28. lib/wpjm_rest/class-wp-job-manager-rest-exception.php +17 -0
  29. lib/wpjm_rest/class-wp-job-manager-rest-expect.php +65 -0
  30. lib/wpjm_rest/class-wp-job-manager-rest-model.php +645 -0
  31. lib/wpjm_rest/class-wp-job-manager-rest-type.php +90 -0
  32. lib/wpjm_rest/controller/bundle/class-wp-job-manager-rest-controller-bundle-builder.php +98 -0
  33. lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-action.php +166 -0
  34. lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-bundle.php +99 -0
  35. lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-crud.php +199 -0
  36. lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-extension.php +83 -0
  37. lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-model.php +165 -0
  38. lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-route.php +90 -0
  39. lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-settings.php +86 -0
  40. lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-abstract.php +73 -0
  41. lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-customposttype.php +178 -0
  42. lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-nil.php +66 -0
  43. lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-option.php +110 -0
  44. lib/wpjm_rest/field/class-wp-job-manager-rest-field-declaration.php +434 -0
  45. lib/wpjm_rest/field/declaration/class-wp-job-manager-rest-field-declaration-builder.php +290 -0
  46. lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-builder.php +22 -0
  47. lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-classloader.php +25 -0
  48. lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-controller.php +26 -0
  49. lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-model.php +151 -0
  50. lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-registrable.php +24 -0
  51. lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-type.php +50 -0
  52. lib/wpjm_rest/interfaces/controller/class-wp-job-manager-rest-interfaces-controller-bundle.php +25 -0
  53. lib/wpjm_rest/interfaces/data/class-wp-job-manager-rest-interfaces-data-store.php +52 -0
  54. lib/wpjm_rest/interfaces/model/class-wp-job-manager-rest-interfaces-model-collection.php +22 -0
  55. lib/wpjm_rest/interfaces/permissions/class-wp-job-manager-rest-interfaces-permissions-provider.php +20 -0
  56. lib/wpjm_rest/model/class-wp-job-manager-rest-model-collection.php +42 -0
  57. lib/wpjm_rest/model/class-wp-job-manager-rest-model-factory.php +175 -0
  58. lib/wpjm_rest/model/class-wp-job-manager-rest-model-settings.php +163 -0
  59. lib/wpjm_rest/permissions/class-wp-job-manager-rest-permissions-any.php +27 -0
  60. lib/wpjm_rest/type/class-wp-job-manager-rest-type-array.php +42 -0
  61. lib/wpjm_rest/type/class-wp-job-manager-rest-type-boolean.php +45 -0
  62. lib/wpjm_rest/type/class-wp-job-manager-rest-type-integer.php +65 -0
  63. lib/wpjm_rest/type/class-wp-job-manager-rest-type-nullable.php +75 -0
  64. lib/wpjm_rest/type/class-wp-job-manager-rest-type-number.php +55 -0
  65. lib/wpjm_rest/type/class-wp-job-manager-rest-type-registry.php +125 -0
  66. lib/wpjm_rest/type/class-wp-job-manager-rest-type-string.php +58 -0
  67. lib/wpjm_rest/type/class-wp-job-manager-rest-type-typedarray.php +71 -0
  68. readme.txt +16 -1
  69. scripts/build_mixtape.sh +118 -0
  70. templates/account-signin.php +17 -0
  71. templates/content-job_listing.php +13 -7
  72. templates/content-no-jobs-found.php +18 -0
  73. templates/content-single-job_listing-company.php +15 -4
  74. templates/content-single-job_listing-meta.php +15 -9
  75. templates/content-single-job_listing.php +22 -5
  76. templates/content-summary-job_listing.php +19 -1
  77. templates/content-widget-job_listing.php +17 -0
  78. templates/content-widget-no-jobs-found.php +19 -1
  79. templates/form-fields/checkbox-field.php +17 -0
  80. templates/form-fields/file-field.php +16 -0
  81. templates/form-fields/multiselect-field.php +18 -1
  82. templates/form-fields/password-field.php +17 -0
  83. templates/form-fields/radio-field.php +15 -1
  84. templates/form-fields/select-field.php +17 -0
  85. templates/form-fields/term-checklist-field.php +17 -0
  86. templates/form-fields/term-multiselect-field.php +16 -0
  87. templates/form-fields/term-select-field.php +16 -0
  88. templates/form-fields/text-field.php +17 -0
  89. templates/form-fields/textarea-field.php +17 -0
  90. templates/form-fields/uploaded-file-html.php +17 -0
  91. templates/form-fields/wp-editor-field.php +16 -0
  92. templates/job-application-email.php +17 -0
  93. templates/job-application-url.php +17 -0
  94. templates/job-application.php +17 -0
  95. templates/job-dashboard-login.php +17 -0
  96. templates/job-dashboard.php +17 -0
  97. templates/job-filter-job-types.php +17 -0
  98. templates/job-filters.php +21 -3
  99. templates/job-listings-end.php +18 -1
  100. templates/job-listings-start.php +18 -1
  101. templates/job-pagination.php +13 -2
  102. templates/job-preview.php +17 -0
  103. templates/job-submit.php +14 -3
  104. templates/job-submitted.php +16 -0
  105. templates/pagination.php +12 -1
  106. wp-job-manager-deprecated.php +13 -0
  107. wp-job-manager-functions.php +68 -37
  108. wp-job-manager-template.php +267 -10
  109. wp-job-manager.php +32 -5
changelog.txt CHANGED
@@ -1,3 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 1.27.0 =
2
  * Enhancement: Admins can now allow users to specify an account password when posting their first job listing. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1063)
3
  * Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1024)
1
+ = 1.28.0 =
2
+ * Enhancement: Improves support for Google Job Search by adding `JobListing` structured data. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1115)
3
+ * Enhancement: Adds ability for job types to be mapped to an employment type as defined for Google Job Search. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1112)
4
+ * Enhancement: Requests search engines no longer index expired and filled job listings. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1120)
5
+ * Enhancement: Improves support with third-party sitemap generation in Jetpack, Yoast SEO, and All in One SEO. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1119)
6
+ * Enhancement: Updated descriptions and help text on settings page. (@donnapep; Props to @michelleweber for updated copy; https://github.com/Automattic/WP-Job-Manager/pull/1107)
7
+ * Enhancement: Lower cache expiration times across plugin and limit use of autoloaded cache transients. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1101/files)
8
+ * Fix: Localization issue with WPML in the [jobs] shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1129)
9
+ * Fix: Show job listings' published date in localized format. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1118)
10
+ * Fix: Job submission form allows users to select multiple job types when they go back a step. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1099)
11
+ * Fix: Some themes that overloaded functions would break in previous release. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1104)
12
+ * Dev: Adds versions to template files so it is easier to tell when they are updated. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1116)
13
+ * Dev: Adds a new `wpjm_notify_new_user` action that allows you to override default behavior. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1125)
14
+ * Dev: Early version of REST API is bundled but disabled by default. Requires PHP 5.3+ and `WPJM_REST_API_ENABLED` constant must be set to true. Do not use in production; endpoints may change. (@pkg)
15
+
16
  = 1.27.0 =
17
  * Enhancement: Admins can now allow users to specify an account password when posting their first job listing. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1063)
18
  * Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1024)
includes/3rd-party/3rd-party.php CHANGED
@@ -2,5 +2,8 @@
2
  /**
3
  * Load 3rd party compatibility tweaks.
4
  */
 
5
  require_once( JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/wpml.php' );
6
  require_once( JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/polylang.php' );
 
 
2
  /**
3
  * Load 3rd party compatibility tweaks.
4
  */
5
+ require_once( JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/jetpack.php' );
6
  require_once( JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/wpml.php' );
7
  require_once( JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/polylang.php' );
8
+ require_once( JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/yoast.php' );
9
+ require_once( JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/all_in_one_seo_pack.php' );
includes/3rd-party/all_in_one_seo_pack.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Adds additional compatibility with All in One SEO Pack.
4
+ */
5
+
6
+ /**
7
+ * Skip filled job listings.
8
+ *
9
+ * @param WP_Post[] $posts
10
+ * @return WP_Post[]
11
+ */
12
+ function wpjm_aiosp_sitemap_filter_filled_jobs( $posts ) {
13
+ foreach ( $posts as $index => $post ) {
14
+ if ( $post instanceof WP_Post && 'job_listing' !== $post->post_type ) {
15
+ continue;
16
+ }
17
+ if ( is_position_filled( $post ) ) {
18
+ unset( $posts[ $index ] );
19
+ }
20
+ }
21
+ return $posts;
22
+ }
23
+ add_action( 'aiosp_sitemap_post_filter', 'wpjm_aiosp_sitemap_filter_filled_jobs', 10, 3 );
includes/3rd-party/jetpack.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Adds additional compatibility with Jetpack.
4
+ */
5
+
6
+ /**
7
+ * Skip filled job listings.
8
+ *
9
+ * @param bool $skip_post
10
+ * @param WP_Post $post
11
+ * @return bool
12
+ */
13
+ function wpjm_jetpack_skip_filled_job_listings( $skip_post, $post ) {
14
+ if ( 'job_listing' !== $post->post_type ) {
15
+ return $skip_post;
16
+ }
17
+
18
+ if ( is_position_filled( $post ) ) {
19
+ return true;
20
+ }
21
+
22
+ return $skip_post;
23
+ }
24
+ add_action( 'jetpack_sitemap_skip_post', 'wpjm_jetpack_skip_filled_job_listings', 10, 2 );
25
+
26
+ /**
27
+ * Add `job_listing` post type to sitemap.
28
+ *
29
+ * @param array $post_types
30
+ * @return array
31
+ */
32
+ function wpjm_jetpack_add_post_type( $post_types ) {
33
+ $post_types[] = 'job_listing';
34
+ return $post_types;
35
+ }
36
+ add_filter( 'jetpack_sitemap_post_types', 'wpjm_jetpack_add_post_type' );
includes/3rd-party/wpml.php CHANGED
@@ -14,9 +14,14 @@ function wpml_wpjm_init() {
14
  add_filter( 'wpjm_page_id', 'wpml_wpjm_page_id' );
15
  }
16
  add_action( 'wpml_loaded', 'wpml_wpjm_init' );
 
17
 
18
  /**
19
  * Sets WPJM's language if it is sent in the Ajax request.
 
 
 
 
20
  *
21
  * @since 1.26.0
22
  */
14
  add_filter( 'wpjm_page_id', 'wpml_wpjm_page_id' );
15
  }
16
  add_action( 'wpml_loaded', 'wpml_wpjm_init' );
17
+ add_action( 'wpml_loaded', 'wpml_wpjm_set_language' );
18
 
19
  /**
20
  * Sets WPJM's language if it is sent in the Ajax request.
21
+ * Note: This is hooked into both `wpml_loaded` and `get_job_listings_init`. As of WPML 3.7.1, if it was hooked
22
+ * into just `wpml_loaded` the query doesn't get the correct language for job listings. If it is just hooked into
23
+ * `get_job_listings_init` the locale doesn't get set correctly and the string translations are only loaded from
24
+ * the default language.
25
  *
26
  * @since 1.26.0
27
  */
includes/3rd-party/yoast.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Adds additional compatibility with Yoast SEO.
4
+ */
5
+
6
+ // Yoast SEO will by default include the `job_listing` post type because it is flagged as public.
7
+
8
+ /**
9
+ * Skip filled job listings.
10
+ *
11
+ * @param array $url Array of URL parts.
12
+ * @param string $type URL type.
13
+ * @param object $user Data object for the URL.
14
+ * @return string|bool False if we're skipping
15
+ */
16
+ function wpjm_yoast_skip_filled_job_listings( $url, $type, $post ) {
17
+ if ( 'job_listing' !== $post->post_type ) {
18
+ return $url;
19
+ }
20
+
21
+ if ( is_position_filled( $post ) ) {
22
+ return false;
23
+ }
24
+
25
+ return $url;
26
+ }
27
+ add_action( 'wpseo_sitemap_entry', 'wpjm_yoast_skip_filled_job_listings', 10, 3 );
includes/admin/class-wp-job-manager-admin.php CHANGED
@@ -51,11 +51,19 @@ class WP_Job_Manager_Admin {
51
 
52
  $this->settings_page = WP_Job_Manager_Settings::instance();
53
 
 
54
  add_action( 'current_screen', array( $this, 'conditional_includes' ) );
55
  add_action( 'admin_menu', array( $this, 'admin_menu' ), 12 );
56
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
57
  }
58
 
 
 
 
 
 
 
 
59
  /**
60
  * Include admin files conditionally.
61
  */
51
 
52
  $this->settings_page = WP_Job_Manager_Settings::instance();
53
 
54
+ add_action( 'admin_init', array( $this, 'admin_init' ) );
55
  add_action( 'current_screen', array( $this, 'conditional_includes' ) );
56
  add_action( 'admin_menu', array( $this, 'admin_menu' ), 12 );
57
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
58
  }
59
 
60
+ /**
61
+ * Set up actions during admin initialization.
62
+ */
63
+ public function admin_init() {
64
+ include_once( 'class-wp-job-manager-taxonomy-meta.php' );
65
+ }
66
+
67
  /**
68
  * Include admin files conditionally.
69
  */
includes/admin/class-wp-job-manager-permalink-settings.php CHANGED
@@ -46,7 +46,7 @@ class WP_Job_Manager_Permalink_Settings {
46
  public function __construct() {
47
  $this->setup_fields();
48
  $this->settings_save();
49
- $this->permalinks = wpjm_get_permalink_structure();
50
  }
51
 
52
  public function setup_fields() {
46
  public function __construct() {
47
  $this->setup_fields();
48
  $this->settings_save();
49
+ $this->permalinks = WP_Job_Manager_Post_Types::get_permalink_structure();
50
  }
51
 
52
  public function setup_fields() {
includes/admin/class-wp-job-manager-settings.php CHANGED
@@ -18,6 +18,13 @@ class WP_Job_Manager_Settings {
18
  */
19
  private static $_instance = null;
20
 
 
 
 
 
 
 
 
21
  /**
22
  * Allows for accessing single instance of class. Class should only be constructed once per call.
23
  *
@@ -40,18 +47,30 @@ class WP_Job_Manager_Settings {
40
  add_action( 'admin_init', array( $this, 'register_settings' ) );
41
  }
42
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  /**
44
  * Initializes the configuration for the plugin's setting fields.
45
  *
46
  * @access protected
47
  */
48
  protected function init_settings() {
49
- // Prepare roles option
50
  $roles = get_editable_roles();
51
  $account_roles = array();
52
 
53
  foreach ( $roles as $key => $role ) {
54
- if ( $key == 'administrator' ) {
55
  continue;
56
  }
57
  $account_roles[ $key ] = $role['name'];
@@ -67,7 +86,7 @@ class WP_Job_Manager_Settings {
67
  'std' => '10',
68
  'placeholder' => '',
69
  'label' => __( 'Listings Per Page', 'wp-job-manager' ),
70
- 'desc' => __( 'How many listings should be shown per page by default?', 'wp-job-manager' ),
71
  'attributes' => array()
72
  ),
73
  array(
@@ -75,7 +94,7 @@ class WP_Job_Manager_Settings {
75
  'std' => '0',
76
  'label' => __( 'Filled Positions', 'wp-job-manager' ),
77
  'cb_label' => __( 'Hide filled positions', 'wp-job-manager' ),
78
- 'desc' => __( 'If enabled, filled positions will be hidden from archives.', 'wp-job-manager' ),
79
  'type' => 'checkbox',
80
  'attributes' => array()
81
  ),
@@ -83,8 +102,8 @@ class WP_Job_Manager_Settings {
83
  'name' => 'job_manager_hide_expired',
84
  'std' => get_option( 'job_manager_hide_expired_content' ) ? '1' : '0', // back compat
85
  'label' => __( 'Hide Expired Listings', 'wp-job-manager' ),
86
- 'cb_label' => __( 'Hide expired listings in job archive/search', 'wp-job-manager' ),
87
- 'desc' => __( 'If enabled, expired job listing is not searchable.', 'wp-job-manager' ),
88
  'type' => 'checkbox',
89
  'attributes' => array()
90
  ),
@@ -92,8 +111,8 @@ class WP_Job_Manager_Settings {
92
  'name' => 'job_manager_hide_expired_content',
93
  'std' => '1',
94
  'label' => __( 'Hide Expired Listings Content', 'wp-job-manager' ),
95
- 'cb_label' => __( 'Hide expired listing content in single job listing (singular)', 'wp-job-manager' ),
96
- 'desc' => __( 'If enabled, the content within expired listings will be hidden. Otherwise, expired listings will be displayed as normal (without the application area).', 'wp-job-manager' ),
97
  'type' => 'checkbox',
98
  'attributes' => array()
99
  ),
@@ -101,8 +120,8 @@ class WP_Job_Manager_Settings {
101
  'name' => 'job_manager_enable_categories',
102
  'std' => '0',
103
  'label' => __( 'Categories', 'wp-job-manager' ),
104
- 'cb_label' => __( 'Enable categories for listings', 'wp-job-manager' ),
105
- 'desc' => __( 'Choose whether to enable categories. Categories must be setup by an admin to allow users to choose them during submission.', 'wp-job-manager' ),
106
  'type' => 'checkbox',
107
  'attributes' => array()
108
  ),
@@ -110,8 +129,8 @@ class WP_Job_Manager_Settings {
110
  'name' => 'job_manager_enable_default_category_multiselect',
111
  'std' => '0',
112
  'label' => __( 'Multi-select Categories', 'wp-job-manager' ),
113
- 'cb_label' => __( 'Enable category multiselect by default', 'wp-job-manager' ),
114
- 'desc' => __( 'If enabled, the category select box will default to a multiselect on the [jobs] shortcode.', 'wp-job-manager' ),
115
  'type' => 'checkbox',
116
  'attributes' => array()
117
  ),
@@ -120,29 +139,18 @@ class WP_Job_Manager_Settings {
120
  'std' => 'any',
121
  'label' => __( 'Category Filter Type', 'wp-job-manager' ),
122
  'desc' => __( 'Determines the logic used to display jobs when selecting multiple categories.', 'wp-job-manager' ),
123
- 'type' => 'select',
124
  'options' => array(
125
  'any' => __( 'Jobs will be shown if within ANY selected category', 'wp-job-manager' ),
126
  'all' => __( 'Jobs will be shown if within ALL selected categories', 'wp-job-manager' ),
127
  )
128
  ),
129
- array(
130
- 'name' => 'job_manager_date_format',
131
- 'std' => 'relative',
132
- 'label' => __( 'Date Format', 'wp-job-manager' ),
133
- 'desc' => __( 'Choose how you want the published date for jobs to be displayed on the front-end.', 'wp-job-manager' ),
134
- 'type' => 'select',
135
- 'options' => array(
136
- 'relative' => __( 'Relative to the current date (e.g., 1 day, 1 week, 1 month ago)', 'wp-job-manager' ),
137
- 'default' => __( 'Default date format as defined in Settings', 'wp-job-manager' ),
138
- )
139
- ),
140
  array(
141
  'name' => 'job_manager_enable_types',
142
  'std' => '1',
143
  'label' => __( 'Types', 'wp-job-manager' ),
144
- 'cb_label' => __( 'Enable types for listings', 'wp-job-manager' ),
145
- 'desc' => __( 'Choose whether to enable types. Types must be setup by an admin to allow users to choose them during submission.', 'wp-job-manager' ),
146
  'type' => 'checkbox',
147
  'attributes' => array()
148
  ),
@@ -150,11 +158,22 @@ class WP_Job_Manager_Settings {
150
  'name' => 'job_manager_multi_job_type',
151
  'std' => '0',
152
  'label' => __( 'Multi-select Listing Types', 'wp-job-manager' ),
153
- 'cb_label' => __( 'Enable multiple types for listings', 'wp-job-manager' ),
154
- 'desc' => __( 'If enabled each job can have more than one type. The metabox on the post editor and the select box on the frontend job submission form are changed by this.', 'wp-job-manager' ),
155
  'type' => 'checkbox',
156
  'attributes' => array()
157
  ),
 
 
 
 
 
 
 
 
 
 
 
158
  array(
159
  'name' => 'job_manager_google_maps_api_key',
160
  'std' => '',
@@ -171,8 +190,8 @@ class WP_Job_Manager_Settings {
171
  'name' => 'job_manager_user_requires_account',
172
  'std' => '1',
173
  'label' => __( 'Account Required', 'wp-job-manager' ),
174
- 'cb_label' => __( 'Submitting listings requires an account', 'wp-job-manager' ),
175
- 'desc' => __( 'If disabled, non-logged in users will be able to submit listings without creating an account.', 'wp-job-manager' ),
176
  'type' => 'checkbox',
177
  'attributes' => array()
178
  ),
@@ -180,8 +199,8 @@ class WP_Job_Manager_Settings {
180
  'name' => 'job_manager_enable_registration',
181
  'std' => '1',
182
  'label' => __( 'Account Creation', 'wp-job-manager' ),
183
- 'cb_label' => __( 'Allow account creation', 'wp-job-manager' ),
184
- 'desc' => __( 'If enabled, non-logged in users will be able to create an account by entering their email address on the submission form.', 'wp-job-manager' ),
185
  'type' => 'checkbox',
186
  'attributes' => array()
187
  ),
@@ -189,8 +208,8 @@ class WP_Job_Manager_Settings {
189
  'name' => 'job_manager_generate_username_from_email',
190
  'std' => '1',
191
  'label' => __( 'Account Username', 'wp-job-manager' ),
192
- 'cb_label' => __( 'Automatically Generate Username from Email Address', 'wp-job-manager' ),
193
- 'desc' => __( 'If enabled, a username will be generated from the first part of the user email address. Otherwise, a username field will be shown.', 'wp-job-manager' ),
194
  'type' => 'checkbox',
195
  'attributes' => array()
196
  ),
@@ -198,8 +217,8 @@ class WP_Job_Manager_Settings {
198
  'name' => 'job_manager_use_standard_password_setup_email',
199
  'std' => '1',
200
  'label' => __( 'Account Password', 'wp-job-manager' ),
201
- 'cb_label' => __( 'Use WordPress\' default behavior and email new users link to set a password', 'wp-job-manager' ),
202
- 'desc' => __( 'If enabled, an email will be sent to the user with their username and a link to set their password. Otherwise, a password field will be shown and their email address won\'t be verified.', 'wp-job-manager' ),
203
  'type' => 'checkbox',
204
  'attributes' => array()
205
  ),
@@ -207,7 +226,7 @@ class WP_Job_Manager_Settings {
207
  'name' => 'job_manager_registration_role',
208
  'std' => 'employer',
209
  'label' => __( 'Account Role', 'wp-job-manager' ),
210
- 'desc' => __( 'If you enable registration on your submission form, choose a role for the new user.', 'wp-job-manager' ),
211
  'type' => 'select',
212
  'options' => $account_roles
213
  ),
@@ -215,8 +234,8 @@ class WP_Job_Manager_Settings {
215
  'name' => 'job_manager_submission_requires_approval',
216
  'std' => '1',
217
  'label' => __( 'Moderate New Listings', 'wp-job-manager' ),
218
- 'cb_label' => __( 'New listing submissions require admin approval', 'wp-job-manager' ),
219
- 'desc' => __( 'If enabled, new submissions will be inactive, pending admin approval.', 'wp-job-manager' ),
220
  'type' => 'checkbox',
221
  'attributes' => array()
222
  ),
@@ -224,8 +243,8 @@ class WP_Job_Manager_Settings {
224
  'name' => 'job_manager_user_can_edit_pending_submissions',
225
  'std' => '0',
226
  'label' => __( 'Allow Pending Edits', 'wp-job-manager' ),
227
- 'cb_label' => __( 'Submissions awaiting approval can be edited', 'wp-job-manager' ),
228
- 'desc' => __( 'If enabled, submissions awaiting admin approval can be edited by the user.', 'wp-job-manager' ),
229
  'type' => 'checkbox',
230
  'attributes' => array()
231
  ),
@@ -233,15 +252,15 @@ class WP_Job_Manager_Settings {
233
  'name' => 'job_manager_submission_duration',
234
  'std' => '30',
235
  'label' => __( 'Listing Duration', 'wp-job-manager' ),
236
- 'desc' => __( 'How many <strong>days</strong> listings are live before expiring. Can be left blank to never expire.', 'wp-job-manager' ),
237
  'attributes' => array()
238
  ),
239
  array(
240
  'name' => 'job_manager_allowed_application_method',
241
  'std' => '',
242
  'label' => __( 'Application Method', 'wp-job-manager' ),
243
- 'desc' => __( 'Choose the contact method for listings.', 'wp-job-manager' ),
244
- 'type' => 'select',
245
  'options' => array(
246
  '' => __( 'Email address or website URL', 'wp-job-manager' ),
247
  'email' => __( 'Email addresses only', 'wp-job-manager' ),
@@ -257,21 +276,21 @@ class WP_Job_Manager_Settings {
257
  'name' => 'job_manager_submit_job_form_page_id',
258
  'std' => '',
259
  'label' => __( 'Submit Job Form Page', 'wp-job-manager' ),
260
- 'desc' => __( 'Select the page where you have placed the [submit_job_form] shortcode. This lets the plugin know where the form is located.', 'wp-job-manager' ),
261
  'type' => 'page'
262
  ),
263
  array(
264
  'name' => 'job_manager_job_dashboard_page_id',
265
  'std' => '',
266
  'label' => __( 'Job Dashboard Page', 'wp-job-manager' ),
267
- 'desc' => __( 'Select the page where you have placed the [job_dashboard] shortcode. This lets the plugin know where the dashboard is located.', 'wp-job-manager' ),
268
  'type' => 'page'
269
  ),
270
  array(
271
  'name' => 'job_manager_jobs_page_id',
272
  'std' => '',
273
  'label' => __( 'Job Listings Page', 'wp-job-manager' ),
274
- 'desc' => __( 'Select the page where you have placed the [jobs] shortcode. This lets the plugin know where the job listings page is located.', 'wp-job-manager' ),
275
  'type' => 'page'
276
  ),
277
  )
@@ -369,6 +388,22 @@ class WP_Job_Manager_Settings {
369
  echo ' <p class="description">' . $option['desc'] . '</p>';
370
  }
371
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  break;
373
  case "page" :
374
 
18
  */
19
  private static $_instance = null;
20
 
21
+ /**
22
+ * Our Settings.
23
+ *
24
+ * @var array Settings.
25
+ */
26
+ protected $settings = array();
27
+
28
  /**
29
  * Allows for accessing single instance of class. Class should only be constructed once per call.
30
  *
47
  add_action( 'admin_init', array( $this, 'register_settings' ) );
48
  }
49
 
50
+ /**
51
+ * Get Job Manager Settings
52
+ *
53
+ * @return array
54
+ */
55
+ public function get_settings() {
56
+ if ( 0 === count( $this->settings ) ) {
57
+ $this->init_settings();
58
+ }
59
+ return $this->settings;
60
+ }
61
+
62
  /**
63
  * Initializes the configuration for the plugin's setting fields.
64
  *
65
  * @access protected
66
  */
67
  protected function init_settings() {
68
+ // Prepare roles option.
69
  $roles = get_editable_roles();
70
  $account_roles = array();
71
 
72
  foreach ( $roles as $key => $role ) {
73
+ if ( 'administrator' === $key ) {
74
  continue;
75
  }
76
  $account_roles[ $key ] = $role['name'];
86
  'std' => '10',
87
  'placeholder' => '',
88
  'label' => __( 'Listings Per Page', 'wp-job-manager' ),
89
+ 'desc' => __( 'Number of job listings to display per page.', 'wp-job-manager' ),
90
  'attributes' => array()
91
  ),
92
  array(
94
  'std' => '0',
95
  'label' => __( 'Filled Positions', 'wp-job-manager' ),
96
  'cb_label' => __( 'Hide filled positions', 'wp-job-manager' ),
97
+ 'desc' => __( 'Filled positions will not display in your archives.', 'wp-job-manager' ),
98
  'type' => 'checkbox',
99
  'attributes' => array()
100
  ),
102
  'name' => 'job_manager_hide_expired',
103
  'std' => get_option( 'job_manager_hide_expired_content' ) ? '1' : '0', // back compat
104
  'label' => __( 'Hide Expired Listings', 'wp-job-manager' ),
105
+ 'cb_label' => __( 'Hide expired listings in job archives/search', 'wp-job-manager' ),
106
+ 'desc' => __( 'Expired job listings will not be searchable.', 'wp-job-manager' ),
107
  'type' => 'checkbox',
108
  'attributes' => array()
109
  ),
111
  'name' => 'job_manager_hide_expired_content',
112
  'std' => '1',
113
  'label' => __( 'Hide Expired Listings Content', 'wp-job-manager' ),
114
+ 'cb_label' => __( 'Hide content in expired single job listings', 'wp-job-manager' ),
115
+ 'desc' => __( 'Your site will display the titles of expired listings, but not the content of the listings. Otherwise, expired listings display their full content minus the application area.', 'wp-job-manager' ),
116
  'type' => 'checkbox',
117
  'attributes' => array()
118
  ),
120
  'name' => 'job_manager_enable_categories',
121
  'std' => '0',
122
  'label' => __( 'Categories', 'wp-job-manager' ),
123
+ 'cb_label' => __( 'Enable listing categories', 'wp-job-manager' ),
124
+ 'desc' => __( 'This lets users select from a list of categories when submitting a job. Note: an admin has to create categories before site users can select them.', 'wp-job-manager' ),
125
  'type' => 'checkbox',
126
  'attributes' => array()
127
  ),
129
  'name' => 'job_manager_enable_default_category_multiselect',
130
  'std' => '0',
131
  'label' => __( 'Multi-select Categories', 'wp-job-manager' ),
132
+ 'cb_label' => __( 'Default to category multiselect', 'wp-job-manager' ),
133
+ 'desc' => __( 'The category selection box will default to allowing multiple selections on the [jobs] shortcode. Without this, users will only be able to select a single category when submitting jobs.', 'wp-job-manager' ),
134
  'type' => 'checkbox',
135
  'attributes' => array()
136
  ),
139
  'std' => 'any',
140
  'label' => __( 'Category Filter Type', 'wp-job-manager' ),
141
  'desc' => __( 'Determines the logic used to display jobs when selecting multiple categories.', 'wp-job-manager' ),
142
+ 'type' => 'radio',
143
  'options' => array(
144
  'any' => __( 'Jobs will be shown if within ANY selected category', 'wp-job-manager' ),
145
  'all' => __( 'Jobs will be shown if within ALL selected categories', 'wp-job-manager' ),
146
  )
147
  ),
 
 
 
 
 
 
 
 
 
 
 
148
  array(
149
  'name' => 'job_manager_enable_types',
150
  'std' => '1',
151
  'label' => __( 'Types', 'wp-job-manager' ),
152
+ 'cb_label' => __( 'Enable listing types', 'wp-job-manager' ),
153
+ 'desc' => __( 'This lets users select from a list of types when submitting a job. Note: an admin has to create types before site users can select them.', 'wp-job-manager' ),
154
  'type' => 'checkbox',
155
  'attributes' => array()
156
  ),
158
  'name' => 'job_manager_multi_job_type',
159
  'std' => '0',
160
  'label' => __( 'Multi-select Listing Types', 'wp-job-manager' ),
161
+ 'cb_label' => __( 'Allow multiple types for listings', 'wp-job-manager' ),
162
+ 'desc' => __( 'This allows users to select more than one type when submitting a job. The metabox on the post editor and the selection box on the front-end job submission form will both reflect this.', 'wp-job-manager' ),
163
  'type' => 'checkbox',
164
  'attributes' => array()
165
  ),
166
+ array(
167
+ 'name' => 'job_manager_date_format',
168
+ 'std' => 'relative',
169
+ 'label' => __( 'Date Format', 'wp-job-manager' ),
170
+ 'desc' => __( 'Choose how you want the published date for jobs to be displayed on the front-end.', 'wp-job-manager' ),
171
+ 'type' => 'radio',
172
+ 'options' => array(
173
+ 'relative' => __( 'Relative to the current date (e.g., 1 day, 1 week, 1 month ago)', 'wp-job-manager' ),
174
+ 'default' => __( 'Default date format as defined in Settings', 'wp-job-manager' ),
175
+ )
176
+ ),
177
  array(
178
  'name' => 'job_manager_google_maps_api_key',
179
  'std' => '',
190
  'name' => 'job_manager_user_requires_account',
191
  'std' => '1',
192
  'label' => __( 'Account Required', 'wp-job-manager' ),
193
+ 'cb_label' => __( 'Require an account to submit listings', 'wp-job-manager' ),
194
+ 'desc' => __( 'Limits job listing submissions to registered, logged-in users.', 'wp-job-manager' ),
195
  'type' => 'checkbox',
196
  'attributes' => array()
197
  ),
199
  'name' => 'job_manager_enable_registration',
200
  'std' => '1',
201
  'label' => __( 'Account Creation', 'wp-job-manager' ),
202
+ 'cb_label' => __( 'Enable account creation during submission', 'wp-job-manager' ),
203
+ 'desc' => __( 'Includes account creation on the listing submission form, to allow non-registered users to create an account and submit a job listing simultaneously.', 'wp-job-manager' ),
204
  'type' => 'checkbox',
205
  'attributes' => array()
206
  ),
208
  'name' => 'job_manager_generate_username_from_email',
209
  'std' => '1',
210
  'label' => __( 'Account Username', 'wp-job-manager' ),
211
+ 'cb_label' => __( 'Generate usernames from email addresses', 'wp-job-manager' ),
212
+ 'desc' => __( 'Automatically generates usernames for new accounts from the registrant\'s email address. If this is not enabled, a "username" field will display instead.', 'wp-job-manager' ),
213
  'type' => 'checkbox',
214
  'attributes' => array()
215
  ),
217
  'name' => 'job_manager_use_standard_password_setup_email',
218
  'std' => '1',
219
  'label' => __( 'Account Password', 'wp-job-manager' ),
220
+ 'cb_label' => __( 'Email new users a link to set a password', 'wp-job-manager' ),
221
+ 'desc' => __( 'Sends an email to the user with their username and a link to set their password. If this is not enabled, a "password" field will display instead, and their email address won\'t be verified.', 'wp-job-manager' ),
222
  'type' => 'checkbox',
223
  'attributes' => array()
224
  ),
226
  'name' => 'job_manager_registration_role',
227
  'std' => 'employer',
228
  'label' => __( 'Account Role', 'wp-job-manager' ),
229
+ 'desc' => __( 'Any new accounts created during submission will have this role. If you haven\'t enabled account creation during submission in the options above, your own method of assigning roles will apply.', 'wp-job-manager' ),
230
  'type' => 'select',
231
  'options' => $account_roles
232
  ),
234
  'name' => 'job_manager_submission_requires_approval',
235
  'std' => '1',
236
  'label' => __( 'Moderate New Listings', 'wp-job-manager' ),
237
+ 'cb_label' => __( 'Require admin approval of all new listing submissions', 'wp-job-manager' ),
238
+ 'desc' => __( 'Sets all new submissions to "pending." They will not appear on your site until an admin approves them.', 'wp-job-manager' ),
239
  'type' => 'checkbox',
240
  'attributes' => array()
241
  ),
243
  'name' => 'job_manager_user_can_edit_pending_submissions',
244
  'std' => '0',
245
  'label' => __( 'Allow Pending Edits', 'wp-job-manager' ),
246
+ 'cb_label' => __( 'Allow editing of pending listings', 'wp-job-manager' ),
247
+ 'desc' => __( 'Users can continue to edit pending listings until they are approved by an admin.', 'wp-job-manager' ),
248
  'type' => 'checkbox',
249
  'attributes' => array()
250
  ),
252
  'name' => 'job_manager_submission_duration',
253
  'std' => '30',
254
  'label' => __( 'Listing Duration', 'wp-job-manager' ),
255
+ 'desc' => __( 'Listings will display for the set number of days, then expire. Leave this field blank if you don\'t want listings to have an expiration date.', 'wp-job-manager' ),
256
  'attributes' => array()
257
  ),
258
  array(
259
  'name' => 'job_manager_allowed_application_method',
260
  'std' => '',
261
  'label' => __( 'Application Method', 'wp-job-manager' ),
262
+ 'desc' => __( 'Choose the application method job listers will need to provide. Specify URL or email address only, or allow listers to choose which they prefer.', 'wp-job-manager' ),
263
+ 'type' => 'radio',
264
  'options' => array(
265
  '' => __( 'Email address or website URL', 'wp-job-manager' ),
266
  'email' => __( 'Email addresses only', 'wp-job-manager' ),
276
  'name' => 'job_manager_submit_job_form_page_id',
277
  'std' => '',
278
  'label' => __( 'Submit Job Form Page', 'wp-job-manager' ),
279
+ 'desc' => __( 'Select the page where you\'ve used the [submit_job_form] shortcode. This lets the plugin know the location of the form.', 'wp-job-manager' ),
280
  'type' => 'page'
281
  ),
282
  array(
283
  'name' => 'job_manager_job_dashboard_page_id',
284
  'std' => '',
285
  'label' => __( 'Job Dashboard Page', 'wp-job-manager' ),
286
+ 'desc' => __( 'Select the page where you\'ve used the [job_dashboard] shortcode. This lets the plugin know the location of the dashboard.', 'wp-job-manager' ),
287
  'type' => 'page'
288
  ),
289
  array(
290
  'name' => 'job_manager_jobs_page_id',
291
  'std' => '',
292
  'label' => __( 'Job Listings Page', 'wp-job-manager' ),
293
+ 'desc' => __( 'Select the page where you\'ve used the [jobs] shortcode. This lets the plugin know the location of the job listings page.', 'wp-job-manager' ),
294
  'type' => 'page'
295
  ),
296
  )
388
  echo ' <p class="description">' . $option['desc'] . '</p>';
389
  }
390
 
391
+ break;
392
+ case "radio":
393
+ ?><fieldset>
394
+ <legend class="screen-reader-text">
395
+ <span><?php echo esc_html( $option['label'] ); ?></span>
396
+ </legend><?php
397
+
398
+ if ( $option['desc'] ) {
399
+ echo '<p class="description">' . $option['desc'] . '</p>';
400
+ }
401
+
402
+ foreach( $option['options'] as $key => $name )
403
+ echo '<label><input name="' . esc_attr( $option['name'] ) . '" type="radio" value="' . esc_attr( $key ) . '" ' . checked( $value, $key, false ) . ' />' . esc_html( $name ) . '</label><br>';
404
+
405
+ ?></fieldset><?php
406
+
407
  break;
408
  case "page" :
409
 
includes/admin/class-wp-job-manager-taxonomy-meta.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
+ /**
7
+ * Handles taxonomy meta custom fields. Just used for job type.
8
+ *
9
+ * @package wp-job-manager
10
+ * @since 1.28.0
11
+ */
12
+ class WP_Job_Manager_Taxonomy_Meta {
13
+ /**
14
+ * The single instance of the class.
15
+ *
16
+ * @var self
17
+ * @since 1.28.0
18
+ */
19
+ private static $_instance = null;
20
+
21
+ /**
22
+ * Allows for accessing single instance of class. Class should only be constructed once per call.
23
+ *
24
+ * @since 1.28.0
25
+ * @static
26
+ * @return self Main instance.
27
+ */
28
+ public static function instance() {
29
+ if ( is_null( self::$_instance ) ) {
30
+ self::$_instance = new self();
31
+ }
32
+ return self::$_instance;
33
+ }
34
+
35
+ /**
36
+ * WP_Job_Manager_Taxonomy_Meta constructor.
37
+ */
38
+ public function __construct() {
39
+ if ( wpjm_job_listing_employment_type_enabled() ) {
40
+ add_action( 'job_listing_type_edit_form_fields', array( $this, 'display_schema_org_employment_type_field' ), 10, 2 );
41
+ add_action( 'job_listing_type_add_form_fields', array( $this, 'add_form_display_schema_org_employment_type_field' ), 10 );
42
+ add_action( 'edited_job_listing_type', array( $this, 'set_schema_org_employment_type_field' ), 10, 2 );
43
+ add_action( 'created_job_listing_type', array( $this, 'set_schema_org_employment_type_field' ), 10, 2 );
44
+ add_filter( 'manage_edit-job_listing_type_columns', array( $this, 'add_employment_type_column' ) );
45
+ add_filter( 'manage_job_listing_type_custom_column', array( $this, 'add_employment_type_column_content' ), 10, 3 );
46
+ add_filter( 'manage_edit-job_listing_type_sortable_columns', array( $this, 'add_employment_type_column_sortable' ) );
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Set the employment type field when creating/updating a job type item.
52
+ *
53
+ * @param int $term_id Term ID.
54
+ * @param int $tt_id Taxonomy type ID.
55
+ */
56
+ public function set_schema_org_employment_type_field( $term_id, $tt_id ) {
57
+ $employment_types = wpjm_job_listing_employment_type_options();
58
+ if( isset( $_POST['employment_type'] ) && isset( $employment_types[ $_POST['employment_type'] ] ) ){
59
+ update_term_meta( $term_id, 'employment_type', $_POST['employment_type'] );
60
+ } elseif ( isset( $_POST['employment_type'] ) ) {
61
+ delete_term_meta( $term_id, 'employment_type' );
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Add the option to select schema.org employmentType for job type on the edit meta field form.
67
+ *
68
+ * @param WP_Term $term Term object.
69
+ * @param string $taxonomy Taxonomy slug.
70
+ */
71
+ public function display_schema_org_employment_type_field( $term, $taxonomy ) {
72
+ $employment_types = wpjm_job_listing_employment_type_options();
73
+ $current_employment_type = get_term_meta( $term->term_id, 'employment_type', true );
74
+
75
+ if ( ! empty( $employment_types ) ) {
76
+ ?>
77
+ <tr class="form-field term-group-wrap">
78
+ <th scope="row"><label for="feature-group"><?php _e( 'Employment Type', 'wp-job-manager' ); ?></label></th>
79
+ <td><select class="postform" id="employment_type" name="employment_type">
80
+ <option value=""></option>
81
+ <?php foreach ( $employment_types as $key => $employment_type ) : ?>
82
+ <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $current_employment_type, $key ); ?>><?php echo esc_html( $employment_type ); ?></option>
83
+ <?php endforeach; ?>
84
+ </select></td>
85
+ </tr><?php
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Add the option to select schema.org employmentType for job type on the add meta field form.
91
+ *
92
+ * @param string $taxonomy Taxonomy slug.
93
+ */
94
+ public function add_form_display_schema_org_employment_type_field( $taxonomy ) {
95
+ $employment_types = wpjm_job_listing_employment_type_options();
96
+
97
+ if ( ! empty( $employment_types ) ) {
98
+ ?>
99
+ <div class="form-field term-group">
100
+ <label for="feature-group"><?php _e( 'Employment Type', 'wp-job-manager' ); ?></label>
101
+ <select class="postform" id="employment_type" name="employment_type">
102
+ <option value=""></option>
103
+ <?php foreach ( $employment_types as $key => $employment_type ) : ?>
104
+ <option value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $employment_type ); ?></option>
105
+ <?php endforeach; ?>
106
+ </select>
107
+ </div><?php
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Adds the Employment Type column when listing job type terms in WP Admin.
113
+ *
114
+ * @param array $columns
115
+ * @return array
116
+ */
117
+ public function add_employment_type_column( $columns ) {
118
+ $columns['employment_type'] = __( 'Employment Type', 'wp-job-manager' );
119
+ return $columns;
120
+ }
121
+
122
+ /**
123
+ * Adds the Employment Type column as a sortable column when listing job type terms in WP Admin.
124
+ *
125
+ * @param array $sortable
126
+ * @return array
127
+ */
128
+ public function add_employment_type_column_sortable( $sortable ) {
129
+ $sortable['employment_type'] = 'employment_type';
130
+ return $sortable;
131
+ }
132
+
133
+ /**
134
+ * Adds the Employment Type column content when listing job type terms in WP Admin.
135
+ *
136
+ * @param string $content
137
+ * @param string $column_name
138
+ * @param int $term_id
139
+ * @return string
140
+ */
141
+ public function add_employment_type_column_content( $content, $column_name, $term_id ) {
142
+ if( 'employment_type' !== $column_name ){
143
+ return $content;
144
+ }
145
+ $employment_types = wpjm_job_listing_employment_type_options();
146
+ $term_id = absint( $term_id );
147
+ $term_employment_type = get_term_meta( $term_id, 'employment_type', true );
148
+
149
+ if ( ! empty( $term_employment_type ) && isset( $employment_types[ $term_employment_type ] ) ) {
150
+ $content .= esc_attr( $employment_types[ $term_employment_type ] );
151
+ }
152
+ return $content;
153
+ }
154
+ }
155
+
156
+ WP_Job_Manager_Taxonomy_Meta::instance();
includes/admin/class-wp-job-manager-writepanels.php CHANGED
@@ -198,7 +198,7 @@ class WP_Job_Manager_Writepanels {
198
  <!-- Display tabs-->
199
  <ul id="<?php echo $taxonomy; ?>-tabs" class="category-tabs">
200
  <li class="tabs"><a href="#<?php echo $taxonomy; ?>-all" tabindex="3"><?php echo $tax->labels->all_items; ?></a></li>
201
- <li class="hide-if-no-js"><a href="#<?php echo $taxonomy; ?>-pop" tabindex="3"><?php _e( 'Most Used' ); ?></a></li>
202
  </ul>
203
 
204
  <!-- Display taxonomy terms -->
198
  <!-- Display tabs-->
199
  <ul id="<?php echo $taxonomy; ?>-tabs" class="category-tabs">
200
  <li class="tabs"><a href="#<?php echo $taxonomy; ?>-all" tabindex="3"><?php echo $tax->labels->all_items; ?></a></li>
201
+ <li class="hide-if-no-js"><a href="#<?php echo $taxonomy; ?>-pop" tabindex="3"><?php _e( 'Most Used', 'wp-job-manager' ); ?></a></li>
202
  </ul>
203
 
204
  <!-- Display taxonomy terms -->
includes/class-wp-job-manager-cache-helper.php CHANGED
@@ -228,7 +228,7 @@ class WP_Job_Manager_Cache_Helper {
228
  $count_posts = wp_count_posts( $post_type, 'readable' );
229
  // Default to 0 $status if object does not have a value
230
  $status_count = isset( $count_posts->$status ) ? $count_posts->$status : 0;
231
- set_transient( $transient, $status_count );
232
  }
233
 
234
  return $status_count;
228
  $count_posts = wp_count_posts( $post_type, 'readable' );
229
  // Default to 0 $status if object does not have a value
230
  $status_count = isset( $count_posts->$status ) ? $count_posts->$status : 0;
231
+ set_transient( $transient, $status_count, DAY_IN_SECONDS * 7 );
232
  }
233
 
234
  return $status_count;
includes/class-wp-job-manager-geocode.php CHANGED
@@ -226,7 +226,7 @@ class WP_Job_Manager_Geocode {
226
  break;
227
  case 'OK' :
228
  if ( ! empty( $geocoded_address->results[0] ) ) {
229
- set_transient( $transient_name, $geocoded_address, 24 * HOUR_IN_SECONDS * 365 );
230
  } else {
231
  throw new Exception( __( "Geocoding error", 'wp-job-manager' ) );
232
  }
226
  break;
227
  case 'OK' :
228
  if ( ! empty( $geocoded_address->results[0] ) ) {
229
+ set_transient( $transient_name, $geocoded_address, DAY_IN_SECONDS * 7 );
230
  } else {
231
  throw new Exception( __( "Geocoding error", 'wp-job-manager' ) );
232
  }
includes/class-wp-job-manager-install.php CHANGED
@@ -32,6 +32,11 @@ class WP_Job_Manager_Install {
32
  $wpdb->query( "UPDATE {$wpdb->posts} p LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id SET p.menu_order = -1 WHERE pm.meta_key = '_featured' AND pm.meta_value='1' AND p.post_type='job_listing';" );
33
  }
34
 
 
 
 
 
 
35
  // Update legacy options
36
  if ( false === get_option( 'job_manager_submit_job_form_page_id', false ) && get_option( 'job_manager_submit_page_slug' ) ) {
37
  $page_id = get_page_by_path( get_option( 'job_manager_submit_page_slug' ) )->ID;
@@ -106,31 +111,73 @@ class WP_Job_Manager_Install {
106
  }
107
 
108
  /**
109
- * Returns the default Job Manager terms.
110
  */
111
  private static function default_terms() {
112
  if ( get_option( 'job_manager_installed_terms' ) == 1 ) {
113
  return;
114
  }
115
 
116
- $taxonomies = array(
117
- 'job_listing_type' => array(
118
- 'Full Time',
119
- 'Part Time',
120
- 'Temporary',
121
- 'Freelance',
122
- 'Internship'
123
- )
124
- );
125
-
126
  foreach ( $taxonomies as $taxonomy => $terms ) {
127
- foreach ( $terms as $term ) {
128
  if ( ! get_term_by( 'slug', sanitize_title( $term ), $taxonomy ) ) {
129
- wp_insert_term( $term, $taxonomy );
 
 
 
 
 
130
  }
131
  }
132
  }
133
 
134
  update_option( 'job_manager_installed_terms', 1 );
135
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  }
32
  $wpdb->query( "UPDATE {$wpdb->posts} p LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id SET p.menu_order = -1 WHERE pm.meta_key = '_featured' AND pm.meta_value='1' AND p.post_type='job_listing';" );
33
  }
34
 
35
+ // Update default term meta with employment types
36
+ if ( version_compare( get_option( 'wp_job_manager_version', JOB_MANAGER_VERSION ), '1.28.0', '<' ) ) {
37
+ self::add_employment_types();
38
+ }
39
+
40
  // Update legacy options
41
  if ( false === get_option( 'job_manager_submit_job_form_page_id', false ) && get_option( 'job_manager_submit_page_slug' ) ) {
42
  $page_id = get_page_by_path( get_option( 'job_manager_submit_page_slug' ) )->ID;
111
  }
112
 
113
  /**
114
+ * Sets up the default WP Job Manager terms.
115
  */
116
  private static function default_terms() {
117
  if ( get_option( 'job_manager_installed_terms' ) == 1 ) {
118
  return;
119
  }
120
 
121
+ $taxonomies = self::get_default_taxonomy_terms();
 
 
 
 
 
 
 
 
 
122
  foreach ( $taxonomies as $taxonomy => $terms ) {
123
+ foreach ( $terms as $term => $meta ) {
124
  if ( ! get_term_by( 'slug', sanitize_title( $term ), $taxonomy ) ) {
125
+ $tt_package = wp_insert_term( $term, $taxonomy );
126
+ if ( is_array( $tt_package ) && isset( $tt_package['term_id'] ) && ! empty( $meta ) ) {
127
+ foreach ( $meta as $meta_key => $meta_value ) {
128
+ add_term_meta( $tt_package['term_id'], $meta_key, $meta_value );
129
+ }
130
+ }
131
  }
132
  }
133
  }
134
 
135
  update_option( 'job_manager_installed_terms', 1 );
136
  }
137
+
138
+ /**
139
+ * Default taxonomy terms to set up in WP Job Manager.
140
+ *
141
+ * @return array Default taxonomy terms.
142
+ */
143
+ private static function get_default_taxonomy_terms() {
144
+ return array(
145
+ 'job_listing_type' => array(
146
+ 'Full Time' => array(
147
+ 'employment_type' => 'FULL_TIME',
148
+ ),
149
+ 'Part Time' => array(
150
+ 'employment_type' => 'PART_TIME',
151
+ ),
152
+ 'Temporary' => array(
153
+ 'employment_type' => 'TEMPORARY',
154
+ ),
155
+ 'Freelance' => array(
156
+ 'employment_type' => 'CONTRACTOR',
157
+ ),
158
+ 'Internship' => array(
159
+ 'employment_type' => 'INTERN',
160
+ ),
161
+ )
162
+ );
163
+ }
164
+
165
+ /**
166
+ * Adds the employment type to default job types when updating from a previous WP Job Manager version.
167
+ */
168
+ private static function add_employment_types() {
169
+ $taxonomies = self::get_default_taxonomy_terms();
170
+ $terms = $taxonomies['job_listing_type'];
171
+
172
+ foreach ( $terms as $term => $meta ) {
173
+ $term = get_term_by( 'slug', sanitize_title( $term ), 'job_listing_type' );
174
+ if ( $term ) {
175
+ foreach ( $meta as $meta_key => $meta_value ) {
176
+ if ( ! get_term_meta( (int) $term->term_id, $meta_key, true ) ) {
177
+ add_term_meta( (int) $term->term_id, $meta_key, $meta_value );
178
+ }
179
+ }
180
+ }
181
+ }
182
+ }
183
  }
includes/class-wp-job-manager-post-types.php CHANGED
@@ -44,6 +44,9 @@ class WP_Job_Manager_Post_Types {
44
  add_action( 'auto-draft_to_publish', array( $this, 'set_expiry' ) );
45
  add_action( 'expired_to_publish', array( $this, 'set_expiry' ) );
46
 
 
 
 
47
  add_filter( 'the_job_description', 'wptexturize' );
48
  add_filter( 'the_job_description', 'convert_smilies' );
49
  add_filter( 'the_job_description', 'convert_chars' );
@@ -86,7 +89,8 @@ class WP_Job_Manager_Post_Types {
86
 
87
  $admin_capability = 'manage_job_listings';
88
 
89
- $permalink_structure = wpjm_get_permalink_structure();
 
90
  /**
91
  * Taxonomies
92
  */
@@ -342,6 +346,8 @@ class WP_Job_Manager_Post_Types {
342
  * Generates the RSS feed for Job Listings.
343
  */
344
  public function job_feed() {
 
 
345
  $query_args = array(
346
  'post_type' => 'job_listing',
347
  'post_status' => 'publish',
@@ -386,7 +392,7 @@ class WP_Job_Manager_Post_Types {
386
  }
387
 
388
  $job_manager_keyword = isset( $_GET['search_keywords'] ) ? sanitize_text_field( $_GET['search_keywords'] ) : '';
389
- if ( !empty( $job_manager_keyword ) ) {
390
  $query_args['s'] = $job_manager_keyword;
391
  add_filter( 'posts_search', 'get_job_listings_keyword_search' );
392
  }
@@ -534,9 +540,11 @@ class WP_Job_Manager_Post_Types {
534
  * Typo wrapper for `set_expiry` method.
535
  *
536
  * @param WP_Post $post
537
- * @deprecated
 
538
  */
539
  public function set_expirey( $post ) {
 
540
  $this->set_expiry( $post );
541
  }
542
 
@@ -600,10 +608,45 @@ class WP_Job_Manager_Post_Types {
600
  * @return array
601
  */
602
  public function fix_post_name( $data, $postarr ) {
603
- if ( 'job_listing' === $data['post_type'] && 'pending' === $data['post_status'] && ! current_user_can( 'publish_posts' ) && isset( $postarr['post_name'] ) ) {
604
- $data['post_name'] = $postarr['post_name'];
605
- }
606
- return $data;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
607
  }
608
 
609
  /**
@@ -683,6 +726,7 @@ class WP_Job_Manager_Post_Types {
683
  * @deprecated 1.19.1
684
  */
685
  public function maybe_generate_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value ) {
 
686
  $this->maybe_update_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value );
687
  }
688
 
@@ -699,6 +743,44 @@ class WP_Job_Manager_Post_Types {
699
  }
700
  }
701
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
702
  /**
703
  * After importing via WP All Import, adds default meta data.
704
  *
44
  add_action( 'auto-draft_to_publish', array( $this, 'set_expiry' ) );
45
  add_action( 'expired_to_publish', array( $this, 'set_expiry' ) );
46
 
47
+ add_action( 'wp_head', array( $this, 'noindex_expired_filled_job_listings' ) );
48
+ add_action( 'wp_footer', array( $this, 'output_structured_data' ) );
49
+
50
  add_filter( 'the_job_description', 'wptexturize' );
51
  add_filter( 'the_job_description', 'convert_smilies' );
52
  add_filter( 'the_job_description', 'convert_chars' );
89
 
90
  $admin_capability = 'manage_job_listings';
91
 
92
+ $permalink_structure = WP_Job_Manager_Post_Types::get_permalink_structure();
93
+
94
  /**
95
  * Taxonomies
96
  */
346
  * Generates the RSS feed for Job Listings.
347
  */
348
  public function job_feed() {
349
+ global $job_manager_keyword;
350
+
351
  $query_args = array(
352
  'post_type' => 'job_listing',
353
  'post_status' => 'publish',
392
  }
393
 
394
  $job_manager_keyword = isset( $_GET['search_keywords'] ) ? sanitize_text_field( $_GET['search_keywords'] ) : '';
395
+ if ( ! empty( $job_manager_keyword ) ) {
396
  $query_args['s'] = $job_manager_keyword;
397
  add_filter( 'posts_search', 'get_job_listings_keyword_search' );
398
  }
540
  * Typo wrapper for `set_expiry` method.
541
  *
542
  * @param WP_Post $post
543
+ * @since 1.0.0
544
+ * @deprecated 1.0.1
545
  */
546
  public function set_expirey( $post ) {
547
+ _deprecated_function( __METHOD__, '1.0.1', 'WP_Job_Manager_Post_Types::set_expiry' );
548
  $this->set_expiry( $post );
549
  }
550
 
608
  * @return array
609
  */
610
  public function fix_post_name( $data, $postarr ) {
611
+ if ( 'job_listing' === $data['post_type']
612
+ && 'pending' === $data['post_status']
613
+ && ! current_user_can( 'publish_posts' )
614
+ && isset( $postarr['post_name'] )
615
+ ) {
616
+ $data['post_name'] = $postarr['post_name'];
617
+ }
618
+ return $data;
619
+ }
620
+
621
+ /**
622
+ * Retrieves permalink settings.
623
+ *
624
+ * @see https://github.com/woocommerce/woocommerce/blob/3.0.8/includes/wc-core-functions.php#L1573
625
+ * @since 1.28.0
626
+ * @return array
627
+ */
628
+ public static function get_permalink_structure() {
629
+ // Switch to the site's default locale, bypassing the active user's locale.
630
+ if ( function_exists( 'switch_to_locale' ) && did_action( 'admin_init' ) ) {
631
+ switch_to_locale( get_locale() );
632
+ }
633
+
634
+ $permalinks = wp_parse_args( (array) get_option( 'wpjm_permalinks', array() ), array(
635
+ 'job_base' => '',
636
+ 'category_base' => '',
637
+ 'type_base' => '',
638
+ ) );
639
+
640
+ // Ensure rewrite slugs are set.
641
+ $permalinks['job_rewrite_slug'] = untrailingslashit( empty( $permalinks['job_base'] ) ? _x( 'job', 'Job permalink - resave permalinks after changing this', 'wp-job-manager' ) : $permalinks['job_base'] );
642
+ $permalinks['category_rewrite_slug'] = untrailingslashit( empty( $permalinks['category_base'] ) ? _x( 'job-category', 'Job category slug - resave permalinks after changing this', 'wp-job-manager' ) : $permalinks['category_base'] );
643
+ $permalinks['type_rewrite_slug'] = untrailingslashit( empty( $permalinks['type_base'] ) ? _x( 'job-type', 'Job type slug - resave permalinks after changing this', 'wp-job-manager' ) : $permalinks['type_base'] );
644
+
645
+ // Restore the original locale.
646
+ if ( function_exists( 'restore_current_locale' ) && did_action( 'admin_init' ) ) {
647
+ restore_current_locale();
648
+ }
649
+ return $permalinks;
650
  }
651
 
652
  /**
726
  * @deprecated 1.19.1
727
  */
728
  public function maybe_generate_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value ) {
729
+ _deprecated_function( __METHOD__, '1.19.1', 'WP_Job_Manager_Post_Types::maybe_update_geolocation_data' );
730
  $this->maybe_update_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value );
731
  }
732
 
743
  }
744
  }
745
 
746
+ /**
747
+ * Add noindex for expired and filled job listings.
748
+ */
749
+ public function noindex_expired_filled_job_listings() {
750
+ if ( ! is_single() ) {
751
+ return;
752
+ }
753
+
754
+ $post = get_post();
755
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
756
+ return;
757
+ }
758
+
759
+ if ( wpjm_allow_indexing_job_listing() ) {
760
+ return;
761
+ }
762
+
763
+ wp_no_robots();
764
+ }
765
+
766
+ /**
767
+ * Add structured data to the footer of job listing pages.
768
+ */
769
+ public function output_structured_data() {
770
+ if ( ! is_single() ) {
771
+ return;
772
+ }
773
+
774
+ if ( ! wpjm_output_job_listing_structured_data() ) {
775
+ return;
776
+ }
777
+
778
+ $structured_data = wpjm_get_job_listing_structured_data();
779
+ if ( ! empty( $structured_data ) ) {
780
+ echo '<script type="application/ld+json">' . wp_json_encode( $structured_data ) . '</script>';
781
+ }
782
+ }
783
+
784
  /**
785
  * After importing via WP All Import, adds default meta data.
786
  *
includes/forms/class-wp-job-manager-form-submit-job.php CHANGED
@@ -197,7 +197,6 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
197
  'label' => __( 'Description', 'wp-job-manager' ),
198
  'type' => 'wp-editor',
199
  'required' => true,
200
- 'placeholder' => '',
201
  'priority' => 5
202
  ),
203
  'application' => array(
@@ -385,7 +384,10 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
385
  $this->fields[ $group_key ][ $key ]['value'] = $job->post_content;
386
  break;
387
  case 'job_type' :
388
- $this->fields[ $group_key ][ $key ]['value'] = current( wp_get_object_terms( $job->ID, 'job_listing_type', array( 'fields' => 'ids' ) ) );
 
 
 
389
  break;
390
  case 'job_category' :
391
  $this->fields[ $group_key ][ $key ]['value'] = wp_get_object_terms( $job->ID, 'job_listing_category', array( 'fields' => 'ids' ) );
197
  'label' => __( 'Description', 'wp-job-manager' ),
198
  'type' => 'wp-editor',
199
  'required' => true,
 
200
  'priority' => 5
201
  ),
202
  'application' => array(
384
  $this->fields[ $group_key ][ $key ]['value'] = $job->post_content;
385
  break;
386
  case 'job_type' :
387
+ $this->fields[ $group_key ][ $key ]['value'] = wp_get_object_terms( $job->ID, 'job_listing_type', array( 'fields' => 'ids' ) );
388
+ if ( ! job_manager_multi_job_type() ) {
389
+ $this->fields[ $group_key ][ $key ]['value'] = current( $this->fields[ $group_key ][ $key ]['value'] );
390
+ }
391
  break;
392
  case 'job_category' :
393
  $this->fields[ $group_key ][ $key ]['value'] = wp_get_object_terms( $job->ID, 'job_listing_category', array( 'fields' => 'ids' ) );
includes/rest-api/class-wp-job-manager-controllers-status.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Declaration of our Status Model
4
+ *
5
+ * @package WPJM/REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_Controllers_Status
14
+ */
15
+ class WP_Job_Manager_Controllers_Status extends WP_Job_Manager_REST_Controller_Model
16
+ implements WP_Job_Manager_REST_Interfaces_Controller {
17
+
18
+
19
+ /**
20
+ * Setup
21
+ */
22
+ public function setup() {
23
+ $this->add_route( '/' )
24
+ ->add_action( $this->action( 'index', 'index' ) );
25
+
26
+ $this->add_route( '/(?P<key>[a-zA-Z_]+)' )
27
+ ->add_action( $this->action( 'show', 'show' ) )
28
+ ->add_action( $this->action( 'update', 'update' ) );
29
+ }
30
+
31
+ /**
32
+ * Index handler
33
+ *
34
+ * @param WP_REST_Request $request The request.
35
+ * @return WP_REST_Response
36
+ */
37
+ public function index( $request ) {
38
+ $params = $request->get_params();
39
+ $filter = $this->environment()
40
+ ->model( 'WP_Job_Manager_Filters_Status' )
41
+ ->new_from_array( $params );
42
+
43
+ if ( is_wp_error( $filter ) ) {
44
+ return $this->bad_request( $filter );
45
+ }
46
+
47
+ $configuration = $this->get_model_factory()
48
+ ->get_data_store()
49
+ ->get_entity( null );
50
+
51
+ if ( empty( $configuration ) ) {
52
+ return $this->not_found( __( 'Not Found', 'wp-job-manager' ) );
53
+ }
54
+
55
+ $dto = $this->prepare_dto( $configuration );
56
+ $keys = $filter->get( 'keys' );
57
+ if ( empty( $keys ) ) {
58
+ return $this->ok( $dto );
59
+ }
60
+
61
+ $filtered_params = array();
62
+ foreach ( $keys as $key ) {
63
+ if ( isset( $params[ $key ] ) ) {
64
+ $filtered_params[ $key ] = $params[ $key ];
65
+ }
66
+ }
67
+ return $this->ok( $filtered_params );
68
+ }
69
+
70
+ /**
71
+ * Show handler
72
+ *
73
+ * @param WP_REST_Request $request The request.
74
+ * @return WP_REST_Response
75
+ */
76
+ public function show( $request ) {
77
+ $key = $request->get_param( 'key' );
78
+ $configuration = $this->get_model_factory()
79
+ ->get_data_store()
80
+ ->get_entity( null );
81
+
82
+ if ( ! $configuration->has( $key ) ) {
83
+ return $this->not_found( 'Invalid key: ' . $key );
84
+ }
85
+
86
+ return $configuration->get( $key );
87
+ }
88
+
89
+ /**
90
+ * Update handler
91
+ *
92
+ * @param WP_REST_Request $request The request.
93
+ * @return WP_REST_Response
94
+ */
95
+ public function update( $request ) {
96
+ $key = $request->get_param( 'key' );
97
+ $value = $request->get_param( 'value' );
98
+ if ( empty( $value ) ) {
99
+ if ( ! function_exists( 'json_decode' ) ) {
100
+ include_once ABSPATH . WPINC . 'compat.php';
101
+ }
102
+ $body = $request->get_body();
103
+ $value = json_decode( $body, true );
104
+ }
105
+ $thing_to_update = array(
106
+ $key => $value,
107
+ );
108
+
109
+ $configuration = $this->get_model_factory()
110
+ ->get_data_store()
111
+ ->get_entity( '' );
112
+ $configuration->update_from_array( $thing_to_update );
113
+ $result = $this->get_model_factory()
114
+ ->get_data_store()
115
+ ->upsert( $configuration );
116
+
117
+ if ( is_wp_error( $result ) ) {
118
+ return $this->respond( $result, 500 );
119
+ }
120
+
121
+ $dto = $this->prepare_dto( $configuration );
122
+
123
+ if ( WP_REST_Server::CREATABLE === $request->get_method() ) {
124
+ return $this->created( $dto );
125
+ }
126
+
127
+ return $this->ok( $dto );
128
+ }
129
+ }
130
+
includes/rest-api/class-wp-job-manager-data-stores-status.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Declaration of our Status Data Store
4
+ *
5
+ * @package WPJM/REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_Data_Stores_Status
14
+ */
15
+ class WP_Job_Manager_Data_Stores_Status extends WP_Job_Manager_REST_Data_Store_Abstract
16
+ implements WP_Job_Manager_REST_Interfaces_Data_Store {
17
+
18
+ /**
19
+ * Get all the models (taking into account any filtering)
20
+ *
21
+ * @param WP_Job_Manager_REST_Interfaces_Model|null $filter A filter.
22
+ * @return WP_Job_Manager_REST_Model_Collection
23
+ */
24
+ public function get_entities( $filter = null ) {
25
+ return new WP_Job_Manager_REST_Model_Collection( array( $this->get_entity( null ) ) );
26
+ }
27
+
28
+ /**
29
+ * Get a Model Using it's unique identifier
30
+ *
31
+ * @param mixed $id The id of the entity.
32
+ * @return WP_Job_Manager_REST_Interfaces_Model
33
+ */
34
+ public function get_entity( $id ) {
35
+ $should_run_page_setup = (bool) get_transient( '_job_manager_activation_redirect' );
36
+ $params = array(
37
+ 'run_page_setup' => $should_run_page_setup,
38
+ );
39
+ return $this->get_model_factory()->create( $params );
40
+ }
41
+
42
+ /**
43
+ * Delete a Model
44
+ *
45
+ * @param WP_Job_Manager_REST_Interfaces_Model $model The model to delete.
46
+ * @param array $args Args.
47
+ * @return mixed
48
+ */
49
+ public function delete( $model, $args = array() ) {
50
+ return true;
51
+ }
52
+
53
+ /**
54
+ * Update/Insert Model
55
+ *
56
+ * @param WP_Job_Manager_REST_Interfaces_Model $model The model.
57
+ * @return mixed
58
+ */
59
+ public function upsert( $model ) {
60
+ $run_page_setup_val = $model->get( 'run_page_setup' );
61
+ if ( $run_page_setup_val ) {
62
+ set_transient( '_job_manager_activation_redirect', 1, HOUR_IN_SECONDS );
63
+ } else {
64
+ delete_transient( '_job_manager_activation_redirect' );
65
+ }
66
+ return true;
67
+ }
68
+ }
69
+
includes/rest-api/class-wp-job-manager-filters-status.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Declaration of our Status Filters (will be used in GET requests)
4
+ *
5
+ * @package WPJM/REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_Filters_Status
14
+ */
15
+ class WP_Job_Manager_Filters_Status extends WP_Job_Manager_REST_Model {
16
+
17
+ /**
18
+ * Declare our fields
19
+ *
20
+ * @return array
21
+ * @throws WP_Job_Manager_REST_Exception Exc.
22
+ */
23
+ public static function declare_fields() {
24
+ $env = self::get_environment();
25
+ return array(
26
+ $env->field( 'keys', 'The status keys to return' )
27
+ ->with_type( $env->type( 'array:string' ) )
28
+ ->with_before_set( 'explode_keys' )
29
+ ->with_default( array() ),
30
+ );
31
+ }
32
+
33
+ /**
34
+ * Explode keys
35
+ *
36
+ * @param mixed $keys The keys.
37
+ * @return array
38
+ */
39
+ public function explode_keys( $keys ) {
40
+ if ( is_string( $keys ) ) {
41
+ return explode( ',', $keys );
42
+ }
43
+ return $keys;
44
+ }
45
+ }
46
+
includes/rest-api/class-wp-job-manager-models-settings.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Declaration of our Settings Model
4
+ *
5
+ * @package WPJM/REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_Models_Settings
14
+ */
15
+ class WP_Job_Manager_Models_Settings extends WP_Job_Manager_REST_Model_Settings
16
+ implements WP_Job_Manager_REST_Interfaces_Permissions_Provider {
17
+
18
+
19
+ /**
20
+ * Fields that have to be valid page ids.
21
+ *
22
+ * @var array|null
23
+ */
24
+ private static $fields_requiring_page_id_validation = null;
25
+
26
+ /**
27
+ * Get Job Manager Settings
28
+ *
29
+ * @return array
30
+ */
31
+ public static function get_settings() {
32
+ if ( ! class_exists( 'WP_Job_Manager_Settings' ) ) {
33
+ $parent = dirname( dirname( __FILE__ ) );
34
+ if ( ! function_exists( 'get_editable_roles' ) ) {
35
+ // WP_Job_Manager_Settings needs this for user roles.
36
+ include_once ABSPATH . 'wp-admin/includes/user.php';
37
+ }
38
+ include_once $parent . '/admin/class-wp-job-manager-settings.php';
39
+ }
40
+
41
+ return WP_Job_Manager_Settings::instance()->get_settings();
42
+ }
43
+
44
+ /**
45
+ * Adds validations to fields requiring page ids.
46
+ *
47
+ * @param string $field_name The fields name.
48
+ * @param WP_Job_Manager_REST_Field_Declaration_Builder $field_builder The field builder.
49
+ * @param array $field_data The field data.
50
+ * @param WP_Job_Manager_REST_Environment $env The definition.
51
+ */
52
+ protected static function on_field_setup( $field_name, $field_builder, $field_data, $env ) {
53
+ if ( in_array( $field_name, self::get_fields_requiring_page_id_validation(), true ) ) {
54
+ $field_builder->with_type( $env->type( 'integer' ) )
55
+ ->with_validations( 'validate_page_id_belongs_to_valid_page' );
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Validates that a page_id points to a valid page.
61
+ *
62
+ * @param int $id The id.
63
+ * @return bool|WP_Error
64
+ */
65
+ public function validate_page_id_belongs_to_valid_page( $id ) {
66
+ $content = get_post( $id );
67
+
68
+ if ( ! empty( $content ) && 'page' === $content->post_type ) {
69
+ return true;
70
+ }
71
+
72
+ return new WP_Error( 'invalid-page-id', __( 'Invalid page ID provided', 'wp-job-manager' ) );
73
+ }
74
+
75
+ /**
76
+ * Permissions for accessing Settings.
77
+ *
78
+ * @param WP_REST_Request $request The request.
79
+ * @param string $action The action.
80
+ *
81
+ * @return bool
82
+ */
83
+ public static function permissions_check( $request, $action ) {
84
+ return current_user_can( 'manage_options' );
85
+ }
86
+
87
+ /**
88
+ * Lazy-load field names requiring Page ID Validation.
89
+ *
90
+ * @return array
91
+ */
92
+ private static function get_fields_requiring_page_id_validation() {
93
+ if ( null === self::$fields_requiring_page_id_validation ) {
94
+ self::$fields_requiring_page_id_validation = (array) apply_filters(
95
+ 'wpjm_rest_api_settings_fields_requiring_page_id_validation',
96
+ array(
97
+ 'job_manager_submit_job_form_page_id',
98
+ 'job_manager_job_dashboard_page_id',
99
+ 'job_manager_jobs_page_id',
100
+ )
101
+ );
102
+ }
103
+
104
+ return self::$fields_requiring_page_id_validation;
105
+ }
106
+ }
107
+
includes/rest-api/class-wp-job-manager-models-status.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Declaration of our Status Model
4
+ *
5
+ * @package WPJM/REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_Models_Status
14
+ */
15
+ class WP_Job_Manager_Models_Status extends WP_Job_Manager_REST_Model
16
+ implements WP_Job_Manager_REST_Interfaces_Permissions_Provider {
17
+
18
+
19
+ /**
20
+ * Declare our fields
21
+ *
22
+ * @return array
23
+ * @throws WP_Job_Manager_REST_Exception Exc.
24
+ */
25
+ public static function declare_fields() {
26
+ $env = self::get_environment();
27
+ return array(
28
+ $env->field( 'run_page_setup', 'Should we run page setup' )
29
+ ->with_type( $env->type( 'boolean' ) ),
30
+ );
31
+ }
32
+
33
+ /**
34
+ * Handle Permissions for a REST Controller Action
35
+ *
36
+ * @param WP_REST_Request $request The request.
37
+ * @param string $action The action (e.g. index, create update etc).
38
+ * @return bool
39
+ */
40
+ public static function permissions_check( $request, $action ) {
41
+ if ( in_array( $action, array( 'index', 'show' ), true ) ) {
42
+ return true;
43
+ }
44
+ return current_user_can( 'manage_options' );
45
+ }
46
+ }
47
+
includes/rest-api/class-wp-job-manager-rest-api.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The REST API Initializer
4
+ *
5
+ * @package WPJM/REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_API
14
+ */
15
+ class WP_Job_Manager_REST_API {
16
+
17
+ /**
18
+ * Is the api enabled?
19
+ *
20
+ * @var bool
21
+ */
22
+ private $is_rest_api_enabled;
23
+ /**
24
+ * Our bootstrap
25
+ *
26
+ * @var WP_Job_Manager_REST_Bootstrap
27
+ */
28
+ private $wpjm_rest_api;
29
+ /**
30
+ * The plugin base dir
31
+ *
32
+ * @var string
33
+ */
34
+ private $base_dir;
35
+
36
+ /**
37
+ * WP_Job_Manager_REST_API constructor.
38
+ *
39
+ * @param string $base_dir The base dir.
40
+ */
41
+ public function __construct( $base_dir ) {
42
+ $this->base_dir = trailingslashit( $base_dir );
43
+ $this->is_rest_api_enabled = defined( 'WPJM_REST_API_ENABLED' ) && ( true === constant( 'WPJM_REST_API_ENABLED' ) );
44
+ }
45
+
46
+ /**
47
+ * Bootstrap our REST Api
48
+ */
49
+ private function bootstrap() {
50
+ $file = $this->base_dir . 'lib/wpjm_rest/class-wp-job-manager-rest-bootstrap.php';
51
+ if ( ! file_exists( $file ) ) {
52
+ return new WP_Error( 'mixtape-missing' );
53
+ }
54
+
55
+ include_once $file;
56
+
57
+ $this->wpjm_rest_api = WP_Job_Manager_REST_Bootstrap::create();
58
+ if ( empty( $this->wpjm_rest_api ) ) {
59
+ return new WP_Error( 'rest-api-bootstrap-failed' );
60
+ }
61
+ $this->wpjm_rest_api->load();
62
+
63
+ include_once 'class-wp-job-manager-models-settings.php';
64
+ include_once 'class-wp-job-manager-models-status.php';
65
+ include_once 'class-wp-job-manager-filters-status.php';
66
+ include_once 'class-wp-job-manager-data-stores-status.php';
67
+ include_once 'class-wp-job-manager-controllers-status.php';
68
+ }
69
+
70
+ /**
71
+ * Get WP_Job_Manager_REST_Bootstrap
72
+ *
73
+ * @return WP_Job_Manager_REST_Bootstrap
74
+ */
75
+ public function get_bootstrap() {
76
+ return $this->wpjm_rest_api;
77
+ }
78
+
79
+ /**
80
+ * Initialize the REST API
81
+ *
82
+ * @return WP_Job_Manager_REST_API $this
83
+ */
84
+ public function init() {
85
+ if ( ! $this->is_rest_api_enabled ) {
86
+ return $this;
87
+ }
88
+ $err = $this->bootstrap();
89
+ if ( is_wp_error( $err ) ) {
90
+ // Silently don't initialize the rest api if we get a wp_error.
91
+ return $this;
92
+ }
93
+ $this->define_api( $this->wpjm_rest_api->environment() );
94
+ $this->wpjm_rest_api->environment()
95
+ ->start();
96
+ return $this;
97
+ }
98
+
99
+ /**
100
+ * Define our REST API Models and Controllers
101
+ *
102
+ * @param WP_Job_Manager_REST_Environment $env The Environment.
103
+ */
104
+ public function define_api( $env ) {
105
+ // Models.
106
+ $env->define_model( 'WP_Job_Manager_Models_Settings' )
107
+ ->with_data_store( new WP_Job_Manager_REST_Data_Store_Option( $env->model( 'WP_Job_Manager_Models_Settings' ) ) );
108
+ $env->define_model( 'WP_Job_Manager_Models_Status' )
109
+ ->with_data_store( new WP_Job_Manager_Data_Stores_Status( $env->model( 'WP_Job_Manager_Models_Status' ) ) );
110
+ $env->define_model( 'WP_Job_Manager_Filters_Status' );
111
+
112
+ // Endpoints.
113
+ $env->rest_api( 'wpjm/v1' )
114
+ ->add_endpoint( new WP_Job_Manager_REST_Controller_Settings( '/settings', 'WP_Job_Manager_Models_Settings' ) )
115
+ ->add_endpoint( new WP_Job_Manager_Controllers_Status( '/status', 'WP_Job_Manager_Models_Status' ) );
116
+ }
117
+ }
118
+
languages/wp-job-manager.pot CHANGED
@@ -2,19 +2,19 @@
2
  # This file is distributed under the GPL2+.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: WP Job Manager 1.27.0\n"
6
- "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wp-job-manager\n"
7
- "POT-Creation-Date: 2017-07-06 11:18:20+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
  "PO-Revision-Date: 2017-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
- "Language-Team: LANGUAGE <LL@li.org>\n"
14
  "X-Generator: grunt-wp-i18n 0.5.4\n"
15
 
16
  #: includes/admin/class-wp-job-manager-addons.php:82
17
- #: includes/admin/class-wp-job-manager-admin.php:105
18
  msgid "WP Job Manager Add-ons"
19
  msgstr ""
20
 
@@ -26,11 +26,11 @@ msgstr ""
26
  msgid "Check out the core add-on bundle &rarr;"
27
  msgstr ""
28
 
29
- #: includes/admin/class-wp-job-manager-admin.php:102
30
  msgid "Settings"
31
  msgstr ""
32
 
33
- #: includes/admin/class-wp-job-manager-admin.php:105
34
  msgid "Add-ons"
35
  msgstr ""
36
 
@@ -129,7 +129,7 @@ msgstr ""
129
  #: includes/admin/class-wp-job-manager-writepanels.php:55
130
  #: includes/forms/class-wp-job-manager-form-submit-job.php:171
131
  #: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:38
132
- #: templates/job-filters.php:17 templates/job-filters.php:18
133
  msgid "Location"
134
  msgstr ""
135
 
@@ -146,7 +146,7 @@ msgid "Expires"
146
  msgstr ""
147
 
148
  #: includes/admin/class-wp-job-manager-cpt.php:364
149
- #: includes/admin/class-wp-job-manager-settings.php:103
150
  msgid "Categories"
151
  msgstr ""
152
 
@@ -192,13 +192,13 @@ msgid "View"
192
  msgstr ""
193
 
194
  #: includes/admin/class-wp-job-manager-cpt.php:494
195
- #: includes/class-wp-job-manager-post-types.php:218
196
- #: templates/job-dashboard.php:33 templates/job-dashboard.php:51
197
  msgid "Edit"
198
  msgstr ""
199
 
200
  #: includes/admin/class-wp-job-manager-cpt.php:501
201
- #: templates/job-dashboard.php:56
202
  msgid "Delete"
203
  msgstr ""
204
 
@@ -214,330 +214,339 @@ msgstr ""
214
  msgid "Job type base"
215
  msgstr ""
216
 
217
- #: includes/admin/class-wp-job-manager-settings.php:63
218
- #: includes/class-wp-job-manager-post-types.php:214
219
- #: includes/class-wp-job-manager-post-types.php:290
220
  msgid "Job Listings"
221
  msgstr ""
222
 
223
- #: includes/admin/class-wp-job-manager-settings.php:69
224
  msgid "Listings Per Page"
225
  msgstr ""
226
 
227
- #: includes/admin/class-wp-job-manager-settings.php:70
228
- msgid "How many listings should be shown per page by default?"
229
  msgstr ""
230
 
231
- #: includes/admin/class-wp-job-manager-settings.php:76
232
  msgid "Filled Positions"
233
  msgstr ""
234
 
235
- #: includes/admin/class-wp-job-manager-settings.php:77
236
  msgid "Hide filled positions"
237
  msgstr ""
238
 
239
- #: includes/admin/class-wp-job-manager-settings.php:78
240
- msgid "If enabled, filled positions will be hidden from archives."
241
  msgstr ""
242
 
243
- #: includes/admin/class-wp-job-manager-settings.php:85
244
  msgid "Hide Expired Listings"
245
  msgstr ""
246
 
247
- #: includes/admin/class-wp-job-manager-settings.php:86
248
- msgid "Hide expired listings in job archive/search"
249
  msgstr ""
250
 
251
- #: includes/admin/class-wp-job-manager-settings.php:87
252
- msgid "If enabled, expired job listing is not searchable."
253
  msgstr ""
254
 
255
- #: includes/admin/class-wp-job-manager-settings.php:94
256
  msgid "Hide Expired Listings Content"
257
  msgstr ""
258
 
259
- #: includes/admin/class-wp-job-manager-settings.php:95
260
- msgid "Hide expired listing content in single job listing (singular)"
261
  msgstr ""
262
 
263
- #: includes/admin/class-wp-job-manager-settings.php:96
264
  msgid ""
265
- "If enabled, the content within expired listings will be hidden. Otherwise, "
266
- "expired listings will be displayed as normal (without the application area)."
 
267
  msgstr ""
268
 
269
- #: includes/admin/class-wp-job-manager-settings.php:104
270
- msgid "Enable categories for listings"
271
  msgstr ""
272
 
273
- #: includes/admin/class-wp-job-manager-settings.php:105
274
  msgid ""
275
- "Choose whether to enable categories. Categories must be setup by an admin "
276
- "to allow users to choose them during submission."
277
  msgstr ""
278
 
279
- #: includes/admin/class-wp-job-manager-settings.php:112
280
  msgid "Multi-select Categories"
281
  msgstr ""
282
 
283
- #: includes/admin/class-wp-job-manager-settings.php:113
284
- msgid "Enable category multiselect by default"
285
  msgstr ""
286
 
287
- #: includes/admin/class-wp-job-manager-settings.php:114
288
  msgid ""
289
- "If enabled, the category select box will default to a multiselect on the "
290
- "[jobs] shortcode."
 
291
  msgstr ""
292
 
293
- #: includes/admin/class-wp-job-manager-settings.php:121
294
  msgid "Category Filter Type"
295
  msgstr ""
296
 
297
- #: includes/admin/class-wp-job-manager-settings.php:122
298
  msgid ""
299
  "Determines the logic used to display jobs when selecting multiple "
300
  "categories."
301
  msgstr ""
302
 
303
- #: includes/admin/class-wp-job-manager-settings.php:125
304
  msgid "Jobs will be shown if within ANY selected category"
305
  msgstr ""
306
 
307
- #: includes/admin/class-wp-job-manager-settings.php:126
308
  msgid "Jobs will be shown if within ALL selected categories"
309
  msgstr ""
310
 
311
- #: includes/admin/class-wp-job-manager-settings.php:132
312
- msgid "Date Format"
313
  msgstr ""
314
 
315
- #: includes/admin/class-wp-job-manager-settings.php:133
316
- msgid ""
317
- "Choose how you want the published date for jobs to be displayed on the "
318
- "front-end."
319
  msgstr ""
320
 
321
- #: includes/admin/class-wp-job-manager-settings.php:136
322
- msgid "Relative to the current date (e.g., 1 day, 1 week, 1 month ago)"
 
 
323
  msgstr ""
324
 
325
- #: includes/admin/class-wp-job-manager-settings.php:137
326
- msgid "Default date format as defined in Settings"
327
  msgstr ""
328
 
329
- #: includes/admin/class-wp-job-manager-settings.php:143
330
- msgid "Types"
331
  msgstr ""
332
 
333
- #: includes/admin/class-wp-job-manager-settings.php:144
334
- msgid "Enable types for listings"
 
 
 
335
  msgstr ""
336
 
337
- #: includes/admin/class-wp-job-manager-settings.php:145
338
- msgid ""
339
- "Choose whether to enable types. Types must be setup by an admin to allow "
340
- "users to choose them during submission."
341
  msgstr ""
342
 
343
- #: includes/admin/class-wp-job-manager-settings.php:152
344
- msgid "Multi-select Listing Types"
 
 
345
  msgstr ""
346
 
347
- #: includes/admin/class-wp-job-manager-settings.php:153
348
- msgid "Enable multiple types for listings"
349
  msgstr ""
350
 
351
- #: includes/admin/class-wp-job-manager-settings.php:154
352
- msgid ""
353
- "If enabled each job can have more than one type. The metabox on the post "
354
- "editor and the select box on the frontend job submission form are changed "
355
- "by this."
356
  msgstr ""
357
 
358
- #: includes/admin/class-wp-job-manager-settings.php:161
359
  msgid "Google Maps API Key"
360
  msgstr ""
361
 
362
- #: includes/admin/class-wp-job-manager-settings.php:162
363
  msgid ""
364
  "Google requires an API key to retrieve location information for job "
365
  "listings. Acquire an API key from the <a href=\"%s\">Google Maps API "
366
  "developer site</a>."
367
  msgstr ""
368
 
369
- #: includes/admin/class-wp-job-manager-settings.php:168
370
  msgid "Job Submission"
371
  msgstr ""
372
 
373
- #: includes/admin/class-wp-job-manager-settings.php:173
374
  msgid "Account Required"
375
  msgstr ""
376
 
377
- #: includes/admin/class-wp-job-manager-settings.php:174
378
- msgid "Submitting listings requires an account"
379
  msgstr ""
380
 
381
- #: includes/admin/class-wp-job-manager-settings.php:175
382
- msgid ""
383
- "If disabled, non-logged in users will be able to submit listings without "
384
- "creating an account."
385
  msgstr ""
386
 
387
- #: includes/admin/class-wp-job-manager-settings.php:182
388
  msgid "Account Creation"
389
  msgstr ""
390
 
391
- #: includes/admin/class-wp-job-manager-settings.php:183
392
- msgid "Allow account creation"
393
  msgstr ""
394
 
395
- #: includes/admin/class-wp-job-manager-settings.php:184
396
  msgid ""
397
- "If enabled, non-logged in users will be able to create an account by "
398
- "entering their email address on the submission form."
 
399
  msgstr ""
400
 
401
- #: includes/admin/class-wp-job-manager-settings.php:191
402
  msgid "Account Username"
403
  msgstr ""
404
 
405
- #: includes/admin/class-wp-job-manager-settings.php:192
406
- msgid "Automatically Generate Username from Email Address"
407
  msgstr ""
408
 
409
- #: includes/admin/class-wp-job-manager-settings.php:193
410
  msgid ""
411
- "If enabled, a username will be generated from the first part of the user "
412
- "email address. Otherwise, a username field will be shown."
 
413
  msgstr ""
414
 
415
- #: includes/admin/class-wp-job-manager-settings.php:200
416
  msgid "Account Password"
417
  msgstr ""
418
 
419
- #: includes/admin/class-wp-job-manager-settings.php:201
420
- msgid "Use WordPress' default behavior and email new users link to set a password"
421
  msgstr ""
422
 
423
- #: includes/admin/class-wp-job-manager-settings.php:202
424
  msgid ""
425
- "If enabled, an email will be sent to the user with their username and a "
426
- "link to set their password. Otherwise, a password field will be shown and "
427
- "their email address won't be verified."
428
  msgstr ""
429
 
430
- #: includes/admin/class-wp-job-manager-settings.php:209
431
  msgid "Account Role"
432
  msgstr ""
433
 
434
- #: includes/admin/class-wp-job-manager-settings.php:210
435
  msgid ""
436
- "If you enable registration on your submission form, choose a role for the "
437
- "new user."
 
438
  msgstr ""
439
 
440
- #: includes/admin/class-wp-job-manager-settings.php:217
441
  msgid "Moderate New Listings"
442
  msgstr ""
443
 
444
- #: includes/admin/class-wp-job-manager-settings.php:218
445
- msgid "New listing submissions require admin approval"
446
  msgstr ""
447
 
448
- #: includes/admin/class-wp-job-manager-settings.php:219
449
- msgid "If enabled, new submissions will be inactive, pending admin approval."
 
 
450
  msgstr ""
451
 
452
- #: includes/admin/class-wp-job-manager-settings.php:226
453
  msgid "Allow Pending Edits"
454
  msgstr ""
455
 
456
- #: includes/admin/class-wp-job-manager-settings.php:227
457
- msgid "Submissions awaiting approval can be edited"
458
  msgstr ""
459
 
460
- #: includes/admin/class-wp-job-manager-settings.php:228
461
- msgid "If enabled, submissions awaiting admin approval can be edited by the user."
 
 
462
  msgstr ""
463
 
464
- #: includes/admin/class-wp-job-manager-settings.php:235
465
  msgid "Listing Duration"
466
  msgstr ""
467
 
468
- #: includes/admin/class-wp-job-manager-settings.php:236
469
  msgid ""
470
- "How many <strong>days</strong> listings are live before expiring. Can be "
471
- "left blank to never expire."
472
  msgstr ""
473
 
474
- #: includes/admin/class-wp-job-manager-settings.php:242
475
  msgid "Application Method"
476
  msgstr ""
477
 
478
- #: includes/admin/class-wp-job-manager-settings.php:243
479
- msgid "Choose the contact method for listings."
 
 
480
  msgstr ""
481
 
482
- #: includes/admin/class-wp-job-manager-settings.php:246
483
  msgid "Email address or website URL"
484
  msgstr ""
485
 
486
- #: includes/admin/class-wp-job-manager-settings.php:247
487
  msgid "Email addresses only"
488
  msgstr ""
489
 
490
- #: includes/admin/class-wp-job-manager-settings.php:248
491
  msgid "Website URLs only"
492
  msgstr ""
493
 
494
- #: includes/admin/class-wp-job-manager-settings.php:254
495
  msgid "Pages"
496
  msgstr ""
497
 
498
- #: includes/admin/class-wp-job-manager-settings.php:259
499
  msgid "Submit Job Form Page"
500
  msgstr ""
501
 
502
- #: includes/admin/class-wp-job-manager-settings.php:260
503
  msgid ""
504
- "Select the page where you have placed the [submit_job_form] shortcode. This "
505
- "lets the plugin know where the form is located."
506
  msgstr ""
507
 
508
- #: includes/admin/class-wp-job-manager-settings.php:266
509
  msgid "Job Dashboard Page"
510
  msgstr ""
511
 
512
- #: includes/admin/class-wp-job-manager-settings.php:267
513
  msgid ""
514
- "Select the page where you have placed the [job_dashboard] shortcode. This "
515
- "lets the plugin know where the dashboard is located."
516
  msgstr ""
517
 
518
- #: includes/admin/class-wp-job-manager-settings.php:273
519
  msgid "Job Listings Page"
520
  msgstr ""
521
 
522
- #: includes/admin/class-wp-job-manager-settings.php:274
523
  msgid ""
524
- "Select the page where you have placed the [jobs] shortcode. This lets the "
525
- "plugin know where the job listings page is located."
526
  msgstr ""
527
 
528
- #: includes/admin/class-wp-job-manager-settings.php:320
529
  msgid "Settings successfully saved"
530
  msgstr ""
531
 
532
- #: includes/admin/class-wp-job-manager-settings.php:380
533
  msgid "--no page--"
534
  msgstr ""
535
 
536
- #: includes/admin/class-wp-job-manager-settings.php:385
537
  msgid "Select a page&hellip;"
538
  msgstr ""
539
 
540
- #: includes/admin/class-wp-job-manager-settings.php:431
541
  msgid "Save Changes"
542
  msgstr ""
543
 
@@ -723,6 +732,12 @@ msgstr ""
723
  msgid "Help other users on the forums"
724
  msgstr ""
725
 
 
 
 
 
 
 
726
  #: includes/admin/class-wp-job-manager-writepanels.php:56
727
  #: includes/forms/class-wp-job-manager-form-submit-job.php:175
728
  msgid "e.g. \"London\""
@@ -860,132 +875,132 @@ msgstr ""
860
  msgid "Geocoding error"
861
  msgstr ""
862
 
863
- #: includes/class-wp-job-manager-install.php:60
864
  msgid "Employer"
865
  msgstr ""
866
 
867
- #: includes/class-wp-job-manager-post-types.php:94
868
  #: includes/forms/class-wp-job-manager-form-submit-job.php:188
869
  msgid "Job category"
870
  msgstr ""
871
 
872
- #: includes/class-wp-job-manager-post-types.php:95
873
  msgid "Job categories"
874
  msgstr ""
875
 
876
- #: includes/class-wp-job-manager-post-types.php:119
877
- #: includes/class-wp-job-manager-post-types.php:167
878
- #: includes/class-wp-job-manager-post-types.php:223
879
  msgid "Search %s"
880
  msgstr ""
881
 
882
- #: includes/class-wp-job-manager-post-types.php:120
883
- #: includes/class-wp-job-manager-post-types.php:168
884
- #: includes/class-wp-job-manager-post-types.php:215
885
  msgid "All %s"
886
  msgstr ""
887
 
888
- #: includes/class-wp-job-manager-post-types.php:121
889
- #: includes/class-wp-job-manager-post-types.php:169
890
- #: includes/class-wp-job-manager-post-types.php:226
891
  msgid "Parent %s"
892
  msgstr ""
893
 
894
- #: includes/class-wp-job-manager-post-types.php:122
895
- #: includes/class-wp-job-manager-post-types.php:170
896
  msgid "Parent %s:"
897
  msgstr ""
898
 
899
- #: includes/class-wp-job-manager-post-types.php:123
900
- #: includes/class-wp-job-manager-post-types.php:171
901
- #: includes/class-wp-job-manager-post-types.php:219
902
  msgid "Edit %s"
903
  msgstr ""
904
 
905
- #: includes/class-wp-job-manager-post-types.php:124
906
- #: includes/class-wp-job-manager-post-types.php:172
907
  msgid "Update %s"
908
  msgstr ""
909
 
910
- #: includes/class-wp-job-manager-post-types.php:125
911
- #: includes/class-wp-job-manager-post-types.php:173
912
  msgid "Add New %s"
913
  msgstr ""
914
 
915
- #: includes/class-wp-job-manager-post-types.php:126
916
- #: includes/class-wp-job-manager-post-types.php:174
917
  msgid "New %s Name"
918
  msgstr ""
919
 
920
- #: includes/class-wp-job-manager-post-types.php:143
921
  #: includes/forms/class-wp-job-manager-form-submit-job.php:179
922
  msgid "Job type"
923
  msgstr ""
924
 
925
- #: includes/class-wp-job-manager-post-types.php:144
926
  msgid "Job types"
927
  msgstr ""
928
 
929
- #: includes/class-wp-job-manager-post-types.php:193
930
  msgid "Job"
931
  msgstr ""
932
 
933
- #: includes/class-wp-job-manager-post-types.php:194
934
  msgid "Jobs"
935
  msgstr ""
936
 
937
- #: includes/class-wp-job-manager-post-types.php:216
938
  msgid "Add New"
939
  msgstr ""
940
 
941
- #: includes/class-wp-job-manager-post-types.php:217
942
  msgid "Add %s"
943
  msgstr ""
944
 
945
- #: includes/class-wp-job-manager-post-types.php:220
946
  msgid "New %s"
947
  msgstr ""
948
 
949
- #: includes/class-wp-job-manager-post-types.php:221
950
- #: includes/class-wp-job-manager-post-types.php:222
951
  msgid "View %s"
952
  msgstr ""
953
 
954
- #: includes/class-wp-job-manager-post-types.php:224
955
  msgid "No %s found"
956
  msgstr ""
957
 
958
- #: includes/class-wp-job-manager-post-types.php:225
959
  msgid "No %s found in trash"
960
  msgstr ""
961
 
962
- #: includes/class-wp-job-manager-post-types.php:227
963
  msgid "Company Logo"
964
  msgstr ""
965
 
966
- #: includes/class-wp-job-manager-post-types.php:228
967
  msgid "Set company logo"
968
  msgstr ""
969
 
970
- #: includes/class-wp-job-manager-post-types.php:229
971
  msgid "Remove company logo"
972
  msgstr ""
973
 
974
- #: includes/class-wp-job-manager-post-types.php:230
975
  msgid "Use as company logo"
976
  msgstr ""
977
 
978
- #: includes/class-wp-job-manager-post-types.php:232
979
  msgid "This is where you can create and manage %s."
980
  msgstr ""
981
 
982
- #: includes/class-wp-job-manager-post-types.php:263
983
  msgid "Expired <span class=\"count\">(%s)</span>"
984
  msgid_plural "Expired <span class=\"count\">(%s)</span>"
985
  msgstr[0] ""
986
  msgstr[1] ""
987
 
988
- #: includes/class-wp-job-manager-post-types.php:271
989
  msgid "Preview <span class=\"count\">(%s)</span>"
990
  msgid_plural "Preview <span class=\"count\">(%s)</span>"
991
  msgstr[0] ""
@@ -1061,8 +1076,8 @@ msgid "Submit Details"
1061
  msgstr ""
1062
 
1063
  #: includes/forms/class-wp-job-manager-form-submit-job.php:69
1064
- #: includes/forms/class-wp-job-manager-form-submit-job.php:432
1065
- #: templates/job-preview.php:5
1066
  msgid "Preview"
1067
  msgstr ""
1068
 
@@ -1075,7 +1090,7 @@ msgid "Application email"
1075
  msgstr ""
1076
 
1077
  #: includes/forms/class-wp-job-manager-form-submit-job.php:144
1078
- #: wp-job-manager-template.php:384
1079
  msgid "you@yourdomain.com"
1080
  msgstr ""
1081
 
@@ -1084,7 +1099,7 @@ msgid "Application URL"
1084
  msgstr ""
1085
 
1086
  #: includes/forms/class-wp-job-manager-form-submit-job.php:148
1087
- #: includes/forms/class-wp-job-manager-form-submit-job.php:223
1088
  msgid "http://"
1089
  msgstr ""
1090
 
@@ -1112,100 +1127,108 @@ msgstr ""
1112
  msgid "Description"
1113
  msgstr ""
1114
 
1115
- #: includes/forms/class-wp-job-manager-form-submit-job.php:213
1116
  msgid "Company name"
1117
  msgstr ""
1118
 
1119
- #: includes/forms/class-wp-job-manager-form-submit-job.php:216
1120
  msgid "Enter the name of the company"
1121
  msgstr ""
1122
 
1123
- #: includes/forms/class-wp-job-manager-form-submit-job.php:220
1124
- #: templates/content-single-job_listing-company.php:19
1125
  msgid "Website"
1126
  msgstr ""
1127
 
1128
- #: includes/forms/class-wp-job-manager-form-submit-job.php:227
1129
  msgid "Tagline"
1130
  msgstr ""
1131
 
1132
- #: includes/forms/class-wp-job-manager-form-submit-job.php:230
1133
  msgid "Briefly describe your company"
1134
  msgstr ""
1135
 
1136
- #: includes/forms/class-wp-job-manager-form-submit-job.php:235
1137
  msgid "Video"
1138
  msgstr ""
1139
 
1140
- #: includes/forms/class-wp-job-manager-form-submit-job.php:238
1141
  msgid "A link to a video about your company"
1142
  msgstr ""
1143
 
1144
- #: includes/forms/class-wp-job-manager-form-submit-job.php:242
1145
  msgid "Twitter username"
1146
  msgstr ""
1147
 
1148
- #: includes/forms/class-wp-job-manager-form-submit-job.php:245
1149
  msgid "@yourcompany"
1150
  msgstr ""
1151
 
1152
- #: includes/forms/class-wp-job-manager-form-submit-job.php:249
1153
  msgid "Logo"
1154
  msgstr ""
1155
 
1156
- #: includes/forms/class-wp-job-manager-form-submit-job.php:285
1157
  msgid "%s is a required field"
1158
  msgstr ""
1159
 
1160
- #: includes/forms/class-wp-job-manager-form-submit-job.php:295
1161
  msgid "%s is invalid"
1162
  msgstr ""
1163
 
1164
- #: includes/forms/class-wp-job-manager-form-submit-job.php:311
1165
- #: wp-job-manager-functions.php:971
1166
  msgid "\"%s\" (filetype %s) needs to be one of the following file types: %s"
1167
  msgstr ""
1168
 
1169
- #: includes/forms/class-wp-job-manager-form-submit-job.php:326
1170
  msgid "Please enter a valid application email address"
1171
  msgstr ""
1172
 
1173
- #: includes/forms/class-wp-job-manager-form-submit-job.php:335
1174
  msgid "Please enter a valid application URL"
1175
  msgstr ""
1176
 
1177
- #: includes/forms/class-wp-job-manager-form-submit-job.php:345
1178
  msgid "Please enter a valid application email address or URL"
1179
  msgstr ""
1180
 
1181
- #: includes/forms/class-wp-job-manager-form-submit-job.php:463
1182
  msgid "Please enter a username."
1183
  msgstr ""
1184
 
1185
- #: includes/forms/class-wp-job-manager-form-submit-job.php:467
1186
  msgid "Please enter a password."
1187
  msgstr ""
1188
 
1189
- #: includes/forms/class-wp-job-manager-form-submit-job.php:471
1190
  msgid "Please enter your email address."
1191
  msgstr ""
1192
 
1193
- #: includes/forms/class-wp-job-manager-form-submit-job.php:477
1194
  msgid "Passwords must match."
1195
  msgstr ""
1196
 
1197
- #: includes/forms/class-wp-job-manager-form-submit-job.php:482
1198
  msgid "Invalid Password: %s"
1199
  msgstr ""
1200
 
1201
- #: includes/forms/class-wp-job-manager-form-submit-job.php:484
1202
  msgid "Password is not valid."
1203
  msgstr ""
1204
 
1205
- #: includes/forms/class-wp-job-manager-form-submit-job.php:505
1206
  msgid "You must be signed in to post a new listing."
1207
  msgstr ""
1208
 
 
 
 
 
 
 
 
 
1209
  #: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:21
1210
  msgid "Display a list of featured listings on your site."
1211
  msgstr ""
@@ -1235,170 +1258,183 @@ msgstr ""
1235
  msgid "Keyword"
1236
  msgstr ""
1237
 
1238
- #: templates/account-signin.php:4
 
 
 
 
 
 
 
 
 
 
 
 
 
1239
  msgid "Your account"
1240
  msgstr ""
1241
 
1242
- #: templates/account-signin.php:8
1243
  msgid "You are currently signed in as <strong>%s</strong>."
1244
  msgstr ""
1245
 
1246
- #: templates/account-signin.php:11
1247
  msgid "Sign out"
1248
  msgstr ""
1249
 
1250
- #: templates/account-signin.php:21
1251
  msgid "Have an account?"
1252
  msgstr ""
1253
 
1254
- #: templates/account-signin.php:23 templates/job-dashboard-login.php:3
1255
  msgid "Sign in"
1256
  msgstr ""
1257
 
1258
- #: templates/account-signin.php:27
1259
  msgid ""
1260
  "If you don&rsquo;t have an account you can %screate one below by entering "
1261
  "your email address/username. Your account details will be confirmed via "
1262
  "email."
1263
  msgstr ""
1264
 
1265
- #: templates/account-signin.php:27
1266
  msgid "optionally"
1267
  msgstr ""
1268
 
1269
- #: templates/account-signin.php:31
1270
  msgid "You must sign in to create a new listing."
1271
  msgstr ""
1272
 
1273
- #: templates/account-signin.php:42 templates/job-submit.php:32
1274
- #: templates/job-submit.php:49
1275
  msgid "(optional)"
1276
  msgstr ""
1277
 
1278
- #: templates/content-no-jobs-found.php:2
1279
  msgid "There are no listings matching your search."
1280
  msgstr ""
1281
 
1282
- #: templates/content-no-jobs-found.php:4
1283
  msgid "There are currently no vacancies."
1284
  msgstr ""
1285
 
1286
- #: templates/content-single-job_listing-meta.php:36
1287
  msgid "This position has been filled"
1288
  msgstr ""
1289
 
1290
- #: templates/content-single-job_listing-meta.php:38
1291
  msgid "Applications have closed"
1292
  msgstr ""
1293
 
1294
- #: templates/content-single-job_listing.php:6
1295
  msgid "This listing has expired."
1296
  msgstr ""
1297
 
1298
- #: templates/form-fields/file-field.php:29
1299
  msgid "Maximum file size: %s."
1300
  msgstr ""
1301
 
1302
- #: templates/form-fields/multiselect-field.php:3
1303
- #: wp-job-manager-functions.php:759
1304
  msgid "No results match"
1305
  msgstr ""
1306
 
1307
- #: templates/form-fields/multiselect-field.php:3
1308
- #: wp-job-manager-functions.php:760
1309
  msgid "Select Some Options"
1310
  msgstr ""
1311
 
1312
- #: templates/form-fields/uploaded-file-html.php:12
1313
- #: templates/form-fields/uploaded-file-html.php:14
1314
  msgid "remove"
1315
  msgstr ""
1316
 
1317
- #: templates/job-application-email.php:1
1318
  msgid ""
1319
  "To apply for this job <strong>email your details to</strong> <a "
1320
  "class=\"job_application_email\" href=\"mailto:%1$s%2$s\">%1$s</a>"
1321
  msgstr ""
1322
 
1323
- #: templates/job-application-url.php:1
1324
  msgid "To apply for this job please visit the following URL:"
1325
  msgstr ""
1326
 
1327
- #: templates/job-application.php:7
1328
  msgid "Apply for job"
1329
  msgstr ""
1330
 
1331
- #: templates/job-dashboard-login.php:3
1332
  msgid "You need to be signed in to manage your listings."
1333
  msgstr ""
1334
 
1335
- #: templates/job-dashboard.php:2
1336
  msgid "Your listings are shown in the table below."
1337
  msgstr ""
1338
 
1339
- #: templates/job-dashboard.php:14
1340
  msgid "You do not have any active listings."
1341
  msgstr ""
1342
 
1343
- #: templates/job-dashboard.php:36
1344
  msgid "Mark not filled"
1345
  msgstr ""
1346
 
1347
- #: templates/job-dashboard.php:38
1348
  msgid "Mark filled"
1349
  msgstr ""
1350
 
1351
- #: templates/job-dashboard.php:41
1352
  msgid "Duplicate"
1353
  msgstr ""
1354
 
1355
- #: templates/job-dashboard.php:45
1356
  msgid "Relist"
1357
  msgstr ""
1358
 
1359
- #: templates/job-filters.php:12 templates/job-filters.php:13
1360
  msgid "Keywords"
1361
  msgstr ""
1362
 
1363
- #: templates/job-filters.php:27
1364
  msgid "Category"
1365
  msgstr ""
1366
 
1367
- #: templates/job-filters.php:31
1368
  msgid "Any category"
1369
  msgstr ""
1370
 
1371
- #: templates/job-filters.php:44
1372
  msgid ""
1373
  "Your browser does not support JavaScript, or it is disabled. JavaScript "
1374
  "must be enabled in order to view listings."
1375
  msgstr ""
1376
 
1377
- #: templates/job-preview.php:3
1378
  msgid "Submit Listing"
1379
  msgstr ""
1380
 
1381
- #: templates/job-preview.php:4
1382
  msgid "Edit listing"
1383
  msgstr ""
1384
 
1385
- #: templates/job-submit.php:13
1386
  msgid "You are editing an existing job. %s"
1387
  msgstr ""
1388
 
1389
- #: templates/job-submit.php:13
1390
  msgid "Create A New Job"
1391
  msgstr ""
1392
 
1393
- #: templates/job-submit.php:43
1394
  msgid "Company Details"
1395
  msgstr ""
1396
 
1397
- #: templates/job-submitted.php:6
1398
  msgid "%s listed successfully. To view your listing <a href=\"%s\">click here</a>."
1399
  msgstr ""
1400
 
1401
- #: templates/job-submitted.php:9
1402
  msgid "%s submitted successfully. Your listing will be visible once approved."
1403
  msgstr ""
1404
 
@@ -1422,15 +1458,47 @@ msgstr ""
1422
  msgid "This email is already registered, please choose another one."
1423
  msgstr ""
1424
 
1425
- #: wp-job-manager-functions.php:676
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1426
  msgid "Passwords must be at least 8 characters long."
1427
  msgstr ""
1428
 
1429
- #: wp-job-manager-functions.php:758
1430
  msgid "Choose a category&hellip;"
1431
  msgstr ""
1432
 
1433
- #: wp-job-manager-functions.php:973
1434
  msgid "Uploaded files need to be one of the following file types: %s"
1435
  msgstr ""
1436
 
@@ -1442,43 +1510,43 @@ msgstr ""
1442
  msgid "Application via \"%s\" listing on %s"
1443
  msgstr ""
1444
 
1445
- #: wp-job-manager-template.php:358
1446
  msgid "Username"
1447
  msgstr ""
1448
 
1449
- #: wp-job-manager-template.php:366
1450
  msgid "Password"
1451
  msgstr ""
1452
 
1453
- #: wp-job-manager-template.php:376
1454
  msgid "Verify Password"
1455
  msgstr ""
1456
 
1457
- #: wp-job-manager-template.php:383
1458
  msgid "Your email"
1459
  msgstr ""
1460
 
1461
- #: wp-job-manager-template.php:410
1462
  msgid "Posted on "
1463
  msgstr ""
1464
 
1465
- #: wp-job-manager-template.php:412 wp-job-manager-template.php:432
1466
  msgid "Posted %s ago"
1467
  msgstr ""
1468
 
1469
- #: wp-job-manager-template.php:455
1470
  msgid "Anywhere"
1471
  msgstr ""
1472
 
1473
- #: wp-job-manager.php:185
1474
  msgid "Load previous listings"
1475
  msgstr ""
1476
 
1477
- #: wp-job-manager.php:236
1478
  msgid "Invalid file type. Accepted types:"
1479
  msgstr ""
1480
 
1481
- #: wp-job-manager.php:247
1482
  msgid "Are you sure you want to delete this listing?"
1483
  msgstr ""
1484
 
@@ -1500,7 +1568,7 @@ msgstr ""
1500
  msgid "Automattic"
1501
  msgstr ""
1502
 
1503
- #: includes/admin/class-wp-job-manager-admin.php:91
1504
  #. translators: jQuery date format, see
1505
  #. http:api.jqueryui.com/datepicker/#utility-formatDate
1506
  msgctxt "Date format for jQuery datepicker."
@@ -1508,19 +1576,19 @@ msgid "yy-mm-dd"
1508
  msgstr ""
1509
 
1510
  #: includes/admin/class-wp-job-manager-permalink-settings.php:81
1511
- #: wp-job-manager-functions.php:545
1512
  msgctxt "Job permalink - resave permalinks after changing this"
1513
  msgid "job"
1514
  msgstr ""
1515
 
1516
  #: includes/admin/class-wp-job-manager-permalink-settings.php:90
1517
- #: wp-job-manager-functions.php:546
1518
  msgctxt "Job category slug - resave permalinks after changing this"
1519
  msgid "job-category"
1520
  msgstr ""
1521
 
1522
  #: includes/admin/class-wp-job-manager-permalink-settings.php:99
1523
- #: wp-job-manager-functions.php:547
1524
  msgctxt "Job type slug - resave permalinks after changing this"
1525
  msgid "job-type"
1526
  msgstr ""
@@ -1546,18 +1614,18 @@ msgctxt "Date format placeholder."
1546
  msgid "yyyy-mm-dd"
1547
  msgstr ""
1548
 
1549
- #: includes/class-wp-job-manager-post-types.php:197
1550
  msgctxt "Post type archive slug - resave permalinks after changing this"
1551
  msgid "jobs"
1552
  msgstr ""
1553
 
1554
- #: includes/class-wp-job-manager-post-types.php:257
1555
  #: wp-job-manager-functions.php:256
1556
  msgctxt "post status"
1557
  msgid "Expired"
1558
  msgstr ""
1559
 
1560
- #: includes/class-wp-job-manager-post-types.php:266
1561
  #: wp-job-manager-functions.php:257
1562
  msgctxt "post status"
1563
  msgid "Preview"
2
  # This file is distributed under the GPL2+.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: WP Job Manager 1.28.0\n"
6
+ "Report-Msgid-Bugs-To: https://github.com/Automattic/WP-Job-Manager/issues\n"
7
+ "POT-Creation-Date: 2017-08-01 16:44:29+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
  "PO-Revision-Date: 2017-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
+ "Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
14
  "X-Generator: grunt-wp-i18n 0.5.4\n"
15
 
16
  #: includes/admin/class-wp-job-manager-addons.php:82
17
+ #: includes/admin/class-wp-job-manager-admin.php:113
18
  msgid "WP Job Manager Add-ons"
19
  msgstr ""
20
 
26
  msgid "Check out the core add-on bundle &rarr;"
27
  msgstr ""
28
 
29
+ #: includes/admin/class-wp-job-manager-admin.php:110
30
  msgid "Settings"
31
  msgstr ""
32
 
33
+ #: includes/admin/class-wp-job-manager-admin.php:113
34
  msgid "Add-ons"
35
  msgstr ""
36
 
129
  #: includes/admin/class-wp-job-manager-writepanels.php:55
130
  #: includes/forms/class-wp-job-manager-form-submit-job.php:171
131
  #: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:38
132
+ #: templates/job-filters.php:35 templates/job-filters.php:36
133
  msgid "Location"
134
  msgstr ""
135
 
146
  msgstr ""
147
 
148
  #: includes/admin/class-wp-job-manager-cpt.php:364
149
+ #: includes/admin/class-wp-job-manager-settings.php:122
150
  msgid "Categories"
151
  msgstr ""
152
 
192
  msgstr ""
193
 
194
  #: includes/admin/class-wp-job-manager-cpt.php:494
195
+ #: includes/class-wp-job-manager-post-types.php:222
196
+ #: templates/job-dashboard.php:50 templates/job-dashboard.php:68
197
  msgid "Edit"
198
  msgstr ""
199
 
200
  #: includes/admin/class-wp-job-manager-cpt.php:501
201
+ #: templates/job-dashboard.php:73
202
  msgid "Delete"
203
  msgstr ""
204
 
214
  msgid "Job type base"
215
  msgstr ""
216
 
217
+ #: includes/admin/class-wp-job-manager-settings.php:82
218
+ #: includes/class-wp-job-manager-post-types.php:218
219
+ #: includes/class-wp-job-manager-post-types.php:294
220
  msgid "Job Listings"
221
  msgstr ""
222
 
223
+ #: includes/admin/class-wp-job-manager-settings.php:88
224
  msgid "Listings Per Page"
225
  msgstr ""
226
 
227
+ #: includes/admin/class-wp-job-manager-settings.php:89
228
+ msgid "Number of job listings to display per page."
229
  msgstr ""
230
 
231
+ #: includes/admin/class-wp-job-manager-settings.php:95
232
  msgid "Filled Positions"
233
  msgstr ""
234
 
235
+ #: includes/admin/class-wp-job-manager-settings.php:96
236
  msgid "Hide filled positions"
237
  msgstr ""
238
 
239
+ #: includes/admin/class-wp-job-manager-settings.php:97
240
+ msgid "Filled positions will not display in your archives."
241
  msgstr ""
242
 
243
+ #: includes/admin/class-wp-job-manager-settings.php:104
244
  msgid "Hide Expired Listings"
245
  msgstr ""
246
 
247
+ #: includes/admin/class-wp-job-manager-settings.php:105
248
+ msgid "Hide expired listings in job archives/search"
249
  msgstr ""
250
 
251
+ #: includes/admin/class-wp-job-manager-settings.php:106
252
+ msgid "Expired job listings will not be searchable."
253
  msgstr ""
254
 
255
+ #: includes/admin/class-wp-job-manager-settings.php:113
256
  msgid "Hide Expired Listings Content"
257
  msgstr ""
258
 
259
+ #: includes/admin/class-wp-job-manager-settings.php:114
260
+ msgid "Hide content in expired single job listings"
261
  msgstr ""
262
 
263
+ #: includes/admin/class-wp-job-manager-settings.php:115
264
  msgid ""
265
+ "Your site will display the titles of expired listings, but not the content "
266
+ "of the listings. Otherwise, expired listings display their full content "
267
+ "minus the application area."
268
  msgstr ""
269
 
270
+ #: includes/admin/class-wp-job-manager-settings.php:123
271
+ msgid "Enable listing categories"
272
  msgstr ""
273
 
274
+ #: includes/admin/class-wp-job-manager-settings.php:124
275
  msgid ""
276
+ "This lets users select from a list of categories when submitting a job. "
277
+ "Note: an admin has to create categories before site users can select them."
278
  msgstr ""
279
 
280
+ #: includes/admin/class-wp-job-manager-settings.php:131
281
  msgid "Multi-select Categories"
282
  msgstr ""
283
 
284
+ #: includes/admin/class-wp-job-manager-settings.php:132
285
+ msgid "Default to category multiselect"
286
  msgstr ""
287
 
288
+ #: includes/admin/class-wp-job-manager-settings.php:133
289
  msgid ""
290
+ "The category selection box will default to allowing multiple selections on "
291
+ "the [jobs] shortcode. Without this, users will only be able to select a "
292
+ "single category when submitting jobs."
293
  msgstr ""
294
 
295
+ #: includes/admin/class-wp-job-manager-settings.php:140
296
  msgid "Category Filter Type"
297
  msgstr ""
298
 
299
+ #: includes/admin/class-wp-job-manager-settings.php:141
300
  msgid ""
301
  "Determines the logic used to display jobs when selecting multiple "
302
  "categories."
303
  msgstr ""
304
 
305
+ #: includes/admin/class-wp-job-manager-settings.php:144
306
  msgid "Jobs will be shown if within ANY selected category"
307
  msgstr ""
308
 
309
+ #: includes/admin/class-wp-job-manager-settings.php:145
310
  msgid "Jobs will be shown if within ALL selected categories"
311
  msgstr ""
312
 
313
+ #: includes/admin/class-wp-job-manager-settings.php:151
314
+ msgid "Types"
315
  msgstr ""
316
 
317
+ #: includes/admin/class-wp-job-manager-settings.php:152
318
+ msgid "Enable listing types"
 
 
319
  msgstr ""
320
 
321
+ #: includes/admin/class-wp-job-manager-settings.php:153
322
+ msgid ""
323
+ "This lets users select from a list of types when submitting a job. Note: an "
324
+ "admin has to create types before site users can select them."
325
  msgstr ""
326
 
327
+ #: includes/admin/class-wp-job-manager-settings.php:160
328
+ msgid "Multi-select Listing Types"
329
  msgstr ""
330
 
331
+ #: includes/admin/class-wp-job-manager-settings.php:161
332
+ msgid "Allow multiple types for listings"
333
  msgstr ""
334
 
335
+ #: includes/admin/class-wp-job-manager-settings.php:162
336
+ msgid ""
337
+ "This allows users to select more than one type when submitting a job. The "
338
+ "metabox on the post editor and the selection box on the front-end job "
339
+ "submission form will both reflect this."
340
  msgstr ""
341
 
342
+ #: includes/admin/class-wp-job-manager-settings.php:169
343
+ msgid "Date Format"
 
 
344
  msgstr ""
345
 
346
+ #: includes/admin/class-wp-job-manager-settings.php:170
347
+ msgid ""
348
+ "Choose how you want the published date for jobs to be displayed on the "
349
+ "front-end."
350
  msgstr ""
351
 
352
+ #: includes/admin/class-wp-job-manager-settings.php:173
353
+ msgid "Relative to the current date (e.g., 1 day, 1 week, 1 month ago)"
354
  msgstr ""
355
 
356
+ #: includes/admin/class-wp-job-manager-settings.php:174
357
+ msgid "Default date format as defined in Settings"
 
 
 
358
  msgstr ""
359
 
360
+ #: includes/admin/class-wp-job-manager-settings.php:180
361
  msgid "Google Maps API Key"
362
  msgstr ""
363
 
364
+ #: includes/admin/class-wp-job-manager-settings.php:181
365
  msgid ""
366
  "Google requires an API key to retrieve location information for job "
367
  "listings. Acquire an API key from the <a href=\"%s\">Google Maps API "
368
  "developer site</a>."
369
  msgstr ""
370
 
371
+ #: includes/admin/class-wp-job-manager-settings.php:187
372
  msgid "Job Submission"
373
  msgstr ""
374
 
375
+ #: includes/admin/class-wp-job-manager-settings.php:192
376
  msgid "Account Required"
377
  msgstr ""
378
 
379
+ #: includes/admin/class-wp-job-manager-settings.php:193
380
+ msgid "Require an account to submit listings"
381
  msgstr ""
382
 
383
+ #: includes/admin/class-wp-job-manager-settings.php:194
384
+ msgid "Limits job listing submissions to registered, logged-in users."
 
 
385
  msgstr ""
386
 
387
+ #: includes/admin/class-wp-job-manager-settings.php:201
388
  msgid "Account Creation"
389
  msgstr ""
390
 
391
+ #: includes/admin/class-wp-job-manager-settings.php:202
392
+ msgid "Enable account creation during submission"
393
  msgstr ""
394
 
395
+ #: includes/admin/class-wp-job-manager-settings.php:203
396
  msgid ""
397
+ "Includes account creation on the listing submission form, to allow "
398
+ "non-registered users to create an account and submit a job listing "
399
+ "simultaneously."
400
  msgstr ""
401
 
402
+ #: includes/admin/class-wp-job-manager-settings.php:210
403
  msgid "Account Username"
404
  msgstr ""
405
 
406
+ #: includes/admin/class-wp-job-manager-settings.php:211
407
+ msgid "Generate usernames from email addresses"
408
  msgstr ""
409
 
410
+ #: includes/admin/class-wp-job-manager-settings.php:212
411
  msgid ""
412
+ "Automatically generates usernames for new accounts from the registrant's "
413
+ "email address. If this is not enabled, a \"username\" field will display "
414
+ "instead."
415
  msgstr ""
416
 
417
+ #: includes/admin/class-wp-job-manager-settings.php:219
418
  msgid "Account Password"
419
  msgstr ""
420
 
421
+ #: includes/admin/class-wp-job-manager-settings.php:220
422
+ msgid "Email new users a link to set a password"
423
  msgstr ""
424
 
425
+ #: includes/admin/class-wp-job-manager-settings.php:221
426
  msgid ""
427
+ "Sends an email to the user with their username and a link to set their "
428
+ "password. If this is not enabled, a \"password\" field will display "
429
+ "instead, and their email address won't be verified."
430
  msgstr ""
431
 
432
+ #: includes/admin/class-wp-job-manager-settings.php:228
433
  msgid "Account Role"
434
  msgstr ""
435
 
436
+ #: includes/admin/class-wp-job-manager-settings.php:229
437
  msgid ""
438
+ "Any new accounts created during submission will have this role. If you "
439
+ "haven't enabled account creation during submission in the options above, "
440
+ "your own method of assigning roles will apply."
441
  msgstr ""
442
 
443
+ #: includes/admin/class-wp-job-manager-settings.php:236
444
  msgid "Moderate New Listings"
445
  msgstr ""
446
 
447
+ #: includes/admin/class-wp-job-manager-settings.php:237
448
+ msgid "Require admin approval of all new listing submissions"
449
  msgstr ""
450
 
451
+ #: includes/admin/class-wp-job-manager-settings.php:238
452
+ msgid ""
453
+ "Sets all new submissions to \"pending.\" They will not appear on your site "
454
+ "until an admin approves them."
455
  msgstr ""
456
 
457
+ #: includes/admin/class-wp-job-manager-settings.php:245
458
  msgid "Allow Pending Edits"
459
  msgstr ""
460
 
461
+ #: includes/admin/class-wp-job-manager-settings.php:246
462
+ msgid "Allow editing of pending listings"
463
  msgstr ""
464
 
465
+ #: includes/admin/class-wp-job-manager-settings.php:247
466
+ msgid ""
467
+ "Users can continue to edit pending listings until they are approved by an "
468
+ "admin."
469
  msgstr ""
470
 
471
+ #: includes/admin/class-wp-job-manager-settings.php:254
472
  msgid "Listing Duration"
473
  msgstr ""
474
 
475
+ #: includes/admin/class-wp-job-manager-settings.php:255
476
  msgid ""
477
+ "Listings will display for the set number of days, then expire. Leave this "
478
+ "field blank if you don't want listings to have an expiration date."
479
  msgstr ""
480
 
481
+ #: includes/admin/class-wp-job-manager-settings.php:261
482
  msgid "Application Method"
483
  msgstr ""
484
 
485
+ #: includes/admin/class-wp-job-manager-settings.php:262
486
+ msgid ""
487
+ "Choose the application method job listers will need to provide. Specify URL "
488
+ "or email address only, or allow listers to choose which they prefer."
489
  msgstr ""
490
 
491
+ #: includes/admin/class-wp-job-manager-settings.php:265
492
  msgid "Email address or website URL"
493
  msgstr ""
494
 
495
+ #: includes/admin/class-wp-job-manager-settings.php:266
496
  msgid "Email addresses only"
497
  msgstr ""
498
 
499
+ #: includes/admin/class-wp-job-manager-settings.php:267
500
  msgid "Website URLs only"
501
  msgstr ""
502
 
503
+ #: includes/admin/class-wp-job-manager-settings.php:273
504
  msgid "Pages"
505
  msgstr ""
506
 
507
+ #: includes/admin/class-wp-job-manager-settings.php:278
508
  msgid "Submit Job Form Page"
509
  msgstr ""
510
 
511
+ #: includes/admin/class-wp-job-manager-settings.php:279
512
  msgid ""
513
+ "Select the page where you've used the [submit_job_form] shortcode. This "
514
+ "lets the plugin know the location of the form."
515
  msgstr ""
516
 
517
+ #: includes/admin/class-wp-job-manager-settings.php:285
518
  msgid "Job Dashboard Page"
519
  msgstr ""
520
 
521
+ #: includes/admin/class-wp-job-manager-settings.php:286
522
  msgid ""
523
+ "Select the page where you've used the [job_dashboard] shortcode. This lets "
524
+ "the plugin know the location of the dashboard."
525
  msgstr ""
526
 
527
+ #: includes/admin/class-wp-job-manager-settings.php:292
528
  msgid "Job Listings Page"
529
  msgstr ""
530
 
531
+ #: includes/admin/class-wp-job-manager-settings.php:293
532
  msgid ""
533
+ "Select the page where you've used the [jobs] shortcode. This lets the "
534
+ "plugin know the location of the job listings page."
535
  msgstr ""
536
 
537
+ #: includes/admin/class-wp-job-manager-settings.php:339
538
  msgid "Settings successfully saved"
539
  msgstr ""
540
 
541
+ #: includes/admin/class-wp-job-manager-settings.php:415
542
  msgid "--no page--"
543
  msgstr ""
544
 
545
+ #: includes/admin/class-wp-job-manager-settings.php:420
546
  msgid "Select a page&hellip;"
547
  msgstr ""
548
 
549
+ #: includes/admin/class-wp-job-manager-settings.php:466
550
  msgid "Save Changes"
551
  msgstr ""
552
 
732
  msgid "Help other users on the forums"
733
  msgstr ""
734
 
735
+ #: includes/admin/class-wp-job-manager-taxonomy-meta.php:78
736
+ #: includes/admin/class-wp-job-manager-taxonomy-meta.php:100
737
+ #: includes/admin/class-wp-job-manager-taxonomy-meta.php:118
738
+ msgid "Employment Type"
739
+ msgstr ""
740
+
741
  #: includes/admin/class-wp-job-manager-writepanels.php:56
742
  #: includes/forms/class-wp-job-manager-form-submit-job.php:175
743
  msgid "e.g. \"London\""
875
  msgid "Geocoding error"
876
  msgstr ""
877
 
878
+ #: includes/class-wp-job-manager-install.php:65
879
  msgid "Employer"
880
  msgstr ""
881
 
882
+ #: includes/class-wp-job-manager-post-types.php:98
883
  #: includes/forms/class-wp-job-manager-form-submit-job.php:188
884
  msgid "Job category"
885
  msgstr ""
886
 
887
+ #: includes/class-wp-job-manager-post-types.php:99
888
  msgid "Job categories"
889
  msgstr ""
890
 
891
+ #: includes/class-wp-job-manager-post-types.php:123
892
+ #: includes/class-wp-job-manager-post-types.php:171
893
+ #: includes/class-wp-job-manager-post-types.php:227
894
  msgid "Search %s"
895
  msgstr ""
896
 
897
+ #: includes/class-wp-job-manager-post-types.php:124
898
+ #: includes/class-wp-job-manager-post-types.php:172
899
+ #: includes/class-wp-job-manager-post-types.php:219
900
  msgid "All %s"
901
  msgstr ""
902
 
903
+ #: includes/class-wp-job-manager-post-types.php:125
904
+ #: includes/class-wp-job-manager-post-types.php:173
905
+ #: includes/class-wp-job-manager-post-types.php:230
906
  msgid "Parent %s"
907
  msgstr ""
908
 
909
+ #: includes/class-wp-job-manager-post-types.php:126
910
+ #: includes/class-wp-job-manager-post-types.php:174
911
  msgid "Parent %s:"
912
  msgstr ""
913
 
914
+ #: includes/class-wp-job-manager-post-types.php:127
915
+ #: includes/class-wp-job-manager-post-types.php:175
916
+ #: includes/class-wp-job-manager-post-types.php:223
917
  msgid "Edit %s"
918
  msgstr ""
919
 
920
+ #: includes/class-wp-job-manager-post-types.php:128
921
+ #: includes/class-wp-job-manager-post-types.php:176
922
  msgid "Update %s"
923
  msgstr ""
924
 
925
+ #: includes/class-wp-job-manager-post-types.php:129
926
+ #: includes/class-wp-job-manager-post-types.php:177
927
  msgid "Add New %s"
928
  msgstr ""
929
 
930
+ #: includes/class-wp-job-manager-post-types.php:130
931
+ #: includes/class-wp-job-manager-post-types.php:178
932
  msgid "New %s Name"
933
  msgstr ""
934
 
935
+ #: includes/class-wp-job-manager-post-types.php:147
936
  #: includes/forms/class-wp-job-manager-form-submit-job.php:179
937
  msgid "Job type"
938
  msgstr ""
939
 
940
+ #: includes/class-wp-job-manager-post-types.php:148
941
  msgid "Job types"
942
  msgstr ""
943
 
944
+ #: includes/class-wp-job-manager-post-types.php:197
945
  msgid "Job"
946
  msgstr ""
947
 
948
+ #: includes/class-wp-job-manager-post-types.php:198
949
  msgid "Jobs"
950
  msgstr ""
951
 
952
+ #: includes/class-wp-job-manager-post-types.php:220
953
  msgid "Add New"
954
  msgstr ""
955
 
956
+ #: includes/class-wp-job-manager-post-types.php:221
957
  msgid "Add %s"
958
  msgstr ""
959
 
960
+ #: includes/class-wp-job-manager-post-types.php:224
961
  msgid "New %s"
962
  msgstr ""
963
 
964
+ #: includes/class-wp-job-manager-post-types.php:225
965
+ #: includes/class-wp-job-manager-post-types.php:226
966
  msgid "View %s"
967
  msgstr ""
968
 
969
+ #: includes/class-wp-job-manager-post-types.php:228
970
  msgid "No %s found"
971
  msgstr ""
972
 
973
+ #: includes/class-wp-job-manager-post-types.php:229
974
  msgid "No %s found in trash"
975
  msgstr ""
976
 
977
+ #: includes/class-wp-job-manager-post-types.php:231
978
  msgid "Company Logo"
979
  msgstr ""
980
 
981
+ #: includes/class-wp-job-manager-post-types.php:232
982
  msgid "Set company logo"
983
  msgstr ""
984
 
985
+ #: includes/class-wp-job-manager-post-types.php:233
986
  msgid "Remove company logo"
987
  msgstr ""
988
 
989
+ #: includes/class-wp-job-manager-post-types.php:234
990
  msgid "Use as company logo"
991
  msgstr ""
992
 
993
+ #: includes/class-wp-job-manager-post-types.php:236
994
  msgid "This is where you can create and manage %s."
995
  msgstr ""
996
 
997
+ #: includes/class-wp-job-manager-post-types.php:267
998
  msgid "Expired <span class=\"count\">(%s)</span>"
999
  msgid_plural "Expired <span class=\"count\">(%s)</span>"
1000
  msgstr[0] ""
1001
  msgstr[1] ""
1002
 
1003
+ #: includes/class-wp-job-manager-post-types.php:275
1004
  msgid "Preview <span class=\"count\">(%s)</span>"
1005
  msgid_plural "Preview <span class=\"count\">(%s)</span>"
1006
  msgstr[0] ""
1076
  msgstr ""
1077
 
1078
  #: includes/forms/class-wp-job-manager-form-submit-job.php:69
1079
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:434
1080
+ #: templates/job-preview.php:22
1081
  msgid "Preview"
1082
  msgstr ""
1083
 
1090
  msgstr ""
1091
 
1092
  #: includes/forms/class-wp-job-manager-form-submit-job.php:144
1093
+ #: wp-job-manager-template.php:641
1094
  msgid "you@yourdomain.com"
1095
  msgstr ""
1096
 
1099
  msgstr ""
1100
 
1101
  #: includes/forms/class-wp-job-manager-form-submit-job.php:148
1102
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:222
1103
  msgid "http://"
1104
  msgstr ""
1105
 
1127
  msgid "Description"
1128
  msgstr ""
1129
 
1130
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:212
1131
  msgid "Company name"
1132
  msgstr ""
1133
 
1134
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:215
1135
  msgid "Enter the name of the company"
1136
  msgstr ""
1137
 
1138
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:219
1139
+ #: templates/content-single-job_listing-company.php:30
1140
  msgid "Website"
1141
  msgstr ""
1142
 
1143
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:226
1144
  msgid "Tagline"
1145
  msgstr ""
1146
 
1147
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:229
1148
  msgid "Briefly describe your company"
1149
  msgstr ""
1150
 
1151
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:234
1152
  msgid "Video"
1153
  msgstr ""
1154
 
1155
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:237
1156
  msgid "A link to a video about your company"
1157
  msgstr ""
1158
 
1159
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:241
1160
  msgid "Twitter username"
1161
  msgstr ""
1162
 
1163
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:244
1164
  msgid "@yourcompany"
1165
  msgstr ""
1166
 
1167
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:248
1168
  msgid "Logo"
1169
  msgstr ""
1170
 
1171
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:284
1172
  msgid "%s is a required field"
1173
  msgstr ""
1174
 
1175
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:294
1176
  msgid "%s is invalid"
1177
  msgstr ""
1178
 
1179
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:310
1180
+ #: wp-job-manager-functions.php:1002
1181
  msgid "\"%s\" (filetype %s) needs to be one of the following file types: %s"
1182
  msgstr ""
1183
 
1184
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:325
1185
  msgid "Please enter a valid application email address"
1186
  msgstr ""
1187
 
1188
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:334
1189
  msgid "Please enter a valid application URL"
1190
  msgstr ""
1191
 
1192
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:344
1193
  msgid "Please enter a valid application email address or URL"
1194
  msgstr ""
1195
 
1196
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:465
1197
  msgid "Please enter a username."
1198
  msgstr ""
1199
 
1200
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:469
1201
  msgid "Please enter a password."
1202
  msgstr ""
1203
 
1204
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:473
1205
  msgid "Please enter your email address."
1206
  msgstr ""
1207
 
1208
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:479
1209
  msgid "Passwords must match."
1210
  msgstr ""
1211
 
1212
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:484
1213
  msgid "Invalid Password: %s"
1214
  msgstr ""
1215
 
1216
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:486
1217
  msgid "Password is not valid."
1218
  msgstr ""
1219
 
1220
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:507
1221
  msgid "You must be signed in to post a new listing."
1222
  msgstr ""
1223
 
1224
+ #: includes/rest-api/class-wp-job-manager-controllers-status.php:52
1225
+ msgid "Not Found"
1226
+ msgstr ""
1227
+
1228
+ #: includes/rest-api/class-wp-job-manager-models-settings.php:72
1229
+ msgid "Invalid page ID provided"
1230
+ msgstr ""
1231
+
1232
  #: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:21
1233
  msgid "Display a list of featured listings on your site."
1234
  msgstr ""
1258
  msgid "Keyword"
1259
  msgstr ""
1260
 
1261
+ #: lib/wpjm_rest/class-wp-job-manager-rest-model.php:207
1262
+ #. translators: %s is usually a field name.
1263
+ msgid "%s cannot be empty"
1264
+ msgstr ""
1265
+
1266
+ #: lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-crud.php:48
1267
+ msgid "Model not found"
1268
+ msgstr ""
1269
+
1270
+ #: lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-settings.php:35
1271
+ msgid "Settings not found"
1272
+ msgstr ""
1273
+
1274
+ #: templates/account-signin.php:21
1275
  msgid "Your account"
1276
  msgstr ""
1277
 
1278
+ #: templates/account-signin.php:25
1279
  msgid "You are currently signed in as <strong>%s</strong>."
1280
  msgstr ""
1281
 
1282
+ #: templates/account-signin.php:28
1283
  msgid "Sign out"
1284
  msgstr ""
1285
 
1286
+ #: templates/account-signin.php:38
1287
  msgid "Have an account?"
1288
  msgstr ""
1289
 
1290
+ #: templates/account-signin.php:40 templates/job-dashboard-login.php:20
1291
  msgid "Sign in"
1292
  msgstr ""
1293
 
1294
+ #: templates/account-signin.php:44
1295
  msgid ""
1296
  "If you don&rsquo;t have an account you can %screate one below by entering "
1297
  "your email address/username. Your account details will be confirmed via "
1298
  "email."
1299
  msgstr ""
1300
 
1301
+ #: templates/account-signin.php:44
1302
  msgid "optionally"
1303
  msgstr ""
1304
 
1305
+ #: templates/account-signin.php:48
1306
  msgid "You must sign in to create a new listing."
1307
  msgstr ""
1308
 
1309
+ #: templates/account-signin.php:59 templates/job-submit.php:43
1310
+ #: templates/job-submit.php:60
1311
  msgid "(optional)"
1312
  msgstr ""
1313
 
1314
+ #: templates/content-no-jobs-found.php:20
1315
  msgid "There are no listings matching your search."
1316
  msgstr ""
1317
 
1318
+ #: templates/content-no-jobs-found.php:22
1319
  msgid "There are currently no vacancies."
1320
  msgstr ""
1321
 
1322
+ #: templates/content-single-job_listing-meta.php:42
1323
  msgid "This position has been filled"
1324
  msgstr ""
1325
 
1326
+ #: templates/content-single-job_listing-meta.php:44
1327
  msgid "Applications have closed"
1328
  msgstr ""
1329
 
1330
+ #: templates/content-single-job_listing.php:23
1331
  msgid "This listing has expired."
1332
  msgstr ""
1333
 
1334
+ #: templates/form-fields/file-field.php:45
1335
  msgid "Maximum file size: %s."
1336
  msgstr ""
1337
 
1338
+ #: templates/form-fields/multiselect-field.php:20
1339
+ #: wp-job-manager-functions.php:790
1340
  msgid "No results match"
1341
  msgstr ""
1342
 
1343
+ #: templates/form-fields/multiselect-field.php:20
1344
+ #: wp-job-manager-functions.php:791
1345
  msgid "Select Some Options"
1346
  msgstr ""
1347
 
1348
+ #: templates/form-fields/uploaded-file-html.php:29
1349
+ #: templates/form-fields/uploaded-file-html.php:31
1350
  msgid "remove"
1351
  msgstr ""
1352
 
1353
+ #: templates/job-application-email.php:18
1354
  msgid ""
1355
  "To apply for this job <strong>email your details to</strong> <a "
1356
  "class=\"job_application_email\" href=\"mailto:%1$s%2$s\">%1$s</a>"
1357
  msgstr ""
1358
 
1359
+ #: templates/job-application-url.php:18
1360
  msgid "To apply for this job please visit the following URL:"
1361
  msgstr ""
1362
 
1363
+ #: templates/job-application.php:24
1364
  msgid "Apply for job"
1365
  msgstr ""
1366
 
1367
+ #: templates/job-dashboard-login.php:20
1368
  msgid "You need to be signed in to manage your listings."
1369
  msgstr ""
1370
 
1371
+ #: templates/job-dashboard.php:19
1372
  msgid "Your listings are shown in the table below."
1373
  msgstr ""
1374
 
1375
+ #: templates/job-dashboard.php:31
1376
  msgid "You do not have any active listings."
1377
  msgstr ""
1378
 
1379
+ #: templates/job-dashboard.php:53
1380
  msgid "Mark not filled"
1381
  msgstr ""
1382
 
1383
+ #: templates/job-dashboard.php:55
1384
  msgid "Mark filled"
1385
  msgstr ""
1386
 
1387
+ #: templates/job-dashboard.php:58
1388
  msgid "Duplicate"
1389
  msgstr ""
1390
 
1391
+ #: templates/job-dashboard.php:62
1392
  msgid "Relist"
1393
  msgstr ""
1394
 
1395
+ #: templates/job-filters.php:30 templates/job-filters.php:31
1396
  msgid "Keywords"
1397
  msgstr ""
1398
 
1399
+ #: templates/job-filters.php:45
1400
  msgid "Category"
1401
  msgstr ""
1402
 
1403
+ #: templates/job-filters.php:49
1404
  msgid "Any category"
1405
  msgstr ""
1406
 
1407
+ #: templates/job-filters.php:62
1408
  msgid ""
1409
  "Your browser does not support JavaScript, or it is disabled. JavaScript "
1410
  "must be enabled in order to view listings."
1411
  msgstr ""
1412
 
1413
+ #: templates/job-preview.php:20
1414
  msgid "Submit Listing"
1415
  msgstr ""
1416
 
1417
+ #: templates/job-preview.php:21
1418
  msgid "Edit listing"
1419
  msgstr ""
1420
 
1421
+ #: templates/job-submit.php:24
1422
  msgid "You are editing an existing job. %s"
1423
  msgstr ""
1424
 
1425
+ #: templates/job-submit.php:24
1426
  msgid "Create A New Job"
1427
  msgstr ""
1428
 
1429
+ #: templates/job-submit.php:54
1430
  msgid "Company Details"
1431
  msgstr ""
1432
 
1433
+ #: templates/job-submitted.php:22
1434
  msgid "%s listed successfully. To view your listing <a href=\"%s\">click here</a>."
1435
  msgstr ""
1436
 
1437
+ #: templates/job-submitted.php:25
1438
  msgid "%s submitted successfully. Your listing will be visible once approved."
1439
  msgstr ""
1440
 
1458
  msgid "This email is already registered, please choose another one."
1459
  msgstr ""
1460
 
1461
+ #: wp-job-manager-functions.php:633
1462
+ msgid "Full Time"
1463
+ msgstr ""
1464
+
1465
+ #: wp-job-manager-functions.php:634
1466
+ msgid "Part Time"
1467
+ msgstr ""
1468
+
1469
+ #: wp-job-manager-functions.php:635
1470
+ msgid "Contractor"
1471
+ msgstr ""
1472
+
1473
+ #: wp-job-manager-functions.php:636
1474
+ msgid "Temporary"
1475
+ msgstr ""
1476
+
1477
+ #: wp-job-manager-functions.php:637
1478
+ msgid "Intern"
1479
+ msgstr ""
1480
+
1481
+ #: wp-job-manager-functions.php:638
1482
+ msgid "Volunteer"
1483
+ msgstr ""
1484
+
1485
+ #: wp-job-manager-functions.php:639
1486
+ msgid "Per Diem"
1487
+ msgstr ""
1488
+
1489
+ #: wp-job-manager-functions.php:640
1490
+ msgid "Other"
1491
+ msgstr ""
1492
+
1493
+ #: wp-job-manager-functions.php:707
1494
  msgid "Passwords must be at least 8 characters long."
1495
  msgstr ""
1496
 
1497
+ #: wp-job-manager-functions.php:789
1498
  msgid "Choose a category&hellip;"
1499
  msgstr ""
1500
 
1501
+ #: wp-job-manager-functions.php:1004
1502
  msgid "Uploaded files need to be one of the following file types: %s"
1503
  msgstr ""
1504
 
1510
  msgid "Application via \"%s\" listing on %s"
1511
  msgstr ""
1512
 
1513
+ #: wp-job-manager-template.php:615
1514
  msgid "Username"
1515
  msgstr ""
1516
 
1517
+ #: wp-job-manager-template.php:623
1518
  msgid "Password"
1519
  msgstr ""
1520
 
1521
+ #: wp-job-manager-template.php:633
1522
  msgid "Verify Password"
1523
  msgstr ""
1524
 
1525
+ #: wp-job-manager-template.php:640
1526
  msgid "Your email"
1527
  msgstr ""
1528
 
1529
+ #: wp-job-manager-template.php:667
1530
  msgid "Posted on "
1531
  msgstr ""
1532
 
1533
+ #: wp-job-manager-template.php:669 wp-job-manager-template.php:689
1534
  msgid "Posted %s ago"
1535
  msgstr ""
1536
 
1537
+ #: wp-job-manager-template.php:712
1538
  msgid "Anywhere"
1539
  msgstr ""
1540
 
1541
+ #: wp-job-manager.php:209
1542
  msgid "Load previous listings"
1543
  msgstr ""
1544
 
1545
+ #: wp-job-manager.php:260
1546
  msgid "Invalid file type. Accepted types:"
1547
  msgstr ""
1548
 
1549
+ #: wp-job-manager.php:271
1550
  msgid "Are you sure you want to delete this listing?"
1551
  msgstr ""
1552
 
1568
  msgid "Automattic"
1569
  msgstr ""
1570
 
1571
+ #: includes/admin/class-wp-job-manager-admin.php:99
1572
  #. translators: jQuery date format, see
1573
  #. http:api.jqueryui.com/datepicker/#utility-formatDate
1574
  msgctxt "Date format for jQuery datepicker."
1576
  msgstr ""
1577
 
1578
  #: includes/admin/class-wp-job-manager-permalink-settings.php:81
1579
+ #: includes/class-wp-job-manager-post-types.php:641
1580
  msgctxt "Job permalink - resave permalinks after changing this"
1581
  msgid "job"
1582
  msgstr ""
1583
 
1584
  #: includes/admin/class-wp-job-manager-permalink-settings.php:90
1585
+ #: includes/class-wp-job-manager-post-types.php:642
1586
  msgctxt "Job category slug - resave permalinks after changing this"
1587
  msgid "job-category"
1588
  msgstr ""
1589
 
1590
  #: includes/admin/class-wp-job-manager-permalink-settings.php:99
1591
+ #: includes/class-wp-job-manager-post-types.php:643
1592
  msgctxt "Job type slug - resave permalinks after changing this"
1593
  msgid "job-type"
1594
  msgstr ""
1614
  msgid "yyyy-mm-dd"
1615
  msgstr ""
1616
 
1617
+ #: includes/class-wp-job-manager-post-types.php:201
1618
  msgctxt "Post type archive slug - resave permalinks after changing this"
1619
  msgid "jobs"
1620
  msgstr ""
1621
 
1622
+ #: includes/class-wp-job-manager-post-types.php:261
1623
  #: wp-job-manager-functions.php:256
1624
  msgctxt "post status"
1625
  msgid "Expired"
1626
  msgstr ""
1627
 
1628
+ #: includes/class-wp-job-manager-post-types.php:270
1629
  #: wp-job-manager-functions.php:257
1630
  msgctxt "post status"
1631
  msgid "Preview"
lib/wpjm_rest/class-wp-job-manager-rest-bootstrap.php ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Bootstrap
4
+ *
5
+ * Loads classes and creates an Environment subclass instance from
6
+ * the specified lib location, with the specified prefix
7
+ *
8
+ * @package Mixtape
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
+
15
+ /**
16
+ * Class WP_Job_Manager_REST_Bootstrap
17
+ *
18
+ * This is the entry point for.
19
+ */
20
+ class WP_Job_Manager_REST_Bootstrap {
21
+ const MINIMUM_PHP_VERSION = '5.3.0';
22
+
23
+ /**
24
+ * The Environment we will use
25
+ *
26
+ * @var null|object the Environment implementation.
27
+ */
28
+ private $environment = null;
29
+
30
+ /**
31
+ * The class loader we will use
32
+ *
33
+ * @var null|WP_Job_Manager_REST_Classloader
34
+ */
35
+ private $class_loader = null;
36
+
37
+ /**
38
+ * Construct a new Bootstrap
39
+ *
40
+ * @param null|WP_Job_Manager_REST_Interfaces_Classloader $class_loader The class loader to use.
41
+ */
42
+ private function __construct( $class_loader = null ) {
43
+ $this->class_loader = $class_loader;
44
+ }
45
+
46
+ /**
47
+ * Check compatibility of PHP Version.
48
+ *
49
+ * @return bool
50
+ */
51
+ public function is_compatible() {
52
+ return version_compare( phpversion(), self::MINIMUM_PHP_VERSION, '>=' );
53
+ }
54
+
55
+ /**
56
+ * Create a Bootstrap, unless we are using a really early php version (< 5.3.0)
57
+ *
58
+ * @param WP_Job_Manager_REST_Interfaces_Classloader|null $class_loader The class loader to use.
59
+ * @return WP_Job_Manager_REST_Bootstrap|null
60
+ */
61
+ public static function create( $class_loader = null ) {
62
+ if ( empty( $class_loader ) ) {
63
+ include_once( 'interfaces/class-wp-job-manager-rest-interfaces-classloader.php' );
64
+ include_once( 'class-wp-job-manager-rest-classloader.php' );
65
+ $prefix = str_replace( '_Bootstrap', '', __CLASS__ );
66
+ $base_dir = untrailingslashit( dirname( __FILE__ ) );
67
+ $class_loader = new WP_Job_Manager_REST_Classloader( $prefix, $base_dir );
68
+ }
69
+ return new self( $class_loader );
70
+ }
71
+
72
+ /**
73
+ * Optional: Instead of calling load() you can
74
+ * register as an auto-loader
75
+ *
76
+ * @return WP_Job_Manager_REST_Bootstrap $this
77
+ */
78
+ function register_autoload() {
79
+ if ( function_exists( 'spl_autoload_register' ) ) {
80
+ spl_autoload_register( array( $this->class_loader(), 'load_class' ), true );
81
+ }
82
+ return $this;
83
+ }
84
+
85
+ /**
86
+ * Loads all classes
87
+ *
88
+ * @return WP_Job_Manager_REST_Bootstrap $this
89
+ * @throws Exception In case a class/file is not found.
90
+ */
91
+ function load() {
92
+ $this->class_loader()
93
+ ->load_class( 'Interfaces_Data_Store' )
94
+ ->load_class( 'Interfaces_Registrable' )
95
+ ->load_class( 'Interfaces_Type' )
96
+ ->load_class( 'Interfaces_Model' )
97
+ ->load_class( 'Interfaces_Builder' )
98
+ ->load_class( 'Interfaces_Model_Collection' )
99
+ ->load_class( 'Interfaces_Controller' )
100
+ ->load_class( 'Interfaces_Controller_Bundle' )
101
+ ->load_class( 'Interfaces_Permissions_Provider' )
102
+ ->load_class( 'Exception' )
103
+ ->load_class( 'Expect' )
104
+ ->load_class( 'Environment' )
105
+ ->load_class( 'Type' )
106
+ ->load_class( 'Type_String' )
107
+ ->load_class( 'Type_Integer' )
108
+ ->load_class( 'Type_Number' )
109
+ ->load_class( 'Type_Boolean' )
110
+ ->load_class( 'Type_Array' )
111
+ ->load_class( 'Type_TypedArray' )
112
+ ->load_class( 'Type_Nullable' )
113
+ ->load_class( 'Type_Registry' )
114
+ ->load_class( 'Data_Store_Nil' )
115
+ ->load_class( 'Data_Store_Abstract' )
116
+ ->load_class( 'Data_Store_CustomPostType' )
117
+ ->load_class( 'Data_Store_Option' )
118
+ ->load_class( 'Permissions_Any' )
119
+ ->load_class( 'Field_Declaration' )
120
+ ->load_class( 'Field_Declaration_Builder' )
121
+ ->load_class( 'Model' )
122
+ ->load_class( 'Model_Factory' )
123
+ ->load_class( 'Model_Settings' )
124
+ ->load_class( 'Model_Collection' )
125
+ ->load_class( 'Controller' )
126
+ ->load_class( 'Controller_Action' )
127
+ ->load_class( 'Controller_Model' )
128
+ ->load_class( 'Controller_Settings' )
129
+ ->load_class( 'Controller_Route' )
130
+ ->load_class( 'Controller_CRUD' )
131
+ ->load_class( 'Controller_Bundle' )
132
+ ->load_class( 'Controller_Extension' )
133
+ ->load_class( 'Controller_Bundle_Builder' );
134
+
135
+ return $this;
136
+ }
137
+
138
+ /**
139
+ * Load Unit Testing Base Classes
140
+ *
141
+ * @return WP_Job_Manager_REST_Bootstrap $this
142
+ */
143
+ function load_testing_classes() {
144
+ $this->class_loader()
145
+ ->load_class( 'Testing_TestCase' )
146
+ ->load_class( 'Testing_Model_TestCase' )
147
+ ->load_class( 'Testing_Controller_TestCase' );
148
+ return $this;
149
+ }
150
+
151
+ /**
152
+ * Get the class loader
153
+ *
154
+ * @return WP_Job_Manager_REST_Classloader
155
+ */
156
+ function class_loader() {
157
+ return $this->class_loader;
158
+ }
159
+
160
+ /**
161
+ * Lazy-load the environment
162
+ *
163
+ * @return WP_Job_Manager_REST_Environment
164
+ */
165
+ public function environment() {
166
+ if ( null === $this->environment ) {
167
+ $this->environment = new WP_Job_Manager_REST_Environment( $this );
168
+ }
169
+ return $this->environment;
170
+ }
171
+ }
lib/wpjm_rest/class-wp-job-manager-rest-classloader.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Default Mixtape_Interfaces_Class_Loader Implementation
4
+ *
5
+ * Loads classes in nested folders.
6
+ *
7
+ * @package Mixtape
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Class WP_Job_Manager_REST_Class_Loader
16
+ */
17
+ class WP_Job_Manager_REST_Classloader implements WP_Job_Manager_REST_Interfaces_Classloader {
18
+ /**
19
+ * Keep a record of classes loaded
20
+ *
21
+ * @var array The loaded class map.
22
+ */
23
+ private $loaded_classes;
24
+ /**
25
+ * The prefix to use (e.g. Mixtape)
26
+ *
27
+ * @var string
28
+ */
29
+ private $prefix;
30
+ /**
31
+ * The directory the loader looks for classes.
32
+ *
33
+ * @var string
34
+ */
35
+ private $base_dir;
36
+
37
+ /**
38
+ * WP_Job_Manager_REST_Class_Loader constructor.
39
+ *
40
+ * @param string $prefix The prefix to use (e.g. Mixtape).
41
+ * @param string $base_dir The directory the loader looks for classes.
42
+ *
43
+ * @throws Exception Throws if an invalid directory is provided.
44
+ */
45
+ public function __construct( $prefix, $base_dir ) {
46
+ $this->loaded_classes = array();
47
+ $this->prefix = $prefix;
48
+ $this->base_dir = $base_dir;
49
+ if ( ! is_dir( $this->base_dir ) ) {
50
+ throw new Exception( 'base_dir does not exist: ' . $this->base_dir );
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Loads a class
56
+ *
57
+ * @param string $class_name The class to load.
58
+ *
59
+ * @return WP_Job_Manager_REST_Interfaces_Classloader
60
+ * @throws Exception Throws in case include_class_file fails.
61
+ */
62
+ public function load_class( $class_name ) {
63
+ $path = $this->get_path_to_class_file( $class_name );
64
+ return $this->include_class_file( $path );
65
+ }
66
+
67
+ /**
68
+ * Get path_to_class_file
69
+ *
70
+ * @param string $class_name The class.
71
+ *
72
+ * @return string The full path to the file.
73
+ */
74
+ public function get_path_to_class_file( $class_name ) {
75
+ return path_join( $this->base_dir, $this->class_name_to_relative_path( $class_name ) );
76
+ }
77
+
78
+ /**
79
+ * Class_name_to_relative_path
80
+ *
81
+ * @param string $class_name The class name.
82
+ * @param null|string $prefix The prefix.
83
+ *
84
+ * @return string
85
+ */
86
+ public function class_name_to_relative_path( $class_name, $prefix = null ) {
87
+ $lowercase = strtolower( $this->prefixed_class_name( $class_name, $prefix ) );
88
+ $file_name = 'class-' . str_replace( '_', '-', $lowercase ) . '.php';
89
+ $parts = explode( '_', strtolower( $this->strip_prefix( $class_name, $prefix ) ) );
90
+ array_pop( $parts );
91
+ $parts[] = $file_name;
92
+ return implode( DIRECTORY_SEPARATOR, $parts );
93
+ }
94
+
95
+ /**
96
+ * Prefixed_class_name
97
+ *
98
+ * @param string $class_name The class name.
99
+ * @param null|string $prefix The prefix.
100
+ *
101
+ * @return string
102
+ */
103
+ public function prefixed_class_name( $class_name, $prefix = null ) {
104
+ if ( empty( $prefix ) ) {
105
+ $prefix = $this->prefix;
106
+ }
107
+ return $prefix . '_' . $this->strip_prefix( $class_name, $prefix );
108
+ }
109
+
110
+ /**
111
+ * Strip_prefix
112
+ *
113
+ * @param string $class_name The class name.
114
+ * @param null|string $prefix The prefix.
115
+ *
116
+ * @return string
117
+ */
118
+ private function strip_prefix( $class_name, $prefix = null ) {
119
+ if ( empty( $prefix ) ) {
120
+ $prefix = $this->prefix;
121
+ }
122
+ return str_replace( $prefix, '', $class_name );
123
+ }
124
+
125
+ /**
126
+ * Include_class_file
127
+ *
128
+ * @param string $path_to_the_class The file path.
129
+ *
130
+ * @return string
131
+ * @throws Exception Throws when the file does not exist.
132
+ */
133
+ private function include_class_file( $path_to_the_class ) {
134
+ if ( isset( $this->loaded_classes[ $path_to_the_class ] ) ) {
135
+ return $this;
136
+ }
137
+ if ( ! file_exists( $path_to_the_class ) ) {
138
+ throw new Exception( $path_to_the_class . ' not found' );
139
+ }
140
+ $included = include_once( $path_to_the_class );
141
+ $this->loaded_classes[ $path_to_the_class ] = $included;
142
+
143
+ return $this;
144
+ }
145
+ }
lib/wpjm_rest/class-wp-job-manager-rest-controller.php ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Controller
4
+ *
5
+ * @package Mixtape/Controller
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Controller
14
+ */
15
+ class WP_Job_Manager_REST_Controller extends WP_REST_Controller implements WP_Job_Manager_REST_Interfaces_Controller {
16
+ const HTTP_CREATED = 201;
17
+ const HTTP_OK = 200;
18
+ const HTTP_BAD_REQUEST = 400;
19
+ const HTTP_NOT_FOUND = 404;
20
+
21
+ /**
22
+ * The bundle this belongs to.
23
+ *
24
+ * @var WP_Job_Manager_REST_Controller_Bundle
25
+ */
26
+ protected $controller_bundle;
27
+
28
+ /**
29
+ * The endpoint base (e.g. /users). Override in subclasses.
30
+ *
31
+ * @var string
32
+ */
33
+ protected $base = null;
34
+ /**
35
+ * Our Handlers
36
+ *
37
+ * @var array
38
+ */
39
+ private $routes = array();
40
+
41
+ /**
42
+ * Optional, an enviromnent.
43
+ *
44
+ * @var null|WP_Job_Manager_REST_Environment
45
+ */
46
+ protected $environment = null;
47
+
48
+ /**
49
+ * WP_Job_Manager_REST_Rest_Api_Controller constructor.
50
+ */
51
+ public function __construct() {
52
+ }
53
+
54
+ /**
55
+ * Set Controller Bundle
56
+ *
57
+ * @param WP_Job_Manager_REST_Controller_Bundle $controller_bundle Controller Bundle this belongs to.
58
+ *
59
+ * @return WP_Job_Manager_REST_Controller $this
60
+ */
61
+ public function set_controller_bundle( $controller_bundle ) {
62
+ $this->controller_bundle = $controller_bundle;
63
+ return $this;
64
+ }
65
+
66
+ /**
67
+ * Set the Environment for this Controller.
68
+ *
69
+ * @param WP_Job_Manager_REST_Environment|null $environment The Environment.
70
+ * @return WP_Job_Manager_REST_Controller
71
+ */
72
+ public function set_environment( $environment ) {
73
+ $this->environment = $environment;
74
+ return $this;
75
+ }
76
+
77
+ /**
78
+ * Register This Controller
79
+ *
80
+ * @param WP_Job_Manager_REST_Controller_Bundle $bundle The bundle to register with.
81
+ * @param WP_Job_Manager_REST_Environment $environment The Environment to use.
82
+ * @throws WP_Job_Manager_REST_Exception Throws.
83
+ *
84
+ * @return bool|WP_Error true if valid otherwise error.
85
+ */
86
+ public function register( $bundle, $environment ) {
87
+ $this->set_controller_bundle( $bundle );
88
+ $this->set_environment( $environment );
89
+ $this->setup();
90
+ WP_Job_Manager_REST_Expect::that( ! empty( $this->base ), 'Need to put a string with a backslash in $base' );
91
+ $prefix = $this->controller_bundle->get_prefix();
92
+ foreach ( $this->routes as $pattern => $route ) {
93
+ /**
94
+ * The route we want to register.
95
+ *
96
+ * @var WP_Job_Manager_REST_Controller_Route $route
97
+ */
98
+ $params = $route->as_array();
99
+ $result = register_rest_route( $prefix, $this->base . $params['pattern'], $params['actions'] );
100
+ if ( false === $result ) {
101
+ // For now we throw on error, maybe we just need to warn though.
102
+ throw new WP_Job_Manager_REST_Exception( 'Registration failed' );
103
+ }
104
+ }
105
+
106
+ return true;
107
+ }
108
+
109
+ /**
110
+ * Create Action
111
+ *
112
+ * @param string $action_name Action Name.
113
+ * @param null|string|array|callable $callback Callback.
114
+ * @return WP_Job_Manager_REST_Controller_Action
115
+ */
116
+ public function action( $action_name, $callback = null ) {
117
+ $route_action = new WP_Job_Manager_REST_Controller_Action( $this, $action_name );
118
+ if ( null !== $callback ) {
119
+ $route_action->callback( $callback );
120
+ }
121
+
122
+ return $route_action;
123
+ }
124
+
125
+ /**
126
+ * Do any additional Configuration. Runs inside register before any register_rest_route
127
+ *
128
+ * This is a good place for overriding classes to define routes and handlers
129
+ */
130
+ protected function setup() {
131
+ }
132
+
133
+ /**
134
+ * Succeed
135
+ *
136
+ * @param array $data The dto.
137
+ *
138
+ * @return WP_REST_Response
139
+ */
140
+ public function ok( $data ) {
141
+ return $this->respond( $data, self::HTTP_OK );
142
+ }
143
+
144
+ /**
145
+ * Created
146
+ *
147
+ * @param array $data The dto.
148
+ *
149
+ * @return WP_REST_Response
150
+ */
151
+ public function created( $data ) {
152
+ return $this->respond( $data, self::HTTP_CREATED );
153
+ }
154
+
155
+ /**
156
+ * Bad request
157
+ *
158
+ * @param array|WP_Error $data The dto.
159
+ *
160
+ * @return WP_REST_Response
161
+ */
162
+ public function bad_request( $data ) {
163
+ return $this->respond( $data, self::HTTP_BAD_REQUEST );
164
+ }
165
+
166
+ /**
167
+ * Not Found (404)
168
+ *
169
+ * @param string $message The message.
170
+ *
171
+ * @return WP_REST_Response
172
+ */
173
+ public function not_found( $message ) {
174
+ return $this->respond( array(
175
+ 'message' => $message,
176
+ ), self::HTTP_NOT_FOUND );
177
+ }
178
+
179
+ /**
180
+ * Respond
181
+ *
182
+ * @param array|WP_REST_Response|WP_Error|mixed $data The thing.
183
+ * @param int $status The Status.
184
+ *
185
+ * @return mixed|WP_REST_Response
186
+ */
187
+ public function respond( $data, $status ) {
188
+ if ( is_a( $data, 'WP_REST_Response' ) ) {
189
+ return $data;
190
+ }
191
+
192
+ return new WP_REST_Response( $data, $status );
193
+ }
194
+
195
+ /**
196
+ * Permissions for get_items
197
+ *
198
+ * @param WP_REST_Request $request Request.
199
+ * @return bool
200
+ */
201
+ public function index_permissions_check( $request ) {
202
+ return $this->permissions_check( $request, 'index' );
203
+ }
204
+
205
+ /**
206
+ * Permissions for get_item
207
+ *
208
+ * @param WP_REST_Request $request The request.
209
+ * @return bool
210
+ */
211
+ public function show_permissions_check( $request ) {
212
+ return $this->permissions_check( $request, 'show' );
213
+ }
214
+
215
+ /**
216
+ * Permissions for create_item
217
+ *
218
+ * @param WP_REST_Request $request Request.
219
+ * @return bool
220
+ */
221
+ public function create_permissions_check( $request ) {
222
+ return $this->permissions_check( $request, 'create' );
223
+ }
224
+
225
+ /**
226
+ * Permissions for update_item
227
+ *
228
+ * @param WP_REST_Request $request Request.
229
+ * @return bool
230
+ */
231
+ public function update_permissions_check( $request ) {
232
+ return $this->permissions_check( $request, 'update' );
233
+ }
234
+
235
+ /**
236
+ * Permissions for delete
237
+ *
238
+ * @param WP_REST_Request $request Request.
239
+ * @return bool
240
+ */
241
+ public function delete_permissions_check( $request ) {
242
+ return $this->permissions_check( $request, 'delete' );
243
+ }
244
+
245
+ /**
246
+ * Generic Permissions Check.
247
+ *
248
+ * @param WP_REST_Request $request Request.
249
+ * @param string $action One of (index, show, create, update, delete, any).
250
+ * @return bool
251
+ */
252
+ function permissions_check( $request, $action = 'any' ) {
253
+ return true;
254
+ }
255
+
256
+ /**
257
+ * Add a route
258
+ *
259
+ * @param string $pattern The route pattern (e.g. '/').
260
+ * @return WP_Job_Manager_REST_Controller_Route
261
+ */
262
+ function add_route( $pattern = '' ) {
263
+ $route = new WP_Job_Manager_REST_Controller_Route( $this, $pattern );
264
+ $this->routes[ $pattern ] = $route;
265
+ return $this->routes[ $pattern ];
266
+ }
267
+
268
+ /**
269
+ * Get Environment
270
+ *
271
+ * @return WP_Job_Manager_REST_Environment
272
+ */
273
+ protected function environment() {
274
+ return $this->environment;
275
+ }
276
+
277
+ /**
278
+ * Get base url
279
+ *
280
+ * @return string
281
+ */
282
+ function get_base() {
283
+ return rest_url( $this->controller_bundle->get_prefix() . $this->base );
284
+ }
285
+ }
lib/wpjm_rest/class-wp-job-manager-rest-environment.php ADDED
@@ -0,0 +1,400 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Environment
4
+ *
5
+ * Contains variables, rest api, type and model definitions
6
+ *
7
+ * @package Mixtape
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Class WP_Job_Manager_REST_Environment
16
+ *
17
+ * Our global Environment
18
+ *
19
+ * @package Mixtape
20
+ */
21
+ class WP_Job_Manager_REST_Environment {
22
+ const REGISTRABLE = 'IRegistrable';
23
+ const BUNDLES = 'Bundles';
24
+ const MODELS = 'Models';
25
+
26
+ /**
27
+ * This environment's registered REST bundles
28
+ *
29
+ * (used for versioned APIs, or logical grouping of related api parts)
30
+ *
31
+ * @var array
32
+ */
33
+ protected $rest_apis;
34
+
35
+ /**
36
+ * This environment's model definitions
37
+ *
38
+ * @var array
39
+ */
40
+ protected $model_definitions;
41
+
42
+ /**
43
+ * The Environment Variables
44
+ *
45
+ * A key-value array of things.
46
+ *
47
+ * @var array
48
+ */
49
+ protected $variables;
50
+
51
+ /**
52
+ * Did this Environment start?
53
+ *
54
+ * @var bool
55
+ */
56
+ private $has_started;
57
+
58
+ /**
59
+ * Our Bootstrap
60
+ *
61
+ * @var WP_Job_Manager_REST_Bootstrap
62
+ */
63
+ private $bootstrap;
64
+
65
+ /**
66
+ * Our Type Registry
67
+ *
68
+ * @var WP_Job_Manager_REST_Type_Registry
69
+ */
70
+ private $type_registry;
71
+
72
+ /**
73
+ * Mixtape_Environment constructor.
74
+ *
75
+ * @param WP_Job_Manager_REST_Bootstrap $bootstrap The bootstrap.
76
+ */
77
+ public function __construct( $bootstrap ) {
78
+ $this->bootstrap = $bootstrap;
79
+ $this->has_started = false;
80
+ $this->rest_apis = array();
81
+ $this->variables = array();
82
+ $this->model_definitions = array();
83
+ $this->type_registry = new WP_Job_Manager_REST_Type_Registry();
84
+ $this->type_registry->initialize( $this );
85
+ // initialize our array vars.
86
+ $this->array_var( self::MODELS )
87
+ ->array_var( self::REGISTRABLE )
88
+ ->array_var( self::BUNDLES );
89
+ }
90
+
91
+ /**
92
+ * Push a Builder to the Environment.
93
+ *
94
+ * All builders are evaluated lazily when needed
95
+ *
96
+ * @param string $where The queue to push the builder to.
97
+ * @param WP_Job_Manager_REST_Interfaces_Builder $builder The builder to push.
98
+ *
99
+ * @return WP_Job_Manager_REST_Environment $this
100
+ * @throws WP_Job_Manager_REST_Exception In case the $builder is not a Mixtape_Interfaces_Builder.
101
+ */
102
+ public function push_builder( $where, $builder ) {
103
+ WP_Job_Manager_REST_Expect::that( is_string( $where ), '$where should be a string' );
104
+ WP_Job_Manager_REST_Expect::is_a( $builder, 'WP_Job_Manager_REST_Interfaces_Builder' );
105
+ return $this->array_var( $where, $builder );
106
+ }
107
+
108
+ /**
109
+ * Retrieve a previously defined Mixtape_Model_Definition
110
+ *
111
+ * @param string $class the class name.
112
+ * @return WP_Job_Manager_REST_Model_Factory the definition.
113
+ * @throws WP_Job_Manager_REST_Exception Throws in case the model is not registered.
114
+ */
115
+ public function model( $class ) {
116
+ if ( ! class_exists( $class ) ) {
117
+ throw new WP_Job_Manager_REST_Exception( $class . ' does not exist' );
118
+ }
119
+ WP_Job_Manager_REST_Expect::that( isset( $this->model_definitions[ $class ] ), $class . ' definition does not exist' );
120
+ return $this->model_definitions[ $class ];
121
+ }
122
+
123
+ /**
124
+ * Time to build pending models and bundles
125
+ *
126
+ * @param string $type One of (models, bundles).
127
+ * @return WP_Job_Manager_REST_Environment
128
+ */
129
+ private function load_pending_builders( $type ) {
130
+ $things = $this->get( $type );
131
+ if ( ! empty( $things ) && is_array( $things ) ) {
132
+ foreach ( $things as $pending ) {
133
+ /**
134
+ * Our pending builder.
135
+ *
136
+ * @var WP_Job_Manager_REST_Interfaces_Builder $pending Our builder.
137
+ */
138
+ if ( self::BUNDLES === $type ) {
139
+ $this->add_rest_bundle( $pending->build() );
140
+ }
141
+ }
142
+ }
143
+
144
+ return $this;
145
+ }
146
+
147
+ /**
148
+ * Start things up
149
+ *
150
+ * This should be called once our Environment is set up to our liking.
151
+ * Evaluates all Builders, creating missing REST Api and Model Definitions.
152
+ *
153
+ *
154
+ * It is recommended we hook this into 'rest_api_init'.
155
+ *
156
+ * @return WP_Job_Manager_REST_Environment $this
157
+ */
158
+ public function start() {
159
+ if ( ! $this->bootstrap->is_compatible() ) {
160
+ // Do not even start on an incompatible system.
161
+ return $this;
162
+ }
163
+
164
+ if ( false === $this->has_started ) {
165
+ do_action( 'mt_environment_before_start', $this, get_class( $this ) );
166
+ $this->load_pending_builders( self::MODELS );
167
+ $this->load_pending_builders( self::BUNDLES );
168
+ $registrables = $this->get( self::REGISTRABLE ) ? $this->get( self::REGISTRABLE ) : array();
169
+ foreach ( $registrables as $registrable ) {
170
+ /**
171
+ * A Registrable
172
+ *
173
+ * @var WP_Job_Manager_REST_Interfaces_Registrable $registrable
174
+ */
175
+ $registrable->register( $this );
176
+ }
177
+
178
+ /**
179
+ * Use this hook to add/remove rest api bundles
180
+ *
181
+ * @param array $rest_apis The existing rest apis.
182
+ * @param WP_Job_Manager_REST_Environment $this The Environment.
183
+ */
184
+ $rest_apis = (array) apply_filters( 'mt_environment_get_rest_apis', $this->rest_apis, $this );
185
+
186
+ foreach ( $rest_apis as $k => $bundle ) {
187
+ /**
188
+ * Register this bundle
189
+ *
190
+ * @var WP_Job_Manager_REST_Interfaces_Controller_Bundle
191
+ */
192
+ $bundle->register( $this );
193
+ }
194
+ $this->has_started = true;
195
+ do_action( 'mt_environment_after_start', $this );
196
+ }
197
+
198
+ return $this;
199
+ }
200
+
201
+ /**
202
+ * Add Registrable
203
+ *
204
+ * @param WP_Job_Manager_REST_Interfaces_Registrable $registrable_thing Registrable.
205
+ * @return WP_Job_Manager_REST_Environment
206
+ * @throws WP_Job_Manager_REST_Exception When not a WP_Job_Manager_REST_Interfaces_Registrable.
207
+ */
208
+ public function add_registrable( $registrable_thing ) {
209
+ WP_Job_Manager_REST_Expect::is_a( $registrable_thing, 'WP_Job_Manager_REST_Interfaces_Registrable' );
210
+ $this->array_var( self::REGISTRABLE, $registrable_thing );
211
+ return $this->define_var( get_class( $registrable_thing ), $registrable_thing );
212
+ }
213
+
214
+ /**
215
+ * Has Variable
216
+ *
217
+ * @param string $name Is this variable Set.
218
+ * @return bool
219
+ */
220
+ public function has_variable( $name ) {
221
+ return isset( $this->variables[ $name ] );
222
+ }
223
+
224
+ /**
225
+ * Append to an array
226
+ *
227
+ * @param string $name The VarArray Name.
228
+ * @param mixed $thing The thing.
229
+ * @return WP_Job_Manager_REST_Environment
230
+ */
231
+ public function array_var( $name, $thing = null ) {
232
+ return $this->define_var( $name, $thing, true );
233
+ }
234
+
235
+ /**
236
+ * Get A Variable
237
+ *
238
+ * @param string $name The Variable Name.
239
+ * @return mixed|null The variable or null
240
+ *
241
+ * @throws WP_Job_Manager_REST_Exception Name should be a string.
242
+ */
243
+ public function get( $name ) {
244
+ WP_Job_Manager_REST_Expect::that( is_string( $name ), '$name should be a string' );
245
+ $value = $this->has_variable( $name ) ? $this->variables[ $name ] : null;
246
+ /**
247
+ * Filter the variable value
248
+ *
249
+ * @param mixed $value The value.
250
+ * @param WP_Job_Manager_REST_Environment $this The Environemnt.
251
+ * @param string $name The var name.
252
+ *
253
+ * @return mixed
254
+ */
255
+ return apply_filters( 'mt_variable_get', $value, $this, $name );
256
+ }
257
+
258
+ /**
259
+ * Def.
260
+ *
261
+ * @param string $name The Variable To Add.
262
+ * @param mixed $thing The thing that is associated with the var.
263
+ * @param bool $append If true, this var is a list.
264
+ *
265
+ * @return $this
266
+ *
267
+ * @throws WP_Job_Manager_REST_Exception When name is not a string.
268
+ */
269
+ public function define_var( $name, $thing = null, $append = false ) {
270
+ WP_Job_Manager_REST_Expect::that( is_string( $name ), '$name should be a string' );
271
+ if ( $append && ! $this->has_variable( $name ) ) {
272
+ $this->variables[ $name ] = array();
273
+ }
274
+ if ( null !== $thing ) {
275
+ if ( $append ) {
276
+ $this->variables[ $name ][] = $thing;
277
+ } else {
278
+ $this->variables[ $name ] = $thing;
279
+ }
280
+ }
281
+ return $this;
282
+ }
283
+
284
+ /**
285
+ * Auto start on rest_api_init. For more control, use ::start();
286
+ */
287
+ public function auto_start() {
288
+ add_action( 'rest_api_init', array( $this, 'start' ) );
289
+ }
290
+
291
+ /**
292
+ * Get this Environment's bootstrap instance
293
+ *
294
+ * @return WP_Job_Manager_REST_Bootstrap our bootstrap.
295
+ */
296
+ public function get_bootstrap() {
297
+ return $this->bootstrap;
298
+ }
299
+
300
+ /**
301
+ * Create a new Field Declaration Builder
302
+ *
303
+ * @param null|string $name Optional, the field name.
304
+ * @param null|string $description Optional, the description.
305
+ * @param null|string $field_kind The field kind (default 'field').
306
+ *
307
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
308
+ */
309
+ public function field( $name = null, $description = null, $field_kind = null ) {
310
+ $builder = new WP_Job_Manager_REST_Field_Declaration_Builder();
311
+
312
+ if ( ! empty( $name ) ) {
313
+ $builder->with_name( $name );
314
+ }
315
+
316
+ if ( ! empty( $description ) ) {
317
+ $builder->with_description( $description );
318
+ }
319
+
320
+ if ( empty( $field_kind ) ) {
321
+ $field_kind = WP_Job_Manager_REST_Field_Declaration::FIELD;
322
+ }
323
+
324
+ $builder->with_kind( $field_kind );
325
+
326
+ return $builder;
327
+ }
328
+
329
+ /**
330
+ * Get our registered types
331
+ *
332
+ * @return WP_Job_Manager_REST_Type_Registry
333
+ */
334
+ public function get_type_registry() {
335
+ return $this->type_registry;
336
+ }
337
+
338
+ /**
339
+ * Get a known type definition
340
+ *
341
+ * @param string $type_name The type name.
342
+ * @return WP_Job_Manager_REST_Interfaces_Type
343
+ *
344
+ * @throws WP_Job_Manager_REST_Exception When provided with an unknown/invalid type.
345
+ */
346
+ public function type( $type_name ) {
347
+ return $this->get_type_registry()->definition( $type_name );
348
+ }
349
+
350
+ /**
351
+ * Define a new REST API Bundle.
352
+ *
353
+ * @param null|string|WP_Job_Manager_REST_Interfaces_Controller_Bundle $maybe_bundle_or_prefix The bundle name.
354
+ * @return WP_Job_Manager_REST_Controller_Bundle_Builder
355
+ */
356
+ public function rest_api( $maybe_bundle_or_prefix = null ) {
357
+ if ( is_a( $maybe_bundle_or_prefix, 'WP_Job_Manager_REST_Interfaces_Controller_Bundle' ) ) {
358
+ $builder = new WP_Job_Manager_REST_Controller_Bundle_Builder( $maybe_bundle_or_prefix );
359
+ } else {
360
+ $builder = new WP_Job_Manager_REST_Controller_Bundle_Builder();
361
+ if ( is_string( $maybe_bundle_or_prefix ) ) {
362
+ $builder->with_prefix( $maybe_bundle_or_prefix );
363
+ }
364
+ $builder->with_environment( $this );
365
+ }
366
+
367
+ $this->push_builder( self::BUNDLES, $builder );
368
+ return $builder;
369
+ }
370
+
371
+ /**
372
+ * Define a new Model
373
+ *
374
+ * @param string $declaration A Model class string.
375
+ *
376
+ * @return WP_Job_Manager_REST_Model_Factory
377
+ */
378
+ function define_model( $declaration ) {
379
+ WP_Job_Manager_REST_Expect::that( class_exists( $declaration ), '$declaration string should be an existing class' );
380
+ WP_Job_Manager_REST_Expect::that( in_array( 'WP_Job_Manager_REST_Interfaces_Model', class_implements( $declaration ), true ), '$declaration does not implement WP_Job_Manager_REST_Interfaces_Model' );
381
+ $factory = new WP_Job_Manager_REST_Model_Factory( $this, $declaration, new WP_Job_Manager_REST_Data_Store_Nil() );
382
+ $this->model_definitions[ $declaration ] = $factory;
383
+ return $factory;
384
+ }
385
+
386
+ /**
387
+ * Add a Bundle to our bundles (muse be Mixtape_Interfaces_Rest_Api_Controller_Bundle)
388
+ *
389
+ * @param WP_Job_Manager_REST_Interfaces_Controller_Bundle $bundle the bundle.
390
+ *
391
+ * @return WP_Job_Manager_REST_Environment $this
392
+ * @throws WP_Job_Manager_REST_Exception In case it's not a WP_Job_Manager_REST_Interfaces_Controller_Bundle.
393
+ */
394
+ private function add_rest_bundle( $bundle ) {
395
+ WP_Job_Manager_REST_Expect::is_a( $bundle, 'WP_Job_Manager_REST_Interfaces_Controller_Bundle' );
396
+ $key = $bundle->get_prefix();
397
+ $this->rest_apis[ $key ] = $bundle;
398
+ return $this;
399
+ }
400
+ }
lib/wpjm_rest/class-wp-job-manager-rest-exception.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Mixtape_Exception
4
+ *
5
+ * @package Mixtape
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Base Exception class
14
+ * Class WP_Job_Manager_REST_Exception
15
+ */
16
+ class WP_Job_Manager_REST_Exception extends Exception {
17
+ }
lib/wpjm_rest/class-wp-job-manager-rest-expect.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Mixtape_Expect
4
+ *
5
+ * Asserts about invariants
6
+ *
7
+ * @package Mixtape
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Class Mixtape_Expect
16
+ */
17
+ class WP_Job_Manager_REST_Expect {
18
+ /**
19
+ * Expect a certain class
20
+ *
21
+ * @param mixed $thing The thing to test.
22
+ * @param string $class_name The class.
23
+ *
24
+ * @throws WP_Job_Manager_REST_Exception Fail if we got an unexpected class.
25
+ */
26
+ static function is_a( $thing, $class_name ) {
27
+ self::is_object( $thing );
28
+ self::that( is_a( $thing, $class_name ), 'Expected ' . $class_name . ', got ' . get_class( $thing ) );
29
+ }
30
+
31
+ /**
32
+ * Expect that thing is an object
33
+ *
34
+ * @param mixed $thing The thing.
35
+ * @throws WP_Job_Manager_REST_Exception Throw if not an object.
36
+ */
37
+ static function is_object( $thing ) {
38
+ self::that( is_object( $thing ), 'Variable is is not an Object' );
39
+ }
40
+
41
+ /**
42
+ * Express an invariant.
43
+ *
44
+ * @param bool $cond The boolean condition that needs to hold.
45
+ * @param string $fail_message In case of failure, the reason this failed.
46
+ *
47
+ * @throws WP_Job_Manager_REST_Exception Fail if condition doesn't hold.
48
+ */
49
+ static function that( $cond, $fail_message ) {
50
+ if ( ! $cond ) {
51
+ throw new WP_Job_Manager_REST_Exception( $fail_message );
52
+ }
53
+ }
54
+
55
+ /**
56
+ * This method should be Overridden
57
+ *
58
+ * @param string $method The method name.
59
+ *
60
+ * @throws WP_Job_Manager_REST_Exception To Overrride this.
61
+ */
62
+ static function should_override( $method ) {
63
+ throw new WP_Job_Manager_REST_Exception( $method . ' should be overriden' );
64
+ }
65
+ }
lib/wpjm_rest/class-wp-job-manager-rest-model.php ADDED
@@ -0,0 +1,645 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Abstract Mixtape_Interfaces_Model Base Class
4
+ *
5
+ * @package Mixtape/Model
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Model
14
+ */
15
+ class WP_Job_Manager_REST_Model implements
16
+ WP_Job_Manager_REST_Interfaces_Model,
17
+ WP_Job_Manager_REST_Interfaces_Permissions_Provider {
18
+
19
+ /**
20
+ * Fields By Class Name
21
+ *
22
+ * @var array
23
+ */
24
+ private static $fields_by_class_name = array();
25
+
26
+ /**
27
+ * Data Stores By Class Name
28
+ *
29
+ * @var array
30
+ */
31
+ private static $data_stores_by_class_name = array();
32
+
33
+ /**
34
+ * The Single Environment instance all children models access
35
+ *
36
+ * @var WP_Job_Manager_REST_Environment
37
+ */
38
+ private static $environment = null;
39
+
40
+ /**
41
+ * Our data
42
+ *
43
+ * @var array
44
+ */
45
+ private $data;
46
+
47
+ /**
48
+ * Our raw data
49
+ *
50
+ * @var array
51
+ */
52
+ private $raw_data;
53
+
54
+ /**
55
+ * Mixtape_Model constructor.
56
+ *
57
+ * @param array $data The data array.
58
+ * @param array $args Args.
59
+ *
60
+ * @throws WP_Job_Manager_REST_Exception Throws when data is not an array.
61
+ */
62
+ function __construct( $data = array(), $args = array() ) {
63
+ WP_Job_Manager_REST_Expect::that( is_array( $data ), '$data should be an array' );
64
+ $this->data = array();
65
+
66
+ if ( isset( $args['deserialize'] ) && true === $args['deserialize'] ) {
67
+ unset( $args['deserialize'] );
68
+ $data = $this->deserialize( $data );
69
+ }
70
+ $this->raw_data = $data;
71
+ $data_keys = array_keys( $data );
72
+
73
+ foreach ( $data_keys as $key ) {
74
+ $this->set( $key, $this->raw_data[ $key ] );
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Gets the value of a previously defined field.
80
+ *
81
+ * @param string $field_name The field name.
82
+ * @param array $args Any args.
83
+ *
84
+ * @return mixed
85
+ * @throws WP_Job_Manager_REST_Exception Fails when field is unknown.
86
+ */
87
+ public function get( $field_name, $args = array() ) {
88
+ WP_Job_Manager_REST_Expect::that( $this->has( $field_name ), 'Field ' . $field_name . 'is not defined' );
89
+ $fields = self::get_fields();
90
+ $field_declaration = $fields[ $field_name ];
91
+ $this->set_field_if_unset( $field_declaration );
92
+
93
+ return $this->prepare_value( $field_declaration );
94
+ }
95
+
96
+ /**
97
+ * Sets a field value.
98
+ *
99
+ * @param string $field The field name.
100
+ * @param mixed $value The new field value.
101
+ *
102
+ * @return $this
103
+ * @throws WP_Job_Manager_REST_Exception Throws when trying to set an unknown field.
104
+ */
105
+ public function set( $field, $value ) {
106
+ WP_Job_Manager_REST_Expect::that( $this->has( $field ), 'Field ' . $field . 'is not defined' );
107
+ $fields = self::get_fields();
108
+ /**
109
+ * The declaration.
110
+ *
111
+ * @var WP_Job_Manager_REST_Field_Declaration $field_declaration The declaration.
112
+ */
113
+ $field_declaration = $fields[ $field ];
114
+ if ( isset( $args['deserializing'] ) && $args['deserializing'] ) {
115
+ $value = $this->deserialize_field( $field_declaration, $value );
116
+ }
117
+ if ( null !== $field_declaration->before_set() ) {
118
+ $val = $this->call( $field_declaration->before_set(), array( $value, $field_declaration->get_name() ) );
119
+ } else {
120
+ $val = $field_declaration->cast_value( $value );
121
+ }
122
+ $this->data[ $field_declaration->get_name() ] = $val;
123
+ return $this;
124
+ }
125
+
126
+ /**
127
+ * Check if this model has a field
128
+ *
129
+ * @param string $field The field name to check.
130
+ * @return bool
131
+ */
132
+ public function has( $field ) {
133
+ $fields = self::get_fields();
134
+ return isset( $fields[ $field ] );
135
+ }
136
+
137
+ /**
138
+ * Validate this Model's current state.
139
+ *
140
+ * @return bool|WP_Error Either true or WP_Error on failure.
141
+ */
142
+ public function validate() {
143
+ $validation_errors = array();
144
+ $fields = self::get_fields();
145
+ foreach ( $fields as $key => $field_declaration ) {
146
+ $is_valid = $this->run_field_validations( $field_declaration );
147
+ if ( is_wp_error( $is_valid ) ) {
148
+ $validation_errors[] = $is_valid->get_error_data();
149
+ }
150
+ }
151
+ if ( count( $validation_errors ) > 0 ) {
152
+ return $this->validation_error( $validation_errors );
153
+ }
154
+ return true;
155
+ }
156
+
157
+ /**
158
+ * Sanitize this Model's current data.
159
+ *
160
+ * @return WP_Job_Manager_REST_Interfaces_Model $this
161
+ */
162
+ public function sanitize() {
163
+ $fields = self::get_fields();
164
+ foreach ( $fields as $key => $field_declaration ) {
165
+ /**
166
+ * Field Declaration.
167
+ *
168
+ * @var WP_Job_Manager_REST_Field_Declaration $field_declaration
169
+ */
170
+ $field_name = $field_declaration->get_name();
171
+ $value = $this->get( $field_name );
172
+ $custom_sanitization = $field_declaration->get_sanitizer();
173
+ if ( ! empty( $custom_sanitization ) ) {
174
+ $value = $this->call( $custom_sanitization, array( $this, $value ) );
175
+ } else {
176
+ $value = $field_declaration->get_type()->sanitize( $value );
177
+ }
178
+ $this->set( $field_name, $value );
179
+ }
180
+ return $this;
181
+ }
182
+
183
+ /**
184
+ * We got a Validation Error
185
+ *
186
+ * @param array $error_data The details.
187
+ * @return WP_Error
188
+ */
189
+ protected function validation_error( $error_data ) {
190
+ return new WP_Error( 'validation-error', 'validation-error', $error_data );
191
+ }
192
+
193
+ /**
194
+ * Run Validations for this field.
195
+ *
196
+ * @param WP_Job_Manager_REST_Field_Declaration $field_declaration The field.
197
+ *
198
+ * @return bool|WP_Error
199
+ */
200
+ protected function run_field_validations( $field_declaration ) {
201
+ if ( $field_declaration->is_kind( WP_Job_Manager_REST_Field_Declaration::DERIVED ) ) {
202
+ return true;
203
+ }
204
+ $value = $this->get( $field_declaration->get_name() );
205
+ if ( $field_declaration->is_required() && empty( $value ) ) {
206
+ // translators: %s is usually a field name.
207
+ $message = sprintf( __( '%s cannot be empty', 'mixtape' ), $field_declaration->get_name() );
208
+ return new WP_Error( 'required-field-empty', $message );
209
+ } elseif ( ! $field_declaration->is_required() && ! empty( $value ) ) {
210
+ foreach ( $field_declaration->get_validations() as $validation ) {
211
+ $result = $this->call( $validation, array( $value ) );
212
+ if ( is_wp_error( $result ) ) {
213
+ $result->add_data(array(
214
+ 'reason' => $result->get_error_messages(),
215
+ 'field' => $field_declaration->get_data_transfer_name(),
216
+ 'value' => $value,
217
+ ) );
218
+ return $result;
219
+ }
220
+ }
221
+ }
222
+ return true;
223
+ }
224
+
225
+ /**
226
+ * Prepare the value associated with this declaraton for output.
227
+ *
228
+ * @param WP_Job_Manager_REST_Field_Declaration $field_declaration The declaration to use.
229
+ * @return mixed
230
+ */
231
+ private function prepare_value( $field_declaration ) {
232
+ $key = $field_declaration->get_name();
233
+ $value = $this->data[ $key ];
234
+ $before_return = $field_declaration->before_get();
235
+ if ( isset( $before_return ) && ! empty( $before_return ) ) {
236
+ $value = $this->call( $before_return, array( $value, $key ) );
237
+ }
238
+
239
+ return $value;
240
+ }
241
+
242
+ /**
243
+ * Sets this field's value. Used for derived fields.
244
+ *
245
+ * @param WP_Job_Manager_REST_Field_Declaration $field_declaration The field declaration.
246
+ */
247
+ private function set_field_if_unset( $field_declaration ) {
248
+ $field_name = $field_declaration->get_name();
249
+ if ( ! isset( $this->data[ $field_name ] ) ) {
250
+ if ( $field_declaration->is_kind( WP_Job_Manager_REST_Field_Declaration::DERIVED ) ) {
251
+ $map_from = $field_declaration->get_map_from();
252
+ $value = $this->call( $map_from );
253
+ $this->set( $field_name, $value );
254
+ } else {
255
+ $this->set( $field_name, $field_declaration->get_default_value() );
256
+ }
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Get this model class fields
262
+ *
263
+ * @param null|string $filter_by_type Filter.
264
+ * @return array
265
+ */
266
+ public static function get_fields( $filter_by_type = null ) {
267
+ $class_name = get_called_class();
268
+ if ( ! isset( self::$fields_by_class_name[ $class_name ] ) ) {
269
+ $fields = static::declare_fields();
270
+ self::$fields_by_class_name[ $class_name ] = self::initialize_field_map( $fields );
271
+ }
272
+
273
+ if ( null === $filter_by_type ) {
274
+ return self::$fields_by_class_name[ $class_name ];
275
+ }
276
+
277
+ $filtered = array();
278
+
279
+ foreach ( self::$fields_by_class_name[ $class_name ] as $field_declaration ) {
280
+ /**
281
+ * The field declaration.
282
+ *
283
+ * @var WP_Job_Manager_REST_Field_Declaration $field_declaration
284
+ */
285
+ if ( $field_declaration->get_kind() === $filter_by_type ) {
286
+ $filtered[] = $field_declaration;
287
+ }
288
+ }
289
+ return $filtered;
290
+ }
291
+
292
+ /**
293
+ * Initialize_field_map
294
+ *
295
+ * @param array $declared_field_builders Array<Mixtape_Model_Field_Declaration_Builder>.
296
+ *
297
+ * @return array
298
+ */
299
+ private static function initialize_field_map( $declared_field_builders ) {
300
+ $fields = array();
301
+ foreach ( $declared_field_builders as $field_builder ) {
302
+ /**
303
+ * Builder
304
+ *
305
+ * @var WP_Job_Manager_REST_Field_Declaration $field Field Builder.
306
+ */
307
+ $field = $field_builder->build();
308
+ $fields[ $field->get_name() ] = $field;
309
+ }
310
+ return $fields;
311
+ }
312
+
313
+ /**
314
+ * Get this model's data store
315
+ *
316
+ * @return WP_Job_Manager_REST_Interfaces_Data_Store
317
+ */
318
+ public static function get_data_store() {
319
+ $class_name = get_called_class();
320
+ if ( ! isset( self::$data_stores_by_class_name[ $class_name ] ) ) {
321
+ self::$data_stores_by_class_name[ $class_name ] = new WP_Job_Manager_REST_Data_Store_Nil();
322
+ }
323
+ return self::$data_stores_by_class_name[ $class_name ];
324
+ }
325
+
326
+ /**
327
+ * Set this model's data store
328
+ *
329
+ * @param WP_Job_Manager_REST_Interfaces_Data_Store $data_store A builder or a Data store.
330
+ * @throws WP_Job_Manager_REST_Exception Throws when Data Store Invalid.
331
+ */
332
+ public static function with_data_store( $data_store ) {
333
+ $class_name = get_called_class();
334
+ // at this point we should have a data store.
335
+ WP_Job_Manager_REST_Expect::is_a( $data_store, 'WP_Job_Manager_REST_Interfaces_Data_Store' );
336
+ self::$data_stores_by_class_name[ $class_name ] = $data_store;
337
+ }
338
+
339
+ /**
340
+ * Get this model's data store
341
+ *
342
+ * @return WP_Job_Manager_REST_Environment
343
+ */
344
+ public static function get_environment() {
345
+ return self::$environment;
346
+ }
347
+
348
+ /**
349
+ * Set the model base class environment (change effective in all subclasses)
350
+ *
351
+ * @param WP_Job_Manager_REST_Environment $environment The Environment.
352
+ *
353
+ * @throws WP_Job_Manager_REST_Exception If an WP_Job_Manager_REST_Environment is not provided.
354
+ */
355
+ public static function with_environment( $environment ) {
356
+ WP_Job_Manager_REST_Expect::is_a( $environment, 'WP_Job_Manager_REST_Environment' );
357
+ self::$environment = $environment;
358
+ }
359
+
360
+ /**
361
+ * Create a new Model Instance
362
+ *
363
+ * @param array $data The data.
364
+ * @param array $args Args.
365
+ *
366
+ * @return WP_Job_Manager_REST_Interfaces_Model
367
+ * @throws WP_Job_Manager_REST_Exception Throws if data not an array.
368
+ */
369
+ public static function create( $data, $args = array() ) {
370
+ WP_Job_Manager_REST_Expect::that( is_array( $data ), '$data should be an array' );
371
+ WP_Job_Manager_REST_Expect::that( is_array( $args ), '$args should be an array' );
372
+ $class_name = get_called_class();
373
+ return new $class_name( $data, $args );
374
+ }
375
+
376
+ /**
377
+ * Merge values from array with current values.
378
+ * Note: Values change in place.
379
+ *
380
+ * @param array $data The data (key-value assumed).
381
+ * @param bool $updating Is this an update?.
382
+ *
383
+ * @return WP_Job_Manager_REST_Interfaces_Model|WP_Error
384
+ * @throws WP_Job_Manager_REST_Exception Throws.
385
+ */
386
+ function update_from_array( $data, $updating = false ) {
387
+ $mapped_data = self::map_data( $data, $updating );
388
+ foreach ( $mapped_data as $name => $value ) {
389
+ $this->set( $name, $value );
390
+ }
391
+ return $this->sanitize();
392
+ }
393
+
394
+ /**
395
+ * Creates a new Model From a Data Array
396
+ *
397
+ * @param array $data The Data.
398
+ *
399
+ * @return WP_Job_Manager_REST_Model|WP_Error
400
+ */
401
+ public static function new_from_array( $data ) {
402
+ $field_data = self::map_data( $data, false );
403
+ return self::create( $field_data )->sanitize();
404
+ }
405
+
406
+ /**
407
+ * Get field DTO Mappings
408
+ *
409
+ * @return array
410
+ */
411
+ public function get_dto_field_mappings() {
412
+ $mappings = array();
413
+ foreach ( self::get_fields() as $field_declaration ) {
414
+ /**
415
+ * Declaration
416
+ *
417
+ * @var WP_Job_Manager_REST_Field_Declaration $field_declaration
418
+ */
419
+ if ( ! $field_declaration->supports_output_type( 'json' ) ) {
420
+ continue;
421
+ }
422
+ $mappings[ $field_declaration->get_data_transfer_name() ] = $field_declaration->get_name();
423
+ }
424
+ return $mappings;
425
+ }
426
+
427
+ /**
428
+ * Prepare the Model for Data Transfer
429
+ *
430
+ * @return array
431
+ */
432
+ function to_dto() {
433
+ $result = array();
434
+ foreach ( self::get_dto_field_mappings() as $mapping_name => $field_name ) {
435
+ $value = $this->get( $field_name );
436
+ $result[ $mapping_name ] = $value;
437
+ }
438
+
439
+ return $result;
440
+ }
441
+
442
+ /**
443
+ * Map data names
444
+ *
445
+ * @param array $data The data to map.
446
+ * @param bool $updating Are we Updating.
447
+ * @return array
448
+ */
449
+ private static function map_data( $data, $updating = false ) {
450
+ $request_data = array();
451
+ $fields = self::get_fields();
452
+ foreach ( $fields as $field ) {
453
+ /**
454
+ * Field
455
+ *
456
+ * @var WP_Job_Manager_REST_Field_Declaration $field Field.
457
+ */
458
+ if ( $field->is_kind( WP_Job_Manager_REST_Field_Declaration::DERIVED ) ) {
459
+ continue;
460
+ }
461
+ $dto_name = $field->get_data_transfer_name();
462
+ $field_name = $field->get_name();
463
+ if ( isset( $data[ $dto_name ] ) && ! ( $updating && $field->is_primary() ) ) {
464
+ $value = $data[ $dto_name ];
465
+ $request_data[ $field_name ] = $value;
466
+ }
467
+ }
468
+ return $request_data;
469
+ }
470
+
471
+ /**
472
+ * Call a method.
473
+ *
474
+ * @param string $method The method.
475
+ * @param array $args The args.
476
+ *
477
+ * @return mixed
478
+ * @throws WP_Job_Manager_REST_Exception Throw if method nonexistent.
479
+ */
480
+ private function call( $method, $args = array() ) {
481
+ if ( is_callable( $method ) ) {
482
+ return call_user_func_array( $method, $args );
483
+ }
484
+ WP_Job_Manager_REST_Expect::that( method_exists( $this, $method ), $method . ' does not exist' );
485
+ return call_user_func_array( array( $this, $method ), $args );
486
+ }
487
+
488
+ /**
489
+ * Get name
490
+ *
491
+ * @return string
492
+ */
493
+ public function get_name() {
494
+ return strtolower( get_class( $this ) );
495
+ }
496
+
497
+ /**
498
+ * Declare fields.
499
+ *
500
+ * @return array
501
+ */
502
+ public static function declare_fields() {
503
+ WP_Job_Manager_REST_Expect::should_override( __METHOD__ );
504
+ return array();
505
+ }
506
+
507
+ /**
508
+ * Get the id
509
+ *
510
+ * @return mixed|null
511
+ */
512
+ function get_id() {
513
+ return $this->get( 'id' );
514
+ }
515
+
516
+ /**
517
+ * Set the id
518
+ *
519
+ * @param mixed $new_id The new id.
520
+ *
521
+ * @return mixed|null
522
+ */
523
+ function set_id( $new_id ) {
524
+ return $this->set( 'id', $new_id );
525
+ }
526
+
527
+ /**
528
+ * Handle Permissions for a REST Controller Action
529
+ *
530
+ * @param WP_REST_Request $request The request.
531
+ * @param string $action The action (e.g. index, create update etc).
532
+ * @return bool
533
+ */
534
+ public static function permissions_check( $request, $action ) {
535
+ return true;
536
+ }
537
+
538
+ /**
539
+ * Create from Post.
540
+ *
541
+ * @param WP_Post $post Post.
542
+ * @return WP_Job_Manager_REST_Model
543
+ * @throws WP_Job_Manager_REST_Exception If something goes wrong.
544
+ */
545
+ public static function from_raw_data( $post ) {
546
+ $raw_post_data = $post->to_array();
547
+ $raw_meta_data = get_post_meta( $post->ID ); // assumes we are only ever adding one postmeta per key.
548
+
549
+ $flattened_meta = array();
550
+ foreach ( $raw_meta_data as $key => $value_arr ) {
551
+ $flattened_meta[ $key ] = $value_arr[0];
552
+ }
553
+ $merged_data = array_merge( $raw_post_data, $flattened_meta );
554
+
555
+ return self::create( $merged_data, array(
556
+ 'deserialize' => true,
557
+ ) );
558
+ }
559
+
560
+ /**
561
+ * Transform raw data to model data
562
+ *
563
+ * @param array $data Data.
564
+ * @return array
565
+ */
566
+ public function deserialize( $data ) {
567
+ $field_declarations = self::get_fields();
568
+ $raw_data = array();
569
+ $post_array_keys = array_keys( $data );
570
+ foreach ( $field_declarations as $declaration ) {
571
+ /**
572
+ * Declaration
573
+ *
574
+ * @var WP_Job_Manager_REST_Field_Declaration $declaration
575
+ */
576
+ $key = $declaration->get_name();
577
+ $mapping = $declaration->get_map_from();
578
+ $value = null;
579
+ if ( in_array( $key, $post_array_keys, true ) ) {
580
+ // simplest case: we got a $key for this, so just map it.
581
+ $value = $this->deserialize_field( $declaration, $data[ $key ] );
582
+ } elseif ( in_array( $mapping, $post_array_keys, true ) ) {
583
+ $value = $this->deserialize_field( $declaration, $data[ $mapping ] );
584
+ } else {
585
+ $value = $declaration->get_default_value();
586
+ }
587
+ $raw_data[ $key ] = $declaration->cast_value( $value );
588
+ }
589
+ return $raw_data;
590
+ }
591
+
592
+ /**
593
+ * Transform Model to raw data array
594
+ *
595
+ * @param null|string $field_type Type.
596
+ *
597
+ * @return array
598
+ */
599
+ function serialize( $field_type = null ) {
600
+ $field_values_to_insert = array();
601
+ foreach ( self::get_fields( $field_type ) as $field_declaration ) {
602
+ /**
603
+ * Declaration
604
+ *
605
+ * @var WP_Job_Manager_REST_Field_Declaration $field_declaration
606
+ */
607
+ $what_to_map_to = $field_declaration->get_map_from();
608
+ $value = $this->get( $field_declaration->get_name() );
609
+ $field_values_to_insert[ $what_to_map_to ] = $this->serialize_field( $field_declaration, $value );
610
+ }
611
+
612
+ return $field_values_to_insert;
613
+ }
614
+
615
+ /**
616
+ * Deserialize
617
+ *
618
+ * @param WP_Job_Manager_REST_Field_Declaration $field_declaration Declaration.
619
+ * @param mixed $value Value.
620
+ * @return mixed the deserialized value
621
+ */
622
+ private function deserialize_field( $field_declaration, $value ) {
623
+ $deserializer = $field_declaration->get_deserializer();
624
+ if ( isset( $deserializer ) && ! empty( $deserializer ) ) {
625
+ return $this->call( $deserializer, array( $value ) );
626
+ }
627
+ return $value;
628
+ }
629
+
630
+ /**
631
+ * Serialize
632
+ *
633
+ * @param WP_Job_Manager_REST_Field_Declaration $field_declaration Declaration.
634
+ * @param mixed $value Value.
635
+ * @return mixed
636
+ * @throws WP_Job_Manager_REST_Exception If call fails.
637
+ */
638
+ private function serialize_field( $field_declaration, $value ) {
639
+ $serializer = $field_declaration->get_serializer();
640
+ if ( isset( $serializer ) && ! empty( $serializer ) ) {
641
+ return $this->call( $serializer, array( $value ) );
642
+ }
643
+ return $value;
644
+ }
645
+ }
lib/wpjm_rest/class-wp-job-manager-rest-type.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The default Mixtape_Interfaces_Type Implementation
4
+ *
5
+ * @package Mixtape/Type
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class Mixtape_Type
14
+ */
15
+ class WP_Job_Manager_REST_Type implements WP_Job_Manager_REST_Interfaces_Type {
16
+ /**
17
+ * The unique identifier of this type.
18
+ *
19
+ * @var string
20
+ */
21
+ protected $identifier;
22
+ /**
23
+ * Mixtape_Type constructor.
24
+ *
25
+ * @param string $identifier The identifier.
26
+ */
27
+ function __construct( $identifier ) {
28
+ $this->identifier = $identifier;
29
+ }
30
+
31
+ /**
32
+ * The name
33
+ *
34
+ * @return string
35
+ */
36
+ function name() {
37
+ return $this->identifier;
38
+ }
39
+
40
+ /**
41
+ * The default value
42
+ *
43
+ * @return null
44
+ */
45
+ function default_value() {
46
+ return null;
47
+ }
48
+
49
+ /**
50
+ * Cast value to be Type
51
+ *
52
+ * @param mixed $value The value that needs casting.
53
+ *
54
+ * @return mixed
55
+ */
56
+ function cast( $value ) {
57
+ return $value;
58
+ }
59
+
60
+ /**
61
+ * Sanitize this value
62
+ *
63
+ * @param mixed $value The value to sanitize.
64
+ *
65
+ * @return mixed
66
+ */
67
+ function sanitize( $value ) {
68
+ return $value;
69
+ }
70
+
71
+ /**
72
+ * Get this type's JSON Schema.
73
+ *
74
+ * @return array
75
+ */
76
+ function schema() {
77
+ return array(
78
+ 'type' => $this->name(),
79
+ );
80
+ }
81
+
82
+ /**
83
+ * Get our "Any" type
84
+ *
85
+ * @return WP_Job_Manager_REST_Type
86
+ */
87
+ static function any() {
88
+ return new self( 'any' );
89
+ }
90
+ }
lib/wpjm_rest/controller/bundle/class-wp-job-manager-rest-controller-bundle-builder.php ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Build a Bundle
4
+ *
5
+ * @package WP_Job_Manager_REST/Controller
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Controller_Bundle_Builder
14
+ */
15
+ class WP_Job_Manager_REST_Controller_Bundle_Builder implements WP_Job_Manager_REST_Interfaces_Builder {
16
+
17
+ /**
18
+ * Prefix.
19
+ *
20
+ * @var string
21
+ */
22
+ private $bundle_prefix;
23
+ /**
24
+ * Env.
25
+ *
26
+ * @var WP_Job_Manager_REST_Environment
27
+ */
28
+ private $environment;
29
+ /**
30
+ * Endpoint Builders.
31
+ *
32
+ * @var array
33
+ */
34
+ private $endpoint_builders = array();
35
+ /**
36
+ * Bundle.
37
+ *
38
+ * @var WP_Job_Manager_REST_Controller_Bundle|null
39
+ */
40
+ private $bundle = null;
41
+
42
+ /**
43
+ * WP_Job_Manager_REST_Controller_Bundle_Builder constructor.
44
+ *
45
+ * @param WP_Job_Manager_REST_Interfaces_Controller_Bundle|null $bundle Bundle.
46
+ */
47
+ function __construct( $bundle = null ) {
48
+ $this->bundle = $bundle;
49
+ }
50
+
51
+ /**
52
+ * Build it
53
+ *
54
+ * @return WP_Job_Manager_REST_Interfaces_Controller_Bundle
55
+ */
56
+ public function build() {
57
+ if ( is_a( $this->bundle, 'WP_Job_Manager_REST_Interfaces_Controller_Bundle' ) ) {
58
+ return $this->bundle;
59
+ }
60
+ return new WP_Job_Manager_REST_Controller_Bundle( $this->bundle_prefix, $this->endpoint_builders );
61
+ }
62
+
63
+ /**
64
+ * Prefix.
65
+ *
66
+ * @param string $bundle_prefix Prefix.
67
+ * @return WP_Job_Manager_REST_Controller_Bundle_Builder $this
68
+ */
69
+ public function with_prefix( $bundle_prefix ) {
70
+ $this->bundle_prefix = $bundle_prefix;
71
+ return $this;
72
+ }
73
+
74
+ /**
75
+ * Env.
76
+ *
77
+ * @param WP_Job_Manager_REST_Environment $env Env.
78
+ * @return WP_Job_Manager_REST_Controller_Bundle_Builder $this
79
+ */
80
+ public function with_environment( $env ) {
81
+ $this->environment = $env;
82
+ return $this;
83
+ }
84
+
85
+ /**
86
+ * Endpoint.
87
+ *
88
+ * Adds a new WP_Job_Manager_REST_Controller_Builder to our builders and returns it for further setup.
89
+ *
90
+ * @param null|WP_Job_Manager_REST_Interfaces_Controller $controller_object The (optional) controller object.
91
+ * @return WP_Job_Manager_REST_Controller_Bundle_Builder $this
92
+ */
93
+ public function add_endpoint( $controller_object = null ) {
94
+ WP_Job_Manager_REST_Expect::is_a( $controller_object, 'WP_Job_Manager_REST_Interfaces_Controller' );
95
+ $this->endpoint_builders[] = $controller_object;
96
+ return $this;
97
+ }
98
+ }
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-action.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An Acton that is part of a Route.
4
+ *
5
+ * @package WP_Job_Manager_REST/Controller
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Controller_Action
14
+ */
15
+ class WP_Job_Manager_REST_Controller_Action {
16
+ /**
17
+ * Permitted actions
18
+ *
19
+ * @var array
20
+ */
21
+ private $actions_to_http_methods = array(
22
+ 'index' => WP_REST_Server::READABLE,
23
+ 'show' => WP_REST_Server::READABLE,
24
+ 'create' => WP_REST_Server::CREATABLE,
25
+ 'update' => WP_REST_Server::EDITABLE,
26
+ 'delete' => WP_REST_Server::DELETABLE,
27
+ 'any' => WP_REST_Server::ALLMETHODS,
28
+ );
29
+
30
+ /**
31
+ * The action name
32
+ *
33
+ * @var string
34
+ */
35
+ private $action_name;
36
+
37
+ /**
38
+ * The Handler
39
+ *
40
+ * @var null|array|string
41
+ */
42
+ private $handler;
43
+
44
+ /**
45
+ * The Permissions Callback
46
+ *
47
+ * @var null|array|string
48
+ */
49
+ private $permission_callback;
50
+
51
+ /**
52
+ * The Args
53
+ *
54
+ * @var null|array|string
55
+ */
56
+ private $args;
57
+
58
+ /**
59
+ * WP_Job_Manager_REST_Controller_Action constructor.
60
+ *
61
+ * @param WP_Job_Manager_REST_Controller $controller Controller.
62
+ * @param string $action_name The action Name.
63
+ */
64
+ public function __construct( $controller, $action_name ) {
65
+ $is_known_action = in_array( $action_name, array_keys( $this->actions_to_http_methods ), true );
66
+ WP_Job_Manager_REST_Expect::that( $is_known_action, 'Unknown method: ' . $action_name );
67
+
68
+ $this->controller = $controller;
69
+ $this->action_name = $action_name;
70
+ $this->handler = null;
71
+ $this->args = null;
72
+ $this->permission_callback = null;
73
+ }
74
+
75
+ /**
76
+ * Get Name
77
+ *
78
+ * @return string
79
+ */
80
+ public function name() {
81
+ return $this->action_name;
82
+ }
83
+
84
+ /**
85
+ * Set Permissions
86
+ *
87
+ * @param mixed $callable A Callable.
88
+ *
89
+ * @return WP_Job_Manager_REST_Controller_Action
90
+ */
91
+ public function permissions( $callable ) {
92
+ $this->permission_callback = $callable;
93
+ return $this;
94
+ }
95
+
96
+ /**
97
+ * Set Handler
98
+ *
99
+ * @param mixed $callable A Callable.
100
+ *
101
+ * @return WP_Job_Manager_REST_Controller_Action
102
+ */
103
+ public function callback( $callable ) {
104
+ $this->handler = $callable;
105
+ return $this;
106
+ }
107
+
108
+ /**
109
+ * Set Handler
110
+ *
111
+ * @param mixed $callable A Callable.
112
+ *
113
+ * @return WP_Job_Manager_REST_Controller_Action
114
+ */
115
+ public function args( $callable ) {
116
+ $this->args = $callable;
117
+ return $this;
118
+ }
119
+
120
+ /**
121
+ * Used in register rest route
122
+ *
123
+ * @return array
124
+ */
125
+ public function as_array() {
126
+ $callable_func = $this->expect_callable( $this->handler );
127
+ if ( null !== $this->permission_callback ) {
128
+ $permission_callback = $this->expect_callable( $this->permission_callback );
129
+ } else {
130
+ $permission_callback = $this->expect_callable( array( $this->controller, $this->action_name . '_permissions_check' ) );
131
+ }
132
+
133
+ if ( null !== $this->args ) {
134
+ $args = call_user_func( $this->expect_callable( $this->args ), $this->actions_to_http_methods[ $this->action_name ] );
135
+ } else {
136
+ $args = $this->controller->get_endpoint_args_for_item_schema( $this->actions_to_http_methods[ $this->action_name ] );
137
+ }
138
+
139
+ $result = array(
140
+ 'methods' => $this->actions_to_http_methods[ $this->action_name ],
141
+ 'callback' => $callable_func,
142
+ 'permission_callback' => $permission_callback,
143
+ 'args' => $args,
144
+ );
145
+
146
+ return $result;
147
+ }
148
+
149
+ /**
150
+ * Expect a callable
151
+ *
152
+ * @param mixed $callable_func A Callable.
153
+ * @return array
154
+ * @throws WP_Job_Manager_REST_Exception If not a callable.
155
+ */
156
+ private function expect_callable( $callable_func ) {
157
+ if ( ! is_callable( $callable_func ) ) {
158
+ // Check if controller has a public method called $callable_func.
159
+ if ( is_string( $callable_func ) && method_exists( $this->controller, $callable_func ) ) {
160
+ return array( $this->controller, $callable_func );
161
+ }
162
+ WP_Job_Manager_REST_Expect::that( is_callable( $callable_func ), 'Callable Expected: $callable_func' );
163
+ }
164
+ return $callable_func;
165
+ }
166
+ }
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-bundle.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A Collection of Controllers, under the same prefix
4
+ *
5
+ * @package WP_Job_Manager_REST/Controller
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Controller_Bundle
14
+ */
15
+ class WP_Job_Manager_REST_Controller_Bundle implements WP_Job_Manager_REST_Interfaces_Controller_Bundle {
16
+
17
+ /**
18
+ * The prefix of this bundle (required)
19
+ *
20
+ * @var string|null
21
+ */
22
+ protected $prefix = null;
23
+
24
+ /**
25
+ * Collection of Mixtape_Rest_Api_Controller subclasses
26
+ *
27
+ * @var array
28
+ */
29
+ protected $endpoints = array();
30
+ /**
31
+ * Our Endpoint Builders
32
+ *
33
+ * @var array
34
+ */
35
+ private $endpoint_builders;
36
+ /**
37
+ * Environment.
38
+ *
39
+ * @var WP_Job_Manager_REST_Environment
40
+ */
41
+ private $environment;
42
+
43
+ /**
44
+ * WP_Job_Manager_REST_Controller_Bundle_Definition constructor.
45
+ *
46
+ * @param string $bundle_prefix Prefix.
47
+ * @param array $endpoints Builders.
48
+ */
49
+ function __construct( $bundle_prefix, $endpoints ) {
50
+ $this->prefix = $bundle_prefix;
51
+ $this->endpoints = $endpoints;
52
+ }
53
+
54
+ /**
55
+ * Register this bundle with the environment.
56
+ *
57
+ * @param WP_Job_Manager_REST_Environment $environment The Environment.
58
+ * @return WP_Job_Manager_REST_Controller_Bundle $this
59
+ * @throws WP_Job_Manager_REST_Exception When no prefix is defined.
60
+ */
61
+ function register( $environment ) {
62
+ WP_Job_Manager_REST_Expect::that( null !== $this->prefix, 'prefix should be defined' );
63
+ $this->environment = $environment;
64
+ /**
65
+ * Add/remove endpoints. Useful for extensions
66
+ *
67
+ * @param array $endpoints An array of WP_Job_Manager_REST_Interfaces_Controller
68
+ * @param $bundle WP_Job_Manager_REST_Controller_Bundle The bundle instance.
69
+ *
70
+ * @return array
71
+ */
72
+ $endpoints = (array) apply_filters(
73
+ 'mt_rest_api_controller_bundle_get_endpoints',
74
+ $this->endpoints,
75
+ $this
76
+ );
77
+
78
+ foreach ( $endpoints as $endpoint ) {
79
+ /**
80
+ * Controller
81
+ *
82
+ * @var WP_Job_Manager_REST_Interfaces_Controller
83
+ */
84
+ $endpoint->register( $this, $this->environment );
85
+ }
86
+
87
+ return $this;
88
+ }
89
+
90
+ /**
91
+ * Get Prefix.
92
+ *
93
+ * @return string
94
+ */
95
+ function get_prefix() {
96
+ return $this->prefix;
97
+ }
98
+ }
99
+
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-crud.php ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Classic Create, Read, Update, Delete Controller
4
+ *
5
+ * @package WP_Job_Manager_REST/Controller
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ } // End if().
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Controller_CRUD
14
+ */
15
+ class WP_Job_Manager_REST_Controller_CRUD extends WP_Job_Manager_REST_Controller_Model implements WP_Job_Manager_REST_Interfaces_Controller {
16
+
17
+ /**
18
+ * Setup
19
+ */
20
+ public function setup() {
21
+ $this->add_route( '/' )
22
+ ->add_action( $this->action( 'index', array( $this, 'get_items' ) ) )
23
+ ->add_action( $this->action( 'create', array( $this, 'create_item' ) ) );
24
+
25
+ $this->add_route( '/(?P<id>\d+)' )
26
+ ->add_action( $this->action( 'show', array( $this, 'get_item' ) ) )
27
+ ->add_action( $this->action( 'update', array( $this, 'update_item' ) ) )
28
+ ->add_action( $this->action( 'delete', array( $this, 'delete_item' ) ) );
29
+ }
30
+
31
+ /**
32
+ * Get Items.
33
+ *
34
+ * @param WP_REST_Request $request Request.
35
+ * @return WP_REST_Response
36
+ */
37
+ public function get_items( $request ) {
38
+ $item_id = isset( $request['id'] ) ? absint( $request['id'] ) : null;
39
+
40
+ if ( null === $item_id ) {
41
+ $models = $this->get_model_data_store()->get_entities();
42
+ $data = $this->prepare_dto( $models );
43
+ return $this->ok( $data );
44
+ }
45
+
46
+ $model = $this->model_factory->get_data_store()->get_entity( $item_id );
47
+ if ( empty( $model ) ) {
48
+ return $this->not_found( __( 'Model not found' ) );
49
+ }
50
+
51
+ return $this->ok( $this->prepare_dto( $model ) );
52
+ }
53
+
54
+ /**
55
+ * Get Item
56
+ *
57
+ * @param WP_REST_Request $request Request.
58
+ * @return WP_REST_Response
59
+ */
60
+ public function get_item( $request ) {
61
+ return $this->get_items( $request );
62
+ }
63
+
64
+
65
+ /**
66
+ * Create Item
67
+ *
68
+ * @param WP_REST_Request $request Request.
69
+ * @return WP_REST_Response
70
+ */
71
+ public function create_item( $request ) {
72
+ $is_update = false;
73
+ return $this->create_or_update( $request, $is_update );
74
+ }
75
+
76
+ /**
77
+ * Update Item
78
+ *
79
+ * @param WP_REST_Request $request Request.
80
+ * @return WP_REST_Response
81
+ */
82
+ public function update_item( $request ) {
83
+ $is_update = true;
84
+ return $this->create_or_update( $request, $is_update );
85
+ }
86
+
87
+ /**
88
+ * Create Or Update Item
89
+ *
90
+ * @param WP_REST_Request $request Request.
91
+ * @param bool $is_update Is Update.
92
+ *
93
+ * @return WP_REST_Response
94
+ */
95
+ protected function create_or_update( $request, $is_update = false ) {
96
+ $model_to_update = null;
97
+ if ( $is_update ) {
98
+ $id = isset( $request['id'] ) ? absint( $request['id'] ) : null;
99
+ if ( ! empty( $id ) ) {
100
+ $model_to_update = $this->model_factory->get_data_store()->get_entity( $id );
101
+ if ( empty( $model_to_update ) ) {
102
+ return $this->not_found( 'Model does not exist' );
103
+ }
104
+ }
105
+ }
106
+
107
+ if ( $is_update && $model_to_update ) {
108
+ $model = $model_to_update->update_from_array( $request->get_params(), $is_update );
109
+ } else {
110
+ $model = $this->get_model_factory()->new_from_array( $request->get_params() );
111
+ }
112
+
113
+ if ( is_wp_error( $model ) ) {
114
+ $wp_err = $model;
115
+ return $this->bad_request( $wp_err );
116
+ }
117
+
118
+ $validation = $model->validate();
119
+ if ( is_wp_error( $validation ) ) {
120
+ return $this->bad_request( $validation );
121
+ }
122
+
123
+ $id_or_error = $this->model_data_store->upsert( $model );
124
+
125
+ if ( is_wp_error( $id_or_error ) ) {
126
+ return $this->bad_request( $id_or_error );
127
+ }
128
+
129
+ $dto = $this->prepare_dto( array(
130
+ 'id' => absint( $id_or_error ),
131
+ ) );
132
+
133
+ return $is_update ? $this->ok( $dto ) : $this->created( $dto );
134
+ }
135
+
136
+ /**
137
+ * Delete an Item
138
+ *
139
+ * @param WP_REST_Request $request Request.
140
+ * @return WP_REST_Response
141
+ */
142
+ public function delete_item( $request ) {
143
+ $id = isset( $request['id'] ) ? absint( $request['id'] ) : null;
144
+ if ( empty( $id ) ) {
145
+ return $this->bad_request( 'No Model ID provided' );
146
+ }
147
+ $model = $this->model_factory->get_data_store()->get_entity( $id );
148
+ if ( null === $model ) {
149
+ return $this->not_found( 'Model does not exist' );
150
+ }
151
+ $result = $this->model_data_store->delete( $model );
152
+ return $this->ok( $result );
153
+ }
154
+
155
+ /**
156
+ * Model To Dto
157
+ *
158
+ * @param WP_Job_Manager_REST_Interfaces_Model $model The Model.
159
+ * @return array
160
+ */
161
+ protected function model_to_dto( $model ) {
162
+ $result = parent::model_to_dto( $model );
163
+ $result['_links'] = $this->add_links( $model );
164
+ return $result;
165
+ }
166
+
167
+ /**
168
+ * Add Links
169
+ *
170
+ * @param WP_Job_Manager_REST_Interfaces_Model $model Model.
171
+ * @return array
172
+ */
173
+ protected function add_links( $model ) {
174
+ $base_url = rest_url() . $this->controller_bundle->get_prefix() . $this->base . '/';
175
+
176
+ $result = array(
177
+ 'collection' => array(
178
+ array(
179
+ 'href' => esc_url( $base_url ),
180
+ ),
181
+ ),
182
+ );
183
+ if ( $model->get_id() ) {
184
+ $result['self'] = array(
185
+ array(
186
+ 'href' => esc_url( $base_url . $model->get_id() ),
187
+ ),
188
+ );
189
+ }
190
+ if ( $model->has( 'author' ) ) {
191
+ $result['author'] = array(
192
+ array(
193
+ 'href' => esc_url( rest_url() . 'wp/v2/users/' . $model->get( 'author' ) ),
194
+ ),
195
+ );
196
+ }
197
+ return $result;
198
+ }
199
+ }
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-extension.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Controller-like class used for extending existing object types (e.g. post)
4
+ * With custom fields. Needs a model definition that will provide the extra fields.
5
+ *
6
+ * @package WP_Job_Manager_REST/Controller
7
+ */
8
+
9
+ /**
10
+ * Class WP_Job_Manager_REST_Controller_Extension
11
+ */
12
+ class WP_Job_Manager_REST_Controller_Extension implements WP_Job_Manager_REST_Interfaces_Registrable {
13
+ /**
14
+ * Environment
15
+ *
16
+ * @var WP_Job_Manager_REST_Environment
17
+ */
18
+ private $environment;
19
+ /**
20
+ * Object to extend
21
+ *
22
+ * @var string
23
+ */
24
+ private $object_to_extend;
25
+ /**
26
+ * Model def.
27
+ *
28
+ * @var WP_Job_Manager_REST_Model_Definition
29
+ */
30
+ private $model_definition;
31
+ /**
32
+ * Model Definition name, This should be a valid Model definition at registration time, otherwise register will throw
33
+ *
34
+ * @var string
35
+ */
36
+ private $model_definition_name;
37
+
38
+ /**
39
+ * WP_Job_Manager_REST_Controller_Extension constructor.
40
+ *
41
+ * @param string $object_to_extend Post type.
42
+ * @param string $model_definition_name Model Definition name.
43
+ */
44
+ function __construct( $object_to_extend, $model_definition_name ) {
45
+ $this->model_definition_name = $model_definition_name;
46
+ $this->object_to_extend = $object_to_extend;
47
+ }
48
+
49
+ /**
50
+ * Register This Controller
51
+ *
52
+ * @param WP_Job_Manager_REST_Environment $environment The Environment to use.
53
+ * @throws WP_Job_Manager_REST_Exception Throws.
54
+ *
55
+ * @return bool|WP_Error true if valid otherwise error.
56
+ */
57
+ function register( $environment ) {
58
+ $this->environment = $environment;
59
+ $this->model_definition = $this->environment->model( $this->model_definition_name );
60
+ if ( ! $this->model_definition ) {
61
+ return new WP_Error( 'model-not-found' );
62
+ }
63
+ $fields = $this->model_definition->get_fields();
64
+ foreach ( $fields as $field ) {
65
+ $this->register_field( $field );
66
+ }
67
+
68
+ return true;
69
+ }
70
+
71
+ /**
72
+ * Register Field
73
+ *
74
+ * @param WP_Job_Manager_REST_Field_Declaration $field Field.
75
+ */
76
+ private function register_field( $field ) {
77
+ register_rest_field( $this->object_to_extend, $field->get_data_transfer_name(), array(
78
+ 'get_callback' => $field->get_reader(),
79
+ 'update_callback' => $field->get_updater(),
80
+ 'schema' => $field->as_item_schema_property(),
81
+ ) );
82
+ }
83
+ }
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-model.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A Controller that is related to a Model Declaration.
4
+ *
5
+ * @package WP_Job_Manager_REST/Controller
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Controller_Model
14
+ * Knows about models
15
+ */
16
+ class WP_Job_Manager_REST_Controller_Model extends WP_Job_Manager_REST_Controller implements WP_Job_Manager_REST_Interfaces_Controller {
17
+
18
+ /**
19
+ * The Factory
20
+ *
21
+ * @var WP_Job_Manager_REST_Model_Factory
22
+ */
23
+ protected $model_factory;
24
+
25
+ /**
26
+ * The data Store
27
+ *
28
+ * @var WP_Job_Manager_REST_Interfaces_Data_Store
29
+ */
30
+ protected $model_data_store;
31
+
32
+ /**
33
+ * Model Definition Name
34
+ *
35
+ * @var string
36
+ */
37
+ private $model_class_name;
38
+
39
+ /**
40
+ * WP_Job_Manager_REST_Controller_Model constructor.
41
+ *
42
+ * @param string $base The baser.
43
+ * @param string $model_class_name A Definition or a definition name.
44
+ */
45
+ public function __construct( $base, $model_class_name ) {
46
+ $this->base = $base;
47
+ $this->model_class_name = $model_class_name;
48
+ }
49
+
50
+ /**
51
+ * Get our model factory
52
+ *
53
+ * @return WP_Job_Manager_REST_Model_Factory
54
+ */
55
+ protected function get_model_factory() {
56
+ return $this->model_factory;
57
+ }
58
+
59
+ /**
60
+ * Register this controller, initialize model-related object fields.
61
+ *
62
+ * @param WP_Job_Manager_REST_Controller_Bundle $bundle The bundle to use.
63
+ * @param WP_Job_Manager_REST_Environment $environment The Environment.
64
+ *
65
+ * @throws WP_Job_Manager_REST_Exception If an invalid model is provided.
66
+ *
67
+ * @return bool|WP_Error true if valid otherwise error.
68
+ */
69
+ public function register( $bundle, $environment ) {
70
+ $this->model_factory = $environment->model( $this->model_class_name );
71
+ $this->model_data_store = $this->model_factory->get_data_store();
72
+ return parent::register( $bundle, $environment );
73
+ }
74
+
75
+ /**
76
+ * Retrieves the item's schema, conforming to JSON Schema.
77
+ *
78
+ * In our case, it gets fields/types from our definition's declared fields.
79
+ *
80
+ * @access public
81
+ *
82
+ * @return array Item schema data.
83
+ */
84
+ public function get_item_schema() {
85
+ $model_definition = $this->get_model_factory();
86
+ $fields = $model_definition->get_fields();
87
+ $properties = array();
88
+ $required = array();
89
+ foreach ( $fields as $field_declaration ) {
90
+ /**
91
+ * Our declaration
92
+ *
93
+ * @var WP_Job_Manager_REST_Field_Declaration $field_declaration
94
+ */
95
+ $properties[ $field_declaration->get_data_transfer_name() ] = $field_declaration->as_item_schema_property();
96
+ if ( $field_declaration->is_required() ) {
97
+ $required[] = $field_declaration->get_data_transfer_name();
98
+ }
99
+ }
100
+ $schema = array(
101
+ '$schema' => 'http://json-schema.org/schema#',
102
+ 'title' => $model_definition->get_name(),
103
+ 'type' => 'object',
104
+ 'properties' => (array) apply_filters( 'mixtape_rest_api_schema_properties', $properties, $this->get_model_factory() ),
105
+ );
106
+
107
+ if ( ! empty( $required ) ) {
108
+ $schema['required'] = $required;
109
+ }
110
+
111
+ return $this->add_additional_fields_schema( $schema );
112
+ }
113
+
114
+ /**
115
+ * Get Model DataStore
116
+ *
117
+ * @return WP_Job_Manager_REST_Interfaces_Data_Store
118
+ */
119
+ protected function get_model_data_store() {
120
+ return $this->model_data_store;
121
+ }
122
+
123
+ /**
124
+ * Generic Permissions Check.
125
+ *
126
+ * @param WP_REST_Request $request Request.
127
+ * @param string $action One of (index, show, create, update, delete).
128
+ * @return bool
129
+ */
130
+ public function permissions_check( $request, $action = 'any' ) {
131
+ return $this->get_model_factory()->permissions_check( $request, $action );
132
+ }
133
+
134
+ /**
135
+ * Prepare Entity to be a DTO
136
+ *
137
+ * @param array|WP_Job_Manager_REST_Model_Collection|WP_Job_Manager_REST_Interfaces_Model $entity The Entity.
138
+ * @return array
139
+ */
140
+ protected function prepare_dto( $entity ) {
141
+ if ( is_a( $entity, 'WP_Job_Manager_REST_Model_Collection' ) ) {
142
+ $results = array();
143
+ foreach ( $entity->get_items() as $model ) {
144
+ $results[] = $this->model_to_dto( $model );
145
+ }
146
+ return $results;
147
+ }
148
+
149
+ if ( is_a( $entity, 'WP_Job_Manager_REST_Interfaces_Model' ) ) {
150
+ return $this->model_to_dto( $entity );
151
+ }
152
+
153
+ return $entity;
154
+ }
155
+
156
+ /**
157
+ * Map a model to a Data Transfer Object (plain array)
158
+ *
159
+ * @param WP_Job_Manager_REST_Interfaces_Model $model The Model.
160
+ * @return array
161
+ */
162
+ protected function model_to_dto( $model ) {
163
+ return $model->to_dto();
164
+ }
165
+ }
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-route.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A Route that is part of a controller.
4
+ *
5
+ * @package WP_Job_Manager_REST/Controller
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Controller_Route
14
+ */
15
+ class WP_Job_Manager_REST_Controller_Route {
16
+
17
+ /**
18
+ * Our pattern
19
+ *
20
+ * @var string
21
+ */
22
+ private $pattern;
23
+
24
+ /**
25
+ * Our Handlers
26
+ *
27
+ * @var array
28
+ */
29
+ private $actions;
30
+
31
+ /**
32
+ * Our Controller
33
+ *
34
+ * @var WP_Job_Manager_REST_Controller
35
+ */
36
+ private $controller;
37
+
38
+ /**
39
+ * HTTP Methods
40
+ *
41
+ * @var array
42
+ */
43
+ private $http_methods;
44
+
45
+ /**
46
+ * WP_Job_Manager_REST_Controller_Route constructor.
47
+ *
48
+ * @param WP_Job_Manager_REST_Controller $controller A Controller.
49
+ * @param string $pattern Pattern.
50
+ */
51
+ public function __construct( $controller, $pattern ) {
52
+ $this->controller = $controller;
53
+ $this->pattern = $pattern;
54
+ $this->actions = array();
55
+ $this->http_methods = explode( ', ', WP_REST_Server::ALLMETHODS );
56
+ }
57
+
58
+ /**
59
+ * Add/Get an action
60
+ *
61
+ * @param WP_Job_Manager_REST_Controller_Action $action Action.
62
+ *
63
+ * @return WP_Job_Manager_REST_Controller_Route
64
+ */
65
+ public function add_action( $action ) {
66
+ $this->actions[ $action->name() ] = $action;
67
+ return $this;
68
+ }
69
+
70
+ /**
71
+ * Gets Route info to use in Register rest route.
72
+ *
73
+ * @throws WP_Job_Manager_REST_Exception If invalid callable.
74
+ * @return array
75
+ */
76
+ public function as_array() {
77
+ $result = array();
78
+ $result['pattern'] = $this->pattern;
79
+ $result['actions'] = array();
80
+ foreach ( $this->actions as $action => $route_action ) {
81
+ /**
82
+ * The route action.
83
+ *
84
+ * @var WP_Job_Manager_REST_Controller_Action $route_action
85
+ */
86
+ $result['actions'][] = $route_action->as_array();
87
+ }
88
+ return $result;
89
+ }
90
+ }
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-settings.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Controller for handling settings
4
+ *
5
+ * @package WP_Job_Manager_REST/Controller
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Controller_Settings
14
+ */
15
+ class WP_Job_Manager_REST_Controller_Settings extends WP_Job_Manager_REST_Controller_Model {
16
+
17
+ /**
18
+ * Setup
19
+ */
20
+ public function setup() {
21
+ $this->add_route()
22
+ ->add_action( $this->action( 'index', array( $this, 'get_items' ) ) )
23
+ ->add_action( $this->action( 'update', array( $this, 'create_item' ) ) );
24
+ }
25
+
26
+ /**
27
+ * Get Settings
28
+ *
29
+ * @param WP_REST_Request $request The request.
30
+ * @return WP_REST_Response
31
+ */
32
+ public function get_items( $request ) {
33
+ $model = $this->model_factory->get_data_store()->get_entity( null );
34
+ if ( empty( $model ) ) {
35
+ return $this->not_found( __( 'Settings not found' ) );
36
+ }
37
+
38
+ return $this->ok( $this->prepare_dto( $model ) );
39
+ }
40
+
41
+ /**
42
+ * Create or Update settings.
43
+ *
44
+ * @param WP_REST_Request $request Request.
45
+ * @return WP_REST_Response
46
+ */
47
+ public function create_item( $request ) {
48
+ return $this->create_or_update( $request );
49
+ }
50
+
51
+ /**
52
+ * Create or Update a Model
53
+ *
54
+ * @param WP_REST_Request $request Request.
55
+ * @return WP_REST_Response
56
+ */
57
+ protected function create_or_update( $request ) {
58
+ $is_update = $request->get_method() !== 'POST';
59
+ $model_to_update = $this->model_factory->get_data_store()->get_entity( null );
60
+ if ( empty( $model_to_update ) ) {
61
+ return $this->not_found( 'Model does not exist' );
62
+ }
63
+
64
+ $model = $model_to_update->update_from_array( $request->get_params(), true );
65
+
66
+ if ( is_wp_error( $model ) ) {
67
+ return $this->bad_request( $model );
68
+ }
69
+
70
+ $validation = $model->validate();
71
+ if ( is_wp_error( $validation ) ) {
72
+ return $this->bad_request( $validation );
73
+ }
74
+
75
+ $id_or_error = $this->model_data_store->upsert( $model );
76
+
77
+ if ( is_wp_error( $id_or_error ) ) {
78
+ return $this->bad_request( $id_or_error );
79
+ }
80
+
81
+ $model = $this->model_factory->get_data_store()->get_entity( null );
82
+ $dto = $this->prepare_dto( $model );
83
+
84
+ return $is_update ? $this->ok( $dto ) : $this->created( $dto );
85
+ }
86
+ }
lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-abstract.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Data Store Abstract
4
+ *
5
+ * @package WP_Job_Manager_REST/Data
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Data_Store_Abstract
14
+ * An abstract Data_Store class that contains a model factory
15
+ */
16
+ abstract class WP_Job_Manager_REST_Data_Store_Abstract implements WP_Job_Manager_REST_Interfaces_Data_Store {
17
+
18
+ /**
19
+ * Definition
20
+ *
21
+ * @var WP_Job_Manager_REST_Model_Factory
22
+ */
23
+ protected $model_factory;
24
+
25
+ /**
26
+ * Type Serializers
27
+ *
28
+ * @var array
29
+ */
30
+ private $type_serializers;
31
+
32
+ /**
33
+ * WP_Job_Manager_REST_Data_Store_Abstract constructor.
34
+ *
35
+ * @param null|WP_Job_Manager_REST_Model_Factory $model_factory Def.
36
+ * @param array $args Args.
37
+ */
38
+ public function __construct( $model_factory = null, $args = array() ) {
39
+ $this->type_serializers = array();
40
+ $this->args = $args;
41
+ if ( is_a( $model_factory, 'WP_Job_Manager_REST_Model_Factory' ) ) {
42
+ $this->set_model_factory( $model_factory );
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Set Definition
48
+ *
49
+ * @param WP_Job_Manager_REST_Model_Factory $factory Def.
50
+ *
51
+ * @return WP_Job_Manager_REST_Interfaces_Data_Store $this
52
+ */
53
+ private function set_model_factory( $factory ) {
54
+ $this->model_factory = $factory;
55
+ $this->configure();
56
+ return $this;
57
+ }
58
+
59
+ /**
60
+ * Configure
61
+ */
62
+ protected function configure() {
63
+ }
64
+
65
+ /**
66
+ * Get Definition
67
+ *
68
+ * @return WP_Job_Manager_REST_Model_Factory
69
+ */
70
+ public function get_model_factory() {
71
+ return $this->model_factory;
72
+ }
73
+ }
lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-customposttype.php ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Data Store For custom Post types
4
+ *
5
+ * @package WP_Job_Manager_REST/Data
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Data_Store_CustomPostType
14
+ */
15
+ class WP_Job_Manager_REST_Data_Store_CustomPostType extends WP_Job_Manager_REST_Data_Store_Abstract {
16
+ /**
17
+ * The post type name
18
+ *
19
+ * @var string
20
+ */
21
+ private $post_type;
22
+
23
+ /**
24
+ * Mixtape_Data_Store_CustomPostType constructor.
25
+ *
26
+ * @param null|WP_Job_Manager_REST_Model_Definition $model_factory Def.
27
+ * @param array $args Args.
28
+ */
29
+ public function __construct( $model_factory = null, $args = array() ) {
30
+ $this->post_type = isset( $args['post_type'] ) ? $args['post_type'] : 'post';
31
+ parent::__construct( $model_factory, $args );
32
+ }
33
+
34
+ /**
35
+ * Get Entities
36
+ *
37
+ * @param null|mixed $filter Filter.
38
+ *
39
+ * @return WP_Job_Manager_REST_Model_Collection
40
+ */
41
+ public function get_entities( $filter = null ) {
42
+ $query = new WP_Query( array(
43
+ 'post_type' => $this->post_type,
44
+ 'post_status' => 'any',
45
+ ) );
46
+ $posts = $query->get_posts();
47
+ $collection = array();
48
+ foreach ( $posts as $post ) {
49
+ $collection[] = $this->create_from_post( $post );
50
+ }
51
+ return new WP_Job_Manager_REST_Model_Collection( $collection );
52
+ }
53
+
54
+ /**
55
+ * Get Entity
56
+ *
57
+ * @param int $id The id of the entity.
58
+ * @return WP_Job_Manager_REST_Model|null
59
+ */
60
+ public function get_entity( $id ) {
61
+ $post = get_post( absint( $id ) );
62
+ if ( empty( $post ) || $post->post_type !== $this->post_type ) {
63
+ return null;
64
+ }
65
+
66
+ return $this->create_from_post( $post );
67
+ }
68
+
69
+ /**
70
+ * Create from Post.
71
+ *
72
+ * @param WP_Post $post Post.
73
+ * @return WP_Job_Manager_REST_Model
74
+ * @throws WP_Job_Manager_REST_Exception If something goes wrong.
75
+ */
76
+ private function create_from_post( $post ) {
77
+ $field_declarations = $this->get_model_factory()->get_fields();
78
+ $raw_post_data = $post->to_array();
79
+ $raw_meta_data = get_post_meta( $post->ID ); // assumes we are only ever adding one postmeta per key.
80
+
81
+ $flattened_meta = array();
82
+ foreach ( $raw_meta_data as $key => $value_arr ) {
83
+ $flattened_meta[ $key ] = $value_arr[0];
84
+ }
85
+ $merged_data = array_merge( $raw_post_data, $flattened_meta );
86
+
87
+ return $this->get_model_factory()->create( $merged_data, array(
88
+ 'deserialize' => true,
89
+ ) );
90
+ }
91
+
92
+ /**
93
+ * Delete
94
+ *
95
+ * @param WP_Job_Manager_REST_Interfaces_Model $model Model.
96
+ * @param array $args Args.
97
+ * @return mixed
98
+ */
99
+ public function delete( $model, $args = array() ) {
100
+ $id = $model->get_id();
101
+
102
+ $args = wp_parse_args( $args, array(
103
+ 'force_delete' => false,
104
+ ) );
105
+
106
+ do_action( 'mixtape_data_store_delete_model_before', $model, $id );
107
+
108
+ if ( $args['force_delete'] ) {
109
+ $result = wp_delete_post( $model->get_id() );
110
+ $model->set( 'id', 0 );
111
+ do_action( 'mixtape_data_store_delete_model', $model, $id );
112
+ } else {
113
+ $result = wp_trash_post( $model->get_id() );
114
+ $model->set( 'status', 'trash' );
115
+ do_action( 'mixtape_data_store_trash_model', $model, $id );
116
+ }
117
+
118
+ if ( false === $result ) {
119
+ do_action( 'mixtape_data_store_delete_model_fail', $model, $id );
120
+ return new WP_Error( 'delete-failed', 'delete-failed' );
121
+ }
122
+ return $result;
123
+ }
124
+
125
+ /**
126
+ * Upsert
127
+ *
128
+ * @param WP_Job_Manager_REST_Interfaces_Model $model Model.
129
+ *
130
+ * @return mixed|WP_Error
131
+ */
132
+ public function upsert( $model ) {
133
+ $id = $model->get_id();
134
+ $updating = ! empty( $id );
135
+ $fields = $model->serialize( WP_Job_Manager_REST_Field_Declaration::FIELD );
136
+ $meta_fields = $model->serialize( WP_Job_Manager_REST_Field_Declaration::META );
137
+ if ( ! isset( $fields['post_type'] ) ) {
138
+ $fields['post_type'] = $this->post_type;
139
+ }
140
+ if ( isset( $fields['ID'] ) && empty( $fields['ID'] ) ) {
141
+ // ID of 0 is not acceptable on CPTs, so remove it.
142
+ unset( $fields['ID'] );
143
+ }
144
+
145
+ do_action( 'mixtape_data_store_model_upsert_before', $model );
146
+
147
+ $id_or_error = wp_insert_post( $fields, true );
148
+ if ( is_wp_error( $id_or_error ) ) {
149
+ do_action( 'mixtape_data_store_model_upsert_error', $model );
150
+ return $id_or_error;
151
+ }
152
+ $model->set( 'id', absint( $id_or_error ) );
153
+ foreach ( $meta_fields as $meta_key => $meta_value ) {
154
+ if ( $updating ) {
155
+ $id_or_bool = update_post_meta( $id_or_error, $meta_key, $meta_value );
156
+ } else {
157
+ $id_or_bool = add_post_meta( $id_or_error, $meta_key, $meta_value );
158
+ }
159
+
160
+ if ( false === $id_or_bool ) {
161
+ do_action( 'mixtape_data_store_model_upsert_error', $model );
162
+ // Something was wrong with this update/create. TODO: Should we stop mid create/update?
163
+ return new WP_Error(
164
+ 'mixtape-error-creating-meta',
165
+ 'There was an error updating/creating an entity field',
166
+ array(
167
+ 'field_key' => $meta_key,
168
+ 'field_value' => $meta_value,
169
+ )
170
+ );
171
+ }
172
+ }
173
+
174
+ do_action( 'mixtape_data_store_model_upsert_after', $model );
175
+
176
+ return absint( $id_or_error );
177
+ }
178
+ }
lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-nil.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Data Store Nil (empty)
4
+ *
5
+ * @package WP_Job_Manager_REST/Data
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Data_Store_Nil
14
+ * Null object for datastores
15
+ */
16
+ class WP_Job_Manager_REST_Data_Store_Nil implements WP_Job_Manager_REST_Interfaces_Data_Store {
17
+
18
+ /**
19
+ * Get Entities
20
+ *
21
+ * @param null $filter F.
22
+ * @return WP_Job_Manager_REST_Model_Collection
23
+ */
24
+ public function get_entities( $filter = null ) {
25
+ return new WP_Job_Manager_REST_Model_Collection( array() );
26
+ }
27
+
28
+ /**
29
+ * Get Entity
30
+ *
31
+ * @param int $id Id.
32
+ * @return null
33
+ */
34
+ public function get_entity( $id ) {
35
+ return null;
36
+ }
37
+
38
+ /**
39
+ * Delete
40
+ *
41
+ * @param WP_Job_Manager_REST_Interfaces_Model $model Model.
42
+ * @param array $args Args.
43
+ * @return bool
44
+ */
45
+ public function delete( $model, $args = array() ) {
46
+ return true;
47
+ }
48
+
49
+ /**
50
+ * Upsert
51
+ *
52
+ * @param WP_Job_Manager_REST_Interfaces_Model $model Model.
53
+ * @return int
54
+ */
55
+ public function upsert( $model ) {
56
+ return 0;
57
+ }
58
+
59
+ /**
60
+ * Def
61
+ *
62
+ * @param mixed $definition Def.
63
+ */
64
+ public function set_definition( $definition ) {
65
+ }
66
+ }
lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-option.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Data Store Abstract
4
+ *
5
+ * @package WP_Job_Manager_REST/Data
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Data_Store_Option
14
+ */
15
+ class WP_Job_Manager_REST_Data_Store_Option extends WP_Job_Manager_REST_Data_Store_Abstract {
16
+
17
+ /**
18
+ * Guard value to distinguish between get_option returning results or not
19
+ *
20
+ * @var stdClass
21
+ */
22
+ private $does_not_exist_guard;
23
+
24
+ /**
25
+ * WP_Job_Manager_REST_Data_Store_Option constructor.
26
+ *
27
+ * @param WP_Job_Manager_REST_Model_Factory $model_factory Def.
28
+ * @param array $args Args.
29
+ */
30
+ public function __construct( $model_factory, $args = array() ) {
31
+ parent::__construct( $model_factory, $args );
32
+ $this->does_not_exist_guard = new stdClass();
33
+ }
34
+
35
+ /**
36
+ * Get Entities
37
+ *
38
+ * @param null|mixed $filter Filter.
39
+ * @return WP_Job_Manager_REST_Interfaces_Model
40
+ */
41
+ public function get_entities( $filter = null ) {
42
+ // there is only one option bag and one option bag global per data store.
43
+ return $this->get_entity( null );
44
+ }
45
+
46
+ /**
47
+ * Get Entity
48
+ *
49
+ * @param int $id The id of the entity.
50
+ * @return WP_Job_Manager_REST_Interfaces_Model
51
+ */
52
+ public function get_entity( $id ) {
53
+ $field_declarations = $this->get_model_factory()->get_fields();
54
+ $raw_data = array();
55
+ foreach ( $field_declarations as $field_declaration ) {
56
+ /**
57
+ * Field Declaration
58
+ *
59
+ * @var WP_Job_Manager_REST_Field_Declaration $field_declaration
60
+ */
61
+ $option = get_option( $field_declaration->get_map_from(), $this->does_not_exist_guard );
62
+ if ( $this->does_not_exist_guard !== $option ) {
63
+ $raw_data[ $field_declaration->get_map_from() ] = $option;
64
+ }
65
+ }
66
+
67
+ return $this->get_model_factory()->create( $raw_data, array(
68
+ 'deserialize' => true,
69
+ ) );
70
+ }
71
+
72
+ /**
73
+ * Delete
74
+ *
75
+ * @param WP_Job_Manager_REST_Interfaces_Model $model Model.
76
+ * @param array $args Args.
77
+ * @return mixed
78
+ */
79
+ public function delete( $model, $args = array() ) {
80
+ $options_to_delete = array_keys( $model->serialize() );
81
+ foreach ( $options_to_delete as $option_to_delete ) {
82
+ if ( false !== get_option( $option_to_delete, false ) ) {
83
+ $result = delete_option( $option_to_delete );
84
+ if ( false === $result ) {
85
+ return new WP_Error( 'delete-option-failed' );
86
+ }
87
+ }
88
+ }
89
+ return true;
90
+ }
91
+
92
+ /**
93
+ * Update/Insert
94
+ *
95
+ * @param WP_Job_Manager_REST_Interfaces_Model $model Model.
96
+ * @return mixed
97
+ */
98
+ public function upsert( $model ) {
99
+ $fields_for_insert = $model->serialize();
100
+ foreach ( $fields_for_insert as $option_name => $option_value ) {
101
+ $previous_value = get_option( $option_name, $this->does_not_exist_guard );
102
+ if ( $this->does_not_exist_guard !== $previous_value ) {
103
+ update_option( $option_name, $option_value );
104
+ } else {
105
+ add_option( $option_name, $option_value );
106
+ }
107
+ }
108
+ return true;
109
+ }
110
+ }
lib/wpjm_rest/field/class-wp-job-manager-rest-field-declaration.php ADDED
@@ -0,0 +1,434 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Fields
4
+ *
5
+ * @package WP_Job_Manager_REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ } // End if().
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Field_Declaration
14
+ */
15
+ class WP_Job_Manager_REST_Field_Declaration {
16
+
17
+ /**
18
+ * Field A field
19
+ */
20
+ const FIELD = 'field';
21
+
22
+ /**
23
+ * Meta a meta field
24
+ */
25
+ const META = 'meta';
26
+
27
+ /**
28
+ * Derived field kinds get their values from callables. It is also
29
+ * possible to update their values from callables
30
+ */
31
+ const DERIVED = 'derived';
32
+ /**
33
+ * Map From
34
+ *
35
+ * @var null|string
36
+ */
37
+ private $map_from;
38
+ /**
39
+ * The field kind
40
+ *
41
+ * @var string
42
+ */
43
+ private $kind;
44
+ /**
45
+ * Field name
46
+ *
47
+ * @var string
48
+ */
49
+ private $name;
50
+ /**
51
+ * Is this a primary field?
52
+ *
53
+ * @var bool
54
+ */
55
+ private $primary;
56
+ /**
57
+ * Is this a required field?
58
+ *
59
+ * @var bool
60
+ */
61
+ private $required;
62
+ /**
63
+ * Outputs
64
+ *
65
+ * @var array
66
+ */
67
+ private $supported_outputs;
68
+ /**
69
+ * Description
70
+ *
71
+ * @var string
72
+ */
73
+ private $description;
74
+ /**
75
+ * Data Transfer Name
76
+ *
77
+ * @var null|string
78
+ */
79
+ private $data_transfer_name;
80
+ /**
81
+ * Validations
82
+ *
83
+ * @var null|array
84
+ */
85
+ private $validations;
86
+ /**
87
+ * Default Value
88
+ *
89
+ * @var null|mixed
90
+ */
91
+ private $default_value;
92
+ /**
93
+ * Field Choices
94
+ *
95
+ * @var null|array
96
+ */
97
+ private $choices;
98
+ /**
99
+ * Type
100
+ *
101
+ * @var null|WP_Job_Manager_REST_Interfaces_Type
102
+ */
103
+ private $type;
104
+ /**
105
+ * Acceptable field kinds
106
+ *
107
+ * @var array
108
+ */
109
+ private $field_kinds = array(
110
+ self::FIELD,
111
+ self::META,
112
+ self::DERIVED,
113
+ );
114
+ /**
115
+ * A custom function to call before serialization
116
+ *
117
+ * @var null|callable
118
+ */
119
+ private $serializer;
120
+ /**
121
+ * A custom function to call before deserialization
122
+ *
123
+ * @var null|callable
124
+ */
125
+ private $deserializer;
126
+ /**
127
+ * A custom function to use for sanitizing the field value before setting it.
128
+ * Used when receiving values from untrusted sources (e.g. a web form of a REST API request)
129
+ *
130
+ * @var null|callable
131
+ */
132
+ private $sanitizer;
133
+ /**
134
+ * A custom filtering callable triggered before setting the field with the value
135
+ *
136
+ * @var null|callable
137
+ */
138
+ private $before_set;
139
+ /**
140
+ * A custom filtering callable triggered before returning the field value
141
+ *
142
+ * @var null|callable
143
+ */
144
+ private $before_get;
145
+ /**
146
+ * Used by derived fields: The function to use to get the field value
147
+ *
148
+ * @var null|callable
149
+ */
150
+ private $reader;
151
+ /**
152
+ * Used by derived fields: The function to use to update the field value
153
+ *
154
+ * @var null|callable
155
+ */
156
+ private $updater;
157
+
158
+ /**
159
+ * Constructor.
160
+ *
161
+ * @param array $args The arguments.
162
+ * @throws WP_Job_Manager_REST_Exception When invalid name or kind provided.
163
+ */
164
+ public function __construct( $args ) {
165
+ if ( ! isset( $args['name'] ) || empty( $args['name'] ) || ! is_string( $args['name'] ) ) {
166
+ throw new WP_Job_Manager_REST_Exception( 'every field declaration should have a (non-empty) name string' );
167
+ }
168
+ if ( ! isset( $args['kind'] ) || ! in_array( $args['kind'], $this->field_kinds, true ) ) {
169
+ throw new WP_Job_Manager_REST_Exception( 'every field should have a kind (one of ' . implode( ',', $this->field_kinds ) . ')' );
170
+ }
171
+
172
+ $this->name = $args['name'];
173
+ $this->description = $this->value_or_default( $args, 'description', '' );
174
+
175
+ $this->kind = $args['kind'];
176
+ $this->type = $this->value_or_default( $args, 'type', WP_Job_Manager_REST_Type::any() );
177
+ $this->choices = $this->value_or_default( $args, 'choices', null );
178
+ $this->default_value = $this->value_or_default( $args, 'default_value' );
179
+
180
+ $this->map_from = $this->value_or_default( $args, 'map_from' );
181
+ $this->data_transfer_name = $this->value_or_default( $args, 'data_transfer_name', $this->get_name() );
182
+
183
+ $this->primary = $this->value_or_default( $args, 'primary', false );
184
+ $this->required = $this->value_or_default( $args, 'required', false );
185
+ $this->supported_outputs = $this->value_or_default( $args, 'supported_outputs', array( 'json' ) );
186
+
187
+ $this->sanitizer = $this->value_or_default( $args, 'sanitizer' );
188
+ $this->validations = $this->value_or_default( $args, 'validations', array() );
189
+
190
+ $this->serializer = $this->value_or_default( $args, 'serializer' );
191
+ $this->deserializer = $this->value_or_default( $args, 'deserializer' );
192
+
193
+ $this->before_get = $this->value_or_default( $args, 'before_get' );
194
+ $this->before_set = $this->value_or_default( $args, 'before_set' );
195
+
196
+ $this->reader = $this->value_or_default( $args, 'reader' );
197
+ $this->updater = $this->value_or_default( $args, 'updater' );
198
+ }
199
+
200
+ /**
201
+ * Get possible choices if set
202
+ *
203
+ * @return null|array
204
+ */
205
+ public function get_choices() {
206
+ return $this->choices;
207
+ }
208
+
209
+ /**
210
+ * Get Sanitizer
211
+ *
212
+ * @return callable|null
213
+ */
214
+ public function get_sanitizer() {
215
+ return $this->sanitizer;
216
+ }
217
+
218
+ /**
219
+ * Value or Default
220
+ *
221
+ * @param array $args Args.
222
+ * @param string $name Name.
223
+ * @param mixed $default Default.
224
+ * @return null
225
+ */
226
+ private function value_or_default( $args, $name, $default = null ) {
227
+ return isset( $args[ $name ] ) ? $args[ $name ] : $default;
228
+ }
229
+
230
+ /**
231
+ * Is Kind
232
+ *
233
+ * @param string $kind The kind.
234
+ * @return bool
235
+ */
236
+ public function is_kind( $kind ) {
237
+ if ( ! in_array( $kind, $this->field_kinds, true ) ) {
238
+ return false;
239
+ }
240
+ return $this->kind === $kind;
241
+ }
242
+
243
+ /**
244
+ * Get default value
245
+ *
246
+ * @return mixed
247
+ */
248
+ public function get_default_value() {
249
+ if ( isset( $this->default_value ) && ! empty( $this->default_value ) ) {
250
+ return ( is_array( $this->default_value ) && is_callable( $this->default_value ) ) ? call_user_func( $this->default_value ) : $this->default_value;
251
+ }
252
+
253
+ return $this->type->default_value();
254
+ }
255
+
256
+ /**
257
+ * Cast a value
258
+ *
259
+ * @param mixed $value Val.
260
+ * @return mixed
261
+ */
262
+ public function cast_value( $value ) {
263
+ return $this->type->cast( $value );
264
+ }
265
+
266
+ /**
267
+ * Supports this type of output.
268
+ *
269
+ * @param string $type Type.
270
+ * @return bool
271
+ */
272
+ public function supports_output_type( $type ) {
273
+ return in_array( $type, $this->supported_outputs, true );
274
+ }
275
+
276
+ /**
277
+ * As Item Schema Property
278
+ *
279
+ * @return array
280
+ */
281
+ public function as_item_schema_property() {
282
+ $schema = $this->type->schema();
283
+ $schema['context'] = array( 'view', 'edit' );
284
+ $schema['description'] = $this->get_description();
285
+
286
+ if ( $this->get_choices() ) {
287
+ $schema['enum'] = (array) $this->get_choices();
288
+ }
289
+ return $schema;
290
+ }
291
+
292
+ /**
293
+ * Get Map From
294
+ *
295
+ * @return null
296
+ */
297
+ public function get_map_from() {
298
+ if ( isset( $this->map_from ) && ! empty( $this->map_from ) ) {
299
+ return $this->map_from;
300
+ }
301
+
302
+ return $this->get_name();
303
+ }
304
+
305
+ /**
306
+ * Get Kind
307
+ *
308
+ * @return mixed
309
+ */
310
+ public function get_kind() {
311
+ return $this->kind;
312
+ }
313
+
314
+ /**
315
+ * Get Name
316
+ *
317
+ * @return mixed
318
+ */
319
+ public function get_name() {
320
+ return $this->name;
321
+ }
322
+
323
+ /**
324
+ * Is Primary
325
+ *
326
+ * @return bool
327
+ */
328
+ public function is_primary() {
329
+ return (bool) $this->primary;
330
+ }
331
+
332
+ /**
333
+ * Is Required
334
+ *
335
+ * @return bool
336
+ */
337
+ public function is_required() {
338
+ return (bool) $this->required;
339
+ }
340
+
341
+ /**
342
+ * Get Description
343
+ *
344
+ * @return string
345
+ */
346
+ public function get_description() {
347
+ if ( isset( $this->description ) && ! empty( $this->description ) ) {
348
+ return $this->description;
349
+ }
350
+ $name = ucfirst( str_replace( '_', ' ', $this->get_name() ) );
351
+ return $name;
352
+ }
353
+
354
+ /**
355
+ * Get Dto name
356
+ *
357
+ * @return string
358
+ */
359
+ public function get_data_transfer_name() {
360
+ return isset( $this->data_transfer_name ) ? $this->data_transfer_name : $this->get_name();
361
+ }
362
+
363
+ /**
364
+ * Get Validations
365
+ *
366
+ * @return array
367
+ */
368
+ public function get_validations() {
369
+ return $this->validations;
370
+ }
371
+
372
+ /**
373
+ * Get Before get
374
+ *
375
+ * @return callable|null
376
+ */
377
+ public function before_get() {
378
+ return $this->before_get;
379
+ }
380
+
381
+ /**
382
+ * Get Serializer
383
+ *
384
+ * @return callable|null
385
+ */
386
+ public function get_serializer() {
387
+ return $this->serializer;
388
+ }
389
+
390
+ /**
391
+ * Get Deserializer
392
+ *
393
+ * @return callable|null
394
+ */
395
+ public function get_deserializer() {
396
+ return $this->deserializer;
397
+ }
398
+
399
+ /**
400
+ * Get Type
401
+ *
402
+ * @return WP_Job_Manager_REST_Interfaces_Type
403
+ */
404
+ function get_type() {
405
+ return $this->type;
406
+ }
407
+
408
+ /**
409
+ * Before Set
410
+ *
411
+ * @return callable|null
412
+ */
413
+ public function before_set() {
414
+ return $this->before_set;
415
+ }
416
+
417
+ /**
418
+ * Get Reader
419
+ *
420
+ * @return callable|null
421
+ */
422
+ public function get_reader() {
423
+ return $this->reader;
424
+ }
425
+
426
+ /**
427
+ * Get Updater
428
+ *
429
+ * @return callable|null
430
+ */
431
+ public function get_updater() {
432
+ return $this->updater;
433
+ }
434
+ }
lib/wpjm_rest/field/declaration/class-wp-job-manager-rest-field-declaration-builder.php ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Field Declaration Builder
4
+ *
5
+ * @package WP_Job_Manager_REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ } // End if().
11
+
12
+ /**
13
+ * Class Mixtape_Model_Field_Declaration_Builder
14
+ * Builds a Mixtape_Model_Field_Declaration
15
+ */
16
+ class WP_Job_Manager_REST_Field_Declaration_Builder {
17
+
18
+ /**
19
+ * Constructor.
20
+ */
21
+ function __construct() {
22
+ $this->args = array(
23
+ 'name' => '',
24
+ 'kind' => WP_Job_Manager_REST_Field_Declaration::FIELD,
25
+ 'type' => WP_Job_Manager_REST_Type::any(),
26
+ 'required' => false,
27
+ 'map_from' => null,
28
+
29
+ 'sanitizer' => null,
30
+
31
+ 'serializer' => null,
32
+ 'deserializer' => null,
33
+
34
+ 'default_value' => null,
35
+ 'data_transfer_name' => null,
36
+ 'supported_outputs' => array( 'json' ),
37
+ 'description' => null,
38
+ 'validations' => array(),
39
+ 'choices' => null,
40
+ 'contexts' => array( 'view', 'edit' ),
41
+ 'before_set' => null,
42
+ 'before_get' => null,
43
+ 'reader' => null,
44
+ 'updater' => null,
45
+ );
46
+ }
47
+
48
+ /**
49
+ * Build it
50
+ *
51
+ * @return WP_Job_Manager_REST_Field_Declaration
52
+ */
53
+ public function build() {
54
+ return new WP_Job_Manager_REST_Field_Declaration( $this->args );
55
+ }
56
+
57
+ /**
58
+ * Default Value.
59
+ *
60
+ * @param mixed $default_value Default.
61
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
62
+ */
63
+ public function with_default( $default_value ) {
64
+ return $this->with( 'default_value', $default_value );
65
+ }
66
+
67
+ /**
68
+ * With Name
69
+ *
70
+ * @param string $name Name.
71
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
72
+ */
73
+ public function with_name( $name ) {
74
+ return $this->with( 'name', $name );
75
+ }
76
+
77
+ /**
78
+ * With Kind
79
+ *
80
+ * @param string $kind Kind.
81
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
82
+ */
83
+ public function with_kind( $kind ) {
84
+ return $this->with( 'kind', $kind );
85
+ }
86
+
87
+ /**
88
+ * With Map From
89
+ *
90
+ * @param string $mapped_from Mapped From.
91
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
92
+ */
93
+ public function with_map_from( $mapped_from ) {
94
+ return $this->with( 'map_from', $mapped_from );
95
+ }
96
+
97
+ /**
98
+ * With Sanitizer
99
+ *
100
+ * @param callable $sanitizer Sanitizer.
101
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
102
+ */
103
+ public function with_sanitizer( $sanitizer ) {
104
+ $this->expect_is_callable( $sanitizer, __METHOD__ );
105
+ return $this->with( 'sanitizer', $sanitizer );
106
+ }
107
+
108
+ /**
109
+ * With Serializer
110
+ *
111
+ * @param callable $serializer Serializer.
112
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
113
+ */
114
+ public function with_serializer( $serializer ) {
115
+ return $this->with( 'serializer', $serializer );
116
+ }
117
+
118
+ /**
119
+ * With Deserializer
120
+ *
121
+ * @param callable $deserializer Deserializer.
122
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
123
+ */
124
+ public function with_deserializer( $deserializer ) {
125
+ return $this->with( 'deserializer', $deserializer );
126
+ }
127
+
128
+ /**
129
+ * With Required
130
+ *
131
+ * @param bool $required Req.
132
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
133
+ */
134
+ public function with_required( $required = true ) {
135
+ return $this->with( 'required', $required );
136
+
137
+ }
138
+
139
+ /**
140
+ * With Supported Outputs
141
+ *
142
+ * @param array $supported_outputs Outputs.
143
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
144
+ */
145
+ public function with_supported_outputs( $supported_outputs = array() ) {
146
+ return $this->with( 'supported_outputs', (array) $supported_outputs );
147
+ }
148
+
149
+ /**
150
+ * Set the type definition of this field declaration
151
+ *
152
+ * @param WP_Job_Manager_REST_Interfaces_Type $value_type Type.
153
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder $this
154
+ *
155
+ * @throws WP_Job_Manager_REST_Exception When not a type.
156
+ */
157
+ public function with_type( $value_type ) {
158
+ if ( ! is_a( $value_type, 'WP_Job_Manager_REST_Interfaces_Type' ) ) {
159
+ throw new WP_Job_Manager_REST_Exception( get_class( $value_type ) . ' is not a Mixtape_Interfaces_Type' );
160
+ }
161
+ return $this->with( 'type', $value_type );
162
+ }
163
+
164
+ /**
165
+ * With Dto Name
166
+ *
167
+ * @param string $dto_name Dto Name.
168
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
169
+ */
170
+ public function with_dto_name( $dto_name ) {
171
+ return $this->with( 'data_transfer_name', $dto_name );
172
+ }
173
+
174
+ /**
175
+ * With Description
176
+ *
177
+ * @param string $description Description.
178
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
179
+ */
180
+ public function with_description( $description ) {
181
+ return $this->with( 'description', $description );
182
+ }
183
+
184
+ /**
185
+ * With Validations
186
+ *
187
+ * @param array|mixed $validations Validations.
188
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
189
+ */
190
+ public function with_validations( $validations ) {
191
+ if ( is_callable( $validations ) || ! is_array( $validations ) ) {
192
+ $validations = array( $validations );
193
+ }
194
+ return $this->with( 'validations', $validations );
195
+ }
196
+
197
+ /**
198
+ * Before Set
199
+ *
200
+ * @param callable $before_set Before set.
201
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
202
+ */
203
+ public function with_before_set( $before_set ) {
204
+ return $this->with( 'before_set', $before_set );
205
+ }
206
+
207
+ /**
208
+ * Before Get
209
+ *
210
+ * @param callable $before_get Before get.
211
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
212
+ */
213
+ public function with_before_get( $before_get ) {
214
+ return $this->with( 'before_get', $before_get );
215
+ }
216
+
217
+ /**
218
+ * Choices.
219
+ *
220
+ * @param array|mixed $choices Choices.
221
+ *
222
+ * @return $this|WP_Job_Manager_REST_Field_Declaration_Builder
223
+ */
224
+ public function with_choices( $choices ) {
225
+ if ( empty( $choices ) ) {
226
+ return $this;
227
+ }
228
+ return $this->with( 'choices', is_array( $choices ) ? $choices : array( $choices ) );
229
+ }
230
+
231
+ /**
232
+ * Set
233
+ *
234
+ * @param string $name Name.
235
+ * @param mixed $value Value.
236
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder $this
237
+ */
238
+ private function with( $name, $value ) {
239
+ $this->args[ $name ] = $value;
240
+ return $this;
241
+ }
242
+
243
+ /**
244
+ * Derived Field
245
+ *
246
+ * @param callable $func The func.
247
+ *
248
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
249
+ */
250
+ public function derived( $func = null ) {
251
+ if ( $func ) {
252
+ $this->with_map_from( $func );
253
+ }
254
+ return $this->with_kind( WP_Job_Manager_REST_Field_Declaration::DERIVED );
255
+ }
256
+
257
+ /**
258
+ * Set Updater
259
+ *
260
+ * @param callable $func Func.
261
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder $this
262
+ * @throws WP_Job_Manager_REST_Exception When no callable.
263
+ */
264
+ public function with_updater( $func ) {
265
+ return $this->with( 'updater', $func );
266
+ }
267
+
268
+ /**
269
+ * Set reader
270
+ *
271
+ * @param callable $func Func.
272
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder $this
273
+ * @throws WP_Job_Manager_REST_Exception When no callable.
274
+ */
275
+ public function with_reader( $func ) {
276
+ return $this->with( 'reader', $func );
277
+ }
278
+
279
+ /**
280
+ * Callable test
281
+ *
282
+ * @param callable|mixed $thing Thing to test.
283
+ * @param string $func The caller.
284
+ *
285
+ * @throws WP_Job_Manager_REST_Exception If not callable.
286
+ */
287
+ private function expect_is_callable( $thing, $func ) {
288
+ WP_Job_Manager_REST_Expect::that( is_callable( $thing ), $func . ' Expected a callable' );
289
+ }
290
+ }
lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-builder.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Build Stuff
4
+ *
5
+ * @package Mixtape
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Interface WP_Job_Manager_REST_Interfaces_Builder
14
+ */
15
+ interface WP_Job_Manager_REST_Interfaces_Builder {
16
+ /**
17
+ * Build something
18
+ *
19
+ * @return mixed
20
+ */
21
+ function build();
22
+ }
lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-classloader.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A Class Loader Interface.
4
+ *
5
+ * Injected into the Bootstrap. Handles all class loading.
6
+ *
7
+ * @package Mixtape
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Interface WP_Job_Manager_REST_Interfaces_Classloader
16
+ */
17
+ interface WP_Job_Manager_REST_Interfaces_Classloader {
18
+ /**
19
+ * Load a class
20
+ *
21
+ * @param string $name The class to load.
22
+ * @return WP_Job_Manager_REST_Interfaces_Classloader
23
+ */
24
+ function load_class( $name );
25
+ }
lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-controller.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Our controller Interface
4
+ *
5
+ * @package Mixtape/Controller
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Interface WP_Job_Manager_REST_Interfaces_Controller
14
+ */
15
+ interface WP_Job_Manager_REST_Interfaces_Controller {
16
+ /**
17
+ * Register This Controller
18
+ *
19
+ * @param WP_Job_Manager_REST_Controller_Bundle $bundle The bundle to register with.
20
+ * @param WP_Job_Manager_REST_Environment $environment The Environment to use.
21
+ * @throws WP_Job_Manager_REST_Exception Throws.
22
+ *
23
+ * @return bool|WP_Error true if valid otherwise error.
24
+ */
25
+ function register( $bundle, $environment );
26
+ }
lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-model.php ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Model
4
+ *
5
+ * This is the model.
6
+ *
7
+ * @package Mixtape/Model
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Interface Mixtape_Interfaces_Model
16
+ */
17
+ interface WP_Job_Manager_REST_Interfaces_Model {
18
+ /**
19
+ * Get this model's unique identifier
20
+ *
21
+ * @return mixed a unique identifier
22
+ */
23
+ function get_id();
24
+
25
+
26
+ /**
27
+ * Set this model's unique identifier
28
+ *
29
+ * @param mixed $new_id The new Id.
30
+ * @return WP_Job_Manager_REST_Interfaces_Model $model This model.
31
+ */
32
+ function set_id( $new_id );
33
+
34
+ /**
35
+ * Get a field for this model
36
+ *
37
+ * @param string $field_name The field name.
38
+ * @param array $args The args.
39
+ *
40
+ * @return mixed|null
41
+ */
42
+ function get( $field_name, $args = array() );
43
+
44
+ /**
45
+ * Set a field for this model
46
+ *
47
+ * @param string $field The field name.
48
+ * @param mixed $value The value.
49
+ *
50
+ * @return WP_Job_Manager_REST_Interfaces_Model $this;
51
+ */
52
+ function set( $field, $value );
53
+
54
+ /**
55
+ * Check if this model has a field
56
+ *
57
+ * @param string $field The field name.
58
+ *
59
+ * @return bool
60
+ */
61
+ function has( $field );
62
+
63
+ /**
64
+ * Validate this Model instance.
65
+ *
66
+ * @throws WP_Job_Manager_REST_Exception Throws.
67
+ *
68
+ * @return bool|WP_Error true if valid otherwise error.
69
+ */
70
+ function validate();
71
+
72
+ /**
73
+ * Sanitize this Model's field values
74
+ *
75
+ * @throws WP_Job_Manager_REST_Exception Throws.
76
+ *
77
+ * @return WP_Job_Manager_REST_Interfaces_Model
78
+ */
79
+ function sanitize();
80
+
81
+ /**
82
+ * Get this model class fields
83
+ *
84
+ * @param null|string $filter_by_type The field type.
85
+ * @return array
86
+ */
87
+ public static function get_fields( $filter_by_type = null );
88
+
89
+ /**
90
+ * Get this model's data store
91
+ *
92
+ * @return array
93
+ */
94
+ public static function get_data_store();
95
+
96
+ /**
97
+ * Set this model's data store
98
+ *
99
+ * @param WP_Job_Manager_REST_Interfaces_Data_Store $data_store A builder or a Data store.
100
+ * @throws WP_Job_Manager_REST_Exception Throws when Data Store Invalid.
101
+ */
102
+ public static function with_data_store( $data_store );
103
+
104
+ /**
105
+ * Get this model's data store
106
+ *
107
+ * @return array
108
+ */
109
+ public static function get_environment();
110
+
111
+ /**
112
+ * Set this model's environment
113
+ *
114
+ * @param WP_Job_Manager_REST_Environment $environment The Environment.
115
+ * @throws WP_Job_Manager_REST_Exception If an WP_Job_Manager_REST_Environment is not provided.
116
+ */
117
+ public static function with_environment( $environment );
118
+
119
+ /**
120
+ * Declare the fields of our Model.
121
+ *
122
+ * @return array list of WP_Job_Manager_REST_Field_Declaration
123
+ */
124
+ public static function declare_fields();
125
+
126
+ /**
127
+ * Prepare this for data transfer
128
+ *
129
+ * @return mixed
130
+ */
131
+ public function to_dto();
132
+
133
+ /**
134
+ * Update from array
135
+ *
136
+ * @param array $data The Data.
137
+ * @param bool $updating Is this an update.
138
+ *
139
+ * @return mixed
140
+ */
141
+ function update_from_array( $data, $updating = false );
142
+
143
+ /**
144
+ * Transform Model to raw data array
145
+ *
146
+ * @param null|string $field_type Type.
147
+ *
148
+ * @return array
149
+ */
150
+ function serialize( $field_type = null );
151
+ }
lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-registrable.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Something that can be registered with an environment
4
+ *
5
+ * @package Mixtape
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Interface WP_Job_Manager_REST_Interfaces_Registrable
14
+ */
15
+
16
+ interface WP_Job_Manager_REST_Interfaces_Registrable {
17
+ /**
18
+ * Register This with an environment
19
+ *
20
+ * @param WP_Job_Manager_REST_Environment $environment The Environment to use.
21
+ * @return void
22
+ */
23
+ function register( $environment );
24
+ }
lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-type.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Type
4
+ *
5
+ * @package Mixtape/Type
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Interface WP_Job_Manager_REST_Interfaces_Type
14
+ */
15
+ interface WP_Job_Manager_REST_Interfaces_Type {
16
+ /**
17
+ * Cast value to be Type
18
+ *
19
+ * @param mixed $value The value that needs casting.
20
+ *
21
+ * @return mixed
22
+ */
23
+ public function cast( $value );
24
+ /**
25
+ * The default value
26
+ *
27
+ * @return null
28
+ */
29
+ public function default_value();
30
+ /**
31
+ * The type's name
32
+ *
33
+ * @return string
34
+ */
35
+ public function name();
36
+ /**
37
+ * Sanitize this value
38
+ *
39
+ * @param mixed $value The value to sanitize.
40
+ *
41
+ * @return mixed
42
+ */
43
+ public function sanitize( $value );
44
+ /**
45
+ * Get this type's JSON Schema.
46
+ *
47
+ * @return array
48
+ */
49
+ public function schema();
50
+ }
lib/wpjm_rest/interfaces/controller/class-wp-job-manager-rest-interfaces-controller-bundle.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Controller Bundle
4
+ *
5
+ * A collection of WP_Job_Manager_REST_Rest_Api_Controller, sharing a common prefix.
6
+ *
7
+ * @package Mixtape/REST
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Interface WP_Job_Manager_REST_Interfaces_Rest_Api_Controller_Bundle
16
+ */
17
+ interface WP_Job_Manager_REST_Interfaces_Controller_Bundle extends WP_Job_Manager_REST_Interfaces_Registrable {
18
+
19
+ /**
20
+ * Get the Prefix
21
+ *
22
+ * @return string
23
+ */
24
+ public function get_prefix();
25
+ }
lib/wpjm_rest/interfaces/data/class-wp-job-manager-rest-interfaces-data-store.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Data Stores
4
+ *
5
+ * Provides a unified way for fetching and storing Models
6
+ *
7
+ * @package Mixtape
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ } // End if().
13
+
14
+ /**
15
+ * Interface WP_Job_Manager_REST_Interfaces_Data_Store
16
+ */
17
+ interface WP_Job_Manager_REST_Interfaces_Data_Store {
18
+
19
+ /**
20
+ * Get all the models (taking into account any filtering)
21
+ *
22
+ * @param WP_Job_Manager_REST_Interfaces_Model|null $filter A filter.
23
+ * @return WP_Job_Manager_REST_Model_Collection
24
+ */
25
+ public function get_entities( $filter = null );
26
+
27
+
28
+ /**
29
+ * Get a Model Using it's unique identifier
30
+ *
31
+ * @param int $id The id of the entity.
32
+ * @return WP_Job_Manager_REST_Interfaces_Model
33
+ */
34
+ public function get_entity( $id );
35
+
36
+ /**
37
+ * Delete a Model
38
+ *
39
+ * @param WP_Job_Manager_REST_Interfaces_Model $model The model to delete.
40
+ * @param array $args Args.
41
+ * @return mixed
42
+ */
43
+ public function delete( $model, $args = array() );
44
+
45
+ /**
46
+ * Update/Insert Model
47
+ *
48
+ * @param WP_Job_Manager_REST_Interfaces_Model $model The model.
49
+ * @return mixed
50
+ */
51
+ public function upsert( $model );
52
+ }
lib/wpjm_rest/interfaces/model/class-wp-job-manager-rest-interfaces-model-collection.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A Collection of Mixtape_Interfaces_Model
4
+ *
5
+ * @package Mixtape
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Interface WP_Job_Manager_REST_Interfaces_Model_Collection
14
+ */
15
+ interface WP_Job_Manager_REST_Interfaces_Model_Collection {
16
+ /**
17
+ * Get all the collection's Items
18
+ *
19
+ * @return Iterator
20
+ */
21
+ function get_items();
22
+ }
lib/wpjm_rest/interfaces/permissions/class-wp-job-manager-rest-interfaces-permissions-provider.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Handle Permissions for a REST Controller Action
4
+ *
5
+ * @package Mixtape/REST
6
+ */
7
+
8
+ /**
9
+ * Interface Mixtape_Interfaces_Rest_Api_Permissions_Provider
10
+ */
11
+ interface WP_Job_Manager_REST_Interfaces_Permissions_Provider {
12
+ /**
13
+ * Handle Permissions for a REST Controller Action
14
+ *
15
+ * @param WP_REST_Request $request The request.
16
+ * @param string $action The action (e.g. index, create update etc).
17
+ * @return bool
18
+ */
19
+ public static function permissions_check( $request, $action );
20
+ }
lib/wpjm_rest/model/class-wp-job-manager-rest-model-collection.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Model Collection Default implementation
4
+ *
5
+ * @package Mixtape/Model
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class Mixtape_Model_Collection
14
+ *
15
+ * Represents a collection of Mixtape_Interfaces_Model.
16
+ */
17
+ class WP_Job_Manager_REST_Model_Collection implements WP_Job_Manager_REST_Interfaces_Model_Collection {
18
+ /**
19
+ * The Models
20
+ *
21
+ * @var array the models Mixtape_Interfaces_Model
22
+ */
23
+ private $models;
24
+
25
+ /**
26
+ * Mixtape_Model_Collection constructor.
27
+ *
28
+ * @param array $models The models.
29
+ */
30
+ public function __construct( $models = array() ) {
31
+ $this->models = $models;
32
+ }
33
+
34
+ /**
35
+ * Get the contents of this collection.
36
+ *
37
+ * @return Iterator
38
+ */
39
+ public function get_items() {
40
+ return new ArrayIterator( $this->models );
41
+ }
42
+ }
lib/wpjm_rest/model/class-wp-job-manager-rest-model-factory.php ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Model Factory
4
+ *
5
+ * @package Mixtape/Model
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Model_Factory
14
+ */
15
+ class WP_Job_Manager_REST_Model_Factory {
16
+ /**
17
+ * The Environment
18
+ *
19
+ * @var WP_Job_Manager_REST_Environment
20
+ */
21
+ private $environment;
22
+ /**
23
+ * The Class Name
24
+ *
25
+ * @var string
26
+ */
27
+ private $class_name;
28
+ /**
29
+ * The Data Store
30
+ *
31
+ * @var WP_Job_Manager_REST_Interfaces_Data_Store
32
+ */
33
+ private $data_store;
34
+ /**
35
+ * Permissions Provider
36
+ *
37
+ * @var WP_Job_Manager_REST_Interfaces_Permissions_Provider
38
+ */
39
+ private $permissions_provider;
40
+
41
+ /**
42
+ * WP_Job_Manager_REST_Model_Factory constructor.
43
+ *
44
+ * @param WP_Job_Manager_REST_Environment $environment Environment.
45
+ * @param string $class_name Class Name.
46
+ * @param WP_Job_Manager_REST_Interfaces_Data_Store $data_store Data Store.
47
+ */
48
+ public function __construct( $environment, $class_name, $data_store ) {
49
+ $this->with_model( $class_name );
50
+ $this->with_environment( $environment );
51
+ $this->with_data_store( $data_store );
52
+ }
53
+
54
+ /**
55
+ * With Environment
56
+ *
57
+ * @param WP_Job_Manager_REST_Environment $environment Env.
58
+ *
59
+ * @return WP_Job_Manager_REST_Model_Factory $this
60
+ */
61
+ public function with_environment( $environment ) {
62
+ $this->environment = $environment;
63
+ $this->call_static_model_method( 'with_environment', array( $this->environment ) );
64
+ return $this;
65
+ }
66
+
67
+ /**
68
+ * With Model
69
+ *
70
+ * @param string $class_name Class Name.
71
+ *
72
+ * @return WP_Job_Manager_REST_Model_Factory $this
73
+ */
74
+ public function with_model( $class_name ) {
75
+ $this->class_name = $class_name;
76
+ return $this;
77
+ }
78
+
79
+ /**
80
+ * With Data Store
81
+ *
82
+ * @param WP_Job_Manager_REST_Interfaces_Data_Store $data_store Data Store.
83
+ *
84
+ * @return WP_Job_Manager_REST_Model_Factory $this
85
+ */
86
+ public function with_data_store( $data_store ) {
87
+ $this->data_store = $data_store;
88
+ $this->call_static_model_method( 'with_data_store', array( $this->data_store ) );
89
+ return $this;
90
+ }
91
+
92
+ /**
93
+ * Call a static method on the model
94
+ *
95
+ * @param string $method Method to call.
96
+ * @param array $args The args.
97
+ *
98
+ * @return mixed
99
+ */
100
+ private function call_static_model_method( $method, $args = array() ) {
101
+ return call_user_func_array( array( $this->class_name, $method ), $args );
102
+ }
103
+
104
+ /**
105
+ * Create a model
106
+ *
107
+ * @param array $props Data.
108
+ * @param array $args Args.
109
+ * @return WP_Job_Manager_REST_Interfaces_Model
110
+ */
111
+ public function create( $props = array(), $args = array() ) {
112
+ return $this->call_static_model_method( 'create', array( $props, $args ) );
113
+ }
114
+
115
+ /**
116
+ * New From Array
117
+ *
118
+ * @param array $data Data.
119
+ *
120
+ * @return WP_Job_Manager_REST_Interfaces_Model|WP_Error
121
+ */
122
+ public function new_from_array( $data ) {
123
+ return $this->call_static_model_method( 'new_from_array', array( $data ) );
124
+ }
125
+
126
+ /**
127
+ * Get Fields
128
+ *
129
+ * @return array
130
+ */
131
+ public function get_fields() {
132
+ return $this->call_static_model_method( 'get_fields' );
133
+ }
134
+
135
+ /**
136
+ * Get Data Store
137
+ *
138
+ * @return WP_Job_Manager_REST_Interfaces_Data_Store
139
+ */
140
+ public function get_data_store() {
141
+ return $this->data_store;
142
+ }
143
+
144
+ /**
145
+ * Get Name
146
+ *
147
+ * @return string
148
+ */
149
+ public function get_name() {
150
+ return strtolower( $this->class_name );
151
+ }
152
+
153
+ /**
154
+ * Permissions Check
155
+ *
156
+ * @param WP_REST_Request $request Request.
157
+ * @param string $action Action.
158
+ * @return mixed
159
+ */
160
+ public function permissions_check( $request, $action ) {
161
+ if ( ! empty( $this->permissions_provider ) ) {
162
+ return call_user_func_array( array( $this->permissions_provider, 'permissions_check' ), array( $request, $action ) );
163
+ }
164
+ return $this->call_static_model_method( 'permissions_check', array( $request, $action ) );
165
+ }
166
+
167
+ /**
168
+ * @param WP_Job_Manager_REST_Interfaces_Permissions_Provider $permissions_provider PP.
169
+ * @return $this
170
+ */
171
+ public function with_permissions_provider( $permissions_provider ) {
172
+ $this->permissions_provider = $permissions_provider;
173
+ return $this;
174
+ }
175
+ }
lib/wpjm_rest/model/class-wp-job-manager-rest-model-settings.php ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Settings Model
4
+ *
5
+ * @package WP_Job_Manager_REST/Model
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Model_Settings
14
+ * Represents a single setting set
15
+ */
16
+ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
17
+
18
+ /**
19
+ * Get Settings
20
+ *
21
+ * @throws WP_Job_Manager_REST_Exception Override this.
22
+ * @return array
23
+ */
24
+ public static function get_settings() {
25
+ WP_Job_Manager_REST_Expect::should_override( __METHOD__ );
26
+ return array();
27
+ }
28
+
29
+ /**
30
+ * Default for Attribute. Override to change this behavior
31
+ *
32
+ * @param array $field_data Data.
33
+ * @param string $attribute Attr.
34
+ * @return mixed
35
+ */
36
+ protected static function default_for_attribute( $field_data, $attribute ) {
37
+ return null;
38
+ }
39
+
40
+ /**
41
+ * On Field Setup
42
+ *
43
+ * @param string $field_name Name.
44
+ * @param WP_Job_Manager_REST_Field_Declaration_Builder $field_builder Builder.
45
+ * @param array $field_data Data.
46
+ * @param WP_Job_Manager_REST_Environment $env Env.
47
+ * @return void
48
+ */
49
+ protected static function on_field_setup( $field_name, $field_builder, $field_data, $env ) {
50
+ }
51
+
52
+ /**
53
+ * Declare Fields
54
+ *
55
+ * @return array
56
+ */
57
+ public static function declare_fields() {
58
+ $env = self::get_environment();
59
+ $settings_per_group = static::get_settings();
60
+ $fields = array();
61
+
62
+ foreach ( $settings_per_group as $group_name => $group_data ) {
63
+ $group_fields = $group_data[1];
64
+
65
+ foreach ( $group_fields as $field_data ) {
66
+ $field_builder = self::field_declaration_builder_from_data( $env, $field_data );
67
+ $fields[] = $field_builder;
68
+ }
69
+ }
70
+ return $fields;
71
+ }
72
+
73
+ /**
74
+ * Convert bool to bit
75
+ *
76
+ * @param mixed $value Val.
77
+ * @return string
78
+ */
79
+ static function bool_to_bit( $value ) {
80
+ return ( ! empty( $value ) && 'false' !== $value ) ? '1' : '';
81
+ }
82
+
83
+ /**
84
+ * Covert bit to bool
85
+ *
86
+ * @param mixed $value Val.
87
+ * @return bool
88
+ */
89
+ static function bit_to_bool( $value ) {
90
+ return ( ! empty( $value ) && '0' !== $value ) ? true : false;
91
+ }
92
+
93
+ /**
94
+ * Get ID
95
+ *
96
+ * @return string
97
+ */
98
+ function get_id() {
99
+ return strtolower( get_class( $this ) );
100
+ }
101
+
102
+ /**
103
+ * Set ID
104
+ *
105
+ * @param mixed $new_id New ID.
106
+ * @return WP_Job_Manager_REST_Interfaces_Model $this
107
+ */
108
+ function set_id( $new_id ) {
109
+ return $this;
110
+ }
111
+
112
+ /**
113
+ * Build declarations from array
114
+ *
115
+ * @param WP_Job_Manager_REST_Environment $env Environment.
116
+ * @param array $field_data Data.
117
+ * @return WP_Job_Manager_REST_Field_Declaration_Builder
118
+ */
119
+ private static function field_declaration_builder_from_data( $env, $field_data ) {
120
+ $field_name = $field_data['name'];
121
+ $field_builder = $env->field( $field_name );
122
+ $default_value = isset( $field_data['std'] ) ? $field_data['std'] : static::default_for_attribute( $field_data, 'std' );
123
+ $label = isset( $field_data['label'] ) ? $field_data['label'] : $field_name;
124
+ $description = isset( $field_data['desc'] ) ? $field_data['desc'] : $label;
125
+ $setting_type = isset( $field_data['type'] ) ? $field_data['type'] : null;
126
+ $choices = isset( $field_data['options'] ) ? array_keys( $field_data['options'] ) : null;
127
+ $field_type = 'string';
128
+
129
+ if ( 'checkbox' === $setting_type ) {
130
+ $field_type = 'boolean';
131
+ if ( $default_value ) {
132
+ // convert our default value as well.
133
+ $default_value = static::bit_to_bool( $default_value );
134
+ }
135
+ $field_builder
136
+ ->with_serializer( array( __CLASS__, 'bool_to_bit' ) )
137
+ ->with_deserializer( array( __CLASS__, 'bit_to_bool' ) );
138
+
139
+ } elseif ( 'select' === $setting_type ) {
140
+ $field_type = 'string';
141
+ } else {
142
+ // try to guess numeric fields, although this is not perfect.
143
+ if ( is_numeric( $default_value ) ) {
144
+ $field_type = is_float( $default_value ) ? 'float' : 'integer';
145
+ }
146
+ }
147
+
148
+ if ( $default_value ) {
149
+ $field_builder->with_default( $default_value );
150
+ }
151
+ $field_builder
152
+ ->with_description( $description )
153
+ ->with_dto_name( $field_name )
154
+ ->with_type( $env->type( $field_type ) );
155
+ if ( $choices ) {
156
+ $field_builder->with_choices( $choices );
157
+ }
158
+
159
+ static::on_field_setup( $field_name, $field_builder, $field_data, $env );
160
+
161
+ return $field_builder;
162
+ }
163
+ }
lib/wpjm_rest/permissions/class-wp-job-manager-rest-permissions-any.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Any Permission
4
+ *
5
+ * @package WP_Job_Manager_REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Permissions_Any
14
+ */
15
+ class WP_Job_Manager_REST_Permissions_Any implements WP_Job_Manager_REST_Interfaces_Permissions_Provider {
16
+
17
+ /**
18
+ * Handle Permissions for a REST Controller Action
19
+ *
20
+ * @param WP_REST_Request $request The request.
21
+ * @param string $action The action (e.g. index, create update etc).
22
+ * @return bool
23
+ */
24
+ public static function permissions_check( $request, $action ) {
25
+ return true;
26
+ }
27
+ }
lib/wpjm_rest/type/class-wp-job-manager-rest-type-array.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Array type
4
+ *
5
+ * @package Mixtape/Type
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Type_Array
14
+ */
15
+ class WP_Job_Manager_REST_Type_Array extends WP_Job_Manager_REST_Type {
16
+
17
+ /**
18
+ * WP_Job_Manager_REST_Type_Array constructor.
19
+ */
20
+ public function __construct() {
21
+ parent::__construct( 'array' );
22
+ }
23
+
24
+ /**
25
+ * Get default
26
+ *
27
+ * @return array
28
+ */
29
+ public function default_value() {
30
+ return array();
31
+ }
32
+
33
+ /**
34
+ * Cast to array
35
+ *
36
+ * @param mixed $value the value.
37
+ * @return array
38
+ */
39
+ public function cast( $value ) {
40
+ return (array) $value;
41
+ }
42
+ }
lib/wpjm_rest/type/class-wp-job-manager-rest-type-boolean.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Boolean Type
4
+ *
5
+ * @package Mixtape/Type
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Type_Boolean
14
+ */
15
+ class WP_Job_Manager_REST_Type_Boolean extends WP_Job_Manager_REST_Type {
16
+
17
+ /**
18
+ * WP_Job_Manager_REST_Type_Boolean constructor.
19
+ */
20
+ public function __construct() {
21
+ parent::__construct( 'boolean' );
22
+ }
23
+
24
+ /**
25
+ * Default
26
+ *
27
+ * @return bool
28
+ */
29
+ public function default_value() {
30
+ return false;
31
+ }
32
+
33
+ /**
34
+ * Cast
35
+ *
36
+ * @param mixed $value Value.
37
+ * @return bool
38
+ */
39
+ public function cast( $value ) {
40
+ if ( 'false' === $value ) {
41
+ return false;
42
+ }
43
+ return (bool) $value;
44
+ }
45
+ }
lib/wpjm_rest/type/class-wp-job-manager-rest-type-integer.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Number Type (a floating point type)
4
+ *
5
+ * @package WP_Job_Manager_REST/Types
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Type_Integer
14
+ */
15
+ class WP_Job_Manager_REST_Type_Integer extends WP_Job_Manager_REST_Type {
16
+
17
+ /**
18
+ * Is this unsigned?
19
+ *
20
+ * @var bool
21
+ */
22
+ private $unsigned;
23
+
24
+ /**
25
+ * WP_Job_Manager_REST_Type_Integer constructor.
26
+ *
27
+ * @param bool $unsigned Unsigned.
28
+ */
29
+ public function __construct( $unsigned = false ) {
30
+ $this->unsigned = $unsigned;
31
+ parent::__construct( 'integer' );
32
+ }
33
+
34
+ /**
35
+ * Default
36
+ *
37
+ * @return int
38
+ */
39
+ public function default_value() {
40
+ return 0;
41
+ }
42
+
43
+ /**
44
+ * Cast
45
+ *
46
+ * @param mixed $value Val.
47
+ * @return int
48
+ */
49
+ public function cast( $value ) {
50
+ if ( ! is_numeric( $value ) ) {
51
+ return $this->default_value();
52
+ }
53
+ return $this->unsigned ? absint( $value ) : intval( $value, 10 );
54
+ }
55
+
56
+ /**
57
+ * Sanitize
58
+ *
59
+ * @param mixed $value Val.
60
+ * @return int
61
+ */
62
+ function sanitize( $value ) {
63
+ return $this->cast( $value );
64
+ }
65
+ }
lib/wpjm_rest/type/class-wp-job-manager-rest-type-nullable.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Nullable Type (a type that can be null)
4
+ *
5
+ * @package WP_Job_Manager_REST/Types
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Type_Nullable
14
+ */
15
+ class WP_Job_Manager_REST_Type_Nullable extends WP_Job_Manager_REST_Type {
16
+ /**
17
+ * The type
18
+ *
19
+ * @var WP_Job_Manager_REST_Interfaces_Type
20
+ */
21
+ private $item_type_definition;
22
+
23
+ /**
24
+ * Construct
25
+ *
26
+ * @param WP_Job_Manager_REST_Interfaces_Type $item_type_definition Def.
27
+ */
28
+ function __construct( $item_type_definition ) {
29
+ parent::__construct( 'nullable:' . $item_type_definition->name() );
30
+ $this->item_type_definition = $item_type_definition;
31
+ }
32
+
33
+ /**
34
+ * Default value as always null.
35
+ *
36
+ * @return null
37
+ */
38
+ public function default_value() {
39
+ return null;
40
+ }
41
+
42
+ /**
43
+ * Cast
44
+ *
45
+ * @param mixed $value Value.
46
+ * @return mixed|null
47
+ */
48
+ public function cast( $value ) {
49
+ if ( null === $value ) {
50
+ return null;
51
+ }
52
+ return $this->item_type_definition->cast( $value );
53
+ }
54
+
55
+ /**
56
+ * Sanitize.
57
+ *
58
+ * @param mixed $value Value.
59
+ * @return mixed|null
60
+ */
61
+ public function sanitize( $value ) {
62
+ if ( null === $value ) {
63
+ return null;
64
+ }
65
+ return $this->item_type_definition->sanitize( $value );
66
+ }
67
+
68
+ /**
69
+ * Schema
70
+ */
71
+ function schema() {
72
+ $schema = parent::schema();
73
+ $schema['type'] = array_unique( array_merge( $schema['type'], array( 'null' ) ) );
74
+ }
75
+ }
lib/wpjm_rest/type/class-wp-job-manager-rest-type-number.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Number Type (a floating point type)
4
+ *
5
+ * @package WP_Job_Manager_REST/Types
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Type_Number
14
+ */
15
+ class WP_Job_Manager_REST_Type_Number extends WP_Job_Manager_REST_Type {
16
+
17
+ /**
18
+ * WP_Job_Manager_REST_Type_Number constructor.
19
+ */
20
+ function __construct() {
21
+ parent::__construct( 'number' );
22
+ }
23
+
24
+ /**
25
+ * The default value
26
+ *
27
+ * @return float
28
+ */
29
+ function default_value() {
30
+ return 0.0;
31
+ }
32
+
33
+ /**
34
+ * Cast
35
+ *
36
+ * @param mixed $value The thing to cast.
37
+ * @return float
38
+ */
39
+ function cast( $value ) {
40
+ if ( ! is_numeric( $value ) ) {
41
+ return $this->default_value();
42
+ }
43
+ return floatval( $value );
44
+ }
45
+
46
+ /**
47
+ * Sanitize
48
+ *
49
+ * @param mixed $value The value to sanitize.
50
+ * @return float
51
+ */
52
+ function sanitize( $value ) {
53
+ return $this->cast( $value );
54
+ }
55
+ }
lib/wpjm_rest/type/class-wp-job-manager-rest-type-registry.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Type Registry
4
+ *
5
+ * @package WP_Job_Manager_REST/Type
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Type_Registry
14
+ */
15
+ class WP_Job_Manager_REST_Type_Registry {
16
+ /**
17
+ * Container Types (types that contain other types)
18
+ *
19
+ * @var array
20
+ */
21
+ private $container_types = array(
22
+ 'array',
23
+ 'nullable',
24
+ );
25
+
26
+ /**
27
+ * Our registered types
28
+ *
29
+ * @var null|array
30
+ */
31
+ private $types = null;
32
+
33
+ /**
34
+ * Define a new type
35
+ *
36
+ * @param string $identifier The Identifier.
37
+ * @param WP_Job_Manager_REST_Interfaces_Type $instance The type instance.
38
+ *
39
+ * @return WP_Job_Manager_REST_Type_Registry $this
40
+ *
41
+ * @throws WP_Job_Manager_REST_Exception When $instance not a WP_Job_Manager_REST_Interfaces_Type.
42
+ */
43
+ public function define( $identifier, $instance ) {
44
+ WP_Job_Manager_REST_Expect::is_a( $instance, 'WP_Job_Manager_REST_Interfaces_Type' );
45
+ $this->types[ $identifier ] = $instance;
46
+ return $this;
47
+ }
48
+
49
+ /**
50
+ * Get a type definition
51
+ *
52
+ * @param string $type The type name.
53
+ * @return WP_Job_Manager_REST_Interfaces_Type
54
+ *
55
+ * @throws WP_Job_Manager_REST_Exception In case of type name not confirming to syntax.
56
+ */
57
+ function definition( $type ) {
58
+ $types = $this->get_types();
59
+
60
+ if ( ! isset( $types[ $type ] ) ) {
61
+ // maybe lazy-register missing compound type.
62
+ $parts = explode( ':', $type );
63
+ if ( count( $parts ) > 1 ) {
64
+
65
+ $container_type = $parts[0];
66
+ if ( ! in_array( $container_type, $this->container_types, true ) ) {
67
+ throw new WP_Job_Manager_REST_Exception( $container_type . ' is not a known container type' );
68
+ }
69
+
70
+ $item_type = $parts[1];
71
+ if ( empty( $item_type ) ) {
72
+ throw new WP_Job_Manager_REST_Exception( $type . ': invalid syntax' );
73
+ }
74
+ $item_type_definition = $this->definition( $item_type );
75
+
76
+ if ( 'array' === $container_type ) {
77
+ $this->define( $type, new WP_Job_Manager_REST_Type_TypedArray( $item_type_definition ) );
78
+ $types = $this->get_types();
79
+ }
80
+
81
+ if ( 'nullable' === $container_type ) {
82
+ $this->define( $type, new WP_Job_Manager_REST_Type_Nullable( $item_type_definition ) );
83
+ $types = $this->get_types();
84
+ }
85
+ }
86
+ }
87
+
88
+ if ( ! isset( $types[ $type ] ) ) {
89
+ throw new WP_Job_Manager_REST_Exception();
90
+ }
91
+ return $types[ $type ];
92
+ }
93
+
94
+ /**
95
+ * Get Types
96
+ *
97
+ * @return array
98
+ */
99
+ private function get_types() {
100
+ return (array) apply_filters( 'mixtape_type_registry_get_types', $this->types, $this );
101
+ }
102
+
103
+ /**
104
+ * Initialize the type registry
105
+ *
106
+ * @param WP_Job_Manager_REST_Environment $environment The Environment.
107
+ */
108
+ public function initialize( $environment ) {
109
+ if ( null !== $this->types ) {
110
+ return;
111
+ }
112
+
113
+ $this->types = apply_filters( 'mixtape_type_registry_register_types', array(
114
+ 'any' => new WP_Job_Manager_REST_Type( 'any' ),
115
+ 'string' => new WP_Job_Manager_REST_Type_String(),
116
+ 'integer' => new WP_Job_Manager_REST_Type_Integer(),
117
+ 'int' => new WP_Job_Manager_REST_Type_Integer(),
118
+ 'uint' => new WP_Job_Manager_REST_Type_Integer( true ),
119
+ 'number' => new WP_Job_Manager_REST_Type_Number(),
120
+ 'float' => new WP_Job_Manager_REST_Type_Number(),
121
+ 'boolean' => new WP_Job_Manager_REST_Type_Boolean(),
122
+ 'array' => new WP_Job_Manager_REST_Type_Array(),
123
+ ), $this, $environment );
124
+ }
125
+ }
lib/wpjm_rest/type/class-wp-job-manager-rest-type-string.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * String type
4
+ *
5
+ * @package Mixtape/Type
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Type_String
14
+ */
15
+ class WP_Job_Manager_REST_Type_String extends WP_Job_Manager_REST_Type {
16
+ /**
17
+ * WP_Job_Manager_REST_Type_String constructor.
18
+ */
19
+ function __construct() {
20
+ parent::__construct( 'string' );
21
+ }
22
+
23
+ /**
24
+ * Sanitize.
25
+ *
26
+ * @param mixed $value Val.
27
+ * @return string
28
+ */
29
+ function sanitize( $value ) {
30
+ return sanitize_text_field( $value );
31
+ }
32
+
33
+ /**
34
+ * Default
35
+ *
36
+ * @return string
37
+ */
38
+ function default_value() {
39
+ return '';
40
+ }
41
+
42
+ /**
43
+ * Cast
44
+ *
45
+ * @param mixed $value Val.
46
+ * @return string
47
+ */
48
+ function cast( $value ) {
49
+ if ( is_array( $value ) ) {
50
+ $cast_ones = array();
51
+ foreach ( $value as $v ) {
52
+ $cast_ones[] = $this->cast( $v );
53
+ }
54
+ return '(' . implode( ',', $cast_ones ) . ')';
55
+ }
56
+ return (string) $value;
57
+ }
58
+ }
lib/wpjm_rest/type/class-wp-job-manager-rest-type-typedarray.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Typed Array
4
+ *
5
+ * A container types
6
+ *
7
+ * @package Mixtape/Type
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Class WP_Job_Manager_REST_Type_TypedArray
16
+ */
17
+ class WP_Job_Manager_REST_Type_TypedArray extends WP_Job_Manager_REST_Type {
18
+
19
+ /**
20
+ * The type this array contains
21
+ *
22
+ * @var WP_Job_Manager_REST_Interfaces_Type
23
+ */
24
+ private $item_type_definition;
25
+
26
+ /**
27
+ * Mixtape_TypeDefinition_TypedArray constructor.
28
+ *
29
+ * @param WP_Job_Manager_REST_Interfaces_Type $item_type_definition The type.
30
+ */
31
+ function __construct( $item_type_definition ) {
32
+ parent::__construct( 'array:' . $item_type_definition->name() );
33
+ $this->item_type_definition = $item_type_definition;
34
+ }
35
+
36
+ /**
37
+ * Get the default value
38
+ *
39
+ * @return array
40
+ */
41
+ public function default_value() {
42
+ return array();
43
+ }
44
+
45
+ /**
46
+ * Cast the value to be a typed array
47
+ *
48
+ * @param mixed $value an array of mixed.
49
+ * @return array
50
+ */
51
+ public function cast( $value ) {
52
+ $new_value = array();
53
+
54
+ foreach ( $value as $v ) {
55
+ $new_value[] = $this->item_type_definition->cast( $v );
56
+ }
57
+ return (array) $new_value;
58
+ }
59
+
60
+ /**
61
+ * Get this type's JSON Schema
62
+ *
63
+ * @return array
64
+ */
65
+ function schema() {
66
+ $schema = parent::schema();
67
+ $schema['type'] = 'array';
68
+ $schema['items'] = $this->item_type_definition->schema();
69
+ return $schema;
70
+ }
71
+ }
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: mikejolley, automattic, adamkheckler, annezazu, cena, chaselivings
3
  Tags: job manager, job listing, job board, job management, job lists, job list, job, jobs, company, hiring, employment, employer, employees, candidate, freelance, internship, job listings, positions, board, application, hiring, listing, manager, recruiting, recruitment, talent
4
  Requires at least: 4.3.1
5
  Tested up to: 4.8
6
- Stable tag: 1.27.0
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -141,6 +141,21 @@ You can view (and contribute) translations via the [translate.wordpress.org](htt
141
 
142
  == Changelog ==
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  = 1.27.0 =
145
  * Enhancement: Admins can now allow users to specify an account password when posting their first job listing. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1063)
146
  * Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1024)
3
  Tags: job manager, job listing, job board, job management, job lists, job list, job, jobs, company, hiring, employment, employer, employees, candidate, freelance, internship, job listings, positions, board, application, hiring, listing, manager, recruiting, recruitment, talent
4
  Requires at least: 4.3.1
5
  Tested up to: 4.8
6
+ Stable tag: 1.28.0
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
141
 
142
  == Changelog ==
143
 
144
+ = 1.28.0 =
145
+ * Enhancement: Improves support for Google Job Search by adding `JobListing` structured data. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1115)
146
+ * Enhancement: Adds ability for job types to be mapped to an employment type as defined for Google Job Search. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1112)
147
+ * Enhancement: Requests search engines no longer index expired and filled job listings. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1120)
148
+ * Enhancement: Improves support with third-party sitemap generation in Jetpack, Yoast SEO, and All in One SEO. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1119)
149
+ * Enhancement: Updated descriptions and help text on settings page. (@donnapep; Props to @michelleweber for updated copy; https://github.com/Automattic/WP-Job-Manager/pull/1107)
150
+ * Enhancement: Lower cache expiration times across plugin and limit use of autoloaded cache transients. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1101/files)
151
+ * Fix: Localization issue with WPML in the [jobs] shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1129)
152
+ * Fix: Show job listings' published date in localized format. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1118)
153
+ * Fix: Job submission form allows users to select multiple job types when they go back a step. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1099)
154
+ * Fix: Some themes that overloaded functions would break in previous release. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1104)
155
+ * Dev: Adds versions to template files so it is easier to tell when they are updated. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1116)
156
+ * Dev: Adds a new `wpjm_notify_new_user` action that allows you to override default behavior. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1125)
157
+ * Dev: Early version of REST API is bundled but disabled by default. Requires PHP 5.3+ and `WPJM_REST_API_ENABLED` constant must be set to true. Do not use in production; endpoints may change. (@pkg)
158
+
159
  = 1.27.0 =
160
  * Enhancement: Admins can now allow users to specify an account password when posting their first job listing. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1063)
161
  * Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1024)
scripts/build_mixtape.sh ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+
3
+ set -e;
4
+
5
+ SCRIPT_ROOT=`pwd`;
6
+ MIXTAPE_TEMP_PATH="$SCRIPT_ROOT/tmp/mt";
7
+ MIXTAPE_REPO="https://github.com/Automattic/mixtape/";
8
+ MIXTAPEFILE_NAME=".mixtapefile";
9
+ MIXTAPE_PATH="${MIXTAPE_PATH-$MIXTAPE_TEMP_PATH}";
10
+
11
+ # Declare all our reusable functions
12
+
13
+ show_usage() {
14
+ echo "Builds mixtape for development and plugin deployment";
15
+ echo "Note: Requires git";
16
+ echo "";
17
+ echo " ./scripts/build_mixtape.sh";
18
+ echo "";
19
+ echo "Assumes $MIXTAPEFILE_NAME is present at project root, generates a stub otherwise";
20
+ };
21
+
22
+ expect_directory() {
23
+ if [ ! -d "$1" ]; then
24
+ echo "Not a directory: $1. Exiting" >&2;
25
+ exit 1;
26
+ fi
27
+ };
28
+
29
+ # Check we have git
30
+ command -v git >/dev/null 2>&1 || {
31
+ echo "No Git found. Exiting." >&2;
32
+ show_usage;
33
+ exit 1;
34
+ };
35
+
36
+ if [ "$MIXTAPE_PATH" == "$MIXTAPE_TEMP_PATH" ]; then
37
+ if [ ! -d "$MIXTAPE_PATH" ]; then
38
+ mkdir -p "$MIXTAPE_PATH";
39
+ git clone "$MIXTAPE_REPO" "$MIXTAPE_PATH" || {
40
+ echo "Error cloning mixtape repo: $MIXTAPE_REPO" >&2;
41
+ exit 1;
42
+ }
43
+ cd "$MIXTAPE_PATH" && git checkout master >/dev/null 2>&1;
44
+ if [ "$?" -ne 0 ]; then
45
+ echo "Can't run git checkout command on $MIXTAPE_PATH" >&2;
46
+ exit 1;
47
+ fi
48
+ fi
49
+ cd "$MIXTAPE_PATH" && git fetch 2>&1;
50
+ fi
51
+
52
+ cd "$SCRIPT_ROOT";
53
+
54
+ expect_directory "$MIXTAPE_PATH";
55
+
56
+ if [ ! -f "$MIXTAPEFILE_NAME" ]; then
57
+ echo "No $MIXTAPEFILE_NAME found. Generating one (using sha from Mixtape HEAD)";
58
+
59
+ echo "sha=$(cd $MIXTAPE_PATH && git rev-parse HEAD)" >> "$MIXTAPEFILE_NAME";
60
+ echo "prefix=YOUR_PREFIX" >> "$MIXTAPEFILE_NAME";
61
+ echo "destination=your/destination" >> "$MIXTAPEFILE_NAME";
62
+
63
+ echo "$MIXTAPEFILE_NAME Generated:";
64
+ echo "";
65
+ cat "$MIXTAPEFILE_NAME";
66
+ echo "Amend it with your prefix, sha and destination and rerun this.";
67
+ exit;
68
+ fi
69
+
70
+ cd "$SCRIPT_ROOT";
71
+
72
+ mt_current_sha="$(cat "$MIXTAPEFILE_NAME" | grep -o 'sha=[^"]*' | sed 's/sha=//')";
73
+ mt_current_prefix="$(cat "$MIXTAPEFILE_NAME" | grep -o 'prefix=[^"]*' | sed 's/prefix=//')";
74
+ mt_current_destination="$(pwd)/$(cat "$MIXTAPEFILE_NAME" | grep -o 'destination=[^"]*' | sed 's/destination=//')";
75
+
76
+ echo "============= Building Mixtape =============";
77
+ echo "";
78
+ echo "SHA = $mt_current_sha";
79
+ echo "PREFIX = $mt_current_prefix";
80
+ echo "DESTINATION = $mt_current_destination";
81
+ echo "";
82
+
83
+ if [ ! -d "$mt_current_destination" ]; then
84
+ mkdir -p "$mt_current_destination"
85
+ fi
86
+
87
+ expect_directory "$mt_current_destination";
88
+
89
+ cd $MIXTAPE_PATH;
90
+ mt_repo_current_sha="$(git rev-parse HEAD)";
91
+
92
+ if [ "$mt_repo_current_sha" != "$mt_current_sha" ]; then
93
+ echo "Dir";
94
+ git checkout "$mt_current_sha" 2>&1;
95
+ if [ $? -ne 0 ]; then
96
+ echo "Git checkout error" >&2;
97
+ exit 1;
98
+ fi
99
+ fi
100
+
101
+ git diff-index --quiet --cached HEAD >/dev/null 2>&1;
102
+
103
+ if [ $? -ne 0 ]; then
104
+ echo "Repository (at $MIXTAPE_PATH) is dirty. Please commit or stash the changes. Exiting." >&2;
105
+ exit 1;
106
+ fi
107
+
108
+ echo "Running project script from $MIXTAPE_PATH"
109
+ sh "$MIXTAPE_PATH/scripts/new_project.sh" "$mt_current_prefix" "$mt_current_destination";
110
+
111
+ if [ $? -ne 0 ]; then
112
+ echo "Something went wrong with the file generation, Exiting" >&2;
113
+ git checkout "$mt_repo_current_sha" >/dev/null 2>&1;
114
+ exit 1;
115
+ else
116
+ echo "Generation done!";
117
+ git checkout "$mt_repo_current_sha" >/dev/null 2>&1;
118
+ fi
templates/account-signin.php CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php if ( is_user_logged_in() ) : ?>
2
 
3
  <fieldset>
1
+ <?php
2
+ /**
3
+ * In job listing creation flow, this template shows above the job creation form.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/account-signin.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.27.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <?php if ( is_user_logged_in() ) : ?>
19
 
20
  <fieldset>
templates/content-job_listing.php CHANGED
@@ -2,16 +2,22 @@
2
  /**
3
  * Job listing in the loop.
4
  *
5
- * @since 1.0.0
6
- * @version 1.27.0
7
  *
8
- * @package WP Job Manager
9
- * @category Template
10
- * @author Automattic
 
 
 
11
  */
12
 
13
- global $post; ?>
 
 
14
 
 
 
15
  <li <?php job_listing_class(); ?> data-longitude="<?php echo esc_attr( $post->geolocation_lat ); ?>" data-latitude="<?php echo esc_attr( $post->geolocation_long ); ?>">
16
  <a href="<?php the_job_permalink(); ?>">
17
  <?php the_company_logo(); ?>
@@ -31,7 +37,7 @@ global $post; ?>
31
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
32
  <?php $types = wpjm_get_the_job_types(); ?>
33
  <?php if ( ! empty( $types ) ) : foreach ( $types as $type ) : ?>
34
- <li class="job-type <?php echo esc_attr( sanitize_title( $type->slug ) ); ?>" itemprop="employmentType"><?php echo esc_html( $type->name ); ?></li>
35
  <?php endforeach; endif; ?>
36
  <?php } ?>
37
 
2
  /**
3
  * Job listing in the loop.
4
  *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/content-job_listing.php.
 
6
  *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @since 1.0.0
12
+ * @version 1.27.0
13
  */
14
 
15
+ if ( ! defined( 'ABSPATH' ) ) {
16
+ exit; // Exit if accessed directly
17
+ }
18
 
19
+ global $post;
20
+ ?>
21
  <li <?php job_listing_class(); ?> data-longitude="<?php echo esc_attr( $post->geolocation_lat ); ?>" data-latitude="<?php echo esc_attr( $post->geolocation_long ); ?>">
22
  <a href="<?php the_job_permalink(); ?>">
23
  <?php the_company_logo(); ?>
37
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
38
  <?php $types = wpjm_get_the_job_types(); ?>
39
  <?php if ( ! empty( $types ) ) : foreach ( $types as $type ) : ?>
40
+ <li class="job-type <?php echo esc_attr( sanitize_title( $type->slug ) ); ?>"><?php echo esc_html( $type->name ); ?></li>
41
  <?php endforeach; endif; ?>
42
  <?php } ?>
43
 
templates/content-no-jobs-found.php CHANGED
@@ -1,3 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php if ( defined( 'DOING_AJAX' ) ) : ?>
2
  <li class="no_job_listings_found"><?php _e( 'There are no listings matching your search.', 'wp-job-manager' ); ?></li>
3
  <?php else : ?>
1
+ <?php
2
+ /**
3
+ * Notice when no jobs were found in `[jobs]` shortcode.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/content-no-jobs-found.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @since 1.0.0
12
+ * @version 1.20.0
13
+ */
14
+
15
+ if ( ! defined( 'ABSPATH' ) ) {
16
+ exit; // Exit if accessed directly
17
+ }
18
+ ?>
19
  <?php if ( defined( 'DOING_AJAX' ) ) : ?>
20
  <li class="no_job_listings_found"><?php _e( 'There are no listings matching your search.', 'wp-job-manager' ); ?></li>
21
  <?php else : ?>
templates/content-single-job_listing-company.php CHANGED
@@ -4,22 +4,33 @@
4
  *
5
  * Hooked into single_job_listing_start priority 30
6
  *
7
- * @since 1.14.0
 
 
 
 
 
 
 
8
  */
9
 
 
 
 
 
10
  if ( ! get_the_company_name() ) {
11
  return;
12
  }
13
  ?>
14
- <div class="company" itemscope itemtype="http://data-vocabulary.org/Organization">
15
  <?php the_company_logo(); ?>
16
 
17
  <p class="name">
18
  <?php if ( $website = get_the_company_website() ) : ?>
19
- <a class="website" href="<?php echo esc_url( $website ); ?>" itemprop="url" target="_blank" rel="nofollow"><?php _e( 'Website', 'wp-job-manager' ); ?></a>
20
  <?php endif; ?>
21
  <?php the_company_twitter(); ?>
22
- <?php the_company_name( '<strong itemprop="name">', '</strong>' ); ?>
23
  </p>
24
  <?php the_company_tagline( '<p class="tagline">', '</p>' ); ?>
25
  <?php the_company_video(); ?>
4
  *
5
  * Hooked into single_job_listing_start priority 30
6
  *
7
+ * This template can be overridden by copying it to yourtheme/job_manager/content-single-job_listing-company.php.
8
+ *
9
+ * @see https://wpjobmanager.com/document/template-overrides/
10
+ * @author Automattic
11
+ * @package WP Job Manager
12
+ * @category Template
13
+ * @since 1.14.0
14
+ * @version 1.28.0
15
  */
16
 
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit; // Exit if accessed directly
19
+ }
20
+
21
  if ( ! get_the_company_name() ) {
22
  return;
23
  }
24
  ?>
25
+ <div class="company">
26
  <?php the_company_logo(); ?>
27
 
28
  <p class="name">
29
  <?php if ( $website = get_the_company_website() ) : ?>
30
+ <a class="website" href="<?php echo esc_url( $website ); ?>" target="_blank" rel="nofollow"><?php _e( 'Website', 'wp-job-manager' ); ?></a>
31
  <?php endif; ?>
32
  <?php the_company_twitter(); ?>
33
+ <?php the_company_name( '<strong>', '</strong>' ); ?>
34
  </p>
35
  <?php the_company_tagline( '<p class="tagline">', '</p>' ); ?>
36
  <?php the_company_video(); ?>
templates/content-single-job_listing-meta.php CHANGED
@@ -1,17 +1,23 @@
1
  <?php
2
  /**
3
- * Single view Job meta box
4
  *
5
  * Hooked into single_job_listing_start priority 20
6
  *
7
- * @since 1.14.0
8
- * @version 1.27.0
9
  *
10
- * @package WP Job Manager
11
- * @category Template
12
- * @author Automattic
 
 
 
13
  */
14
 
 
 
 
 
15
  global $post;
16
 
17
  do_action( 'single_job_listing_meta_before' ); ?>
@@ -23,14 +29,14 @@ do_action( 'single_job_listing_meta_before' ); ?>
23
  <?php $types = wpjm_get_the_job_types(); ?>
24
  <?php if ( ! empty( $types ) ) : foreach ( $types as $type ) : ?>
25
 
26
- <li class="job-type <?php echo esc_attr( sanitize_title( $type->slug ) ); ?>" itemprop="employmentType"><?php echo esc_html( $type->name ); ?></li>
27
 
28
  <?php endforeach; endif; ?>
29
  <?php } ?>
30
 
31
- <li class="location" itemprop="jobLocation"><?php the_job_location(); ?></li>
32
 
33
- <li class="date-posted" itemprop="datePosted"><?php the_job_publish_date(); ?></li>
34
 
35
  <?php if ( is_position_filled() ) : ?>
36
  <li class="position-filled"><?php _e( 'This position has been filled', 'wp-job-manager' ); ?></li>
1
  <?php
2
  /**
3
+ * Single view job meta box.
4
  *
5
  * Hooked into single_job_listing_start priority 20
6
  *
7
+ * This template can be overridden by copying it to yourtheme/job_manager/content-single-job_listing-meta.php.
 
8
  *
9
+ * @see https://wpjobmanager.com/document/template-overrides/
10
+ * @author Automattic
11
+ * @package WP Job Manager
12
+ * @category Template
13
+ * @since 1.14.0
14
+ * @version 1.28.0
15
  */
16
 
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit; // Exit if accessed directly
19
+ }
20
+
21
  global $post;
22
 
23
  do_action( 'single_job_listing_meta_before' ); ?>
29
  <?php $types = wpjm_get_the_job_types(); ?>
30
  <?php if ( ! empty( $types ) ) : foreach ( $types as $type ) : ?>
31
 
32
+ <li class="job-type <?php echo esc_attr( sanitize_title( $type->slug ) ); ?>"><?php echo esc_html( $type->name ); ?></li>
33
 
34
  <?php endforeach; endif; ?>
35
  <?php } ?>
36
 
37
+ <li class="location"><?php the_job_location(); ?></li>
38
 
39
+ <li class="date-posted"><?php the_job_publish_date(); ?></li>
40
 
41
  <?php if ( is_position_filled() ) : ?>
42
  <li class="position-filled"><?php _e( 'This position has been filled', 'wp-job-manager' ); ?></li>
templates/content-single-job_listing.php CHANGED
@@ -1,7 +1,24 @@
1
- <?php global $post; ?>
2
- <div class="single_job_listing" itemscope itemtype="http://schema.org/JobPosting">
3
- <meta itemprop="title" content="<?php echo esc_attr( wpjm_get_the_job_title( $post ) ); ?>" />
 
 
 
 
 
 
 
 
 
 
4
 
 
 
 
 
 
 
 
5
  <?php if ( get_option( 'job_manager_hide_expired_content', 1 ) && 'expired' === $post->post_status ) : ?>
6
  <div class="job-manager-info"><?php _e( 'This listing has expired.', 'wp-job-manager' ); ?></div>
7
  <?php else : ?>
@@ -15,8 +32,8 @@
15
  do_action( 'single_job_listing_start' );
16
  ?>
17
 
18
- <div class="job_description" itemprop="description">
19
- <?php echo apply_filters( 'the_job_description', get_the_content() ); ?>
20
  </div>
21
 
22
  <?php if ( candidates_can_apply() ) : ?>
1
+ <?php
2
+ /**
3
+ * Single job listing.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/content-single-job_listing.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @since 1.0.0
12
+ * @version 1.28.0
13
+ */
14
 
15
+ if ( ! defined( 'ABSPATH' ) ) {
16
+ exit; // Exit if accessed directly
17
+ }
18
+
19
+ global $post;
20
+ ?>
21
+ <div class="single_job_listing">
22
  <?php if ( get_option( 'job_manager_hide_expired_content', 1 ) && 'expired' === $post->post_status ) : ?>
23
  <div class="job-manager-info"><?php _e( 'This listing has expired.', 'wp-job-manager' ); ?></div>
24
  <?php else : ?>
32
  do_action( 'single_job_listing_start' );
33
  ?>
34
 
35
+ <div class="job_description">
36
+ <?php wpjm_the_job_description(); ?>
37
  </div>
38
 
39
  <?php if ( candidates_can_apply() ) : ?>
templates/content-summary-job_listing.php CHANGED
@@ -1,4 +1,22 @@
1
- <?php global $job_manager; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  <a href="<?php the_permalink(); ?>">
4
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
1
+ <?php
2
+ /**
3
+ * Job listing summary
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/content-summary-job_listing.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.27.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+
18
+ global $job_manager;
19
+ ?>
20
 
21
  <a href="<?php the_permalink(); ?>">
22
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
templates/content-widget-job_listing.php CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <li <?php job_listing_class(); ?>>
2
  <a href="<?php the_job_permalink(); ?>">
3
  <div class="position">
1
+ <?php
2
+ /**
3
+ * Single job listing widget content.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/content-widget-job_listing.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.27.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <li <?php job_listing_class(); ?>>
19
  <a href="<?php the_job_permalink(); ?>">
20
  <div class="position">
templates/content-widget-no-jobs-found.php CHANGED
@@ -1 +1,19 @@
1
- <?php /** Intentionally empty - override to modify the content **/ ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Placeholder if no jobs are found in featured jobs widget.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/content-widget-no-jobs-found.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @since 1.20.0
12
+ * @version 1.20.0
13
+ */
14
+
15
+ if ( ! defined( 'ABSPATH' ) ) {
16
+ exit; // Exit if accessed directly
17
+ }
18
+
19
+ /** Intentionally empty - override to modify the content **/
templates/form-fields/checkbox-field.php CHANGED
@@ -1,2 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <input type="checkbox" class="input-checkbox" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" id="<?php echo esc_attr( $key ); ?>" <?php checked( ! empty( $field['value'] ), true ); ?> value="1" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> />
2
  <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
1
+ <?php
2
+ /**
3
+ * Shows the `checkbox` form field on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/checkbox-field.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.21.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <input type="checkbox" class="input-checkbox" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" id="<?php echo esc_attr( $key ); ?>" <?php checked( ! empty( $field['value'] ), true ); ?> value="1" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> />
19
  <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
templates/form-fields/file-field.php CHANGED
@@ -1,4 +1,20 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  $classes = array( 'input-text' );
3
  $allowed_mime_types = array_keys( ! empty( $field['allowed_mime_types'] ) ? $field['allowed_mime_types'] : get_allowed_mime_types() );
4
  $field_name = isset( $field['name'] ) ? $field['name'] : $key;
1
  <?php
2
+ /**
3
+ * Shows the `file` form field on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/file-field.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.27.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+
18
  $classes = array( 'input-text' );
19
  $allowed_mime_types = array_keys( ! empty( $field['allowed_mime_types'] ) ? $field['allowed_mime_types'] : get_allowed_mime_types() );
20
  $field_name = isset( $field['name'] ) ? $field['name'] : $key;
templates/form-fields/multiselect-field.php CHANGED
@@ -1,5 +1,22 @@
1
- <?php wp_enqueue_script( 'wp-job-manager-multiselect' ); ?>
 
 
 
 
 
 
 
 
 
 
 
2
 
 
 
 
 
 
 
3
  <select multiple="multiple" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>[]" id="<?php echo esc_attr( $key ); ?>" class="job-manager-multiselect" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> data-no_results_text="<?php _e( 'No results match', 'wp-job-manager' ); ?>" data-multiple_text="<?php _e( 'Select Some Options', 'wp-job-manager' ); ?>">
4
  <?php foreach ( $field['options'] as $key => $value ) : ?>
5
  <option value="<?php echo esc_attr( $key ); ?>" <?php if ( ! empty( $field['value'] ) && is_array( $field['value'] ) ) selected( in_array( $key, $field['value'] ), true ); ?>><?php echo esc_html( $value ); ?></option>
1
+ <?php
2
+ /**
3
+ * Shows the `select` (multiple) form field on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/checkbox-field.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.23.7
12
+ */
13
 
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+
18
+ wp_enqueue_script( 'wp-job-manager-multiselect' );
19
+ ?>
20
  <select multiple="multiple" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>[]" id="<?php echo esc_attr( $key ); ?>" class="job-manager-multiselect" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> data-no_results_text="<?php _e( 'No results match', 'wp-job-manager' ); ?>" data-multiple_text="<?php _e( 'Select Some Options', 'wp-job-manager' ); ?>">
21
  <?php foreach ( $field['options'] as $key => $value ) : ?>
22
  <option value="<?php echo esc_attr( $key ); ?>" <?php if ( ! empty( $field['value'] ) && is_array( $field['value'] ) ) selected( in_array( $key, $field['value'] ), true ); ?>><?php echo esc_html( $value ); ?></option>
templates/form-fields/password-field.php CHANGED
@@ -1,2 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <input type="password" class="input-text"<?php if ( isset( $field['autocomplete'] ) && false === $field['autocomplete'] ) { echo ' autocomplete="off"'; } ?> name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo isset( $field['value'] ) ? esc_attr( $field['value'] ) : ''; ?>" maxlength="<?php echo ! empty( $field['maxlength'] ) ? $field['maxlength'] : ''; ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> />
2
  <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
1
+ <?php
2
+ /**
3
+ * Shows the `password` form field on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/password-field.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.5.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <input type="password" class="input-text"<?php if ( isset( $field['autocomplete'] ) && false === $field['autocomplete'] ) { echo ' autocomplete="off"'; } ?> name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo isset( $field['value'] ) ? esc_attr( $field['value'] ) : ''; ?>" maxlength="<?php echo ! empty( $field['maxlength'] ) ? $field['maxlength'] : ''; ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> />
19
  <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
templates/form-fields/radio-field.php CHANGED
@@ -1,6 +1,10 @@
1
  <?php
2
  /**
3
- * Radio Field. Example definition:
 
 
 
 
4
  *
5
  * 'test_radio' => array(
6
  * 'label' => __( 'Test Radio', 'wp-job-manager' ),
@@ -13,8 +17,18 @@
13
  * 'option2' => 'This is option 2'
14
  * )
15
  * )
 
 
 
 
 
 
16
  */
17
 
 
 
 
 
18
  $field['default'] = empty( $field['default'] ) ? current( array_keys( $field['options'] ) ) : $field['default'];
19
  $default = ! empty( $field['value'] ) ? $field['value'] : $field['default'];
20
 
1
  <?php
2
  /**
3
+ * Shows the `radio` form field on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/radio-field.php.
6
+ *
7
+ * Example definition:
8
  *
9
  * 'test_radio' => array(
10
  * 'label' => __( 'Test Radio', 'wp-job-manager' ),
17
  * 'option2' => 'This is option 2'
18
  * )
19
  * )
20
+ *
21
+ * @see https://wpjobmanager.com/document/template-overrides/
22
+ * @author Automattic
23
+ * @package WP Job Manager
24
+ * @category Template
25
+ * @version 1.23.0
26
  */
27
 
28
+ if ( ! defined( 'ABSPATH' ) ) {
29
+ exit; // Exit if accessed directly
30
+ }
31
+
32
  $field['default'] = empty( $field['default'] ) ? current( array_keys( $field['options'] ) ) : $field['default'];
33
  $default = ! empty( $field['value'] ) ? $field['value'] : $field['default'];
34
 
templates/form-fields/select-field.php CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <select name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" id="<?php echo esc_attr( $key ); ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?>>
2
  <?php foreach ( $field['options'] as $key => $value ) : ?>
3
  <option value="<?php echo esc_attr( $key ); ?>" <?php if ( isset( $field['value'] ) || isset( $field['default'] ) ) selected( isset( $field['value'] ) ? $field['value'] : $field['default'], $key ); ?>><?php echo esc_html( $value ); ?></option>
1
+ <?php
2
+ /**
3
+ * Shows the `select` form field on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/select-field.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.19.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <select name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" id="<?php echo esc_attr( $key ); ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?>>
19
  <?php foreach ( $field['options'] as $key => $value ) : ?>
20
  <option value="<?php echo esc_attr( $key ); ?>" <?php if ( isset( $field['value'] ) || isset( $field['default'] ) ) selected( isset( $field['value'] ) ? $field['value'] : $field['default'], $key ); ?>><?php echo esc_html( $value ); ?></option>
templates/form-fields/term-checklist-field.php CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <ul class="job-manager-term-checklist job-manager-term-checklist-<?php echo $key ?>">
2
  <?php
3
  require_once( ABSPATH . '/wp-admin/includes/template.php' );
1
+ <?php
2
+ /**
3
+ * Shows `checkbox` form fields in a list from a list on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/term-checklist-field.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.22.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <ul class="job-manager-term-checklist job-manager-term-checklist-<?php echo $key ?>">
19
  <?php
20
  require_once( ABSPATH . '/wp-admin/includes/template.php' );
templates/form-fields/term-multiselect-field.php CHANGED
@@ -1,4 +1,20 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  // Get selected value
3
  if ( isset( $field['value'] ) ) {
4
  $selected = $field['value'];
1
  <?php
2
+ /**
3
+ * Shows term `select` (multiple) form field on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/term-multiselect-field.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.22.2
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+
18
  // Get selected value
19
  if ( isset( $field['value'] ) ) {
20
  $selected = $field['value'];
templates/form-fields/term-select-field.php CHANGED
@@ -1,4 +1,20 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  // Get selected value
3
  if ( isset( $field['value'] ) ) {
4
  $selected = $field['value'];
1
  <?php
2
+ /**
3
+ * Shows term `select` form field on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/term-select-field.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.27.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+
18
  // Get selected value
19
  if ( isset( $field['value'] ) ) {
20
  $selected = $field['value'];
templates/form-fields/text-field.php CHANGED
@@ -1,2 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <input type="text" class="input-text" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>"<?php if ( isset( $field['autocomplete'] ) && false === $field['autocomplete'] ) { echo ' autocomplete="off"'; } ?> id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo isset( $field['value'] ) ? esc_attr( $field['value'] ) : ''; ?>" maxlength="<?php echo ! empty( $field['maxlength'] ) ? $field['maxlength'] : ''; ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> />
2
  <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
1
+ <?php
2
+ /**
3
+ * Shows the `text` form field on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/text-field.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.27.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <input type="text" class="input-text" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>"<?php if ( isset( $field['autocomplete'] ) && false === $field['autocomplete'] ) { echo ' autocomplete="off"'; } ?> id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo isset( $field['value'] ) ? esc_attr( $field['value'] ) : ''; ?>" maxlength="<?php echo ! empty( $field['maxlength'] ) ? $field['maxlength'] : ''; ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> />
19
  <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
templates/form-fields/textarea-field.php CHANGED
@@ -1,2 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <textarea cols="20" rows="3" class="input-text" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" maxlength="<?php echo ! empty( $field['maxlength'] ) ? $field['maxlength'] : ''; ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?>><?php echo isset( $field['value'] ) ? esc_textarea( $field['value'] ) : ''; ?></textarea>
2
  <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
1
+ <?php
2
+ /**
3
+ * Shows the `textarea` form field on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/textarea-field.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.27.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <textarea cols="20" rows="3" class="input-text" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" maxlength="<?php echo ! empty( $field['maxlength'] ) ? $field['maxlength'] : ''; ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?>><?php echo isset( $field['value'] ) ? esc_textarea( $field['value'] ) : ''; ?></textarea>
19
  <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
templates/form-fields/uploaded-file-html.php CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <div class="job-manager-uploaded-file">
2
  <?php
3
  if ( is_numeric( $value ) ) {
1
+ <?php
2
+ /**
3
+ * Shows info for an uploaded file on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/uploaded-file-html.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.24.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <div class="job-manager-uploaded-file">
19
  <?php
20
  if ( is_numeric( $value ) ) {
templates/form-fields/wp-editor-field.php CHANGED
@@ -1,4 +1,20 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  $editor = apply_filters( 'submit_job_form_wp_editor_args', array(
3
  'textarea_name' => isset( $field['name'] ) ? $field['name'] : $key,
4
  'media_buttons' => false,
1
  <?php
2
+ /**
3
+ * Shows the right `textarea` form field with WP Editor on job listing forms.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/form-fields/wp-editor-field.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.23.9
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+
18
  $editor = apply_filters( 'submit_job_form_wp_editor_args', array(
19
  'textarea_name' => isset( $field['name'] ) ? $field['name'] : $key,
20
  'media_buttons' => false,
templates/job-application-email.php CHANGED
@@ -1 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <p><?php printf( __( 'To apply for this job <strong>email your details to</strong> <a class="job_application_email" href="mailto:%1$s%2$s">%1$s</a>', 'wp-job-manager' ), $apply->email, '?subject=' . rawurlencode( $apply->subject ) ); ?></p>
1
+ <?php
2
+ /**
3
+ * Apply by email content.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-application-email.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.9.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <p><?php printf( __( 'To apply for this job <strong>email your details to</strong> <a class="job_application_email" href="mailto:%1$s%2$s">%1$s</a>', 'wp-job-manager' ), $apply->email, '?subject=' . rawurlencode( $apply->subject ) ); ?></p>
templates/job-application-url.php CHANGED
@@ -1 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <p><?php _e( 'To apply for this job please visit the following URL:', 'wp-job-manager' ); ?> <a href="<?php echo esc_url( $apply->url ); ?>" target="_blank" rel="nofollow"><?php echo esc_html( $apply->url ); ?> &rarr;</a></p>
1
+ <?php
2
+ /**
3
+ * Apply using link to website.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-application-url.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.9.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <p><?php _e( 'To apply for this job please visit the following URL:', 'wp-job-manager' ); ?> <a href="<?php echo esc_url( $apply->url ); ?>" target="_blank" rel="nofollow"><?php echo esc_html( $apply->url ); ?> &rarr;</a></p>
templates/job-application.php CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php if ( $apply = get_the_job_application_method() ) :
2
  wp_enqueue_script( 'wp-job-manager-job-application' );
3
  ?>
1
+ <?php
2
+ /**
3
+ * Show job application when viewing a single job listing.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-application.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.16.1
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <?php if ( $apply = get_the_job_application_method() ) :
19
  wp_enqueue_script( 'wp-job-manager-job-application' );
20
  ?>
templates/job-dashboard-login.php CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <div id="job-manager-job-dashboard">
2
 
3
  <p class="account-sign-in"><?php _e( 'You need to be signed in to manage your listings.', 'wp-job-manager' ); ?> <a class="button" href="<?php echo apply_filters( 'job_manager_job_dashboard_login_url', wp_login_url( get_permalink() ) ); ?>"><?php _e( 'Sign in', 'wp-job-manager' ); ?></a></p>
1
+ <?php
2
+ /**
3
+ * Job dashboard shortcode content if user is not logged in.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-dashboard-login.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.19.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <div id="job-manager-job-dashboard">
19
 
20
  <p class="account-sign-in"><?php _e( 'You need to be signed in to manage your listings.', 'wp-job-manager' ); ?> <a class="button" href="<?php echo apply_filters( 'job_manager_job_dashboard_login_url', wp_login_url( get_permalink() ) ); ?>"><?php _e( 'Sign in', 'wp-job-manager' ); ?></a></p>
templates/job-dashboard.php CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <div id="job-manager-job-dashboard">
2
  <p><?php _e( 'Your listings are shown in the table below.', 'wp-job-manager' ); ?></p>
3
  <table class="job-manager-jobs">
1
+ <?php
2
+ /**
3
+ * Job dashboard shortcode content.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-dashboard.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.27.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <div id="job-manager-job-dashboard">
19
  <p><?php _e( 'Your listings are shown in the table below.', 'wp-job-manager' ); ?></p>
20
  <table class="job-manager-jobs">
templates/job-filter-job-types.php CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php if ( ! is_tax( 'job_listing_type' ) && empty( $job_types ) ) : ?>
2
  <ul class="job_types">
3
  <?php foreach ( get_job_listing_types() as $type ) : ?>
1
+ <?php
2
+ /**
3
+ * Filter in `[jobs]` shortcode for job types.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-filter-job-types.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.20.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <?php if ( ! is_tax( 'job_listing_type' ) && empty( $job_types ) ) : ?>
19
  <ul class="job_types">
20
  <?php foreach ( get_job_listing_types() as $type ) : ?>
templates/job-filters.php CHANGED
@@ -1,6 +1,24 @@
1
- <?php wp_enqueue_script( 'wp-job-manager-ajax-filters' ); ?>
2
-
3
- <?php do_action( 'job_manager_job_filters_before', $atts ); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  <form class="job_filters">
6
  <?php do_action( 'job_manager_job_filters_start', $atts ); ?>
1
+ <?php
2
+ /**
3
+ * Filters in `[jobs]` shortcode.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-filters.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.21.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+
18
+ wp_enqueue_script( 'wp-job-manager-ajax-filters' );
19
+
20
+ do_action( 'job_manager_job_filters_before', $atts );
21
+ ?>
22
 
23
  <form class="job_filters">
24
  <?php do_action( 'job_manager_job_filters_start', $atts ); ?>
templates/job-listings-end.php CHANGED
@@ -1 +1,18 @@
1
- </ul>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Content shown after job listings in `[jobs]` shortcode.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-listings-end.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.15.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
+ </ul>
templates/job-listings-start.php CHANGED
@@ -1 +1,18 @@
1
- <ul class="job_listings">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Content shown before job listings in `[jobs]` shortcode.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-listings-start.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.15.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
+ <ul class="job_listings">
templates/job-pagination.php CHANGED
@@ -1,8 +1,19 @@
1
  <?php
2
  /**
3
- * Pagination - Show numbered pagination for the [jobs] shortcode
 
 
 
 
 
 
 
 
4
  */
5
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
 
6
 
7
  if ( $max_num_pages <= 1 ) {
8
  return;
1
  <?php
2
  /**
3
+ * Pagination - Show numbered pagination for the `[jobs]` shortcode.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-pagination.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.21.4
12
  */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
 
18
  if ( $max_num_pages <= 1 ) {
19
  return;
templates/job-preview.php CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <form method="post" id="job_preview" action="<?php echo esc_url( $form->get_action() ); ?>">
2
  <div class="job_listing_preview_title">
3
  <input type="submit" name="continue" id="job_preview_submit_button" class="button job-manager-button-submit-listing" value="<?php echo apply_filters( 'submit_job_step_preview_submit_text', __( 'Submit Listing', 'wp-job-manager' ) ); ?>" />
1
+ <?php
2
+ /**
3
+ * Job listing preview when submitting job listings.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-preview.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.27.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+ ?>
18
  <form method="post" id="job_preview" action="<?php echo esc_url( $form->get_action() ); ?>">
19
  <div class="job_listing_preview_title">
20
  <input type="submit" name="continue" id="job_preview_submit_button" class="button job-manager-button-submit-listing" value="<?php echo apply_filters( 'submit_job_step_preview_submit_text', __( 'Submit Listing', 'wp-job-manager' ) ); ?>" />
templates/job-submit.php CHANGED
@@ -1,8 +1,19 @@
1
  <?php
2
  /**
3
- * Job Submission Form
 
 
 
 
 
 
 
 
4
  */
5
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
 
6
 
7
  global $job_manager;
8
  ?>
@@ -10,7 +21,7 @@ global $job_manager;
10
 
11
  <?php
12
  if ( isset( $resume_edit ) && $resume_edit ) {
13
- printf( '<p><strong>' . __( "You are editing an existing job. %s" ) . '</strong></p>', '<a href="?new=1&key=' . $resume_edit . '">' . __( 'Create A New Job' ) . '</a>' );
14
  }
15
  ?>
16
 
1
  <?php
2
  /**
3
+ * Content for job submission (`[submit_job_form]`) shortcode.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-submit.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.27.0
12
  */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
 
18
  global $job_manager;
19
  ?>
21
 
22
  <?php
23
  if ( isset( $resume_edit ) && $resume_edit ) {
24
+ printf( '<p><strong>' . __( "You are editing an existing job. %s", 'wp-job-manager' ) . '</strong></p>', '<a href="?new=1&key=' . $resume_edit . '">' . __( 'Create A New Job', 'wp-job-manager' ) . '</a>' );
25
  }
26
  ?>
27
 
templates/job-submitted.php CHANGED
@@ -1,4 +1,20 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  global $wp_post_types;
3
 
4
  switch ( $job->post_status ) :
1
  <?php
2
+ /**
3
+ * Notice when job has been submitted.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/job-submitted.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.20.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+
18
  global $wp_post_types;
19
 
20
  switch ( $job->post_status ) :
templates/pagination.php CHANGED
@@ -1,8 +1,19 @@
1
  <?php
2
  /**
3
  * Pagination - Show numbered pagination for catalog pages.
 
 
 
 
 
 
 
 
4
  */
5
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
 
6
 
7
  if ( $max_num_pages <= 1 ) {
8
  return;
1
  <?php
2
  /**
3
  * Pagination - Show numbered pagination for catalog pages.
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/job_manager/pagination.php.
6
+ *
7
+ * @see https://wpjobmanager.com/document/template-overrides/
8
+ * @author Automattic
9
+ * @package WP Job Manager
10
+ * @category Template
11
+ * @version 1.20.0
12
  */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
 
18
  if ( $max_num_pages <= 1 ) {
19
  return;
wp-job-manager-deprecated.php CHANGED
@@ -71,3 +71,16 @@ function get_the_job_type( $post = null ) {
71
  return apply_filters( 'the_job_type', $type, $post );
72
  }
73
  endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  return apply_filters( 'the_job_type', $type, $post );
72
  }
73
  endif;
74
+
75
+ if ( ! function_exists( 'wpjm_get_permalink_structure' ) ) :
76
+ /**
77
+ * Retrieves permalink settings. Moved to `WP_Job_Manager_Post_Types` class in 1.28.0.
78
+ *
79
+ * @since 1.27.0
80
+ * @deprecated 1.28.0
81
+ * @return array
82
+ */
83
+ function wpjm_get_permalink_structure() {
84
+ return WP_Job_Manager_Post_Types::get_permalink_structure();
85
+ }
86
+ endif;
wp-job-manager-functions.php CHANGED
@@ -152,7 +152,7 @@ function get_job_listings( $args = array() ) {
152
 
153
  if ( false === ( $result = get_transient( $query_args_hash ) ) ) {
154
  $result = new WP_Query( $query_args );
155
- set_transient( $query_args_hash, $result, DAY_IN_SECONDS * 30 );
156
  }
157
 
158
  // random order is cached so shuffle them
@@ -287,7 +287,7 @@ if ( ! function_exists( 'get_job_listing_types' ) ) :
287
  *
288
  * @since 1.0.0
289
  * @param string|array $fields
290
- * @return array
291
  */
292
  function get_job_listing_types( $fields = 'all' ) {
293
  if ( ! get_option( 'job_manager_enable_types' ) ) {
@@ -510,8 +510,23 @@ function wp_job_manager_create_account( $args, $deprecated = '' ) {
510
  return $user_id;
511
  }
512
 
513
- // Notify
514
- wp_job_manager_notify_new_user( $user_id, $password, $new_user );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
515
 
516
  // Login
517
  wp_set_auth_cookie( $user_id, true, is_ssl() );
@@ -521,38 +536,6 @@ function wp_job_manager_create_account( $args, $deprecated = '' ) {
521
  }
522
  endif;
523
 
524
-
525
- /**
526
- * Retrieves permalink settings.
527
- *
528
- * @see https://github.com/woocommerce/woocommerce/blob/3.0.8/includes/wc-core-functions.php#L1573
529
- * @since 2.7.3
530
- * @return array
531
- */
532
- function wpjm_get_permalink_structure() {
533
- // Switch to the site's default locale, bypassing the active user's locale.
534
- if ( function_exists( 'switch_to_locale' ) && did_action( 'admin_init' ) ) {
535
- switch_to_locale( get_locale() );
536
- }
537
-
538
- $permalinks = wp_parse_args( (array) get_option( 'wpjm_permalinks', array() ), array(
539
- 'job_base' => '',
540
- 'category_base' => '',
541
- 'type_base' => '',
542
- ) );
543
-
544
- // Ensure rewrite slugs are set.
545
- $permalinks['job_rewrite_slug'] = untrailingslashit( empty( $permalinks['job_base'] ) ? _x( 'job', 'Job permalink - resave permalinks after changing this', 'wp-job-manager' ) : $permalinks['job_base'] );
546
- $permalinks['category_rewrite_slug'] = untrailingslashit( empty( $permalinks['category_base'] ) ? _x( 'job-category', 'Job category slug - resave permalinks after changing this', 'wp-job-manager' ) : $permalinks['category_base'] );
547
- $permalinks['type_rewrite_slug'] = untrailingslashit( empty( $permalinks['type_base'] ) ? _x( 'job-type', 'Job type slug - resave permalinks after changing this', 'wp-job-manager' ) : $permalinks['type_base'] );
548
-
549
- // Restore the original locale.
550
- if ( function_exists( 'restore_current_locale' ) && did_action( 'admin_init' ) ) {
551
- restore_current_locale();
552
- }
553
- return $permalinks;
554
- }
555
-
556
  /**
557
  * Checks if the user can upload a file via the Ajax endpoint.
558
  *
@@ -637,6 +620,54 @@ function wpjm_use_standard_password_setup_email() {
637
  return apply_filters( 'wpjm_use_standard_password_setup_email', $use_standard_password_setup_email );
638
  }
639
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
640
  /**
641
  * Checks if a password should be auto-generated for new users.
642
  *
@@ -784,7 +815,7 @@ function job_manager_dropdown_categories( $args = '' ) {
784
  'exclude' => $r['exclude'],
785
  'hierarchical' => $r['hierarchical']
786
  ) );
787
- set_transient( $categories_hash, $categories, DAY_IN_SECONDS * 30 );
788
  }
789
 
790
  $name = esc_attr( $name );
152
 
153
  if ( false === ( $result = get_transient( $query_args_hash ) ) ) {
154
  $result = new WP_Query( $query_args );
155
+ set_transient( $query_args_hash, $result, DAY_IN_SECONDS );
156
  }
157
 
158
  // random order is cached so shuffle them
287
  *
288
  * @since 1.0.0
289
  * @param string|array $fields
290
+ * @return WP_Term[]
291
  */
292
  function get_job_listing_types( $fields = 'all' ) {
293
  if ( ! get_option( 'job_manager_enable_types' ) ) {
510
  return $user_id;
511
  }
512
 
513
+ /**
514
+ * Send notification to new users.
515
+ *
516
+ * @since 1.28.0
517
+ *
518
+ * @param int $user_id
519
+ * @param string|bool $password
520
+ * @param array $new_user {
521
+ * Information about the new user.
522
+ *
523
+ * @type string $user_login Username for the user.
524
+ * @type string $user_pass Password for the user (may be blank).
525
+ * @type string $user_email Email for the new user account.
526
+ * @type string $role New user's role.
527
+ * }
528
+ */
529
+ do_action( 'wpjm_notify_new_user', $user_id, $password, $new_user );
530
 
531
  // Login
532
  wp_set_auth_cookie( $user_id, true, is_ssl() );
536
  }
537
  endif;
538
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  /**
540
  * Checks if the user can upload a file via the Ajax endpoint.
541
  *
620
  return apply_filters( 'wpjm_use_standard_password_setup_email', $use_standard_password_setup_email );
621
  }
622
 
623
+ /**
624
+ * Returns the list of employment types from Google's modification of schema.org's employmentType.
625
+ *
626
+ * @since 1.28.0
627
+ * @see https://developers.google.com/search/docs/data-types/job-postings#definitions
628
+ *
629
+ * @return array
630
+ */
631
+ function wpjm_job_listing_employment_type_options() {
632
+ $employment_types = array();
633
+ $employment_types['FULL_TIME'] = __( 'Full Time', 'wp-job-manager' );
634
+ $employment_types['PART_TIME'] = __( 'Part Time', 'wp-job-manager' );
635
+ $employment_types['CONTRACTOR'] = __( 'Contractor', 'wp-job-manager' );
636
+ $employment_types['TEMPORARY'] = __( 'Temporary', 'wp-job-manager' );
637
+ $employment_types['INTERN'] = __( 'Intern', 'wp-job-manager' );
638
+ $employment_types['VOLUNTEER'] = __( 'Volunteer', 'wp-job-manager' );
639
+ $employment_types['PER_DIEM'] = __( 'Per Diem', 'wp-job-manager' );
640
+ $employment_types['OTHER'] = __( 'Other', 'wp-job-manager' );
641
+
642
+ /**
643
+ * Filter the list of employment types.
644
+ *
645
+ * @since 1.28.0
646
+ *
647
+ * @param array List of employment types { string $key => string $label }.
648
+ */
649
+ return apply_filters( 'wpjm_job_listing_employment_type_options', $employment_types );
650
+ }
651
+
652
+
653
+ /**
654
+ * Check if employment type meta fields are enabled on job type terms.
655
+ *
656
+ * @since 1.28.0
657
+ *
658
+ * @return bool
659
+ */
660
+ function wpjm_job_listing_employment_type_enabled() {
661
+ /**
662
+ * Filter whether employment types are enabled for job type terms.
663
+ *
664
+ * @since 1.28.0
665
+ *
666
+ * @param bool True if employment type meta field is enabled on job type terms.
667
+ */
668
+ return apply_filters( 'wpjm_job_listing_employment_type_enabled', get_option( 'job_manager_enable_types' ) ? true : false );
669
+ }
670
+
671
  /**
672
  * Checks if a password should be auto-generated for new users.
673
  *
815
  'exclude' => $r['exclude'],
816
  'hierarchical' => $r['hierarchical']
817
  ) );
818
+ set_transient( $categories_hash, $categories, DAY_IN_SECONDS * 7 );
819
  }
820
 
821
  $name = esc_attr( $name );
wp-job-manager-template.php CHANGED
@@ -220,7 +220,7 @@ function get_the_job_permalink( $post = null ) {
220
  function get_the_job_application_method( $post = null ) {
221
  $post = get_post( $post );
222
 
223
- if ( $post && $post->post_type !== 'job_listing' ) {
224
  return;
225
  }
226
 
@@ -245,6 +245,225 @@ function get_the_job_application_method( $post = null ) {
245
  return apply_filters( 'the_job_application_method', $method, $post );
246
  }
247
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
  /**
249
  * Displays the job title for the listing.
250
  *
@@ -267,7 +486,7 @@ function wpjm_the_job_title( $post = null ) {
267
  */
268
  function wpjm_get_the_job_title( $post = null ) {
269
  $post = get_post( $post );
270
- if ( $post->post_type !== 'job_listing' ) {
271
  return;
272
  }
273
 
@@ -283,6 +502,44 @@ function wpjm_get_the_job_title( $post = null ) {
283
  return apply_filters( 'wpjm_the_job_title', $title, $post );
284
  }
285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  /**
287
  * Displays multiple job types for the listing.
288
  *
@@ -316,7 +573,7 @@ function wpjm_the_job_types( $post = null, $separator = ', ' ) {
316
  function wpjm_get_the_job_types( $post = null ) {
317
  $post = get_post( $post );
318
 
319
- if ( 'job_listing' !== $post->post_type ) {
320
  return false;
321
  }
322
 
@@ -407,7 +664,7 @@ function the_job_publish_date( $post = null ) {
407
  $date_format = get_option( 'job_manager_date_format' );
408
 
409
  if ( $date_format === 'default' ) {
410
- $display_date = __( 'Posted on ', 'wp-job-manager' ) . get_post_time( get_option( 'date_format' ) );
411
  } else {
412
  $display_date = sprintf( __( 'Posted %s ago', 'wp-job-manager' ), human_time_diff( get_post_time( 'U' ), current_time( 'timestamp' ) ) );
413
  }
@@ -465,7 +722,7 @@ function the_job_location( $map_link = true, $post = null ) {
465
  */
466
  function get_the_job_location( $post = null ) {
467
  $post = get_post( $post );
468
- if ( $post->post_type !== 'job_listing' ) {
469
  return;
470
  }
471
 
@@ -620,7 +877,7 @@ function the_company_video( $post = null ) {
620
  */
621
  function get_the_company_video( $post = null ) {
622
  $post = get_post( $post );
623
- if ( $post->post_type !== 'job_listing' ) {
624
  return;
625
  }
626
  return apply_filters( 'the_company_video', $post->_company_video, $post );
@@ -661,7 +918,7 @@ function the_company_name( $before = '', $after = '', $echo = true, $post = null
661
  */
662
  function get_the_company_name( $post = null ) {
663
  $post = get_post( $post );
664
- if ( $post->post_type !== 'job_listing' ) {
665
  return '';
666
  }
667
 
@@ -678,7 +935,7 @@ function get_the_company_name( $post = null ) {
678
  function get_the_company_website( $post = null ) {
679
  $post = get_post( $post );
680
 
681
- if ( $post->post_type !== 'job_listing' )
682
  return;
683
 
684
  $website = $post->_company_website;
@@ -725,7 +982,7 @@ function the_company_tagline( $before = '', $after = '', $echo = true, $post = n
725
  function get_the_company_tagline( $post = null ) {
726
  $post = get_post( $post );
727
 
728
- if ( $post->post_type !== 'job_listing' )
729
  return;
730
 
731
  return apply_filters( 'the_company_tagline', $post->_company_tagline, $post );
@@ -765,7 +1022,7 @@ function the_company_twitter( $before = '', $after = '', $echo = true, $post = n
765
  */
766
  function get_the_company_twitter( $post = null ) {
767
  $post = get_post( $post );
768
- if ( $post->post_type !== 'job_listing' )
769
  return;
770
 
771
  $company_twitter = $post->_company_twitter;
220
  function get_the_job_application_method( $post = null ) {
221
  $post = get_post( $post );
222
 
223
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
224
  return;
225
  }
226
 
245
  return apply_filters( 'the_job_application_method', $method, $post );
246
  }
247
 
248
+ /**
249
+ * Get the employment types for the job listing.
250
+ *
251
+ * @since 1.28.0
252
+ *
253
+ * @param WP_Post|int|null $post
254
+ * @return bool|array
255
+ */
256
+ function wpjm_get_job_employment_types( $post = null) {
257
+ if ( ! wpjm_job_listing_employment_type_enabled() ) {
258
+ return false;
259
+ }
260
+ $employment_types = array();
261
+ $job_types = wpjm_get_the_job_types( $post );
262
+
263
+ if ( ! empty( $job_types ) ) {
264
+ foreach ( $job_types as $job_type ) {
265
+ $employment_type = get_term_meta( $job_type->term_id, 'employment_type', true );
266
+ if ( ! empty( $employment_type ) ) {
267
+ $employment_types[] = $employment_type;
268
+ }
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Filter the employment types for a job listing.
274
+ *
275
+ * @since 1.28.0
276
+ *
277
+ * @param array $employment_types Employment types.
278
+ * @param WP_Post|int|null $post
279
+ */
280
+ return apply_filters( 'wpjm_get_job_employment_types', array_unique( $employment_types ), $post );
281
+ }
282
+
283
+ /**
284
+ * Returns if we allow indexing of a job listing.
285
+ *
286
+ * @since 1.28.0
287
+ *
288
+ * @param WP_Post|int|null $post
289
+ * @return bool
290
+ */
291
+ function wpjm_allow_indexing_job_listing( $post = null ) {
292
+ $post = get_post( $post );
293
+
294
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
295
+ return true;
296
+ }
297
+
298
+ // Only index job listings that are un-filled and published.
299
+ $index_job_listing = ! is_position_filled( $post ) && 'publish' === $post->post_status;
300
+
301
+ /**
302
+ * Filter if we should allow indexing of job listing.
303
+ *
304
+ * @since 1.28.0
305
+ *
306
+ * @param bool $index_job_listing True if we should allow indexing of job listing.
307
+ * @param WP_Post|int|null $post
308
+ */
309
+ return apply_filters( 'wpjm_allow_indexing_job_listing', $index_job_listing, $post );
310
+ }
311
+
312
+ /**
313
+ * Returns if we output job listing structured data for a post.
314
+ *
315
+ * @since 1.28.0
316
+ *
317
+ * @param WP_Post|int|null $post
318
+ * @return bool
319
+ */
320
+ function wpjm_output_job_listing_structured_data( $post = null ) {
321
+ $post = get_post( $post );
322
+
323
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
324
+ return false;
325
+ }
326
+
327
+ // Only show structured data for un-filled and published job listings.
328
+ $output_structured_data = ! is_position_filled( $post ) && 'publish' === $post->post_status;
329
+
330
+ /**
331
+ * Filter if we should output structured data.
332
+ *
333
+ * @since 1.28.0
334
+ *
335
+ * @param bool $output_structured_data True if we should show structured data for post.
336
+ * @param WP_Post|int|null $post
337
+ */
338
+ return apply_filters( 'wpjm_output_job_listing_structured_data', $output_structured_data, $post );
339
+ }
340
+
341
+ /**
342
+ * Gets the structured data for the job listing.
343
+ *
344
+ * @since 1.28.0
345
+ * @see https://developers.google.com/search/docs/data-types/job-postings
346
+ *
347
+ * @param WP_Post|int|null $post
348
+ * @return bool|array False if functionality is disabled; otherwise array of structured data.
349
+ */
350
+ function wpjm_get_job_listing_structured_data( $post = null ) {
351
+ $post = get_post( $post );
352
+
353
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
354
+ return false;
355
+ }
356
+
357
+ $data = array();
358
+ $data['@context'] = 'http://schema.org/';
359
+ $data['@type'] = 'JobPosting';
360
+ $data['datePosted'] = get_post_time( 'c', false, $post );
361
+
362
+ $job_expires = get_post_meta( $post->ID, '_job_expires', true );
363
+ if ( ! empty( $job_expires ) ) {
364
+ $data[ 'validThrough' ] = date( 'c', strtotime( $job_expires ) );
365
+ }
366
+
367
+ $data['title'] = strip_tags( wpjm_get_the_job_title( $post ) );
368
+ $data['description'] = wpjm_get_the_job_description( $post );
369
+
370
+ $employmentTypes = wpjm_get_job_employment_types();
371
+ if ( ! empty( $employmentTypes ) ) {
372
+ $data['employmentType'] = $employmentTypes;
373
+ }
374
+
375
+ $data['hiringOrganization'] = array();
376
+ $data['hiringOrganization']['@type'] = 'Organization';
377
+ $data['hiringOrganization']['name'] = get_the_company_name( $post );
378
+ if ( $company_website = get_the_company_website( $post ) ) {
379
+ $data['hiringOrganization']['sameAs'] = $company_website;
380
+ $data['hiringOrganization']['url'] = $company_website;
381
+ }
382
+
383
+ $data['identifier'] = array();
384
+ $data['identifier']['@type'] = 'PropertyValue';
385
+ $data['identifier']['name'] = get_the_company_name( $post );
386
+ $data['identifier']['value'] = get_the_guid( $post );
387
+
388
+ $location = get_the_job_location( $post );
389
+ if ( ! empty( $location ) ) {
390
+ $data['jobLocation'] = array();
391
+ $data['jobLocation']['@type'] = 'Place';
392
+ $data['jobLocation']['address'] = wpjm_get_job_listing_location_structured_data( $post );
393
+ if ( empty( $data['jobLocation']['address'] ) ) {
394
+ $data['jobLocation']['address'] = $location;
395
+ }
396
+ }
397
+
398
+ /**
399
+ * Filter the structured data for a job listing.
400
+ *
401
+ * @since 1.28.0
402
+ *
403
+ * @param bool|array $structured_data False if functionality is disabled; otherwise array of structured data.
404
+ * @param WP_Post $post
405
+ */
406
+ return apply_filters( 'wpjm_get_job_listing_structured_data', $data, $post );
407
+ }
408
+
409
+ /**
410
+ * Gets the job listing location data.
411
+ *
412
+ * @see http://schema.org/PostalAddress
413
+ *
414
+ * @param WP_Post $post
415
+ * @return array|bool
416
+ */
417
+ function wpjm_get_job_listing_location_structured_data( $post ) {
418
+ $post = get_post( $post );
419
+
420
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
421
+ return false;
422
+ }
423
+
424
+ $mapping = array();
425
+ $mapping['streetAddress'] = array( 'street_number', 'street' );
426
+ $mapping['addressLocality'] = 'city';
427
+ $mapping['addressRegion'] = 'state_short';
428
+ $mapping['postalCode'] = 'postcode';
429
+ $mapping['addressCountry'] = 'country_short';
430
+
431
+ $address = array();
432
+ $address['@type'] = 'PostalAddress';
433
+ foreach ( $mapping as $schema_key => $geolocation_key ) {
434
+ if ( is_array( $geolocation_key ) ) {
435
+ $values = array();
436
+ foreach ( $geolocation_key as $sub_geo_key ) {
437
+ $geo_value = get_post_meta( $post->ID, 'geolocation_' . $sub_geo_key, true );
438
+ if ( ! empty( $geo_value ) ) {
439
+ $values[] = $geo_value;
440
+ }
441
+ }
442
+ $value = implode( ' ', $values );
443
+ } else {
444
+ $value = get_post_meta( $post->ID, 'geolocation_' . $geolocation_key, true );
445
+ }
446
+ if ( ! empty( $value ) ) {
447
+ $address[ $schema_key ] = $value;
448
+ }
449
+ }
450
+
451
+ // No address parts were found
452
+ if ( 1 === count( $address ) ) {
453
+ $address = false;
454
+ }
455
+
456
+ /**
457
+ * Gets the job listing location structured data.
458
+ *
459
+ * @since 1.28.0
460
+ *
461
+ * @param array|bool $address Array of address data.
462
+ * @param WP_Post $post
463
+ */
464
+ return apply_filters( 'wpjm_get_job_listing_location_structured_data', $address, $post );
465
+ }
466
+
467
  /**
468
  * Displays the job title for the listing.
469
  *
486
  */
487
  function wpjm_get_the_job_title( $post = null ) {
488
  $post = get_post( $post );
489
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
490
  return;
491
  }
492
 
502
  return apply_filters( 'wpjm_the_job_title', $title, $post );
503
  }
504
 
505
+ /**
506
+ * Displays the job description for the listing.
507
+ *
508
+ * @since 1.28.0
509
+ * @param int|WP_Post $post
510
+ * @return string
511
+ */
512
+ function wpjm_the_job_description( $post = null ) {
513
+ if ( $job_description = wpjm_get_the_job_description( $post ) ) {
514
+ echo $job_description;
515
+ }
516
+ }
517
+
518
+ /**
519
+ * Gets the job description for the listing.
520
+ *
521
+ * @since 1.28.0
522
+ * @param int|WP_Post $post (default: null)
523
+ * @return string|bool|null
524
+ */
525
+ function wpjm_get_the_job_description( $post = null ) {
526
+ $post = get_post( $post );
527
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
528
+ return;
529
+ }
530
+
531
+ $description = apply_filters( 'the_job_description', get_the_content( $post ) );
532
+
533
+ /**
534
+ * Filter for the job description.
535
+ *
536
+ * @since 1.28.0
537
+ * @param string $title Title to be filtered.
538
+ * @param int|WP_Post $post
539
+ */
540
+ return apply_filters( 'wpjm_the_job_description', $description, $post );
541
+ }
542
+
543
  /**
544
  * Displays multiple job types for the listing.
545
  *
573
  function wpjm_get_the_job_types( $post = null ) {
574
  $post = get_post( $post );
575
 
576
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
577
  return false;
578
  }
579
 
664
  $date_format = get_option( 'job_manager_date_format' );
665
 
666
  if ( $date_format === 'default' ) {
667
+ $display_date = __( 'Posted on ', 'wp-job-manager' ) . date_i18n( get_option( 'date_format' ), get_post_time( 'U' ) );
668
  } else {
669
  $display_date = sprintf( __( 'Posted %s ago', 'wp-job-manager' ), human_time_diff( get_post_time( 'U' ), current_time( 'timestamp' ) ) );
670
  }
722
  */
723
  function get_the_job_location( $post = null ) {
724
  $post = get_post( $post );
725
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
726
  return;
727
  }
728
 
877
  */
878
  function get_the_company_video( $post = null ) {
879
  $post = get_post( $post );
880
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
881
  return;
882
  }
883
  return apply_filters( 'the_company_video', $post->_company_video, $post );
918
  */
919
  function get_the_company_name( $post = null ) {
920
  $post = get_post( $post );
921
+ if ( ! $post || 'job_listing' !== $post->post_type ) {
922
  return '';
923
  }
924
 
935
  function get_the_company_website( $post = null ) {
936
  $post = get_post( $post );
937
 
938
+ if ( ! $post || 'job_listing' !== $post->post_type )
939
  return;
940
 
941
  $website = $post->_company_website;
982
  function get_the_company_tagline( $post = null ) {
983
  $post = get_post( $post );
984
 
985
+ if ( ! $post || 'job_listing' !== $post->post_type )
986
  return;
987
 
988
  return apply_filters( 'the_company_tagline', $post->_company_tagline, $post );
1022
  */
1023
  function get_the_company_twitter( $post = null ) {
1024
  $post = get_post( $post );
1025
+ if ( ! $post || 'job_listing' !== $post->post_type )
1026
  return;
1027
 
1028
  $company_twitter = $post->_company_twitter;
wp-job-manager.php CHANGED
@@ -3,11 +3,11 @@
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.27.0
7
  * Author: Automattic
8
  * Author URI: https://wpjobmanager.com/
9
  * Requires at least: 4.1
10
- * Tested up to: 4.7
11
  * Text Domain: wp-job-manager
12
  * Domain Path: /languages/
13
  * License: GPL2+
@@ -31,6 +31,11 @@ class WP_Job_Manager {
31
  */
32
  private static $_instance = null;
33
 
 
 
 
 
 
34
  /**
35
  * Main WP Job Manager Instance.
36
  *
@@ -53,13 +58,11 @@ class WP_Job_Manager {
53
  */
54
  public function __construct() {
55
  // Define constants
56
- define( 'JOB_MANAGER_VERSION', '1.27.0' );
57
  define( 'JOB_MANAGER_PLUGIN_DIR', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
58
  define( 'JOB_MANAGER_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
59
 
60
  // Includes
61
- include_once( 'wp-job-manager-functions.php' );
62
- include_once( 'wp-job-manager-deprecated.php' );
63
  include_once( 'includes/class-wp-job-manager-install.php' );
64
  include_once( 'includes/class-wp-job-manager-post-types.php' );
65
  include_once( 'includes/class-wp-job-manager-ajax.php' );
@@ -69,6 +72,8 @@ class WP_Job_Manager {
69
  include_once( 'includes/class-wp-job-manager-geocode.php' );
70
  include_once( 'includes/class-wp-job-manager-cache-helper.php' );
71
 
 
 
72
  if ( is_admin() ) {
73
  include_once( 'includes/admin/class-wp-job-manager-admin.php' );
74
  }
@@ -98,6 +103,9 @@ class WP_Job_Manager {
98
  add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
99
  add_action( 'admin_init', array( $this, 'updater' ) );
100
  add_action( 'wp_logout', array( $this, 'cleanup_job_posting_cookies' ) );
 
 
 
101
  }
102
 
103
  /**
@@ -105,7 +113,10 @@ class WP_Job_Manager {
105
  */
106
  public function activate() {
107
  WP_Job_Manager_Ajax::add_endpoint();
 
 
108
  $this->post_types->register_post_types();
 
109
  WP_Job_Manager_Install::install();
110
  flush_rewrite_rules();
111
  }
@@ -128,10 +139,26 @@ class WP_Job_Manager {
128
  load_plugin_textdomain( 'wp-job-manager', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
129
  }
130
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  /**
132
  * Loads plugin's core helper template functions.
133
  */
134
  public function include_template_functions() {
 
 
135
  include_once( 'wp-job-manager-template.php' );
136
  }
137
 
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.28.0
7
  * Author: Automattic
8
  * Author URI: https://wpjobmanager.com/
9
  * Requires at least: 4.1
10
+ * Tested up to: 4.8
11
  * Text Domain: wp-job-manager
12
  * Domain Path: /languages/
13
  * License: GPL2+
31
  */
32
  private static $_instance = null;
33
 
34
+ /**
35
+ * @var WP_Job_Manager_REST_API
36
+ */
37
+ private $rest_api = null;
38
+
39
  /**
40
  * Main WP Job Manager Instance.
41
  *
58
  */
59
  public function __construct() {
60
  // Define constants
61
+ define( 'JOB_MANAGER_VERSION', '1.28.0' );
62
  define( 'JOB_MANAGER_PLUGIN_DIR', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
63
  define( 'JOB_MANAGER_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
64
 
65
  // Includes
 
 
66
  include_once( 'includes/class-wp-job-manager-install.php' );
67
  include_once( 'includes/class-wp-job-manager-post-types.php' );
68
  include_once( 'includes/class-wp-job-manager-ajax.php' );
72
  include_once( 'includes/class-wp-job-manager-geocode.php' );
73
  include_once( 'includes/class-wp-job-manager-cache-helper.php' );
74
 
75
+ add_action( 'rest_api_init', array( $this, 'rest_api' ) );
76
+
77
  if ( is_admin() ) {
78
  include_once( 'includes/admin/class-wp-job-manager-admin.php' );
79
  }
103
  add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
104
  add_action( 'admin_init', array( $this, 'updater' ) );
105
  add_action( 'wp_logout', array( $this, 'cleanup_job_posting_cookies' ) );
106
+
107
+ // Defaults for WPJM core actions
108
+ add_action( 'wpjm_notify_new_user', 'wp_job_manager_notify_new_user', 10, 2 );
109
  }
110
 
111
  /**
113
  */
114
  public function activate() {
115
  WP_Job_Manager_Ajax::add_endpoint();
116
+ unregister_post_type( 'job_listing' );
117
+ add_filter( 'pre_option_job_manager_enable_types', '__return_true' );
118
  $this->post_types->register_post_types();
119
+ remove_filter( 'pre_option_job_manager_enable_types', '__return_true' );
120
  WP_Job_Manager_Install::install();
121
  flush_rewrite_rules();
122
  }
139
  load_plugin_textdomain( 'wp-job-manager', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
140
  }
141
 
142
+ /**
143
+ * Initialize our REST API.
144
+ *
145
+ * @return WP_Job_Manager_REST_API|WP_Error
146
+ */
147
+ public function rest_api() {
148
+ if ( null === $this->rest_api ) {
149
+ include( 'includes/rest-api/class-wp-job-manager-rest-api.php' );
150
+ $this->rest_api = new WP_Job_Manager_REST_API( dirname( __FILE__ ) );
151
+ $this->rest_api->init();
152
+ }
153
+ return $this->rest_api;
154
+ }
155
+
156
  /**
157
  * Loads plugin's core helper template functions.
158
  */
159
  public function include_template_functions() {
160
+ include_once( 'wp-job-manager-deprecated.php' );
161
+ include_once( 'wp-job-manager-functions.php' );
162
  include_once( 'wp-job-manager-template.php' );
163
  }
164