WP Job Manager - Version 1.29.1

Version Description

  • Enhancement: When retrieving listings in [jobs] shortcode, setting orderby to rand_featured will still place featured listings at the top. (@jom)
  • Enhancement: Scroll to show application details when clicking on "Apply for Job" button. (@jom)
  • Change: Updates account-signin.php template to warn users email will be confirmed only if that is enabled. (@jom)
  • Fix: Sanitize URLs and emails differently on the application method job listing field. (@jom)
  • Fix: Remove PHP notice in Featured Jobs widget. (@himanshuahuja96)
  • Fix: String fix for consistent spelling of "license" when appearing in strings. (@garrett-eclipse)
  • Fix: Issue with paid add-on licenses not showing up when some third-party plugins were installed. (@jom)
  • Dev: Runs new actions (job_manager_recent_jobs_widget_before and job_manager_recent_jobs_widget_after) inside Recent Jobs widget. (@jom)
  • Dev: Change wpjm_get_the_job_types() to return an empty array when job types are disabled. (@jom)
  • See all: https://github.com/Automattic/WP-Job-Manager/milestone/15?closed=1
Download this release

Release Info

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

Code changes from version 1.29.0 to 1.29.1

Files changed (47) hide show
  1. assets/js/job-application.js +36 -3
  2. assets/js/job-application.min.js +1 -1
  3. changelog.txt +89 -77
  4. includes/3rd-party/polylang.php +17 -0
  5. includes/abstracts/abstract-wp-job-manager-form.php +37 -8
  6. includes/admin/class-wp-job-manager-admin.php +6 -6
  7. includes/admin/class-wp-job-manager-writepanels.php +9 -9
  8. includes/forms/class-wp-job-manager-form-submit-job.php +5 -0
  9. includes/helper/class-wp-job-manager-helper.php +28 -9
  10. includes/rest-api/class-wp-job-manager-controllers-status.php +4 -4
  11. includes/rest-api/class-wp-job-manager-data-stores-status.php +1 -1
  12. includes/rest-api/class-wp-job-manager-filters-status.php +2 -2
  13. includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php +104 -0
  14. includes/rest-api/class-wp-job-manager-models-job-types-custom-fields.php +58 -0
  15. includes/rest-api/class-wp-job-manager-models-settings.php +4 -4
  16. includes/rest-api/class-wp-job-manager-models-status.php +3 -3
  17. includes/rest-api/class-wp-job-manager-registrable-job-listings.php +228 -0
  18. includes/rest-api/class-wp-job-manager-registrable-job-types.php +213 -0
  19. includes/rest-api/class-wp-job-manager-rest-api.php +29 -29
  20. includes/widgets/class-wp-job-manager-widget-featured-jobs.php +3 -3
  21. includes/widgets/class-wp-job-manager-widget-recent-jobs.php +22 -0
  22. languages/wp-job-manager.pot +105 -86
  23. lib/wpjm_rest/class-wp-job-manager-rest-bootstrap.php +29 -4
  24. lib/wpjm_rest/class-wp-job-manager-rest-environment.php +34 -8
  25. lib/wpjm_rest/class-wp-job-manager-rest-events.php +144 -0
  26. lib/wpjm_rest/class-wp-job-manager-rest-expect.php +12 -0
  27. lib/wpjm_rest/class-wp-job-manager-rest-model.php +81 -40
  28. lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-bundle.php +2 -2
  29. lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-crud.php +4 -4
  30. lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-model.php +10 -10
  31. lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-settings.php +3 -3
  32. lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-abstract.php +12 -13
  33. lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-customposttype.php +39 -15
  34. lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-option.php +6 -6
  35. lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-model.php +8 -8
  36. lib/wpjm_rest/interfaces/permissions/class-wp-job-manager-rest-interfaces-permissions-provider.php +1 -1
  37. lib/wpjm_rest/model/class-wp-job-manager-rest-model-factory.php +0 -175
  38. lib/wpjm_rest/model/class-wp-job-manager-rest-model-settings.php +17 -17
  39. lib/wpjm_rest/permissions/class-wp-job-manager-rest-permissions-any.php +1 -1
  40. lib/wpjm_rest/type/class-wp-job-manager-rest-type-model.php +74 -0
  41. lib/wpjm_rest/type/class-wp-job-manager-rest-type-registry.php +39 -10
  42. readme.txt +69 -82
  43. scripts/build_mixtape.sh +0 -118
  44. templates/account-signin.php +9 -5
  45. wp-job-manager-functions.php +41 -7
  46. wp-job-manager-template.php +4 -0
  47. wp-job-manager.php +21 -22
assets/js/job-application.js CHANGED
@@ -1,9 +1,42 @@
1
  jQuery(document).ready(function($) {
2
  // Slide toggle
3
  if ( ! $( 'body' ).hasClass( 'job-application-details-keep-open' ) ) {
4
- $('.application_details').hide();
5
  }
6
- $( '.application_button' ).click(function() {
7
- $( '.application_details' ).slideToggle();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  });
9
  });
1
  jQuery(document).ready(function($) {
2
  // Slide toggle
3
  if ( ! $( 'body' ).hasClass( 'job-application-details-keep-open' ) ) {
4
+ $( '.application_details' ).hide();
5
  }
6
+
7
+ $( 'body' ).on( 'click', '.job_application .application_button', function() {
8
+ var $details = $(this).siblings('.application_details').first();
9
+ var $button = $(this);
10
+ $details.slideToggle( 400, function() {
11
+ if ( ! $(this).is(':visible') ) {
12
+ // Only care if we toggled to be visible
13
+ return;
14
+ }
15
+
16
+ // If max(33% height, 200px) of the application details aren't shown, scroll.
17
+ var minimum_details_threshold = Math.max( Math.min( $details.outerHeight(), 200 ), $details.outerHeight() * .33 );
18
+ var details_visible_threshold = $details.offset().top + minimum_details_threshold;
19
+ var nice_buffer = 5;
20
+ var top_viewport_buffer = nice_buffer;
21
+ // We can't account for all theme headers with a fixed position on the top, but we can at least account for #wpadminbar and a fixed <header>
22
+ if ( $( '#wpadminbar' ).length > 0 && 'fixed' === $( '#wpadminbar' ).css( 'position' ) ) {
23
+ top_viewport_buffer += $( '#wpadminbar' ).outerHeight();
24
+ }
25
+ if ( $( 'header' ).length > 0 && 'fixed' === $( 'header' ).css( 'position' ) ) {
26
+ top_viewport_buffer += $( 'header' ).outerHeight();
27
+ }
28
+ var bottom_of_screen = $(window).scrollTop() + window.innerHeight;
29
+ var amount_hidden = $details.offset().top + $details.outerHeight() - bottom_of_screen;
30
+ var window_height = window.innerHeight - top_viewport_buffer;
31
+
32
+ if ( amount_hidden > 0 && $details.outerHeight() < ( window_height * .9 ) ) {
33
+ // Application contents are shorter than the 90% of viewport, just scroll to show the bottom of details (with `nice_buffer` buffer)
34
+ $('html, body').animate( { scrollTop: $(window).scrollTop() + amount_hidden + nice_buffer }, 400 );
35
+ } else if( bottom_of_screen < details_visible_threshold ){
36
+ // The application box is larger than the viewport AND our `minimum_details_threshold` is not visible.
37
+ // Scroll to show top of application button, showing top of details
38
+ $('html, body').animate( { scrollTop: $button.offset().top - top_viewport_buffer }, 600 );
39
+ }
40
+ });
41
  });
42
  });
assets/js/job-application.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(i){i("body").hasClass("job-application-details-keep-open")||i(".application_details").hide(),i(".application_button").click(function(){i(".application_details").slideToggle()})});
1
+ jQuery(document).ready(function(i){i("body").hasClass("job-application-details-keep-open")||i(".application_details").hide(),i("body").on("click",".job_application .application_button",function(){var t=i(this).siblings(".application_details").first(),o=i(this);t.slideToggle(400,function(){if(i(this).is(":visible")){var e=Math.max(Math.min(t.outerHeight(),200),.33*t.outerHeight()),a=t.offset().top+e,n=5;i("#wpadminbar").length>0&&"fixed"===i("#wpadminbar").css("position")&&(n+=i("#wpadminbar").outerHeight()),i("header").length>0&&"fixed"===i("header").css("position")&&(n+=i("header").outerHeight());var s=i(window).scrollTop()+window.innerHeight,l=t.offset().top+t.outerHeight()-s,p=window.innerHeight-n;l>0&&t.outerHeight()<.9*p?i("html, body").animate({scrollTop:i(window).scrollTop()+l+5},400):s<a&&i("html, body").animate({scrollTop:o.offset().top-n},600)}})})});
changelog.txt CHANGED
@@ -1,70 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 1.29.0 =
2
- * Enhancement: Moves license and update management for official add-ons to the core plugin. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1168)
3
- * Enhancement: Update language for setup wizard with more clear descriptions. (@donnapep; https://github.com/Automattic/WP-Job-Manager/pull/1194)
4
- * Fix: Prevent duplicate attachments to job listing posts for non-image media. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1144)
5
- * Fix: PHP error on registration form due to missing placeholder text. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1180)
6
- * Fix: Apply `the_job_application_method` filter even when no default is available. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/issues/1164)
7
- * Fix: Properly reset category selector on `[jobs]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1190)
8
 
9
  = 1.28.0 =
10
- * Enhancement: Improves support for Google Job Search by adding `JobPosting` structured data. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1115)
11
- * 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)
12
- * Enhancement: Requests search engines no longer index expired and filled job listings. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1120)
13
- * 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)
14
- * 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)
15
- * 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)
16
- * Fix: Localization issue with WPML in the [jobs] shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1129)
17
- * Fix: Show job listings' published date in localized format. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1118)
18
- * 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)
19
- * Fix: Some themes that overloaded functions would break in previous release. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1104)
20
- * 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)
21
- * 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)
22
  * 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)
23
 
24
  = 1.27.0 =
25
- * 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)
26
- * Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1024)
27
- * Enhancement: Allows users to override permalink slugs in WP Admin's Permalink Settings screen. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1042)
28
- * Enhancement: Allows admins to perform bulk updating of jobs as filled/not filled. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1049)
29
- * Enhancement: Adds job listing status CSS classes on single job listings. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1041)
30
- * Enhancement: Adds `wpjm_the_job_title` filter for inserting non-escaped HTML alongside job titles in templates. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1033)
31
- * Enhancement: Allows admins to filter by `post_status` in `[jobs]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1051)
32
- * Enhancement: Allows accessing settings tab from hash in URL. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/999)
33
- * Fix: Make sure cron jobs for checking/cleaning expired listings are always in place. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1058)
34
- * Fix: Better handling of multiple job types. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/1014)
35
- * Fix: Issue with deleting company logos from job listings submission form. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1047)
36
- * Fix: Warning thrown on job submission form when user not logged in. (@piersb; https://github.com/Automattic/WP-Job-Manager/pull/1011)
37
- * Fix: Issue with WPML not syncing some meta fields. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1027)
38
- * Fix: Better handling of AJAX upload errors. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1044)
39
- * Fix: Remove job posting cookies on logout. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1065)
40
- * Fix: Expiration date can be cleared if default job duration option is empty. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/1076)
41
- * Fix: Issue with Safari and expiration datepicker. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1078)
42
 
43
  = 1.26.2 =
44
- * Fix: Prevents use of Ajax file upload endpoint for visitors who aren't logged in. Themes should check with `job_manager_user_can_upload_file_via_ajax()` if using endpoint in templates. (https://github.com/Automattic/WP-Job-Manager/pull/1020)
45
- * Fix: Escape post title in WP Admin's Job Listings page and template segments. (Props to @EhsanCod3r; https://github.com/Automattic/WP-Job-Manager/pull/1026)
46
 
47
  = 1.26.1 =
48
- * Enhancement: Add language using WordPress's current locale to geocode requests. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1007)
49
- * Fix: Allow attempts to use Google Maps Geocode API without an API key. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/998)
50
- * Fix: Issue affecting job expiry date when editing a job listing. (@spencerfinnell, @jom; https://github.com/Automattic/WP-Job-Manager/pull/1008)
51
- * Fix: Show correct total count of results on `[jobs]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1006)
52
 
53
  = 1.26.0 =
54
- * Enhancement: Warn the user if they're editing an existing job. (@donnchawp; https://github.com/Automattic/WP-Job-Manager/pull/847)
55
- * Enhancement: WP Admin Job Listing page's table is now responsive. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/906)
56
- * Enhancement: New setting for hiding expired listings from `[jobs]` filter. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/903)
57
- * Enhancement: Use WP Query's built in search function to improve searching in `[jobs]`. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/960)
58
- * Fix: Job Listing filter only searches meta fields with relevant content. Add custom fields with `job_listing_searchable_meta_keys` filter. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/910)
59
- * Fix: Improved support for WPML and Polylang. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/963)
60
- * Fix: Expired field no longer forces admins to choose a date in the future. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/903)
61
- * Fix: Listings with expiration date in past will immediately expire; moving to Active status will extend if necessary. (@turtlepod, @jom; https://github.com/Automattic/WP-Job-Manager/pull/903, https://github.com/Automattic/WP-Job-Manager/pull/975)
62
- * Fix: Google Maps API key setting added to fix geolocation retrieval on new sites. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/912)
63
- * Fix: Issue when duplicating a job listing with a field for multiple file uploads. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/911)
64
- * Fix: Hide page results when adding links in the `[submit_job_form]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/922)
65
- * Fix: Job feed now loads when a site has no posts. (@dbtlr; https://github.com/Automattic/WP-Job-Manager/pull/870)
66
- * Fix: No error is thrown when deleting a user. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/875)
67
- * Dev: Plugins and themes can now retrieve JSON of Job Listings results without HTML. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/888)
68
  * Dev: Updated inline documentation.
69
 
70
  = 1.25.3 =
@@ -79,30 +91,30 @@
79
  * Fix: Fixed taxonomy search conditions. See https://github.com/automattic/wp-job-manager/pull/859/ Props Jonas Vogel.
80
 
81
  = 1.25.2 =
82
- * Fix - The date format of the expiry date picker was incorrect in translations so we added a comment to clarify, and fixed translations. (https://github.com/Automattic/WP-Job-Manager/issues/697)
83
- * Fix - Changing the date of an expired job would forget the date, even though the job would become active. (https://github.com/Automattic/WP-Job-Manager/issues/653)
84
- * Fix - Site owner can allow jobs to have only one or more than one types. (https://github.com/Automattic/WP-Job-Manager/issues/549)
85
- * Fix - Show expired jobs if that setting is enabled. (https://github.com/Automattic/WP-Job-Manager/issues/703)
86
- * Fix - Simplify the search message on the jobs page to avoid translation problems. (https://github.com/Automattic/WP-Job-Manager/issues/647)
87
- * Fix - The uploader would ignore WordPress created image sizes. (https://github.com/Automattic/WP-Job-Manager/issues/706)
88
- * Fix - setup.css was loaded on all admin pages. (https://github.com/Automattic/WP-Job-Manager/issues/728)
89
- * Fix - The preview of a listing could be edited or viewed by anyone. Props @tripflex (https://github.com/Automattic/WP-Job-Manager/issues/690)
90
- * Fix - When users were deleted their jobs weren't. (https://github.com/Automattic/WP-Job-Manager/issues/675)
91
- * Fix - OrderBy Rand wasn't working. (https://github.com/Automattic/WP-Job-Manager/issues/714)
92
- * Dev - Add upload filters and update PHPDocs, props @tripflex (https://github.com/Automattic/WP-Job-Manager/pull/747)
93
- * Fix - Stop using jQuery.live, props @tripflex (https://github.com/Automattic/WP-Job-Manager/pull/664)
94
 
95
  = 1.25.1 =
96
- * Feature - Adds a view button to the Admin UI for easy access to submitted files or URLs. Props tripflex (https://github.com/Automattic/WP-Job-Manager/pull/650)
97
  * Fix - Add hardening to file uploads to prevent accepting unexpected file times. Previously, other WP-allowed types were sometimes accepted.
98
- * Fix - Job post form categories are now properly cached and displayed per language when using WPML or Polylang. (https://github.com/Automattic/WP-Job-Manager/issues/692)
99
- * Fix - Refactored WPML workaround, which was causing no job listings on non-default languages. (https://github.com/Automattic/WP-Job-Manager/issues/617)
100
- * Fix - Allow employers to edit job listings when a listing is pending payment. (https://github.com/Automattic/WP-Job-Manager/pull/664)
101
- * Fix - No longer display Job Taxonomies in the WordPress tag cloud. (https://github.com/Automattic/WP-Job-Manager/pull/658)
102
- * Fix - Migrate away from jQuery.live, which is no longer supported. ( https://github.com/Automattic/WP-Job-Manager/pull/664 )
103
- * Tweak - Updated incorrect settings description. (https://github.com/Automattic/WP-Job-Manager/pull/632)
104
- * Dev - Adds hook to add items in a job's RSS feed item. (https://github.com/Automattic/WP-Job-Manager/pull/636)
105
- * Dev - Adds filter to disable Job Listings cache (https://github.com/Automattic/WP-Job-Manager/pull/684)
106
  * Dev - Inline docs and coding standards improvements.
107
 
108
  = 1.25.0 =
@@ -110,7 +122,7 @@
110
  * Fix - Support WP_EMBED in job descriptions.
111
  * Fix - Ensure logo is displayed on edit, before submission.
112
  * Fix - Attachment URLs on multisite.
113
- * Fix - Refactored WPML workaround, which was causing no job listings on non-default languages. (https://github.com/Automattic/WP-Job-Manager/issues/617)
114
  * Fix - No need to decode URLs anymore https://core.trac.wordpress.org/ticket/23605.
115
  * Dev - submit_job_form_end/submit_job_form_start actions.
116
  * Dev - job-manager-datepicker class for backend date fields.
1
+ = 1.29.1 =
2
+ * Enhancement: When retrieving listings in `[jobs]` shortcode, setting `orderby` to `rand_featured` will still place featured listings at the top. (@jom)
3
+ * Enhancement: Scroll to show application details when clicking on "Apply for Job" button. (@jom)
4
+ * Change: Updates `account-signin.php` template to warn users email will be confirmed only if that is enabled. (@jom)
5
+ * Fix: Sanitize URLs and emails differently on the application method job listing field. (@jom)
6
+ * Fix: Remove PHP notice in Featured Jobs widget. (@himanshuahuja96)
7
+ * Fix: String fix for consistent spelling of "license" when appearing in strings. (@garrett-eclipse)
8
+ * Fix: Issue with paid add-on licenses not showing up when some third-party plugins were installed. (@jom)
9
+ * Dev: Runs new actions (`job_manager_recent_jobs_widget_before` and `job_manager_recent_jobs_widget_after`) inside Recent Jobs widget. (@jom)
10
+ * Dev: Change `wpjm_get_the_job_types()` to return an empty array when job types are disabled. (@jom)
11
+ * See all: https://github.com/Automattic/WP-Job-Manager/milestone/15?closed=1
12
+
13
  = 1.29.0 =
14
+ * Enhancement: Moves license and update management for official add-ons to the core plugin. (@jom)
15
+ * Enhancement: Update language for setup wizard with more clear descriptions. (@donnapep)
16
+ * Fix: Prevent duplicate attachments to job listing posts for non-image media. (@tripflex)
17
+ * Fix: PHP error on registration form due to missing placeholder text. (@jom)
18
+ * Fix: Apply `the_job_application_method` filter even when no default is available. (@turtlepod)
19
+ * Fix: Properly reset category selector on `[jobs]` shortcode. (@jom)
20
 
21
  = 1.28.0 =
22
+ * Enhancement: Improves support for Google Job Search by adding `JobPosting` structured data. (@jom)
23
+ * Enhancement: Adds ability for job types to be mapped to an employment type as defined for Google Job Search. (@jom)
24
+ * Enhancement: Requests search engines no longer index expired and filled job listings. (@jom)
25
+ * Enhancement: Improves support with third-party sitemap generation in Jetpack, Yoast SEO, and All in One SEO. (@jom)
26
+ * Enhancement: Updated descriptions and help text on settings page. (@donnapep; Props to @michelleweber for updated copy)
27
+ * Enhancement: Lower cache expiration times across plugin and limit use of autoloaded cache transients. (@jom/files)
28
+ * Fix: Localization issue with WPML in the [jobs] shortcode. (@jom)
29
+ * Fix: Show job listings' published date in localized format. (@jom)
30
+ * Fix: Job submission form allows users to select multiple job types when they go back a step. (@jom)
31
+ * Fix: Some themes that overloaded functions would break in previous release. (@jom)
32
+ * Dev: Adds versions to template files so it is easier to tell when they are updated. (@jom)
33
+ * Dev: Adds a new `wpjm_notify_new_user` action that allows you to override default behavior. (@jom)
34
  * 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)
35
 
36
  = 1.27.0 =
37
+ * Enhancement: Admins can now allow users to specify an account password when posting their first job listing. (@jom)
38
+ * Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex)
39
+ * Enhancement: Allows users to override permalink slugs in WP Admin's Permalink Settings screen. (@jom)
40
+ * Enhancement: Allows admins to perform bulk updating of jobs as filled/not filled. (@jom)
41
+ * Enhancement: Adds job listing status CSS classes on single job listings. (@jom)
42
+ * Enhancement: Adds `wpjm_the_job_title` filter for inserting non-escaped HTML alongside job titles in templates. (@jom)
43
+ * Enhancement: Allows admins to filter by `post_status` in `[jobs]` shortcode. (@jom)
44
+ * Enhancement: Allows accessing settings tab from hash in URL. (@tripflex)
45
+ * Fix: Make sure cron jobs for checking/cleaning expired listings are always in place. (@jom)
46
+ * Fix: Better handling of multiple job types. (@spencerfinnell)
47
+ * Fix: Issue with deleting company logos from job listings submission form. (@jom)
48
+ * Fix: Warning thrown on job submission form when user not logged in. (@piersb)
49
+ * Fix: Issue with WPML not syncing some meta fields. (@jom)
50
+ * Fix: Better handling of AJAX upload errors. (@tripflex)
51
+ * Fix: Remove job posting cookies on logout. (@jom)
52
+ * Fix: Expiration date can be cleared if default job duration option is empty. (@spencerfinnell)
53
+ * Fix: Issue with Safari and expiration datepicker. (@jom)
54
 
55
  = 1.26.2 =
56
+ * Fix: Prevents use of Ajax file upload endpoint for visitors who aren't logged in. Themes should check with `job_manager_user_can_upload_file_via_ajax()` if using endpoint in templates.
57
+ * Fix: Escape post title in WP Admin's Job Listings page and template segments. (Props to @EhsanCod3r)
58
 
59
  = 1.26.1 =
60
+ * Enhancement: Add language using WordPress's current locale to geocode requests. (@jom)
61
+ * Fix: Allow attempts to use Google Maps Geocode API without an API key. (@spencerfinnell)
62
+ * Fix: Issue affecting job expiry date when editing a job listing. (@spencerfinnell, @jom)
63
+ * Fix: Show correct total count of results on `[jobs]` shortcode. (@jom)
64
 
65
  = 1.26.0 =
66
+ * Enhancement: Warn the user if they're editing an existing job. (@donnchawp)
67
+ * Enhancement: WP Admin Job Listing page's table is now responsive. (@turtlepod)
68
+ * Enhancement: New setting for hiding expired listings from `[jobs]` filter. (@turtlepod)
69
+ * Enhancement: Use WP Query's built in search function to improve searching in `[jobs]`. (@jom)
70
+ * Fix: Job Listing filter only searches meta fields with relevant content. Add custom fields with `job_listing_searchable_meta_keys` filter. (@turtlepod)
71
+ * Fix: Improved support for WPML and Polylang. (@jom)
72
+ * Fix: Expired field no longer forces admins to choose a date in the future. (@turtlepod)
73
+ * Fix: Listings with expiration date in past will immediately expire; moving to Active status will extend if necessary. (@turtlepod, @jom, https://github.com/Automattic/WP-Job-Manager/pull/975)
74
+ * Fix: Google Maps API key setting added to fix geolocation retrieval on new sites. (@jom)
75
+ * Fix: Issue when duplicating a job listing with a field for multiple file uploads. (@turtlepod)
76
+ * Fix: Hide page results when adding links in the `[submit_job_form]` shortcode. (@jom)
77
+ * Fix: Job feed now loads when a site has no posts. (@dbtlr)
78
+ * Fix: No error is thrown when deleting a user. (@tripflex)
79
+ * Dev: Plugins and themes can now retrieve JSON of Job Listings results without HTML. (@spencerfinnell)
80
  * Dev: Updated inline documentation.
81
 
82
  = 1.25.3 =
91
  * Fix: Fixed taxonomy search conditions. See https://github.com/automattic/wp-job-manager/pull/859/ Props Jonas Vogel.
92
 
93
  = 1.25.2 =
94
+ * Fix - The date format of the expiry date picker was incorrect in translations so we added a comment to clarify, and fixed translations.
95
+ * Fix - Changing the date of an expired job would forget the date, even though the job would become active.
96
+ * Fix - Site owner can allow jobs to have only one or more than one types.
97
+ * Fix - Show expired jobs if that setting is enabled.
98
+ * Fix - Simplify the search message on the jobs page to avoid translation problems.
99
+ * Fix - The uploader would ignore WordPress created image sizes.
100
+ * Fix - setup.css was loaded on all admin pages.
101
+ * Fix - The preview of a listing could be edited or viewed by anyone. Props @tripflex
102
+ * Fix - When users were deleted their jobs weren't.
103
+ * Fix - OrderBy Rand wasn't working.
104
+ * Dev - Add upload filters and update PHPDocs, props @tripflex
105
+ * Fix - Stop using jQuery.live, props @tripflex
106
 
107
  = 1.25.1 =
108
+ * Feature - Adds a view button to the Admin UI for easy access to submitted files or URLs. Props tripflex
109
  * Fix - Add hardening to file uploads to prevent accepting unexpected file times. Previously, other WP-allowed types were sometimes accepted.
110
+ * Fix - Job post form categories are now properly cached and displayed per language when using WPML or Polylang.
111
+ * Fix - Refactored WPML workaround, which was causing no job listings on non-default languages.
112
+ * Fix - Allow employers to edit job listings when a listing is pending payment.
113
+ * Fix - No longer display Job Taxonomies in the WordPress tag cloud.
114
+ * Fix - Migrate away from jQuery.live, which is no longer supported.
115
+ * Tweak - Updated incorrect settings description.
116
+ * Dev - Adds hook to add items in a job's RSS feed item.
117
+ * Dev - Adds filter to disable Job Listings cache
118
  * Dev - Inline docs and coding standards improvements.
119
 
120
  = 1.25.0 =
122
  * Fix - Support WP_EMBED in job descriptions.
123
  * Fix - Ensure logo is displayed on edit, before submission.
124
  * Fix - Attachment URLs on multisite.
125
+ * Fix - Refactored WPML workaround, which was causing no job listings on non-default languages.
126
  * Fix - No need to decode URLs anymore https://core.trac.wordpress.org/ticket/23605.
127
  * Dev - submit_job_form_end/submit_job_form_start actions.
128
  * Dev - job-manager-datepicker class for backend date fields.
includes/3rd-party/polylang.php CHANGED
@@ -11,9 +11,26 @@
11
  function polylang_wpjm_init() {
12
  add_filter( 'wpjm_lang', 'polylang_wpjm_get_job_listings_lang' );
13
  add_filter( 'wpjm_page_id', 'polylang_wpjm_page_id' );
 
14
  }
15
  add_action( 'pll_init', 'polylang_wpjm_init' );
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  /**
18
  * Returns Polylang's current language.
19
  *
11
  function polylang_wpjm_init() {
12
  add_filter( 'wpjm_lang', 'polylang_wpjm_get_job_listings_lang' );
13
  add_filter( 'wpjm_page_id', 'polylang_wpjm_page_id' );
14
+ add_action( 'get_job_listings_query_args', 'polylang_wpjm_query_language' );
15
  }
16
  add_action( 'pll_init', 'polylang_wpjm_init' );
17
 
18
+
19
+ /**
20
+ * Sets the current language when running job listings query.
21
+ *
22
+ * @since 1.29.1
23
+ *
24
+ * @param array $query_args
25
+ * @return array
26
+ */
27
+ function polylang_wpjm_query_language( $query_args ) {
28
+ if ( isset( $_POST['lang'] ) ) {
29
+ $query_args['lang'] = $_POST['lang'];
30
+ }
31
+ return $query_args;
32
+ }
33
+
34
  /**
35
  * Returns Polylang's current language.
36
  *
includes/abstracts/abstract-wp-job-manager-form.php CHANGED
@@ -283,14 +283,39 @@ abstract class WP_Job_Manager_Form {
283
  /**
284
  * Navigates through an array and sanitizes the field.
285
  *
286
- * @param array|string $value The array or string to be sanitized.
287
- * @return array|string $value The sanitized array (or string from the callback).
288
- */
289
- protected function sanitize_posted_field( $value ) {
290
- // Santize value
291
- $value = is_array( $value ) ? array_map( array( $this, 'sanitize_posted_field' ), $value ) : sanitize_text_field( stripslashes( trim( $value ) ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
 
293
- return $value;
 
 
 
 
 
 
 
294
  }
295
 
296
  /**
@@ -301,7 +326,11 @@ abstract class WP_Job_Manager_Form {
301
  * @return string|array
302
  */
303
  protected function get_posted_field( $key, $field ) {
304
- return isset( $_POST[ $key ] ) ? $this->sanitize_posted_field( $_POST[ $key ] ) : '';
 
 
 
 
305
  }
306
 
307
  /**
283
  /**
284
  * Navigates through an array and sanitizes the field.
285
  *
286
+ * @since 1.22.0
287
+ * @since 1.29.1 Added the $sanitizer argument
288
+ *
289
+ * @param array|string $value The array or string to be sanitized.
290
+ * @param string|callable $sanitizer The sanitization method to use. Built in: `url`, `email`, `url_or_email`, or
291
+ * default (text). Custom single argument callable allowed.
292
+ * @return array|string $value The sanitized array (or string from the callback).
293
+ */
294
+ protected function sanitize_posted_field( $value, $sanitizer = null ) {
295
+ // Sanitize value
296
+ if ( is_array( $value ) ) {
297
+ return array_map( array( $this, 'sanitize_posted_field' ), $value, $sanitizer );
298
+ }
299
+ $value = trim( $value );
300
+
301
+ if ( 'url' === $sanitizer ) {
302
+ return esc_url_raw( $value );
303
+ } elseif ( 'email' === $sanitizer ) {
304
+ return sanitize_email( $value );
305
+ } elseif ( 'url_or_email' === $sanitizer ) {
306
+ if ( null !== parse_url( $value, PHP_URL_HOST ) ) {
307
+ // Sanitize as URL
308
+ return esc_url_raw( $value );
309
+ }
310
 
311
+ // Sanitize as email
312
+ return sanitize_email( $value );
313
+ } elseif ( is_callable( $sanitizer ) ) {
314
+ return call_user_func( $sanitizer, $value );
315
+ }
316
+
317
+ // Use standard text sanitizer
318
+ return sanitize_text_field( stripslashes( $value ) );
319
  }
320
 
321
  /**
326
  * @return string|array
327
  */
328
  protected function get_posted_field( $key, $field ) {
329
+ // Allow custom sanitizers with standard text fields.
330
+ if ( ! isset( $field['sanitizer'] ) ) {
331
+ $field['sanitizer'] = null;
332
+ }
333
+ return isset( $_POST[ $key ] ) ? $this->sanitize_posted_field( $_POST[ $key ], $field['sanitizer'] ) : '';
334
  }
335
 
336
  /**
includes/admin/class-wp-job-manager-admin.php CHANGED
@@ -38,16 +38,16 @@ class WP_Job_Manager_Admin {
38
  public function __construct() {
39
  global $wp_version;
40
 
41
- include_once( 'class-wp-job-manager-cpt.php' );
42
  if ( version_compare( $wp_version, '4.7.0', '<' ) ) {
43
- include_once( 'class-wp-job-manager-cpt-legacy.php' );
44
  WP_Job_Manager_CPT_Legacy::instance();
45
  } else {
46
  WP_Job_Manager_CPT::instance();
47
  }
48
- include_once( 'class-wp-job-manager-settings.php' );
49
- include_once( 'class-wp-job-manager-writepanels.php' );
50
- include_once( 'class-wp-job-manager-setup.php' );
51
 
52
  $this->settings_page = WP_Job_Manager_Settings::instance();
53
 
@@ -61,7 +61,7 @@ class WP_Job_Manager_Admin {
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
  /**
38
  public function __construct() {
39
  global $wp_version;
40
 
41
+ include_once( dirname( __FILE__ ) . '/class-wp-job-manager-cpt.php' );
42
  if ( version_compare( $wp_version, '4.7.0', '<' ) ) {
43
+ include_once( dirname( __FILE__ ) . '/class-wp-job-manager-cpt-legacy.php' );
44
  WP_Job_Manager_CPT_Legacy::instance();
45
  } else {
46
  WP_Job_Manager_CPT::instance();
47
  }
48
+ include_once( dirname( __FILE__ ) . '/class-wp-job-manager-settings.php' );
49
+ include_once( dirname( __FILE__ ) . '/class-wp-job-manager-writepanels.php' );
50
+ include_once( dirname( __FILE__ ) . '/class-wp-job-manager-setup.php' );
51
 
52
  $this->settings_page = WP_Job_Manager_Settings::instance();
53
 
61
  * Set up actions during admin initialization.
62
  */
63
  public function admin_init() {
64
+ include_once( dirname( __FILE__ ) . '/class-wp-job-manager-taxonomy-meta.php' );
65
  }
66
 
67
  /**
includes/admin/class-wp-job-manager-writepanels.php CHANGED
@@ -251,7 +251,7 @@ class WP_Job_Manager_Writepanels {
251
  }
252
  ?>
253
  <p class="form-field">
254
- <label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
255
  <?php
256
  if ( ! empty( $field['multiple'] ) ) {
257
  foreach ( (array) $field['value'] as $value ) {
@@ -292,7 +292,7 @@ class WP_Job_Manager_Writepanels {
292
  }
293
  ?>
294
  <p class="form-field">
295
- <label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
296
  <input type="text" autocomplete="off" name="<?php echo esc_attr( $name ); ?>" class="<?php echo esc_attr( $classes ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo esc_attr( $field['value'] ); ?>" />
297
  </p>
298
  <?php
@@ -344,7 +344,7 @@ class WP_Job_Manager_Writepanels {
344
  }
345
  ?>
346
  <p class="form-field">
347
- <label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
348
  <?php if ( ! empty( $field['information'] ) ) : ?><span class="information"><?php echo wp_kses( $field['information'], array( 'a' => array( 'href' => array() ) ) ); ?></span><?php endif; ?>
349
  <?php echo $hidden_input; ?>
350
  </p>
@@ -370,7 +370,7 @@ class WP_Job_Manager_Writepanels {
370
  }
371
  ?>
372
  <p class="form-field">
373
- <label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
374
  <textarea name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>"><?php echo esc_html( $field['value'] ); ?></textarea>
375
  </p>
376
  <?php
@@ -395,7 +395,7 @@ class WP_Job_Manager_Writepanels {
395
  }
396
  ?>
397
  <p class="form-field">
398
- <label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
399
  <select name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>">
400
  <?php foreach ( $field['options'] as $key => $value ) : ?>
401
  <option value="<?php echo esc_attr( $key ); ?>" <?php if ( isset( $field['value'] ) ) selected( $field['value'], $key ); ?>><?php echo esc_html( $value ); ?></option>
@@ -424,7 +424,7 @@ class WP_Job_Manager_Writepanels {
424
  }
425
  ?>
426
  <p class="form-field">
427
- <label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
428
  <select multiple="multiple" name="<?php echo esc_attr( $name ); ?>[]" id="<?php echo esc_attr( $key ); ?>">
429
  <?php foreach ( $field['options'] as $key => $value ) : ?>
430
  <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>
@@ -453,7 +453,7 @@ class WP_Job_Manager_Writepanels {
453
  }
454
  ?>
455
  <p class="form-field form-field-checkbox">
456
- <label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ) ; ?></label>
457
  <input type="checkbox" class="checkbox" name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" value="1" <?php checked( $field['value'], 1 ); ?> />
458
  <?php if ( ! empty( $field['description'] ) ) : ?><span class="description"><?php echo $field['description']; ?></span><?php endif; ?>
459
  </p>
@@ -481,7 +481,7 @@ class WP_Job_Manager_Writepanels {
481
  $name = ! empty( $field['name'] ) ? $field['name'] : $key;
482
  ?>
483
  <p class="form-field form-field-author">
484
- <label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ) ; ?>:</label>
485
  <span class="current-author">
486
  <?php
487
  if ( $posted_by ) {
@@ -518,7 +518,7 @@ class WP_Job_Manager_Writepanels {
518
  }
519
  ?>
520
  <p class="form-field form-field-checkbox">
521
- <label><?php echo esc_html( $field['label'] ) ; ?></label>
522
  <?php foreach ( $field['options'] as $option_key => $value ) : ?>
523
  <label><input type="radio" class="radio" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" value="<?php echo esc_attr( $option_key ); ?>" <?php checked( $field['value'], $option_key ); ?> /> <?php echo esc_html( $value ); ?></label>
524
  <?php endforeach; ?>
251
  }
252
  ?>
253
  <p class="form-field">
254
+ <label for="<?php echo esc_attr( $key ); ?>"><?php echo wp_strip_all_tags( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
255
  <?php
256
  if ( ! empty( $field['multiple'] ) ) {
257
  foreach ( (array) $field['value'] as $value ) {
292
  }
293
  ?>
294
  <p class="form-field">
295
+ <label for="<?php echo esc_attr( $key ); ?>"><?php echo wp_strip_all_tags( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
296
  <input type="text" autocomplete="off" name="<?php echo esc_attr( $name ); ?>" class="<?php echo esc_attr( $classes ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo esc_attr( $field['value'] ); ?>" />
297
  </p>
298
  <?php
344
  }
345
  ?>
346
  <p class="form-field">
347
+ <label for="<?php echo esc_attr( $key ); ?>"><?php echo wp_strip_all_tags( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
348
  <?php if ( ! empty( $field['information'] ) ) : ?><span class="information"><?php echo wp_kses( $field['information'], array( 'a' => array( 'href' => array() ) ) ); ?></span><?php endif; ?>
349
  <?php echo $hidden_input; ?>
350
  </p>
370
  }
371
  ?>
372
  <p class="form-field">
373
+ <label for="<?php echo esc_attr( $key ); ?>"><?php echo wp_strip_all_tags( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
374
  <textarea name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>"><?php echo esc_html( $field['value'] ); ?></textarea>
375
  </p>
376
  <?php
395
  }
396
  ?>
397
  <p class="form-field">
398
+ <label for="<?php echo esc_attr( $key ); ?>"><?php echo wp_strip_all_tags( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
399
  <select name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>">
400
  <?php foreach ( $field['options'] as $key => $value ) : ?>
401
  <option value="<?php echo esc_attr( $key ); ?>" <?php if ( isset( $field['value'] ) ) selected( $field['value'], $key ); ?>><?php echo esc_html( $value ); ?></option>
424
  }
425
  ?>
426
  <p class="form-field">
427
+ <label for="<?php echo esc_attr( $key ); ?>"><?php echo wp_strip_all_tags( $field['label'] ) ; ?>: <?php if ( ! empty( $field['description'] ) ) : ?><span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span><?php endif; ?></label>
428
  <select multiple="multiple" name="<?php echo esc_attr( $name ); ?>[]" id="<?php echo esc_attr( $key ); ?>">
429
  <?php foreach ( $field['options'] as $key => $value ) : ?>
430
  <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>
453
  }
454
  ?>
455
  <p class="form-field form-field-checkbox">
456
+ <label for="<?php echo esc_attr( $key ); ?>"><?php echo wp_strip_all_tags( $field['label'] ) ; ?></label>
457
  <input type="checkbox" class="checkbox" name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" value="1" <?php checked( $field['value'], 1 ); ?> />
458
  <?php if ( ! empty( $field['description'] ) ) : ?><span class="description"><?php echo $field['description']; ?></span><?php endif; ?>
459
  </p>
481
  $name = ! empty( $field['name'] ) ? $field['name'] : $key;
482
  ?>
483
  <p class="form-field form-field-author">
484
+ <label for="<?php echo esc_attr( $key ); ?>"><?php echo wp_strip_all_tags( $field['label'] ) ; ?>:</label>
485
  <span class="current-author">
486
  <?php
487
  if ( $posted_by ) {
518
  }
519
  ?>
520
  <p class="form-field form-field-checkbox">
521
+ <label><?php echo wp_strip_all_tags( $field['label'] ) ; ?></label>
522
  <?php foreach ( $field['options'] as $option_key => $value ) : ?>
523
  <label><input type="radio" class="radio" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" value="<?php echo esc_attr( $option_key ); ?>" <?php checked( $field['value'], $option_key ); ?> /> <?php echo esc_html( $value ); ?></label>
524
  <?php endforeach; ?>
includes/forms/class-wp-job-manager-form-submit-job.php CHANGED
@@ -142,14 +142,17 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
142
  case 'email' :
143
  $application_method_label = __( 'Application email', 'wp-job-manager' );
144
  $application_method_placeholder = __( 'you@yourdomain.com', 'wp-job-manager' );
 
145
  break;
146
  case 'url' :
147
  $application_method_label = __( 'Application URL', 'wp-job-manager' );
148
  $application_method_placeholder = __( 'http://', 'wp-job-manager' );
 
149
  break;
150
  default :
151
  $application_method_label = __( 'Application email/URL', 'wp-job-manager' );
152
  $application_method_placeholder = __( 'Enter an email address or website URL', 'wp-job-manager' );
 
153
  break;
154
  }
155
 
@@ -202,6 +205,7 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
202
  'application' => array(
203
  'label' => $application_method_label,
204
  'type' => 'text',
 
205
  'required' => true,
206
  'placeholder' => $application_method_placeholder,
207
  'priority' => 6
@@ -218,6 +222,7 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
218
  'company_website' => array(
219
  'label' => __( 'Website', 'wp-job-manager' ),
220
  'type' => 'text',
 
221
  'required' => false,
222
  'placeholder' => __( 'http://', 'wp-job-manager' ),
223
  'priority' => 2
142
  case 'email' :
143
  $application_method_label = __( 'Application email', 'wp-job-manager' );
144
  $application_method_placeholder = __( 'you@yourdomain.com', 'wp-job-manager' );
145
+ $application_method_sanitizer = 'email';
146
  break;
147
  case 'url' :
148
  $application_method_label = __( 'Application URL', 'wp-job-manager' );
149
  $application_method_placeholder = __( 'http://', 'wp-job-manager' );
150
+ $application_method_sanitizer = 'url';
151
  break;
152
  default :
153
  $application_method_label = __( 'Application email/URL', 'wp-job-manager' );
154
  $application_method_placeholder = __( 'Enter an email address or website URL', 'wp-job-manager' );
155
+ $application_method_sanitizer = 'url_or_email';
156
  break;
157
  }
158
 
205
  'application' => array(
206
  'label' => $application_method_label,
207
  'type' => 'text',
208
+ 'sanitizer' => $application_method_sanitizer,
209
  'required' => true,
210
  'placeholder' => $application_method_placeholder,
211
  'priority' => 6
222
  'company_website' => array(
223
  'label' => __( 'Website', 'wp-job-manager' ),
224
  'type' => 'text',
225
+ 'sanitizer' => 'url',
226
  'required' => false,
227
  'placeholder' => __( 'http://', 'wp-job-manager' ),
228
  'priority' => 2
includes/helper/class-wp-job-manager-helper.php CHANGED
@@ -29,6 +29,12 @@ class WP_Job_Manager_Helper {
29
  */
30
  private static $_instance = null;
31
 
 
 
 
 
 
 
32
  /**
33
  * Allows for accessing single instance of class. Class should only be constructed once per call.
34
  *
@@ -47,8 +53,8 @@ class WP_Job_Manager_Helper {
47
  * Loads the class, runs on init.
48
  */
49
  public function init() {
50
- include_once( 'class-wp-job-manager-helper-options.php' );
51
- include_once( 'class-wp-job-manager-helper-api.php' );
52
 
53
  $this->api = WP_Job_Manager_Helper_API::instance();
54
 
@@ -256,7 +262,7 @@ class WP_Job_Manager_Helper {
256
  }
257
 
258
  /**
259
- * Returns the plugin info for a licenced WPJM plugin.
260
  *
261
  * @param string $product_slug
262
  *
@@ -318,7 +324,7 @@ class WP_Job_Manager_Helper {
318
  }
319
 
320
  /**
321
- * Gets the licence key and email for a WPJM managed plugin.
322
  *
323
  * @param string $product_slug
324
  * @return array|bool
@@ -347,7 +353,7 @@ class WP_Job_Manager_Helper {
347
  }
348
 
349
  /**
350
- * Returns list of installed WPJM plugins with managed licences indexed by product ID.
351
  *
352
  * @param bool $active_only Only return active plugins
353
  * @return array
@@ -357,6 +363,19 @@ class WP_Job_Manager_Helper {
357
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
358
  }
359
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
  $wpjm_plugins = array();
361
  $plugins = get_plugins();
362
 
@@ -375,7 +394,7 @@ class WP_Job_Manager_Helper {
375
  }
376
 
377
  /**
378
- * Outputs the licence management.
379
  */
380
  public function licence_output() {
381
  if ( ! current_user_can( 'update_plugins' ) ) {
@@ -389,7 +408,7 @@ class WP_Job_Manager_Helper {
389
  }
390
 
391
  /**
392
- * Outputs unset licence key notices.
393
  */
394
  public function licence_error_notices() {
395
  foreach( $this->get_installed_plugins() as $product_slug => $plugin_data ) {
@@ -401,7 +420,7 @@ class WP_Job_Manager_Helper {
401
  }
402
 
403
  /**
404
- * Handles a request on the manage licence key screen.
405
  */
406
  private function handle_request() {
407
  $licenced_plugins = $this->get_installed_plugins();
@@ -468,7 +487,7 @@ class WP_Job_Manager_Helper {
468
  private function deactivate_licence( $product_slug ) {
469
  $licence = $this->get_plugin_licence( $product_slug );
470
  if ( empty( $licence['licence_key'] ) || empty( $licence['email'] ) ) {
471
- $this->add_error( $product_slug, __( 'licence is not active.', 'wp-job-manager' ) );
472
  return;
473
  }
474
  $this->api->deactivate( array(
29
  */
30
  private static $_instance = null;
31
 
32
+ /**
33
+ * @var bool
34
+ * @since 1.29.1
35
+ */
36
+ private static $cleared_plugin_cache = false;
37
+
38
  /**
39
  * Allows for accessing single instance of class. Class should only be constructed once per call.
40
  *
53
  * Loads the class, runs on init.
54
  */
55
  public function init() {
56
+ include_once( dirname( __FILE__ ) . '/class-wp-job-manager-helper-options.php' );
57
+ include_once( dirname( __FILE__ ) . '/class-wp-job-manager-helper-api.php' );
58
 
59
  $this->api = WP_Job_Manager_Helper_API::instance();
60
 
262
  }
263
 
264
  /**
265
+ * Returns the plugin info for a licensed WPJM plugin.
266
  *
267
  * @param string $product_slug
268
  *
324
  }
325
 
326
  /**
327
+ * Gets the license key and email for a WPJM managed plugin.
328
  *
329
  * @param string $product_slug
330
  * @return array|bool
353
  }
354
 
355
  /**
356
+ * Returns list of installed WPJM plugins with managed licenses indexed by product ID.
357
  *
358
  * @param bool $active_only Only return active plugins
359
  * @return array
363
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
364
  }
365
 
366
+ /**
367
+ * Clear the plugin cache on first request for installed WPJM add-on plugins.
368
+ *
369
+ * @since 1.29.1
370
+ *
371
+ * @param bool $clear_plugin_cache True if we should clear the plugin cache.
372
+ */
373
+ if ( ! self::$cleared_plugin_cache && apply_filters( 'job_manager_clear_plugin_cache', true ) ) {
374
+ // Reset the plugin cache on the first call. Some plugins prematurely hydrate the cache.
375
+ wp_clean_plugins_cache( false );
376
+ self::$cleared_plugin_cache = true;
377
+ }
378
+
379
  $wpjm_plugins = array();
380
  $plugins = get_plugins();
381
 
394
  }
395
 
396
  /**
397
+ * Outputs the license management.
398
  */
399
  public function licence_output() {
400
  if ( ! current_user_can( 'update_plugins' ) ) {
408
  }
409
 
410
  /**
411
+ * Outputs unset license key notices.
412
  */
413
  public function licence_error_notices() {
414
  foreach( $this->get_installed_plugins() as $product_slug => $plugin_data ) {
420
  }
421
 
422
  /**
423
+ * Handles a request on the manage license key screen.
424
  */
425
  private function handle_request() {
426
  $licenced_plugins = $this->get_installed_plugins();
487
  private function deactivate_licence( $product_slug ) {
488
  $licence = $this->get_plugin_licence( $product_slug );
489
  if ( empty( $licence['licence_key'] ) || empty( $licence['email'] ) ) {
490
+ $this->add_error( $product_slug, __( 'license is not active.', 'wp-job-manager' ) );
491
  return;
492
  }
493
  $this->api->deactivate( array(
includes/rest-api/class-wp-job-manager-controllers-status.php CHANGED
@@ -44,7 +44,7 @@ class WP_Job_Manager_Controllers_Status extends WP_Job_Manager_REST_Controller_M
44
  return $this->bad_request( $filter );
45
  }
46
 
47
- $configuration = $this->get_model_factory()
48
  ->get_data_store()
49
  ->get_entity( null );
50
 
@@ -75,7 +75,7 @@ class WP_Job_Manager_Controllers_Status extends WP_Job_Manager_REST_Controller_M
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
 
@@ -106,11 +106,11 @@ class WP_Job_Manager_Controllers_Status extends WP_Job_Manager_REST_Controller_M
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
 
44
  return $this->bad_request( $filter );
45
  }
46
 
47
+ $configuration = $this->get_model_prototype()
48
  ->get_data_store()
49
  ->get_entity( null );
50
 
75
  */
76
  public function show( $request ) {
77
  $key = $request->get_param( 'key' );
78
+ $configuration = $this->get_model_prototype()
79
  ->get_data_store()
80
  ->get_entity( null );
81
 
106
  $key => $value,
107
  );
108
 
109
+ $configuration = $this->get_model_prototype()
110
  ->get_data_store()
111
  ->get_entity( '' );
112
  $configuration->update_from_array( $thing_to_update );
113
+ $result = $this->get_model_prototype()
114
  ->get_data_store()
115
  ->upsert( $configuration );
116
 
includes/rest-api/class-wp-job-manager-data-stores-status.php CHANGED
@@ -36,7 +36,7 @@ class WP_Job_Manager_Data_Stores_Status extends WP_Job_Manager_REST_Data_Store_A
36
  $params = array(
37
  'run_page_setup' => $should_run_page_setup,
38
  );
39
- return $this->get_model_factory()->create( $params );
40
  }
41
 
42
  /**
36
  $params = array(
37
  'run_page_setup' => $should_run_page_setup,
38
  );
39
+ return $this->get_model_prototype()->create( $params );
40
  }
41
 
42
  /**
includes/rest-api/class-wp-job-manager-filters-status.php CHANGED
@@ -20,8 +20,8 @@ class WP_Job_Manager_Filters_Status extends WP_Job_Manager_REST_Model {
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' ) )
20
  * @return array
21
  * @throws WP_Job_Manager_REST_Exception Exc.
22
  */
23
+ public function declare_fields() {
24
+ $env = $this->get_environment();
25
  return array(
26
  $env->field( 'keys', 'The status keys to return' )
27
  ->with_type( $env->type( 'array:string' ) )
includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Declaration of our Job Listings Custom Fields Model
4
+ *
5
+ * @package WPJM/REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_Models_Job_Listings_Custom_Fields
14
+ */
15
+ class WP_Job_Manager_Models_Job_Listings_Custom_Fields extends WP_Job_Manager_REST_Model {
16
+
17
+ /**
18
+ * Declare Fields
19
+ *
20
+ * @return array
21
+ * @throws WP_Job_Manager_REST_Exception Exc.
22
+ */
23
+ public function declare_fields() {
24
+ $env = $this->get_environment();
25
+ $current_user = wp_get_current_user();
26
+
27
+ $declarations = array(
28
+ $env->field( '_job_location', __( 'Leave this blank if the location is not important.', 'wp-job-manager' ) )
29
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
30
+ ->with_type( $env->type( 'string' ) ),
31
+
32
+ $env->field( '_application', __( 'Application Email or URL', 'wp-job-manager' ) )
33
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
34
+ ->with_default( $current_user->user_email )
35
+ ->with_type( $env->type( 'string' ) ),
36
+
37
+ $env->field( '_company_name', __( 'Company Name', 'wp-job-manager' ) )
38
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
39
+ ->with_type( $env->type( 'string' ) ),
40
+
41
+ $env->field( '_company_website', __( 'Company Website', 'wp-job-manager' ) )
42
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
43
+ ->with_type( $env->type( 'string' ) ),
44
+
45
+ $env->field( '_company_tagline', __( 'Company Tagline', 'wp-job-manager' ) )
46
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
47
+ ->with_type( $env->type( 'string' ) ),
48
+
49
+ $env->field( '_company_twitter', __( 'Company Twitter', 'wp-job-manager' ) )
50
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
51
+ ->with_type( $env->type( 'string' ) ),
52
+
53
+ $env->field( '_company_video', __( 'Company Video', 'wp-job-manager' ) )
54
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
55
+ ->with_type( $env->type( 'string' ) ),
56
+
57
+ $env->field( '_filled', __( 'Position Filled', 'wp-job-manager' ) )
58
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
59
+ ->with_type( $env->type( 'boolean' ) ),
60
+ );
61
+
62
+ // These caps are more related to updating.
63
+ if ( $current_user->has_cap( 'manage_job_listings' ) ) {
64
+ $declarations[] = $env->field( '_featured', __( 'Featured Listing', 'wp-job-manager' ) )
65
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
66
+ ->with_type( $env->type( 'boolean' ) );
67
+
68
+ $declarations[] = $env->field( '_job_expires', __( 'Listing Expiry Date', 'wp-job-manager' ) )
69
+ ->with_type( $env->type( 'string' ) )
70
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
71
+ ->with_before_get( 'format_job_expires' );
72
+ }
73
+
74
+ if ( $current_user->has_cap( 'edit_others_job_listings' ) ) {
75
+ $declarations[] = $env->field( '_job_author', __( 'Posted by', 'wp-job-manager' ) )
76
+ ->with_type( $env->type( 'string' ) )
77
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META );
78
+ }
79
+
80
+ /**
81
+ * Exposed so extension developers can add their custom fields.
82
+ *
83
+ * If the fields map to meta, you can follow the
84
+ * Example of the above declarations to shape s your own (remember to add any validation or formatting callbacks).
85
+ * For more constom things, you might want to check out Derived fields.
86
+ *
87
+ * @param array $declarations The Declarations so far.
88
+ * @param WP_Job_Manager_REST_Environment $env Environment.
89
+ *
90
+ * @return array
91
+ */
92
+ return (array) apply_filters( 'wpjm_rest_api_job_listings_declare_fields', $declarations, $env );
93
+ }
94
+
95
+ /**
96
+ * Format the date of Job_Expires
97
+ *
98
+ * @param mixed $value Value.
99
+ * @return bool|string
100
+ */
101
+ public function format_job_expires( $value ) {
102
+ return ! empty( $value ) ? date( 'Y-m-d H:i:s', strtotime( $value ) ) : '';
103
+ }
104
+ }
includes/rest-api/class-wp-job-manager-models-job-types-custom-fields.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Declaration of Job Types Custom Fields Model
4
+ *
5
+ * @package WPJM/REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_Models_Job_Types_Custom_Fields
14
+ */
15
+ class WP_Job_Manager_Models_Job_Types_Custom_Fields extends WP_Job_Manager_REST_Model
16
+ implements WP_Job_Manager_REST_Interfaces_Model {
17
+
18
+ /**
19
+ * Accepted employment types
20
+ *
21
+ * @var array
22
+ */
23
+ private static $accepted_employment_types = array();
24
+
25
+ /**
26
+ * Declare Fields
27
+ *
28
+ * @return array
29
+ */
30
+ public function declare_fields() {
31
+ $env = $this->get_environment();
32
+ $employment_types = wpjm_job_listing_employment_type_options();
33
+ self::$accepted_employment_types = array_keys( $employment_types );
34
+ return array(
35
+ $env->field( 'employment_type', __( 'Employment Type', 'wp-job-manager' ) )
36
+ ->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
37
+ ->with_type( $env->type( 'string' ) )
38
+ ->with_choices( self::$accepted_employment_types ),
39
+ );
40
+ }
41
+
42
+ /**
43
+ * Validate this
44
+ *
45
+ * @return bool|WP_Error
46
+ */
47
+ public function validate() {
48
+ $employment_type = $this->get( 'employment_type' );
49
+ if ( ! empty( $employment_type ) && ! in_array( $employment_type, self::$accepted_employment_types, true ) ) {
50
+ return new WP_Error('invalid_employment_type', __( 'Invalid Employment Type', 'wp-job-manager' ), array(
51
+ 'input' => $employment_type,
52
+ 'acceptable_values' => self::$accepted_employment_types,
53
+ 'status' => 400,
54
+ ) );
55
+ }
56
+ return parent::validate();
57
+ }
58
+ }
includes/rest-api/class-wp-job-manager-models-settings.php CHANGED
@@ -28,7 +28,7 @@ class WP_Job_Manager_Models_Settings extends WP_Job_Manager_REST_Model_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' ) ) {
@@ -49,7 +49,7 @@ class WP_Job_Manager_Models_Settings extends WP_Job_Manager_REST_Model_Settings
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' );
@@ -80,7 +80,7 @@ class WP_Job_Manager_Models_Settings extends WP_Job_Manager_REST_Model_Settings
80
  *
81
  * @return bool
82
  */
83
- public static function permissions_check( $request, $action ) {
84
  return current_user_can( 'manage_options' );
85
  }
86
 
@@ -89,7 +89,7 @@ class WP_Job_Manager_Models_Settings extends WP_Job_Manager_REST_Model_Settings
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',
28
  *
29
  * @return array
30
  */
31
+ public function get_settings() {
32
  if ( ! class_exists( 'WP_Job_Manager_Settings' ) ) {
33
  $parent = dirname( dirname( __FILE__ ) );
34
  if ( ! function_exists( 'get_editable_roles' ) ) {
49
  * @param array $field_data The field data.
50
  * @param WP_Job_Manager_REST_Environment $env The definition.
51
  */
52
+ protected 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' );
80
  *
81
  * @return bool
82
  */
83
+ public function permissions_check( $request, $action ) {
84
  return current_user_can( 'manage_options' );
85
  }
86
 
89
  *
90
  * @return array
91
  */
92
+ private 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',
includes/rest-api/class-wp-job-manager-models-status.php CHANGED
@@ -22,8 +22,8 @@ class WP_Job_Manager_Models_Status extends WP_Job_Manager_REST_Model
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' ) ),
@@ -37,7 +37,7 @@ class WP_Job_Manager_Models_Status extends WP_Job_Manager_REST_Model
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
  }
22
  * @return array
23
  * @throws WP_Job_Manager_REST_Exception Exc.
24
  */
25
+ public function declare_fields() {
26
+ $env = $this->get_environment();
27
  return array(
28
  $env->field( 'run_page_setup', 'Should we run page setup' )
29
  ->with_type( $env->type( 'boolean' ) ),
37
  * @param string $action The action (e.g. index, create update etc).
38
  * @return bool
39
  */
40
+ public function permissions_check( $request, $action ) {
41
  if ( in_array( $action, array( 'index', 'show' ), true ) ) {
42
  return true;
43
  }
includes/rest-api/class-wp-job-manager-registrable-job-listings.php ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Used for RESTifying the job_listing post type
4
+ *
5
+ * Adds custom fields. Needs a model definition that will provide the extra fields.
6
+ *
7
+ * @package WPJM/REST
8
+ */
9
+
10
+ /**
11
+ * Class MT_Controller_Extension
12
+ */
13
+ class WP_Job_Manager_Registrable_Job_Listings implements WP_Job_Manager_REST_Interfaces_Registrable {
14
+
15
+ /**
16
+ * Environment
17
+ *
18
+ * @var WP_Job_Manager_REST_Environment
19
+ */
20
+ private $environment;
21
+
22
+ /**
23
+ * Object to extend
24
+ *
25
+ * @var string
26
+ */
27
+ private $object_to_extend;
28
+
29
+ /**
30
+ * Model def.
31
+ *
32
+ * @var WP_Job_Manager_REST_Model_Factory
33
+ */
34
+ private $model_factory;
35
+
36
+ /**
37
+ * Model Definition name, This should be a valid Model definition at registration time, otherwise register throws
38
+ *
39
+ * @var string
40
+ */
41
+ private $model_class;
42
+
43
+ /**
44
+ * REST Field name, the field name we will nest under
45
+ *
46
+ * @var string
47
+ */
48
+ private $rest_field_name;
49
+
50
+ /**
51
+ * Constructor.
52
+ *
53
+ * @param string $object_to_extend Post type.
54
+ * @param string $model_class Model Class name.
55
+ * @param string $rest_field_name The REST field name.
56
+ */
57
+ public function __construct( $object_to_extend, $model_class, $rest_field_name ) {
58
+ $this->model_class = $model_class;
59
+ $this->object_to_extend = $object_to_extend;
60
+ $this->rest_field_name = $rest_field_name;
61
+ }
62
+
63
+ /**
64
+ * Register This Controller
65
+ *
66
+ * @param WP_Job_Manager_REST_Environment $environment The Environment to use.
67
+ * @throws WP_Job_Manager_REST_Exception Throws.
68
+ *
69
+ * @return bool|WP_Error true if valid otherwise error.
70
+ */
71
+ function register( $environment ) {
72
+ global $wp_post_types;
73
+ $post_type_name = $this->object_to_extend;
74
+ if ( ! isset( $wp_post_types[ $post_type_name ] ) ) {
75
+ return false;
76
+ }
77
+
78
+ if ( $wp_post_types[ $post_type_name ]->show_in_rest ) {
79
+ return true;
80
+ }
81
+
82
+ // Optionally customize the rest_base or controller class.
83
+ $wp_post_types[ $post_type_name ]->show_in_rest = true;
84
+ $wp_post_types[ $post_type_name ]->rest_base = 'job-listings';
85
+ $wp_post_types[ $post_type_name ]->rest_controller_class = 'WP_REST_Posts_Controller';
86
+
87
+ $this->environment = $environment;
88
+ $this->model_factory = $this->environment->model( $this->model_class );
89
+ if ( ! $this->model_factory ) {
90
+ return new WP_Error( 'model-not-found' );
91
+ }
92
+ register_rest_field( $this->object_to_extend, $this->rest_field_name, array(
93
+ 'get_callback' => array( $this, 'get_fields' ),
94
+ 'update_callback' => array( $this, 'update_fields' ),
95
+ 'schema' => $this->get_item_schema(),
96
+ ) );
97
+
98
+ return true;
99
+ }
100
+
101
+ /**
102
+ * Get Item Schema
103
+ *
104
+ * @return array
105
+ */
106
+ public function get_item_schema() {
107
+ $fields = $this->model_factory->get_fields();
108
+ $properties = array();
109
+ $required = array();
110
+ foreach ( $fields as $field_declaration ) {
111
+ /**
112
+ * Our declaration
113
+ *
114
+ * @var WP_Job_Manager_REST_Field_Declaration $field_declaration
115
+ */
116
+ $properties[ $field_declaration->get_data_transfer_name() ] = $field_declaration->as_item_schema_property();
117
+ if ( $field_declaration->is_required() ) {
118
+ $required[] = $field_declaration->get_data_transfer_name();
119
+ }
120
+ }
121
+ $schema = array(
122
+ '$schema' => 'http://json-schema.org/schema#',
123
+ 'title' => $this->model_factory->get_name(),
124
+ 'type' => 'object',
125
+ 'properties' => (array) apply_filters( 'mixtape_rest_api_schema_properties', $properties, $this->model_factory ),
126
+ );
127
+
128
+ if ( ! empty( $required ) ) {
129
+ $schema['required'] = $required;
130
+ }
131
+
132
+ return $schema;
133
+ }
134
+
135
+ /**
136
+ * Our Get Fields.
137
+ *
138
+ * @param array $object Object.
139
+ * @param string $field_name Field Name.
140
+ * @param WP_REST_Request $request Request.
141
+ * @param string $object_type Object Type.
142
+ *
143
+ * @return mixed|string
144
+ * @throws WP_Job_Manager_REST_Exception If type not there.
145
+ */
146
+ public function get_fields( $object, $field_name, $request, $object_type ) {
147
+ if ( 'job_listing' !== $object_type ) {
148
+ return null;
149
+ }
150
+
151
+ if ( $this->rest_field_name !== $field_name ) {
152
+ return null;
153
+ }
154
+
155
+ $object_id = absint( $object['id'] );
156
+ $model = $this->get_model( $object_id );
157
+ return $model->to_dto();
158
+ }
159
+
160
+ /**
161
+ * Get a model if exists
162
+ *
163
+ * @param int $object_id Object ID.
164
+ * @return WP_Job_Manager_REST_Interfaces_Model
165
+ * @throws WP_Job_Manager_REST_Exception On Error.
166
+ */
167
+ private function get_model( $object_id ) {
168
+ $data = array();
169
+ foreach ( $this->model_factory->get_fields() as $field_declaration ) {
170
+ $field_name = $field_declaration->get_name();
171
+ if ( metadata_exists( 'post', $object_id, $field_name ) ) {
172
+ $meta = get_post_meta( $object_id, $field_name, true );
173
+ $data[ $field_name ] = $meta;
174
+ }
175
+ }
176
+
177
+ return $this->model_factory->create( $data, array(
178
+ 'deserialize' => true,
179
+ ) );
180
+ }
181
+
182
+ /**
183
+ * Our Reader.
184
+ *
185
+ * @param mixed $data Data.
186
+ * @param array|object $object Object.
187
+ * @param string $field_name Field Name.
188
+ * @param WP_REST_Request $request Request.
189
+ * @param string $object_type Object Type.
190
+ *
191
+ * @return mixed|string
192
+ * @throws WP_Job_Manager_REST_Exception If type not there.
193
+ */
194
+ public function update_fields( $data, $object, $field_name, $request, $object_type ) {
195
+ if ( 'job_listing' !== $object_type ) {
196
+ return null;
197
+ }
198
+
199
+ if ( $this->rest_field_name !== $field_name ) {
200
+ return null;
201
+ }
202
+
203
+ $object_id = absint( $object->ID );
204
+ $existing_model = $this->get_model( $object_id );
205
+
206
+ $updated = $existing_model->update_from_array( $data );
207
+ if ( is_wp_error( $updated ) ) {
208
+ return $updated;
209
+ }
210
+
211
+ $maybe_validation_error = $updated->validate();
212
+ if ( is_wp_error( $maybe_validation_error ) ) {
213
+ return $maybe_validation_error;
214
+ }
215
+
216
+ $serialized_data = $updated->serialize( WP_Job_Manager_REST_Field_Declaration::META );
217
+
218
+ foreach ( $serialized_data as $field_name => $val ) {
219
+ if ( metadata_exists( 'post', $object_id, $field_name ) ) {
220
+ update_post_meta( $object_id, $field_name, $val );
221
+ } else {
222
+ add_post_meta( $object_id, $field_name, $val );
223
+ }
224
+ }
225
+
226
+ return true;
227
+ }
228
+ }
includes/rest-api/class-wp-job-manager-registrable-job-types.php ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Exposes Job Types Taxonomy REST Api
4
+ *
5
+ * @package WPJM/REST
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_Registrable_Job_Types
14
+ */
15
+ class WP_Job_Manager_Registrable_Job_Types implements WP_Job_Manager_REST_Interfaces_Registrable {
16
+
17
+ /**
18
+ * The Model Prototype
19
+ *
20
+ * @var WP_Job_Manager_REST_Model
21
+ */
22
+ private $model_prototype;
23
+
24
+ /**
25
+ * Rest Field Name
26
+ *
27
+ * @var string
28
+ */
29
+ private $rest_field_name;
30
+
31
+ /**
32
+ * Taxonomy Type
33
+ *
34
+ * @var string
35
+ */
36
+ private $taxonomy_type;
37
+
38
+ /**
39
+ * Register Job Types
40
+ *
41
+ * @param WP_Job_Manager_REST_Environment $environment The Environment to use.
42
+ * @throws WP_Job_Manager_REST_Exception Throws.
43
+ *
44
+ * @return bool|WP_Error true if valid otherwise error.
45
+ */
46
+ public function register( $environment ) {
47
+ global $wp_taxonomies;
48
+ $this->taxonomy_type = 'job_listing_type';
49
+ $this->rest_field_name = 'fields';
50
+
51
+ if ( ! isset( $wp_taxonomies[ $this->taxonomy_type ] ) ) {
52
+ return false;
53
+ }
54
+
55
+ if ( $wp_taxonomies[ $this->taxonomy_type ]->show_in_rest ) {
56
+ return true;
57
+ }
58
+
59
+ $wp_taxonomies[ $this->taxonomy_type ]->show_in_rest = true;
60
+ $wp_taxonomies[ $this->taxonomy_type ]->rest_base = 'job-types';
61
+
62
+ $this->model_prototype = $environment->model( 'WP_Job_Manager_Models_Job_Types_Custom_Fields' );
63
+
64
+ if ( ! $this->model_prototype ) {
65
+ return new WP_Error( 'model-not-found' );
66
+ }
67
+ register_rest_field( $this->taxonomy_type, $this->rest_field_name, array(
68
+ 'get_callback' => array( $this, 'get_employment_type' ),
69
+ 'update_callback' => array( $this, 'update_employment_type' ),
70
+ 'schema' => $this->get_item_schema(),
71
+ ) );
72
+
73
+ return true;
74
+ }
75
+
76
+ /**
77
+ * Get Item Schema
78
+ *
79
+ * @return array
80
+ */
81
+ public function get_item_schema() {
82
+ $fields = $this->model_prototype->get_fields();
83
+ $properties = array();
84
+ $required = array();
85
+ foreach ( $fields as $field_declaration ) {
86
+ /**
87
+ * Our declaration
88
+ *
89
+ * @var WP_Job_Manager_REST_Field_Declaration $field_declaration
90
+ */
91
+ $properties[ $field_declaration->get_data_transfer_name() ] = $field_declaration->as_item_schema_property();
92
+ if ( $field_declaration->is_required() ) {
93
+ $required[] = $field_declaration->get_data_transfer_name();
94
+ }
95
+ }
96
+ $schema = array(
97
+ '$schema' => 'http://json-schema.org/schema#',
98
+ 'title' => $this->model_prototype->get_name(),
99
+ 'type' => 'object',
100
+ 'properties' => (array) apply_filters( 'mixtape_rest_api_schema_properties', $properties, $this->model_prototype ),
101
+ );
102
+
103
+ if ( ! empty( $required ) ) {
104
+ $schema['required'] = $required;
105
+ }
106
+
107
+ return $schema;
108
+ }
109
+
110
+ /**
111
+ * Our Get Fields.
112
+ *
113
+ * @param array $object Object.
114
+ * @param string $field_name Field Name.
115
+ * @param WP_REST_Request $request Request.
116
+ * @param string $object_type Object Type.
117
+ *
118
+ * @return mixed|string
119
+ * @throws WP_Job_Manager_REST_Exception If type not there.
120
+ */
121
+ public function get_employment_type( $object, $field_name, $request, $object_type ) {
122
+ if ( $this->taxonomy_type !== $object_type ) {
123
+ return null;
124
+ }
125
+
126
+ if ( $this->rest_field_name !== $field_name ) {
127
+ return null;
128
+ }
129
+
130
+ $object_id = absint( $object['id'] );
131
+ $model = $this->get_model( $object_id );
132
+ return $model->to_dto();
133
+ }
134
+
135
+ /**
136
+ * Get a model if exists
137
+ *
138
+ * @param int $object_id Object ID.
139
+ * @return WP_Job_Manager_REST_Interfaces_Model
140
+ * @throws WP_Job_Manager_REST_Exception On Error.
141
+ */
142
+ private function get_model( $object_id ) {
143
+ $data = array();
144
+ foreach ( $this->model_prototype->get_fields( WP_Job_Manager_REST_Field_Declaration::META ) as $field_declaration ) {
145
+ $field_name = $field_declaration->get_name();
146
+ if ( metadata_exists( 'term', $object_id, $field_name ) ) {
147
+ $meta = get_term_meta( $object_id, $field_name, true );
148
+ $data[ $field_name ] = $meta;
149
+ }
150
+ }
151
+
152
+ return $this->model_prototype->create( $data, array(
153
+ 'deserialize' => true,
154
+ ) );
155
+ }
156
+
157
+ /**
158
+ * Our Reader.
159
+ *
160
+ * @param mixed $data Data.
161
+ * @param object $object Object.
162
+ * @param string $field_name Field Name.
163
+ * @param WP_REST_Request $request Request.
164
+ * @param string $object_type Object Type.
165
+ *
166
+ * @return mixed|string
167
+ * @throws WP_Job_Manager_REST_Exception If type not there.
168
+ */
169
+ public function update_employment_type( $data, $object, $field_name, $request, $object_type ) {
170
+ if ( $this->taxonomy_type !== $object_type ) {
171
+ return null;
172
+ }
173
+
174
+ if ( $this->rest_field_name !== $field_name ) {
175
+ return null;
176
+ }
177
+
178
+ if ( ! is_a( $object, 'WP_Term' ) ) {
179
+ return null;
180
+ }
181
+
182
+ $term_id = absint( $object->term_id );
183
+ if ( ! $term_id ) {
184
+ // No way to update this. Bail.
185
+ return new WP_Error( 'job-types-error-invalid-id', 'job-types-error-invalid-id', array(
186
+ 'status' => 400,
187
+ ) );
188
+ }
189
+ $existing_model = $this->get_model( $term_id );
190
+
191
+ $updated = $existing_model->update_from_array( $data );
192
+ if ( is_wp_error( $updated ) ) {
193
+ return $updated;
194
+ }
195
+
196
+ $maybe_validation_error = $updated->sanitize()->validate();
197
+ if ( is_wp_error( $maybe_validation_error ) ) {
198
+ return $maybe_validation_error;
199
+ }
200
+
201
+ $serialized_data = $updated->serialize( WP_Job_Manager_REST_Field_Declaration::META );
202
+
203
+ foreach ( $serialized_data as $field_name => $val ) {
204
+ if ( metadata_exists( 'term', $term_id, $field_name ) ) {
205
+ update_term_meta( $term_id, $field_name, $val );
206
+ } else {
207
+ add_term_meta( $term_id, $field_name, $val );
208
+ }
209
+ }
210
+
211
+ return true;
212
+ }
213
+ }
includes/rest-api/class-wp-job-manager-rest-api.php CHANGED
@@ -41,30 +41,16 @@ class WP_Job_Manager_REST_API {
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
  /**
@@ -85,14 +71,7 @@ class WP_Job_Manager_REST_API {
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
 
@@ -102,17 +81,38 @@ class WP_Job_Manager_REST_API {
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
 
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
  $file = $this->base_dir . 'lib/wpjm_rest/class-wp-job-manager-rest-bootstrap.php';
45
+ if ( file_exists( $file ) && $this->is_rest_api_enabled ) {
46
+ include_once $file;
47
+ $this->wpjm_rest_api = WP_Job_Manager_REST_Bootstrap::create();
48
+ $this->wpjm_rest_api
49
+ ->environment()
50
+ ->get_event_dispatcher()
51
+ ->add_action( 'environment_before_start', array( $this, 'define_api' ) );
52
+ $this->wpjm_rest_api->run();
 
53
  }
 
 
 
 
 
 
 
54
  }
55
 
56
  /**
71
  if ( ! $this->is_rest_api_enabled ) {
72
  return $this;
73
  }
 
 
 
 
 
74
  $this->define_api( $this->wpjm_rest_api->environment() );
 
 
75
  return $this;
76
  }
77
 
81
  * @param WP_Job_Manager_REST_Environment $env The Environment.
82
  */
83
  public function define_api( $env ) {
84
+ if ( ! is_a( $env, 'WP_Job_Manager_REST_Environment' ) ) {
85
+ return;
86
+ }
87
+
88
+ include_once 'class-wp-job-manager-models-settings.php';
89
+ include_once 'class-wp-job-manager-models-status.php';
90
+ include_once 'class-wp-job-manager-filters-status.php';
91
+ include_once 'class-wp-job-manager-data-stores-status.php';
92
+ include_once 'class-wp-job-manager-controllers-status.php';
93
+ include_once 'class-wp-job-manager-models-job-listings-custom-fields.php';
94
+ include_once 'class-wp-job-manager-models-job-types-custom-fields.php';
95
+ include_once 'class-wp-job-manager-registrable-job-listings.php';
96
+ include_once 'class-wp-job-manager-registrable-job-types.php';
97
+
98
  // Models.
99
  $env->define_model( 'WP_Job_Manager_Models_Settings' )
100
  ->with_data_store( new WP_Job_Manager_REST_Data_Store_Option( $env->model( 'WP_Job_Manager_Models_Settings' ) ) );
101
  $env->define_model( 'WP_Job_Manager_Models_Status' )
102
  ->with_data_store( new WP_Job_Manager_Data_Stores_Status( $env->model( 'WP_Job_Manager_Models_Status' ) ) );
103
  $env->define_model( 'WP_Job_Manager_Filters_Status' );
104
+ $env->define_model( 'WP_Job_Manager_Models_Job_Listings_Custom_Fields' );
105
+ $env->define_model( 'WP_Job_Manager_Models_Job_Types_Custom_Fields' );
106
 
107
  // Endpoints.
108
  $env->rest_api( 'wpjm/v1' )
109
  ->add_endpoint( new WP_Job_Manager_REST_Controller_Settings( '/settings', 'WP_Job_Manager_Models_Settings' ) )
110
  ->add_endpoint( new WP_Job_Manager_Controllers_Status( '/status', 'WP_Job_Manager_Models_Status' ) );
111
+ $env->add_registrable( new WP_Job_Manager_Registrable_Job_Listings(
112
+ 'job_listing',
113
+ 'WP_Job_Manager_Models_Job_Listings_Custom_Fields',
114
+ 'fields' ) );
115
+ $env->add_registrable( new WP_Job_Manager_Registrable_Job_Types() );
116
  }
117
  }
118
 
includes/widgets/class-wp-job-manager-widget-featured-jobs.php CHANGED
@@ -54,9 +54,9 @@ class WP_Job_Manager_Widget_Featured_Jobs extends WP_Job_Manager_Widget {
54
  ob_start();
55
 
56
  extract( $args );
57
-
58
- $title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
59
- $number = absint( $instance['number'] );
60
  $jobs = get_job_listings( array(
61
  'posts_per_page' => $number,
62
  'orderby' => 'date',
54
  ob_start();
55
 
56
  extract( $args );
57
+ $titleInstance = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
58
+ $number = isset( $instance['number'] ) ? absint( $instance['number'] ) : '';
59
+ $title = apply_filters( 'widget_title', $titleInstance, $instance, $this->id_base );
60
  $jobs = get_job_listings( array(
61
  'posts_per_page' => $number,
62
  'orderby' => 'date',
includes/widgets/class-wp-job-manager-widget-recent-jobs.php CHANGED
@@ -75,6 +75,17 @@ class WP_Job_Manager_Widget_Recent_Jobs extends WP_Job_Manager_Widget {
75
  'order' => 'DESC',
76
  ) );
77
 
 
 
 
 
 
 
 
 
 
 
 
78
  if ( $jobs->have_posts() ) : ?>
79
 
80
  <?php echo $before_widget; ?>
@@ -99,6 +110,17 @@ class WP_Job_Manager_Widget_Recent_Jobs extends WP_Job_Manager_Widget {
99
 
100
  <?php endif;
101
 
 
 
 
 
 
 
 
 
 
 
 
102
  wp_reset_postdata();
103
 
104
  $content = ob_get_clean();
75
  'order' => 'DESC',
76
  ) );
77
 
78
+ /**
79
+ * Runs before Recent Jobs widget content.
80
+ *
81
+ * @since 1.29.1
82
+ *
83
+ * @param array $args
84
+ * @param array $instance
85
+ * @param WP_Query $jobs
86
+ */
87
+ do_action( 'job_manager_recent_jobs_widget_before', $args, $instance, $jobs );
88
+
89
  if ( $jobs->have_posts() ) : ?>
90
 
91
  <?php echo $before_widget; ?>
110
 
111
  <?php endif;
112
 
113
+ /**
114
+ * Runs after Recent Jobs widget content.
115
+ *
116
+ * @since 1.29.1
117
+ *
118
+ * @param array $args
119
+ * @param array $instance
120
+ * @param WP_Query $jobs
121
+ */
122
+ do_action( 'job_manager_recent_jobs_widget_after', $args, $instance, $jobs );
123
+
124
  wp_reset_postdata();
125
 
126
  $content = ob_get_clean();
languages/wp-job-manager.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the GPL2+.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: WP Job Manager 1.29.0\n"
6
  "Report-Msgid-Bugs-To: https://github.com/Automattic/WP-Job-Manager/issues\n"
7
- "POT-Creation-Date: 2017-10-02 17:06:15+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -133,7 +133,7 @@ msgstr ""
133
 
134
  #: includes/admin/class-wp-job-manager-cpt.php:360
135
  #: includes/admin/class-wp-job-manager-writepanels.php:55
136
- #: includes/forms/class-wp-job-manager-form-submit-job.php:171
137
  #: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:38
138
  #: templates/job-filters.php:35 templates/job-filters.php:36
139
  msgid "Location"
@@ -740,19 +740,22 @@ msgstr ""
740
  #: includes/admin/class-wp-job-manager-taxonomy-meta.php:78
741
  #: includes/admin/class-wp-job-manager-taxonomy-meta.php:100
742
  #: includes/admin/class-wp-job-manager-taxonomy-meta.php:118
 
743
  msgid "Employment Type"
744
  msgstr ""
745
 
746
  #: includes/admin/class-wp-job-manager-writepanels.php:56
747
- #: includes/forms/class-wp-job-manager-form-submit-job.php:175
748
  msgid "e.g. \"London\""
749
  msgstr ""
750
 
751
  #: includes/admin/class-wp-job-manager-writepanels.php:57
 
752
  msgid "Leave this blank if the location is not important."
753
  msgstr ""
754
 
755
  #: includes/admin/class-wp-job-manager-writepanels.php:61
 
756
  msgid "Application Email or URL"
757
  msgstr ""
758
 
@@ -767,14 +770,17 @@ msgid ""
767
  msgstr ""
768
 
769
  #: includes/admin/class-wp-job-manager-writepanels.php:68
 
770
  msgid "Company Name"
771
  msgstr ""
772
 
773
  #: includes/admin/class-wp-job-manager-writepanels.php:73
 
774
  msgid "Company Website"
775
  msgstr ""
776
 
777
  #: includes/admin/class-wp-job-manager-writepanels.php:78
 
778
  msgid "Company Tagline"
779
  msgstr ""
780
 
@@ -783,10 +789,12 @@ msgid "Brief description about the company"
783
  msgstr ""
784
 
785
  #: includes/admin/class-wp-job-manager-writepanels.php:83
 
786
  msgid "Company Twitter"
787
  msgstr ""
788
 
789
  #: includes/admin/class-wp-job-manager-writepanels.php:88
 
790
  msgid "Company Video"
791
  msgstr ""
792
 
@@ -795,6 +803,7 @@ msgid "URL to the company video"
795
  msgstr ""
796
 
797
  #: includes/admin/class-wp-job-manager-writepanels.php:94
 
798
  msgid "Position Filled"
799
  msgstr ""
800
 
@@ -803,6 +812,7 @@ msgid "Filled listings will no longer accept applications."
803
  msgstr ""
804
 
805
  #: includes/admin/class-wp-job-manager-writepanels.php:102
 
806
  msgid "Featured Listing"
807
  msgstr ""
808
 
@@ -813,10 +823,12 @@ msgid ""
813
  msgstr ""
814
 
815
  #: includes/admin/class-wp-job-manager-writepanels.php:109
 
816
  msgid "Listing Expiry Date"
817
  msgstr ""
818
 
819
  #: includes/admin/class-wp-job-manager-writepanels.php:119
 
820
  msgid "Posted by"
821
  msgstr ""
822
 
@@ -885,7 +897,7 @@ msgid "Employer"
885
  msgstr ""
886
 
887
  #: includes/class-wp-job-manager-post-types.php:98
888
- #: includes/forms/class-wp-job-manager-form-submit-job.php:188
889
  msgid "Job category"
890
  msgstr ""
891
 
@@ -938,7 +950,7 @@ msgid "New %s Name"
938
  msgstr ""
939
 
940
  #: includes/class-wp-job-manager-post-types.php:147
941
- #: includes/forms/class-wp-job-manager-form-submit-job.php:179
942
  msgid "Job type"
943
  msgstr ""
944
 
@@ -1081,7 +1093,7 @@ msgid "Submit Details"
1081
  msgstr ""
1082
 
1083
  #: includes/forms/class-wp-job-manager-form-submit-job.php:69
1084
- #: includes/forms/class-wp-job-manager-form-submit-job.php:434
1085
  #: templates/job-preview.php:22
1086
  msgid "Preview"
1087
  msgstr ""
@@ -1095,134 +1107,134 @@ msgid "Application email"
1095
  msgstr ""
1096
 
1097
  #: includes/forms/class-wp-job-manager-form-submit-job.php:144
1098
- #: wp-job-manager-template.php:642
1099
  msgid "you@yourdomain.com"
1100
  msgstr ""
1101
 
1102
- #: includes/forms/class-wp-job-manager-form-submit-job.php:147
1103
  msgid "Application URL"
1104
  msgstr ""
1105
 
1106
- #: includes/forms/class-wp-job-manager-form-submit-job.php:148
1107
- #: includes/forms/class-wp-job-manager-form-submit-job.php:222
1108
  msgid "http://"
1109
  msgstr ""
1110
 
1111
- #: includes/forms/class-wp-job-manager-form-submit-job.php:151
1112
  msgid "Application email/URL"
1113
  msgstr ""
1114
 
1115
- #: includes/forms/class-wp-job-manager-form-submit-job.php:152
1116
  msgid "Enter an email address or website URL"
1117
  msgstr ""
1118
 
1119
- #: includes/forms/class-wp-job-manager-form-submit-job.php:164
1120
  msgid "Job Title"
1121
  msgstr ""
1122
 
1123
- #: includes/forms/class-wp-job-manager-form-submit-job.php:172
1124
  msgid "Leave this blank if the location is not important"
1125
  msgstr ""
1126
 
1127
- #: includes/forms/class-wp-job-manager-form-submit-job.php:182
1128
  msgid "Choose job type&hellip;"
1129
  msgstr ""
1130
 
1131
- #: includes/forms/class-wp-job-manager-form-submit-job.php:197
1132
  msgid "Description"
1133
  msgstr ""
1134
 
1135
- #: includes/forms/class-wp-job-manager-form-submit-job.php:212
1136
  msgid "Company name"
1137
  msgstr ""
1138
 
1139
- #: includes/forms/class-wp-job-manager-form-submit-job.php:215
1140
  msgid "Enter the name of the company"
1141
  msgstr ""
1142
 
1143
- #: includes/forms/class-wp-job-manager-form-submit-job.php:219
1144
  #: templates/content-single-job_listing-company.php:30
1145
  msgid "Website"
1146
  msgstr ""
1147
 
1148
- #: includes/forms/class-wp-job-manager-form-submit-job.php:226
1149
  msgid "Tagline"
1150
  msgstr ""
1151
 
1152
- #: includes/forms/class-wp-job-manager-form-submit-job.php:229
1153
  msgid "Briefly describe your company"
1154
  msgstr ""
1155
 
1156
- #: includes/forms/class-wp-job-manager-form-submit-job.php:234
1157
  msgid "Video"
1158
  msgstr ""
1159
 
1160
- #: includes/forms/class-wp-job-manager-form-submit-job.php:237
1161
  msgid "A link to a video about your company"
1162
  msgstr ""
1163
 
1164
- #: includes/forms/class-wp-job-manager-form-submit-job.php:241
1165
  msgid "Twitter username"
1166
  msgstr ""
1167
 
1168
- #: includes/forms/class-wp-job-manager-form-submit-job.php:244
1169
  msgid "@yourcompany"
1170
  msgstr ""
1171
 
1172
- #: includes/forms/class-wp-job-manager-form-submit-job.php:248
1173
  msgid "Logo"
1174
  msgstr ""
1175
 
1176
- #: includes/forms/class-wp-job-manager-form-submit-job.php:284
1177
  msgid "%s is a required field"
1178
  msgstr ""
1179
 
1180
- #: includes/forms/class-wp-job-manager-form-submit-job.php:294
1181
  msgid "%s is invalid"
1182
  msgstr ""
1183
 
1184
- #: includes/forms/class-wp-job-manager-form-submit-job.php:310
1185
- #: wp-job-manager-functions.php:1002
1186
  msgid "\"%s\" (filetype %s) needs to be one of the following file types: %s"
1187
  msgstr ""
1188
 
1189
- #: includes/forms/class-wp-job-manager-form-submit-job.php:325
1190
  msgid "Please enter a valid application email address"
1191
  msgstr ""
1192
 
1193
- #: includes/forms/class-wp-job-manager-form-submit-job.php:334
1194
  msgid "Please enter a valid application URL"
1195
  msgstr ""
1196
 
1197
- #: includes/forms/class-wp-job-manager-form-submit-job.php:344
1198
  msgid "Please enter a valid application email address or URL"
1199
  msgstr ""
1200
 
1201
- #: includes/forms/class-wp-job-manager-form-submit-job.php:465
1202
  msgid "Please enter a username."
1203
  msgstr ""
1204
 
1205
- #: includes/forms/class-wp-job-manager-form-submit-job.php:469
1206
  msgid "Please enter a password."
1207
  msgstr ""
1208
 
1209
- #: includes/forms/class-wp-job-manager-form-submit-job.php:473
1210
  msgid "Please enter your email address."
1211
  msgstr ""
1212
 
1213
- #: includes/forms/class-wp-job-manager-form-submit-job.php:479
1214
  msgid "Passwords must match."
1215
  msgstr ""
1216
 
1217
- #: includes/forms/class-wp-job-manager-form-submit-job.php:484
1218
  msgid "Invalid Password: %s"
1219
  msgstr ""
1220
 
1221
- #: includes/forms/class-wp-job-manager-form-submit-job.php:486
1222
  msgid "Password is not valid."
1223
  msgstr ""
1224
 
1225
- #: includes/forms/class-wp-job-manager-form-submit-job.php:507
1226
  msgid "You must be signed in to post a new listing."
1227
  msgstr ""
1228
 
@@ -1254,7 +1266,7 @@ msgid "An unknown error occurred while attempting to activate the license"
1254
  msgstr ""
1255
 
1256
  #: includes/helper/class-wp-job-manager-helper.php:471
1257
- msgid "licence is not active."
1258
  msgstr ""
1259
 
1260
  #: includes/helper/class-wp-job-manager-helper.php:485
@@ -1287,6 +1299,10 @@ msgstr ""
1287
  msgid "Not Found"
1288
  msgstr ""
1289
 
 
 
 
 
1290
  #: includes/rest-api/class-wp-job-manager-models-settings.php:72
1291
  msgid "Invalid page ID provided"
1292
  msgstr ""
@@ -1320,7 +1336,7 @@ msgstr ""
1320
  msgid "Keyword"
1321
  msgstr ""
1322
 
1323
- #: lib/wpjm_rest/class-wp-job-manager-rest-model.php:207
1324
  #. translators: %s is usually a field name.
1325
  msgid "%s cannot be empty"
1326
  msgstr ""
@@ -1345,30 +1361,33 @@ msgstr ""
1345
  msgid "Sign out"
1346
  msgstr ""
1347
 
1348
- #: templates/account-signin.php:38
1349
  msgid "Have an account?"
1350
  msgstr ""
1351
 
1352
- #: templates/account-signin.php:40 templates/job-dashboard-login.php:20
1353
  msgid "Sign in"
1354
  msgstr ""
1355
 
1356
- #: templates/account-signin.php:44
1357
  msgid ""
1358
  "If you don&rsquo;t have an account you can %screate one below by entering "
1359
- "your email address/username. Your account details will be confirmed via "
1360
- "email."
1361
  msgstr ""
1362
 
1363
- #: templates/account-signin.php:44
1364
  msgid "optionally"
1365
  msgstr ""
1366
 
1367
- #: templates/account-signin.php:48
 
 
 
 
1368
  msgid "You must sign in to create a new listing."
1369
  msgstr ""
1370
 
1371
- #: templates/account-signin.php:59 templates/job-submit.php:43
1372
  #: templates/job-submit.php:60
1373
  msgid "(optional)"
1374
  msgstr ""
@@ -1398,12 +1417,12 @@ msgid "Maximum file size: %s."
1398
  msgstr ""
1399
 
1400
  #: templates/form-fields/multiselect-field.php:20
1401
- #: wp-job-manager-functions.php:790
1402
  msgid "No results match"
1403
  msgstr ""
1404
 
1405
  #: templates/form-fields/multiselect-field.php:20
1406
- #: wp-job-manager-functions.php:791
1407
  msgid "Select Some Options"
1408
  msgstr ""
1409
 
@@ -1500,67 +1519,67 @@ msgstr ""
1500
  msgid "%s submitted successfully. Your listing will be visible once approved."
1501
  msgstr ""
1502
 
1503
- #: wp-job-manager-functions.php:361
1504
  msgid "Reset"
1505
  msgstr ""
1506
 
1507
- #: wp-job-manager-functions.php:365
1508
  msgid "RSS"
1509
  msgstr ""
1510
 
1511
- #: wp-job-manager-functions.php:460
1512
  msgid "Invalid email address."
1513
  msgstr ""
1514
 
1515
- #: wp-job-manager-functions.php:468
1516
  msgid "Your email address isn&#8217;t correct."
1517
  msgstr ""
1518
 
1519
- #: wp-job-manager-functions.php:472
1520
  msgid "This email is already registered, please choose another one."
1521
  msgstr ""
1522
 
1523
- #: wp-job-manager-functions.php:633
1524
  msgid "Full Time"
1525
  msgstr ""
1526
 
1527
- #: wp-job-manager-functions.php:634
1528
  msgid "Part Time"
1529
  msgstr ""
1530
 
1531
- #: wp-job-manager-functions.php:635
1532
  msgid "Contractor"
1533
  msgstr ""
1534
 
1535
- #: wp-job-manager-functions.php:636
1536
  msgid "Temporary"
1537
  msgstr ""
1538
 
1539
- #: wp-job-manager-functions.php:637
1540
  msgid "Intern"
1541
  msgstr ""
1542
 
1543
- #: wp-job-manager-functions.php:638
1544
  msgid "Volunteer"
1545
  msgstr ""
1546
 
1547
- #: wp-job-manager-functions.php:639
1548
  msgid "Per Diem"
1549
  msgstr ""
1550
 
1551
- #: wp-job-manager-functions.php:640
1552
  msgid "Other"
1553
  msgstr ""
1554
 
1555
- #: wp-job-manager-functions.php:707
1556
  msgid "Passwords must be at least 8 characters long."
1557
  msgstr ""
1558
 
1559
- #: wp-job-manager-functions.php:789
1560
  msgid "Choose a category&hellip;"
1561
  msgstr ""
1562
 
1563
- #: wp-job-manager-functions.php:1004
1564
  msgid "Uploaded files need to be one of the following file types: %s"
1565
  msgstr ""
1566
 
@@ -1572,43 +1591,43 @@ msgstr ""
1572
  msgid "Application via \"%s\" listing on %s"
1573
  msgstr ""
1574
 
1575
- #: wp-job-manager-template.php:616
1576
  msgid "Username"
1577
  msgstr ""
1578
 
1579
- #: wp-job-manager-template.php:624
1580
  msgid "Password"
1581
  msgstr ""
1582
 
1583
- #: wp-job-manager-template.php:634
1584
  msgid "Verify Password"
1585
  msgstr ""
1586
 
1587
- #: wp-job-manager-template.php:641
1588
  msgid "Your email"
1589
  msgstr ""
1590
 
1591
- #: wp-job-manager-template.php:668
1592
  msgid "Posted on "
1593
  msgstr ""
1594
 
1595
- #: wp-job-manager-template.php:670 wp-job-manager-template.php:690
1596
  msgid "Posted %s ago"
1597
  msgstr ""
1598
 
1599
- #: wp-job-manager-template.php:713
1600
  msgid "Anywhere"
1601
  msgstr ""
1602
 
1603
- #: wp-job-manager.php:213
1604
  msgid "Load previous listings"
1605
  msgstr ""
1606
 
1607
- #: wp-job-manager.php:264
1608
  msgid "Invalid file type. Accepted types:"
1609
  msgstr ""
1610
 
1611
- #: wp-job-manager.php:275
1612
  msgid "Are you sure you want to delete this listing?"
1613
  msgstr ""
1614
 
@@ -1682,33 +1701,33 @@ msgid "jobs"
1682
  msgstr ""
1683
 
1684
  #: includes/class-wp-job-manager-post-types.php:261
1685
- #: wp-job-manager-functions.php:256
1686
  msgctxt "post status"
1687
  msgid "Expired"
1688
  msgstr ""
1689
 
1690
  #: includes/class-wp-job-manager-post-types.php:270
1691
- #: wp-job-manager-functions.php:257
1692
  msgctxt "post status"
1693
  msgid "Preview"
1694
  msgstr ""
1695
 
1696
- #: wp-job-manager-functions.php:255
1697
  msgctxt "post status"
1698
  msgid "Draft"
1699
  msgstr ""
1700
 
1701
- #: wp-job-manager-functions.php:258
1702
  msgctxt "post status"
1703
  msgid "Pending approval"
1704
  msgstr ""
1705
 
1706
- #: wp-job-manager-functions.php:259
1707
  msgctxt "post status"
1708
  msgid "Pending payment"
1709
  msgstr ""
1710
 
1711
- #: wp-job-manager-functions.php:260
1712
  msgctxt "post status"
1713
  msgid "Active"
1714
- msgstr ""
2
  # This file is distributed under the GPL2+.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: WP Job Manager 1.29.1\n"
6
  "Report-Msgid-Bugs-To: https://github.com/Automattic/WP-Job-Manager/issues\n"
7
+ "POT-Creation-Date: 2017-11-27 12:20:43+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
133
 
134
  #: includes/admin/class-wp-job-manager-cpt.php:360
135
  #: includes/admin/class-wp-job-manager-writepanels.php:55
136
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:174
137
  #: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:38
138
  #: templates/job-filters.php:35 templates/job-filters.php:36
139
  msgid "Location"
740
  #: includes/admin/class-wp-job-manager-taxonomy-meta.php:78
741
  #: includes/admin/class-wp-job-manager-taxonomy-meta.php:100
742
  #: includes/admin/class-wp-job-manager-taxonomy-meta.php:118
743
+ #: includes/rest-api/class-wp-job-manager-models-job-types-custom-fields.php:35
744
  msgid "Employment Type"
745
  msgstr ""
746
 
747
  #: includes/admin/class-wp-job-manager-writepanels.php:56
748
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:178
749
  msgid "e.g. \"London\""
750
  msgstr ""
751
 
752
  #: includes/admin/class-wp-job-manager-writepanels.php:57
753
+ #: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:28
754
  msgid "Leave this blank if the location is not important."
755
  msgstr ""
756
 
757
  #: includes/admin/class-wp-job-manager-writepanels.php:61
758
+ #: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:32
759
  msgid "Application Email or URL"
760
  msgstr ""
761
 
770
  msgstr ""
771
 
772
  #: includes/admin/class-wp-job-manager-writepanels.php:68
773
+ #: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:37
774
  msgid "Company Name"
775
  msgstr ""
776
 
777
  #: includes/admin/class-wp-job-manager-writepanels.php:73
778
+ #: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:41
779
  msgid "Company Website"
780
  msgstr ""
781
 
782
  #: includes/admin/class-wp-job-manager-writepanels.php:78
783
+ #: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:45
784
  msgid "Company Tagline"
785
  msgstr ""
786
 
789
  msgstr ""
790
 
791
  #: includes/admin/class-wp-job-manager-writepanels.php:83
792
+ #: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:49
793
  msgid "Company Twitter"
794
  msgstr ""
795
 
796
  #: includes/admin/class-wp-job-manager-writepanels.php:88
797
+ #: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:53
798
  msgid "Company Video"
799
  msgstr ""
800
 
803
  msgstr ""
804
 
805
  #: includes/admin/class-wp-job-manager-writepanels.php:94
806
+ #: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:57
807
  msgid "Position Filled"
808
  msgstr ""
809
 
812
  msgstr ""
813
 
814
  #: includes/admin/class-wp-job-manager-writepanels.php:102
815
+ #: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:64
816
  msgid "Featured Listing"
817
  msgstr ""
818
 
823
  msgstr ""
824
 
825
  #: includes/admin/class-wp-job-manager-writepanels.php:109
826
+ #: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:68
827
  msgid "Listing Expiry Date"
828
  msgstr ""
829
 
830
  #: includes/admin/class-wp-job-manager-writepanels.php:119
831
+ #: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:75
832
  msgid "Posted by"
833
  msgstr ""
834
 
897
  msgstr ""
898
 
899
  #: includes/class-wp-job-manager-post-types.php:98
900
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:191
901
  msgid "Job category"
902
  msgstr ""
903
 
950
  msgstr ""
951
 
952
  #: includes/class-wp-job-manager-post-types.php:147
953
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:182
954
  msgid "Job type"
955
  msgstr ""
956
 
1093
  msgstr ""
1094
 
1095
  #: includes/forms/class-wp-job-manager-form-submit-job.php:69
1096
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:439
1097
  #: templates/job-preview.php:22
1098
  msgid "Preview"
1099
  msgstr ""
1107
  msgstr ""
1108
 
1109
  #: includes/forms/class-wp-job-manager-form-submit-job.php:144
1110
+ #: wp-job-manager-template.php:646
1111
  msgid "you@yourdomain.com"
1112
  msgstr ""
1113
 
1114
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:148
1115
  msgid "Application URL"
1116
  msgstr ""
1117
 
1118
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:149
1119
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:227
1120
  msgid "http://"
1121
  msgstr ""
1122
 
1123
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:153
1124
  msgid "Application email/URL"
1125
  msgstr ""
1126
 
1127
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:154
1128
  msgid "Enter an email address or website URL"
1129
  msgstr ""
1130
 
1131
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:167
1132
  msgid "Job Title"
1133
  msgstr ""
1134
 
1135
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:175
1136
  msgid "Leave this blank if the location is not important"
1137
  msgstr ""
1138
 
1139
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:185
1140
  msgid "Choose job type&hellip;"
1141
  msgstr ""
1142
 
1143
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:200
1144
  msgid "Description"
1145
  msgstr ""
1146
 
1147
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:216
1148
  msgid "Company name"
1149
  msgstr ""
1150
 
1151
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:219
1152
  msgid "Enter the name of the company"
1153
  msgstr ""
1154
 
1155
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:223
1156
  #: templates/content-single-job_listing-company.php:30
1157
  msgid "Website"
1158
  msgstr ""
1159
 
1160
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:231
1161
  msgid "Tagline"
1162
  msgstr ""
1163
 
1164
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:234
1165
  msgid "Briefly describe your company"
1166
  msgstr ""
1167
 
1168
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:239
1169
  msgid "Video"
1170
  msgstr ""
1171
 
1172
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:242
1173
  msgid "A link to a video about your company"
1174
  msgstr ""
1175
 
1176
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:246
1177
  msgid "Twitter username"
1178
  msgstr ""
1179
 
1180
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:249
1181
  msgid "@yourcompany"
1182
  msgstr ""
1183
 
1184
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:253
1185
  msgid "Logo"
1186
  msgstr ""
1187
 
1188
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:289
1189
  msgid "%s is a required field"
1190
  msgstr ""
1191
 
1192
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:299
1193
  msgid "%s is invalid"
1194
  msgstr ""
1195
 
1196
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:315
1197
+ #: wp-job-manager-functions.php:1036
1198
  msgid "\"%s\" (filetype %s) needs to be one of the following file types: %s"
1199
  msgstr ""
1200
 
1201
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:330
1202
  msgid "Please enter a valid application email address"
1203
  msgstr ""
1204
 
1205
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:339
1206
  msgid "Please enter a valid application URL"
1207
  msgstr ""
1208
 
1209
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:349
1210
  msgid "Please enter a valid application email address or URL"
1211
  msgstr ""
1212
 
1213
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:470
1214
  msgid "Please enter a username."
1215
  msgstr ""
1216
 
1217
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:474
1218
  msgid "Please enter a password."
1219
  msgstr ""
1220
 
1221
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:478
1222
  msgid "Please enter your email address."
1223
  msgstr ""
1224
 
1225
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:484
1226
  msgid "Passwords must match."
1227
  msgstr ""
1228
 
1229
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:489
1230
  msgid "Invalid Password: %s"
1231
  msgstr ""
1232
 
1233
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:491
1234
  msgid "Password is not valid."
1235
  msgstr ""
1236
 
1237
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:512
1238
  msgid "You must be signed in to post a new listing."
1239
  msgstr ""
1240
 
1266
  msgstr ""
1267
 
1268
  #: includes/helper/class-wp-job-manager-helper.php:471
1269
+ msgid "license is not active."
1270
  msgstr ""
1271
 
1272
  #: includes/helper/class-wp-job-manager-helper.php:485
1299
  msgid "Not Found"
1300
  msgstr ""
1301
 
1302
+ #: includes/rest-api/class-wp-job-manager-models-job-types-custom-fields.php:50
1303
+ msgid "Invalid Employment Type"
1304
+ msgstr ""
1305
+
1306
  #: includes/rest-api/class-wp-job-manager-models-settings.php:72
1307
  msgid "Invalid page ID provided"
1308
  msgstr ""
1336
  msgid "Keyword"
1337
  msgstr ""
1338
 
1339
+ #: lib/wpjm_rest/class-wp-job-manager-rest-model.php:214
1340
  #. translators: %s is usually a field name.
1341
  msgid "%s cannot be empty"
1342
  msgstr ""
1361
  msgid "Sign out"
1362
  msgstr ""
1363
 
1364
+ #: templates/account-signin.php:39
1365
  msgid "Have an account?"
1366
  msgstr ""
1367
 
1368
+ #: templates/account-signin.php:41 templates/job-dashboard-login.php:20
1369
  msgid "Sign in"
1370
  msgstr ""
1371
 
1372
+ #: templates/account-signin.php:45
1373
  msgid ""
1374
  "If you don&rsquo;t have an account you can %screate one below by entering "
1375
+ "your email address/username."
 
1376
  msgstr ""
1377
 
1378
+ #: templates/account-signin.php:45
1379
  msgid "optionally"
1380
  msgstr ""
1381
 
1382
+ #: templates/account-signin.php:47
1383
+ msgid "Your account details will be confirmed via email."
1384
+ msgstr ""
1385
+
1386
+ #: templates/account-signin.php:52
1387
  msgid "You must sign in to create a new listing."
1388
  msgstr ""
1389
 
1390
+ #: templates/account-signin.php:63 templates/job-submit.php:43
1391
  #: templates/job-submit.php:60
1392
  msgid "(optional)"
1393
  msgstr ""
1417
  msgstr ""
1418
 
1419
  #: templates/form-fields/multiselect-field.php:20
1420
+ #: wp-job-manager-functions.php:824
1421
  msgid "No results match"
1422
  msgstr ""
1423
 
1424
  #: templates/form-fields/multiselect-field.php:20
1425
+ #: wp-job-manager-functions.php:825
1426
  msgid "Select Some Options"
1427
  msgstr ""
1428
 
1519
  msgid "%s submitted successfully. Your listing will be visible once approved."
1520
  msgstr ""
1521
 
1522
+ #: wp-job-manager-functions.php:395
1523
  msgid "Reset"
1524
  msgstr ""
1525
 
1526
+ #: wp-job-manager-functions.php:399
1527
  msgid "RSS"
1528
  msgstr ""
1529
 
1530
+ #: wp-job-manager-functions.php:494
1531
  msgid "Invalid email address."
1532
  msgstr ""
1533
 
1534
+ #: wp-job-manager-functions.php:502
1535
  msgid "Your email address isn&#8217;t correct."
1536
  msgstr ""
1537
 
1538
+ #: wp-job-manager-functions.php:506
1539
  msgid "This email is already registered, please choose another one."
1540
  msgstr ""
1541
 
1542
+ #: wp-job-manager-functions.php:667
1543
  msgid "Full Time"
1544
  msgstr ""
1545
 
1546
+ #: wp-job-manager-functions.php:668
1547
  msgid "Part Time"
1548
  msgstr ""
1549
 
1550
+ #: wp-job-manager-functions.php:669
1551
  msgid "Contractor"
1552
  msgstr ""
1553
 
1554
+ #: wp-job-manager-functions.php:670
1555
  msgid "Temporary"
1556
  msgstr ""
1557
 
1558
+ #: wp-job-manager-functions.php:671
1559
  msgid "Intern"
1560
  msgstr ""
1561
 
1562
+ #: wp-job-manager-functions.php:672
1563
  msgid "Volunteer"
1564
  msgstr ""
1565
 
1566
+ #: wp-job-manager-functions.php:673
1567
  msgid "Per Diem"
1568
  msgstr ""
1569
 
1570
+ #: wp-job-manager-functions.php:674
1571
  msgid "Other"
1572
  msgstr ""
1573
 
1574
+ #: wp-job-manager-functions.php:741
1575
  msgid "Passwords must be at least 8 characters long."
1576
  msgstr ""
1577
 
1578
+ #: wp-job-manager-functions.php:823
1579
  msgid "Choose a category&hellip;"
1580
  msgstr ""
1581
 
1582
+ #: wp-job-manager-functions.php:1038
1583
  msgid "Uploaded files need to be one of the following file types: %s"
1584
  msgstr ""
1585
 
1591
  msgid "Application via \"%s\" listing on %s"
1592
  msgstr ""
1593
 
1594
+ #: wp-job-manager-template.php:620
1595
  msgid "Username"
1596
  msgstr ""
1597
 
1598
+ #: wp-job-manager-template.php:628
1599
  msgid "Password"
1600
  msgstr ""
1601
 
1602
+ #: wp-job-manager-template.php:638
1603
  msgid "Verify Password"
1604
  msgstr ""
1605
 
1606
+ #: wp-job-manager-template.php:645
1607
  msgid "Your email"
1608
  msgstr ""
1609
 
1610
+ #: wp-job-manager-template.php:672
1611
  msgid "Posted on "
1612
  msgstr ""
1613
 
1614
+ #: wp-job-manager-template.php:674 wp-job-manager-template.php:694
1615
  msgid "Posted %s ago"
1616
  msgstr ""
1617
 
1618
+ #: wp-job-manager-template.php:717
1619
  msgid "Anywhere"
1620
  msgstr ""
1621
 
1622
+ #: wp-job-manager.php:212
1623
  msgid "Load previous listings"
1624
  msgstr ""
1625
 
1626
+ #: wp-job-manager.php:263
1627
  msgid "Invalid file type. Accepted types:"
1628
  msgstr ""
1629
 
1630
+ #: wp-job-manager.php:274
1631
  msgid "Are you sure you want to delete this listing?"
1632
  msgstr ""
1633
 
1701
  msgstr ""
1702
 
1703
  #: includes/class-wp-job-manager-post-types.php:261
1704
+ #: wp-job-manager-functions.php:290
1705
  msgctxt "post status"
1706
  msgid "Expired"
1707
  msgstr ""
1708
 
1709
  #: includes/class-wp-job-manager-post-types.php:270
1710
+ #: wp-job-manager-functions.php:291
1711
  msgctxt "post status"
1712
  msgid "Preview"
1713
  msgstr ""
1714
 
1715
+ #: wp-job-manager-functions.php:289
1716
  msgctxt "post status"
1717
  msgid "Draft"
1718
  msgstr ""
1719
 
1720
+ #: wp-job-manager-functions.php:292
1721
  msgctxt "post status"
1722
  msgid "Pending approval"
1723
  msgstr ""
1724
 
1725
+ #: wp-job-manager-functions.php:293
1726
  msgctxt "post status"
1727
  msgid "Pending payment"
1728
  msgstr ""
1729
 
1730
+ #: wp-job-manager-functions.php:294
1731
  msgctxt "post status"
1732
  msgid "Active"
1733
+ msgstr ""
lib/wpjm_rest/class-wp-job-manager-rest-bootstrap.php CHANGED
@@ -18,7 +18,7 @@ if ( ! defined( 'ABSPATH' ) ) {
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
@@ -48,10 +48,19 @@ class WP_Job_Manager_REST_Bootstrap {
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
  *
@@ -63,12 +72,26 @@ class WP_Job_Manager_REST_Bootstrap {
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
@@ -101,6 +124,7 @@ class WP_Job_Manager_REST_Bootstrap {
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' )
@@ -110,6 +134,7 @@ class WP_Job_Manager_REST_Bootstrap {
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' )
@@ -119,7 +144,6 @@ class WP_Job_Manager_REST_Bootstrap {
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' )
@@ -164,6 +188,7 @@ class WP_Job_Manager_REST_Bootstrap {
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;
18
  * This is the entry point for.
19
  */
20
  class WP_Job_Manager_REST_Bootstrap {
21
+ const MINIMUM_PHP_VERSION = '5.2.0';
22
 
23
  /**
24
  * The Environment we will use
48
  *
49
  * @return bool
50
  */
51
+ public static function is_compatible() {
52
  return version_compare( phpversion(), self::MINIMUM_PHP_VERSION, '>=' );
53
  }
54
 
55
+ /**
56
+ * Get Base Dir
57
+ *
58
+ * @return string
59
+ */
60
+ public static function get_base_dir() {
61
+ return untrailingslashit( dirname( __FILE__ ) );
62
+ }
63
+
64
  /**
65
  * Create a Bootstrap, unless we are using a really early php version (< 5.3.0)
66
  *
72
  include_once( 'interfaces/class-wp-job-manager-rest-interfaces-classloader.php' );
73
  include_once( 'class-wp-job-manager-rest-classloader.php' );
74
  $prefix = str_replace( '_Bootstrap', '', __CLASS__ );
75
+ $base_dir = self::get_base_dir();
76
  $class_loader = new WP_Job_Manager_REST_Classloader( $prefix, $base_dir );
77
  }
78
  return new self( $class_loader );
79
  }
80
 
81
+ /**
82
+ * Run the app
83
+ *
84
+ * @return bool
85
+ */
86
+ public function run() {
87
+ if ( ! self::is_compatible() ) {
88
+ return false;
89
+ }
90
+ $this->load()
91
+ ->environment()->start();
92
+ return true;
93
+ }
94
+
95
  /**
96
  * Optional: Instead of calling load() you can
97
  * register as an auto-loader
124
  ->load_class( 'Interfaces_Permissions_Provider' )
125
  ->load_class( 'Exception' )
126
  ->load_class( 'Expect' )
127
+ ->load_class( 'Events' )
128
  ->load_class( 'Environment' )
129
  ->load_class( 'Type' )
130
  ->load_class( 'Type_String' )
134
  ->load_class( 'Type_Array' )
135
  ->load_class( 'Type_TypedArray' )
136
  ->load_class( 'Type_Nullable' )
137
+ ->load_class( 'Type_Model' )
138
  ->load_class( 'Type_Registry' )
139
  ->load_class( 'Data_Store_Nil' )
140
  ->load_class( 'Data_Store_Abstract' )
144
  ->load_class( 'Field_Declaration' )
145
  ->load_class( 'Field_Declaration_Builder' )
146
  ->load_class( 'Model' )
 
147
  ->load_class( 'Model_Settings' )
148
  ->load_class( 'Model_Collection' )
149
  ->load_class( 'Controller' )
188
  */
189
  public function environment() {
190
  if ( null === $this->environment ) {
191
+ $this->load();
192
  $this->environment = new WP_Job_Manager_REST_Environment( $this );
193
  }
194
  return $this->environment;
lib/wpjm_rest/class-wp-job-manager-rest-environment.php CHANGED
@@ -69,12 +69,20 @@ class WP_Job_Manager_REST_Environment {
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();
@@ -88,6 +96,15 @@ class WP_Job_Manager_REST_Environment {
88
  ->array_var( self::BUNDLES );
89
  }
90
 
 
 
 
 
 
 
 
 
 
91
  /**
92
  * Push a Builder to the Environment.
93
  *
@@ -106,10 +123,10 @@ class WP_Job_Manager_REST_Environment {
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 ) {
@@ -162,7 +179,7 @@ class WP_Job_Manager_REST_Environment {
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();
@@ -181,7 +198,7 @@ class WP_Job_Manager_REST_Environment {
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
  /**
@@ -192,7 +209,7 @@ class WP_Job_Manager_REST_Environment {
192
  $bundle->register( $this );
193
  }
194
  $this->has_started = true;
195
- do_action( 'mt_environment_after_start', $this );
196
  }
197
 
198
  return $this;
@@ -252,7 +269,7 @@ class WP_Job_Manager_REST_Environment {
252
  *
253
  * @return mixed
254
  */
255
- return apply_filters( 'mt_variable_get', $value, $this, $name );
256
  }
257
 
258
  /**
@@ -373,12 +390,21 @@ class WP_Job_Manager_REST_Environment {
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
  }
69
  */
70
  private $type_registry;
71
 
72
+ /**
73
+ * Events
74
+ *
75
+ * @var WP_Job_Manager_REST_Events
76
+ */
77
+ private $event_dispatcher;
78
+
79
  /**
80
  * Mixtape_Environment constructor.
81
  *
82
  * @param WP_Job_Manager_REST_Bootstrap $bootstrap The bootstrap.
83
  */
84
  public function __construct( $bootstrap ) {
85
+ $this->event_dispatcher = new WP_Job_Manager_REST_Events();
86
  $this->bootstrap = $bootstrap;
87
  $this->has_started = false;
88
  $this->rest_apis = array();
96
  ->array_var( self::BUNDLES );
97
  }
98
 
99
+ /**
100
+ * Get Event Dispacher
101
+ *
102
+ * @return WP_Job_Manager_REST_Events
103
+ */
104
+ public function get_event_dispatcher() {
105
+ return $this->event_dispatcher;
106
+ }
107
+
108
  /**
109
  * Push a Builder to the Environment.
110
  *
123
  }
124
 
125
  /**
126
+ * Retrieve a previously defined WP_Job_Manager_REST_Model
127
  *
128
  * @param string $class the class name.
129
+ * @return WP_Job_Manager_REST_Model the definition.
130
  * @throws WP_Job_Manager_REST_Exception Throws in case the model is not registered.
131
  */
132
  public function model( $class ) {
179
  }
180
 
181
  if ( false === $this->has_started ) {
182
+ $this->get_event_dispatcher()->do_action( 'environment_before_start', $this, get_class( $this ) );
183
  $this->load_pending_builders( self::MODELS );
184
  $this->load_pending_builders( self::BUNDLES );
185
  $registrables = $this->get( self::REGISTRABLE ) ? $this->get( self::REGISTRABLE ) : array();
198
  * @param array $rest_apis The existing rest apis.
199
  * @param WP_Job_Manager_REST_Environment $this The Environment.
200
  */
201
+ $rest_apis = (array) $this->get_event_dispatcher()->apply_filters( 'environment_get_rest_apis', $this->rest_apis, $this );
202
 
203
  foreach ( $rest_apis as $k => $bundle ) {
204
  /**
209
  $bundle->register( $this );
210
  }
211
  $this->has_started = true;
212
+ $this->get_event_dispatcher()->do_action( 'environment_after_start', $this );
213
  }
214
 
215
  return $this;
269
  *
270
  * @return mixed
271
  */
272
+ return $this->get_event_dispatcher()->apply_filters( 'variable_get', $value, $this, $name );
273
  }
274
 
275
  /**
390
  *
391
  * @param string $declaration A Model class string.
392
  *
393
+ * @return WP_Job_Manager_REST_Model
394
  */
395
  function define_model( $declaration ) {
396
  WP_Job_Manager_REST_Expect::that( class_exists( $declaration ), '$declaration string should be an existing class' );
397
  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' );
398
+
399
+ /**
400
+ * Create an empty Model to act as our factory (I know this is weird, see php5.2)
401
+ *
402
+ * @var WP_Job_Manager_REST_Model $factory
403
+ */
404
+ $factory = new $declaration();
405
+ $factory->with_environment( $this );
406
+ $factory->with_data_store( new WP_Job_Manager_REST_Data_Store_Nil() );
407
+ $factory->with_permissions_provider( new WP_Job_Manager_REST_Permissions_Any() );
408
  $this->model_definitions[ $declaration ] = $factory;
409
  return $factory;
410
  }
lib/wpjm_rest/class-wp-job-manager-rest-events.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WP_Job_Manager_REST_Events: Simple event bus
4
+ *
5
+ * @package Mixtape
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Events
14
+ *
15
+ * Simple event bus
16
+ *
17
+ * @package Mixtape
18
+ */
19
+ class WP_Job_Manager_REST_Events {
20
+ /**
21
+ * Events
22
+ *
23
+ * @var array
24
+ */
25
+ private $events = array();
26
+
27
+ /**
28
+ * Add Filter
29
+ *
30
+ * @param string $event Event.
31
+ * @param callable $func Func.
32
+ * @param int $priority Priority.
33
+ * @param int $accepted_args Accepted Args.
34
+ *
35
+ * @return $this
36
+ */
37
+ public function add_filter( $event, $func, $priority = 10, $accepted_args = 1 ) {
38
+ WP_Job_Manager_REST_Expect::that( is_callable( $func ), sprintf( '$func is not callable' ) );
39
+ if ( ! isset( $this->events[ $event ] ) ) {
40
+ $this->events[ $event ] = new WP_Hook();
41
+ }
42
+ /**
43
+ * The hook.
44
+ *
45
+ * @var WP_Hook $hook
46
+ */
47
+ $hook = $this->events[ $event ];
48
+ $hook->add_filter( $event, $func, $priority, $accepted_args );
49
+ return $this;
50
+ }
51
+
52
+ /**
53
+ * Add Action
54
+ *
55
+ * @param string $event Event.
56
+ * @param callable $func Func.
57
+ * @param int $priority Priority.
58
+ * @param int $accepted_args Accepted Args.
59
+ *
60
+ * @return $this
61
+ */
62
+ public function add_action( $event, $func, $priority = 10, $accepted_args = 1 ) {
63
+ return $this->add_filter( $event, $func, $priority, $accepted_args );
64
+ }
65
+
66
+ /**
67
+ * Apply Filters
68
+ *
69
+ * @param string $event Event.
70
+ * @param mixed $value Value.
71
+ *
72
+ * @return mixed
73
+ */
74
+ public function apply_filters( $event, $value ) {
75
+ $func_args = func_get_args();
76
+ if ( ! isset( $this->events[ $event ] ) ) {
77
+ return $value;
78
+ }
79
+ /**
80
+ * The hook.
81
+ *
82
+ * @var WP_Hook $hook
83
+ */
84
+ $hook = $this->events[ $event ];
85
+ $func_args = array_slice( $func_args, 1 );
86
+ return $hook->apply_filters( $value, $func_args );
87
+
88
+ }
89
+
90
+ /**
91
+ * Do Action
92
+ *
93
+ * @param string $event Event.
94
+ *
95
+ * @return mixed
96
+ */
97
+ public function do_action( $event ) {
98
+ $func_args = func_get_args();
99
+ if ( ! isset( $this->events[ $event ] ) ) {
100
+ return;
101
+ }
102
+ /**
103
+ * The hook.
104
+ *
105
+ * @var WP_Hook $hook
106
+ */
107
+ $hook = $this->events[ $event ];
108
+ array_shift( $func_args );
109
+ $hook->do_action( $func_args );
110
+ }
111
+
112
+ /**
113
+ * Remove
114
+ *
115
+ * @param string $event The Event.
116
+ * @param bool|callable $function_to_remove The callable.
117
+ * @param int $priority Priority.
118
+ * @return $this
119
+ */
120
+ public function remove( $event, $function_to_remove = false, $priority = 10 ) {
121
+ if ( isset( $this->events[ $event ] ) ) {
122
+ if ( false === $function_to_remove ) {
123
+ /**
124
+ * The hook.
125
+ *
126
+ * @var WP_Hook $hook
127
+ */
128
+ $hook = $this->events[ $event ];
129
+ $hook->remove_all_filters();
130
+ unset( $this->events[ $event ] );
131
+ }
132
+ /**
133
+ * The hook.
134
+ *
135
+ * @var WP_Hook $hook
136
+ */
137
+ $hook = $this->events[ $event ];
138
+ if ( $hook->has_filter( $event, $function_to_remove ) ) {
139
+ $hook->remove_filter( $event, $function_to_remove, $priority );
140
+ }
141
+ }
142
+ return $this;
143
+ }
144
+ }
lib/wpjm_rest/class-wp-job-manager-rest-expect.php CHANGED
@@ -28,6 +28,18 @@ class WP_Job_Manager_REST_Expect {
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
  *
28
  self::that( is_a( $thing, $class_name ), 'Expected ' . $class_name . ', got ' . get_class( $thing ) );
29
  }
30
 
31
+ /**
32
+ * Expect that something implements an interface.
33
+ *
34
+ * @param object|string|mixed $thing The thing to check.
35
+ * @param string $interface_name The interface name.
36
+ */
37
+ static function implements_interface( $thing, $interface_name ) {
38
+ $thing_class = is_object( $thing ) ? get_class( $thing ) : (string) $thing;
39
+ $interfaces = class_implements( $thing );
40
+ self::that( in_array( $interface_name, $interfaces, true ), 'Class ' . $thing_class . ' does not implement interface ' . $interface_name );
41
+ }
42
+
43
  /**
44
  * Expect that thing is an object
45
  *
lib/wpjm_rest/class-wp-job-manager-rest-model.php CHANGED
@@ -31,11 +31,18 @@ class WP_Job_Manager_REST_Model implements
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
@@ -86,7 +93,7 @@ class WP_Job_Manager_REST_Model implements
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
 
@@ -130,7 +137,7 @@ class WP_Job_Manager_REST_Model implements
130
  * @return bool
131
  */
132
  public function has( $field ) {
133
- $fields = self::get_fields();
134
  return isset( $fields[ $field ] );
135
  }
136
 
@@ -263,10 +270,16 @@ class WP_Job_Manager_REST_Model implements
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
 
@@ -315,8 +328,8 @@ class WP_Job_Manager_REST_Model implements
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
  }
@@ -329,20 +342,24 @@ class WP_Job_Manager_REST_Model implements
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
  /**
@@ -350,11 +367,15 @@ class WP_Job_Manager_REST_Model implements
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
  /**
@@ -366,10 +387,10 @@ class WP_Job_Manager_REST_Model implements
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
 
@@ -398,9 +419,9 @@ class WP_Job_Manager_REST_Model implements
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
  /**
@@ -410,7 +431,7 @@ class WP_Job_Manager_REST_Model implements
410
  */
411
  public function get_dto_field_mappings() {
412
  $mappings = array();
413
- foreach ( self::get_fields() as $field_declaration ) {
414
  /**
415
  * Declaration
416
  *
@@ -431,7 +452,7 @@ class WP_Job_Manager_REST_Model implements
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
  }
@@ -446,9 +467,9 @@ class WP_Job_Manager_REST_Model implements
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
@@ -499,7 +520,7 @@ class WP_Job_Manager_REST_Model implements
499
  *
500
  * @return array
501
  */
502
- public static function declare_fields() {
503
  WP_Job_Manager_REST_Expect::should_override( __METHOD__ );
504
  return array();
505
  }
@@ -524,17 +545,6 @@ class WP_Job_Manager_REST_Model implements
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
  *
@@ -564,7 +574,7 @@ class WP_Job_Manager_REST_Model implements
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 ) {
@@ -580,8 +590,10 @@ class WP_Job_Manager_REST_Model implements
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 );
@@ -598,7 +610,7 @@ class WP_Job_Manager_REST_Model implements
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
  *
@@ -642,4 +654,33 @@ class WP_Job_Manager_REST_Model implements
642
  }
643
  return $value;
644
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
645
  }
31
  private static $data_stores_by_class_name = array();
32
 
33
  /**
34
+ * The Environment the model exists in
35
  *
36
  * @var WP_Job_Manager_REST_Environment
37
  */
38
+ private static $environments_by_class_name = array();
39
+
40
+ /**
41
+ * Permissions Providers by class Name
42
+ *
43
+ * @var array
44
+ */
45
+ private static $permissions_providers_by_class_name = array();
46
 
47
  /**
48
  * Our data
93
  */
94
  public function get( $field_name, $args = array() ) {
95
  WP_Job_Manager_REST_Expect::that( $this->has( $field_name ), 'Field ' . $field_name . 'is not defined' );
96
+ $fields = $this->get_fields();
97
  $field_declaration = $fields[ $field_name ];
98
  $this->set_field_if_unset( $field_declaration );
99
 
137
  * @return bool
138
  */
139
  public function has( $field ) {
140
+ $fields = $this->get_fields();
141
  return isset( $fields[ $field ] );
142
  }
143
 
270
  * @param null|string $filter_by_type Filter.
271
  * @return array
272
  */
273
+ public function get_fields( $filter_by_type = null ) {
274
+ $class_name = get_class( $this );
275
+ /**
276
+ * Out model
277
+ *
278
+ * @var WP_Job_Manager_REST_Interfaces_Model $instance
279
+ */
280
+ $instance = new $class_name();
281
  if ( ! isset( self::$fields_by_class_name[ $class_name ] ) ) {
282
+ $fields = $instance->declare_fields();
283
  self::$fields_by_class_name[ $class_name ] = self::initialize_field_map( $fields );
284
  }
285
 
328
  *
329
  * @return WP_Job_Manager_REST_Interfaces_Data_Store
330
  */
331
+ public function get_data_store() {
332
+ $class_name = get_class( $this );
333
  if ( ! isset( self::$data_stores_by_class_name[ $class_name ] ) ) {
334
  self::$data_stores_by_class_name[ $class_name ] = new WP_Job_Manager_REST_Data_Store_Nil();
335
  }
342
  * @param WP_Job_Manager_REST_Interfaces_Data_Store $data_store A builder or a Data store.
343
  * @throws WP_Job_Manager_REST_Exception Throws when Data Store Invalid.
344
  */
345
+ public function with_data_store( $data_store ) {
346
+ $class_name = get_class( $this );
347
  // at this point we should have a data store.
348
  WP_Job_Manager_REST_Expect::is_a( $data_store, 'WP_Job_Manager_REST_Interfaces_Data_Store' );
349
  self::$data_stores_by_class_name[ $class_name ] = $data_store;
350
  }
351
 
352
  /**
353
+ * Get this model's environment
354
  *
355
+ * @return WP_Job_Manager_REST_Environment|null
356
  */
357
+ public function get_environment() {
358
+ $class_name = get_class( $this );
359
+ if ( isset( self::$environments_by_class_name[ $class_name ] ) ) {
360
+ return self::$environments_by_class_name[ $class_name ];
361
+ }
362
+ return null;
363
  }
364
 
365
  /**
367
  *
368
  * @param WP_Job_Manager_REST_Environment $environment The Environment.
369
  *
370
+ * @return WP_Job_Manager_REST_Interfaces_Model
371
+ *
372
  * @throws WP_Job_Manager_REST_Exception If an WP_Job_Manager_REST_Environment is not provided.
373
  */
374
+ public function with_environment( $environment ) {
375
  WP_Job_Manager_REST_Expect::is_a( $environment, 'WP_Job_Manager_REST_Environment' );
376
+ $class_name = get_class( $this );
377
+ self::$environments_by_class_name[ $class_name ] = $environment;
378
+ return $this;
379
  }
380
 
381
  /**
387
  * @return WP_Job_Manager_REST_Interfaces_Model
388
  * @throws WP_Job_Manager_REST_Exception Throws if data not an array.
389
  */
390
+ public function create( $data, $args = array() ) {
391
  WP_Job_Manager_REST_Expect::that( is_array( $data ), '$data should be an array' );
392
  WP_Job_Manager_REST_Expect::that( is_array( $args ), '$args should be an array' );
393
+ $class_name = get_class( $this );
394
  return new $class_name( $data, $args );
395
  }
396
 
419
  *
420
  * @return WP_Job_Manager_REST_Model|WP_Error
421
  */
422
+ public function new_from_array( $data ) {
423
+ $field_data = $this->map_data( $data, false );
424
+ return $this->create( $field_data )->sanitize();
425
  }
426
 
427
  /**
431
  */
432
  public function get_dto_field_mappings() {
433
  $mappings = array();
434
+ foreach ( $this->get_fields() as $field_declaration ) {
435
  /**
436
  * Declaration
437
  *
452
  */
453
  function to_dto() {
454
  $result = array();
455
+ foreach ( $this->get_dto_field_mappings() as $mapping_name => $field_name ) {
456
  $value = $this->get( $field_name );
457
  $result[ $mapping_name ] = $value;
458
  }
467
  * @param bool $updating Are we Updating.
468
  * @return array
469
  */
470
+ private function map_data( $data, $updating = false ) {
471
  $request_data = array();
472
+ $fields = $this->get_fields();
473
  foreach ( $fields as $field ) {
474
  /**
475
  * Field
520
  *
521
  * @return array
522
  */
523
+ public function declare_fields() {
524
  WP_Job_Manager_REST_Expect::should_override( __METHOD__ );
525
  return array();
526
  }
545
  return $this->set( 'id', $new_id );
546
  }
547
 
 
 
 
 
 
 
 
 
 
 
 
548
  /**
549
  * Create from Post.
550
  *
574
  * @return array
575
  */
576
  public function deserialize( $data ) {
577
+ $field_declarations = $this->get_fields();
578
  $raw_data = array();
579
  $post_array_keys = array_keys( $data );
580
  foreach ( $field_declarations as $declaration ) {
590
  // simplest case: we got a $key for this, so just map it.
591
  $value = $this->deserialize_field( $declaration, $data[ $key ] );
592
  } elseif ( in_array( $mapping, $post_array_keys, true ) ) {
593
+ // other case: we got a mapping.
594
  $value = $this->deserialize_field( $declaration, $data[ $mapping ] );
595
  } else {
596
+ // just provide a default.
597
  $value = $declaration->get_default_value();
598
  }
599
  $raw_data[ $key ] = $declaration->cast_value( $value );
610
  */
611
  function serialize( $field_type = null ) {
612
  $field_values_to_insert = array();
613
+ foreach ( $this->get_fields( $field_type ) as $field_declaration ) {
614
  /**
615
  * Declaration
616
  *
654
  }
655
  return $value;
656
  }
657
+
658
+ /**
659
+ * Handle Permissions for a REST Controller Action
660
+ *
661
+ * @param WP_REST_Request $request The request.
662
+ * @param string $action The action (e.g. index, create update etc).
663
+ * @return bool
664
+ */
665
+ public function permissions_check( $request, $action ) {
666
+ $class_name = get_class( $this );
667
+ if ( isset( self::$permissions_providers_by_class_name[ $class_name ] ) ) {
668
+ $permissions_provider = self::$permissions_providers_by_class_name[ $class_name ];
669
+ return call_user_func_array( array( $permissions_provider, 'permissions_check' ), array( $request, $action ) );
670
+ }
671
+ return true;
672
+ }
673
+
674
+ /**
675
+ * Set a Proxy Permission Provider for this class
676
+ *
677
+ * @param WP_Job_Manager_REST_Interfaces_Permissions_Provider $permissions_provider PP.
678
+ * @return WP_Job_Manager_REST_Model $this
679
+ */
680
+ public function with_permissions_provider( $permissions_provider ) {
681
+ WP_Job_Manager_REST_Expect::is_a( $permissions_provider, 'WP_Job_Manager_REST_Interfaces_Permissions_Provider' );
682
+ $class_name = get_class( $this );
683
+ self::$permissions_providers_by_class_name[ $class_name ] = $permissions_provider;
684
+ return $this;
685
+ }
686
  }
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-bundle.php CHANGED
@@ -69,8 +69,8 @@ class WP_Job_Manager_REST_Controller_Bundle implements WP_Job_Manager_REST_Inter
69
  *
70
  * @return array
71
  */
72
- $endpoints = (array) apply_filters(
73
- 'mt_rest_api_controller_bundle_get_endpoints',
74
  $this->endpoints,
75
  $this
76
  );
69
  *
70
  * @return array
71
  */
72
+ $endpoints = (array) $this->environment->get_event_dispatcher()->apply_filters(
73
+ 'rest_api_controller_bundle_get_endpoints',
74
  $this->endpoints,
75
  $this
76
  );
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-crud.php CHANGED
@@ -43,7 +43,7 @@ class WP_Job_Manager_REST_Controller_CRUD extends WP_Job_Manager_REST_Controller
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
  }
@@ -97,7 +97,7 @@ class WP_Job_Manager_REST_Controller_CRUD extends WP_Job_Manager_REST_Controller
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
  }
@@ -107,7 +107,7 @@ class WP_Job_Manager_REST_Controller_CRUD extends WP_Job_Manager_REST_Controller
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 ) ) {
@@ -144,7 +144,7 @@ class WP_Job_Manager_REST_Controller_CRUD extends WP_Job_Manager_REST_Controller
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
  }
43
  return $this->ok( $data );
44
  }
45
 
46
+ $model = $this->model_prototype->get_data_store()->get_entity( $item_id );
47
  if ( empty( $model ) ) {
48
  return $this->not_found( __( 'Model not found' ) );
49
  }
97
  if ( $is_update ) {
98
  $id = isset( $request['id'] ) ? absint( $request['id'] ) : null;
99
  if ( ! empty( $id ) ) {
100
+ $model_to_update = $this->model_prototype->get_data_store()->get_entity( $id );
101
  if ( empty( $model_to_update ) ) {
102
  return $this->not_found( 'Model does not exist' );
103
  }
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_prototype()->new_from_array( $request->get_params() );
111
  }
112
 
113
  if ( is_wp_error( $model ) ) {
144
  if ( empty( $id ) ) {
145
  return $this->bad_request( 'No Model ID provided' );
146
  }
147
+ $model = $this->model_prototype->get_data_store()->get_entity( $id );
148
  if ( null === $model ) {
149
  return $this->not_found( 'Model does not exist' );
150
  }
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-model.php CHANGED
@@ -18,9 +18,9 @@ class WP_Job_Manager_REST_Controller_Model extends WP_Job_Manager_REST_Controlle
18
  /**
19
  * The Factory
20
  *
21
- * @var WP_Job_Manager_REST_Model_Factory
22
  */
23
- protected $model_factory;
24
 
25
  /**
26
  * The data Store
@@ -50,10 +50,10 @@ class WP_Job_Manager_REST_Controller_Model extends WP_Job_Manager_REST_Controlle
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
  /**
@@ -67,8 +67,8 @@ class WP_Job_Manager_REST_Controller_Model extends WP_Job_Manager_REST_Controlle
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
 
@@ -82,7 +82,7 @@ class WP_Job_Manager_REST_Controller_Model extends WP_Job_Manager_REST_Controlle
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();
@@ -101,7 +101,7 @@ class WP_Job_Manager_REST_Controller_Model extends WP_Job_Manager_REST_Controlle
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 ) ) {
@@ -128,7 +128,7 @@ class WP_Job_Manager_REST_Controller_Model extends WP_Job_Manager_REST_Controlle
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
  /**
18
  /**
19
  * The Factory
20
  *
21
+ * @var WP_Job_Manager_REST_Model
22
  */
23
+ protected $model_prototype;
24
 
25
  /**
26
  * The data Store
50
  /**
51
  * Get our model factory
52
  *
53
+ * @return WP_Job_Manager_REST_Model
54
  */
55
+ protected function get_model_prototype() {
56
+ return $this->model_prototype;
57
  }
58
 
59
  /**
67
  * @return bool|WP_Error true if valid otherwise error.
68
  */
69
  public function register( $bundle, $environment ) {
70
+ $this->model_prototype = $environment->model( $this->model_class_name );
71
+ $this->model_data_store = $this->model_prototype->get_data_store();
72
  return parent::register( $bundle, $environment );
73
  }
74
 
82
  * @return array Item schema data.
83
  */
84
  public function get_item_schema() {
85
+ $model_definition = $this->get_model_prototype();
86
  $fields = $model_definition->get_fields();
87
  $properties = array();
88
  $required = array();
101
  '$schema' => 'http://json-schema.org/schema#',
102
  'title' => $model_definition->get_name(),
103
  'type' => 'object',
104
+ 'properties' => (array) $this->environment()->get_event_dispatcher()->apply_filters( 'rest_api_schema_properties', $properties, $this->get_model_prototype() ),
105
  );
106
 
107
  if ( ! empty( $required ) ) {
128
  * @return bool
129
  */
130
  public function permissions_check( $request, $action = 'any' ) {
131
+ return $this->get_model_prototype()->permissions_check( $request, $action );
132
  }
133
 
134
  /**
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-settings.php CHANGED
@@ -30,7 +30,7 @@ class WP_Job_Manager_REST_Controller_Settings extends WP_Job_Manager_REST_Contro
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
  }
@@ -56,7 +56,7 @@ class WP_Job_Manager_REST_Controller_Settings extends WP_Job_Manager_REST_Contro
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
  }
@@ -78,7 +78,7 @@ class WP_Job_Manager_REST_Controller_Settings extends WP_Job_Manager_REST_Contro
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 );
30
  * @return WP_REST_Response
31
  */
32
  public function get_items( $request ) {
33
+ $model = $this->model_prototype->get_data_store()->get_entity( null );
34
  if ( empty( $model ) ) {
35
  return $this->not_found( __( 'Settings not found' ) );
36
  }
56
  */
57
  protected function create_or_update( $request ) {
58
  $is_update = $request->get_method() !== 'POST';
59
+ $model_to_update = $this->model_prototype->get_data_store()->get_entity( null );
60
  if ( empty( $model_to_update ) ) {
61
  return $this->not_found( 'Model does not exist' );
62
  }
78
  return $this->bad_request( $id_or_error );
79
  }
80
 
81
+ $model = $this->model_prototype->get_data_store()->get_entity( null );
82
  $dto = $this->prepare_dto( $model );
83
 
84
  return $is_update ? $this->ok( $dto ) : $this->created( $dto );
lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-abstract.php CHANGED
@@ -18,9 +18,9 @@ abstract class WP_Job_Manager_REST_Data_Store_Abstract implements WP_Job_Manager
18
  /**
19
  * Definition
20
  *
21
- * @var WP_Job_Manager_REST_Model_Factory
22
  */
23
- protected $model_factory;
24
 
25
  /**
26
  * Type Serializers
@@ -32,26 +32,25 @@ abstract class WP_Job_Manager_REST_Data_Store_Abstract implements WP_Job_Manager
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
  }
@@ -65,9 +64,9 @@ abstract class WP_Job_Manager_REST_Data_Store_Abstract implements WP_Job_Manager
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
  }
18
  /**
19
  * Definition
20
  *
21
+ * @var WP_Job_Manager_REST_Model
22
  */
23
+ protected $model_prototype;
24
 
25
  /**
26
  * Type Serializers
32
  /**
33
  * WP_Job_Manager_REST_Data_Store_Abstract constructor.
34
  *
35
+ * @param null|WP_Job_Manager_REST_Model $model_prototype Def.
36
+ * @param array $args Args.
37
  */
38
+ public function __construct( $model_prototype = null, $args = array() ) {
39
  $this->type_serializers = array();
40
  $this->args = $args;
41
+ WP_Job_Manager_REST_Expect::is_a( $model_prototype, 'WP_Job_Manager_REST_Interfaces_Model' );
42
+ $this->set_model_factory( $model_prototype );
 
43
  }
44
 
45
  /**
46
  * Set Definition
47
  *
48
+ * @param WP_Job_Manager_REST_Model $factory Def.
49
  *
50
  * @return WP_Job_Manager_REST_Interfaces_Data_Store $this
51
  */
52
  private function set_model_factory( $factory ) {
53
+ $this->model_prototype = $factory;
54
  $this->configure();
55
  return $this;
56
  }
64
  /**
65
  * Get Definition
66
  *
67
+ * @return WP_Job_Manager_REST_Model
68
  */
69
+ public function get_model_prototype() {
70
+ return $this->model_prototype;
71
  }
72
  }
lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-customposttype.php CHANGED
@@ -23,12 +23,12 @@ class WP_Job_Manager_REST_Data_Store_CustomPostType extends WP_Job_Manager_REST_
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
  /**
@@ -55,7 +55,7 @@ class WP_Job_Manager_REST_Data_Store_CustomPostType extends WP_Job_Manager_REST_
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 ) );
@@ -70,11 +70,11 @@ class WP_Job_Manager_REST_Data_Store_CustomPostType extends WP_Job_Manager_REST_
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
 
@@ -84,7 +84,7 @@ class WP_Job_Manager_REST_Data_Store_CustomPostType extends WP_Job_Manager_REST_
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
  }
@@ -103,20 +103,32 @@ class WP_Job_Manager_REST_Data_Store_CustomPostType extends WP_Job_Manager_REST_
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;
@@ -142,11 +154,17 @@ class WP_Job_Manager_REST_Data_Store_CustomPostType extends WP_Job_Manager_REST_
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 ) );
@@ -158,7 +176,10 @@ class WP_Job_Manager_REST_Data_Store_CustomPostType extends WP_Job_Manager_REST_
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',
@@ -171,7 +192,10 @@ class WP_Job_Manager_REST_Data_Store_CustomPostType extends WP_Job_Manager_REST_
171
  }
172
  }
173
 
174
- do_action( 'mixtape_data_store_model_upsert_after', $model );
 
 
 
175
 
176
  return absint( $id_or_error );
177
  }
23
  /**
24
  * Mixtape_Data_Store_CustomPostType constructor.
25
  *
26
+ * @param null|WP_Job_Manager_REST_Interfaces_Model $model_prototype Def.
27
  * @param array $args Args.
28
  */
29
+ public function __construct( $model_prototype = null, $args = array() ) {
30
  $this->post_type = isset( $args['post_type'] ) ? $args['post_type'] : 'post';
31
+ parent::__construct( $model_prototype, $args );
32
  }
33
 
34
  /**
55
  * Get Entity
56
  *
57
  * @param int $id The id of the entity.
58
+ * @return WP_Job_Manager_REST_Interfaces_Model|null
59
  */
60
  public function get_entity( $id ) {
61
  $post = get_post( absint( $id ) );
70
  * Create from Post.
71
  *
72
  * @param WP_Post $post Post.
73
+ * @return WP_Job_Manager_REST_Interfaces_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_prototype()->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
 
84
  }
85
  $merged_data = array_merge( $raw_post_data, $flattened_meta );
86
 
87
+ return $this->get_model_prototype()->create( $merged_data, array(
88
  'deserialize' => true,
89
  ) );
90
  }
103
  'force_delete' => false,
104
  ) );
105
 
106
+ $this->get_model_prototype()
107
+ ->get_environment()
108
+ ->get_event_dispatcher()
109
+ ->do_action( 'data_store_delete_model_before', $model, $id );
110
 
111
  if ( $args['force_delete'] ) {
112
  $result = wp_delete_post( $model->get_id() );
113
  $model->set( 'id', 0 );
114
+ $this->get_model_prototype()
115
+ ->get_environment()
116
+ ->get_event_dispatcher()
117
+ ->do_action( 'data_store_delete_model', $model, $id );
118
  } else {
119
  $result = wp_trash_post( $model->get_id() );
120
  $model->set( 'status', 'trash' );
121
+ $this->get_model_prototype()
122
+ ->get_environment()
123
+ ->get_event_dispatcher()
124
+ ->do_action( 'data_store_trash_model', $model, $id );
125
  }
126
 
127
  if ( false === $result ) {
128
+ $this->get_model_prototype()
129
+ ->get_environment()
130
+ ->get_event_dispatcher()
131
+ ->do_action( 'data_store_delete_model_fail', $model, $id );
132
  return new WP_Error( 'delete-failed', 'delete-failed' );
133
  }
134
  return $result;
154
  unset( $fields['ID'] );
155
  }
156
 
157
+ $this->get_model_prototype()
158
+ ->get_environment()
159
+ ->get_event_dispatcher()
160
+ ->do_action( 'data_store_model_upsert_before', $model );
161
 
162
  $id_or_error = wp_insert_post( $fields, true );
163
  if ( is_wp_error( $id_or_error ) ) {
164
+ $this->get_model_prototype()
165
+ ->get_environment()
166
+ ->get_event_dispatcher()
167
+ ->do_action( 'data_store_model_upsert_error', $model );
168
  return $id_or_error;
169
  }
170
  $model->set( 'id', absint( $id_or_error ) );
176
  }
177
 
178
  if ( false === $id_or_bool ) {
179
+ $this->get_model_prototype()
180
+ ->get_environment()
181
+ ->get_event_dispatcher()
182
+ ->do_action( 'data_store_model_upsert_error', $model );
183
  // Something was wrong with this update/create. TODO: Should we stop mid create/update?
184
  return new WP_Error(
185
  'mixtape-error-creating-meta',
192
  }
193
  }
194
 
195
+ $this->get_model_prototype()
196
+ ->get_environment()
197
+ ->get_event_dispatcher()
198
+ ->do_action( 'data_store_model_upsert_after', $model );
199
 
200
  return absint( $id_or_error );
201
  }
lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-option.php CHANGED
@@ -24,11 +24,11 @@ class WP_Job_Manager_REST_Data_Store_Option extends WP_Job_Manager_REST_Data_Sto
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
 
@@ -50,7 +50,7 @@ class WP_Job_Manager_REST_Data_Store_Option extends WP_Job_Manager_REST_Data_Sto
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
  /**
@@ -64,7 +64,7 @@ class WP_Job_Manager_REST_Data_Store_Option extends WP_Job_Manager_REST_Data_Sto
64
  }
65
  }
66
 
67
- return $this->get_model_factory()->create( $raw_data, array(
68
  'deserialize' => true,
69
  ) );
70
  }
24
  /**
25
  * WP_Job_Manager_REST_Data_Store_Option constructor.
26
  *
27
+ * @param WP_Job_Manager_REST_Model $model_prototype Def.
28
+ * @param array $args Args.
29
  */
30
+ public function __construct( $model_prototype, $args = array() ) {
31
+ parent::__construct( $model_prototype, $args );
32
  $this->does_not_exist_guard = new stdClass();
33
  }
34
 
50
  * @return WP_Job_Manager_REST_Interfaces_Model
51
  */
52
  public function get_entity( $id ) {
53
+ $field_declarations = $this->get_model_prototype()->get_fields();
54
  $raw_data = array();
55
  foreach ( $field_declarations as $field_declaration ) {
56
  /**
64
  }
65
  }
66
 
67
+ return $this->get_model_prototype()->create( $raw_data, array(
68
  'deserialize' => true,
69
  ) );
70
  }
lib/wpjm_rest/interfaces/class-wp-job-manager-rest-interfaces-model.php CHANGED
@@ -84,29 +84,29 @@ interface WP_Job_Manager_REST_Interfaces_Model {
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
@@ -114,14 +114,14 @@ interface WP_Job_Manager_REST_Interfaces_Model {
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
84
  * @param null|string $filter_by_type The field type.
85
  * @return array
86
  */
87
+ public function get_fields( $filter_by_type = null );
88
 
89
  /**
90
  * Get this model's data store
91
  *
92
  * @return array
93
  */
94
+ public function get_data_store();
95
 
96
  /**
97
+ * Set this model's data store (statically, all models of that class get the same one)
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 function with_data_store( $data_store );
103
 
104
  /**
105
+ * Get this model's environment
106
  *
107
  * @return array
108
  */
109
+ public function get_environment();
110
 
111
  /**
112
  * Set this model's environment
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 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 function declare_fields();
125
 
126
  /**
127
  * Prepare this for data transfer
lib/wpjm_rest/interfaces/permissions/class-wp-job-manager-rest-interfaces-permissions-provider.php CHANGED
@@ -16,5 +16,5 @@ interface WP_Job_Manager_REST_Interfaces_Permissions_Provider {
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
  }
16
  * @param string $action The action (e.g. index, create update etc).
17
  * @return bool
18
  */
19
+ public function permissions_check( $request, $action );
20
  }
lib/wpjm_rest/model/class-wp-job-manager-rest-model-factory.php DELETED
@@ -1,175 +0,0 @@
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 CHANGED
@@ -21,7 +21,7 @@ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
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
  }
@@ -33,7 +33,7 @@ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
33
  * @param string $attribute Attr.
34
  * @return mixed
35
  */
36
- protected static function default_for_attribute( $field_data, $attribute ) {
37
  return null;
38
  }
39
 
@@ -46,7 +46,7 @@ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
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
  /**
@@ -54,16 +54,16 @@ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
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
  }
@@ -76,7 +76,7 @@ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
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
 
@@ -86,7 +86,7 @@ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
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
 
@@ -95,7 +95,7 @@ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
95
  *
96
  * @return string
97
  */
98
- function get_id() {
99
  return strtolower( get_class( $this ) );
100
  }
101
 
@@ -105,7 +105,7 @@ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
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
 
@@ -116,10 +116,10 @@ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
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;
@@ -130,11 +130,11 @@ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
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';
@@ -156,7 +156,7 @@ class WP_Job_Manager_REST_Model_Settings extends WP_Job_Manager_REST_Model {
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
  }
21
  * @throws WP_Job_Manager_REST_Exception Override this.
22
  * @return array
23
  */
24
+ public function get_settings() {
25
  WP_Job_Manager_REST_Expect::should_override( __METHOD__ );
26
  return array();
27
  }
33
  * @param string $attribute Attr.
34
  * @return mixed
35
  */
36
+ protected function default_for_attribute( $field_data, $attribute ) {
37
  return null;
38
  }
39
 
46
  * @param WP_Job_Manager_REST_Environment $env Env.
47
  * @return void
48
  */
49
+ protected function on_field_setup( $field_name, $field_builder, $field_data, $env ) {
50
  }
51
 
52
  /**
54
  *
55
  * @return array
56
  */
57
+ public function declare_fields() {
58
+ $env = $this->get_environment();
59
+ $settings_per_group = $this->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 = $this->field_declaration_builder_from_data( $env, $field_data );
67
  $fields[] = $field_builder;
68
  }
69
  }
76
  * @param mixed $value Val.
77
  * @return string
78
  */
79
+ public function bool_to_bit( $value ) {
80
  return ( ! empty( $value ) && 'false' !== $value ) ? '1' : '';
81
  }
82
 
86
  * @param mixed $value Val.
87
  * @return bool
88
  */
89
+ public function bit_to_bool( $value ) {
90
  return ( ! empty( $value ) && '0' !== $value ) ? true : false;
91
  }
92
 
95
  *
96
  * @return string
97
  */
98
+ public function get_id() {
99
  return strtolower( get_class( $this ) );
100
  }
101
 
105
  * @param mixed $new_id New ID.
106
  * @return WP_Job_Manager_REST_Interfaces_Model $this
107
  */
108
+ public function set_id( $new_id ) {
109
  return $this;
110
  }
111
 
116
  * @param array $field_data Data.
117
  * @return WP_Job_Manager_REST_Field_Declaration_Builder
118
  */
119
+ private 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'] : $this->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;
130
  $field_type = 'boolean';
131
  if ( $default_value ) {
132
  // convert our default value as well.
133
+ $default_value = $this->bit_to_bool( $default_value );
134
  }
135
  $field_builder
136
+ ->with_serializer( array( $this, 'bool_to_bit' ) )
137
+ ->with_deserializer( array( $this, 'bit_to_bool' ) );
138
 
139
  } elseif ( 'select' === $setting_type ) {
140
  $field_type = 'string';
156
  $field_builder->with_choices( $choices );
157
  }
158
 
159
+ $this->on_field_setup( $field_name, $field_builder, $field_data, $env );
160
 
161
  return $field_builder;
162
  }
lib/wpjm_rest/permissions/class-wp-job-manager-rest-permissions-any.php CHANGED
@@ -21,7 +21,7 @@ class WP_Job_Manager_REST_Permissions_Any implements WP_Job_Manager_REST_Interfa
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
  }
21
  * @param string $action The action (e.g. index, create update etc).
22
  * @return bool
23
  */
24
+ public function permissions_check( $request, $action ) {
25
  return true;
26
  }
27
  }
lib/wpjm_rest/type/class-wp-job-manager-rest-type-model.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Model type
4
+ *
5
+ * @package Mixtape/Type
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Class WP_Job_Manager_REST_Type_Model
14
+ */
15
+ class WP_Job_Manager_REST_Type_Model extends WP_Job_Manager_REST_Type {
16
+ /**
17
+ * The Class (must implement WP_Job_Manager_REST_Interfaces_Model).
18
+ *
19
+ * @var string
20
+ */
21
+ private $model_class;
22
+
23
+ /**
24
+ * WP_Job_Manager_REST_Type_Array constructor.
25
+ *
26
+ * @param string $model_class The model class.
27
+ */
28
+ public function __construct( $model_class = 'WP_Job_Manager_REST_Model' ) {
29
+ WP_Job_Manager_REST_Expect::implements_interface( $model_class, 'WP_Job_Manager_REST_Interfaces_Model' );
30
+ $this->model_class = $model_class;
31
+ parent::__construct( 'model:' . $model_class );
32
+ }
33
+
34
+ /**
35
+ * Get default WP_Job_Manager_REST_Interfaces_Model
36
+ *
37
+ * @return WP_Job_Manager_REST_Interfaces_Model
38
+ */
39
+ public function default_value() {
40
+ $klass = $this->model_class;
41
+ return new $klass();
42
+ }
43
+
44
+ /**
45
+ * Sanitize.
46
+ *
47
+ * @param WP_Job_Manager_REST_Interfaces_Model|mixed $value Val.
48
+ * @return WP_Job_Manager_REST_Interfaces_Model
49
+ * @throws WP_Job_Manager_REST_Exception If value not a $this->model_class.
50
+ */
51
+ function sanitize( $value ) {
52
+ if ( is_a( $value, $this->model_class ) ) {
53
+ return $value->sanitize();
54
+ }
55
+ throw new WP_Job_Manager_REST_Exception( 'WP_Job_Manager_REST_Type_Model: don\'t know how to sanitize provided value' );
56
+ }
57
+
58
+ /**
59
+ * Cast to WP_Job_Manager_REST_Interfaces_Model if possible.
60
+ *
61
+ * @param WP_Job_Manager_REST_Interfaces_Model|array $value The value. Should be either array or type class.
62
+ * @return WP_Job_Manager_REST_Interfaces_Model
63
+ * @throws WP_Job_Manager_REST_Exception If value not an array or a $this->model_class.
64
+ */
65
+ public function cast( $value ) {
66
+ if ( is_a( $value, $this->model_class ) ) {
67
+ return $value;
68
+ } elseif ( is_array( $value ) ) {
69
+ $klass = $this->model_class;
70
+ return new $klass( $value );
71
+ }
72
+ throw new WP_Job_Manager_REST_Exception( 'WP_Job_Manager_REST_Type_Model: don\'t know how to cast provided value' );
73
+ }
74
+ }
lib/wpjm_rest/type/class-wp-job-manager-rest-type-registry.php CHANGED
@@ -11,6 +11,20 @@ if ( ! defined( 'ABSPATH' ) ) {
11
 
12
  /**
13
  * Class WP_Job_Manager_REST_Type_Registry
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  */
15
  class WP_Job_Manager_REST_Type_Registry {
16
  /**
@@ -21,6 +35,7 @@ class WP_Job_Manager_REST_Type_Registry {
21
  private $container_types = array(
22
  'array',
23
  'nullable',
 
24
  );
25
 
26
  /**
@@ -30,6 +45,13 @@ class WP_Job_Manager_REST_Type_Registry {
30
  */
31
  private $types = null;
32
 
 
 
 
 
 
 
 
33
  /**
34
  * Define a new type
35
  *
@@ -52,7 +74,7 @@ class WP_Job_Manager_REST_Type_Registry {
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();
@@ -63,31 +85,35 @@ class WP_Job_Manager_REST_Type_Registry {
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
 
@@ -97,7 +123,9 @@ class WP_Job_Manager_REST_Type_Registry {
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
  /**
@@ -110,7 +138,8 @@ class WP_Job_Manager_REST_Type_Registry {
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(),
11
 
12
  /**
13
  * Class WP_Job_Manager_REST_Type_Registry
14
+ *
15
+ * We support some primitive types, as well as container types:
16
+ * 'any'
17
+ * 'string'
18
+ * 'integer'
19
+ * 'int'
20
+ * 'uint'
21
+ * 'number'
22
+ * 'float'
23
+ * 'boolean
24
+ * 'array' (untyped array)
25
+ * 'array:<type>' (typed array)
26
+ * 'nullable:<type>' (nullable type)
27
+ * 'model:<class>' (a model type)
28
  */
29
  class WP_Job_Manager_REST_Type_Registry {
30
  /**
35
  private $container_types = array(
36
  'array',
37
  'nullable',
38
+ 'model',
39
  );
40
 
41
  /**
45
  */
46
  private $types = null;
47
 
48
+ /**
49
+ * Environment
50
+ *
51
+ * @var null|WP_Job_Manager_REST_Environment
52
+ */
53
+ private $environment = null;
54
+
55
  /**
56
  * Define a new type
57
  *
74
  * @param string $type The type name.
75
  * @return WP_Job_Manager_REST_Interfaces_Type
76
  *
77
+ * @throws WP_Job_Manager_REST_Exception In case of type name not conforming to syntax.
78
  */
79
  function definition( $type ) {
80
  $types = $this->get_types();
85
  if ( count( $parts ) > 1 ) {
86
 
87
  $container_type = $parts[0];
88
+ WP_Job_Manager_REST_Expect::that( in_array( $container_type, $this->container_types, true ), $container_type . ' is not a known container type' );
 
 
89
 
90
  $item_type = $parts[1];
91
+
92
  if ( empty( $item_type ) ) {
93
  throw new WP_Job_Manager_REST_Exception( $type . ': invalid syntax' );
94
  }
 
95
 
96
  if ( 'array' === $container_type ) {
97
+ $item_type_definition = $this->definition( $item_type );
98
  $this->define( $type, new WP_Job_Manager_REST_Type_TypedArray( $item_type_definition ) );
99
  $types = $this->get_types();
100
  }
101
 
102
  if ( 'nullable' === $container_type ) {
103
+ $item_type_definition = $this->definition( $item_type );
104
  $this->define( $type, new WP_Job_Manager_REST_Type_Nullable( $item_type_definition ) );
105
  $types = $this->get_types();
106
  }
107
+
108
+ if ( 'model' === $container_type ) {
109
+ $this->define( $type, new WP_Job_Manager_REST_Type_Model( $item_type ) );
110
+ $types = $this->get_types();
111
+ }
112
  }
113
  }
114
 
115
+ WP_Job_Manager_REST_Expect::that( isset( $types[ $type ] ), 'invalid type ' . $type );
116
+
 
117
  return $types[ $type ];
118
  }
119
 
123
  * @return array
124
  */
125
  private function get_types() {
126
+ return (array) $this->environment
127
+ ->get_event_dispatcher()
128
+ ->apply_filters( 'type_registry_get_types', $this->types, $this );
129
  }
130
 
131
  /**
138
  return;
139
  }
140
 
141
+ $this->environment = $environment;
142
+ $this->types = (array) $this->environment->get_event_dispatcher()->apply_filters( 'type_registry_register_types', array(
143
  'any' => new WP_Job_Manager_REST_Type( 'any' ),
144
  'string' => new WP_Job_Manager_REST_Type_String(),
145
  'integer' => new WP_Job_Manager_REST_Type_Integer(),
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: mikejolley, automattic, adamkheckler, annezazu, cena, chaselivingston, csonnek, davor.altman, drawmyface, erania-pinnera, jacobshere, jakeom, jeherve, jenhooks, jgs, jonryan, kraftbj, lamdayap, lschuyler, macmanx, nancythanki, orangesareorange, rachelsquirrel, ryancowles, richardmtl, scarstocea
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.29.0
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -141,100 +141,87 @@ You can view (and contribute) translations via the [translate.wordpress.org](htt
141
 
142
  == Changelog ==
143
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  = 1.29.0 =
145
- * Enhancement: Moves license and update management for official add-ons to the core plugin. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1168)
146
- * Enhancement: Update language for setup wizard with more clear descriptions. (@donnapep; https://github.com/Automattic/WP-Job-Manager/pull/1194)
147
- * Fix: Prevent duplicate attachments to job listing posts for non-image media. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1144)
148
- * Fix: PHP error on registration form due to missing placeholder text. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1180)
149
- * Fix: Apply `the_job_application_method` filter even when no default is available. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/issues/1164)
150
- * Fix: Properly reset category selector on `[jobs]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1190)
151
 
152
  = 1.28.0 =
153
- * Enhancement: Improves support for Google Job Search by adding `JobPosting` structured data. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1115)
154
- * 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)
155
- * Enhancement: Requests search engines no longer index expired and filled job listings. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1120)
156
- * 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)
157
- * 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)
158
- * 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)
159
- * Fix: Localization issue with WPML in the [jobs] shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1129)
160
- * Fix: Show job listings' published date in localized format. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1118)
161
- * 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)
162
- * Fix: Some themes that overloaded functions would break in previous release. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1104)
163
- * 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)
164
- * 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)
165
  * 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)
166
 
167
  = 1.27.0 =
168
- * 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)
169
- * Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1024)
170
- * Enhancement: Allows users to override permalink slugs in WP Admin's Permalink Settings screen. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1042)
171
- * Enhancement: Allows admins to perform bulk updating of jobs as filled/not filled. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1049)
172
- * Enhancement: Adds job listing status CSS classes on single job listings. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1041)
173
- * Enhancement: Adds `wpjm_the_job_title` filter for inserting non-escaped HTML alongside job titles in templates. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1033)
174
- * Enhancement: Allows admins to filter by `post_status` in `[jobs]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1051)
175
- * Enhancement: Allows accessing settings tab from hash in URL. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/999)
176
- * Fix: Make sure cron jobs for checking/cleaning expired listings are always in place. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1058)
177
- * Fix: Better handling of multiple job types. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/1014)
178
- * Fix: Issue with deleting company logos from job listings submission form. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1047)
179
- * Fix: Warning thrown on job submission form when user not logged in. (@piersb; https://github.com/Automattic/WP-Job-Manager/pull/1011)
180
- * Fix: Issue with WPML not syncing some meta fields. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1027)
181
- * Fix: Better handling of AJAX upload errors. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1044)
182
- * Fix: Remove job posting cookies on logout. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1065)
183
- * Fix: Expiration date can be cleared if default job duration option is empty. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/1076)
184
- * Fix: Issue with Safari and expiration datepicker. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1078)
185
 
186
  = 1.26.2 =
187
- * Fix: Prevents use of Ajax file upload endpoint for visitors who aren't logged in. Themes should check with `job_manager_user_can_upload_file_via_ajax()` if using endpoint in templates. (https://github.com/Automattic/WP-Job-Manager/pull/1020)
188
- * Fix: Escape post title in WP Admin's Job Listings page and template segments. (Props to @EhsanCod3r; https://github.com/Automattic/WP-Job-Manager/pull/1026)
189
 
190
  = 1.26.1 =
191
- * Enhancement: Add language using WordPress's current locale to geocode requests. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1007)
192
- * Fix: Allow attempts to use Google Maps Geocode API without an API key. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/998)
193
- * Fix: Issue affecting job expiry date when editing a job listing. (@spencerfinnell, @jom; https://github.com/Automattic/WP-Job-Manager/pull/1008)
194
- * Fix: Show correct total count of results on `[jobs]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1006)
195
 
196
  = 1.26.0 =
197
- * Enhancement: Warn the user if they're editing an existing job. (@donnchawp; https://github.com/Automattic/WP-Job-Manager/pull/847)
198
- * Enhancement: WP Admin Job Listing page's table is now responsive. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/906)
199
- * Enhancement: New setting for hiding expired listings from `[jobs]` filter. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/903)
200
- * Enhancement: Use WP Query's built in search function to improve searching in `[jobs]`. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/960)
201
- * Fix: Job Listing filter only searches meta fields with relevant content. Add custom fields with `job_listing_searchable_meta_keys` filter. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/910)
202
- * Fix: Improved support for WPML and Polylang. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/963)
203
- * Fix: Expired field no longer forces admins to choose a date in the future. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/903)
204
- * Fix: Listings with expiration date in past will immediately expire; moving to Active status will extend if necessary. (@turtlepod, @jom; https://github.com/Automattic/WP-Job-Manager/pull/903, https://github.com/Automattic/WP-Job-Manager/pull/975)
205
- * Fix: Google Maps API key setting added to fix geolocation retrieval on new sites. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/912)
206
- * Fix: Issue when duplicating a job listing with a field for multiple file uploads. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/911)
207
- * Fix: Hide page results when adding links in the `[submit_job_form]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/922)
208
- * Fix: Job feed now loads when a site has no posts. (@dbtlr; https://github.com/Automattic/WP-Job-Manager/pull/870)
209
- * Fix: No error is thrown when deleting a user. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/875)
210
- * Dev: Plugins and themes can now retrieve JSON of Job Listings results without HTML. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/888)
211
  * Dev: Updated inline documentation.
212
 
213
- = 1.25.3 =
214
- * Enhancement: Allow job types to be optional, just like categories. https://github.com/automattic/wp-job-manager/pull/789 Props Donncha.
215
- * Enhancement: Add get_job_listing_types filter. https://github.com/automattic/wp-job-manager/pull/824 Props Adam Heckler.
216
- * Enhancement: Various date format setting improvements. See https://github.com/automattic/wp-job-manager/pull/757 Props Christian Nolen.
217
- * Enhancement: Pass search values with the job_manager_get_listings_custom_filter_text filter. https://github.com/automattic/wp-job-manager/pull/845 Props Kraft.
218
- * Fix: Prevent a potential CSRF vector. https://github.com/automattic/wp-job-manager/pull/891 Props Jay Patel for the responsible disclosure.
219
- * Fix: Improve load time by removing unnecessary oEmbed call. https://github.com/automattic/wp-job-manager/pull/768 Props Myles McNamara.
220
- * Fix: Improve WPML compatibility. https://github.com/automattic/wp-job-manager/pull/787 Props Spencer Finnell.
221
- * Fix: Add an implicit whitelist for API requests. https://github.com/automattic/wp-job-manager/pull/855 Props muddletoes.
222
- * Fix: Fixed taxonomy search conditions. See https://github.com/automattic/wp-job-manager/pull/859/ Props Jonas Vogel.
223
-
224
- = 1.25.2 =
225
- * Fix - The date format of the expiry date picker was incorrect in translations so we added a comment to clarify, and fixed translations. (https://github.com/Automattic/WP-Job-Manager/issues/697)
226
- * Fix - Changing the date of an expired job would forget the date, even though the job would become active. (https://github.com/Automattic/WP-Job-Manager/issues/653)
227
- * Fix - Site owner can allow jobs to have only one or more than one types. (https://github.com/Automattic/WP-Job-Manager/issues/549)
228
- * Fix - Show expired jobs if that setting is enabled. (https://github.com/Automattic/WP-Job-Manager/issues/703)
229
- * Fix - Simplify the search message on the jobs page to avoid translation problems. (https://github.com/Automattic/WP-Job-Manager/issues/647)
230
- * Fix - The uploader would ignore WordPress created image sizes. (https://github.com/Automattic/WP-Job-Manager/issues/706)
231
- * Fix - setup.css was loaded on all admin pages. (https://github.com/Automattic/WP-Job-Manager/issues/728)
232
- * Fix - The preview of a listing could be edited or viewed by anyone. Props @tripflex (https://github.com/Automattic/WP-Job-Manager/issues/690)
233
- * Fix - When users were deleted their jobs weren't. (https://github.com/Automattic/WP-Job-Manager/issues/675)
234
- * Fix - OrderBy Rand wasn't working. (https://github.com/Automattic/WP-Job-Manager/issues/714)
235
- * Dev - Add upload filters and update PHPDocs, props @tripflex (https://github.com/Automattic/WP-Job-Manager/pull/747)
236
- * Fix - Stop using jQuery.live, props @tripflex (https://github.com/Automattic/WP-Job-Manager/pull/664)
237
-
238
  See additional changelog items in changelog.txt
239
 
240
  == Upgrade Notice ==
2
  Contributors: mikejolley, automattic, adamkheckler, annezazu, cena, chaselivingston, csonnek, davor.altman, drawmyface, erania-pinnera, jacobshere, jakeom, jeherve, jenhooks, jgs, jonryan, kraftbj, lamdayap, lschuyler, macmanx, nancythanki, orangesareorange, rachelsquirrel, ryancowles, richardmtl, scarstocea
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.9
6
+ Stable tag: 1.29.1
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
141
 
142
  == Changelog ==
143
 
144
+ = 1.29.1 =
145
+ * Enhancement: When retrieving listings in `[jobs]` shortcode, setting `orderby` to `rand_featured` will still place featured listings at the top. (@jom)
146
+ * Enhancement: Scroll to show application details when clicking on "Apply for Job" button. (@jom)
147
+ * Change: Updates `account-signin.php` template to warn users email will be confirmed only if that is enabled. (@jom)
148
+ * Fix: Sanitize URLs and emails differently on the application method job listing field. (@jom)
149
+ * Fix: Remove PHP notice in Featured Jobs widget. (@himanshuahuja96)
150
+ * Fix: String fix for consistent spelling of "license" when appearing in strings. (@garrett-eclipse)
151
+ * Fix: Issue with paid add-on licenses not showing up when some third-party plugins were installed. (@jom)
152
+ * Dev: Runs new actions (`job_manager_recent_jobs_widget_before` and `job_manager_recent_jobs_widget_after`) inside Recent Jobs widget. (@jom)
153
+ * Dev: Change `wpjm_get_the_job_types()` to return an empty array when job types are disabled. (@jom)
154
+ * See all: https://github.com/Automattic/WP-Job-Manager/milestone/15?closed=1
155
+
156
  = 1.29.0 =
157
+ * Enhancement: Moves license and update management for official add-ons to the core plugin. (@jom)
158
+ * Enhancement: Update language for setup wizard with more clear descriptions. (@donnapep)
159
+ * Fix: Prevent duplicate attachments to job listing posts for non-image media. (@tripflex)
160
+ * Fix: PHP error on registration form due to missing placeholder text. (@jom)
161
+ * Fix: Apply `the_job_application_method` filter even when no default is available. (@turtlepod)
162
+ * Fix: Properly reset category selector on `[jobs]` shortcode. (@jom)
163
 
164
  = 1.28.0 =
165
+ * Enhancement: Improves support for Google Job Search by adding `JobPosting` structured data. (@jom)
166
+ * Enhancement: Adds ability for job types to be mapped to an employment type as defined for Google Job Search. (@jom)
167
+ * Enhancement: Requests search engines no longer index expired and filled job listings. (@jom)
168
+ * Enhancement: Improves support with third-party sitemap generation in Jetpack, Yoast SEO, and All in One SEO. (@jom)
169
+ * Enhancement: Updated descriptions and help text on settings page. (@donnapep; Props to @michelleweber for updated copy)
170
+ * Enhancement: Lower cache expiration times across plugin and limit use of autoloaded cache transients. (@jom/files)
171
+ * Fix: Localization issue with WPML in the [jobs] shortcode. (@jom)
172
+ * Fix: Show job listings' published date in localized format. (@jom)
173
+ * Fix: Job submission form allows users to select multiple job types when they go back a step. (@jom)
174
+ * Fix: Some themes that overloaded functions would break in previous release. (@jom)
175
+ * Dev: Adds versions to template files so it is easier to tell when they are updated. (@jom)
176
+ * Dev: Adds a new `wpjm_notify_new_user` action that allows you to override default behavior. (@jom)
177
  * 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)
178
 
179
  = 1.27.0 =
180
+ * Enhancement: Admins can now allow users to specify an account password when posting their first job listing. (@jom)
181
+ * Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex)
182
+ * Enhancement: Allows users to override permalink slugs in WP Admin's Permalink Settings screen. (@jom)
183
+ * Enhancement: Allows admins to perform bulk updating of jobs as filled/not filled. (@jom)
184
+ * Enhancement: Adds job listing status CSS classes on single job listings. (@jom)
185
+ * Enhancement: Adds `wpjm_the_job_title` filter for inserting non-escaped HTML alongside job titles in templates. (@jom)
186
+ * Enhancement: Allows admins to filter by `post_status` in `[jobs]` shortcode. (@jom)
187
+ * Enhancement: Allows accessing settings tab from hash in URL. (@tripflex)
188
+ * Fix: Make sure cron jobs for checking/cleaning expired listings are always in place. (@jom)
189
+ * Fix: Better handling of multiple job types. (@spencerfinnell)
190
+ * Fix: Issue with deleting company logos from job listings submission form. (@jom)
191
+ * Fix: Warning thrown on job submission form when user not logged in. (@piersb)
192
+ * Fix: Issue with WPML not syncing some meta fields. (@jom)
193
+ * Fix: Better handling of AJAX upload errors. (@tripflex)
194
+ * Fix: Remove job posting cookies on logout. (@jom)
195
+ * Fix: Expiration date can be cleared if default job duration option is empty. (@spencerfinnell)
196
+ * Fix: Issue with Safari and expiration datepicker. (@jom)
197
 
198
  = 1.26.2 =
199
+ * Fix: Prevents use of Ajax file upload endpoint for visitors who aren't logged in. Themes should check with `job_manager_user_can_upload_file_via_ajax()` if using endpoint in templates.
200
+ * Fix: Escape post title in WP Admin's Job Listings page and template segments. (Props to @EhsanCod3r)
201
 
202
  = 1.26.1 =
203
+ * Enhancement: Add language using WordPress's current locale to geocode requests. (@jom)
204
+ * Fix: Allow attempts to use Google Maps Geocode API without an API key. (@spencerfinnell)
205
+ * Fix: Issue affecting job expiry date when editing a job listing. (@spencerfinnell, @jom)
206
+ * Fix: Show correct total count of results on `[jobs]` shortcode. (@jom)
207
 
208
  = 1.26.0 =
209
+ * Enhancement: Warn the user if they're editing an existing job. (@donnchawp)
210
+ * Enhancement: WP Admin Job Listing page's table is now responsive. (@turtlepod)
211
+ * Enhancement: New setting for hiding expired listings from `[jobs]` filter. (@turtlepod)
212
+ * Enhancement: Use WP Query's built in search function to improve searching in `[jobs]`. (@jom)
213
+ * Fix: Job Listing filter only searches meta fields with relevant content. Add custom fields with `job_listing_searchable_meta_keys` filter. (@turtlepod)
214
+ * Fix: Improved support for WPML and Polylang. (@jom)
215
+ * Fix: Expired field no longer forces admins to choose a date in the future. (@turtlepod)
216
+ * Fix: Listings with expiration date in past will immediately expire; moving to Active status will extend if necessary. (@turtlepod, @jom, https://github.com/Automattic/WP-Job-Manager/pull/975)
217
+ * Fix: Google Maps API key setting added to fix geolocation retrieval on new sites. (@jom)
218
+ * Fix: Issue when duplicating a job listing with a field for multiple file uploads. (@turtlepod)
219
+ * Fix: Hide page results when adding links in the `[submit_job_form]` shortcode. (@jom)
220
+ * Fix: Job feed now loads when a site has no posts. (@dbtlr)
221
+ * Fix: No error is thrown when deleting a user. (@tripflex)
222
+ * Dev: Plugins and themes can now retrieve JSON of Job Listings results without HTML. (@spencerfinnell)
223
  * Dev: Updated inline documentation.
224
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  See additional changelog items in changelog.txt
226
 
227
  == Upgrade Notice ==
scripts/build_mixtape.sh DELETED
@@ -1,118 +0,0 @@
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
@@ -8,7 +8,7 @@
8
  * @author Automattic
9
  * @package WP Job Manager
10
  * @category Template
11
- * @version 1.27.0
12
  */
13
 
14
  if ( ! defined( 'ABSPATH' ) ) {
@@ -30,9 +30,10 @@ if ( ! defined( 'ABSPATH' ) ) {
30
  </fieldset>
31
 
32
  <?php else :
33
- $account_required = job_manager_user_requires_account();
34
- $registration_enabled = job_manager_enable_registration();
35
- $registration_fields = wpjm_get_registration_fields();
 
36
  ?>
37
  <fieldset>
38
  <label><?php _e( 'Have an account?', 'wp-job-manager' ); ?></label>
@@ -41,7 +42,10 @@ if ( ! defined( 'ABSPATH' ) ) {
41
 
42
  <?php if ( $registration_enabled ) : ?>
43
 
44
- <?php printf( __( 'If you don&rsquo;t have an account you can %screate one below by entering your email address/username. Your account details will be confirmed via email.', 'wp-job-manager' ), $account_required ? '' : __( 'optionally', 'wp-job-manager' ) . ' ' ); ?>
 
 
 
45
 
46
  <?php elseif ( $account_required ) : ?>
47
 
8
  * @author Automattic
9
  * @package WP Job Manager
10
  * @category Template
11
+ * @version 1.29.1
12
  */
13
 
14
  if ( ! defined( 'ABSPATH' ) ) {
30
  </fieldset>
31
 
32
  <?php else :
33
+ $account_required = job_manager_user_requires_account();
34
+ $registration_enabled = job_manager_enable_registration();
35
+ $registration_fields = wpjm_get_registration_fields();
36
+ $use_standard_password_email = wpjm_use_standard_password_setup_email();
37
  ?>
38
  <fieldset>
39
  <label><?php _e( 'Have an account?', 'wp-job-manager' ); ?></label>
42
 
43
  <?php if ( $registration_enabled ) : ?>
44
 
45
+ <?php printf( __( 'If you don&rsquo;t have an account you can %screate one below by entering your email address/username.', 'wp-job-manager' ), $account_required ? '' : __( 'optionally', 'wp-job-manager' ) . ' ' ); ?>
46
+ <?php if ( $use_standard_password_email ) : ?>
47
+ <?php printf( __( 'Your account details will be confirmed via email.', 'wp-job-manager' ) ); ?>
48
+ <?php endif; ?>
49
 
50
  <?php elseif ( $account_required ) : ?>
51
 
wp-job-manager-functions.php CHANGED
@@ -118,6 +118,13 @@ function get_job_listings( $args = array() ) {
118
  );
119
  }
120
 
 
 
 
 
 
 
 
121
  $job_manager_keyword = sanitize_text_field( $args['search_keywords'] );
122
 
123
  if ( ! empty( $job_manager_keyword ) && strlen( $job_manager_keyword ) >= apply_filters( 'job_manager_get_listings_keyword_length_threshold', 2 ) ) {
@@ -149,19 +156,22 @@ function get_job_listings( $args = array() ) {
149
 
150
  // Cache results
151
  if ( apply_filters( 'get_job_listings_cache_results', true ) ) {
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
159
- if ( $query_args[ 'orderby' ] == 'rand' ) {
160
- shuffle( $result->posts );
 
 
 
 
161
  }
162
-
163
- }
164
- else {
165
  $result = new WP_Query( $query_args );
166
  }
167
 
@@ -173,6 +183,30 @@ function get_job_listings( $args = array() ) {
173
  }
174
  endif;
175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  if ( ! function_exists( 'get_job_listings_keyword_search' ) ) :
177
  /**
178
  * Adds join and where query for keywords.
118
  );
119
  }
120
 
121
+ if ( 'rand_featured' === $args['orderby'] ) {
122
+ $query_args['orderby'] = array(
123
+ 'menu_order' => 'ASC',
124
+ 'rand' => 'ASC'
125
+ );
126
+ }
127
+
128
  $job_manager_keyword = sanitize_text_field( $args['search_keywords'] );
129
 
130
  if ( ! empty( $job_manager_keyword ) && strlen( $job_manager_keyword ) >= apply_filters( 'job_manager_get_listings_keyword_length_threshold', 2 ) ) {
156
 
157
  // Cache results
158
  if ( apply_filters( 'get_job_listings_cache_results', true ) ) {
159
+ $cached_query = true;
160
  if ( false === ( $result = get_transient( $query_args_hash ) ) ) {
161
  $result = new WP_Query( $query_args );
162
+ $cached_query = false;
163
  set_transient( $query_args_hash, $result, DAY_IN_SECONDS );
164
  }
165
 
166
+ if ( $cached_query ) {
167
+ // random order is cached so shuffle them
168
+ if ( 'rand_featured' === $args['orderby'] ) {
169
+ usort( $result->posts, '_wpjm_shuffle_featured_post_results_helper' );
170
+ } elseif ( 'rand' === $args['orderby'] ) {
171
+ shuffle( $result->posts );
172
+ }
173
  }
174
+ } else {
 
 
175
  $result = new WP_Query( $query_args );
176
  }
177
 
183
  }
184
  endif;
185
 
186
+ if ( ! function_exists( '_wpjm_shuffle_featured_post_results_helper' ) ) :
187
+ /**
188
+ * Helper function to maintain featured status when shuffling results.
189
+ *
190
+ * @param WP_Post $a
191
+ * @param WP_Post $b
192
+ *
193
+ * @return bool
194
+ */
195
+ function _wpjm_shuffle_featured_post_results_helper( $a, $b ) {
196
+ if ( -1 === $a->menu_order || -1 === $b->menu_order ) {
197
+ // Left is featured
198
+ if ( 0 === $b->menu_order ) {
199
+ return -1;
200
+ }
201
+ // Right is featured
202
+ if ( 0 === $a->menu_order ) {
203
+ return 1;
204
+ }
205
+ }
206
+ return rand( -1, 1 );
207
+ }
208
+ endif;
209
+
210
  if ( ! function_exists( 'get_job_listings_keyword_search' ) ) :
211
  /**
212
  * Adds join and where query for keywords.
wp-job-manager-template.php CHANGED
@@ -580,6 +580,10 @@ function wpjm_get_the_job_types( $post = null ) {
580
 
581
  $types = get_the_terms( $post->ID, 'job_listing_type' );
582
 
 
 
 
 
583
  // Return single if not enabled.
584
  if ( ! empty( $types ) && ! job_manager_multi_job_type() ) {
585
  $types = array( current( $types ) );
580
 
581
  $types = get_the_terms( $post->ID, 'job_listing_type' );
582
 
583
+ if ( empty( $types ) || is_wp_error( $types ) ) {
584
+ $types = array();
585
+ }
586
+
587
  // Return single if not enabled.
588
  if ( ! empty( $types ) && ! job_manager_multi_job_type() ) {
589
  $types = array( current( $types ) );
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.29.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+
@@ -58,29 +58,29 @@ class WP_Job_Manager {
58
  */
59
  public function __construct() {
60
  // Define constants
61
- define( 'JOB_MANAGER_VERSION', '1.29.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' );
69
- include_once( 'includes/class-wp-job-manager-shortcodes.php' );
70
- include_once( 'includes/class-wp-job-manager-api.php' );
71
- include_once( 'includes/class-wp-job-manager-forms.php' );
72
- include_once( 'includes/class-wp-job-manager-geocode.php' );
73
- include_once( 'includes/class-wp-job-manager-cache-helper.php' );
74
- include_once( 'includes/helper/class-wp-job-manager-helper.php' );
75
 
76
  add_action( 'rest_api_init', array( $this, 'rest_api' ) );
77
 
78
  if ( is_admin() ) {
79
- include_once( 'includes/admin/class-wp-job-manager-admin.php' );
80
  }
81
 
82
  // Load 3rd party customizations
83
- include_once( 'includes/3rd-party/3rd-party.php' );
84
 
85
  // Init classes
86
  $this->forms = WP_Job_Manager_Forms::instance();
@@ -147,9 +147,8 @@ class WP_Job_Manager {
147
  */
148
  public function rest_api() {
149
  if ( null === $this->rest_api ) {
150
- include( 'includes/rest-api/class-wp-job-manager-rest-api.php' );
151
  $this->rest_api = new WP_Job_Manager_REST_API( dirname( __FILE__ ) );
152
- $this->rest_api->init();
153
  }
154
  return $this->rest_api;
155
  }
@@ -158,18 +157,18 @@ class WP_Job_Manager {
158
  * Loads plugin's core helper template functions.
159
  */
160
  public function include_template_functions() {
161
- include_once( 'wp-job-manager-deprecated.php' );
162
- include_once( 'wp-job-manager-functions.php' );
163
- include_once( 'wp-job-manager-template.php' );
164
  }
165
 
166
  /**
167
  * Loads plugin's widgets.
168
  */
169
  public function widgets_init() {
170
- include_once( 'includes/class-wp-job-manager-widget.php' );
171
- include_once( 'includes/widgets/class-wp-job-manager-widget-recent-jobs.php' );
172
- include_once( 'includes/widgets/class-wp-job-manager-widget-featured-jobs.php' );
173
  }
174
 
175
  /**
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.29.1
7
  * Author: Automattic
8
  * Author URI: https://wpjobmanager.com/
9
  * Requires at least: 4.1
10
+ * Tested up to: 4.9
11
  * Text Domain: wp-job-manager
12
  * Domain Path: /languages/
13
  * License: GPL2+
58
  */
59
  public function __construct() {
60
  // Define constants
61
+ define( 'JOB_MANAGER_VERSION', '1.29.1' );
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( JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-install.php' );
67
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-post-types.php' );
68
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-ajax.php' );
69
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-shortcodes.php' );
70
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-api.php' );
71
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-forms.php' );
72
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-geocode.php' );
73
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-cache-helper.php' );
74
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/helper/class-wp-job-manager-helper.php' );
75
 
76
  add_action( 'rest_api_init', array( $this, 'rest_api' ) );
77
 
78
  if ( is_admin() ) {
79
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/admin/class-wp-job-manager-admin.php' );
80
  }
81
 
82
  // Load 3rd party customizations
83
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/3rd-party.php' );
84
 
85
  // Init classes
86
  $this->forms = WP_Job_Manager_Forms::instance();
147
  */
148
  public function rest_api() {
149
  if ( null === $this->rest_api ) {
150
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/rest-api/class-wp-job-manager-rest-api.php' );
151
  $this->rest_api = new WP_Job_Manager_REST_API( dirname( __FILE__ ) );
 
152
  }
153
  return $this->rest_api;
154
  }
157
  * Loads plugin's core helper template functions.
158
  */
159
  public function include_template_functions() {
160
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/wp-job-manager-deprecated.php' );
161
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/wp-job-manager-functions.php' );
162
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/wp-job-manager-template.php' );
163
  }
164
 
165
  /**
166
  * Loads plugin's widgets.
167
  */
168
  public function widgets_init() {
169
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-widget.php' );
170
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/widgets/class-wp-job-manager-widget-recent-jobs.php' );
171
+ include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/widgets/class-wp-job-manager-widget-featured-jobs.php' );
172
  }
173
 
174
  /**