WP Job Manager - Version 1.27.0

Version Description

  • 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)
  • Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1024)
  • Enhancement: Allows users to override permalink slugs in WP Admin's Permalink Settings screen. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1042)
  • Enhancement: Allows admins to perform bulk updating of jobs as filled/not filled. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1049)
  • Enhancement: Adds job listing status CSS classes on single job listings. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1041)
  • 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)
  • Enhancement: Allows admins to filter by post_status in [jobs] shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1051)
  • Enhancement: Allows accessing settings tab from hash in URL. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/999)
  • Fix: Make sure cron jobs for checking/cleaning expired listings are always in place. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1058)
  • Fix: Better handling of multiple job types. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/1014)
  • Fix: Issue with deleting company logos from job listings submission form. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1047)
  • Fix: Warning thrown on job submission form when user not logged in. (@piersb; https://github.com/Automattic/WP-Job-Manager/pull/1011)
  • Fix: Issue with WPML not syncing some meta fields. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1027)
  • Fix: Better handling of AJAX upload errors. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1044)
  • Fix: Remove job posting cookies on logout. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1065)
  • Fix: Expiration date can be cleared if default job duration option is empty. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/1076)
  • Fix: Issue with Safari and expiration datepicker. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1078)
Download this release

Release Info

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

Code changes from version 1.26.2 to 1.27.0

Files changed (44) hide show
  1. assets/js/admin.js +5 -2
  2. assets/js/admin.min.js +1 -1
  3. assets/js/ajax-file-upload.js +5 -0
  4. assets/js/ajax-file-upload.min.js +1 -1
  5. assets/js/ajax-filters.js +5 -0
  6. assets/js/ajax-filters.min.js +1 -1
  7. assets/js/job-application.js +4 -2
  8. assets/js/job-application.min.js +1 -1
  9. changelog.txt +19 -0
  10. includes/admin/class-wp-job-manager-addons.php +2 -2
  11. includes/admin/class-wp-job-manager-admin.php +25 -2
  12. includes/admin/class-wp-job-manager-cpt-legacy.php +84 -0
  13. includes/admin/class-wp-job-manager-cpt.php +181 -101
  14. includes/admin/class-wp-job-manager-permalink-settings.php +130 -0
  15. includes/admin/class-wp-job-manager-settings.php +50 -8
  16. includes/admin/class-wp-job-manager-setup.php +2 -2
  17. includes/admin/class-wp-job-manager-writepanels.php +77 -7
  18. includes/class-wp-job-manager-ajax.php +13 -11
  19. includes/class-wp-job-manager-api.php +2 -2
  20. includes/class-wp-job-manager-cache-helper.php +105 -0
  21. includes/class-wp-job-manager-category-walker.php +1 -1
  22. includes/class-wp-job-manager-forms.php +2 -2
  23. includes/class-wp-job-manager-geocode.php +2 -2
  24. includes/class-wp-job-manager-install.php +0 -13
  25. includes/class-wp-job-manager-post-types.php +47 -41
  26. includes/class-wp-job-manager-shortcodes.php +29 -20
  27. includes/forms/class-wp-job-manager-form-submit-job.php +42 -5
  28. languages/wp-job-manager.pot +260 -190
  29. readme.txt +26 -7
  30. templates/account-signin.php +17 -20
  31. templates/content-job_listing.php +20 -3
  32. templates/content-single-job_listing-meta.php +13 -2
  33. templates/content-single-job_listing.php +1 -1
  34. templates/content-summary-job_listing.php +7 -2
  35. templates/content-widget-job_listing.php +5 -2
  36. templates/form-fields/password-field.php +2 -2
  37. templates/form-fields/text-field.php +2 -2
  38. templates/job-dashboard.php +2 -2
  39. templates/job-preview.php +1 -1
  40. wp-job-manager-deprecated.php +73 -0
  41. wp-job-manager-functions.php +116 -22
  42. wp-job-manager-template.php +164 -33
  43. wp-job-manager.php +49 -17
  44. wpml-config.xml +7 -0
assets/js/admin.js CHANGED
@@ -23,8 +23,11 @@ jQuery(document).ready(function($) {
23
 
24
  $( 'input.job-manager-datepicker, input#_job_expires' ).each( function(){
25
  if ( $(this).val() ) {
26
- var date = new Date( $(this).val() );
27
- $(this).datepicker( 'setDate', date );
 
 
 
28
  }
29
  });
30
 
23
 
24
  $( 'input.job-manager-datepicker, input#_job_expires' ).each( function(){
25
  if ( $(this).val() ) {
26
+ var dateParts = $(this).val().split("-");
27
+ if ( 3 === dateParts.length ) {
28
+ var selectedDate = new Date(parseInt(dateParts[0], 10), (parseInt(dateParts[1], 10) - 1), parseInt(dateParts[2], 10));
29
+ $(this).datepicker('setDate', selectedDate);
30
+ }
31
  }
32
  });
33
 
assets/js/admin.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(a){a(".tips, .help_tip").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:200}),a("p.form-field-author").on("click","a.change-author",function(){return a(this).closest("p").find(".current-author").hide(),a(this).closest("p").find(".change-author").show(),!1}),a("input.job-manager-datepicker, input#_job_expires").datepicker({altFormat:"yy-mm-dd",dateFormat:job_manager_admin.date_format}),a("input.job-manager-datepicker, input#_job_expires").each(function(){if(a(this).val()){var b=new Date(a(this).val());a(this).datepicker("setDate",b)}});var b,c,d;a(document).on("click",".wp_job_manager_add_another_file_button",function(b){b.preventDefault();var c=a(this).data("field_name"),d=a(this).data("field_placeholder"),e=a(this).data("uploader_button_text"),f=a(this).data("uploader_button"),g=a(this).data("view_button");a(this).before('<span class="file_url"><input type="text" name="'+c+'[]" placeholder="'+d+'" /><button class="button button-small wp_job_manager_upload_file_button" data-uploader_button_text="'+e+'">'+f+'</button><button class="button button-small wp_job_manager_view_file_button">'+g+"</button></span>")}),a(document).on("click",".wp_job_manager_view_file_button",function(b){b.preventDefault(),d=a(this).closest(".file_url"),c=d.find("input");var e=c.val();e.indexOf("://")>-1?window.open(e,"_blank"):(c.addClass("file_no_url"),setTimeout(function(){c.removeClass("file_no_url")},1e3))}),a(document).on("click",".wp_job_manager_upload_file_button",function(e){return e.preventDefault(),d=a(this).closest(".file_url"),c=d.find("input"),b?void b.open():(b=wp.media.frames.file_frame=wp.media({title:a(this).data("uploader_title"),button:{text:a(this).data("uploader_button_text")},multiple:!1}),b.on("select",function(){var d=b.state().get("selection").first().toJSON();a(c).val(d.url)}),void b.open())})}),jQuery(document).ready(function(a){var b="job_listing_type";a("#"+b+"checklist li :radio, #"+b+"checklist-pop :radio").live("click",function(){var c=a(this),d=c.is(":checked"),e=c.val();a("#"+b+"checklist li :radio, #"+b+"checklist-pop :radio").prop("checked",!1),a("#in-"+b+"-"+e+", #in-popular-"+b+"-"+e).prop("checked",d)})});
1
+ jQuery(document).ready(function(a){a(".tips, .help_tip").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:200}),a("p.form-field-author").on("click","a.change-author",function(){return a(this).closest("p").find(".current-author").hide(),a(this).closest("p").find(".change-author").show(),!1}),a("input.job-manager-datepicker, input#_job_expires").datepicker({altFormat:"yy-mm-dd",dateFormat:job_manager_admin.date_format}),a("input.job-manager-datepicker, input#_job_expires").each(function(){if(a(this).val()){var b=a(this).val().split("-");if(3===b.length){var c=new Date(parseInt(b[0],10),parseInt(b[1],10)-1,parseInt(b[2],10));a(this).datepicker("setDate",c)}}});var b,c,d;a(document).on("click",".wp_job_manager_add_another_file_button",function(b){b.preventDefault();var c=a(this).data("field_name"),d=a(this).data("field_placeholder"),e=a(this).data("uploader_button_text"),f=a(this).data("uploader_button"),g=a(this).data("view_button");a(this).before('<span class="file_url"><input type="text" name="'+c+'[]" placeholder="'+d+'" /><button class="button button-small wp_job_manager_upload_file_button" data-uploader_button_text="'+e+'">'+f+'</button><button class="button button-small wp_job_manager_view_file_button">'+g+"</button></span>")}),a(document).on("click",".wp_job_manager_view_file_button",function(b){b.preventDefault(),d=a(this).closest(".file_url"),c=d.find("input");var e=c.val();e.indexOf("://")>-1?window.open(e,"_blank"):(c.addClass("file_no_url"),setTimeout(function(){c.removeClass("file_no_url")},1e3))}),a(document).on("click",".wp_job_manager_upload_file_button",function(e){if(e.preventDefault(),d=a(this).closest(".file_url"),c=d.find("input"),b)return void b.open();b=wp.media.frames.file_frame=wp.media({title:a(this).data("uploader_title"),button:{text:a(this).data("uploader_button_text")},multiple:!1}),b.on("select",function(){var d=b.state().get("selection").first().toJSON();a(c).val(d.url)}),b.open()})}),jQuery(document).ready(function(a){var b="job_listing_type";a("#"+b+"checklist li :radio, #"+b+"checklist-pop :radio").live("click",function(){var c=a(this),d=c.is(":checked"),e=c.val();a("#"+b+"checklist li :radio, #"+b+"checklist-pop :radio").prop("checked",!1),a("#in-"+b+"-"+e+", #in-popular-"+b+"-"+e).prop("checked",d)})});
assets/js/ajax-file-upload.js CHANGED
@@ -59,6 +59,11 @@ jQuery(function($) {
59
 
60
  data.context.remove();
61
 
 
 
 
 
 
62
  $.each(data.result.files, function(index, file) {
63
  if ( file.error ) {
64
  window.alert( file.error );
59
 
60
  data.context.remove();
61
 
62
+ // Handle JSON errors when success is false
63
+ if( typeof data.result.success !== 'undefined' && ! data.result.success ){
64
+ window.alert( data.result.data );
65
+ }
66
+
67
  $.each(data.result.files, function(index, file) {
68
  if ( file.error ) {
69
  window.alert( file.error );
assets/js/ajax-file-upload.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(function(a){a(".wp-job-manager-file-upload").each(function(){a(this).fileupload({dataType:"json",dropZone:a(this),url:job_manager_ajax_file_upload.ajax_url.toString().replace("%%endpoint%%","upload_file"),maxNumberOfFiles:1,formData:{script:!0},add:function(b,c){var d=a(this),e=d.closest("form"),f=d.parent().find(".job-manager-uploaded-files"),g=[],h=a(this).data("file_types");if(h){var i=new RegExp("(.|/)("+h+")$","i");c.originalFiles[0].name.length&&!i.test(c.originalFiles[0].name)&&g.push(job_manager_ajax_file_upload.i18n_invalid_file_type+" "+h)}g.length>0?window.alert(g.join("\n")):(e.find(':input[type="submit"]').attr("disabled","disabled"),c.context=a('<progress value="" max="100"></progress>').appendTo(f),c.submit())},progress:function(a,b){var c=parseInt(b.loaded/b.total*100,10);b.context.val(c)},fail:function(b,c){var d=a(this),e=d.closest("form");c.errorThrown&&window.alert(c.errorThrown),c.context.remove(),e.find(':input[type="submit"]').removeAttr("disabled")},done:function(b,c){var d=a(this),e=d.closest("form"),f=d.parent().find(".job-manager-uploaded-files"),g=d.attr("multiple")?1:0,h=["jpg","gif","png","jpeg","jpe"];c.context.remove(),a.each(c.result.files,function(b,c){if(c.error)window.alert(c.error);else{var e;a.inArray(c.extension,h)>=0?(e=a.parseHTML(job_manager_ajax_file_upload.js_field_html_img),a(e).find(".job-manager-uploaded-file-preview img").attr("src",c.url)):(e=a.parseHTML(job_manager_ajax_file_upload.js_field_html),a(e).find(".job-manager-uploaded-file-name code").text(c.name)),a(e).find(".input-text").val(c.url),a(e).find(".input-text").attr("name","current_"+d.attr("name")),g?f.append(e):f.html(e)}}),e.find(':input[type="submit"]').removeAttr("disabled")}})})});
1
+ jQuery(function(a){a(".wp-job-manager-file-upload").each(function(){a(this).fileupload({dataType:"json",dropZone:a(this),url:job_manager_ajax_file_upload.ajax_url.toString().replace("%%endpoint%%","upload_file"),maxNumberOfFiles:1,formData:{script:!0},add:function(b,c){var d=a(this),e=d.closest("form"),f=d.parent().find(".job-manager-uploaded-files"),g=[],h=a(this).data("file_types");if(h){var i=new RegExp("(.|/)("+h+")$","i");c.originalFiles[0].name.length&&!i.test(c.originalFiles[0].name)&&g.push(job_manager_ajax_file_upload.i18n_invalid_file_type+" "+h)}g.length>0?window.alert(g.join("\n")):(e.find(':input[type="submit"]').attr("disabled","disabled"),c.context=a('<progress value="" max="100"></progress>').appendTo(f),c.submit())},progress:function(a,b){var c=parseInt(b.loaded/b.total*100,10);b.context.val(c)},fail:function(b,c){var d=a(this),e=d.closest("form");c.errorThrown&&window.alert(c.errorThrown),c.context.remove(),e.find(':input[type="submit"]').removeAttr("disabled")},done:function(b,c){var d=a(this),e=d.closest("form"),f=d.parent().find(".job-manager-uploaded-files"),g=d.attr("multiple")?1:0,h=["jpg","gif","png","jpeg","jpe"];c.context.remove(),void 0===c.result.success||c.result.success||window.alert(c.result.data),a.each(c.result.files,function(b,c){if(c.error)window.alert(c.error);else{var e;a.inArray(c.extension,h)>=0?(e=a.parseHTML(job_manager_ajax_file_upload.js_field_html_img),a(e).find(".job-manager-uploaded-file-preview img").attr("src",c.url)):(e=a.parseHTML(job_manager_ajax_file_upload.js_field_html),a(e).find(".job-manager-uploaded-file-name code").text(c.name)),a(e).find(".input-text").val(c.url),a(e).find(".input-text").attr("name","current_"+d.attr("name")),g?f.append(e):f.html(e)}}),e.find(':input[type="submit"]').removeAttr("disabled")}})})});
assets/js/ajax-filters.js CHANGED
@@ -14,6 +14,8 @@ jQuery( document ).ready( function ( $ ) {
14
  var order = target.data( 'order' );
15
  var featured = target.data( 'featured' );
16
  var filled = target.data( 'filled' );
 
 
17
  var index = $( 'div.job_listings' ).index(this);
18
  var categories, keywords, location;
19
 
@@ -70,6 +72,7 @@ jQuery( document ).ready( function ( $ ) {
70
  search_location: location,
71
  search_categories: categories,
72
  filter_job_type: filter_job_type,
 
73
  per_page: per_page,
74
  orderby: orderby,
75
  order: order,
@@ -95,6 +98,8 @@ jQuery( document ).ready( function ( $ ) {
95
  search_categories: categories,
96
  search_keywords: keywords,
97
  search_location: location,
 
 
98
  per_page: per_page,
99
  orderby: orderby,
100
  order: order,
14
  var order = target.data( 'order' );
15
  var featured = target.data( 'featured' );
16
  var filled = target.data( 'filled' );
17
+ var job_types = target.data( 'job_types' );
18
+ var post_status = target.data( 'post_status' );
19
  var index = $( 'div.job_listings' ).index(this);
20
  var categories, keywords, location;
21
 
72
  search_location: location,
73
  search_categories: categories,
74
  filter_job_type: filter_job_type,
75
+ filter_post_status: post_status,
76
  per_page: per_page,
77
  orderby: orderby,
78
  order: order,
98
  search_categories: categories,
99
  search_keywords: keywords,
100
  search_location: location,
101
+ filter_post_status: post_status,
102
+ filter_job_type: job_types,
103
  per_page: per_page,
104
  orderby: orderby,
105
  order: order,
assets/js/ajax-filters.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(a){function b(b,c){if(d){var f=b.find(".job_filters"),g=a(f).serialize(),h=a("div.job_listings").index(b);window.history.replaceState({id:"job_manager_state",page:c,data:g,index:h},"",e+"#s=1")}}var c=[];a(".job_listings").on("update_results",function(b,d,e,f){var g,h,i,j="",k=a(this),l=k.find(".job_filters"),m=k.find(".showing_jobs"),n=k.find(".job_listings"),o=k.data("per_page"),p=k.data("orderby"),q=k.data("order"),r=k.data("featured"),s=k.data("filled"),t=a("div.job_listings").index(this);if(!(0>t)){if(c[t]&&c[t].abort(),e||(a(n).addClass("loading"),a("li.job_listing, li.no_job_listings_found",n).css("visibility","hidden"),d>1&&!0!==k.data("show_pagination")?a(n).before('<a class="load_more_jobs load_previous" href="#"><strong>'+job_manager_ajax_filters.i18n_load_prev_listings+"</strong></a>"):k.find(".load_previous").remove(),k.find(".load_more_jobs").data("page",d)),!0===k.data("show_filters")){var u=[];a(':input[name="filter_job_type[]"]:checked, :input[name="filter_job_type[]"][type="hidden"], :input[name="filter_job_type"]',l).each(function(){u.push(a(this).val())}),g=l.find(':input[name^="search_categories"]').map(function(){return a(this).val()}).get(),h="",i="";var v=l.find(':input[name="search_keywords"]'),w=l.find(':input[name="search_location"]');v.val()!==v.attr("placeholder")&&(h=v.val()),w.val()!==w.attr("placeholder")&&(i=w.val()),j={lang:job_manager_ajax_filters.lang,search_keywords:h,search_location:i,search_categories:g,filter_job_type:u,per_page:o,orderby:p,order:q,page:d,featured:r,filled:s,show_pagination:k.data("show_pagination"),form_data:l.serialize()}}else g=k.data("categories"),h=k.data("keywords"),i=k.data("location"),g&&(g=g.split(",")),j={lang:job_manager_ajax_filters.lang,search_categories:g,search_keywords:h,search_location:i,per_page:o,orderby:p,order:q,page:d,featured:r,filled:s,show_pagination:k.data("show_pagination")};c[t]=a.ajax({type:"POST",url:job_manager_ajax_filters.ajax_url.toString().replace("%%endpoint%%","get_listings"),data:j,success:function(b){if(b)try{b.showing?a(m).show().html("<span>"+b.showing+"</span>"+b.showing_links):a(m).hide(),b.showing_all?a(m).addClass("wp-job-manager-showing-all"):a(m).removeClass("wp-job-manager-showing-all"),b.html&&(e&&f?a(n).prepend(b.html):e?a(n).append(b.html):a(n).html(b.html)),!0===k.data("show_pagination")?(k.find(".job-manager-pagination").remove(),b.pagination&&k.append(b.pagination)):(!b.found_jobs||b.max_num_pages<=d?a(".load_more_jobs:not(.load_previous)",k).hide():f||a(".load_more_jobs",k).show(),a(".load_more_jobs",k).removeClass("loading"),a("li.job_listing",n).css("visibility","visible")),a(n).removeClass("loading"),k.triggerHandler("updated_results",b)}catch(c){window.console&&window.console.log(c)}},error:function(a,b,c){window.console&&"abort"!==b&&window.console.log(b+": "+c)},statusCode:{404:function(){window.console&&window.console.log("Error 404: Ajax Endpoint cannot be reached. Go to Settings > Permalinks and save to resolve.")}}})}}),a("#search_keywords, #search_location, .job_types :input, #search_categories, .job-manager-filter").change(function(){var c=a(this).closest("div.job_listings");c.triggerHandler("update_results",[1,!1]),b(c,1)}).on("keyup",function(b){13===b.which&&a(this).trigger("change")}),a(".job_filters").on("click",".reset",function(){var c=a(this).closest("div.job_listings"),d=a(this).closest("form");return d.find(':input[name="search_keywords"], :input[name="search_location"], .job-manager-filter').not(':input[type="hidden"]').val("").trigger("chosen:updated"),d.find(':input[name^="search_categories"]').not(':input[type="hidden"]').val(0).trigger("chosen:updated"),a(':input[name="filter_job_type[]"]',d).not(':input[type="hidden"]').attr("checked","checked"),c.triggerHandler("reset"),c.triggerHandler("update_results",[1,!1]),b(c,1),!1}),a(document.body).on("click",".load_more_jobs",function(){var c=a(this).closest("div.job_listings"),d=parseInt(a(this).data("page")||1,10),e=!1;return a(this).addClass("loading"),a(this).is(".load_previous")?(d-=1,e=!0,1===d?a(this).remove():a(this).data("page",d)):(d+=1,a(this).data("page",d),b(c,d)),c.triggerHandler("update_results",[d,!0,e]),!1}),a("div.job_listings").on("click",".job-manager-pagination a",function(){var c=a(this).closest("div.job_listings"),d=a(this).data("page");return b(c,d),c.triggerHandler("update_results",[d,!1]),a("body, html").animate({scrollTop:c.offset().top},600),!1}),a.isFunction(a.fn.chosen)&&(1===job_manager_ajax_filters.is_rtl&&a('select[name^="search_categories"]').addClass("chosen-rtl"),a('select[name^="search_categories"]').chosen({search_contains:!0}));var d=!1;window.history&&window.history.pushState&&(d=!0);var e=document.location.href.split("#")[0];a(window).on("load",function(){a(".job_filters").each(function(){var b=a(this).closest("div.job_listings"),c=b.find(".job_filters"),d=1,e=a("div.job_listings").index(b);if(window.history.state&&window.location.hash){var f=window.history.state;f.id&&"job_manager_state"===f.id&&e===f.index&&(d=f.page,c.deserialize(f.data),c.find(':input[name^="search_categories"]').not(':input[type="hidden"]').trigger("chosen:updated"))}b.triggerHandler("update_results",[d,!1])})})});
1
+ jQuery(document).ready(function(a){function b(b,c){if(d){var f=b.find(".job_filters"),g=a(f).serialize(),h=a("div.job_listings").index(b);window.history.replaceState({id:"job_manager_state",page:c,data:g,index:h},"",e+"#s=1")}}var c=[];a(".job_listings").on("update_results",function(b,d,e,f){var g,h,i,j="",k=a(this),l=k.find(".job_filters"),m=k.find(".showing_jobs"),n=k.find(".job_listings"),o=k.data("per_page"),p=k.data("orderby"),q=k.data("order"),r=k.data("featured"),s=k.data("filled"),t=k.data("job_types"),u=k.data("post_status"),v=a("div.job_listings").index(this);if(!(v<0)){if(c[v]&&c[v].abort(),e||(a(n).addClass("loading"),a("li.job_listing, li.no_job_listings_found",n).css("visibility","hidden"),d>1&&!0!==k.data("show_pagination")?a(n).before('<a class="load_more_jobs load_previous" href="#"><strong>'+job_manager_ajax_filters.i18n_load_prev_listings+"</strong></a>"):k.find(".load_previous").remove(),k.find(".load_more_jobs").data("page",d)),!0===k.data("show_filters")){var w=[];a(':input[name="filter_job_type[]"]:checked, :input[name="filter_job_type[]"][type="hidden"], :input[name="filter_job_type"]',l).each(function(){w.push(a(this).val())}),g=l.find(':input[name^="search_categories"]').map(function(){return a(this).val()}).get(),h="",i="";var x=l.find(':input[name="search_keywords"]'),y=l.find(':input[name="search_location"]');x.val()!==x.attr("placeholder")&&(h=x.val()),y.val()!==y.attr("placeholder")&&(i=y.val()),j={lang:job_manager_ajax_filters.lang,search_keywords:h,search_location:i,search_categories:g,filter_job_type:w,filter_post_status:u,per_page:o,orderby:p,order:q,page:d,featured:r,filled:s,show_pagination:k.data("show_pagination"),form_data:l.serialize()}}else g=k.data("categories"),h=k.data("keywords"),i=k.data("location"),g&&(g=g.split(",")),j={lang:job_manager_ajax_filters.lang,search_categories:g,search_keywords:h,search_location:i,filter_post_status:u,filter_job_type:t,per_page:o,orderby:p,order:q,page:d,featured:r,filled:s,show_pagination:k.data("show_pagination")};c[v]=a.ajax({type:"POST",url:job_manager_ajax_filters.ajax_url.toString().replace("%%endpoint%%","get_listings"),data:j,success:function(b){if(b)try{b.showing?a(m).show().html("<span>"+b.showing+"</span>"+b.showing_links):a(m).hide(),b.showing_all?a(m).addClass("wp-job-manager-showing-all"):a(m).removeClass("wp-job-manager-showing-all"),b.html&&(e&&f?a(n).prepend(b.html):e?a(n).append(b.html):a(n).html(b.html)),!0===k.data("show_pagination")?(k.find(".job-manager-pagination").remove(),b.pagination&&k.append(b.pagination)):(!b.found_jobs||b.max_num_pages<=d?a(".load_more_jobs:not(.load_previous)",k).hide():f||a(".load_more_jobs",k).show(),a(".load_more_jobs",k).removeClass("loading"),a("li.job_listing",n).css("visibility","visible")),a(n).removeClass("loading"),k.triggerHandler("updated_results",b)}catch(c){window.console&&window.console.log(c)}},error:function(a,b,c){window.console&&"abort"!==b&&window.console.log(b+": "+c)},statusCode:{404:function(){window.console&&window.console.log("Error 404: Ajax Endpoint cannot be reached. Go to Settings > Permalinks and save to resolve.")}}})}}),a("#search_keywords, #search_location, .job_types :input, #search_categories, .job-manager-filter").change(function(){var c=a(this).closest("div.job_listings");c.triggerHandler("update_results",[1,!1]),b(c,1)}).on("keyup",function(b){13===b.which&&a(this).trigger("change")}),a(".job_filters").on("click",".reset",function(){var c=a(this).closest("div.job_listings"),d=a(this).closest("form");return d.find(':input[name="search_keywords"], :input[name="search_location"], .job-manager-filter').not(':input[type="hidden"]').val("").trigger("chosen:updated"),d.find(':input[name^="search_categories"]').not(':input[type="hidden"]').val(0).trigger("chosen:updated"),a(':input[name="filter_job_type[]"]',d).not(':input[type="hidden"]').attr("checked","checked"),c.triggerHandler("reset"),c.triggerHandler("update_results",[1,!1]),b(c,1),!1}),a(document.body).on("click",".load_more_jobs",function(){var c=a(this).closest("div.job_listings"),d=parseInt(a(this).data("page")||1,10),e=!1;return a(this).addClass("loading"),a(this).is(".load_previous")?(d-=1,e=!0,1===d?a(this).remove():a(this).data("page",d)):(d+=1,a(this).data("page",d),b(c,d)),c.triggerHandler("update_results",[d,!0,e]),!1}),a("div.job_listings").on("click",".job-manager-pagination a",function(){var c=a(this).closest("div.job_listings"),d=a(this).data("page");return b(c,d),c.triggerHandler("update_results",[d,!1]),a("body, html").animate({scrollTop:c.offset().top},600),!1}),a.isFunction(a.fn.chosen)&&(1===job_manager_ajax_filters.is_rtl&&a('select[name^="search_categories"]').addClass("chosen-rtl"),a('select[name^="search_categories"]').chosen({search_contains:!0}));var d=!1;window.history&&window.history.pushState&&(d=!0);var e=document.location.href.split("#")[0];a(window).on("load",function(){a(".job_filters").each(function(){var b=a(this).closest("div.job_listings"),c=b.find(".job_filters"),d=1,e=a("div.job_listings").index(b);if(window.history.state&&window.location.hash){var f=window.history.state;f.id&&"job_manager_state"===f.id&&e===f.index&&(d=f.page,c.deserialize(f.data),c.find(':input[name^="search_categories"]').not(':input[type="hidden"]').trigger("chosen:updated"))}b.triggerHandler("update_results",[d,!1])})})});
assets/js/job-application.js CHANGED
@@ -1,7 +1,9 @@
1
  jQuery(document).ready(function($) {
2
  // Slide toggle
3
- $( '.application_details' ).hide();
 
 
4
  $( '.application_button' ).click(function() {
5
  $( '.application_details' ).slideToggle();
6
  });
7
- });
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
+ });
assets/js/job-application.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(a){a(".application_details").hide(),a(".application_button").click(function(){a(".application_details").slideToggle()})});
1
+ jQuery(document).ready(function(a){a("body").hasClass("job-application-details-keep-open")||a(".application_details").hide(),a(".application_button").click(function(){a(".application_details").slideToggle()})});
changelog.txt CHANGED
@@ -1,3 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 1.26.2 =
2
  * 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)
3
  * 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)
1
+ = 1.27.0 =
2
+ * Enhancement: Admins can now allow users to specify an account password when posting their first job listing. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1063)
3
+ * Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1024)
4
+ * Enhancement: Allows users to override permalink slugs in WP Admin's Permalink Settings screen. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1042)
5
+ * Enhancement: Allows admins to perform bulk updating of jobs as filled/not filled. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1049)
6
+ * Enhancement: Adds job listing status CSS classes on single job listings. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1041)
7
+ * 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)
8
+ * Enhancement: Allows admins to filter by `post_status` in `[jobs]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1051)
9
+ * Enhancement: Allows accessing settings tab from hash in URL. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/999)
10
+ * Fix: Make sure cron jobs for checking/cleaning expired listings are always in place. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1058)
11
+ * Fix: Better handling of multiple job types. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/1014)
12
+ * Fix: Issue with deleting company logos from job listings submission form. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1047)
13
+ * Fix: Warning thrown on job submission form when user not logged in. (@piersb; https://github.com/Automattic/WP-Job-Manager/pull/1011)
14
+ * Fix: Issue with WPML not syncing some meta fields. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1027)
15
+ * Fix: Better handling of AJAX upload errors. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1044)
16
+ * Fix: Remove job posting cookies on logout. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1065)
17
+ * Fix: Expiration date can be cleared if default job duration option is empty. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/1076)
18
+ * Fix: Issue with Safari and expiration datepicker. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1078)
19
+
20
  = 1.26.2 =
21
  * 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)
22
  * 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)
includes/admin/class-wp-job-manager-addons.php CHANGED
@@ -19,14 +19,14 @@ class WP_Job_Manager_Addons {
19
  * The single instance of the class.
20
  *
21
  * @var self
22
- * @since 1.26
23
  */
24
  private static $_instance = null;
25
 
26
  /**
27
  * Allows for accessing single instance of class. Class should only be constructed once per call.
28
  *
29
- * @since 1.26
30
  * @static
31
  * @return self Main instance.
32
  */
19
  * The single instance of the class.
20
  *
21
  * @var self
22
+ * @since 1.26.0
23
  */
24
  private static $_instance = null;
25
 
26
  /**
27
  * Allows for accessing single instance of class. Class should only be constructed once per call.
28
  *
29
+ * @since 1.26.0
30
  * @static
31
  * @return self Main instance.
32
  */
includes/admin/class-wp-job-manager-admin.php CHANGED
@@ -14,14 +14,14 @@ class WP_Job_Manager_Admin {
14
  * The single instance of the class.
15
  *
16
  * @var self
17
- * @since 1.26
18
  */
19
  private static $_instance = null;
20
 
21
  /**
22
  * Allows for accessing single instance of class. Class should only be constructed once per call.
23
  *
24
- * @since 1.26
25
  * @static
26
  * @return self Main instance.
27
  */
@@ -36,17 +36,40 @@ class WP_Job_Manager_Admin {
36
  * Constructor.
37
  */
38
  public function __construct() {
 
 
39
  include_once( 'class-wp-job-manager-cpt.php' );
 
 
 
 
 
 
40
  include_once( 'class-wp-job-manager-settings.php' );
41
  include_once( 'class-wp-job-manager-writepanels.php' );
42
  include_once( 'class-wp-job-manager-setup.php' );
43
 
44
  $this->settings_page = WP_Job_Manager_Settings::instance();
45
 
 
46
  add_action( 'admin_menu', array( $this, 'admin_menu' ), 12 );
47
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
48
  }
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  /**
51
  * Enqueues CSS and JS assets.
52
  */
14
  * The single instance of the class.
15
  *
16
  * @var self
17
+ * @since 1.26.0
18
  */
19
  private static $_instance = null;
20
 
21
  /**
22
  * Allows for accessing single instance of class. Class should only be constructed once per call.
23
  *
24
+ * @since 1.26.0
25
  * @static
26
  * @return self Main instance.
27
  */
36
  * Constructor.
37
  */
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
 
54
+ add_action( 'current_screen', array( $this, 'conditional_includes' ) );
55
  add_action( 'admin_menu', array( $this, 'admin_menu' ), 12 );
56
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
57
  }
58
 
59
+ /**
60
+ * Include admin files conditionally.
61
+ */
62
+ public function conditional_includes() {
63
+ if ( ! $screen = get_current_screen() ) {
64
+ return;
65
+ }
66
+ switch ( $screen->id ) {
67
+ case 'options-permalink' :
68
+ include( 'class-wp-job-manager-permalink-settings.php' );
69
+ break;
70
+ }
71
+ }
72
+
73
  /**
74
  * Enqueues CSS and JS assets.
75
  */
includes/admin/class-wp-job-manager-cpt-legacy.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ /**
6
+ * Handles legacy actions and filters specific to the custom post type for Job Listings.
7
+ *
8
+ * @package wp-job-manager
9
+ * @since 1.27.0
10
+ */
11
+ class WP_Job_Manager_CPT_Legacy extends WP_Job_Manager_CPT {
12
+ /**
13
+ * The single instance of the class.
14
+ *
15
+ * @var self
16
+ * @since 1.27.0
17
+ */
18
+ private static $_instance = null;
19
+
20
+ /**
21
+ * Allows for accessing single instance of class. Class should only be constructed once per call.
22
+ *
23
+ * @since 1.27.0
24
+ * @static
25
+ * @return self Main instance.
26
+ */
27
+ public static function instance() {
28
+ if ( is_null( self::$_instance ) ) {
29
+ self::$_instance = new self();
30
+ }
31
+
32
+ return self::$_instance;
33
+ }
34
+
35
+ /**
36
+ * Constructor.
37
+ */
38
+ public function __construct() {
39
+ parent::__construct();
40
+ add_action( 'admin_footer-edit.php', array( $this, 'add_bulk_actions_legacy' ) );
41
+ add_action( 'load-edit.php', array( $this, 'do_bulk_actions_legacy' ) );
42
+ remove_action( 'bulk_actions-edit-job_listing', array( $this, 'add_bulk_actions' ) );
43
+ }
44
+
45
+ /**
46
+ * Adds bulk actions to drop downs on Job Listing admin page.
47
+ */
48
+ public function add_bulk_actions_legacy() {
49
+ global $post_type, $wp_post_types;
50
+
51
+ if ( $post_type === 'job_listing' ) {
52
+ ?>
53
+ <script type="text/javascript">
54
+ jQuery(document).ready(function() {
55
+ <?php
56
+ foreach( $this->get_bulk_actions() as $key => $bulk_action ) {
57
+ if ( isset( $bulk_action[ 'label' ] ) ) {
58
+ echo 'jQuery(\'<option>\').val(\'' . $key . '\').text(\'' . addslashes( sprintf( $bulk_action[ 'label' ], $wp_post_types[ 'job_listing' ]->labels->name ) ) . '\').appendTo("select[name=\'action\']");';
59
+ echo 'jQuery(\'<option>\').val(\'' . $key . '\').text(\'' . addslashes( sprintf( $bulk_action[ 'label' ], $wp_post_types[ 'job_listing' ]->labels->name ) ) . '\').appendTo("select[name=\'action2\']");';
60
+ }
61
+ }
62
+ ?>
63
+ });
64
+ </script>
65
+ <?php
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Performs bulk actions on Job Listing admin page.
71
+ */
72
+ public function do_bulk_actions_legacy() {
73
+ $wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
74
+ $action = $wp_list_table->current_action();
75
+ $actions_handled = $this->get_bulk_actions();
76
+ if ( isset ( $actions_handled[ $action ] ) && isset ( $actions_handled[ $action ]['handler'] ) ) {
77
+ check_admin_referer( 'bulk-posts' );
78
+ $post_ids = array_map( 'absint', array_filter( (array) $_GET['post'] ) );
79
+ if ( ! empty( $post_ids ) ) {
80
+ $this->do_bulk_actions( admin_url( 'edit.php?post_type=job_listing' ), $action, $post_ids );
81
+ }
82
+ }
83
+ }
84
+ }
includes/admin/class-wp-job-manager-cpt.php CHANGED
@@ -14,14 +14,14 @@ class WP_Job_Manager_CPT {
14
  * The single instance of the class.
15
  *
16
  * @var self
17
- * @since 1.26
18
  */
19
  private static $_instance = null;
20
 
21
  /**
22
  * Allows for accessing single instance of class. Class should only be constructed once per call.
23
  *
24
- * @since 1.26
25
  * @static
26
  * @return self Main instance.
27
  */
@@ -46,11 +46,10 @@ class WP_Job_Manager_CPT {
46
  add_action( 'parse_query', array( $this, 'search_meta' ) );
47
  add_filter( 'get_search_query', array( $this, 'search_meta_label' ) );
48
  add_filter( 'post_updated_messages', array( $this, 'post_updated_messages' ) );
49
- add_action( 'admin_footer-edit.php', array( $this, 'add_bulk_actions' ) );
50
- add_action( 'load-edit.php', array( $this, 'do_bulk_actions' ) );
51
  add_action( 'admin_init', array( $this, 'approve_job' ) );
52
- add_action( 'admin_notices', array( $this, 'approved_notice' ) );
53
- add_action( 'admin_notices', array( $this, 'expired_notice' ) );
54
 
55
  if ( get_option( 'job_manager_enable_categories' ) ) {
56
  add_action( "restrict_manage_posts", array( $this, "jobs_by_category" ) );
@@ -61,77 +60,166 @@ class WP_Job_Manager_CPT {
61
  }
62
  }
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  /**
65
  * Adds bulk actions to drop downs on Job Listing admin page.
 
 
 
66
  */
67
- public function add_bulk_actions() {
68
- global $post_type, $wp_post_types;;
69
-
70
- if ( $post_type == 'job_listing' ) {
71
- ?>
72
- <script type="text/javascript">
73
- jQuery(document).ready(function() {
74
- jQuery('<option>').val('approve_jobs').text('<?php printf( __( 'Approve %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name ); ?>').appendTo("select[name='action']");
75
- jQuery('<option>').val('approve_jobs').text('<?php printf( __( 'Approve %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name ); ?>').appendTo("select[name='action2']");
76
-
77
- jQuery('<option>').val('expire_jobs').text('<?php printf( __( 'Expire %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name ); ?>').appendTo("select[name='action']");
78
- jQuery('<option>').val('expire_jobs').text('<?php printf( __( 'Expire %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name ); ?>').appendTo("select[name='action2']");
79
- });
80
- </script>
81
- <?php
82
  }
 
83
  }
84
 
85
  /**
86
  * Performs bulk actions on Job Listing admin page.
 
 
 
 
 
 
87
  */
88
- public function do_bulk_actions() {
89
- $wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
90
- $action = $wp_list_table->current_action();
91
-
92
- switch( $action ) {
93
- case 'approve_jobs' :
94
- check_admin_referer( 'bulk-posts' );
95
-
96
- $post_ids = array_map( 'absint', array_filter( (array) $_GET['post'] ) );
97
- $approved_jobs = array();
98
-
99
- if ( ! empty( $post_ids ) )
100
- foreach( $post_ids as $post_id ) {
101
- $job_data = array(
102
- 'ID' => $post_id,
103
- 'post_status' => 'publish'
104
- );
105
- if ( in_array( get_post_status( $post_id ), array( 'pending', 'pending_payment' ) ) && current_user_can( 'publish_post', $post_id ) && wp_update_post( $job_data ) ) {
106
- $approved_jobs[] = $post_id;
107
- }
108
  }
109
-
110
- wp_redirect( add_query_arg( 'approved_jobs', $approved_jobs, remove_query_arg( array( 'approved_jobs', 'expired_jobs' ), admin_url( 'edit.php?post_type=job_listing' ) ) ) );
111
  exit;
112
- break;
113
- case 'expire_jobs' :
114
- check_admin_referer( 'bulk-posts' );
115
 
116
- $post_ids = array_map( 'absint', array_filter( (array) $_GET['post'] ) );
117
- $expired_jobs = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
- if ( ! empty( $post_ids ) )
120
- foreach( $post_ids as $post_id ) {
121
- $job_data = array(
122
- 'ID' => $post_id,
123
- 'post_status' => 'expired'
124
- );
125
- if ( current_user_can( 'manage_job_listings' ) && wp_update_post( $job_data ) )
126
- $expired_jobs[] = $post_id;
127
- }
 
 
 
 
 
 
 
 
 
 
128
 
129
- wp_redirect( add_query_arg( 'expired_jobs', $expired_jobs, remove_query_arg( array( 'approved_jobs', 'expired_jobs' ), admin_url( 'edit.php?post_type=job_listing' ) ) ) );
130
- exit;
131
- break;
 
 
 
 
 
 
 
 
 
132
  }
 
 
133
 
134
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  }
136
 
137
  /**
@@ -145,47 +233,37 @@ class WP_Job_Manager_CPT {
145
  'post_status' => 'publish'
146
  );
147
  wp_update_post( $job_data );
148
- wp_redirect( remove_query_arg( 'approve_job', add_query_arg( 'approved_jobs', $post_id, admin_url( 'edit.php?post_type=job_listing' ) ) ) );
149
  exit;
150
  }
151
  }
152
 
153
  /**
154
- * Shows a notice if we did a bulk approval action.
155
- */
156
- public function approved_notice() {
157
- global $post_type, $pagenow;
158
-
159
- if ( $pagenow == 'edit.php' && $post_type == 'job_listing' && ! empty( $_REQUEST['approved_jobs'] ) ) {
160
- $approved_jobs = $_REQUEST['approved_jobs'];
161
- if ( is_array( $approved_jobs ) ) {
162
- $approved_jobs = array_map( 'absint', $approved_jobs );
163
- $titles = array();
164
- foreach ( $approved_jobs as $job_id )
165
- $titles[] = get_the_title( $job_id );
166
- echo '<div class="updated"><p>' . sprintf( __( '%s approved', 'wp-job-manager' ), '&quot;' . implode( '&quot;, &quot;', $titles ) . '&quot;' ) . '</p></div>';
167
- } else {
168
- echo '<div class="updated"><p>' . sprintf( __( '%s approved', 'wp-job-manager' ), '&quot;' . get_the_title( $approved_jobs ) . '&quot;' ) . '</p></div>';
169
- }
170
- }
171
- }
172
-
173
- /**
174
- * Shows a notice if we did a bulk expired action.
175
  */
176
- public function expired_notice() {
177
- global $post_type, $pagenow;
178
-
179
- if ( $pagenow == 'edit.php' && $post_type == 'job_listing' && ! empty( $_REQUEST['expired_jobs'] ) ) {
180
- $expired_jobs = $_REQUEST['expired_jobs'];
181
- if ( is_array( $expired_jobs ) ) {
182
- $expired_jobs = array_map( 'absint', $expired_jobs );
183
- $titles = array();
184
- foreach ( $expired_jobs as $job_id )
185
- $titles[] = get_the_title( $job_id );
186
- echo '<div class="updated"><p>' . sprintf( __( '%s expired', 'wp-job-manager' ), '&quot;' . implode( '&quot;, &quot;', $titles ) . '&quot;' ) . '</p></div>';
 
 
 
 
 
 
 
 
 
 
187
  } else {
188
- echo '<div class="updated"><p>' . sprintf( __( '%s expired', 'wp-job-manager' ), '&quot;' . get_the_title( $expired_jobs ) . '&quot;' ) . '</p></div>';
189
  }
190
  }
191
  }
@@ -340,13 +418,17 @@ class WP_Job_Manager_CPT {
340
 
341
  switch ( $column ) {
342
  case "job_listing_type" :
343
- $type = get_the_job_type( $post );
344
- if ( $type )
345
- echo '<span class="job-type ' . $type->slug . '">' . $type->name . '</span>';
 
 
 
 
346
  break;
347
  case "job_position" :
348
  echo '<div class="job_position">';
349
- echo '<a href="' . admin_url('post.php?post=' . $post->ID . '&action=edit') . '" class="tips job_title" data-tip="' . sprintf( __( 'ID: %d', 'wp-job-manager' ), $post->ID ) . '">' . esc_html( $post->post_title ) . '</a>';
350
 
351
  echo '<div class="company">';
352
 
@@ -566,5 +648,3 @@ class WP_Job_Manager_CPT {
566
  <?php
567
  }
568
  }
569
-
570
- WP_Job_Manager_CPT::instance();
14
  * The single instance of the class.
15
  *
16
  * @var self
17
+ * @since 1.26.0
18
  */
19
  private static $_instance = null;
20
 
21
  /**
22
  * Allows for accessing single instance of class. Class should only be constructed once per call.
23
  *
24
+ * @since 1.26.0
25
  * @static
26
  * @return self Main instance.
27
  */
46
  add_action( 'parse_query', array( $this, 'search_meta' ) );
47
  add_filter( 'get_search_query', array( $this, 'search_meta_label' ) );
48
  add_filter( 'post_updated_messages', array( $this, 'post_updated_messages' ) );
49
+ add_action( 'bulk_actions-edit-job_listing', array( $this, 'add_bulk_actions' ) );
50
+ add_action( 'handle_bulk_actions-edit-job_listing', array( $this, 'do_bulk_actions' ), 10, 3 );
51
  add_action( 'admin_init', array( $this, 'approve_job' ) );
52
+ add_action( 'admin_notices', array( $this, 'action_notices' ) );
 
53
 
54
  if ( get_option( 'job_manager_enable_categories' ) ) {
55
  add_action( "restrict_manage_posts", array( $this, "jobs_by_category" ) );
60
  }
61
  }
62
 
63
+ /**
64
+ * Returns the list of bulk actions that can be performed on job listings.
65
+ *
66
+ * @return array
67
+ */
68
+ public function get_bulk_actions() {
69
+ $actions_handled = array();
70
+ $actions_handled['approve_jobs'] = array(
71
+ 'label' => __( 'Approve %s', 'wp-job-manager' ),
72
+ 'notice' => __( '%s approved', 'wp-job-manager' ),
73
+ 'handler' => array( $this, 'bulk_action_handle_approve_job' ),
74
+ );
75
+ $actions_handled['expire_jobs'] = array(
76
+ 'label' => __( 'Expire %s', 'wp-job-manager' ),
77
+ 'notice' => __( '%s expired', 'wp-job-manager' ),
78
+ 'handler' => array( $this, 'bulk_action_handle_expire_job' ),
79
+ );
80
+ $actions_handled['mark_jobs_filled'] = array(
81
+ 'label' => __( 'Mark %s Filled', 'wp-job-manager' ),
82
+ 'notice' => __( '%s marked as filled', 'wp-job-manager' ),
83
+ 'handler' => array( $this, 'bulk_action_handle_mark_job_filled' ),
84
+ );
85
+ $actions_handled['mark_jobs_not_filled'] = array(
86
+ 'label' => __( 'Mark %s Not Filled', 'wp-job-manager' ),
87
+ 'notice' => __( '%s marked as not filled', 'wp-job-manager' ),
88
+ 'handler' => array( $this, 'bulk_action_handle_mark_job_not_filled' ),
89
+ );
90
+
91
+ /**
92
+ * Filters the bulk actions that can be applied to job listings.
93
+ *
94
+ * @since 1.27.0
95
+ *
96
+ * @param array $actions_handled {
97
+ * Bulk actions that can be handled, indexed by a unique key name (approve_jobs, expire_jobs, etc). Handlers
98
+ * are responsible for checking abilities (`current_user_can( 'manage_job_listings', $post_id )`) before
99
+ * performing action.
100
+ *
101
+ * @type string $label Label for the bulk actions dropdown. Passed through sprintf with label name of job listing post type.
102
+ * @type string $notice Success notice shown after performing the action. Passed through sprintf with title(s) of affected job listings.
103
+ * @type callback $handler Callable handler for performing action. Passed one argument (int $post_id) and should return true on success and false on failure.
104
+ * }
105
+ */
106
+ return apply_filters( 'wpjm_job_listing_bulk_actions', $actions_handled );
107
+ }
108
+
109
  /**
110
  * Adds bulk actions to drop downs on Job Listing admin page.
111
+ *
112
+ * @param array $bulk_actions
113
+ * @return array
114
  */
115
+ public function add_bulk_actions( $bulk_actions ) {
116
+ global $wp_post_types;
117
+
118
+ foreach ( $this->get_bulk_actions() as $key => $bulk_action ) {
119
+ if ( isset( $bulk_action['label'] ) ) {
120
+ $bulk_actions[ $key ] = sprintf( $bulk_action['label'], $wp_post_types['job_listing']->labels->name );
121
+ }
 
 
 
 
 
 
 
 
122
  }
123
+ return $bulk_actions;
124
  }
125
 
126
  /**
127
  * Performs bulk actions on Job Listing admin page.
128
+ *
129
+ * @since 1.27.0
130
+ *
131
+ * @param string $redirect_url The redirect URL.
132
+ * @param string $action The action being taken.
133
+ * @param array $post_ids The posts to take the action on.
134
  */
135
+ public function do_bulk_actions( $redirect_url, $action, $post_ids ) {
136
+ $actions_handled = $this->get_bulk_actions();
137
+ if ( isset ( $actions_handled[ $action ] ) && isset ( $actions_handled[ $action ]['handler'] ) ) {
138
+ $handled_jobs = array();
139
+ if ( ! empty( $post_ids ) ) {
140
+ foreach ( $post_ids as $post_id ) {
141
+ if ( 'job_listing' === get_post_type( $post_id )
142
+ && call_user_func( $actions_handled[ $action ]['handler'], $post_id ) ) {
143
+ $handled_jobs[] = $post_id;
 
 
 
 
 
 
 
 
 
 
 
144
  }
145
+ }
146
+ wp_redirect( add_query_arg( 'handled_jobs', $handled_jobs, add_query_arg( 'action_performed', $action, $redirect_url ) ) );
147
  exit;
148
+ }
149
+ }
150
+ }
151
 
152
+ /**
153
+ * Performs bulk action to approve a single job listing.
154
+ *
155
+ * @param $post_id
156
+ *
157
+ * @return bool
158
+ */
159
+ public function bulk_action_handle_approve_job( $post_id ) {
160
+ $job_data = array(
161
+ 'ID' => $post_id,
162
+ 'post_status' => 'publish',
163
+ );
164
+ if ( in_array( get_post_status( $post_id ), array( 'pending', 'pending_payment' ) )
165
+ && current_user_can( 'publish_post', $post_id )
166
+ && wp_update_post( $job_data )
167
+ ) {
168
+ return true;
169
+ }
170
+ return false;
171
+ }
172
 
173
+ /**
174
+ * Performs bulk action to expire a single job listing.
175
+ *
176
+ * @param $post_id
177
+ *
178
+ * @return bool
179
+ */
180
+ public function bulk_action_handle_expire_job( $post_id ) {
181
+ $job_data = array(
182
+ 'ID' => $post_id,
183
+ 'post_status' => 'expired',
184
+ );
185
+ if ( current_user_can( 'manage_job_listings', $post_id )
186
+ && wp_update_post( $job_data )
187
+ ) {
188
+ return true;
189
+ }
190
+ return false;
191
+ }
192
 
193
+ /**
194
+ * Performs bulk action to mark a single job listing as filled.
195
+ *
196
+ * @param $post_id
197
+ *
198
+ * @return bool
199
+ */
200
+ public function bulk_action_handle_mark_job_filled( $post_id ) {
201
+ if ( current_user_can( 'manage_job_listings', $post_id )
202
+ && update_post_meta( $post_id, '_filled', 1 )
203
+ ) {
204
+ return true;
205
  }
206
+ return false;
207
+ }
208
 
209
+ /**
210
+ * Performs bulk action to mark a single job listing as not filled.
211
+ *
212
+ * @param $post_id
213
+ *
214
+ * @return bool
215
+ */
216
+ public function bulk_action_handle_mark_job_not_filled( $post_id ) {
217
+ if ( current_user_can( 'manage_job_listings', $post_id )
218
+ && update_post_meta( $post_id, '_filled', 0 )
219
+ ) {
220
+ return true;
221
+ }
222
+ return false;
223
  }
224
 
225
  /**
233
  'post_status' => 'publish'
234
  );
235
  wp_update_post( $job_data );
236
+ wp_redirect( remove_query_arg( 'approve_job', add_query_arg( 'handled_jobs', $post_id, add_query_arg( 'action_performed', 'approve_jobs', admin_url( 'edit.php?post_type=job_listing' ) ) ) ) );
237
  exit;
238
  }
239
  }
240
 
241
  /**
242
+ * Shows a notice if we did a bulk action.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  */
244
+ public function action_notices() {
245
+ global $post_type, $pagenow;
246
+
247
+ $handled_jobs = isset ( $_REQUEST['handled_jobs'] ) ? $_REQUEST['handled_jobs'] : false;
248
+ $action = isset ( $_REQUEST['action_performed'] ) ? $_REQUEST['action_performed'] : false;
249
+ $actions_handled = $this->get_bulk_actions();
250
+
251
+ if ( $pagenow == 'edit.php'
252
+ && $post_type == 'job_listing'
253
+ && $action
254
+ && ! empty( $handled_jobs )
255
+ && isset ( $actions_handled[ $action ] )
256
+ && isset ( $actions_handled[ $action ]['notice'] )
257
+ ) {
258
+ if ( is_array( $handled_jobs ) ) {
259
+ $handled_jobs = array_map( 'absint', $handled_jobs );
260
+ $titles = array();
261
+ foreach ( $handled_jobs as $job_id ) {
262
+ $titles[] = wpjm_get_the_job_title( $job_id );
263
+ }
264
+ echo '<div class="updated"><p>' . sprintf( $actions_handled[ $action ]['notice'], '&quot;' . implode( '&quot;, &quot;', $titles ) . '&quot;' ) . '</p></div>';
265
  } else {
266
+ echo '<div class="updated"><p>' . sprintf( $actions_handled[ $action ]['notice'], '&quot;' . wpjm_get_the_job_title( absint( $handled_jobs ) ) . '&quot;' ) . '</p></div>';
267
  }
268
  }
269
  }
418
 
419
  switch ( $column ) {
420
  case "job_listing_type" :
421
+ $types = wpjm_get_the_job_types( $post );
422
+
423
+ if ( $types && ! empty( $types ) ) {
424
+ foreach ( $types as $type ) {
425
+ echo '<span class="job-type ' . $type->slug . '">' . $type->name . '</span>';
426
+ }
427
+ }
428
  break;
429
  case "job_position" :
430
  echo '<div class="job_position">';
431
+ echo '<a href="' . admin_url('post.php?post=' . $post->ID . '&action=edit') . '" class="tips job_title" data-tip="' . sprintf( __( 'ID: %d', 'wp-job-manager' ), $post->ID ) . '">' . wpjm_get_the_job_title() . '</a>';
432
 
433
  echo '<div class="company">';
434
 
648
  <?php
649
  }
650
  }
 
 
includes/admin/class-wp-job-manager-permalink-settings.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ /**
6
+ * Handles front admin page for WP Job Manager.
7
+ *
8
+ * @package wp-job-manager
9
+ * @see https://github.com/woocommerce/woocommerce/blob/3.0.8/includes/admin/class-wc-admin-permalink-settings.php Based on WooCommerce's implementation.
10
+ * @since 1.27.0
11
+ */
12
+ class WP_Job_Manager_Permalink_Settings {
13
+ /**
14
+ * The single instance of the class.
15
+ *
16
+ * @var self
17
+ * @since 1.27.0
18
+ */
19
+ private static $_instance = null;
20
+
21
+ /**
22
+ * Permalink settings.
23
+ *
24
+ * @var array
25
+ * @since 1.27.0
26
+ */
27
+ private $permalinks = array();
28
+
29
+ /**
30
+ * Allows for accessing single instance of class. Class should only be constructed once per call.
31
+ *
32
+ * @since 1.27.0
33
+ * @static
34
+ * @return self Main instance.
35
+ */
36
+ public static function instance() {
37
+ if ( is_null( self::$_instance ) ) {
38
+ self::$_instance = new self();
39
+ }
40
+ return self::$_instance;
41
+ }
42
+
43
+ /**
44
+ * Constructor.
45
+ */
46
+ public function __construct() {
47
+ $this->setup_fields();
48
+ $this->settings_save();
49
+ $this->permalinks = wpjm_get_permalink_structure();
50
+ }
51
+
52
+ public function setup_fields() {
53
+ add_settings_field(
54
+ 'wpjm_job_base_slug',
55
+ __( 'Job base', 'wp-job-manager' ),
56
+ array( $this, 'job_base_slug_input' ),
57
+ 'permalink',
58
+ 'optional'
59
+ );
60
+ add_settings_field(
61
+ 'wpjm_job_category_slug',
62
+ __( 'Job category base', 'wp-job-manager' ),
63
+ array( $this, 'job_category_slug_input' ),
64
+ 'permalink',
65
+ 'optional'
66
+ );
67
+ add_settings_field(
68
+ 'wpjm_job_type_slug',
69
+ __( 'Job type base', 'wp-job-manager' ),
70
+ array( $this, 'job_type_slug_input' ),
71
+ 'permalink',
72
+ 'optional'
73
+ );
74
+ }
75
+
76
+ /**
77
+ * Show a slug input box for job post type slug.
78
+ */
79
+ public function job_base_slug_input() {
80
+ ?>
81
+ <input name="wpjm_job_base_slug" type="text" class="regular-text code" value="<?php echo esc_attr( $this->permalinks['job_base'] ); ?>" placeholder="<?php echo esc_attr_x( 'job', 'Job permalink - resave permalinks after changing this', 'wp-job-manager' ) ?>" />
82
+ <?php
83
+ }
84
+
85
+ /**
86
+ * Show a slug input box for job category slug.
87
+ */
88
+ public function job_category_slug_input() {
89
+ ?>
90
+ <input name="wpjm_job_category_slug" type="text" class="regular-text code" value="<?php echo esc_attr( $this->permalinks['category_base'] ); ?>" placeholder="<?php echo esc_attr_x( 'job-category', 'Job category slug - resave permalinks after changing this', 'wp-job-manager' ) ?>" />
91
+ <?php
92
+ }
93
+
94
+ /**
95
+ * Show a slug input box for job type slug.
96
+ */
97
+ public function job_type_slug_input() {
98
+ ?>
99
+ <input name="wpjm_job_type_slug" type="text" class="regular-text code" value="<?php echo esc_attr( $this->permalinks['type_base'] ); ?>" placeholder="<?php echo esc_attr_x( 'job-type', 'Job type slug - resave permalinks after changing this', 'wp-job-manager' ) ?>" />
100
+ <?php
101
+ }
102
+
103
+ /**
104
+ * Save the settings.
105
+ */
106
+ public function settings_save() {
107
+ if ( ! is_admin() ) {
108
+ return;
109
+ }
110
+
111
+ if ( isset( $_POST['permalink_structure'] ) ) {
112
+ if ( function_exists( 'switch_to_locale' ) ) {
113
+ switch_to_locale( get_locale() );
114
+ }
115
+
116
+ $permalinks = (array) get_option( 'wpjm_permalinks', array() );
117
+ $permalinks['job_base'] = sanitize_title_with_dashes( $_POST['wpjm_job_base_slug'] );
118
+ $permalinks['category_base'] = sanitize_title_with_dashes( $_POST['wpjm_job_category_slug'] );
119
+ $permalinks['type_base'] = sanitize_title_with_dashes( $_POST['wpjm_job_type_slug'] );
120
+
121
+ update_option( 'wpjm_permalinks', $permalinks );
122
+
123
+ if ( function_exists( 'restore_current_locale' ) ) {
124
+ restore_current_locale();
125
+ }
126
+ }
127
+ }
128
+ }
129
+
130
+ WP_Job_Manager_Permalink_Settings::instance();
includes/admin/class-wp-job-manager-settings.php CHANGED
@@ -14,14 +14,14 @@ class WP_Job_Manager_Settings {
14
  * The single instance of the class.
15
  *
16
  * @var self
17
- * @since 1.26
18
  */
19
  private static $_instance = null;
20
 
21
  /**
22
  * Allows for accessing single instance of class. Class should only be constructed once per call.
23
  *
24
- * @since 1.26
25
  * @static
26
  * @return self Main instance.
27
  */
@@ -134,7 +134,7 @@ class WP_Job_Manager_Settings {
134
  'type' => 'select',
135
  'options' => array(
136
  'relative' => __( 'Relative to the current date (e.g., 1 day, 1 week, 1 month ago)', 'wp-job-manager' ),
137
- 'default' => __( 'Default date format as defined in Setttings', 'wp-job-manager' ),
138
  )
139
  ),
140
  array(
@@ -194,6 +194,15 @@ class WP_Job_Manager_Settings {
194
  'type' => 'checkbox',
195
  'attributes' => array()
196
  ),
 
 
 
 
 
 
 
 
 
197
  array(
198
  'name' => 'job_manager_registration_role',
199
  'std' => 'employer',
@@ -431,14 +440,47 @@ class WP_Job_Manager_Settings {
431
  jQuery(this).addClass('nav-tab-active');
432
  return false;
433
  });
434
- jQuery('.nav-tab-wrapper a:first').click();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
435
  jQuery('#setting-job_manager_enable_registration').change(function(){
436
  if ( jQuery( this ).is(':checked') ) {
437
- jQuery('#setting-job_manager_registration_role').closest('tr').show();
438
- jQuery('#setting-job_manager_registration_username_from_email').closest('tr').show();
 
439
  } else {
440
- jQuery('#setting-job_manager_registration_role').closest('tr').hide();
441
- jQuery('#setting-job_manager_registration_username_from_email').closest('tr').hide();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
442
  }
443
  }).change();
444
  </script>
14
  * The single instance of the class.
15
  *
16
  * @var self
17
+ * @since 1.26.0
18
  */
19
  private static $_instance = null;
20
 
21
  /**
22
  * Allows for accessing single instance of class. Class should only be constructed once per call.
23
  *
24
+ * @since 1.26.0
25
  * @static
26
  * @return self Main instance.
27
  */
134
  'type' => 'select',
135
  'options' => array(
136
  'relative' => __( 'Relative to the current date (e.g., 1 day, 1 week, 1 month ago)', 'wp-job-manager' ),
137
+ 'default' => __( 'Default date format as defined in Settings', 'wp-job-manager' ),
138
  )
139
  ),
140
  array(
194
  'type' => 'checkbox',
195
  'attributes' => array()
196
  ),
197
+ array(
198
+ 'name' => 'job_manager_use_standard_password_setup_email',
199
+ 'std' => '1',
200
+ 'label' => __( 'Account Password', 'wp-job-manager' ),
201
+ 'cb_label' => __( 'Use WordPress\' default behavior and email new users link to set a password', 'wp-job-manager' ),
202
+ 'desc' => __( 'If enabled, an email will be sent to the user with their username and a link to set their password. Otherwise, a password field will be shown and their email address won\'t be verified.', 'wp-job-manager' ),
203
+ 'type' => 'checkbox',
204
+ 'attributes' => array()
205
+ ),
206
  array(
207
  'name' => 'job_manager_registration_role',
208
  'std' => 'employer',
440
  jQuery(this).addClass('nav-tab-active');
441
  return false;
442
  });
443
+ var goto_hash = window.location.hash;
444
+ if ( goto_hash ) {
445
+ var the_tab = jQuery( 'a[href="' + goto_hash + '"]' );
446
+ if ( the_tab.length > 0 ) {
447
+ the_tab.click();
448
+ } else {
449
+ jQuery( '.nav-tab-wrapper a:first' ).click();
450
+ }
451
+ } else {
452
+ jQuery( '.nav-tab-wrapper a:first' ).click();
453
+ }
454
+ var $use_standard_password_setup_email = jQuery('#setting-job_manager_use_standard_password_setup_email');
455
+ var $generate_username_from_email = jQuery('#setting-job_manager_generate_username_from_email');
456
+ var $job_manager_registration_role = jQuery('#setting-job_manager_registration_role');
457
+
458
  jQuery('#setting-job_manager_enable_registration').change(function(){
459
  if ( jQuery( this ).is(':checked') ) {
460
+ $job_manager_registration_role.closest('tr').show();
461
+ $use_standard_password_setup_email.closest('tr').show();
462
+ $generate_username_from_email.closest('tr').show();
463
  } else {
464
+ $job_manager_registration_role.closest('tr').hide();
465
+ $use_standard_password_setup_email.closest('tr').hide();
466
+ $generate_username_from_email.closest('tr').hide();
467
+ }
468
+ }).change();
469
+
470
+ // If generate username is enabled on page load, assume use_standard_password_setup_email has been cleared.
471
+ // Default is true, so let's sneakily set it to that before it gets cleared and disabled.
472
+ if ( $generate_username_from_email.is(':checked') ) {
473
+ $use_standard_password_setup_email.prop('checked', true);
474
+ }
475
+
476
+ $generate_username_from_email.change(function() {
477
+ if ( jQuery( this ).is(':checked') ) {
478
+ $use_standard_password_setup_email.data('original-state', $use_standard_password_setup_email.is(':checked')).prop('checked', true).prop('disabled', true);
479
+ } else {
480
+ $use_standard_password_setup_email.prop('disabled', false);
481
+ if ( undefined !== $use_standard_password_setup_email.data('original-state') ) {
482
+ $use_standard_password_setup_email.prop('checked', $use_standard_password_setup_email.data('original-state'));
483
+ }
484
  }
485
  }).change();
486
  </script>
includes/admin/class-wp-job-manager-setup.php CHANGED
@@ -15,14 +15,14 @@ class WP_Job_Manager_Setup {
15
  * The single instance of the class.
16
  *
17
  * @var self
18
- * @since 1.26
19
  */
20
  private static $_instance = null;
21
 
22
  /**
23
  * Allows for accessing single instance of class. Class should only be constructed once per call.
24
  *
25
- * @since 1.26
26
  * @static
27
  * @return self Main instance.
28
  */
15
  * The single instance of the class.
16
  *
17
  * @var self
18
+ * @since 1.26.0
19
  */
20
  private static $_instance = null;
21
 
22
  /**
23
  * Allows for accessing single instance of class. Class should only be constructed once per call.
24
  *
25
+ * @since 1.26.0
26
  * @static
27
  * @return self Main instance.
28
  */
includes/admin/class-wp-job-manager-writepanels.php CHANGED
@@ -13,14 +13,14 @@ class WP_Job_Manager_Writepanels {
13
  * The single instance of the class.
14
  *
15
  * @var self
16
- * @since 1.26
17
  */
18
  private static $_instance = null;
19
 
20
  /**
21
  * Allows for accessing single instance of class. Class should only be constructed once per call.
22
  *
23
- * @since 1.26
24
  * @static
25
  * @return self Main instance.
26
  */
@@ -111,7 +111,7 @@ class WP_Job_Manager_Writepanels {
111
  'classes' => array( 'job-manager-datepicker' ),
112
  /* translators: date format placeholder, see https://secure.php.net/date */
113
  'placeholder' => ! empty( $job_expires ) ? _x( 'yyyy-mm-dd', 'Date format placeholder.', 'wp-job-manager' ) : calculate_job_expiry( $post->ID ),
114
- 'value' => ! empty( $job_expires ) ? date( 'Y-m-d H:i:s', strtotime( $job_expires ) ) : '',
115
  );
116
  }
117
  if ( $current_user->has_cap( 'edit_others_job_listings' ) ) {
@@ -122,7 +122,16 @@ class WP_Job_Manager_Writepanels {
122
  );
123
  }
124
 
125
- $fields = apply_filters( 'job_manager_job_listing_data_fields', $fields );
 
 
 
 
 
 
 
 
 
126
 
127
  uasort( $fields, array( $this, 'sort_by_priority' ) );
128
 
@@ -289,6 +298,59 @@ class WP_Job_Manager_Writepanels {
289
  <?php
290
  }
291
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  /**
293
  * Displays label and textarea input field.
294
  *
@@ -529,12 +591,20 @@ class WP_Job_Manager_Writepanels {
529
 
530
  // Save fields
531
  foreach ( $this->job_listing_fields() as $key => $field ) {
 
 
 
 
532
  // Expirey date
533
  if ( '_job_expires' === $key ) {
534
- if ( ! empty( $_POST[ $key ] ) ) {
535
- update_post_meta( $post_id, $key, date( 'Y-m-d', strtotime( sanitize_text_field( $_POST[ $key ] ) ) ) );
 
 
 
 
536
  } else {
537
- update_post_meta( $post_id, $key, calculate_job_expiry( $post_id ) );
538
  }
539
  }
540
 
13
  * The single instance of the class.
14
  *
15
  * @var self
16
+ * @since 1.26.0
17
  */
18
  private static $_instance = null;
19
 
20
  /**
21
  * Allows for accessing single instance of class. Class should only be constructed once per call.
22
  *
23
+ * @since 1.26.0
24
  * @static
25
  * @return self Main instance.
26
  */
111
  'classes' => array( 'job-manager-datepicker' ),
112
  /* translators: date format placeholder, see https://secure.php.net/date */
113
  'placeholder' => ! empty( $job_expires ) ? _x( 'yyyy-mm-dd', 'Date format placeholder.', 'wp-job-manager' ) : calculate_job_expiry( $post->ID ),
114
+ 'value' => ! empty( $job_expires ) ? date( 'Y-m-d', strtotime( $job_expires ) ) : '',
115
  );
116
  }
117
  if ( $current_user->has_cap( 'edit_others_job_listings' ) ) {
122
  );
123
  }
124
 
125
+ /**
126
+ * Filters job listing data fields for WP Admin post editor.
127
+ *
128
+ * @since 1.0.0
129
+ * @since 1.27.0 $post_id was added
130
+ *
131
+ * @param array $fields
132
+ * @param int $post_id
133
+ */
134
+ $fields = apply_filters( 'job_manager_job_listing_data_fields', $fields, $post->ID );
135
 
136
  uasort( $fields, array( $this, 'sort_by_priority' ) );
137
 
298
  <?php
299
  }
300
 
301
+ /**
302
+ * Just displays information.
303
+ *
304
+ * @since 1.27.0
305
+ *
306
+ * @param string $key
307
+ * @param array $field
308
+ */
309
+ public static function input_info( $key, $field ) {
310
+ self::input_hidden( $key, $field );
311
+ }
312
+
313
+ /**
314
+ * Displays information and/or hidden input.
315
+ *
316
+ * @since 1.27.0
317
+ *
318
+ * @param string $key
319
+ * @param array $field
320
+ */
321
+ public static function input_hidden( $key, $field ) {
322
+ global $thepostid;
323
+
324
+ if ( 'hidden' === $field['type'] && ! isset( $field['value'] ) ) {
325
+ $field['value'] = get_post_meta( $thepostid, $key, true );
326
+ }
327
+ if ( ! empty( $field['name'] ) ) {
328
+ $name = $field['name'];
329
+ } else {
330
+ $name = $key;
331
+ }
332
+ if ( ! empty( $field['classes'] ) ) {
333
+ $classes = implode( ' ', is_array( $field['classes'] ) ? $field['classes'] : array( $field['classes'] ) );
334
+ } else {
335
+ $classes = '';
336
+ }
337
+ $hidden_input = '';
338
+ if ( 'hidden' === $field['type'] ) {
339
+ $hidden_input = '<input type="hidden" name="' . esc_attr( $name ) . '" class="' . esc_attr( $classes ) . '" id="' . esc_attr( $key ) . '" value="' . esc_attr( $field['value'] ) . '" />';
340
+ if ( empty( $field['label'] ) ) {
341
+ echo $hidden_input;
342
+ return;
343
+ }
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>
351
+ <?php
352
+ }
353
+
354
  /**
355
  * Displays label and textarea input field.
356
  *
591
 
592
  // Save fields
593
  foreach ( $this->job_listing_fields() as $key => $field ) {
594
+ if ( isset( $field['type'] ) && 'info' === $field['type'] ) {
595
+ continue;
596
+ }
597
+
598
  // Expirey date
599
  if ( '_job_expires' === $key ) {
600
+ if ( empty( $_POST[ $key ] ) ) {
601
+ if ( get_option( 'job_manager_submission_duration' ) ) {
602
+ update_post_meta( $post_id, $key, calculate_job_expiry( $post_id ) );
603
+ } else {
604
+ delete_post_meta( $post_id, $key );
605
+ }
606
  } else {
607
+ update_post_meta( $post_id, $key, date( 'Y-m-d', strtotime( sanitize_text_field( $_POST[ $key ] ) ) ) );
608
  }
609
  }
610
 
includes/class-wp-job-manager-ajax.php CHANGED
@@ -16,14 +16,14 @@ class WP_Job_Manager_Ajax {
16
  * The single instance of the class.
17
  *
18
  * @var self
19
- * @since 1.26
20
  */
21
  private static $_instance = null;
22
 
23
  /**
24
  * Allows for accessing single instance of class. Class should only be constructed once per call.
25
  *
26
- * @since 1.26
27
  * @static
28
  * @return self Main instance.
29
  */
@@ -114,14 +114,15 @@ class WP_Job_Manager_Ajax {
114
  public function get_listings() {
115
  global $wp_post_types;
116
 
117
- $result = array();
118
- $search_location = sanitize_text_field( stripslashes( $_REQUEST['search_location'] ) );
119
- $search_keywords = sanitize_text_field( stripslashes( $_REQUEST['search_keywords'] ) );
120
- $search_categories = isset( $_REQUEST['search_categories'] ) ? $_REQUEST['search_categories'] : '';
121
- $filter_job_types = isset( $_REQUEST['filter_job_type'] ) ? array_filter( array_map( 'sanitize_title', (array) $_REQUEST['filter_job_type'] ) ) : null;
122
- $types = get_job_listing_types();
123
- $post_type_label = $wp_post_types['job_listing']->labels->name;
124
- $orderby = sanitize_text_field( $_REQUEST['orderby'] );
 
125
 
126
  if ( is_array( $search_categories ) ) {
127
  $search_categories = array_filter( array_map( 'sanitize_text_field', array_map( 'stripslashes', $search_categories ) ) );
@@ -134,6 +135,7 @@ class WP_Job_Manager_Ajax {
134
  'search_keywords' => $search_keywords,
135
  'search_categories' => $search_categories,
136
  'job_types' => is_null( $filter_job_types ) || sizeof( $types ) === sizeof( $filter_job_types ) ? '' : $filter_job_types + array( 0 ),
 
137
  'orderby' => $orderby,
138
  'order' => sanitize_text_field( $_REQUEST['order'] ),
139
  'offset' => ( absint( $_REQUEST['page'] ) - 1 ) * absint( $_REQUEST['per_page'] ),
@@ -264,7 +266,7 @@ class WP_Job_Manager_Ajax {
264
  */
265
  public function upload_file() {
266
  if ( ! job_manager_user_can_upload_file_via_ajax() ) {
267
- wp_send_json_error( new WP_Error( 'upload', __( 'You must be logged in to upload files using this method.', 'wp-job-manager' ) ) );
268
  return;
269
  }
270
  $data = array(
16
  * The single instance of the class.
17
  *
18
  * @var self
19
+ * @since 1.26.0
20
  */
21
  private static $_instance = null;
22
 
23
  /**
24
  * Allows for accessing single instance of class. Class should only be constructed once per call.
25
  *
26
+ * @since 1.26.0
27
  * @static
28
  * @return self Main instance.
29
  */
114
  public function get_listings() {
115
  global $wp_post_types;
116
 
117
+ $result = array();
118
+ $search_location = sanitize_text_field( stripslashes( $_REQUEST['search_location'] ) );
119
+ $search_keywords = sanitize_text_field( stripslashes( $_REQUEST['search_keywords'] ) );
120
+ $search_categories = isset( $_REQUEST['search_categories'] ) ? $_REQUEST['search_categories'] : '';
121
+ $filter_job_types = isset( $_REQUEST['filter_job_type'] ) ? array_filter( array_map( 'sanitize_title', (array) $_REQUEST['filter_job_type'] ) ) : null;
122
+ $filter_post_status = isset( $_REQUEST['filter_post_status'] ) ? array_filter( array_map( 'sanitize_title', (array) $_REQUEST['filter_post_status'] ) ) : null;
123
+ $types = get_job_listing_types();
124
+ $post_type_label = $wp_post_types['job_listing']->labels->name;
125
+ $orderby = sanitize_text_field( $_REQUEST['orderby'] );
126
 
127
  if ( is_array( $search_categories ) ) {
128
  $search_categories = array_filter( array_map( 'sanitize_text_field', array_map( 'stripslashes', $search_categories ) ) );
135
  'search_keywords' => $search_keywords,
136
  'search_categories' => $search_categories,
137
  'job_types' => is_null( $filter_job_types ) || sizeof( $types ) === sizeof( $filter_job_types ) ? '' : $filter_job_types + array( 0 ),
138
+ 'post_status' => $filter_post_status,
139
  'orderby' => $orderby,
140
  'order' => sanitize_text_field( $_REQUEST['order'] ),
141
  'offset' => ( absint( $_REQUEST['page'] ) - 1 ) * absint( $_REQUEST['per_page'] ),
266
  */
267
  public function upload_file() {
268
  if ( ! job_manager_user_can_upload_file_via_ajax() ) {
269
+ wp_send_json_error( __( 'You must be logged in to upload files using this method.', 'wp-job-manager' ) );
270
  return;
271
  }
272
  $data = array(
includes/class-wp-job-manager-api.php CHANGED
@@ -16,14 +16,14 @@ class WP_Job_Manager_API {
16
  * The single instance of the class.
17
  *
18
  * @var self
19
- * @since 1.26
20
  */
21
  private static $_instance = null;
22
 
23
  /**
24
  * Allows for accessing single instance of class. Class should only be constructed once per call.
25
  *
26
- * @since 1.26
27
  * @static
28
  * @return self Main instance.
29
  */
16
  * The single instance of the class.
17
  *
18
  * @var self
19
+ * @since 1.26.0
20
  */
21
  private static $_instance = null;
22
 
23
  /**
24
  * Allows for accessing single instance of class. Class should only be constructed once per call.
25
  *
26
+ * @since 1.26.0
27
  * @static
28
  * @return self Main instance.
29
  */
includes/class-wp-job-manager-cache-helper.php CHANGED
@@ -23,6 +23,7 @@ class WP_Job_Manager_Cache_Helper {
23
  add_action( 'create_term', array( __CLASS__, 'edited_term' ), 10, 3 );
24
  add_action( 'delete_term', array( __CLASS__, 'edited_term' ), 10, 3 );
25
  add_action( 'job_manager_clear_expired_transients', array( __CLASS__, 'clear_expired_transients' ), 10 );
 
26
  }
27
 
28
  /**
@@ -128,6 +129,110 @@ class WP_Job_Manager_Cache_Helper {
128
  $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_transient_jm_' ) . '%', $wpdb->esc_like( '_transient_timeout_jm_' ) . '%', time() ) );
129
  }
130
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  }
132
 
133
  WP_Job_Manager_Cache_Helper::init();
23
  add_action( 'create_term', array( __CLASS__, 'edited_term' ), 10, 3 );
24
  add_action( 'delete_term', array( __CLASS__, 'edited_term' ), 10, 3 );
25
  add_action( 'job_manager_clear_expired_transients', array( __CLASS__, 'clear_expired_transients' ), 10 );
26
+ add_action( 'transition_post_status', array( __CLASS__, 'maybe_clear_count_transients' ), 10, 3 );
27
  }
28
 
29
  /**
129
  $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_transient_jm_' ) . '%', $wpdb->esc_like( '_transient_timeout_jm_' ) . '%', time() ) );
130
  }
131
  }
132
+
133
+ /**
134
+ * Maybe remove pending count transients
135
+ *
136
+ * When a supported post type status is updated, check if any cached count transients
137
+ * need to be removed, and remove the
138
+ *
139
+ * @since 1.27.0
140
+ *
141
+ * @param string $new_status New post status.
142
+ * @param string $old_status Old post status.
143
+ * @param WP_Post $post Post object.
144
+ */
145
+ public static function maybe_clear_count_transients( $new_status, $old_status, $post ) {
146
+ global $wpdb;
147
+
148
+ /**
149
+ * Get supported post types for count caching
150
+ *
151
+ * @since 1.27.0
152
+ *
153
+ * @param array $post_types Post types that should be cached.
154
+ * @param string $new_status New post status.
155
+ * @param string $old_status Old post status.
156
+ * @param WP_Post $post Post object.
157
+ */
158
+ $post_types = apply_filters( 'wpjm_count_cache_supported_post_types', array( 'job_listing' ), $new_status, $old_status, $post );
159
+
160
+ // Only proceed when statuses do not match, and post type is supported post type
161
+ if ( $new_status === $old_status || ! in_array( $post->post_type, $post_types ) ) {
162
+ return;
163
+ }
164
+
165
+ /**
166
+ * Get supported post statuses for count caching
167
+ *
168
+ * @since 1.27.0
169
+ *
170
+ * @param array $post_statuses Post statuses that should be cached.
171
+ * @param string $new_status New post status.
172
+ * @param string $old_status Old post status.
173
+ * @param WP_Post $post Post object.
174
+ */
175
+ $valid_statuses = apply_filters( 'wpjm_count_cache_supported_statuses', array( 'pending' ), $new_status, $old_status, $post );
176
+
177
+ $rlike = array();
178
+ // New status transient option name
179
+ if( in_array( $new_status, $valid_statuses ) ){
180
+ $rlike[] = "^_transient_jm_{$new_status}_{$post->post_type}_count_user_";
181
+ }
182
+ // Old status transient option name
183
+ if( in_array( $old_status, $valid_statuses ) ){
184
+ $rlike[] = "^_transient_jm_{$old_status}_{$post->post_type}_count_user_";
185
+ }
186
+
187
+ if ( empty( $rlike ) ) {
188
+ return;
189
+ }
190
+
191
+ $sql = $wpdb->prepare( "SELECT option_name FROM $wpdb->options WHERE option_name RLIKE '%s'", implode('|', $rlike ) );
192
+ $transients = $wpdb->get_col( $sql );
193
+
194
+ // For each transient...
195
+ foreach ( $transients as $transient ) {
196
+ // Strip away the WordPress prefix in order to arrive at the transient key.
197
+ $key = str_replace( '_transient_', '', $transient );
198
+ // Now that we have the key, use WordPress core to the delete the transient.
199
+ delete_transient( $key );
200
+ }
201
+
202
+ // Sometimes transients are not in the DB, so we have to do this too:
203
+ wp_cache_flush();
204
+ }
205
+
206
+ /**
207
+ * Get Listings Count from Cache
208
+ *
209
+ * @since 1.27.0
210
+ *
211
+ * @param string $post_type
212
+ * @param string $status
213
+ * @param bool $force Force update cache
214
+ *
215
+ * @return int
216
+ */
217
+ public static function get_listings_count( $post_type = 'job_listing', $status = 'pending', $force = false ) {
218
+
219
+ // Get user based cache transient
220
+ $user_id = get_current_user_id();
221
+ $transient = "jm_{$status}_{$post_type}_count_user_{$user_id}";
222
+
223
+ // Set listings_count value from cache if exists, otherwise set to 0 as default
224
+ $status_count = ( $cached_count = get_transient( $transient ) ) ? $cached_count : 0;
225
+
226
+ // $cached_count will be false if transient does not exist
227
+ if ( $cached_count === false || $force ) {
228
+ $count_posts = wp_count_posts( $post_type, 'readable' );
229
+ // Default to 0 $status if object does not have a value
230
+ $status_count = isset( $count_posts->$status ) ? $count_posts->$status : 0;
231
+ set_transient( $transient, $status_count );
232
+ }
233
+
234
+ return $status_count;
235
+ }
236
  }
237
 
238
  WP_Job_Manager_Cache_Helper::init();
includes/class-wp-job-manager-category-walker.php CHANGED
@@ -47,7 +47,7 @@ class WP_Job_Manager_Category_Walker extends Walker {
47
 
48
  $output .= "\t<option class=\"level-$depth\" value=\"" . $value . "\"";
49
 
50
- if ( $value == $args['selected'] || ( is_array( $args['selected'] ) && in_array( $value, $args['selected'] ) ) )
51
  $output .= ' selected="selected"';
52
 
53
  $output .= '>';
47
 
48
  $output .= "\t<option class=\"level-$depth\" value=\"" . $value . "\"";
49
 
50
+ if ( isset( $args['selected'] ) && ( $value == $args['selected'] || ( is_array( $args['selected'] ) && in_array( $value, $args['selected'] ) ) ) )
51
  $output .= ' selected="selected"';
52
 
53
  $output .= '>';
includes/class-wp-job-manager-forms.php CHANGED
@@ -11,14 +11,14 @@ class WP_Job_Manager_Forms {
11
  * The single instance of the class.
12
  *
13
  * @var self
14
- * @since 1.26
15
  */
16
  private static $_instance = null;
17
 
18
  /**
19
  * Allows for accessing single instance of class. Class should only be constructed once per call.
20
  *
21
- * @since 1.26
22
  * @static
23
  * @return self Main instance.
24
  */
11
  * The single instance of the class.
12
  *
13
  * @var self
14
+ * @since 1.26.0
15
  */
16
  private static $_instance = null;
17
 
18
  /**
19
  * Allows for accessing single instance of class. Class should only be constructed once per call.
20
  *
21
+ * @since 1.26.0
22
  * @static
23
  * @return self Main instance.
24
  */
includes/class-wp-job-manager-geocode.php CHANGED
@@ -16,14 +16,14 @@ class WP_Job_Manager_Geocode {
16
  * The single instance of the class.
17
  *
18
  * @var self
19
- * @since 1.26
20
  */
21
  private static $_instance = null;
22
 
23
  /**
24
  * Allows for accessing single instance of class. Class should only be constructed once per call.
25
  *
26
- * @since 1.26
27
  * @static
28
  * @return self Main instance.
29
  */
16
  * The single instance of the class.
17
  *
18
  * @var self
19
+ * @since 1.26.0
20
  */
21
  private static $_instance = null;
22
 
23
  /**
24
  * Allows for accessing single instance of class. Class should only be constructed once per call.
25
  *
26
+ * @since 1.26.0
27
  * @static
28
  * @return self Main instance.
29
  */
includes/class-wp-job-manager-install.php CHANGED
@@ -20,7 +20,6 @@ class WP_Job_Manager_Install {
20
 
21
  self::init_user_roles();
22
  self::default_terms();
23
- self::schedule_cron();
24
 
25
  // Redirect to setup screen for new installs
26
  if ( ! get_option( 'wp_job_manager_version' ) ) {
@@ -134,16 +133,4 @@ class WP_Job_Manager_Install {
134
 
135
  update_option( 'job_manager_installed_terms', 1 );
136
  }
137
-
138
- /**
139
- * Setup cron jobs.
140
- */
141
- private static function schedule_cron() {
142
- wp_clear_scheduled_hook( 'job_manager_check_for_expired_jobs' );
143
- wp_clear_scheduled_hook( 'job_manager_delete_old_previews' );
144
- wp_clear_scheduled_hook( 'job_manager_clear_expired_transients' );
145
- wp_schedule_event( time(), 'hourly', 'job_manager_check_for_expired_jobs' );
146
- wp_schedule_event( time(), 'daily', 'job_manager_delete_old_previews' );
147
- wp_schedule_event( time(), 'twicedaily', 'job_manager_clear_expired_transients' );
148
- }
149
  }
20
 
21
  self::init_user_roles();
22
  self::default_terms();
 
23
 
24
  // Redirect to setup screen for new installs
25
  if ( ! get_option( 'wp_job_manager_version' ) ) {
133
 
134
  update_option( 'job_manager_installed_terms', 1 );
135
  }
 
 
 
 
 
 
 
 
 
 
 
 
136
  }
includes/class-wp-job-manager-post-types.php CHANGED
@@ -11,14 +11,14 @@ class WP_Job_Manager_Post_Types {
11
  * The single instance of the class.
12
  *
13
  * @var self
14
- * @since 1.26
15
  */
16
  private static $_instance = null;
17
 
18
  /**
19
  * Allows for accessing single instance of class. Class should only be constructed once per call.
20
  *
21
- * @since 1.26
22
  * @static
23
  * @return self Main instance.
24
  */
@@ -86,6 +86,7 @@ class WP_Job_Manager_Post_Types {
86
 
87
  $admin_capability = 'manage_job_listings';
88
 
 
89
  /**
90
  * Taxonomies
91
  */
@@ -95,7 +96,7 @@ class WP_Job_Manager_Post_Types {
95
 
96
  if ( current_theme_supports( 'job-manager-templates' ) ) {
97
  $rewrite = array(
98
- 'slug' => _x( 'job-category', 'Job category slug - resave permalinks after changing this', 'wp-job-manager' ),
99
  'with_front' => false,
100
  'hierarchical' => false
101
  );
@@ -107,11 +108,11 @@ class WP_Job_Manager_Post_Types {
107
 
108
  register_taxonomy( "job_listing_category",
109
  apply_filters( 'register_taxonomy_job_listing_category_object_type', array( 'job_listing' ) ),
110
- apply_filters( 'register_taxonomy_job_listing_category_args', array(
111
- 'hierarchical' => true,
112
- 'update_count_callback' => '_update_post_term_count',
113
- 'label' => $plural,
114
- 'labels' => array(
115
  'name' => $plural,
116
  'singular_name' => $singular,
117
  'menu_name' => ucwords( $plural ),
@@ -123,19 +124,19 @@ class WP_Job_Manager_Post_Types {
123
  'update_item' => sprintf( __( 'Update %s', 'wp-job-manager' ), $singular ),
124
  'add_new_item' => sprintf( __( 'Add New %s', 'wp-job-manager' ), $singular ),
125
  'new_item_name' => sprintf( __( 'New %s Name', 'wp-job-manager' ), $singular )
126
- ),
127
- 'show_ui' => true,
128
- 'show_tagcloud' => false,
129
- 'public' => $public,
130
- 'capabilities' => array(
131
- 'manage_terms' => $admin_capability,
132
- 'edit_terms' => $admin_capability,
133
- 'delete_terms' => $admin_capability,
134
- 'assign_terms' => $admin_capability,
135
- ),
136
- 'rewrite' => $rewrite,
137
- ) )
138
- );
139
  }
140
 
141
  if ( get_option( 'job_manager_enable_types' ) ) {
@@ -144,7 +145,7 @@ class WP_Job_Manager_Post_Types {
144
 
145
  if ( current_theme_supports( 'job-manager-templates' ) ) {
146
  $rewrite = array(
147
- 'slug' => _x( 'job-type', 'Job type slug - resave permalinks after changing this', 'wp-job-manager' ),
148
  'with_front' => false,
149
  'hierarchical' => false
150
  );
@@ -186,7 +187,7 @@ class WP_Job_Manager_Post_Types {
186
  );
187
  }
188
 
189
- /**
190
  * Post types
191
  */
192
  $singular = __( 'Job', 'wp-job-manager' );
@@ -199,7 +200,7 @@ class WP_Job_Manager_Post_Types {
199
  }
200
 
201
  $rewrite = array(
202
- 'slug' => _x( 'job', 'Job permalink - resave permalinks after changing this', 'wp-job-manager' ),
203
  'with_front' => false,
204
  'feeds' => true,
205
  'pages' => false
@@ -277,17 +278,21 @@ class WP_Job_Manager_Post_Types {
277
  public function admin_head() {
278
  global $menu;
279
 
280
- $plural = __( 'Job Listings', 'wp-job-manager' );
281
- $count_jobs = wp_count_posts( 'job_listing', 'readable' );
282
 
283
- if ( ! empty( $menu ) && is_array( $menu ) ) {
284
- foreach ( $menu as $key => $menu_item ) {
285
- if ( strpos( $menu_item[0], $plural ) === 0 ) {
286
- if ( $order_count = $count_jobs->pending ) {
287
- $menu[ $key ][0] .= " <span class='awaiting-mod update-plugins count-$order_count'><span class='pending-count'>" . number_format_i18n( $count_jobs->pending ) . "</span></span>" ;
288
- }
289
- break;
290
- }
 
 
 
 
 
291
  }
292
  }
293
  }
@@ -437,16 +442,17 @@ class WP_Job_Manager_Post_Types {
437
  * Adds custom data to the job feed.
438
  */
439
  public function job_feed_item() {
440
- $post_id = get_the_ID();
441
- $location = get_the_job_location( $post_id );
442
- $job_type = get_the_job_type( $post_id );
443
- $company = get_the_company_name( $post_id );
444
 
445
  if ( $location ) {
446
  echo "<job_listing:location><![CDATA[" . esc_html( $location ) . "]]></job_listing:location>\n";
447
  }
448
- if ( $job_type ) {
449
- echo "<job_listing:job_type><![CDATA[" . esc_html( $job_type->name ) . "]]></job_listing:job_type>\n";
 
450
  }
451
  if ( $company ) {
452
  echo "<job_listing:company><![CDATA[" . esc_html( $company ) . "]]></job_listing:company>\n";
@@ -594,7 +600,7 @@ class WP_Job_Manager_Post_Types {
594
  * @return array
595
  */
596
  public function fix_post_name( $data, $postarr ) {
597
- if ( 'job_listing' === $data['post_type'] && 'pending' === $data['post_status'] && ! current_user_can( 'publish_posts' ) ) {
598
  $data['post_name'] = $postarr['post_name'];
599
  }
600
  return $data;
11
  * The single instance of the class.
12
  *
13
  * @var self
14
+ * @since 1.26.0
15
  */
16
  private static $_instance = null;
17
 
18
  /**
19
  * Allows for accessing single instance of class. Class should only be constructed once per call.
20
  *
21
+ * @since 1.26.0
22
  * @static
23
  * @return self Main instance.
24
  */
86
 
87
  $admin_capability = 'manage_job_listings';
88
 
89
+ $permalink_structure = wpjm_get_permalink_structure();
90
  /**
91
  * Taxonomies
92
  */
96
 
97
  if ( current_theme_supports( 'job-manager-templates' ) ) {
98
  $rewrite = array(
99
+ 'slug' => $permalink_structure['category_rewrite_slug'],
100
  'with_front' => false,
101
  'hierarchical' => false
102
  );
108
 
109
  register_taxonomy( "job_listing_category",
110
  apply_filters( 'register_taxonomy_job_listing_category_object_type', array( 'job_listing' ) ),
111
+ apply_filters( 'register_taxonomy_job_listing_category_args', array(
112
+ 'hierarchical' => true,
113
+ 'update_count_callback' => '_update_post_term_count',
114
+ 'label' => $plural,
115
+ 'labels' => array(
116
  'name' => $plural,
117
  'singular_name' => $singular,
118
  'menu_name' => ucwords( $plural ),
124
  'update_item' => sprintf( __( 'Update %s', 'wp-job-manager' ), $singular ),
125
  'add_new_item' => sprintf( __( 'Add New %s', 'wp-job-manager' ), $singular ),
126
  'new_item_name' => sprintf( __( 'New %s Name', 'wp-job-manager' ), $singular )
127
+ ),
128
+ 'show_ui' => true,
129
+ 'show_tagcloud' => false,
130
+ 'public' => $public,
131
+ 'capabilities' => array(
132
+ 'manage_terms' => $admin_capability,
133
+ 'edit_terms' => $admin_capability,
134
+ 'delete_terms' => $admin_capability,
135
+ 'assign_terms' => $admin_capability,
136
+ ),
137
+ 'rewrite' => $rewrite,
138
+ ) )
139
+ );
140
  }
141
 
142
  if ( get_option( 'job_manager_enable_types' ) ) {
145
 
146
  if ( current_theme_supports( 'job-manager-templates' ) ) {
147
  $rewrite = array(
148
+ 'slug' => $permalink_structure['type_rewrite_slug'],
149
  'with_front' => false,
150
  'hierarchical' => false
151
  );
187
  );
188
  }
189
 
190
+ /**
191
  * Post types
192
  */
193
  $singular = __( 'Job', 'wp-job-manager' );
200
  }
201
 
202
  $rewrite = array(
203
+ 'slug' => $permalink_structure['job_rewrite_slug'],
204
  'with_front' => false,
205
  'feeds' => true,
206
  'pages' => false
278
  public function admin_head() {
279
  global $menu;
280
 
281
+ $pending_jobs = WP_Job_Manager_Cache_Helper::get_listings_count();
 
282
 
283
+ // No need to go further if no pending jobs, menu is not set, or is not an array
284
+ if( empty( $pending_jobs ) || empty( $menu ) || ! is_array( $menu ) ){
285
+ return;
286
+ }
287
+
288
+ // Try to pull menu_name from post type object to support themes/plugins that change the menu string
289
+ $post_type = get_post_type_object( 'job_listing' );
290
+ $plural = isset( $post_type->labels, $post_type->labels->menu_name ) ? $post_type->labels->menu_name : __( 'Job Listings', 'wp-job-manager' );
291
+
292
+ foreach ( $menu as $key => $menu_item ) {
293
+ if ( strpos( $menu_item[0], $plural ) === 0 ) {
294
+ $menu[ $key ][0] .= " <span class='awaiting-mod update-plugins count-{$pending_jobs}'><span class='pending-count'>" . number_format_i18n( $pending_jobs ) . "</span></span>" ;
295
+ break;
296
  }
297
  }
298
  }
442
  * Adds custom data to the job feed.
443
  */
444
  public function job_feed_item() {
445
+ $post_id = get_the_ID();
446
+ $location = get_the_job_location( $post_id );
447
+ $company = get_the_company_name( $post_id );
448
+ $job_types = wpjm_get_the_job_types( $post_id );
449
 
450
  if ( $location ) {
451
  echo "<job_listing:location><![CDATA[" . esc_html( $location ) . "]]></job_listing:location>\n";
452
  }
453
+ if ( ! empty( $job_types ) ) {
454
+ $job_types_names = implode( ', ', wp_list_pluck( $job_types, 'name' ) );
455
+ echo "<job_listing:job_type><![CDATA[" . esc_html( $job_types_names ) . "]]></job_listing:job_type>\n";
456
  }
457
  if ( $company ) {
458
  echo "<job_listing:company><![CDATA[" . esc_html( $company ) . "]]></job_listing:company>\n";
600
  * @return array
601
  */
602
  public function fix_post_name( $data, $postarr ) {
603
+ if ( 'job_listing' === $data['post_type'] && 'pending' === $data['post_status'] && ! current_user_can( 'publish_posts' ) && isset( $postarr['post_name'] ) ) {
604
  $data['post_name'] = $postarr['post_name'];
605
  }
606
  return $data;
includes/class-wp-job-manager-shortcodes.php CHANGED
@@ -22,14 +22,14 @@ class WP_Job_Manager_Shortcodes {
22
  * The single instance of the class.
23
  *
24
  * @var self
25
- * @since 1.26
26
  */
27
  private static $_instance = null;
28
 
29
  /**
30
  * Allows for accessing single instance of class. Class should only be constructed once per call.
31
  *
32
- * @since 1.26
33
  * @static
34
  * @return self Main instance.
35
  */
@@ -106,7 +106,7 @@ class WP_Job_Manager_Shortcodes {
106
  update_post_meta( $job_id, '_filled', 1 );
107
 
108
  // Message
109
- $this->job_dashboard_message = '<div class="job-manager-message">' . sprintf( __( '%s has been filled', 'wp-job-manager' ), esc_html( $job->post_title ) ) . '</div>';
110
  break;
111
  case 'mark_not_filled' :
112
  // Check status
@@ -118,14 +118,14 @@ class WP_Job_Manager_Shortcodes {
118
  update_post_meta( $job_id, '_filled', 0 );
119
 
120
  // Message
121
- $this->job_dashboard_message = '<div class="job-manager-message">' . sprintf( __( '%s has been marked as not filled', 'wp-job-manager' ), esc_html( $job->post_title ) ) . '</div>';
122
  break;
123
  case 'delete' :
124
  // Trash it
125
  wp_trash_post( $job_id );
126
 
127
  // Message
128
- $this->job_dashboard_message = '<div class="job-manager-message">' . sprintf( __( '%s has been deleted', 'wp-job-manager' ), esc_html( $job->post_title ) ) . '</div>';
129
 
130
  break;
131
  case 'duplicate' :
@@ -255,9 +255,10 @@ class WP_Job_Manager_Shortcodes {
255
  'show_pagination' => false,
256
  'show_more' => true,
257
 
258
- // Limit what jobs are shown based on category and type
259
  'categories' => '',
260
  'job_types' => '',
 
261
  'featured' => null, // True to show only featured, false to hide featured, leave null to show both.
262
  'filled' => null, // True to show only filled, false to hide filled, leave null to show both/use the settings.
263
 
@@ -290,6 +291,7 @@ class WP_Job_Manager_Shortcodes {
290
  // Array handling
291
  $categories = is_array( $categories ) ? $categories : array_filter( array_map( 'trim', explode( ',', $categories ) ) );
292
  $job_types = is_array( $job_types ) ? $job_types : array_filter( array_map( 'trim', explode( ',', $job_types ) ) );
 
293
  $selected_job_types = is_array( $selected_job_types ) ? $selected_job_types : array_filter( array_map( 'trim', explode( ',', $selected_job_types ) ) );
294
 
295
  // Get keywords and location from querystring if set
@@ -303,6 +305,16 @@ class WP_Job_Manager_Shortcodes {
303
  $selected_category = sanitize_text_field( $_GET['search_category'] );
304
  }
305
 
 
 
 
 
 
 
 
 
 
 
306
  if ( $show_filters ) {
307
 
308
  get_job_manager_template( 'job-filters.php', array( 'per_page' => $per_page, 'orderby' => $orderby, 'order' => $order, 'show_categories' => $show_categories, 'categories' => $categories, 'selected_category' => $selected_category, 'job_types' => $job_types, 'atts' => $atts, 'location' => $location, 'keywords' => $keywords, 'selected_job_types' => $selected_job_types, 'show_category_multiselect' => $show_category_multiselect ) );
@@ -315,10 +327,10 @@ class WP_Job_Manager_Shortcodes {
315
  }
316
 
317
  } else {
318
-
319
  $jobs = get_job_listings( apply_filters( 'job_manager_output_jobs_args', array(
320
  'search_location' => $location,
321
  'search_keywords' => $keywords,
 
322
  'search_categories' => $categories,
323
  'job_types' => $job_types,
324
  'orderby' => $orderby,
@@ -328,6 +340,10 @@ class WP_Job_Manager_Shortcodes {
328
  'filled' => $filled
329
  ) ) );
330
 
 
 
 
 
331
  if ( $jobs->have_posts() ) : ?>
332
 
333
  <?php get_job_manager_template( 'job-listings-start.php' ); ?>
@@ -358,21 +374,14 @@ class WP_Job_Manager_Shortcodes {
358
  }
359
 
360
  $data_attributes_string = '';
361
- $data_attributes = array(
362
- 'location' => $location,
363
- 'keywords' => $keywords,
364
- 'show_filters' => $show_filters ? 'true' : 'false',
365
- 'show_pagination' => $show_pagination ? 'true' : 'false',
366
- 'per_page' => $per_page,
367
- 'orderby' => $orderby,
368
- 'order' => $order,
369
- 'categories' => implode( ',', $categories ),
370
- );
371
  if ( ! is_null( $featured ) ) {
372
- $data_attributes[ 'featured' ] = $featured ? 'true' : 'false';
373
  }
374
  if ( ! is_null( $filled ) ) {
375
- $data_attributes[ 'filled' ] = $filled ? 'true' : 'false';
 
 
 
376
  }
377
  foreach ( $data_attributes as $key => $value ) {
378
  $data_attributes_string .= 'data-' . esc_attr( $key ) . '="' . esc_attr( $value ) . '" ';
@@ -450,7 +459,7 @@ class WP_Job_Manager_Shortcodes {
450
 
451
  <?php while ( $jobs->have_posts() ) : $jobs->the_post(); ?>
452
 
453
- <h1><?php echo esc_html( get_the_title() ); ?></h1>
454
 
455
  <?php get_job_manager_template_part( 'content-single', 'job_listing' ); ?>
456
 
22
  * The single instance of the class.
23
  *
24
  * @var self
25
+ * @since 1.26.0
26
  */
27
  private static $_instance = null;
28
 
29
  /**
30
  * Allows for accessing single instance of class. Class should only be constructed once per call.
31
  *
32
+ * @since 1.26.0
33
  * @static
34
  * @return self Main instance.
35
  */
106
  update_post_meta( $job_id, '_filled', 1 );
107
 
108
  // Message
109
+ $this->job_dashboard_message = '<div class="job-manager-message">' . sprintf( __( '%s has been filled', 'wp-job-manager' ), wpjm_get_the_job_title( $job ) ) . '</div>';
110
  break;
111
  case 'mark_not_filled' :
112
  // Check status
118
  update_post_meta( $job_id, '_filled', 0 );
119
 
120
  // Message
121
+ $this->job_dashboard_message = '<div class="job-manager-message">' . sprintf( __( '%s has been marked as not filled', 'wp-job-manager' ), wpjm_get_the_job_title( $job ) ) . '</div>';
122
  break;
123
  case 'delete' :
124
  // Trash it
125
  wp_trash_post( $job_id );
126
 
127
  // Message
128
+ $this->job_dashboard_message = '<div class="job-manager-message">' . sprintf( __( '%s has been deleted', 'wp-job-manager' ), wpjm_get_the_job_title( $job ) ) . '</div>';
129
 
130
  break;
131
  case 'duplicate' :
255
  'show_pagination' => false,
256
  'show_more' => true,
257
 
258
+ // Limit what jobs are shown based on category, post status, and type
259
  'categories' => '',
260
  'job_types' => '',
261
+ 'post_status' => '',
262
  'featured' => null, // True to show only featured, false to hide featured, leave null to show both.
263
  'filled' => null, // True to show only filled, false to hide filled, leave null to show both/use the settings.
264
 
291
  // Array handling
292
  $categories = is_array( $categories ) ? $categories : array_filter( array_map( 'trim', explode( ',', $categories ) ) );
293
  $job_types = is_array( $job_types ) ? $job_types : array_filter( array_map( 'trim', explode( ',', $job_types ) ) );
294
+ $post_status = is_array( $post_status ) ? $post_status : array_filter( array_map( 'trim', explode( ',', $post_status ) ) );
295
  $selected_job_types = is_array( $selected_job_types ) ? $selected_job_types : array_filter( array_map( 'trim', explode( ',', $selected_job_types ) ) );
296
 
297
  // Get keywords and location from querystring if set
305
  $selected_category = sanitize_text_field( $_GET['search_category'] );
306
  }
307
 
308
+ $data_attributes = array(
309
+ 'location' => $location,
310
+ 'keywords' => $keywords,
311
+ 'show_filters' => $show_filters ? 'true' : 'false',
312
+ 'show_pagination' => $show_pagination ? 'true' : 'false',
313
+ 'per_page' => $per_page,
314
+ 'orderby' => $orderby,
315
+ 'order' => $order,
316
+ 'categories' => implode( ',', $categories ),
317
+ );
318
  if ( $show_filters ) {
319
 
320
  get_job_manager_template( 'job-filters.php', array( 'per_page' => $per_page, 'orderby' => $orderby, 'order' => $order, 'show_categories' => $show_categories, 'categories' => $categories, 'selected_category' => $selected_category, 'job_types' => $job_types, 'atts' => $atts, 'location' => $location, 'keywords' => $keywords, 'selected_job_types' => $selected_job_types, 'show_category_multiselect' => $show_category_multiselect ) );
327
  }
328
 
329
  } else {
 
330
  $jobs = get_job_listings( apply_filters( 'job_manager_output_jobs_args', array(
331
  'search_location' => $location,
332
  'search_keywords' => $keywords,
333
+ 'post_status' => $post_status,
334
  'search_categories' => $categories,
335
  'job_types' => $job_types,
336
  'orderby' => $orderby,
340
  'filled' => $filled
341
  ) ) );
342
 
343
+ if ( ! empty( $job_types ) ) {
344
+ $data_attributes[ 'job_types' ] = implode( ',', $job_types );
345
+ }
346
+
347
  if ( $jobs->have_posts() ) : ?>
348
 
349
  <?php get_job_manager_template( 'job-listings-start.php' ); ?>
374
  }
375
 
376
  $data_attributes_string = '';
 
 
 
 
 
 
 
 
 
 
377
  if ( ! is_null( $featured ) ) {
378
+ $data_attributes[ 'featured' ] = $featured ? 'true' : 'false';
379
  }
380
  if ( ! is_null( $filled ) ) {
381
+ $data_attributes[ 'filled' ] = $filled ? 'true' : 'false';
382
+ }
383
+ if ( ! empty( $post_status ) ) {
384
+ $data_attributes[ 'post_status' ] = implode( ',', $post_status );
385
  }
386
  foreach ( $data_attributes as $key => $value ) {
387
  $data_attributes_string .= 'data-' . esc_attr( $key ) . '="' . esc_attr( $value ) . '" ';
459
 
460
  <?php while ( $jobs->have_posts() ) : $jobs->the_post(); ?>
461
 
462
+ <h1><?php wpjm_the_job_title(); ?></h1>
463
 
464
  <?php get_job_manager_template_part( 'content-single', 'job_listing' ); ?>
465
 
includes/forms/class-wp-job-manager-form-submit-job.php CHANGED
@@ -462,15 +462,36 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
462
  if ( ! job_manager_generate_username_from_email() && empty( $_POST['create_account_username'] ) ) {
463
  throw new Exception( __( 'Please enter a username.', 'wp-job-manager' ) );
464
  }
 
 
 
 
 
465
  if ( empty( $_POST['create_account_email'] ) ) {
466
  throw new Exception( __( 'Please enter your email address.', 'wp-job-manager' ) );
467
  }
468
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469
  if ( ! empty( $_POST['create_account_email'] ) ) {
470
  $create_account = wp_job_manager_create_account( array(
471
- 'username' => empty( $_POST['create_account_username'] ) ? '' : $_POST['create_account_username'],
 
472
  'email' => $_POST['create_account_email'],
473
- 'role' => get_option( 'job_manager_registration_role' )
474
  ) );
475
  }
476
  }
@@ -529,7 +550,19 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
529
 
530
  // Prepend with job type
531
  if ( apply_filters( 'submit_job_form_prefix_post_name_with_job_type', true ) && ! empty( $values['job']['job_type'] ) ) {
532
- $job_slug[] = $values['job']['job_type'];
 
 
 
 
 
 
 
 
 
 
 
 
533
  }
534
 
535
  $job_slug[] = $post_title;
@@ -577,7 +610,7 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
577
  }
578
 
579
  $attachment = array(
580
- 'post_title' => get_the_title( $this->job_id ),
581
  'post_content' => '',
582
  'post_status' => 'inherit',
583
  'post_parent' => $this->job_id,
@@ -624,7 +657,11 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
624
  // Company logo is a featured image
625
  } elseif ( 'company_logo' === $key ) {
626
  $attachment_id = is_numeric( $values[ $group_key ][ $key ] ) ? absint( $values[ $group_key ][ $key ] ) : $this->create_attachment( $values[ $group_key ][ $key ] );
627
- set_post_thumbnail( $this->job_id, $attachment_id );
 
 
 
 
628
  update_user_meta( get_current_user_id(), '_company_logo', $attachment_id );
629
 
630
  // Save meta data
462
  if ( ! job_manager_generate_username_from_email() && empty( $_POST['create_account_username'] ) ) {
463
  throw new Exception( __( 'Please enter a username.', 'wp-job-manager' ) );
464
  }
465
+ if ( ! wpjm_use_standard_password_setup_email() ) {
466
+ if ( empty( $_POST['create_account_password'] ) ) {
467
+ throw new Exception( __( 'Please enter a password.', 'wp-job-manager' ) );
468
+ }
469
+ }
470
  if ( empty( $_POST['create_account_email'] ) ) {
471
  throw new Exception( __( 'Please enter your email address.', 'wp-job-manager' ) );
472
  }
473
  }
474
+
475
+ if ( ! wpjm_use_standard_password_setup_email() && ! empty( $_POST['create_account_password'] ) ) {
476
+ if ( empty( $_POST['create_account_password_verify'] ) || $_POST['create_account_password_verify'] !== $_POST['create_account_password'] ) {
477
+ throw new Exception( __( 'Passwords must match.', 'wp-job-manager' ) );
478
+ }
479
+ if ( ! wpjm_validate_new_password( $_POST['create_account_password'] ) ) {
480
+ $password_hint = wpjm_get_password_rules_hint();
481
+ if ( $password_hint ) {
482
+ throw new Exception( sprintf( __( 'Invalid Password: %s', 'wp-job-manager' ), $password_hint ) );
483
+ } else {
484
+ throw new Exception( __( 'Password is not valid.', 'wp-job-manager' ) );
485
+ }
486
+ }
487
+ }
488
+
489
  if ( ! empty( $_POST['create_account_email'] ) ) {
490
  $create_account = wp_job_manager_create_account( array(
491
+ 'username' => ( job_manager_generate_username_from_email() || empty( $_POST['create_account_username'] ) ) ? '' : $_POST['create_account_username'],
492
+ 'password' => ( wpjm_use_standard_password_setup_email() || empty( $_POST['create_account_password'] ) ) ? '' : $_POST['create_account_password'],
493
  'email' => $_POST['create_account_email'],
494
+ 'role' => get_option( 'job_manager_registration_role' ),
495
  ) );
496
  }
497
  }
550
 
551
  // Prepend with job type
552
  if ( apply_filters( 'submit_job_form_prefix_post_name_with_job_type', true ) && ! empty( $values['job']['job_type'] ) ) {
553
+ if ( ! job_manager_multi_job_type() ) {
554
+ $job_slug[] = $values['job']['job_type'];
555
+ } else {
556
+ $terms = $values['job']['job_type'];
557
+
558
+ foreach ( $terms as $term ) {
559
+ $term = get_term_by( 'id', intval( $term ), 'job_listing_type' );
560
+
561
+ if ( $term ) {
562
+ $job_slug[] = $term->slug;
563
+ }
564
+ }
565
+ }
566
  }
567
 
568
  $job_slug[] = $post_title;
610
  }
611
 
612
  $attachment = array(
613
+ 'post_title' => wpjm_get_the_job_title( $this->job_id ),
614
  'post_content' => '',
615
  'post_status' => 'inherit',
616
  'post_parent' => $this->job_id,
657
  // Company logo is a featured image
658
  } elseif ( 'company_logo' === $key ) {
659
  $attachment_id = is_numeric( $values[ $group_key ][ $key ] ) ? absint( $values[ $group_key ][ $key ] ) : $this->create_attachment( $values[ $group_key ][ $key ] );
660
+ if ( empty( $attachment_id ) ) {
661
+ delete_post_thumbnail( $this->job_id );
662
+ } else {
663
+ set_post_thumbnail( $this->job_id, $attachment_id );
664
+ }
665
  update_user_meta( get_current_user_id(), '_company_logo', $attachment_id );
666
 
667
  // Save meta data
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.26.1\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wp-job-manager\n"
7
- "POT-Creation-Date: 2017-06-12 15:22:01+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -14,7 +14,7 @@ msgstr ""
14
  "X-Generator: grunt-wp-i18n 0.5.4\n"
15
 
16
  #: includes/admin/class-wp-job-manager-addons.php:82
17
- #: includes/admin/class-wp-job-manager-admin.php:82
18
  msgid "WP Job Manager Add-ons"
19
  msgstr ""
20
 
@@ -26,94 +26,106 @@ msgstr ""
26
  msgid "Check out the core add-on bundle &rarr;"
27
  msgstr ""
28
 
29
- #: includes/admin/class-wp-job-manager-admin.php:79
30
  msgid "Settings"
31
  msgstr ""
32
 
33
- #: includes/admin/class-wp-job-manager-admin.php:82
34
  msgid "Add-ons"
35
  msgstr ""
36
 
37
- #: includes/admin/class-wp-job-manager-cpt.php:74
38
- #: includes/admin/class-wp-job-manager-cpt.php:75
39
  msgid "Approve %s"
40
  msgstr ""
41
 
42
- #: includes/admin/class-wp-job-manager-cpt.php:77
43
- #: includes/admin/class-wp-job-manager-cpt.php:78
44
- msgid "Expire %s"
45
  msgstr ""
46
 
47
- #: includes/admin/class-wp-job-manager-cpt.php:166
48
- #: includes/admin/class-wp-job-manager-cpt.php:168
49
- msgid "%s approved"
50
  msgstr ""
51
 
52
- #: includes/admin/class-wp-job-manager-cpt.php:186
53
- #: includes/admin/class-wp-job-manager-cpt.php:188
54
  msgid "%s expired"
55
  msgstr ""
56
 
57
- #: includes/admin/class-wp-job-manager-cpt.php:220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  msgid "Select category"
59
  msgstr ""
60
 
61
- #: includes/admin/class-wp-job-manager-cpt.php:236
62
- #: includes/admin/class-wp-job-manager-cpt.php:280
63
  msgid "Position"
64
  msgstr ""
65
 
66
- #: includes/admin/class-wp-job-manager-cpt.php:251
67
  msgid "%s updated. <a href=\"%s\">View</a>"
68
  msgstr ""
69
 
70
- #: includes/admin/class-wp-job-manager-cpt.php:252
71
  msgid "Custom field updated."
72
  msgstr ""
73
 
74
- #: includes/admin/class-wp-job-manager-cpt.php:253
75
  msgid "Custom field deleted."
76
  msgstr ""
77
 
78
- #: includes/admin/class-wp-job-manager-cpt.php:254
79
  msgid "%s updated."
80
  msgstr ""
81
 
82
- #: includes/admin/class-wp-job-manager-cpt.php:255
83
  msgid "%s restored to revision from %s"
84
  msgstr ""
85
 
86
- #: includes/admin/class-wp-job-manager-cpt.php:256
87
  msgid "%s published. <a href=\"%s\">View</a>"
88
  msgstr ""
89
 
90
- #: includes/admin/class-wp-job-manager-cpt.php:257
91
  msgid "%s saved."
92
  msgstr ""
93
 
94
- #: includes/admin/class-wp-job-manager-cpt.php:258
95
  msgid "%s submitted. <a target=\"_blank\" href=\"%s\">Preview</a>"
96
  msgstr ""
97
 
98
- #: includes/admin/class-wp-job-manager-cpt.php:259
99
  msgid ""
100
  "%s scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" "
101
  "href=\"%2$s\">Preview</a>"
102
  msgstr ""
103
 
104
- #: includes/admin/class-wp-job-manager-cpt.php:260
105
  msgid "M j, Y @ G:i"
106
  msgstr ""
107
 
108
- #: includes/admin/class-wp-job-manager-cpt.php:261
109
  msgid "%s draft updated. <a target=\"_blank\" href=\"%s\">Preview</a>"
110
  msgstr ""
111
 
112
- #: includes/admin/class-wp-job-manager-cpt.php:281
113
  msgid "Type"
114
  msgstr ""
115
 
116
- #: includes/admin/class-wp-job-manager-cpt.php:282
117
  #: includes/admin/class-wp-job-manager-writepanels.php:55
118
  #: includes/forms/class-wp-job-manager-form-submit-job.php:171
119
  #: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:38
@@ -121,78 +133,90 @@ msgstr ""
121
  msgid "Location"
122
  msgstr ""
123
 
124
- #: includes/admin/class-wp-job-manager-cpt.php:283
125
  msgid "Status"
126
  msgstr ""
127
 
128
- #: includes/admin/class-wp-job-manager-cpt.php:284
129
  msgid "Posted"
130
  msgstr ""
131
 
132
- #: includes/admin/class-wp-job-manager-cpt.php:285
133
  msgid "Expires"
134
  msgstr ""
135
 
136
- #: includes/admin/class-wp-job-manager-cpt.php:286
137
  #: includes/admin/class-wp-job-manager-settings.php:103
138
  msgid "Categories"
139
  msgstr ""
140
 
141
- #: includes/admin/class-wp-job-manager-cpt.php:287
142
  msgid "Featured?"
143
  msgstr ""
144
 
145
- #: includes/admin/class-wp-job-manager-cpt.php:288
146
  #: includes/class-wp-job-manager-shortcodes.php:218
147
  msgid "Filled?"
148
  msgstr ""
149
 
150
- #: includes/admin/class-wp-job-manager-cpt.php:289
151
  msgid "Actions"
152
  msgstr ""
153
 
154
- #: includes/admin/class-wp-job-manager-cpt.php:349
155
  msgid "ID: %d"
156
  msgstr ""
157
 
158
- #: includes/admin/class-wp-job-manager-cpt.php:378
159
- #: includes/admin/class-wp-job-manager-cpt.php:383
160
  msgid "M j, Y"
161
  msgstr ""
162
 
163
- #: includes/admin/class-wp-job-manager-cpt.php:379
164
  msgid "by a guest"
165
  msgstr ""
166
 
167
- #: includes/admin/class-wp-job-manager-cpt.php:379
168
  msgid "by %s"
169
  msgstr ""
170
 
171
- #: includes/admin/class-wp-job-manager-cpt.php:397
172
  msgid "Approve"
173
  msgstr ""
174
 
175
- #: includes/admin/class-wp-job-manager-cpt.php:405
176
- #: includes/admin/class-wp-job-manager-writepanels.php:249
177
- #: includes/admin/class-wp-job-manager-writepanels.php:252
178
- #: includes/admin/class-wp-job-manager-writepanels.php:255
179
  msgid "View"
180
  msgstr ""
181
 
182
- #: includes/admin/class-wp-job-manager-cpt.php:412
183
- #: includes/class-wp-job-manager-post-types.php:217
184
  #: templates/job-dashboard.php:33 templates/job-dashboard.php:51
185
  msgid "Edit"
186
  msgstr ""
187
 
188
- #: includes/admin/class-wp-job-manager-cpt.php:419
189
  #: templates/job-dashboard.php:56
190
  msgid "Delete"
191
  msgstr ""
192
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  #: includes/admin/class-wp-job-manager-settings.php:63
194
- #: includes/class-wp-job-manager-post-types.php:213
195
- #: includes/class-wp-job-manager-post-types.php:280
196
  msgid "Job Listings"
197
  msgstr ""
198
 
@@ -299,7 +323,7 @@ msgid "Relative to the current date (e.g., 1 day, 1 week, 1 month ago)"
299
  msgstr ""
300
 
301
  #: includes/admin/class-wp-job-manager-settings.php:137
302
- msgid "Default date format as defined in Setttings"
303
  msgstr ""
304
 
305
  #: includes/admin/class-wp-job-manager-settings.php:143
@@ -389,116 +413,131 @@ msgid ""
389
  msgstr ""
390
 
391
  #: includes/admin/class-wp-job-manager-settings.php:200
392
- msgid "Account Role"
393
  msgstr ""
394
 
395
  #: includes/admin/class-wp-job-manager-settings.php:201
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
  msgid ""
397
  "If you enable registration on your submission form, choose a role for the "
398
  "new user."
399
  msgstr ""
400
 
401
- #: includes/admin/class-wp-job-manager-settings.php:208
402
  msgid "Moderate New Listings"
403
  msgstr ""
404
 
405
- #: includes/admin/class-wp-job-manager-settings.php:209
406
  msgid "New listing submissions require admin approval"
407
  msgstr ""
408
 
409
- #: includes/admin/class-wp-job-manager-settings.php:210
410
  msgid "If enabled, new submissions will be inactive, pending admin approval."
411
  msgstr ""
412
 
413
- #: includes/admin/class-wp-job-manager-settings.php:217
414
  msgid "Allow Pending Edits"
415
  msgstr ""
416
 
417
- #: includes/admin/class-wp-job-manager-settings.php:218
418
  msgid "Submissions awaiting approval can be edited"
419
  msgstr ""
420
 
421
- #: includes/admin/class-wp-job-manager-settings.php:219
422
  msgid "If enabled, submissions awaiting admin approval can be edited by the user."
423
  msgstr ""
424
 
425
- #: includes/admin/class-wp-job-manager-settings.php:226
426
  msgid "Listing Duration"
427
  msgstr ""
428
 
429
- #: includes/admin/class-wp-job-manager-settings.php:227
430
  msgid ""
431
  "How many <strong>days</strong> listings are live before expiring. Can be "
432
  "left blank to never expire."
433
  msgstr ""
434
 
435
- #: includes/admin/class-wp-job-manager-settings.php:233
436
  msgid "Application Method"
437
  msgstr ""
438
 
439
- #: includes/admin/class-wp-job-manager-settings.php:234
440
  msgid "Choose the contact method for listings."
441
  msgstr ""
442
 
443
- #: includes/admin/class-wp-job-manager-settings.php:237
444
  msgid "Email address or website URL"
445
  msgstr ""
446
 
447
- #: includes/admin/class-wp-job-manager-settings.php:238
448
  msgid "Email addresses only"
449
  msgstr ""
450
 
451
- #: includes/admin/class-wp-job-manager-settings.php:239
452
  msgid "Website URLs only"
453
  msgstr ""
454
 
455
- #: includes/admin/class-wp-job-manager-settings.php:245
456
  msgid "Pages"
457
  msgstr ""
458
 
459
- #: includes/admin/class-wp-job-manager-settings.php:250
460
  msgid "Submit Job Form Page"
461
  msgstr ""
462
 
463
- #: includes/admin/class-wp-job-manager-settings.php:251
464
  msgid ""
465
  "Select the page where you have placed the [submit_job_form] shortcode. This "
466
  "lets the plugin know where the form is located."
467
  msgstr ""
468
 
469
- #: includes/admin/class-wp-job-manager-settings.php:257
470
  msgid "Job Dashboard Page"
471
  msgstr ""
472
 
473
- #: includes/admin/class-wp-job-manager-settings.php:258
474
  msgid ""
475
  "Select the page where you have placed the [job_dashboard] shortcode. This "
476
  "lets the plugin know where the dashboard is located."
477
  msgstr ""
478
 
479
- #: includes/admin/class-wp-job-manager-settings.php:264
480
  msgid "Job Listings Page"
481
  msgstr ""
482
 
483
- #: includes/admin/class-wp-job-manager-settings.php:265
484
  msgid ""
485
  "Select the page where you have placed the [jobs] shortcode. This lets the "
486
  "plugin know where the job listings page is located."
487
  msgstr ""
488
 
489
- #: includes/admin/class-wp-job-manager-settings.php:311
490
  msgid "Settings successfully saved"
491
  msgstr ""
492
 
493
- #: includes/admin/class-wp-job-manager-settings.php:371
494
  msgid "--no page--"
495
  msgstr ""
496
 
497
- #: includes/admin/class-wp-job-manager-settings.php:376
498
  msgid "Select a page&hellip;"
499
  msgstr ""
500
 
501
- #: includes/admin/class-wp-job-manager-settings.php:422
502
  msgid "Save Changes"
503
  msgstr ""
504
 
@@ -761,49 +800,49 @@ msgstr ""
761
  msgid "Posted by"
762
  msgstr ""
763
 
764
- #: includes/admin/class-wp-job-manager-writepanels.php:152
765
  msgid "%s Data"
766
  msgstr ""
767
 
768
- #: includes/admin/class-wp-job-manager-writepanels.php:192
769
  msgid "Most Used"
770
  msgstr ""
771
 
772
- #: includes/admin/class-wp-job-manager-writepanels.php:249
773
- #: includes/admin/class-wp-job-manager-writepanels.php:252
774
- #: includes/admin/class-wp-job-manager-writepanels.php:255
775
  msgid "Use file"
776
  msgstr ""
777
 
778
- #: includes/admin/class-wp-job-manager-writepanels.php:249
779
- #: includes/admin/class-wp-job-manager-writepanels.php:252
780
- #: includes/admin/class-wp-job-manager-writepanels.php:255
781
  msgid "Upload"
782
  msgstr ""
783
 
784
- #: includes/admin/class-wp-job-manager-writepanels.php:255
785
  msgid "Add file"
786
  msgstr ""
787
 
788
- #: includes/admin/class-wp-job-manager-writepanels.php:428
789
  msgid "Guest User"
790
  msgstr ""
791
 
792
- #: includes/admin/class-wp-job-manager-writepanels.php:430
793
  msgid "Change"
794
  msgstr ""
795
 
796
- #: includes/admin/class-wp-job-manager-writepanels.php:434
797
  msgid "Enter the ID of the user, or leave blank if submitted by a guest."
798
  msgstr ""
799
 
800
- #: includes/class-wp-job-manager-ajax.php:168
801
  msgid "Search completed. Found %d matching record."
802
  msgid_plural "Search completed. Found %d matching records."
803
  msgstr[0] ""
804
  msgstr[1] ""
805
 
806
- #: includes/class-wp-job-manager-ajax.php:267
807
  msgid "You must be logged in to upload files using this method."
808
  msgstr ""
809
 
@@ -821,132 +860,132 @@ msgstr ""
821
  msgid "Geocoding error"
822
  msgstr ""
823
 
824
- #: includes/class-wp-job-manager-install.php:61
825
  msgid "Employer"
826
  msgstr ""
827
 
828
- #: includes/class-wp-job-manager-post-types.php:93
829
  #: includes/forms/class-wp-job-manager-form-submit-job.php:188
830
  msgid "Job category"
831
  msgstr ""
832
 
833
- #: includes/class-wp-job-manager-post-types.php:94
834
  msgid "Job categories"
835
  msgstr ""
836
 
837
- #: includes/class-wp-job-manager-post-types.php:118
838
- #: includes/class-wp-job-manager-post-types.php:166
839
- #: includes/class-wp-job-manager-post-types.php:222
840
- msgid "Search %s"
841
- msgstr ""
842
-
843
  #: includes/class-wp-job-manager-post-types.php:119
844
  #: includes/class-wp-job-manager-post-types.php:167
845
- #: includes/class-wp-job-manager-post-types.php:214
846
- msgid "All %s"
847
  msgstr ""
848
 
849
  #: includes/class-wp-job-manager-post-types.php:120
850
  #: includes/class-wp-job-manager-post-types.php:168
851
- #: includes/class-wp-job-manager-post-types.php:225
852
- msgid "Parent %s"
853
  msgstr ""
854
 
855
  #: includes/class-wp-job-manager-post-types.php:121
856
  #: includes/class-wp-job-manager-post-types.php:169
857
- msgid "Parent %s:"
 
858
  msgstr ""
859
 
860
  #: includes/class-wp-job-manager-post-types.php:122
861
  #: includes/class-wp-job-manager-post-types.php:170
862
- #: includes/class-wp-job-manager-post-types.php:218
863
- msgid "Edit %s"
864
  msgstr ""
865
 
866
  #: includes/class-wp-job-manager-post-types.php:123
867
  #: includes/class-wp-job-manager-post-types.php:171
868
- msgid "Update %s"
 
869
  msgstr ""
870
 
871
  #: includes/class-wp-job-manager-post-types.php:124
872
  #: includes/class-wp-job-manager-post-types.php:172
873
- msgid "Add New %s"
874
  msgstr ""
875
 
876
  #: includes/class-wp-job-manager-post-types.php:125
877
  #: includes/class-wp-job-manager-post-types.php:173
 
 
 
 
 
878
  msgid "New %s Name"
879
  msgstr ""
880
 
881
- #: includes/class-wp-job-manager-post-types.php:142
882
  #: includes/forms/class-wp-job-manager-form-submit-job.php:179
883
  msgid "Job type"
884
  msgstr ""
885
 
886
- #: includes/class-wp-job-manager-post-types.php:143
887
  msgid "Job types"
888
  msgstr ""
889
 
890
- #: includes/class-wp-job-manager-post-types.php:192
891
  msgid "Job"
892
  msgstr ""
893
 
894
- #: includes/class-wp-job-manager-post-types.php:193
895
  msgid "Jobs"
896
  msgstr ""
897
 
898
- #: includes/class-wp-job-manager-post-types.php:215
899
  msgid "Add New"
900
  msgstr ""
901
 
902
- #: includes/class-wp-job-manager-post-types.php:216
903
  msgid "Add %s"
904
  msgstr ""
905
 
906
- #: includes/class-wp-job-manager-post-types.php:219
907
  msgid "New %s"
908
  msgstr ""
909
 
910
- #: includes/class-wp-job-manager-post-types.php:220
911
  #: includes/class-wp-job-manager-post-types.php:221
 
912
  msgid "View %s"
913
  msgstr ""
914
 
915
- #: includes/class-wp-job-manager-post-types.php:223
916
  msgid "No %s found"
917
  msgstr ""
918
 
919
- #: includes/class-wp-job-manager-post-types.php:224
920
  msgid "No %s found in trash"
921
  msgstr ""
922
 
923
- #: includes/class-wp-job-manager-post-types.php:226
924
  msgid "Company Logo"
925
  msgstr ""
926
 
927
- #: includes/class-wp-job-manager-post-types.php:227
928
  msgid "Set company logo"
929
  msgstr ""
930
 
931
- #: includes/class-wp-job-manager-post-types.php:228
932
  msgid "Remove company logo"
933
  msgstr ""
934
 
935
- #: includes/class-wp-job-manager-post-types.php:229
936
  msgid "Use as company logo"
937
  msgstr ""
938
 
939
- #: includes/class-wp-job-manager-post-types.php:231
940
  msgid "This is where you can create and manage %s."
941
  msgstr ""
942
 
943
- #: includes/class-wp-job-manager-post-types.php:262
944
  msgid "Expired <span class=\"count\">(%s)</span>"
945
  msgid_plural "Expired <span class=\"count\">(%s)</span>"
946
  msgstr[0] ""
947
  msgstr[1] ""
948
 
949
- #: includes/class-wp-job-manager-post-types.php:270
950
  msgid "Preview <span class=\"count\">(%s)</span>"
951
  msgid_plural "Preview <span class=\"count\">(%s)</span>"
952
  msgstr[0] ""
@@ -995,8 +1034,8 @@ msgstr ""
995
  msgid "Listing Expires"
996
  msgstr ""
997
 
998
- #: includes/class-wp-job-manager-shortcodes.php:314
999
- #: includes/class-wp-job-manager-shortcodes.php:348
1000
  msgid "Load more listings"
1001
  msgstr ""
1002
 
@@ -1036,7 +1075,7 @@ msgid "Application email"
1036
  msgstr ""
1037
 
1038
  #: includes/forms/class-wp-job-manager-form-submit-job.php:144
1039
- #: templates/account-signin.php:49
1040
  msgid "you@yourdomain.com"
1041
  msgstr ""
1042
 
@@ -1123,7 +1162,7 @@ msgid "%s is invalid"
1123
  msgstr ""
1124
 
1125
  #: includes/forms/class-wp-job-manager-form-submit-job.php:311
1126
- #: wp-job-manager-functions.php:877
1127
  msgid "\"%s\" (filetype %s) needs to be one of the following file types: %s"
1128
  msgstr ""
1129
 
@@ -1143,11 +1182,27 @@ msgstr ""
1143
  msgid "Please enter a username."
1144
  msgstr ""
1145
 
1146
- #: includes/forms/class-wp-job-manager-form-submit-job.php:466
 
 
 
 
1147
  msgid "Please enter your email address."
1148
  msgstr ""
1149
 
 
 
 
 
 
 
 
 
1150
  #: includes/forms/class-wp-job-manager-form-submit-job.php:484
 
 
 
 
1151
  msgid "You must be signed in to post a new listing."
1152
  msgstr ""
1153
 
@@ -1192,42 +1247,34 @@ msgstr ""
1192
  msgid "Sign out"
1193
  msgstr ""
1194
 
1195
- #: templates/account-signin.php:22
1196
  msgid "Have an account?"
1197
  msgstr ""
1198
 
1199
- #: templates/account-signin.php:24 templates/job-dashboard-login.php:3
1200
  msgid "Sign in"
1201
  msgstr ""
1202
 
1203
- #: templates/account-signin.php:28
1204
  msgid ""
1205
  "If you don&rsquo;t have an account you can %screate one below by entering "
1206
  "your email address/username. Your account details will be confirmed via "
1207
  "email."
1208
  msgstr ""
1209
 
1210
- #: templates/account-signin.php:28
1211
  msgid "optionally"
1212
  msgstr ""
1213
 
1214
- #: templates/account-signin.php:32
1215
  msgid "You must sign in to create a new listing."
1216
  msgstr ""
1217
 
1218
- #: templates/account-signin.php:40
1219
- msgid "Username"
1220
- msgstr ""
1221
-
1222
- #: templates/account-signin.php:40 templates/account-signin.php:47
1223
- #: templates/job-submit.php:32 templates/job-submit.php:49
1224
  msgid "(optional)"
1225
  msgstr ""
1226
 
1227
- #: templates/account-signin.php:47
1228
- msgid "Your email"
1229
- msgstr ""
1230
-
1231
  #: templates/content-no-jobs-found.php:2
1232
  msgid "There are no listings matching your search."
1233
  msgstr ""
@@ -1236,11 +1283,11 @@ msgstr ""
1236
  msgid "There are currently no vacancies."
1237
  msgstr ""
1238
 
1239
- #: templates/content-single-job_listing-meta.php:25
1240
  msgid "This position has been filled"
1241
  msgstr ""
1242
 
1243
- #: templates/content-single-job_listing-meta.php:27
1244
  msgid "Applications have closed"
1245
  msgstr ""
1246
 
@@ -1253,12 +1300,12 @@ msgid "Maximum file size: %s."
1253
  msgstr ""
1254
 
1255
  #: templates/form-fields/multiselect-field.php:3
1256
- #: wp-job-manager-functions.php:665
1257
  msgid "No results match"
1258
  msgstr ""
1259
 
1260
  #: templates/form-fields/multiselect-field.php:3
1261
- #: wp-job-manager-functions.php:666
1262
  msgid "Select Some Options"
1263
  msgstr ""
1264
 
@@ -1355,31 +1402,35 @@ msgstr ""
1355
  msgid "%s submitted successfully. Your listing will be visible once approved."
1356
  msgstr ""
1357
 
1358
- #: wp-job-manager-functions.php:373
1359
  msgid "Reset"
1360
  msgstr ""
1361
 
1362
- #: wp-job-manager-functions.php:377
1363
  msgid "RSS"
1364
  msgstr ""
1365
 
1366
- #: wp-job-manager-functions.php:468
1367
  msgid "Invalid email address."
1368
  msgstr ""
1369
 
1370
- #: wp-job-manager-functions.php:476
1371
  msgid "Your email address isn&#8217;t correct."
1372
  msgstr ""
1373
 
1374
- #: wp-job-manager-functions.php:480
1375
  msgid "This email is already registered, please choose another one."
1376
  msgstr ""
1377
 
1378
- #: wp-job-manager-functions.php:664
 
 
 
 
1379
  msgid "Choose a category&hellip;"
1380
  msgstr ""
1381
 
1382
- #: wp-job-manager-functions.php:879
1383
  msgid "Uploaded files need to be one of the following file types: %s"
1384
  msgstr ""
1385
 
@@ -1391,27 +1442,43 @@ msgstr ""
1391
  msgid "Application via \"%s\" listing on %s"
1392
  msgstr ""
1393
 
1394
- #: wp-job-manager-template.php:298
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1395
  msgid "Posted on "
1396
  msgstr ""
1397
 
1398
- #: wp-job-manager-template.php:300 wp-job-manager-template.php:320
1399
  msgid "Posted %s ago"
1400
  msgstr ""
1401
 
1402
- #: wp-job-manager-template.php:343
1403
  msgid "Anywhere"
1404
  msgstr ""
1405
 
1406
- #: wp-job-manager.php:153
1407
  msgid "Load previous listings"
1408
  msgstr ""
1409
 
1410
- #: wp-job-manager.php:204
1411
  msgid "Invalid file type. Accepted types:"
1412
  msgstr ""
1413
 
1414
- #: wp-job-manager.php:215
1415
  msgid "Are you sure you want to delete this listing?"
1416
  msgstr ""
1417
 
@@ -1433,13 +1500,31 @@ msgstr ""
1433
  msgid "Automattic"
1434
  msgstr ""
1435
 
1436
- #: includes/admin/class-wp-job-manager-admin.php:68
1437
  #. translators: jQuery date format, see
1438
  #. http:api.jqueryui.com/datepicker/#utility-formatDate
1439
  msgctxt "Date format for jQuery datepicker."
1440
  msgid "yy-mm-dd"
1441
  msgstr ""
1442
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1443
  #: includes/admin/class-wp-job-manager-setup.php:190
1444
  msgctxt "Default page title (wizard)"
1445
  msgid "Post a Job"
@@ -1461,54 +1546,39 @@ msgctxt "Date format placeholder."
1461
  msgid "yyyy-mm-dd"
1462
  msgstr ""
1463
 
1464
- #: includes/class-wp-job-manager-post-types.php:98
1465
- msgctxt "Job category slug - resave permalinks after changing this"
1466
- msgid "job-category"
1467
- msgstr ""
1468
-
1469
- #: includes/class-wp-job-manager-post-types.php:147
1470
- msgctxt "Job type slug - resave permalinks after changing this"
1471
- msgid "job-type"
1472
- msgstr ""
1473
-
1474
- #: includes/class-wp-job-manager-post-types.php:196
1475
  msgctxt "Post type archive slug - resave permalinks after changing this"
1476
  msgid "jobs"
1477
  msgstr ""
1478
 
1479
- #: includes/class-wp-job-manager-post-types.php:202
1480
- msgctxt "Job permalink - resave permalinks after changing this"
1481
- msgid "job"
1482
- msgstr ""
1483
-
1484
- #: includes/class-wp-job-manager-post-types.php:256
1485
- #: wp-job-manager-functions.php:268
1486
  msgctxt "post status"
1487
  msgid "Expired"
1488
  msgstr ""
1489
 
1490
- #: includes/class-wp-job-manager-post-types.php:265
1491
- #: wp-job-manager-functions.php:269
1492
  msgctxt "post status"
1493
  msgid "Preview"
1494
  msgstr ""
1495
 
1496
- #: wp-job-manager-functions.php:267
1497
  msgctxt "post status"
1498
  msgid "Draft"
1499
  msgstr ""
1500
 
1501
- #: wp-job-manager-functions.php:270
1502
  msgctxt "post status"
1503
  msgid "Pending approval"
1504
  msgstr ""
1505
 
1506
- #: wp-job-manager-functions.php:271
1507
  msgctxt "post status"
1508
  msgid "Pending payment"
1509
  msgstr ""
1510
 
1511
- #: wp-job-manager-functions.php:272
1512
  msgctxt "post status"
1513
  msgid "Active"
1514
  msgstr ""
2
  # This file is distributed under the GPL2+.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: WP Job Manager 1.27.0\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wp-job-manager\n"
7
+ "POT-Creation-Date: 2017-07-06 11:18:20+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
14
  "X-Generator: grunt-wp-i18n 0.5.4\n"
15
 
16
  #: includes/admin/class-wp-job-manager-addons.php:82
17
+ #: includes/admin/class-wp-job-manager-admin.php:105
18
  msgid "WP Job Manager Add-ons"
19
  msgstr ""
20
 
26
  msgid "Check out the core add-on bundle &rarr;"
27
  msgstr ""
28
 
29
+ #: includes/admin/class-wp-job-manager-admin.php:102
30
  msgid "Settings"
31
  msgstr ""
32
 
33
+ #: includes/admin/class-wp-job-manager-admin.php:105
34
  msgid "Add-ons"
35
  msgstr ""
36
 
37
+ #: includes/admin/class-wp-job-manager-cpt.php:71
 
38
  msgid "Approve %s"
39
  msgstr ""
40
 
41
+ #: includes/admin/class-wp-job-manager-cpt.php:72
42
+ msgid "%s approved"
 
43
  msgstr ""
44
 
45
+ #: includes/admin/class-wp-job-manager-cpt.php:76
46
+ msgid "Expire %s"
 
47
  msgstr ""
48
 
49
+ #: includes/admin/class-wp-job-manager-cpt.php:77
 
50
  msgid "%s expired"
51
  msgstr ""
52
 
53
+ #: includes/admin/class-wp-job-manager-cpt.php:81
54
+ msgid "Mark %s Filled"
55
+ msgstr ""
56
+
57
+ #: includes/admin/class-wp-job-manager-cpt.php:82
58
+ msgid "%s marked as filled"
59
+ msgstr ""
60
+
61
+ #: includes/admin/class-wp-job-manager-cpt.php:86
62
+ msgid "Mark %s Not Filled"
63
+ msgstr ""
64
+
65
+ #: includes/admin/class-wp-job-manager-cpt.php:87
66
+ msgid "%s marked as not filled"
67
+ msgstr ""
68
+
69
+ #: includes/admin/class-wp-job-manager-cpt.php:298
70
  msgid "Select category"
71
  msgstr ""
72
 
73
+ #: includes/admin/class-wp-job-manager-cpt.php:314
74
+ #: includes/admin/class-wp-job-manager-cpt.php:358
75
  msgid "Position"
76
  msgstr ""
77
 
78
+ #: includes/admin/class-wp-job-manager-cpt.php:329
79
  msgid "%s updated. <a href=\"%s\">View</a>"
80
  msgstr ""
81
 
82
+ #: includes/admin/class-wp-job-manager-cpt.php:330
83
  msgid "Custom field updated."
84
  msgstr ""
85
 
86
+ #: includes/admin/class-wp-job-manager-cpt.php:331
87
  msgid "Custom field deleted."
88
  msgstr ""
89
 
90
+ #: includes/admin/class-wp-job-manager-cpt.php:332
91
  msgid "%s updated."
92
  msgstr ""
93
 
94
+ #: includes/admin/class-wp-job-manager-cpt.php:333
95
  msgid "%s restored to revision from %s"
96
  msgstr ""
97
 
98
+ #: includes/admin/class-wp-job-manager-cpt.php:334
99
  msgid "%s published. <a href=\"%s\">View</a>"
100
  msgstr ""
101
 
102
+ #: includes/admin/class-wp-job-manager-cpt.php:335
103
  msgid "%s saved."
104
  msgstr ""
105
 
106
+ #: includes/admin/class-wp-job-manager-cpt.php:336
107
  msgid "%s submitted. <a target=\"_blank\" href=\"%s\">Preview</a>"
108
  msgstr ""
109
 
110
+ #: includes/admin/class-wp-job-manager-cpt.php:337
111
  msgid ""
112
  "%s scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" "
113
  "href=\"%2$s\">Preview</a>"
114
  msgstr ""
115
 
116
+ #: includes/admin/class-wp-job-manager-cpt.php:338
117
  msgid "M j, Y @ G:i"
118
  msgstr ""
119
 
120
+ #: includes/admin/class-wp-job-manager-cpt.php:339
121
  msgid "%s draft updated. <a target=\"_blank\" href=\"%s\">Preview</a>"
122
  msgstr ""
123
 
124
+ #: includes/admin/class-wp-job-manager-cpt.php:359
125
  msgid "Type"
126
  msgstr ""
127
 
128
+ #: includes/admin/class-wp-job-manager-cpt.php:360
129
  #: includes/admin/class-wp-job-manager-writepanels.php:55
130
  #: includes/forms/class-wp-job-manager-form-submit-job.php:171
131
  #: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:38
133
  msgid "Location"
134
  msgstr ""
135
 
136
+ #: includes/admin/class-wp-job-manager-cpt.php:361
137
  msgid "Status"
138
  msgstr ""
139
 
140
+ #: includes/admin/class-wp-job-manager-cpt.php:362
141
  msgid "Posted"
142
  msgstr ""
143
 
144
+ #: includes/admin/class-wp-job-manager-cpt.php:363
145
  msgid "Expires"
146
  msgstr ""
147
 
148
+ #: includes/admin/class-wp-job-manager-cpt.php:364
149
  #: includes/admin/class-wp-job-manager-settings.php:103
150
  msgid "Categories"
151
  msgstr ""
152
 
153
+ #: includes/admin/class-wp-job-manager-cpt.php:365
154
  msgid "Featured?"
155
  msgstr ""
156
 
157
+ #: includes/admin/class-wp-job-manager-cpt.php:366
158
  #: includes/class-wp-job-manager-shortcodes.php:218
159
  msgid "Filled?"
160
  msgstr ""
161
 
162
+ #: includes/admin/class-wp-job-manager-cpt.php:367
163
  msgid "Actions"
164
  msgstr ""
165
 
166
+ #: includes/admin/class-wp-job-manager-cpt.php:431
167
  msgid "ID: %d"
168
  msgstr ""
169
 
170
+ #: includes/admin/class-wp-job-manager-cpt.php:460
171
+ #: includes/admin/class-wp-job-manager-cpt.php:465
172
  msgid "M j, Y"
173
  msgstr ""
174
 
175
+ #: includes/admin/class-wp-job-manager-cpt.php:461
176
  msgid "by a guest"
177
  msgstr ""
178
 
179
+ #: includes/admin/class-wp-job-manager-cpt.php:461
180
  msgid "by %s"
181
  msgstr ""
182
 
183
+ #: includes/admin/class-wp-job-manager-cpt.php:479
184
  msgid "Approve"
185
  msgstr ""
186
 
187
+ #: includes/admin/class-wp-job-manager-cpt.php:487
188
+ #: includes/admin/class-wp-job-manager-writepanels.php:258
189
+ #: includes/admin/class-wp-job-manager-writepanels.php:261
190
+ #: includes/admin/class-wp-job-manager-writepanels.php:264
191
  msgid "View"
192
  msgstr ""
193
 
194
+ #: includes/admin/class-wp-job-manager-cpt.php:494
195
+ #: includes/class-wp-job-manager-post-types.php:218
196
  #: templates/job-dashboard.php:33 templates/job-dashboard.php:51
197
  msgid "Edit"
198
  msgstr ""
199
 
200
+ #: includes/admin/class-wp-job-manager-cpt.php:501
201
  #: templates/job-dashboard.php:56
202
  msgid "Delete"
203
  msgstr ""
204
 
205
+ #: includes/admin/class-wp-job-manager-permalink-settings.php:55
206
+ msgid "Job base"
207
+ msgstr ""
208
+
209
+ #: includes/admin/class-wp-job-manager-permalink-settings.php:62
210
+ msgid "Job category base"
211
+ msgstr ""
212
+
213
+ #: includes/admin/class-wp-job-manager-permalink-settings.php:69
214
+ msgid "Job type base"
215
+ msgstr ""
216
+
217
  #: includes/admin/class-wp-job-manager-settings.php:63
218
+ #: includes/class-wp-job-manager-post-types.php:214
219
+ #: includes/class-wp-job-manager-post-types.php:290
220
  msgid "Job Listings"
221
  msgstr ""
222
 
323
  msgstr ""
324
 
325
  #: includes/admin/class-wp-job-manager-settings.php:137
326
+ msgid "Default date format as defined in Settings"
327
  msgstr ""
328
 
329
  #: includes/admin/class-wp-job-manager-settings.php:143
413
  msgstr ""
414
 
415
  #: includes/admin/class-wp-job-manager-settings.php:200
416
+ msgid "Account Password"
417
  msgstr ""
418
 
419
  #: includes/admin/class-wp-job-manager-settings.php:201
420
+ msgid "Use WordPress' default behavior and email new users link to set a password"
421
+ msgstr ""
422
+
423
+ #: includes/admin/class-wp-job-manager-settings.php:202
424
+ msgid ""
425
+ "If enabled, an email will be sent to the user with their username and a "
426
+ "link to set their password. Otherwise, a password field will be shown and "
427
+ "their email address won't be verified."
428
+ msgstr ""
429
+
430
+ #: includes/admin/class-wp-job-manager-settings.php:209
431
+ msgid "Account Role"
432
+ msgstr ""
433
+
434
+ #: includes/admin/class-wp-job-manager-settings.php:210
435
  msgid ""
436
  "If you enable registration on your submission form, choose a role for the "
437
  "new user."
438
  msgstr ""
439
 
440
+ #: includes/admin/class-wp-job-manager-settings.php:217
441
  msgid "Moderate New Listings"
442
  msgstr ""
443
 
444
+ #: includes/admin/class-wp-job-manager-settings.php:218
445
  msgid "New listing submissions require admin approval"
446
  msgstr ""
447
 
448
+ #: includes/admin/class-wp-job-manager-settings.php:219
449
  msgid "If enabled, new submissions will be inactive, pending admin approval."
450
  msgstr ""
451
 
452
+ #: includes/admin/class-wp-job-manager-settings.php:226
453
  msgid "Allow Pending Edits"
454
  msgstr ""
455
 
456
+ #: includes/admin/class-wp-job-manager-settings.php:227
457
  msgid "Submissions awaiting approval can be edited"
458
  msgstr ""
459
 
460
+ #: includes/admin/class-wp-job-manager-settings.php:228
461
  msgid "If enabled, submissions awaiting admin approval can be edited by the user."
462
  msgstr ""
463
 
464
+ #: includes/admin/class-wp-job-manager-settings.php:235
465
  msgid "Listing Duration"
466
  msgstr ""
467
 
468
+ #: includes/admin/class-wp-job-manager-settings.php:236
469
  msgid ""
470
  "How many <strong>days</strong> listings are live before expiring. Can be "
471
  "left blank to never expire."
472
  msgstr ""
473
 
474
+ #: includes/admin/class-wp-job-manager-settings.php:242
475
  msgid "Application Method"
476
  msgstr ""
477
 
478
+ #: includes/admin/class-wp-job-manager-settings.php:243
479
  msgid "Choose the contact method for listings."
480
  msgstr ""
481
 
482
+ #: includes/admin/class-wp-job-manager-settings.php:246
483
  msgid "Email address or website URL"
484
  msgstr ""
485
 
486
+ #: includes/admin/class-wp-job-manager-settings.php:247
487
  msgid "Email addresses only"
488
  msgstr ""
489
 
490
+ #: includes/admin/class-wp-job-manager-settings.php:248
491
  msgid "Website URLs only"
492
  msgstr ""
493
 
494
+ #: includes/admin/class-wp-job-manager-settings.php:254
495
  msgid "Pages"
496
  msgstr ""
497
 
498
+ #: includes/admin/class-wp-job-manager-settings.php:259
499
  msgid "Submit Job Form Page"
500
  msgstr ""
501
 
502
+ #: includes/admin/class-wp-job-manager-settings.php:260
503
  msgid ""
504
  "Select the page where you have placed the [submit_job_form] shortcode. This "
505
  "lets the plugin know where the form is located."
506
  msgstr ""
507
 
508
+ #: includes/admin/class-wp-job-manager-settings.php:266
509
  msgid "Job Dashboard Page"
510
  msgstr ""
511
 
512
+ #: includes/admin/class-wp-job-manager-settings.php:267
513
  msgid ""
514
  "Select the page where you have placed the [job_dashboard] shortcode. This "
515
  "lets the plugin know where the dashboard is located."
516
  msgstr ""
517
 
518
+ #: includes/admin/class-wp-job-manager-settings.php:273
519
  msgid "Job Listings Page"
520
  msgstr ""
521
 
522
+ #: includes/admin/class-wp-job-manager-settings.php:274
523
  msgid ""
524
  "Select the page where you have placed the [jobs] shortcode. This lets the "
525
  "plugin know where the job listings page is located."
526
  msgstr ""
527
 
528
+ #: includes/admin/class-wp-job-manager-settings.php:320
529
  msgid "Settings successfully saved"
530
  msgstr ""
531
 
532
+ #: includes/admin/class-wp-job-manager-settings.php:380
533
  msgid "--no page--"
534
  msgstr ""
535
 
536
+ #: includes/admin/class-wp-job-manager-settings.php:385
537
  msgid "Select a page&hellip;"
538
  msgstr ""
539
 
540
+ #: includes/admin/class-wp-job-manager-settings.php:431
541
  msgid "Save Changes"
542
  msgstr ""
543
 
800
  msgid "Posted by"
801
  msgstr ""
802
 
803
+ #: includes/admin/class-wp-job-manager-writepanels.php:161
804
  msgid "%s Data"
805
  msgstr ""
806
 
807
+ #: includes/admin/class-wp-job-manager-writepanels.php:201
808
  msgid "Most Used"
809
  msgstr ""
810
 
811
+ #: includes/admin/class-wp-job-manager-writepanels.php:258
812
+ #: includes/admin/class-wp-job-manager-writepanels.php:261
813
+ #: includes/admin/class-wp-job-manager-writepanels.php:264
814
  msgid "Use file"
815
  msgstr ""
816
 
817
+ #: includes/admin/class-wp-job-manager-writepanels.php:258
818
+ #: includes/admin/class-wp-job-manager-writepanels.php:261
819
+ #: includes/admin/class-wp-job-manager-writepanels.php:264
820
  msgid "Upload"
821
  msgstr ""
822
 
823
+ #: includes/admin/class-wp-job-manager-writepanels.php:264
824
  msgid "Add file"
825
  msgstr ""
826
 
827
+ #: includes/admin/class-wp-job-manager-writepanels.php:490
828
  msgid "Guest User"
829
  msgstr ""
830
 
831
+ #: includes/admin/class-wp-job-manager-writepanels.php:492
832
  msgid "Change"
833
  msgstr ""
834
 
835
+ #: includes/admin/class-wp-job-manager-writepanels.php:496
836
  msgid "Enter the ID of the user, or leave blank if submitted by a guest."
837
  msgstr ""
838
 
839
+ #: includes/class-wp-job-manager-ajax.php:170
840
  msgid "Search completed. Found %d matching record."
841
  msgid_plural "Search completed. Found %d matching records."
842
  msgstr[0] ""
843
  msgstr[1] ""
844
 
845
+ #: includes/class-wp-job-manager-ajax.php:269
846
  msgid "You must be logged in to upload files using this method."
847
  msgstr ""
848
 
860
  msgid "Geocoding error"
861
  msgstr ""
862
 
863
+ #: includes/class-wp-job-manager-install.php:60
864
  msgid "Employer"
865
  msgstr ""
866
 
867
+ #: includes/class-wp-job-manager-post-types.php:94
868
  #: includes/forms/class-wp-job-manager-form-submit-job.php:188
869
  msgid "Job category"
870
  msgstr ""
871
 
872
+ #: includes/class-wp-job-manager-post-types.php:95
873
  msgid "Job categories"
874
  msgstr ""
875
 
 
 
 
 
 
 
876
  #: includes/class-wp-job-manager-post-types.php:119
877
  #: includes/class-wp-job-manager-post-types.php:167
878
+ #: includes/class-wp-job-manager-post-types.php:223
879
+ msgid "Search %s"
880
  msgstr ""
881
 
882
  #: includes/class-wp-job-manager-post-types.php:120
883
  #: includes/class-wp-job-manager-post-types.php:168
884
+ #: includes/class-wp-job-manager-post-types.php:215
885
+ msgid "All %s"
886
  msgstr ""
887
 
888
  #: includes/class-wp-job-manager-post-types.php:121
889
  #: includes/class-wp-job-manager-post-types.php:169
890
+ #: includes/class-wp-job-manager-post-types.php:226
891
+ msgid "Parent %s"
892
  msgstr ""
893
 
894
  #: includes/class-wp-job-manager-post-types.php:122
895
  #: includes/class-wp-job-manager-post-types.php:170
896
+ msgid "Parent %s:"
 
897
  msgstr ""
898
 
899
  #: includes/class-wp-job-manager-post-types.php:123
900
  #: includes/class-wp-job-manager-post-types.php:171
901
+ #: includes/class-wp-job-manager-post-types.php:219
902
+ msgid "Edit %s"
903
  msgstr ""
904
 
905
  #: includes/class-wp-job-manager-post-types.php:124
906
  #: includes/class-wp-job-manager-post-types.php:172
907
+ msgid "Update %s"
908
  msgstr ""
909
 
910
  #: includes/class-wp-job-manager-post-types.php:125
911
  #: includes/class-wp-job-manager-post-types.php:173
912
+ msgid "Add New %s"
913
+ msgstr ""
914
+
915
+ #: includes/class-wp-job-manager-post-types.php:126
916
+ #: includes/class-wp-job-manager-post-types.php:174
917
  msgid "New %s Name"
918
  msgstr ""
919
 
920
+ #: includes/class-wp-job-manager-post-types.php:143
921
  #: includes/forms/class-wp-job-manager-form-submit-job.php:179
922
  msgid "Job type"
923
  msgstr ""
924
 
925
+ #: includes/class-wp-job-manager-post-types.php:144
926
  msgid "Job types"
927
  msgstr ""
928
 
929
+ #: includes/class-wp-job-manager-post-types.php:193
930
  msgid "Job"
931
  msgstr ""
932
 
933
+ #: includes/class-wp-job-manager-post-types.php:194
934
  msgid "Jobs"
935
  msgstr ""
936
 
937
+ #: includes/class-wp-job-manager-post-types.php:216
938
  msgid "Add New"
939
  msgstr ""
940
 
941
+ #: includes/class-wp-job-manager-post-types.php:217
942
  msgid "Add %s"
943
  msgstr ""
944
 
945
+ #: includes/class-wp-job-manager-post-types.php:220
946
  msgid "New %s"
947
  msgstr ""
948
 
 
949
  #: includes/class-wp-job-manager-post-types.php:221
950
+ #: includes/class-wp-job-manager-post-types.php:222
951
  msgid "View %s"
952
  msgstr ""
953
 
954
+ #: includes/class-wp-job-manager-post-types.php:224
955
  msgid "No %s found"
956
  msgstr ""
957
 
958
+ #: includes/class-wp-job-manager-post-types.php:225
959
  msgid "No %s found in trash"
960
  msgstr ""
961
 
962
+ #: includes/class-wp-job-manager-post-types.php:227
963
  msgid "Company Logo"
964
  msgstr ""
965
 
966
+ #: includes/class-wp-job-manager-post-types.php:228
967
  msgid "Set company logo"
968
  msgstr ""
969
 
970
+ #: includes/class-wp-job-manager-post-types.php:229
971
  msgid "Remove company logo"
972
  msgstr ""
973
 
974
+ #: includes/class-wp-job-manager-post-types.php:230
975
  msgid "Use as company logo"
976
  msgstr ""
977
 
978
+ #: includes/class-wp-job-manager-post-types.php:232
979
  msgid "This is where you can create and manage %s."
980
  msgstr ""
981
 
982
+ #: includes/class-wp-job-manager-post-types.php:263
983
  msgid "Expired <span class=\"count\">(%s)</span>"
984
  msgid_plural "Expired <span class=\"count\">(%s)</span>"
985
  msgstr[0] ""
986
  msgstr[1] ""
987
 
988
+ #: includes/class-wp-job-manager-post-types.php:271
989
  msgid "Preview <span class=\"count\">(%s)</span>"
990
  msgid_plural "Preview <span class=\"count\">(%s)</span>"
991
  msgstr[0] ""
1034
  msgid "Listing Expires"
1035
  msgstr ""
1036
 
1037
+ #: includes/class-wp-job-manager-shortcodes.php:326
1038
+ #: includes/class-wp-job-manager-shortcodes.php:364
1039
  msgid "Load more listings"
1040
  msgstr ""
1041
 
1075
  msgstr ""
1076
 
1077
  #: includes/forms/class-wp-job-manager-form-submit-job.php:144
1078
+ #: wp-job-manager-template.php:384
1079
  msgid "you@yourdomain.com"
1080
  msgstr ""
1081
 
1162
  msgstr ""
1163
 
1164
  #: includes/forms/class-wp-job-manager-form-submit-job.php:311
1165
+ #: wp-job-manager-functions.php:971
1166
  msgid "\"%s\" (filetype %s) needs to be one of the following file types: %s"
1167
  msgstr ""
1168
 
1182
  msgid "Please enter a username."
1183
  msgstr ""
1184
 
1185
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:467
1186
+ msgid "Please enter a password."
1187
+ msgstr ""
1188
+
1189
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:471
1190
  msgid "Please enter your email address."
1191
  msgstr ""
1192
 
1193
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:477
1194
+ msgid "Passwords must match."
1195
+ msgstr ""
1196
+
1197
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:482
1198
+ msgid "Invalid Password: %s"
1199
+ msgstr ""
1200
+
1201
  #: includes/forms/class-wp-job-manager-form-submit-job.php:484
1202
+ msgid "Password is not valid."
1203
+ msgstr ""
1204
+
1205
+ #: includes/forms/class-wp-job-manager-form-submit-job.php:505
1206
  msgid "You must be signed in to post a new listing."
1207
  msgstr ""
1208
 
1247
  msgid "Sign out"
1248
  msgstr ""
1249
 
1250
+ #: templates/account-signin.php:21
1251
  msgid "Have an account?"
1252
  msgstr ""
1253
 
1254
+ #: templates/account-signin.php:23 templates/job-dashboard-login.php:3
1255
  msgid "Sign in"
1256
  msgstr ""
1257
 
1258
+ #: templates/account-signin.php:27
1259
  msgid ""
1260
  "If you don&rsquo;t have an account you can %screate one below by entering "
1261
  "your email address/username. Your account details will be confirmed via "
1262
  "email."
1263
  msgstr ""
1264
 
1265
+ #: templates/account-signin.php:27
1266
  msgid "optionally"
1267
  msgstr ""
1268
 
1269
+ #: templates/account-signin.php:31
1270
  msgid "You must sign in to create a new listing."
1271
  msgstr ""
1272
 
1273
+ #: templates/account-signin.php:42 templates/job-submit.php:32
1274
+ #: templates/job-submit.php:49
 
 
 
 
1275
  msgid "(optional)"
1276
  msgstr ""
1277
 
 
 
 
 
1278
  #: templates/content-no-jobs-found.php:2
1279
  msgid "There are no listings matching your search."
1280
  msgstr ""
1283
  msgid "There are currently no vacancies."
1284
  msgstr ""
1285
 
1286
+ #: templates/content-single-job_listing-meta.php:36
1287
  msgid "This position has been filled"
1288
  msgstr ""
1289
 
1290
+ #: templates/content-single-job_listing-meta.php:38
1291
  msgid "Applications have closed"
1292
  msgstr ""
1293
 
1300
  msgstr ""
1301
 
1302
  #: templates/form-fields/multiselect-field.php:3
1303
+ #: wp-job-manager-functions.php:759
1304
  msgid "No results match"
1305
  msgstr ""
1306
 
1307
  #: templates/form-fields/multiselect-field.php:3
1308
+ #: wp-job-manager-functions.php:760
1309
  msgid "Select Some Options"
1310
  msgstr ""
1311
 
1402
  msgid "%s submitted successfully. Your listing will be visible once approved."
1403
  msgstr ""
1404
 
1405
+ #: wp-job-manager-functions.php:361
1406
  msgid "Reset"
1407
  msgstr ""
1408
 
1409
+ #: wp-job-manager-functions.php:365
1410
  msgid "RSS"
1411
  msgstr ""
1412
 
1413
+ #: wp-job-manager-functions.php:460
1414
  msgid "Invalid email address."
1415
  msgstr ""
1416
 
1417
+ #: wp-job-manager-functions.php:468
1418
  msgid "Your email address isn&#8217;t correct."
1419
  msgstr ""
1420
 
1421
+ #: wp-job-manager-functions.php:472
1422
  msgid "This email is already registered, please choose another one."
1423
  msgstr ""
1424
 
1425
+ #: wp-job-manager-functions.php:676
1426
+ msgid "Passwords must be at least 8 characters long."
1427
+ msgstr ""
1428
+
1429
+ #: wp-job-manager-functions.php:758
1430
  msgid "Choose a category&hellip;"
1431
  msgstr ""
1432
 
1433
+ #: wp-job-manager-functions.php:973
1434
  msgid "Uploaded files need to be one of the following file types: %s"
1435
  msgstr ""
1436
 
1442
  msgid "Application via \"%s\" listing on %s"
1443
  msgstr ""
1444
 
1445
+ #: wp-job-manager-template.php:358
1446
+ msgid "Username"
1447
+ msgstr ""
1448
+
1449
+ #: wp-job-manager-template.php:366
1450
+ msgid "Password"
1451
+ msgstr ""
1452
+
1453
+ #: wp-job-manager-template.php:376
1454
+ msgid "Verify Password"
1455
+ msgstr ""
1456
+
1457
+ #: wp-job-manager-template.php:383
1458
+ msgid "Your email"
1459
+ msgstr ""
1460
+
1461
+ #: wp-job-manager-template.php:410
1462
  msgid "Posted on "
1463
  msgstr ""
1464
 
1465
+ #: wp-job-manager-template.php:412 wp-job-manager-template.php:432
1466
  msgid "Posted %s ago"
1467
  msgstr ""
1468
 
1469
+ #: wp-job-manager-template.php:455
1470
  msgid "Anywhere"
1471
  msgstr ""
1472
 
1473
+ #: wp-job-manager.php:185
1474
  msgid "Load previous listings"
1475
  msgstr ""
1476
 
1477
+ #: wp-job-manager.php:236
1478
  msgid "Invalid file type. Accepted types:"
1479
  msgstr ""
1480
 
1481
+ #: wp-job-manager.php:247
1482
  msgid "Are you sure you want to delete this listing?"
1483
  msgstr ""
1484
 
1500
  msgid "Automattic"
1501
  msgstr ""
1502
 
1503
+ #: includes/admin/class-wp-job-manager-admin.php:91
1504
  #. translators: jQuery date format, see
1505
  #. http:api.jqueryui.com/datepicker/#utility-formatDate
1506
  msgctxt "Date format for jQuery datepicker."
1507
  msgid "yy-mm-dd"
1508
  msgstr ""
1509
 
1510
+ #: includes/admin/class-wp-job-manager-permalink-settings.php:81
1511
+ #: wp-job-manager-functions.php:545
1512
+ msgctxt "Job permalink - resave permalinks after changing this"
1513
+ msgid "job"
1514
+ msgstr ""
1515
+
1516
+ #: includes/admin/class-wp-job-manager-permalink-settings.php:90
1517
+ #: wp-job-manager-functions.php:546
1518
+ msgctxt "Job category slug - resave permalinks after changing this"
1519
+ msgid "job-category"
1520
+ msgstr ""
1521
+
1522
+ #: includes/admin/class-wp-job-manager-permalink-settings.php:99
1523
+ #: wp-job-manager-functions.php:547
1524
+ msgctxt "Job type slug - resave permalinks after changing this"
1525
+ msgid "job-type"
1526
+ msgstr ""
1527
+
1528
  #: includes/admin/class-wp-job-manager-setup.php:190
1529
  msgctxt "Default page title (wizard)"
1530
  msgid "Post a Job"
1546
  msgid "yyyy-mm-dd"
1547
  msgstr ""
1548
 
1549
+ #: includes/class-wp-job-manager-post-types.php:197
 
 
 
 
 
 
 
 
 
 
1550
  msgctxt "Post type archive slug - resave permalinks after changing this"
1551
  msgid "jobs"
1552
  msgstr ""
1553
 
1554
+ #: includes/class-wp-job-manager-post-types.php:257
1555
+ #: wp-job-manager-functions.php:256
 
 
 
 
 
1556
  msgctxt "post status"
1557
  msgid "Expired"
1558
  msgstr ""
1559
 
1560
+ #: includes/class-wp-job-manager-post-types.php:266
1561
+ #: wp-job-manager-functions.php:257
1562
  msgctxt "post status"
1563
  msgid "Preview"
1564
  msgstr ""
1565
 
1566
+ #: wp-job-manager-functions.php:255
1567
  msgctxt "post status"
1568
  msgid "Draft"
1569
  msgstr ""
1570
 
1571
+ #: wp-job-manager-functions.php:258
1572
  msgctxt "post status"
1573
  msgid "Pending approval"
1574
  msgstr ""
1575
 
1576
+ #: wp-job-manager-functions.php:259
1577
  msgctxt "post status"
1578
  msgid "Pending payment"
1579
  msgstr ""
1580
 
1581
+ #: wp-job-manager-functions.php:260
1582
  msgctxt "post status"
1583
  msgid "Active"
1584
  msgstr ""
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === WP Job Manager ===
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.1
5
  Tested up to: 4.8
6
- Stable tag: 1.26.2
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -72,7 +72,7 @@ Use the WordPress.org forums for community support where we try to help all user
72
 
73
  If you need help with one of our add-ons, [please raise a ticket in our help desk](https://wpjobmanager.com/support/).
74
 
75
- If you want help with a customisation, please consider hiring a developer! [http://jobs.wordpress.net/](http://jobs.wordpress.net/) is a good place to start.
76
 
77
  == Installation ==
78
 
@@ -111,12 +111,12 @@ View the getting [installation](https://wpjobmanager.com/document/installation/)
111
  Yes! If you don't setup the [submit_job_form] shortcode, you can just post from the admin backend.
112
 
113
  = How can I customize the job application process? =
114
- There are several ways to customise the job application process in WP Job Manager, including using some extra plugins (some are free on Wordpress.org).
115
 
116
- See: [Customising the Job Application Process](https://wpjobmanager.com/document/customising-job-application-process/)
117
 
118
  = How can I customize the job submission form? =
119
- There are three ways to customise the fields in WP Job Manager;
120
 
121
  1. For simple text changes, using a localisation file or a plugin such as https://wordpress.org/plugins/say-what/
122
  2. For field changes, or adding new fields, using functions/filters inside your theme's functions.php file: [https://wpjobmanager.com/document/editing-job-submission-fields/](https://wpjobmanager.com/document/editing-job-submission-fields/)
@@ -141,6 +141,25 @@ You can view (and contribute) translations via the [translate.wordpress.org](htt
141
 
142
  == Changelog ==
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  = 1.26.2 =
145
  * 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)
146
  * 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)
@@ -175,7 +194,7 @@ You can view (and contribute) translations via the [translate.wordpress.org](htt
175
  * 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.
176
  * Fix: Prevent a potential CSRF vector. https://github.com/automattic/wp-job-manager/pull/891 Props Jay Patel for the responsible disclosure.
177
  * Fix: Improve load time by removing unnecessary oEmbed call. https://github.com/automattic/wp-job-manager/pull/768 Props Myles McNamara.
178
- * Fix: Improve WPML compatability. https://github.com/automattic/wp-job-manager/pull/787 Props Spencer Finnell.
179
  * Fix: Add an implicit whitelist for API requests. https://github.com/automattic/wp-job-manager/pull/855 Props muddletoes.
180
  * Fix: Fixed taxonomy search conditions. See https://github.com/automattic/wp-job-manager/pull/859/ Props Jonas Vogel.
181
 
1
  === WP Job Manager ===
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.27.0
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
72
 
73
  If you need help with one of our add-ons, [please raise a ticket in our help desk](https://wpjobmanager.com/support/).
74
 
75
+ If you want help with a customization, please consider hiring a developer! [http://jobs.wordpress.net/](http://jobs.wordpress.net/) is a good place to start.
76
 
77
  == Installation ==
78
 
111
  Yes! If you don't setup the [submit_job_form] shortcode, you can just post from the admin backend.
112
 
113
  = How can I customize the job application process? =
114
+ There are several ways to customize the job application process in WP Job Manager, including using some extra plugins (some are free on Wordpress.org).
115
 
116
+ See: [Customizing the Job Application Process](https://wpjobmanager.com/document/customising-job-application-process/)
117
 
118
  = How can I customize the job submission form? =
119
+ There are three ways to customize the fields in WP Job Manager;
120
 
121
  1. For simple text changes, using a localisation file or a plugin such as https://wordpress.org/plugins/say-what/
122
  2. For field changes, or adding new fields, using functions/filters inside your theme's functions.php file: [https://wpjobmanager.com/document/editing-job-submission-fields/](https://wpjobmanager.com/document/editing-job-submission-fields/)
141
 
142
  == Changelog ==
143
 
144
+ = 1.27.0 =
145
+ * Enhancement: Admins can now allow users to specify an account password when posting their first job listing. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1063)
146
+ * Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1024)
147
+ * Enhancement: Allows users to override permalink slugs in WP Admin's Permalink Settings screen. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1042)
148
+ * Enhancement: Allows admins to perform bulk updating of jobs as filled/not filled. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1049)
149
+ * Enhancement: Adds job listing status CSS classes on single job listings. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1041)
150
+ * 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)
151
+ * Enhancement: Allows admins to filter by `post_status` in `[jobs]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1051)
152
+ * Enhancement: Allows accessing settings tab from hash in URL. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/999)
153
+ * Fix: Make sure cron jobs for checking/cleaning expired listings are always in place. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1058)
154
+ * Fix: Better handling of multiple job types. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/1014)
155
+ * Fix: Issue with deleting company logos from job listings submission form. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1047)
156
+ * Fix: Warning thrown on job submission form when user not logged in. (@piersb; https://github.com/Automattic/WP-Job-Manager/pull/1011)
157
+ * Fix: Issue with WPML not syncing some meta fields. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1027)
158
+ * Fix: Better handling of AJAX upload errors. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/1044)
159
+ * Fix: Remove job posting cookies on logout. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1065)
160
+ * Fix: Expiration date can be cleared if default job duration option is empty. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/1076)
161
+ * Fix: Issue with Safari and expiration datepicker. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1078)
162
+
163
  = 1.26.2 =
164
  * 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)
165
  * 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)
194
  * 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.
195
  * Fix: Prevent a potential CSRF vector. https://github.com/automattic/wp-job-manager/pull/891 Props Jay Patel for the responsible disclosure.
196
  * Fix: Improve load time by removing unnecessary oEmbed call. https://github.com/automattic/wp-job-manager/pull/768 Props Myles McNamara.
197
+ * Fix: Improve WPML compatibility. https://github.com/automattic/wp-job-manager/pull/787 Props Spencer Finnell.
198
  * Fix: Add an implicit whitelist for API requests. https://github.com/automattic/wp-job-manager/pull/855 Props muddletoes.
199
  * Fix: Fixed taxonomy search conditions. See https://github.com/automattic/wp-job-manager/pull/859/ Props Jonas Vogel.
200
 
templates/account-signin.php CHANGED
@@ -13,10 +13,9 @@
13
  </fieldset>
14
 
15
  <?php else :
16
-
17
- $account_required = job_manager_user_requires_account();
18
- $registration_enabled = job_manager_enable_registration();
19
- $generate_username_from_email = job_manager_generate_username_from_email();
20
  ?>
21
  <fieldset>
22
  <label><?php _e( 'Have an account?', 'wp-job-manager' ); ?></label>
@@ -34,22 +33,20 @@
34
  <?php endif; ?>
35
  </div>
36
  </fieldset>
37
- <?php if ( $registration_enabled ) : ?>
38
- <?php if ( ! $generate_username_from_email ) : ?>
39
- <fieldset>
40
- <label><?php _e( 'Username', 'wp-job-manager' ); ?> <?php echo apply_filters( 'submit_job_form_required_label', ( ! $account_required ) ? ' <small>' . __( '(optional)', 'wp-job-manager' ) . '</small>' : '' ); ?></label>
41
- <div class="field">
42
- <input type="text" class="input-text" name="create_account_username" id="account_username" value="<?php echo empty( $_POST['create_account_username'] ) ? '' : esc_attr( sanitize_text_field( stripslashes( $_POST['create_account_username'] ) ) ); ?>" />
 
 
 
43
  </div>
44
  </fieldset>
45
- <?php endif; ?>
46
- <fieldset>
47
- <label><?php _e( 'Your email', 'wp-job-manager' ); ?> <?php echo apply_filters( 'submit_job_form_required_label', ( ! $account_required ) ? ' <small>' . __( '(optional)', 'wp-job-manager' ) . '</small>' : '' ); ?></label>
48
- <div class="field">
49
- <input type="email" class="input-text" name="create_account_email" id="account_email" placeholder="<?php esc_attr_e( 'you@yourdomain.com', 'wp-job-manager' ); ?>" value="<?php echo empty( $_POST['create_account_email'] ) ? '' : esc_attr( sanitize_text_field( stripslashes( $_POST['create_account_email'] ) ) ); ?>" />
50
- </div>
51
- </fieldset>
52
- <?php do_action( 'job_manager_register_form' ); ?>
53
- <?php endif; ?>
54
-
55
  <?php endif; ?>
13
  </fieldset>
14
 
15
  <?php else :
16
+ $account_required = job_manager_user_requires_account();
17
+ $registration_enabled = job_manager_enable_registration();
18
+ $registration_fields = wpjm_get_registration_fields();
 
19
  ?>
20
  <fieldset>
21
  <label><?php _e( 'Have an account?', 'wp-job-manager' ); ?></label>
33
  <?php endif; ?>
34
  </div>
35
  </fieldset>
36
+ <?php
37
+ if ( ! empty( $registration_fields ) ) {
38
+ foreach ( $registration_fields as $key => $field ) {
39
+ ?>
40
+ <fieldset class="fieldset-<?php echo esc_attr( $key ); ?>">
41
+ <label
42
+ for="<?php echo esc_attr( $key ); ?>"><?php echo $field[ 'label' ] . apply_filters( 'submit_job_form_required_label', $field[ 'required' ] ? '' : ' <small>' . __( '(optional)', 'wp-job-manager' ) . '</small>', $field ); ?></label>
43
+ <div class="field <?php echo $field[ 'required' ] ? 'required-field' : ''; ?>">
44
+ <?php get_job_manager_template( 'form-fields/' . $field[ 'type' ] . '-field.php', array( 'key' => $key, 'field' => $field ) ); ?>
45
  </div>
46
  </fieldset>
47
+ <?php
48
+ }
49
+ do_action( 'job_manager_register_form' );
50
+ }
51
+ ?>
 
 
 
 
 
52
  <?php endif; ?>
templates/content-job_listing.php CHANGED
@@ -1,9 +1,22 @@
1
- <?php global $post; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  <li <?php job_listing_class(); ?> data-longitude="<?php echo esc_attr( $post->geolocation_lat ); ?>" data-latitude="<?php echo esc_attr( $post->geolocation_long ); ?>">
3
  <a href="<?php the_job_permalink(); ?>">
4
  <?php the_company_logo(); ?>
5
  <div class="position">
6
- <h3><?php echo esc_html( get_the_title() ); ?></h3>
7
  <div class="company">
8
  <?php the_company_name( '<strong>', '</strong> ' ); ?>
9
  <?php the_company_tagline( '<span class="tagline">', '</span>' ); ?>
@@ -16,8 +29,12 @@
16
  <?php do_action( 'job_listing_meta_start' ); ?>
17
 
18
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
19
- <li class="job-type <?php echo get_the_job_type() ? sanitize_title( get_the_job_type()->slug ) : ''; ?>"><?php the_job_type(); ?></li>
 
 
 
20
  <?php } ?>
 
21
  <li class="date"><?php the_job_publish_date(); ?></li>
22
 
23
  <?php do_action( 'job_listing_meta_end' ); ?>
1
+ <?php
2
+ /**
3
+ * Job listing in the loop.
4
+ *
5
+ * @since 1.0.0
6
+ * @version 1.27.0
7
+ *
8
+ * @package WP Job Manager
9
+ * @category Template
10
+ * @author Automattic
11
+ */
12
+
13
+ global $post; ?>
14
+
15
  <li <?php job_listing_class(); ?> data-longitude="<?php echo esc_attr( $post->geolocation_lat ); ?>" data-latitude="<?php echo esc_attr( $post->geolocation_long ); ?>">
16
  <a href="<?php the_job_permalink(); ?>">
17
  <?php the_company_logo(); ?>
18
  <div class="position">
19
+ <h3><?php wpjm_the_job_title(); ?></h3>
20
  <div class="company">
21
  <?php the_company_name( '<strong>', '</strong> ' ); ?>
22
  <?php the_company_tagline( '<span class="tagline">', '</span>' ); ?>
29
  <?php do_action( 'job_listing_meta_start' ); ?>
30
 
31
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
32
+ <?php $types = wpjm_get_the_job_types(); ?>
33
+ <?php if ( ! empty( $types ) ) : foreach ( $types as $type ) : ?>
34
+ <li class="job-type <?php echo esc_attr( sanitize_title( $type->slug ) ); ?>" itemprop="employmentType"><?php echo esc_html( $type->name ); ?></li>
35
+ <?php endforeach; endif; ?>
36
  <?php } ?>
37
+
38
  <li class="date"><?php the_job_publish_date(); ?></li>
39
 
40
  <?php do_action( 'job_listing_meta_end' ); ?>
templates/content-single-job_listing-meta.php CHANGED
@@ -4,8 +4,14 @@
4
  *
5
  * Hooked into single_job_listing_start priority 20
6
  *
7
- * @since 1.14.0
 
 
 
 
 
8
  */
 
9
  global $post;
10
 
11
  do_action( 'single_job_listing_meta_before' ); ?>
@@ -14,7 +20,12 @@ do_action( 'single_job_listing_meta_before' ); ?>
14
  <?php do_action( 'single_job_listing_meta_start' ); ?>
15
 
16
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
17
- <li class="job-type <?php echo get_the_job_type() ? sanitize_title( get_the_job_type()->slug ) : ''; ?>" itemprop="employmentType"><?php the_job_type(); ?></li>
 
 
 
 
 
18
  <?php } ?>
19
 
20
  <li class="location" itemprop="jobLocation"><?php the_job_location(); ?></li>
4
  *
5
  * Hooked into single_job_listing_start priority 20
6
  *
7
+ * @since 1.14.0
8
+ * @version 1.27.0
9
+ *
10
+ * @package WP Job Manager
11
+ * @category Template
12
+ * @author Automattic
13
  */
14
+
15
  global $post;
16
 
17
  do_action( 'single_job_listing_meta_before' ); ?>
20
  <?php do_action( 'single_job_listing_meta_start' ); ?>
21
 
22
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
23
+ <?php $types = wpjm_get_the_job_types(); ?>
24
+ <?php if ( ! empty( $types ) ) : foreach ( $types as $type ) : ?>
25
+
26
+ <li class="job-type <?php echo esc_attr( sanitize_title( $type->slug ) ); ?>" itemprop="employmentType"><?php echo esc_html( $type->name ); ?></li>
27
+
28
+ <?php endforeach; endif; ?>
29
  <?php } ?>
30
 
31
  <li class="location" itemprop="jobLocation"><?php the_job_location(); ?></li>
templates/content-single-job_listing.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php global $post; ?>
2
  <div class="single_job_listing" itemscope itemtype="http://schema.org/JobPosting">
3
- <meta itemprop="title" content="<?php echo esc_attr( $post->post_title ); ?>" />
4
 
5
  <?php if ( get_option( 'job_manager_hide_expired_content', 1 ) && 'expired' === $post->post_status ) : ?>
6
  <div class="job-manager-info"><?php _e( 'This listing has expired.', 'wp-job-manager' ); ?></div>
1
  <?php global $post; ?>
2
  <div class="single_job_listing" itemscope itemtype="http://schema.org/JobPosting">
3
+ <meta itemprop="title" content="<?php echo esc_attr( wpjm_get_the_job_title( $post ) ); ?>" />
4
 
5
  <?php if ( get_option( 'job_manager_hide_expired_content', 1 ) && 'expired' === $post->post_status ) : ?>
6
  <div class="job-manager-info"><?php _e( 'This listing has expired.', 'wp-job-manager' ); ?></div>
templates/content-summary-job_listing.php CHANGED
@@ -2,7 +2,12 @@
2
 
3
  <a href="<?php the_permalink(); ?>">
4
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
5
- <div class="job-type <?php echo get_the_job_type() ? sanitize_title( get_the_job_type()->slug ) : ''; ?>"><?php the_job_type(); ?></div>
 
 
 
 
 
6
  <?php } ?>
7
 
8
  <?php if ( $logo = get_the_company_logo() ) : ?>
@@ -11,7 +16,7 @@
11
 
12
  <div class="job_summary_content">
13
 
14
- <h1><?php echo esc_html( get_the_title() ); ?></h1>
15
 
16
  <p class="meta"><?php the_job_location( false ); ?> &mdash; <?php the_job_publish_date(); ?></p>
17
 
2
 
3
  <a href="<?php the_permalink(); ?>">
4
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
5
+ <?php $types = wpjm_get_the_job_types(); ?>
6
+ <?php if ( ! empty( $types ) ) : foreach ( $types as $type ) : ?>
7
+
8
+ <div class="job-type <?php echo esc_attr( sanitize_title( $type->slug ) ); ?>"><?php echo esc_html( $type->name ); ?></div>
9
+
10
+ <?php endforeach; endif; ?>
11
  <?php } ?>
12
 
13
  <?php if ( $logo = get_the_company_logo() ) : ?>
16
 
17
  <div class="job_summary_content">
18
 
19
+ <h1><?php wpjm_the_job_title(); ?></h1>
20
 
21
  <p class="meta"><?php the_job_location( false ); ?> &mdash; <?php the_job_publish_date(); ?></p>
22
 
templates/content-widget-job_listing.php CHANGED
@@ -1,13 +1,16 @@
1
  <li <?php job_listing_class(); ?>>
2
  <a href="<?php the_job_permalink(); ?>">
3
  <div class="position">
4
- <h3><?php echo esc_html( get_the_title() ); ?></h3>
5
  </div>
6
  <ul class="meta">
7
  <li class="location"><?php the_job_location( false ); ?></li>
8
  <li class="company"><?php the_company_name(); ?></li>
9
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
10
- <li class="job-type <?php echo get_the_job_type() ? sanitize_title( get_the_job_type()->slug ) : ''; ?>"><?php the_job_type(); ?></li>
 
 
 
11
  <?php } ?>
12
  </ul>
13
  </a>
1
  <li <?php job_listing_class(); ?>>
2
  <a href="<?php the_job_permalink(); ?>">
3
  <div class="position">
4
+ <h3><?php wpjm_the_job_title(); ?></h3>
5
  </div>
6
  <ul class="meta">
7
  <li class="location"><?php the_job_location( false ); ?></li>
8
  <li class="company"><?php the_company_name(); ?></li>
9
  <?php if ( get_option( 'job_manager_enable_types' ) ) { ?>
10
+ <?php $types = wpjm_get_the_job_types(); ?>
11
+ <?php if ( ! empty( $types ) ) : foreach ( $types as $type ) : ?>
12
+ <li class="job-type <?php echo esc_attr( sanitize_title( $type->slug ) ); ?>"><?php echo esc_html( $type->name ); ?></li>
13
+ <?php endforeach; endif; ?>
14
  <?php } ?>
15
  </ul>
16
  </a>
templates/form-fields/password-field.php CHANGED
@@ -1,2 +1,2 @@
1
- <input type="password" class="input-text" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo isset( $field['value'] ) ? esc_attr( $field['value'] ) : ''; ?>" maxlength="<?php echo ! empty( $field['maxlength'] ) ? $field['maxlength'] : ''; ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> />
2
- <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
1
+ <input type="password" class="input-text"<?php if ( isset( $field['autocomplete'] ) && false === $field['autocomplete'] ) { echo ' autocomplete="off"'; } ?> name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo isset( $field['value'] ) ? esc_attr( $field['value'] ) : ''; ?>" maxlength="<?php echo ! empty( $field['maxlength'] ) ? $field['maxlength'] : ''; ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> />
2
+ <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
templates/form-fields/text-field.php CHANGED
@@ -1,2 +1,2 @@
1
- <input type="text" class="input-text" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo isset( $field['value'] ) ? esc_attr( $field['value'] ) : ''; ?>" maxlength="<?php echo ! empty( $field['maxlength'] ) ? $field['maxlength'] : ''; ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> />
2
- <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
1
+ <input type="text" class="input-text" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>"<?php if ( isset( $field['autocomplete'] ) && false === $field['autocomplete'] ) { echo ' autocomplete="off"'; } ?> id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo isset( $field['value'] ) ? esc_attr( $field['value'] ) : ''; ?>" maxlength="<?php echo ! empty( $field['maxlength'] ) ? $field['maxlength'] : ''; ?>" <?php if ( ! empty( $field['required'] ) ) echo 'required'; ?> />
2
+ <?php if ( ! empty( $field['description'] ) ) : ?><small class="description"><?php echo $field['description']; ?></small><?php endif; ?>
templates/job-dashboard.php CHANGED
@@ -20,9 +20,9 @@
20
  <td class="<?php echo esc_attr( $key ); ?>">
21
  <?php if ('job_title' === $key ) : ?>
22
  <?php if ( $job->post_status == 'publish' ) : ?>
23
- <a href="<?php echo get_permalink( $job->ID ); ?>"><?php echo esc_html( $job->post_title ); ?></a>
24
  <?php else : ?>
25
- <?php echo esc_html( $job->post_title ); ?> <small>(<?php the_job_status( $job ); ?>)</small>
26
  <?php endif; ?>
27
  <ul class="job-dashboard-actions">
28
  <?php
20
  <td class="<?php echo esc_attr( $key ); ?>">
21
  <?php if ('job_title' === $key ) : ?>
22
  <?php if ( $job->post_status == 'publish' ) : ?>
23
+ <a href="<?php echo get_permalink( $job->ID ); ?>"><?php wpjm_the_job_title( $job ); ?></a>
24
  <?php else : ?>
25
+ <?php wpjm_the_job_title( $job ); ?> <small>(<?php the_job_status( $job ); ?>)</small>
26
  <?php endif; ?>
27
  <ul class="job-dashboard-actions">
28
  <?php
templates/job-preview.php CHANGED
@@ -5,7 +5,7 @@
5
  <h2><?php _e( 'Preview', 'wp-job-manager' ); ?></h2>
6
  </div>
7
  <div class="job_listing_preview single_job_listing">
8
- <h1><?php echo esc_html( get_the_title() ); ?></h1>
9
 
10
  <?php get_job_manager_template_part( 'content-single', 'job_listing' ); ?>
11
 
5
  <h2><?php _e( 'Preview', 'wp-job-manager' ); ?></h2>
6
  </div>
7
  <div class="job_listing_preview single_job_listing">
8
+ <h1><?php wpjm_the_job_title(); ?></h1>
9
 
10
  <?php get_job_manager_template_part( 'content-single', 'job_listing' ); ?>
11
 
wp-job-manager-deprecated.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Deprecated functions. Do not use these.
4
+ */
5
+
6
+ if ( ! function_exists( 'order_featured_job_listing' ) ) :
7
+ /**
8
+ * Was used for sorting.
9
+ *
10
+ * @deprecated 1.22.4
11
+ * @param array $args
12
+ * @return array
13
+ */
14
+ function order_featured_job_listing( $args ) {
15
+ global $wpdb;
16
+ $args['orderby'] = "$wpdb->posts.menu_order ASC, $wpdb->posts.post_date DESC";
17
+ return $args;
18
+ }
19
+ endif;
20
+
21
+
22
+
23
+ if ( ! function_exists( 'the_job_type' ) ) :
24
+ /**
25
+ * Displays the job type for the listing.
26
+ *
27
+ * @since 1.0.0
28
+ * @deprecated 1.27.0 Use `wpjm_the_job_types()` instead.
29
+ *
30
+ * @param int|WP_Post $post
31
+ * @return string
32
+ */
33
+ function the_job_type( $post = null ) {
34
+ _deprecated_function( __FUNCTION__, '1.27.0', 'wpjm_the_job_types' );
35
+
36
+ if ( ! get_option( 'job_manager_enable_types' ) ) {
37
+ return '';
38
+ }
39
+ if ( $job_type = get_the_job_type( $post ) ) {
40
+ echo $job_type->name;
41
+ }
42
+ }
43
+ endif;
44
+
45
+ if ( ! function_exists( 'get_the_job_type' ) ) :
46
+ /**
47
+ * Gets the job type for the listing.
48
+ *
49
+ * @since 1.0.0
50
+ * @deprecated 1.27.0 Use `wpjm_get_the_job_types()` instead.
51
+ *
52
+ * @param int|WP_Post $post (default: null)
53
+ * @return string|bool|null
54
+ */
55
+ function get_the_job_type( $post = null ) {
56
+ _deprecated_function( __FUNCTION__, '1.27.0', 'wpjm_get_the_job_types' );
57
+
58
+ $post = get_post( $post );
59
+ if ( $post->post_type !== 'job_listing' ) {
60
+ return;
61
+ }
62
+
63
+ $types = wp_get_post_terms( $post->ID, 'job_listing_type' );
64
+
65
+ if ( $types ) {
66
+ $type = current( $types );
67
+ } else {
68
+ $type = false;
69
+ }
70
+
71
+ return apply_filters( 'the_job_type', $type, $post );
72
+ }
73
+ endif;
wp-job-manager-functions.php CHANGED
@@ -15,6 +15,7 @@ function get_job_listings( $args = array() ) {
15
  'search_keywords' => '',
16
  'search_categories' => array(),
17
  'job_types' => array(),
 
18
  'offset' => 0,
19
  'posts_per_page' => 20,
20
  'orderby' => 'date',
@@ -33,7 +34,9 @@ function get_job_listings( $args = array() ) {
33
  */
34
  do_action( 'get_job_listings_init', $args );
35
 
36
- if ( false == get_option( 'job_manager_hide_expired', get_option( 'job_manager_hide_expired_content', 1 ) ) ) {
 
 
37
  $post_status = array( 'publish', 'expired' );
38
  } else {
39
  $post_status = 'publish';
@@ -240,21 +243,6 @@ if ( ! function_exists( 'get_job_listings_keyword_search' ) ) :
240
  }
241
  endif;
242
 
243
- if ( ! function_exists( 'order_featured_job_listing' ) ) :
244
- /**
245
- * Was used for sorting.
246
- *
247
- * @deprecated 1.22.4
248
- * @param array $args
249
- * @return array
250
- */
251
- function order_featured_job_listing( $args ) {
252
- global $wpdb;
253
- $args['orderby'] = "$wpdb->posts.menu_order ASC, $wpdb->posts.post_date DESC";
254
- return $args;
255
- }
256
- endif;
257
-
258
  if ( ! function_exists( 'get_job_listing_post_statuses' ) ) :
259
  /**
260
  * Gets post statuses used for jobs.
@@ -417,8 +405,8 @@ if ( ! function_exists( 'wp_job_manager_notify_new_user' ) ) :
417
  * Handles notification of new users.
418
  *
419
  * @since 1.23.10
420
- * @param int $user_id
421
- * @param string $password
422
  */
423
  function wp_job_manager_notify_new_user( $user_id, $password ) {
424
  global $wp_version;
@@ -426,7 +414,11 @@ if ( ! function_exists( 'wp_job_manager_notify_new_user' ) ) :
426
  if ( version_compare( $wp_version, '4.3.1', '<' ) ) {
427
  wp_new_user_notification( $user_id, $password );
428
  } else {
429
- wp_new_user_notification( $user_id, null, 'both' );
 
 
 
 
430
  }
431
  }
432
  endif;
@@ -446,14 +438,14 @@ function wp_job_manager_create_account( $args, $deprecated = '' ) {
446
  // Soft Deprecated in 1.20.0
447
  if ( ! is_array( $args ) ) {
448
  $username = '';
449
- $password = wp_generate_password();
450
  $email = $args;
451
  $role = $deprecated;
452
  } else {
453
  $defaults = array(
454
  'username' => '',
455
  'email' => '',
456
- 'password' => wp_generate_password(),
457
  'role' => get_option( 'default_role' )
458
  );
459
 
@@ -504,9 +496,14 @@ function wp_job_manager_create_account( $args, $deprecated = '' ) {
504
  'user_login' => $username,
505
  'user_pass' => $password,
506
  'user_email' => $email,
507
- 'role' => $role
508
  );
509
 
 
 
 
 
 
510
  $user_id = wp_insert_user( apply_filters( 'job_manager_create_account_data', $new_user ) );
511
 
512
  if ( is_wp_error( $user_id ) ) {
@@ -515,6 +512,7 @@ function wp_job_manager_create_account( $args, $deprecated = '' ) {
515
 
516
  // Notify
517
  wp_job_manager_notify_new_user( $user_id, $password, $new_user );
 
518
  // Login
519
  wp_set_auth_cookie( $user_id, true, is_ssl() );
520
  $current_user = get_user_by( 'id', $user_id );
@@ -523,6 +521,38 @@ function wp_job_manager_create_account( $args, $deprecated = '' ) {
523
  }
524
  endif;
525
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
  /**
527
  * Checks if the user can upload a file via the Ajax endpoint.
528
  *
@@ -582,6 +612,70 @@ function job_manager_user_can_edit_job( $job_id ) {
582
  return apply_filters( 'job_manager_user_can_edit_job', $can_edit, $job_id );
583
  }
584
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
585
  /**
586
  * Checks if only one type allowed per job.
587
  *
15
  'search_keywords' => '',
16
  'search_categories' => array(),
17
  'job_types' => array(),
18
+ 'post_status' => array(),
19
  'offset' => 0,
20
  'posts_per_page' => 20,
21
  'orderby' => 'date',
34
  */
35
  do_action( 'get_job_listings_init', $args );
36
 
37
+ if ( ! empty( $args['post_status'] ) ) {
38
+ $post_status = $args['post_status'];
39
+ } elseif ( false == get_option( 'job_manager_hide_expired', get_option( 'job_manager_hide_expired_content', 1 ) ) ) {
40
  $post_status = array( 'publish', 'expired' );
41
  } else {
42
  $post_status = 'publish';
243
  }
244
  endif;
245
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  if ( ! function_exists( 'get_job_listing_post_statuses' ) ) :
247
  /**
248
  * Gets post statuses used for jobs.
405
  * Handles notification of new users.
406
  *
407
  * @since 1.23.10
408
+ * @param int $user_id
409
+ * @param string|bool $password
410
  */
411
  function wp_job_manager_notify_new_user( $user_id, $password ) {
412
  global $wp_version;
414
  if ( version_compare( $wp_version, '4.3.1', '<' ) ) {
415
  wp_new_user_notification( $user_id, $password );
416
  } else {
417
+ $notify = 'admin';
418
+ if ( empty( $password ) ) {
419
+ $notify = 'both';
420
+ }
421
+ wp_new_user_notification( $user_id, null, $notify );
422
  }
423
  }
424
  endif;
438
  // Soft Deprecated in 1.20.0
439
  if ( ! is_array( $args ) ) {
440
  $username = '';
441
+ $password = false;
442
  $email = $args;
443
  $role = $deprecated;
444
  } else {
445
  $defaults = array(
446
  'username' => '',
447
  'email' => '',
448
+ 'password' => false,
449
  'role' => get_option( 'default_role' )
450
  );
451
 
496
  'user_login' => $username,
497
  'user_pass' => $password,
498
  'user_email' => $email,
499
+ 'role' => $role,
500
  );
501
 
502
+ // User is forced to set up account with email sent to them. This password will remain a secret.
503
+ if ( empty( $new_user['user_pass'] ) ) {
504
+ $new_user['user_pass'] = wp_generate_password();
505
+ }
506
+
507
  $user_id = wp_insert_user( apply_filters( 'job_manager_create_account_data', $new_user ) );
508
 
509
  if ( is_wp_error( $user_id ) ) {
512
 
513
  // Notify
514
  wp_job_manager_notify_new_user( $user_id, $password, $new_user );
515
+
516
  // Login
517
  wp_set_auth_cookie( $user_id, true, is_ssl() );
518
  $current_user = get_user_by( 'id', $user_id );
521
  }
522
  endif;
523
 
524
+
525
+ /**
526
+ * Retrieves permalink settings.
527
+ *
528
+ * @see https://github.com/woocommerce/woocommerce/blob/3.0.8/includes/wc-core-functions.php#L1573
529
+ * @since 2.7.3
530
+ * @return array
531
+ */
532
+ function wpjm_get_permalink_structure() {
533
+ // Switch to the site's default locale, bypassing the active user's locale.
534
+ if ( function_exists( 'switch_to_locale' ) && did_action( 'admin_init' ) ) {
535
+ switch_to_locale( get_locale() );
536
+ }
537
+
538
+ $permalinks = wp_parse_args( (array) get_option( 'wpjm_permalinks', array() ), array(
539
+ 'job_base' => '',
540
+ 'category_base' => '',
541
+ 'type_base' => '',
542
+ ) );
543
+
544
+ // Ensure rewrite slugs are set.
545
+ $permalinks['job_rewrite_slug'] = untrailingslashit( empty( $permalinks['job_base'] ) ? _x( 'job', 'Job permalink - resave permalinks after changing this', 'wp-job-manager' ) : $permalinks['job_base'] );
546
+ $permalinks['category_rewrite_slug'] = untrailingslashit( empty( $permalinks['category_base'] ) ? _x( 'job-category', 'Job category slug - resave permalinks after changing this', 'wp-job-manager' ) : $permalinks['category_base'] );
547
+ $permalinks['type_rewrite_slug'] = untrailingslashit( empty( $permalinks['type_base'] ) ? _x( 'job-type', 'Job type slug - resave permalinks after changing this', 'wp-job-manager' ) : $permalinks['type_base'] );
548
+
549
+ // Restore the original locale.
550
+ if ( function_exists( 'restore_current_locale' ) && did_action( 'admin_init' ) ) {
551
+ restore_current_locale();
552
+ }
553
+ return $permalinks;
554
+ }
555
+
556
  /**
557
  * Checks if the user can upload a file via the Ajax endpoint.
558
  *
612
  return apply_filters( 'job_manager_user_can_edit_job', $can_edit, $job_id );
613
  }
614
 
615
+ /**
616
+ * Checks to see if the standard password setup email should be used.
617
+ *
618
+ * @since 1.27.0
619
+ *
620
+ * @return bool True if they are to use standard email, false to allow user to set password at first job creation.
621
+ */
622
+ function wpjm_use_standard_password_setup_email() {
623
+ $use_standard_password_setup_email = true;
624
+
625
+ // If username is being automatically generated, force them to send password setup email.
626
+ if ( ! job_manager_generate_username_from_email() ) {
627
+ $use_standard_password_setup_email = get_option( 'job_manager_use_standard_password_setup_email' ) == 1 ? true : false;
628
+ }
629
+
630
+ /**
631
+ * Allows an override of the setting for if a password should be auto-generated for new users.
632
+ *
633
+ * @since 1.27.0
634
+ *
635
+ * @param bool $use_standard_password_setup_email True if a standard account setup email should be sent.
636
+ */
637
+ return apply_filters( 'wpjm_use_standard_password_setup_email', $use_standard_password_setup_email );
638
+ }
639
+
640
+ /**
641
+ * Checks if a password should be auto-generated for new users.
642
+ *
643
+ * @since 1.27.0
644
+ *
645
+ * @param string $password Password to validate.
646
+ * @return bool True if password meets rules.
647
+ */
648
+ function wpjm_validate_new_password( $password ) {
649
+ // Password must be at least 8 characters long. Trimming here because `wp_hash_password()` will later on.
650
+ $is_valid_password = strlen( trim ( $password ) ) >= 8;
651
+
652
+ /**
653
+ * Allows overriding default WPJM password validation rules.
654
+ *
655
+ * @since 1.27.0
656
+ *
657
+ * @param bool $is_valid_password True if new password is validated.
658
+ * @param string $password Password to validate.
659
+ */
660
+ return apply_filters( 'wpjm_validate_new_password', $is_valid_password, $password );
661
+ }
662
+
663
+ /**
664
+ * Returns the password rules hint.
665
+ *
666
+ * @return string
667
+ */
668
+ function wpjm_get_password_rules_hint() {
669
+ /**
670
+ * Allows overriding the hint shown below the new password input field. Describes rules set in `wpjm_validate_new_password`.
671
+ *
672
+ * @since 1.27.0
673
+ *
674
+ * @param string $password_rules Password rules description.
675
+ */
676
+ return apply_filters( 'wpjm_password_rules_hint', __( 'Passwords must be at least 8 characters long.', 'wp-job-manager') );
677
+ }
678
+
679
  /**
680
  * Checks if only one type allowed per job.
681
  *
wp-job-manager-template.php CHANGED
@@ -244,46 +244,158 @@ function get_the_job_application_method( $post = null ) {
244
 
245
  return apply_filters( 'the_job_application_method', $method, $post );
246
  }
 
247
  /**
248
- * Displays the job type for the listing.
249
  *
250
- * @since 1.0.0
251
  * @param int|WP_Post $post
252
  * @return string
253
  */
254
- function the_job_type( $post = null ) {
255
- if ( ! get_option( 'job_manager_enable_types' ) ) {
256
- return '';
257
- }
258
- if ( $job_type = get_the_job_type( $post ) ) {
259
- echo $job_type->name;
260
  }
261
  }
262
 
263
  /**
264
- * Gets the job type for the listing.
265
  *
266
- * @since 1.0.0
267
  * @param int|WP_Post $post (default: null)
268
  * @return string|bool|null
269
  */
270
- function get_the_job_type( $post = null ) {
271
  $post = get_post( $post );
272
  if ( $post->post_type !== 'job_listing' ) {
273
  return;
274
  }
275
 
276
- $types = wp_get_post_terms( $post->ID, 'job_listing_type' );
277
 
278
- if ( $types ) {
279
- $type = current( $types );
280
- } else {
281
- $type = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  }
283
 
284
- return apply_filters( 'the_job_type', $type, $post );
 
 
 
 
 
 
285
  }
286
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
 
288
  /**
289
  * Displays the published date of the job listing.
@@ -688,25 +800,50 @@ function job_listing_class( $class = '', $post_id = null ) {
688
  * @return array
689
  */
690
  function get_job_listing_class( $class = '', $post_id = null ) {
691
- if ( ! get_option( 'job_manager_enable_types' ) ) {
692
- return get_post_class( array( 'job_classes' ), $post_id );
693
- }
694
-
695
  $post = get_post( $post_id );
696
 
697
- if ( $post->post_type !== 'job_listing' ) {
698
  return array();
699
  }
700
 
701
  $classes = array();
702
 
703
- if ( empty( $post ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
704
  return $classes;
705
  }
706
 
707
  $classes[] = 'job_listing';
708
- if ( $job_type = get_the_job_type() ) {
709
- $classes[] = 'job-type-' . sanitize_title( $job_type->name );
 
 
 
 
 
 
710
  }
711
 
712
  if ( is_position_filled( $post ) ) {
@@ -717,15 +854,9 @@ function get_job_listing_class( $class = '', $post_id = null ) {
717
  $classes[] = 'job_position_featured';
718
  }
719
 
720
- if ( ! empty( $class ) ) {
721
- if ( ! is_array( $class ) ) {
722
- $class = preg_split( '#\s+#', $class );
723
- }
724
- $classes = array_merge( $classes, $class );
725
- }
726
-
727
- return get_post_class( $classes, $post->ID );
728
  }
 
729
 
730
  /**
731
  * Displays job meta data on the single job page.
244
 
245
  return apply_filters( 'the_job_application_method', $method, $post );
246
  }
247
+
248
  /**
249
+ * Displays the job title for the listing.
250
  *
251
+ * @since 1.27.0
252
  * @param int|WP_Post $post
253
  * @return string
254
  */
255
+ function wpjm_the_job_title( $post = null ) {
256
+ if ( $job_title = wpjm_get_the_job_title( $post ) ) {
257
+ echo $job_title;
 
 
 
258
  }
259
  }
260
 
261
  /**
262
+ * Gets the job title for the listing.
263
  *
264
+ * @since 1.27.0
265
  * @param int|WP_Post $post (default: null)
266
  * @return string|bool|null
267
  */
268
+ function wpjm_get_the_job_title( $post = null ) {
269
  $post = get_post( $post );
270
  if ( $post->post_type !== 'job_listing' ) {
271
  return;
272
  }
273
 
274
+ $title = esc_html( get_the_title( $post ) );
275
 
276
+ /**
277
+ * Filter for the job title.
278
+ *
279
+ * @since 1.27.0
280
+ * @param string $title Title to be filtered.
281
+ * @param int|WP_Post $post
282
+ */
283
+ return apply_filters( 'wpjm_the_job_title', $title, $post );
284
+ }
285
+
286
+ /**
287
+ * Displays multiple job types for the listing.
288
+ *
289
+ * @since 1.27.0
290
+ *
291
+ * @param int|WP_Post $post Current post object.
292
+ * @param string $separator String to join the term names with.
293
+ */
294
+ function wpjm_the_job_types( $post = null, $separator = ', ' ) {
295
+ if ( ! get_option( 'job_manager_enable_types' ) ) {
296
+ return;
297
  }
298
 
299
+ $job_types = wpjm_get_the_job_types( $post );
300
+
301
+ if ( $job_types ) {
302
+ $names = wp_list_pluck( $job_types, 'name' );
303
+
304
+ echo esc_html( implode( $separator, $names ) );
305
+ }
306
  }
307
 
308
+ /**
309
+ * Gets the job type for the listing.
310
+ *
311
+ * @since 1.27.0
312
+ *
313
+ * @param int|WP_Post $post (default: null).
314
+ * @return bool|array
315
+ */
316
+ function wpjm_get_the_job_types( $post = null ) {
317
+ $post = get_post( $post );
318
+
319
+ if ( 'job_listing' !== $post->post_type ) {
320
+ return false;
321
+ }
322
+
323
+ $types = get_the_terms( $post->ID, 'job_listing_type' );
324
+
325
+ // Return single if not enabled.
326
+ if ( ! empty( $types ) && ! job_manager_multi_job_type() ) {
327
+ $types = array( current( $types ) );
328
+ }
329
+
330
+ /**
331
+ * Filter the returned job types for a post.
332
+ *
333
+ * @since 1.27.0
334
+ *
335
+ * @param array $types
336
+ * @param WP_Post $post
337
+ */
338
+ return apply_filters( 'wpjm_the_job_types', $types, $post );
339
+ }
340
+
341
+ /**
342
+ * Returns the registration fields used when an account is required.
343
+ *
344
+ * @since 1.27.0
345
+ *
346
+ * @return array $registration_fields
347
+ */
348
+ function wpjm_get_registration_fields() {
349
+ $generate_username_from_email = job_manager_generate_username_from_email();
350
+ $use_standard_password_setup_email = wpjm_use_standard_password_setup_email();
351
+ $account_required = job_manager_user_requires_account();
352
+
353
+ $registration_fields = array();
354
+ if ( job_manager_enable_registration() ) {
355
+ if ( ! $generate_username_from_email ) {
356
+ $registration_fields['create_account_username'] = array(
357
+ 'type' => 'text',
358
+ 'label' => __( 'Username', 'wp-job-manager' ),
359
+ 'required' => $account_required,
360
+ 'value' => isset( $_POST['create_account_username'] ) ? $_POST['create_account_username'] : '',
361
+ );
362
+ }
363
+ if ( ! $use_standard_password_setup_email ) {
364
+ $registration_fields['create_account_password'] = array(
365
+ 'type' => 'password',
366
+ 'label' => __( 'Password', 'wp-job-manager' ),
367
+ 'autocomplete' => false,
368
+ 'required' => $account_required,
369
+ );
370
+ $password_hint = wpjm_get_password_rules_hint();
371
+ if ( $password_hint ) {
372
+ $registration_fields['create_account_password']['description'] = $password_hint;
373
+ }
374
+ $registration_fields['create_account_password_verify'] = array(
375
+ 'type' => 'password',
376
+ 'label' => __( 'Verify Password', 'wp-job-manager' ),
377
+ 'autocomplete' => false,
378
+ 'required' => $account_required,
379
+ );
380
+ }
381
+ $registration_fields['create_account_email'] = array(
382
+ 'type' => 'text',
383
+ 'label' => __( 'Your email', 'wp-job-manager' ),
384
+ 'placeholder' => __( 'you@yourdomain.com', 'wp-job-manager' ),
385
+ 'required' => $account_required,
386
+ 'value' => isset( $_POST['create_account_email'] ) ? $_POST['create_account_email'] : '',
387
+ );
388
+ }
389
+
390
+ /**
391
+ * Filters the fields used at registration.
392
+ *
393
+ * @since 1.27.0
394
+ *
395
+ * @param array $registration_fields
396
+ */
397
+ return apply_filters( 'wpjm_get_registration_fields', $registration_fields );
398
+ }
399
 
400
  /**
401
  * Displays the published date of the job listing.
800
  * @return array
801
  */
802
  function get_job_listing_class( $class = '', $post_id = null ) {
 
 
 
 
803
  $post = get_post( $post_id );
804
 
805
+ if ( empty( $post ) || 'job_listing' !== $post->post_type ) {
806
  return array();
807
  }
808
 
809
  $classes = array();
810
 
811
+ if ( ! empty( $class ) ) {
812
+ if ( ! is_array( $class ) ) {
813
+ $class = preg_split( '#\s+#', $class );
814
+ }
815
+ $classes = array_merge( $classes, $class );
816
+ }
817
+
818
+ return get_post_class( $classes, $post->ID );
819
+ }
820
+
821
+ /**
822
+ * Adds post classes with meta info and the status of the job listing.
823
+ *
824
+ * @since 1.27.0
825
+ *
826
+ * @param array $classes An array of post classes.
827
+ * @param array $class An array of additional classes added to the post.
828
+ * @param int $post_id The post ID.
829
+ * @return array
830
+ */
831
+ function wpjm_add_post_class( $classes, $class, $post_id ) {
832
+ $post = get_post( $post_id );
833
+
834
+ if ( empty( $post ) || 'job_listing' !== $post->post_type ) {
835
  return $classes;
836
  }
837
 
838
  $classes[] = 'job_listing';
839
+
840
+ if ( get_option( 'job_manager_enable_types' ) ) {
841
+ $job_types = wpjm_get_the_job_types( $post );
842
+ if ( ! empty( $job_types ) ) {
843
+ foreach ( $job_types as $job_type ) {
844
+ $classes[] = 'job-type-' . sanitize_title( $job_type->name );
845
+ }
846
+ }
847
  }
848
 
849
  if ( is_position_filled( $post ) ) {
854
  $classes[] = 'job_position_featured';
855
  }
856
 
857
+ return $classes;
 
 
 
 
 
 
 
858
  }
859
+ add_action( 'post_class', 'wpjm_add_post_class', 10, 3 );
860
 
861
  /**
862
  * Displays job meta data on the single job page.
wp-job-manager.php CHANGED
@@ -3,7 +3,7 @@
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.26.2
7
  * Author: Automattic
8
  * Author URI: https://wpjobmanager.com/
9
  * Requires at least: 4.1
@@ -27,7 +27,7 @@ class WP_Job_Manager {
27
  * The single instance of the class.
28
  *
29
  * @var self
30
- * @since 1.26
31
  */
32
  private static $_instance = null;
33
 
@@ -36,7 +36,7 @@ class WP_Job_Manager {
36
  *
37
  * Ensures only one instance of WP Job Manager is loaded or can be loaded.
38
  *
39
- * @since 1.26
40
  * @static
41
  * @see WPJM()
42
  * @return self Main instance.
@@ -53,31 +53,36 @@ class WP_Job_Manager {
53
  */
54
  public function __construct() {
55
  // Define constants
56
- define( 'JOB_MANAGER_VERSION', '1.26.2' );
57
  define( 'JOB_MANAGER_PLUGIN_DIR', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
58
  define( 'JOB_MANAGER_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
59
 
60
  // Includes
61
- include( 'includes/class-wp-job-manager-install.php' );
62
- include( 'includes/class-wp-job-manager-post-types.php' );
63
- include( 'includes/class-wp-job-manager-ajax.php' );
64
- include( 'includes/class-wp-job-manager-shortcodes.php' );
65
- include( 'includes/class-wp-job-manager-api.php' );
66
- include( 'includes/class-wp-job-manager-forms.php' );
67
- include( 'includes/class-wp-job-manager-geocode.php' );
68
- include( 'includes/class-wp-job-manager-cache-helper.php' );
 
 
69
 
70
  if ( is_admin() ) {
71
- include( 'includes/admin/class-wp-job-manager-admin.php' );
72
  }
73
 
74
  // Load 3rd party customizations
75
- require_once( 'includes/3rd-party/3rd-party.php' );
76
 
77
  // Init classes
78
  $this->forms = WP_Job_Manager_Forms::instance();
79
  $this->post_types = WP_Job_Manager_Post_Types::instance();
80
 
 
 
 
81
  // Activation - works with symlinks
82
  register_activation_hook( basename( dirname( __FILE__ ) ) . '/' . basename( __FILE__ ), array( $this, 'activate' ) );
83
 
@@ -92,6 +97,7 @@ class WP_Job_Manager {
92
  add_action( 'widgets_init', array( $this, 'widgets_init' ) );
93
  add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
94
  add_action( 'admin_init', array( $this, 'updater' ) );
 
95
  }
96
 
97
  /**
@@ -123,11 +129,10 @@ class WP_Job_Manager {
123
  }
124
 
125
  /**
126
- * Loads plugin's core helper functions.
127
  */
128
  public function include_template_functions() {
129
- include( 'wp-job-manager-functions.php' );
130
- include( 'wp-job-manager-template.php' );
131
  }
132
 
133
  /**
@@ -139,6 +144,33 @@ class WP_Job_Manager {
139
  include_once( 'includes/widgets/class-wp-job-manager-widget-featured-jobs.php' );
140
  }
141
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  /**
143
  * Registers and enqueues scripts and CSS.
144
  */
3
  * Plugin Name: WP Job Manager
4
  * Plugin URI: https://wpjobmanager.com/
5
  * Description: Manage job listings from the WordPress admin panel, and allow users to post jobs directly to your site.
6
+ * Version: 1.27.0
7
  * Author: Automattic
8
  * Author URI: https://wpjobmanager.com/
9
  * Requires at least: 4.1
27
  * The single instance of the class.
28
  *
29
  * @var self
30
+ * @since 1.26.0
31
  */
32
  private static $_instance = null;
33
 
36
  *
37
  * Ensures only one instance of WP Job Manager is loaded or can be loaded.
38
  *
39
+ * @since 1.26.0
40
  * @static
41
  * @see WPJM()
42
  * @return self Main instance.
53
  */
54
  public function __construct() {
55
  // Define constants
56
+ define( 'JOB_MANAGER_VERSION', '1.27.0' );
57
  define( 'JOB_MANAGER_PLUGIN_DIR', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
58
  define( 'JOB_MANAGER_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
59
 
60
  // Includes
61
+ include_once( 'wp-job-manager-functions.php' );
62
+ include_once( 'wp-job-manager-deprecated.php' );
63
+ include_once( 'includes/class-wp-job-manager-install.php' );
64
+ include_once( 'includes/class-wp-job-manager-post-types.php' );
65
+ include_once( 'includes/class-wp-job-manager-ajax.php' );
66
+ include_once( 'includes/class-wp-job-manager-shortcodes.php' );
67
+ include_once( 'includes/class-wp-job-manager-api.php' );
68
+ include_once( 'includes/class-wp-job-manager-forms.php' );
69
+ include_once( 'includes/class-wp-job-manager-geocode.php' );
70
+ include_once( 'includes/class-wp-job-manager-cache-helper.php' );
71
 
72
  if ( is_admin() ) {
73
+ include_once( 'includes/admin/class-wp-job-manager-admin.php' );
74
  }
75
 
76
  // Load 3rd party customizations
77
+ include_once( 'includes/3rd-party/3rd-party.php' );
78
 
79
  // Init classes
80
  $this->forms = WP_Job_Manager_Forms::instance();
81
  $this->post_types = WP_Job_Manager_Post_Types::instance();
82
 
83
+ // Schedule cron jobs
84
+ self::maybe_schedule_cron_jobs();
85
+
86
  // Activation - works with symlinks
87
  register_activation_hook( basename( dirname( __FILE__ ) ) . '/' . basename( __FILE__ ), array( $this, 'activate' ) );
88
 
97
  add_action( 'widgets_init', array( $this, 'widgets_init' ) );
98
  add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
99
  add_action( 'admin_init', array( $this, 'updater' ) );
100
+ add_action( 'wp_logout', array( $this, 'cleanup_job_posting_cookies' ) );
101
  }
102
 
103
  /**
129
  }
130
 
131
  /**
132
+ * Loads plugin's core helper template functions.
133
  */
134
  public function include_template_functions() {
135
+ include_once( 'wp-job-manager-template.php' );
 
136
  }
137
 
138
  /**
144
  include_once( 'includes/widgets/class-wp-job-manager-widget-featured-jobs.php' );
145
  }
146
 
147
+ /**
148
+ * Schedule cron jobs for WPJM events.
149
+ */
150
+ public static function maybe_schedule_cron_jobs() {
151
+ if ( ! wp_next_scheduled( 'job_manager_check_for_expired_jobs' ) ) {
152
+ wp_schedule_event( time(), 'hourly', 'job_manager_check_for_expired_jobs' );
153
+ }
154
+ if ( ! wp_next_scheduled( 'job_manager_delete_old_previews' ) ) {
155
+ wp_schedule_event( time(), 'daily', 'job_manager_delete_old_previews' );
156
+ }
157
+ if ( ! wp_next_scheduled( 'job_manager_clear_expired_transients' ) ) {
158
+ wp_schedule_event( time(), 'twicedaily', 'job_manager_clear_expired_transients' );
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Cleanup job posting cookies.
164
+ */
165
+ public function cleanup_job_posting_cookies() {
166
+ if ( isset( $_COOKIE['wp-job-manager-submitting-job-id'] ) ) {
167
+ setcookie( 'wp-job-manager-submitting-job-id', '', 0, COOKIEPATH, COOKIE_DOMAIN, false );
168
+ }
169
+ if ( isset( $_COOKIE['wp-job-manager-submitting-job-key'] ) ) {
170
+ setcookie( 'wp-job-manager-submitting-job-key', '', 0, COOKIEPATH, COOKIE_DOMAIN, false );
171
+ }
172
+ }
173
+
174
  /**
175
  * Registers and enqueues scripts and CSS.
176
  */
wpml-config.xml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <wpml-config>
2
+ <custom-fields>
3
+ <custom-field action="copy">_job_expires</custom-field>
4
+ <custom-field action="copy">_job_duration</custom-field>
5
+ <custom-field action="copy">_filled</custom-field>
6
+ </custom-fields>
7
+ </wpml-config>