Version Description
Download this release
Release Info
Developer | jakeom |
Plugin | WP Job Manager |
Version | 1.26.2.1 |
Comparing to | |
See all releases |
Code changes from version 1.31.2 to 1.26.2.1
- assets/css/admin.css +1 -1
- assets/css/admin.less +544 -0
- assets/css/chosen.css +1 -1
- assets/css/chosen.less +435 -0
- assets/css/frontend.css +1 -1
- assets/css/frontend.less +958 -0
- assets/css/icons.less +40 -0
- assets/css/job-listings.css +0 -1
- assets/css/job-submission.css +11 -1
- assets/css/job-submission.less +14 -0
- assets/css/menu.less +17 -0
- assets/css/mixins.less +105 -0
- assets/css/setup.less +93 -0
- assets/js/admin.js +108 -0
- assets/js/admin.min.js +1 -1
- assets/js/ajax-file-upload.js +90 -0
- assets/js/ajax-file-upload.min.js +1 -1
- assets/js/ajax-filters.js +290 -0
- assets/js/ajax-filters.min.js +1 -1
- assets/js/datepicker.min.js +0 -1
- assets/js/job-application.js +7 -0
- assets/js/job-application.min.js +1 -1
- assets/js/job-dashboard.js +8 -0
- assets/js/job-dashboard.min.js +1 -1
- assets/js/job-submission.js +6 -0
- assets/js/job-submission.min.js +1 -1
- assets/js/jquery-chosen/chosen.jquery.js +1229 -0
- assets/js/jquery-tiptip/jquery.tipTip.js +191 -0
- assets/js/jquery-tiptip/jquery.tipTip.min.js +1 -1
- assets/js/multiselect.js +4 -0
- assets/js/term-multiselect.js +4 -0
- changelog.txt +42 -165
- includes/3rd-party/3rd-party.php +2 -7
- includes/3rd-party/all-in-one-seo-pack.php +0 -25
- includes/3rd-party/jetpack.php +0 -38
- includes/3rd-party/polylang.php +2 -21
- includes/3rd-party/rp4wp.php +0 -56
- includes/3rd-party/wp-all-import.php +0 -25
- includes/3rd-party/wpml.php +0 -54
- includes/3rd-party/yoast.php +0 -29
- includes/abstracts/abstract-wp-job-manager-email-template.php +0 -133
- includes/abstracts/abstract-wp-job-manager-email.php +0 -231
- includes/abstracts/abstract-wp-job-manager-form.php +32 -168
- includes/admin/class-wp-job-manager-addons.php +44 -100
- includes/admin/class-wp-job-manager-admin.php +23 -97
- includes/admin/class-wp-job-manager-cpt-legacy.php +0 -91
- includes/admin/class-wp-job-manager-cpt.php +230 -494
- includes/admin/class-wp-job-manager-permalink-settings.php +0 -135
- includes/admin/class-wp-job-manager-settings.php +219 -638
- includes/admin/class-wp-job-manager-setup.php +72 -173
- includes/admin/class-wp-job-manager-taxonomy-meta.php +0 -158
- includes/admin/class-wp-job-manager-writepanels.php +135 -295
- includes/admin/views/html-admin-page-addons.php +0 -72
- includes/class-wp-job-manager-ajax.php +59 -63
- includes/class-wp-job-manager-api.php +8 -8
- includes/class-wp-job-manager-cache-helper.php +4 -117
- includes/class-wp-job-manager-category-walker.php +10 -24
- includes/class-wp-job-manager-data-cleaner.php +0 -367
- includes/class-wp-job-manager-data-exporter.php +0 -89
- includes/class-wp-job-manager-email-notifications.php +0 -827
- includes/class-wp-job-manager-forms.php +10 -11
- includes/class-wp-job-manager-geocode.php +52 -53
- includes/class-wp-job-manager-install.php +53 -91
- includes/class-wp-job-manager-post-types.php +281 -381
- includes/class-wp-job-manager-shortcodes.php +233 -294
- includes/class-wp-job-manager-usage-tracking-data.php +0 -315
- includes/class-wp-job-manager-usage-tracking.php +0 -219
- includes/class-wp-job-manager-widget.php +9 -46
- includes/emails/class-wp-job-manager-email-admin-expiring-job.php +0 -52
- includes/emails/class-wp-job-manager-email-admin-new-job.php +0 -91
- includes/emails/class-wp-job-manager-email-admin-updated-job.php +0 -91
- includes/emails/class-wp-job-manager-email-employer-expiring-job.php +0 -159
- includes/forms/class-wp-job-manager-form-edit-job.php +35 -120
- includes/forms/class-wp-job-manager-form-submit-job.php +249 -342
- includes/helper/class-wp-job-manager-helper-api.php +0 -176
- includes/helper/class-wp-job-manager-helper-options.php +0 -115
- includes/helper/class-wp-job-manager-helper.php +0 -609
- includes/helper/views/html-licence-key-error.php +0 -9
- includes/helper/views/html-licence-key-notice.php +0 -9
- includes/helper/views/html-licences.php +0 -81
- includes/rest-api/class-wp-job-manager-controllers-status.php +0 -132
- includes/rest-api/class-wp-job-manager-data-stores-status.php +0 -72
- includes/rest-api/class-wp-job-manager-filters-status.php +0 -46
- includes/rest-api/class-wp-job-manager-models-job-categories-custom-fields.php +0 -26
- includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php +0 -104
- includes/rest-api/class-wp-job-manager-models-job-types-custom-fields.php +0 -64
- includes/rest-api/class-wp-job-manager-models-settings.php +0 -109
- includes/rest-api/class-wp-job-manager-models-status.php +0 -50
- includes/rest-api/class-wp-job-manager-registrable-job-categories.php +0 -42
- includes/rest-api/class-wp-job-manager-registrable-job-listings.php +0 -238
- includes/rest-api/class-wp-job-manager-registrable-job-types.php +0 -42
- includes/rest-api/class-wp-job-manager-registrable-taxonomy-type.php +0 -239
- includes/rest-api/class-wp-job-manager-rest-api.php +0 -128
- includes/widgets/class-wp-job-manager-widget-featured-jobs.php +20 -57
- includes/widgets/class-wp-job-manager-widget-recent-jobs.php +24 -67
- languages/wp-job-manager.pot +592 -1364
- lib/emogrifier/class-emogrifier.php +0 -1557
- lib/usage-tracking/class-usage-tracking-base.php +0 -581
- lib/usage-tracking/tests/support/class-usage-tracking-test-subclass.php +0 -67
- lib/usage-tracking/tests/support/wp-die-exception.php +0 -18
- lib/usage-tracking/tests/test-class-usage-tracking.php +0 -527
- lib/wpjm_rest/class-wp-job-manager-rest-bootstrap.php +0 -196
- lib/wpjm_rest/class-wp-job-manager-rest-classloader.php +0 -145
- lib/wpjm_rest/class-wp-job-manager-rest-controller.php +0 -285
- lib/wpjm_rest/class-wp-job-manager-rest-environment.php +0 -426
- lib/wpjm_rest/class-wp-job-manager-rest-events.php +0 -144
- lib/wpjm_rest/class-wp-job-manager-rest-exception.php +0 -17
- lib/wpjm_rest/class-wp-job-manager-rest-expect.php +0 -77
- lib/wpjm_rest/class-wp-job-manager-rest-model.php +0 -686
- lib/wpjm_rest/class-wp-job-manager-rest-type.php +0 -90
- lib/wpjm_rest/controller/bundle/class-wp-job-manager-rest-controller-bundle-builder.php +0 -98
- lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-action.php +0 -166
- lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-bundle.php +0 -99
- lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-crud.php +0 -199
- lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-extension.php +0 -83
- lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-model.php +0 -165
- lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-route.php +0 -90
- lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-settings.php +0 -86
- lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-abstract.php +0 -72
- lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-customposttype.php +0 -0
assets/css/admin.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
.clearfix{zoom:1}.clearfix:after,.clearfix:before{content:"";display:table}.clearfix:after{clear:both}@font-face{font-family:job-manager;src:url(../font/job-manager.eot?4963673);src:url(../font/job-manager.eot?4963673#iefix) format('embedded-opentype'),url(../font/job-manager.woff?4963673) format('woff'),url(../font/job-manager.ttf?4963673) format('truetype'),url(../font/job-manager.svg?4963673#job-manager) format('svg');font-weight:400;font-style:normal}@font-face{font-family:jm-logo;src:url(../font/jm-logo/jm.eot?ycsbky);src:url(../font/jm-logo/jm.eot?#iefixycsbky) format('embedded-opentype'),url(../font/jm-logo/jm.woff?ycsbky) format('woff'),url(../font/jm-logo/jm.ttf?ycsbky) format('truetype'),url(../font/jm-logo/jm.svg?ycsbky#icomoon) format('svg');font-weight:400;font-style:normal}.jm-icon{font-family:job-manager!important;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;text-align:center;font-variant:normal;text-transform:none;line-height:1em}.job-manager-settings-wrap .updated{display:none}.job-manager-settings-wrap .job-manager-updated{display:block;margin:1em 0 0}a.wpjm-activate-licence-link,a.wpjm-activate-licence-link:active,a.wpjm-activate-licence-link:hover,a.wpjm-activate-licence-link:link,a.wpjm-activate-licence-link:visited{color:#ff4500}.wpjm-licences{margin-top:10px}.wpjm-licences .licence-row{align-items:center;border:solid 1px #e2e0e2;display:flex;background-color:#fff;flex-wrap:wrap;min-height:82px;margin-bottom:20px;position:relative}.wpjm-licences .plugin-info{font-size:18px;flex-basis:320px;padding:0 20px;margin-right:10px}.wpjm-licences .plugin-info .plugin-author{font-size:12px}.wpjm-licences .plugin-licence{flex:1;flex-basis:40%;padding-bottom:5px}.wpjm-licences .plugin-licence label{white-space:nowrap}.widefat td.column-featured_job,.widefat td.column-filled,.widefat td.column-job_status{width:46px;text-align:left;padding-left:11px}.widefat th.column-featured_job,.widefat th.column-filled,.widefat th.column-job_status{width:1em}.widefat th.column-featured_job span,.widefat th.column-filled span,.widefat th.column-job_status span{display:block;width:1em;height:1em;line-height:1em;padding:1px 0 0 0;overflow:hidden}.widefat th.column-featured_job span:before,.widefat th.column-filled span:before,.widefat th.column-job_status span:before{content:'\e803';font-family:job-manager!important;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;text-align:center;font-variant:normal;text-transform:none;line-height:1em}.widefat th.column-filled span:before{content:'\e807'}.widefat th.column-job_status span:before{content:'\e828'}.widefat .column-job_posted strong{display:block;margin-bottom:.2em}.widefat td.column-job_status span{position:relative;font-size:1em;line-height:1.5em;width:1em;height:0;padding:2em 0 0 0;overflow:hidden;display:block}.widefat td.column-job_status span:before{font-family:job-manager!important;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;position:absolute;top:0;left:0;line-height:1.5em;vertical-align:middle;color:#999;content:'\e829'}.widefat td.column-job_status .status-trash:before{content:'\e82b';color:#a00}.widefat td.column-job_status .status-pending:before{content:'\e82c';color:#ffba00}.widefat td.column-job_status .status-publish:before{content:'\e82f';color:#73a724}.widefat td.column-job_status .status-expired:before{content:'\e82e';color:#a00}.widefat .column-job_listing_type{text-align:left;width:6em;word-wrap:normal!important}.widefat .column-job_listing_type .job-type{color:#fff;padding:4px;font-size:11px;-webkit-border-radius:2px;border-radius:2px;display:block;background-color:#f08d3c;text-align:center}.widefat .column-job_listing_type .full-time{background-color:#90da36}.widefat .column-job_listing_type .part-time{background-color:#f08d3c}.widefat .column-job_listing_type .temporary{background-color:#d93674}.widefat .column-job_listing_type .freelance{background-color:#39c}.widefat .column-job_listing_type .internship{background-color:#6033cc}.widefat th.column-job_position{width:20%}.widefat td.column-job_position{width:20%;height:34px}.widefat td.column-job_position .job_position{position:relative;padding-right:50px!important}.widefat td.column-job_position a.job_title{font-weight:700}.widefat td.column-job_position img{width:32px;height:32px;position:absolute;right:7px;top:0;-webkit-border-radius:50%;border-radius:50%;box-shadow:0 1px 0 1px rgba(0,0,0,.1);-webkit-box-shadow:0 1px 0 1px rgba(0,0,0,.1);-moz-box-shadow:0 1px 0 1px rgba(0,0,0,.1);border:1px solid #fff}.widefat td.column-job_position .company{margin-top:.2em;display:block;padding-top:2px;color:#bbb}.widefat .column-job_location{width:10%}.widefat .column-job_actions{text-align:right;width:128px}.widefat .column-job_actions strong{display:block;margin-bottom:.2em}.widefat .column-job_actions .actions{padding-top:2px}.widefat .column-job_actions a.button{display:inline-block;margin:0 0 2px 4px;cursor:pointer;padding:0 6px!important;font-size:1em!important;line-height:2em!important;overflow:hidden}.widefat .column-job_actions a.button-icon{width:2em!important;padding:0!important}.widefat .column-job_actions a.button-icon:before{font-family:job-manager!important;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;float:left;width:2em!important;line-height:2em}.widefat .column-job_actions .icon-view:before{content:'\e805'}.widefat .column-job_actions .icon-edit:before{content:'\e804'}.widefat .column-job_actions .icon-delete:before{content:'\e82b'}.widefat .column-job_actions .icon-approve:before{content:'\e802'}.wp_job_manager_meta_data{zoom:1}.wp_job_manager_meta_data:after,.wp_job_manager_meta_data:before{content:"";display:table}.wp_job_manager_meta_data:after{clear:both}.wp_job_manager_meta_data .form-field{width:50%;line-height:2em;float:left;box-sizing:border-box;padding:0 12px 0 0;margin:0 0 12px;clear:both}.wp_job_manager_meta_data .form-field:nth-child(even){float:right;padding:0 0 0 12px;clear:right}.wp_job_manager_meta_data .form-field:nth-last-child(-n+2){margin-bottom:0;padding-bottom:0;border-bottom:0}.wp_job_manager_meta_data .form-field label{vertical-align:middle;display:block;font-weight:700;margin:0}.wp_job_manager_meta_data .form-field .tips{cursor:help;float:right;font-weight:400;color:#999}.wp_job_manager_meta_data .form-field input{width:100%;margin:1px 0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;vertical-align:middle}.wp_job_manager_meta_data .form-field input.checkbox,.wp_job_manager_meta_data .form-field input.radio{width:auto;margin:4px 2px;display:inline-block}.wp_job_manager_meta_data .form-field .description{display:block;color:#999}.wp_job_manager_meta_data .form-field.form-field-checkbox .description{display:inline}.wp_job_manager_meta_data .form-field .file_url input{width:75%}.wp_job_manager_meta_data .form-field .button{margin-left:4px}.wp_job_manager_meta_data .form-field .file_no_url{-o-animation:flash .3s linear infinite alternate;-webkit-animation:flash .3s linear infinite alternate;-moz-animation:flash .3s linear infinite alternate;animation:flash .3s linear infinite alternate}@-o-keyframes flash{from{background-color:unset}to{background-color:#dc3232}}@-ms-keyframes flash{from{background-color:unset}to{background-color:#dc3232}}@-moz-keyframes flash{from{background-color:unset}to{background-color:#dc3232}}@-webkit-keyframes flash{from{background-color:unset}to{background-color:#dc3232}}@keyframes flash{from{background-color:unset}to{background-color:#dc3232}}#tiptip_holder{display:none;position:absolute;top:0;left:0;z-index:99999}#tiptip_holder.tip_top{padding-bottom:5px}#tiptip_holder.tip_bottom{padding-top:5px}#tiptip_holder.tip_right{padding-left:5px}#tiptip_holder.tip_left{padding-right:5px}#tiptip_content{font-size:11px;color:#fff;padding:4px 8px;background:#464646;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;box-shadow:1px 1px 3px rgba(0,0,0,.1);-webkit-box-shadow:1px 1px 3px rgba(0,0,0,.1);-moz-box-shadow:1px 1px 3px rgba(0,0,0,.1);text-align:center}#tiptip_content code{background:#999;padding:1px}#tiptip_arrow,#tiptip_arrow_inner{position:absolute;border-color:transparent;border-style:solid;border-width:6px;height:0;width:0}#tiptip_holder.tip_top #tiptip_arrow_inner{margin-top:-7px;margin-left:-6px;border-top-color:#464646}#tiptip_holder.tip_bottom #tiptip_arrow_inner{margin-top:-5px;margin-left:-6px;border-bottom-color:#464646}#tiptip_holder.tip_right #tiptip_arrow_inner{margin-top:-6px;margin-left:-5px;border-right-color:#464646}#tiptip_holder.tip_left #tiptip_arrow_inner{margin-top:-6px;margin-left:-7px;border-left-color:#464646}.wp_job_manager_add_ons_wrap .products{overflow:hidden}.wp_job_manager_add_ons_wrap .products li{float:left;margin:0 1em 1em 0!important;padding:0;vertical-align:top;width:350px}.wp_job_manager_add_ons_wrap .products li a{text-decoration:none;color:inherit;border:1px solid #ddd;display:block;min-height:220px;overflow:hidden;background:#f6f6f6;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),inset 0 -1px 0 rgba(0,0,0,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),inset 0 -1px 0 rgba(0,0,0,.1)}.wp_job_manager_add_ons_wrap .products li img{display:inline-block;width:auto;max-height:60px;max-width:90px;margin:0 5px 0 0;float:left}.wp_job_manager_add_ons_wrap .products li h2{margin:0!important;padding:20px!important;background:#fff;height:20px;font-size:16px}.wp_job_manager_add_ons_wrap .products li p{padding:20px!important;margin:0!important;border-top:1px solid #f1f1f1}.wp_job_manager_add_ons_wrap .products li .price{display:none}.rtl .widefat .column-job_actions a.button-icon:before{float:right}.rtl .wp_job_manager_meta_data p{padding:0 20% 0 0}.rtl .wp_job_manager_meta_data label{left:auto;right:0}table.form-table.settings tr{border-bottom:1px solid rgba(0,0,0,.1)}table.form-table.settings tr.no-separator,table.form-table.settings tr:last-child{border-bottom:0}div.setting-enable-expand{border:1px solid rgba(0,0,0,.1);padding:15px 10px}div.setting-enable-expand .sub-settings-expandable{display:none;padding-left:25px}div.setting-enable-expand .sub-settings-expandable.expanded{display:block}tr.email-setting-row td{padding:5px}@media only screen and (max-width:782px){.wpjm-licences .plugin-info{padding:10px}.wpjm-licences .plugin-licence{padding:10px}.widefat .job_position.column-primary{display:table-cell!important}.widefat .toggle-row:before{top:5px}.widefat .column-job_actions{text-align:left}.widefat .column-job_actions a.button-icon:before{float:left}.rtl .widefat .column-job_actions{text-align:right}.rtl .widefat .column-job_actions a.button-icon:before{float:right}.wp_job_manager_meta_data .form-field{width:100%;padding:0}.wp_job_manager_meta_data .form-field:nth-child(even){float:none;padding:0;margin-bottom:12px;clear:both}.wp_job_manager_meta_data .form-field:nth-last-child(-n+2){float:none;padding:0;margin-bottom:12px;clear:both}}
|
1 |
+
.clearfix{zoom:1}.clearfix:after,.clearfix:before{content:"";display:table}.clearfix:after{clear:both}@font-face{font-family:job-manager;src:url(../font/job-manager.eot?4963673);src:url(../font/job-manager.eot?4963673#iefix) format('embedded-opentype'),url(../font/job-manager.woff?4963673) format('woff'),url(../font/job-manager.ttf?4963673) format('truetype'),url(../font/job-manager.svg?4963673#job-manager) format('svg');font-weight:400;font-style:normal}@font-face{font-family:jm-logo;src:url(../font/jm-logo/jm.eot?ycsbky);src:url(../font/jm-logo/jm.eot?#iefixycsbky) format('embedded-opentype'),url(../font/jm-logo/jm.woff?ycsbky) format('woff'),url(../font/jm-logo/jm.ttf?ycsbky) format('truetype'),url(../font/jm-logo/jm.svg?ycsbky#icomoon) format('svg');font-weight:400;font-style:normal}.jm-icon{font-family:job-manager!important;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;text-align:center;font-variant:normal;text-transform:none;line-height:1em}.job-manager-settings-wrap .updated{display:none}.job-manager-settings-wrap .job-manager-updated{display:block;margin:1em 0 0}.widefat td.column-featured_job,.widefat td.column-filled,.widefat td.column-job_status{width:46px;text-align:left;padding-left:11px}.widefat th.column-featured_job,.widefat th.column-filled,.widefat th.column-job_status{width:1em}.widefat th.column-featured_job span,.widefat th.column-filled span,.widefat th.column-job_status span{display:block;width:1em;height:1em;line-height:1em;padding:1px 0 0;overflow:hidden}.widefat th.column-featured_job span:before,.widefat th.column-filled span:before,.widefat th.column-job_status span:before{content:'\e803';font-family:job-manager!important;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;text-align:center;font-variant:normal;text-transform:none;line-height:1em}.widefat th.column-filled span:before{content:'\e807'}.widefat th.column-job_status span:before{content:'\e828'}.widefat .column-job_posted strong{display:block;margin-bottom:.2em}.widefat td.column-job_status span{position:relative;font-size:1em;line-height:1.5em;width:1em;height:0;padding:2em 0 0;overflow:hidden;display:block}.widefat td.column-job_status span:before{font-family:job-manager!important;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;text-align:center;font-variant:normal;text-transform:none;position:absolute;top:0;left:0;line-height:1.5em;vertical-align:middle;color:#999;content:'\e829'}.widefat td.column-job_status .status-trash:before{content:'\e82b';color:#a00}.widefat td.column-job_status .status-pending:before{content:'\e82c';color:#ffba00}.widefat td.column-job_status .status-publish:before{content:'\e82f';color:#73a724}.widefat td.column-job_status .status-expired:before{content:'\e82e';color:#a00}.widefat .column-job_listing_type{text-align:left;width:6em;word-wrap:normal!important}.widefat .column-job_listing_type .job-type{color:#fff;padding:4px;font-size:11px;-webkit-border-radius:2px;border-radius:2px;display:block;background-color:#f08d3c;text-align:center}.widefat .column-job_listing_type .full-time{background-color:#90da36}.widefat .column-job_listing_type .part-time{background-color:#f08d3c}.widefat .column-job_listing_type .temporary{background-color:#d93674}.widefat .column-job_listing_type .freelance{background-color:#39c}.widefat .column-job_listing_type .internship{background-color:#6033cc}.widefat th.column-job_position{width:20%}.widefat td.column-job_position{width:20%;height:34px}.widefat td.column-job_position .job_position{position:relative;padding-right:50px!important}.widefat td.column-job_position a.job_title{font-weight:700}.widefat td.column-job_position img{width:32px;height:32px;position:absolute;right:7px;top:0;-webkit-border-radius:50%;border-radius:50%;box-shadow:0 1px 0 1px rgba(0,0,0,.1);-webkit-box-shadow:0 1px 0 1px rgba(0,0,0,.1);-moz-box-shadow:0 1px 0 1px rgba(0,0,0,.1);border:1px solid #fff}.widefat td.column-job_position .company{margin-top:.2em;display:block;padding-top:2px;color:#bbb}.widefat .column-job_location{width:10%}.widefat .column-job_actions{text-align:right;width:128px}.widefat .column-job_actions strong{display:block;margin-bottom:.2em}.widefat .column-job_actions .actions{padding-top:2px}.widefat .column-job_actions a.button{display:inline-block;margin:0 0 2px 4px;cursor:pointer;padding:0 6px!important;font-size:1em!important;line-height:2em!important;overflow:hidden}.widefat .column-job_actions a.button-icon{width:2em!important;padding:0!important}.widefat .column-job_actions a.button-icon:before{font-family:job-manager!important;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;text-align:center;font-variant:normal;text-transform:none;float:left;width:2em!important;line-height:2em}.widefat .column-job_actions .icon-view:before{content:'\e805'}.widefat .column-job_actions .icon-edit:before{content:'\e804'}.widefat .column-job_actions .icon-delete:before{content:'\e82b'}.widefat .column-job_actions .icon-approve:before{content:'\e802'}.wp_job_manager_meta_data{zoom:1}.wp_job_manager_meta_data:after,.wp_job_manager_meta_data:before{content:"";display:table}.wp_job_manager_meta_data:after{clear:both}.wp_job_manager_meta_data .form-field{width:50%;line-height:2em;float:left;box-sizing:border-box;padding:0 12px 0 0;margin:0 0 12px;clear:both}.wp_job_manager_meta_data .form-field:nth-child(even){float:right;padding:0 0 0 12px;clear:right}.wp_job_manager_meta_data .form-field:nth-last-child(-n+2){margin-bottom:0;padding-bottom:0;border-bottom:0}.wp_job_manager_meta_data .form-field label{vertical-align:middle;display:block;font-weight:700;margin:0}.wp_job_manager_meta_data .form-field .tips{cursor:help;float:right;font-weight:400;color:#999}.wp_job_manager_meta_data .form-field input{width:100%;margin:1px 0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;vertical-align:middle}.wp_job_manager_meta_data .form-field input.checkbox,.wp_job_manager_meta_data .form-field input.radio{width:auto;margin:4px 2px;display:inline-block}.wp_job_manager_meta_data .form-field .description{display:block;color:#999}.wp_job_manager_meta_data .form-field.form-field-checkbox .description{display:inline}.wp_job_manager_meta_data .form-field .file_url input{width:75%}.wp_job_manager_meta_data .form-field .button{margin-left:4px}.wp_job_manager_meta_data .form-field .file_no_url{-o-animation:flash .3s linear infinite alternate;-webkit-animation:flash .3s linear infinite alternate;-moz-animation:flash .3s linear infinite alternate;animation:flash .3s linear infinite alternate}@-o-keyframes flash{from{background-color:unset}to{background-color:#dc3232}}@-ms-keyframes flash{from{background-color:unset}to{background-color:#dc3232}}@-moz-keyframes flash{from{background-color:unset}to{background-color:#dc3232}}@-webkit-keyframes flash{from{background-color:unset}to{background-color:#dc3232}}@keyframes flash{from{background-color:unset}to{background-color:#dc3232}}#tiptip_holder{display:none;position:absolute;top:0;left:0;z-index:99999}#tiptip_holder.tip_top{padding-bottom:5px}#tiptip_holder.tip_bottom{padding-top:5px}#tiptip_holder.tip_right{padding-left:5px}#tiptip_holder.tip_left{padding-right:5px}#tiptip_content{font-size:11px;color:#fff;padding:4px 8px;background:#464646;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;box-shadow:1px 1px 3px rgba(0,0,0,.1);-webkit-box-shadow:1px 1px 3px rgba(0,0,0,.1);-moz-box-shadow:1px 1px 3px rgba(0,0,0,.1);text-align:center}#tiptip_content code{background:#999;padding:1px}#tiptip_arrow,#tiptip_arrow_inner{position:absolute;border-color:transparent;border-style:solid;border-width:6px;height:0;width:0}#tiptip_holder.tip_top #tiptip_arrow_inner{margin-top:-7px;margin-left:-6px;border-top-color:#464646}#tiptip_holder.tip_bottom #tiptip_arrow_inner{margin-top:-5px;margin-left:-6px;border-bottom-color:#464646}#tiptip_holder.tip_right #tiptip_arrow_inner{margin-top:-6px;margin-left:-5px;border-right-color:#464646}#tiptip_holder.tip_left #tiptip_arrow_inner{margin-top:-6px;margin-left:-7px;border-left-color:#464646}.wp_job_manager_addons_wrap #job-manager-addons-banner{position:relative;background:#d85677;padding:0 2em 0 5em;color:#fff;margin:10px .25% 20px 0;border-color:rgba(0,0,0,.1);overflow:hidden}.wp_job_manager_addons_wrap #job-manager-addons-banner strong{font-size:1.25em;line-height:.8em;text-shadow:0 2px 0 rgba(0,0,0,.1);font-weight:400;float:left;padding:1.6em 0}.wp_job_manager_addons_wrap #job-manager-addons-banner a.button{color:#fff;text-decoration:none;font-weight:700;float:right;background:#d85677;border:1px solid #fff;line-height:1em;padding:1em;margin:1em 0;text-shadow:0 2px 0 rgba(0,0,0,.1);box-shadow:0 2px 0 rgba(0,0,0,.1);height:auto;position:relative}.wp_job_manager_addons_wrap #job-manager-addons-banner:before{display:inline-block;-webkit-font-smoothing:antialiased;vertical-align:top;font-family:jm-logo;content:"\e600";top:.02em;left:0;position:absolute;text-shadow:0 2px 0 rgba(0,0,0,.1);font-size:5em;font-weight:400;text-align:center;width:1em;height:1em;line-height:1em}.wp_job_manager_addons_wrap .products{overflow:hidden}.wp_job_manager_addons_wrap .products li{display:inline-block;margin:0 1% 10px 0!important;padding:0;vertical-align:top;width:24%;min-width:250px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:1px solid #ddd;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),inset 0 -1px 0 rgba(0,0,0,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),inset 0 -1px 0 rgba(0,0,0,.1);overflow:hidden;position:relative;opacity:.8}.wp_job_manager_addons_wrap .products li:nth-child(4n+0){margin-right:0!important}.wp_job_manager_addons_wrap .products li a{color:inherit;text-decoration:none}.wp_job_manager_addons_wrap .products li img{width:100%;height:auto;display:block;padding:0;margin:0;background:#fff;border-bottom:1px solid rgba(0,0,0,.1)}.wp_job_manager_addons_wrap .products li h2{margin:0!important;padding:10px 0!important;line-height:1;background:rgba(255,255,255,.6);border-bottom:1px solid rgba(0,0,0,.1);color:#000;text-align:center;position:absolute;width:100%;top:0;left:0;font-size:16px;text-shadow:none;display:none}.wp_job_manager_addons_wrap .products li:focus,.wp_job_manager_addons_wrap .products li:hover{opacity:1}.wp_job_manager_addons_wrap .products li:focus h2,.wp_job_manager_addons_wrap .products li:hover h2{display:block}.wp_job_manager_addons_wrap .products li .third_party{display:none}.wp_job_manager_addons_wrap .products li p{padding:20px!important;margin:0!important;border-top:1px solid #f1f1f1}.wp_job_manager_addons_wrap .products li .price{display:none}.rtl .widefat .column-job_actions a.button-icon:before{float:right}.rtl .wp_job_manager_meta_data p{padding:0 20% 0 0}.rtl .wp_job_manager_meta_data label{left:auto;right:0}@media only screen and (max-width:782px){.widefat .job_position.column-primary{display:table-cell!important}.widefat .toggle-row:before{top:5px}.widefat .column-job_actions{text-align:left}.widefat .column-job_actions a.button-icon:before{float:left}.rtl .widefat .column-job_actions{text-align:right}.rtl .widefat .column-job_actions a.button-icon:before{float:right}.wp_job_manager_meta_data .form-field{width:100%;padding:0}.wp_job_manager_meta_data .form-field:nth-child(even),.wp_job_manager_meta_data .form-field:nth-last-child(-n+2){float:none;padding:0;margin-bottom:12px;clear:both}}
|
assets/css/admin.less
ADDED
@@ -0,0 +1,544 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@import "mixins";
|
2 |
+
@import "icons.less";
|
3 |
+
|
4 |
+
.job-manager-settings-wrap {
|
5 |
+
.updated {
|
6 |
+
display: none;
|
7 |
+
}
|
8 |
+
.job-manager-updated {
|
9 |
+
display: block;
|
10 |
+
margin: 1em 0 0;
|
11 |
+
}
|
12 |
+
}
|
13 |
+
.widefat {
|
14 |
+
td.column-featured_job, td.column-filled, td.column-job_status {
|
15 |
+
width: 46px;
|
16 |
+
text-align: left;
|
17 |
+
padding-left: 11px;
|
18 |
+
}
|
19 |
+
th.column-featured_job, th.column-filled, th.column-job_status {
|
20 |
+
width: 1em;
|
21 |
+
span {
|
22 |
+
display: block;
|
23 |
+
width: 1em;
|
24 |
+
height: 1em;
|
25 |
+
line-height: 1em;
|
26 |
+
padding: 1px 0 0 0;
|
27 |
+
overflow: hidden;
|
28 |
+
&:before {
|
29 |
+
content: '\e803';
|
30 |
+
.jm-icon;
|
31 |
+
}
|
32 |
+
}
|
33 |
+
}
|
34 |
+
th.column-filled {
|
35 |
+
span {
|
36 |
+
&:before {
|
37 |
+
content: '\e807';
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
41 |
+
th.column-job_status {
|
42 |
+
span {
|
43 |
+
&:before {
|
44 |
+
content: '\e828';
|
45 |
+
}
|
46 |
+
}
|
47 |
+
}
|
48 |
+
.column-job_posted {
|
49 |
+
strong {
|
50 |
+
display: block;
|
51 |
+
margin-bottom: .2em;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
td.column-job_status {
|
55 |
+
span {
|
56 |
+
position: relative;
|
57 |
+
font-size: 1em;
|
58 |
+
line-height: 1.5em;
|
59 |
+
width: 1em;
|
60 |
+
height: 0;
|
61 |
+
padding: 2em 0 0 0;
|
62 |
+
overflow: hidden;
|
63 |
+
display: block;
|
64 |
+
}
|
65 |
+
span:before {
|
66 |
+
.jm-icon;
|
67 |
+
position: absolute;
|
68 |
+
top: 0;
|
69 |
+
left: 0;
|
70 |
+
line-height: 1.5em;
|
71 |
+
vertical-align: middle;
|
72 |
+
color: #999;
|
73 |
+
content: '\e829';
|
74 |
+
}
|
75 |
+
.status-trash:before {
|
76 |
+
content: '\e82b';
|
77 |
+
color: #a00;
|
78 |
+
}
|
79 |
+
.status-pending:before {
|
80 |
+
content: '\e82c';
|
81 |
+
color: #ffba00;
|
82 |
+
}
|
83 |
+
.status-publish:before {
|
84 |
+
content: '\e82f';
|
85 |
+
color: #73a724;
|
86 |
+
}
|
87 |
+
.status-expired:before {
|
88 |
+
content: '\e82e';
|
89 |
+
color: #a00;
|
90 |
+
}
|
91 |
+
}
|
92 |
+
.column-job_listing_type {
|
93 |
+
text-align: left;
|
94 |
+
width: 6em;
|
95 |
+
word-wrap: normal !important;
|
96 |
+
.job-type {
|
97 |
+
color: #fff;
|
98 |
+
padding: 4px;
|
99 |
+
font-size: 11px;
|
100 |
+
.border_radius( 2px );
|
101 |
+
display:block;
|
102 |
+
background-color: @part-time;
|
103 |
+
text-align: center;
|
104 |
+
}
|
105 |
+
.full-time {
|
106 |
+
background-color: @full-time;
|
107 |
+
}
|
108 |
+
.part-time {
|
109 |
+
background-color: @part-time;
|
110 |
+
}
|
111 |
+
.temporary {
|
112 |
+
background-color: @temporary;
|
113 |
+
}
|
114 |
+
.freelance {
|
115 |
+
background-color: @freelance;
|
116 |
+
}
|
117 |
+
.internship {
|
118 |
+
background-color: @internship;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
th.column-job_position {
|
122 |
+
width: 20%;
|
123 |
+
}
|
124 |
+
td.column-job_position {
|
125 |
+
width: 20%;
|
126 |
+
height: 34px;
|
127 |
+
.job_position {
|
128 |
+
position: relative;
|
129 |
+
padding-right: 50px !important;
|
130 |
+
}
|
131 |
+
a.job_title {
|
132 |
+
font-weight: bold;
|
133 |
+
}
|
134 |
+
img {
|
135 |
+
width: 32px;
|
136 |
+
height: 32px;
|
137 |
+
position: absolute;
|
138 |
+
right: 7px;
|
139 |
+
top: 0;
|
140 |
+
.border_radius( 50% );
|
141 |
+
.box_shadow( 0, 1px, 0, 1px, rgba( 0,0,0,0.1 ) );
|
142 |
+
border: 1px solid #fff;
|
143 |
+
}
|
144 |
+
.company {
|
145 |
+
margin-top: .2em;
|
146 |
+
display: block;
|
147 |
+
padding-top: 2px;
|
148 |
+
color: #bbbbbb;
|
149 |
+
}
|
150 |
+
}
|
151 |
+
.column-job_location {
|
152 |
+
width: 10%;
|
153 |
+
}
|
154 |
+
.column-job_actions {
|
155 |
+
text-align: right;
|
156 |
+
width: 128px;
|
157 |
+
strong {
|
158 |
+
display: block;
|
159 |
+
margin-bottom: .2em;
|
160 |
+
}
|
161 |
+
.actions {
|
162 |
+
padding-top: 2px;
|
163 |
+
}
|
164 |
+
a.button {
|
165 |
+
display: inline-block;
|
166 |
+
margin: 0 0 2px 4px;
|
167 |
+
cursor: pointer;
|
168 |
+
padding: 0 6px !important;
|
169 |
+
font-size: 1em !important;
|
170 |
+
line-height: 2em !important;
|
171 |
+
overflow: hidden;
|
172 |
+
}
|
173 |
+
a.button-icon {
|
174 |
+
width: 2em !important;
|
175 |
+
padding: 0 !important;
|
176 |
+
&:before {
|
177 |
+
.jm-icon;
|
178 |
+
float: left;
|
179 |
+
width: 2em !important;
|
180 |
+
line-height: 2em;
|
181 |
+
}
|
182 |
+
}
|
183 |
+
.icon-view:before {
|
184 |
+
content: '\e805';
|
185 |
+
}
|
186 |
+
.icon-edit:before {
|
187 |
+
content: '\e804';
|
188 |
+
}
|
189 |
+
.icon-delete:before {
|
190 |
+
content: '\e82b';
|
191 |
+
}
|
192 |
+
.icon-approve:before {
|
193 |
+
content: '\e802';
|
194 |
+
}
|
195 |
+
}
|
196 |
+
}
|
197 |
+
.wp_job_manager_meta_data {
|
198 |
+
zoom: 1;
|
199 |
+
&:before,
|
200 |
+
&:after {
|
201 |
+
content: "";
|
202 |
+
display: table;
|
203 |
+
}
|
204 |
+
&:after {
|
205 |
+
clear: both;
|
206 |
+
}
|
207 |
+
.form-field {
|
208 |
+
width: 50%;
|
209 |
+
line-height: 2em;
|
210 |
+
float: left;
|
211 |
+
box-sizing: border-box;
|
212 |
+
padding: 0 12px 0 0;
|
213 |
+
margin: 0 0 12px;
|
214 |
+
clear: both;
|
215 |
+
&:nth-child(even) {
|
216 |
+
float: right;
|
217 |
+
padding: 0 0 0 12px;
|
218 |
+
clear: right;
|
219 |
+
}
|
220 |
+
&:nth-last-child(-n+2) {
|
221 |
+
margin-bottom: 0;
|
222 |
+
padding-bottom: 0;
|
223 |
+
border-bottom: 0;
|
224 |
+
}
|
225 |
+
label {
|
226 |
+
vertical-align: middle;
|
227 |
+
display: block;
|
228 |
+
font-weight: bold;
|
229 |
+
margin: 0;
|
230 |
+
}
|
231 |
+
.tips {
|
232 |
+
cursor: help;
|
233 |
+
float: right;
|
234 |
+
font-weight: normal;
|
235 |
+
color: #999;
|
236 |
+
}
|
237 |
+
input {
|
238 |
+
width: 100%;
|
239 |
+
margin: 1px 0;
|
240 |
+
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
241 |
+
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
242 |
+
box-sizing: border-box; /* Opera/IE 8+ */
|
243 |
+
vertical-align: middle;
|
244 |
+
}
|
245 |
+
input.checkbox, input.radio {
|
246 |
+
width: auto;
|
247 |
+
margin: 4px 2px;
|
248 |
+
display: inline-block;
|
249 |
+
}
|
250 |
+
.description {
|
251 |
+
display: block;
|
252 |
+
color: #999;
|
253 |
+
}
|
254 |
+
&.form-field-checkbox .description {
|
255 |
+
display: inline;
|
256 |
+
}
|
257 |
+
.file_url {
|
258 |
+
input {
|
259 |
+
width: 75%;
|
260 |
+
}
|
261 |
+
}
|
262 |
+
.button {
|
263 |
+
margin-left: 4px;
|
264 |
+
}
|
265 |
+
.file_no_url {
|
266 |
+
.keyframes(flash; {
|
267 |
+
from { background-color: unset; }
|
268 |
+
to { background-color: #dc3232; }
|
269 |
+
});
|
270 |
+
|
271 |
+
.animation(flash 0.3s linear infinite alternate);
|
272 |
+
}
|
273 |
+
}
|
274 |
+
}
|
275 |
+
|
276 |
+
/* TipTip CSS - Version 1.2 */
|
277 |
+
#tiptip_holder {
|
278 |
+
display: none;
|
279 |
+
position: absolute;
|
280 |
+
top: 0;
|
281 |
+
left: 0;
|
282 |
+
z-index: 99999;
|
283 |
+
}
|
284 |
+
#tiptip_holder.tip_top {
|
285 |
+
padding-bottom: 5px;
|
286 |
+
}
|
287 |
+
#tiptip_holder.tip_bottom {
|
288 |
+
padding-top: 5px;
|
289 |
+
}
|
290 |
+
#tiptip_holder.tip_right {
|
291 |
+
padding-left: 5px;
|
292 |
+
}
|
293 |
+
#tiptip_holder.tip_left {
|
294 |
+
padding-right: 5px;
|
295 |
+
}
|
296 |
+
#tiptip_content {
|
297 |
+
font-size: 11px;
|
298 |
+
color: #fff;
|
299 |
+
padding: 4px 8px;
|
300 |
+
background:#464646;
|
301 |
+
border-radius: 3px;
|
302 |
+
-webkit-border-radius: 3px;
|
303 |
+
-moz-border-radius: 3px;
|
304 |
+
box-shadow: 1px 1px 3px rgba(0,0,0,0.10);
|
305 |
+
-webkit-box-shadow: 1px 1px 3px rgba(0,0,0,0.10);
|
306 |
+
-moz-box-shadow: 1px 1px 3px rgba(0,0,0,0.10);
|
307 |
+
text-align: center;
|
308 |
+
code {
|
309 |
+
background: #999;
|
310 |
+
padding: 1px;
|
311 |
+
}
|
312 |
+
}
|
313 |
+
#tiptip_arrow, #tiptip_arrow_inner {
|
314 |
+
position: absolute;
|
315 |
+
border-color: transparent;
|
316 |
+
border-style: solid;
|
317 |
+
border-width: 6px;
|
318 |
+
height: 0;
|
319 |
+
width: 0;
|
320 |
+
}
|
321 |
+
#tiptip_holder.tip_top #tiptip_arrow_inner {
|
322 |
+
margin-top: -7px;
|
323 |
+
margin-left: -6px;
|
324 |
+
border-top-color: #464646;
|
325 |
+
}
|
326 |
+
|
327 |
+
#tiptip_holder.tip_bottom #tiptip_arrow_inner {
|
328 |
+
margin-top: -5px;
|
329 |
+
margin-left: -6px;
|
330 |
+
border-bottom-color: #464646;
|
331 |
+
}
|
332 |
+
|
333 |
+
#tiptip_holder.tip_right #tiptip_arrow_inner {
|
334 |
+
margin-top: -6px;
|
335 |
+
margin-left: -5px;
|
336 |
+
border-right-color: #464646;
|
337 |
+
}
|
338 |
+
|
339 |
+
#tiptip_holder.tip_left #tiptip_arrow_inner {
|
340 |
+
margin-top: -6px;
|
341 |
+
margin-left: -7px;
|
342 |
+
border-left-color: #464646;
|
343 |
+
}
|
344 |
+
|
345 |
+
/* Addons */
|
346 |
+
.wp_job_manager_addons_wrap {
|
347 |
+
#job-manager-addons-banner {
|
348 |
+
position: relative;
|
349 |
+
background: #d85677;
|
350 |
+
padding: 0 2em 0 5em;
|
351 |
+
color: #fff;
|
352 |
+
margin: 10px .25% 20px 0;
|
353 |
+
border-color: rgba(0,0,0,.1);
|
354 |
+
overflow: hidden;
|
355 |
+
strong {
|
356 |
+
font-size: 1.25em;
|
357 |
+
line-height: 1/1.25em;
|
358 |
+
text-shadow: 0 2px 0 rgba(0,0,0,.1);
|
359 |
+
font-weight: normal;
|
360 |
+
float: left;
|
361 |
+
padding: 1/1.25*2em 0;
|
362 |
+
}
|
363 |
+
a.button {
|
364 |
+
color: #fff;
|
365 |
+
text-decoration: none;
|
366 |
+
font-weight: bold;
|
367 |
+
float: right;
|
368 |
+
background: #d85677;
|
369 |
+
border: 1px solid #fff;
|
370 |
+
line-height: 1em;
|
371 |
+
padding: 1em;
|
372 |
+
margin: 1em 0;
|
373 |
+
text-shadow: 0 2px 0 rgba(0,0,0,.1);
|
374 |
+
box-shadow: 0 2px 0 rgba(0,0,0,.1);
|
375 |
+
height: auto;
|
376 |
+
position: relative;
|
377 |
+
}
|
378 |
+
&:before {
|
379 |
+
display: inline-block;
|
380 |
+
-webkit-font-smoothing: antialiased;
|
381 |
+
vertical-align: top;
|
382 |
+
font-family: 'jm-logo';
|
383 |
+
content: "\e600";
|
384 |
+
top: .02em;
|
385 |
+
left: 0;
|
386 |
+
position: absolute;
|
387 |
+
text-shadow: 0 2px 0 rgba(0,0,0,0.1);
|
388 |
+
font-size: 5em;
|
389 |
+
font-weight: normal;
|
390 |
+
text-align: center;
|
391 |
+
width: 1em;
|
392 |
+
height: 1em;
|
393 |
+
line-height: 1em;
|
394 |
+
}
|
395 |
+
}
|
396 |
+
.products {
|
397 |
+
overflow: hidden;
|
398 |
+
li {
|
399 |
+
display: inline-block;
|
400 |
+
margin: 0 1% 10px 0 !important;
|
401 |
+
padding: 0;
|
402 |
+
vertical-align: top;
|
403 |
+
width: 24%;
|
404 |
+
min-width: 250px;
|
405 |
+
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
406 |
+
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
407 |
+
box-sizing: border-box; /* Opera/IE 8+ */
|
408 |
+
border: 1px solid #ddd;
|
409 |
+
-webkit-box-shadow:
|
410 |
+
inset 0 1px 0 rgba(255,255,255,0.2),
|
411 |
+
inset 0 -1px 0 rgba(0,0,0,0.1);
|
412 |
+
box-shadow:
|
413 |
+
inset 0 1px 0 rgba(255,255,255,0.2),
|
414 |
+
inset 0 -1px 0 rgba(0,0,0,0.1);
|
415 |
+
overflow: hidden;
|
416 |
+
position: relative;
|
417 |
+
opacity: 0.8;
|
418 |
+
&:nth-child(4n+0) {
|
419 |
+
margin-right: 0 !important;
|
420 |
+
}
|
421 |
+
a {
|
422 |
+
color: inherit;
|
423 |
+
text-decoration: none;
|
424 |
+
}
|
425 |
+
img {
|
426 |
+
width: 100%;
|
427 |
+
height: auto;
|
428 |
+
display: block;
|
429 |
+
padding: 0;
|
430 |
+
margin: 0;
|
431 |
+
background: #fff;
|
432 |
+
border-bottom: 1px solid rgba(0,0,0,0.1);
|
433 |
+
}
|
434 |
+
h2 {
|
435 |
+
margin: 0 !important;
|
436 |
+
padding: 10px 0 !important;
|
437 |
+
line-height: 1;
|
438 |
+
background: rgba(255,255,255,0.6);
|
439 |
+
border-bottom: 1px solid rgba(0,0,0,0.1);
|
440 |
+
color: #000;
|
441 |
+
text-align: center;
|
442 |
+
position: absolute;
|
443 |
+
width: 100%;
|
444 |
+
top: 0;
|
445 |
+
left: 0;
|
446 |
+
font-size: 16px;
|
447 |
+
text-shadow: none;
|
448 |
+
display: none;
|
449 |
+
}
|
450 |
+
&:hover, &:focus {
|
451 |
+
opacity: 1;
|
452 |
+
h2 {
|
453 |
+
display: block;
|
454 |
+
}
|
455 |
+
}
|
456 |
+
.third_party {
|
457 |
+
display: none;
|
458 |
+
}
|
459 |
+
p {
|
460 |
+
padding: 20px !important;
|
461 |
+
margin: 0 !important;
|
462 |
+
border-top: 1px solid #f1f1f1;
|
463 |
+
}
|
464 |
+
.price {
|
465 |
+
display: none;
|
466 |
+
}
|
467 |
+
}
|
468 |
+
}
|
469 |
+
}
|
470 |
+
.rtl {
|
471 |
+
.widefat {
|
472 |
+
.column-job_actions {
|
473 |
+
a.button-icon {
|
474 |
+
&:before {
|
475 |
+
float: right;
|
476 |
+
}
|
477 |
+
}
|
478 |
+
}
|
479 |
+
}
|
480 |
+
.wp_job_manager_meta_data {
|
481 |
+
p {
|
482 |
+
padding: 0 20% 0 0;
|
483 |
+
}
|
484 |
+
label {
|
485 |
+
left: auto;
|
486 |
+
right: 0;
|
487 |
+
}
|
488 |
+
}
|
489 |
+
}
|
490 |
+
|
491 |
+
/**
|
492 |
+
* Mobile styles
|
493 |
+
*/
|
494 |
+
@media only screen and (max-width: 782px) {
|
495 |
+
.widefat {
|
496 |
+
.job_position.column-primary{
|
497 |
+
display: table-cell !important;
|
498 |
+
}
|
499 |
+
.toggle-row:before{
|
500 |
+
top: 5px;
|
501 |
+
}
|
502 |
+
.column-job_actions {
|
503 |
+
text-align: left;
|
504 |
+
|
505 |
+
a.button-icon {
|
506 |
+
&:before {
|
507 |
+
float: left;
|
508 |
+
}
|
509 |
+
}
|
510 |
+
}
|
511 |
+
}
|
512 |
+
.rtl {
|
513 |
+
.widefat {
|
514 |
+
.column-job_actions {
|
515 |
+
text-align: right;
|
516 |
+
|
517 |
+
a.button-icon {
|
518 |
+
&:before {
|
519 |
+
float: right;
|
520 |
+
}
|
521 |
+
}
|
522 |
+
}
|
523 |
+
}
|
524 |
+
}
|
525 |
+
.wp_job_manager_meta_data {
|
526 |
+
.form-field {
|
527 |
+
width: 100%;
|
528 |
+
padding: 0;
|
529 |
+
|
530 |
+
&:nth-child(even) {
|
531 |
+
float: none;
|
532 |
+
padding: 0;
|
533 |
+
margin-bottom: 12px;
|
534 |
+
clear: both;
|
535 |
+
}
|
536 |
+
&:nth-last-child(-n+2) {
|
537 |
+
float: none;
|
538 |
+
padding: 0;
|
539 |
+
margin-bottom: 12px;
|
540 |
+
clear: both;
|
541 |
+
}
|
542 |
+
}
|
543 |
+
}
|
544 |
+
}
|
assets/css/chosen.css
CHANGED
@@ -8,4 +8,4 @@ Copyright (c) 2011 Harvest http://getharvest.com
|
|
8 |
|
9 |
MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
|
10 |
This file is generated by `grunt build`, do not edit it by hand.
|
11 |
-
*/.chosen-container{position:relative;display:inline-block;vertical-align:middle;font-size:13px;zoom:1;-webkit-user-select:none;-moz-user-select:none;user-select:none}.chosen-container .chosen-drop{position:absolute;top:100%;left:-9999px;z-index:1010;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;border:1px solid #aaa;border-top:0;background:#fff;box-shadow:0 4px 5px rgba(0,0,0,.15)}.chosen-container.chosen-with-drop .chosen-drop{left:0}.chosen-container a{cursor:pointer}.chosen-container-single .chosen-single{position:relative;display:block;overflow:hidden;padding:0 0 0 8px;height:23px;border:1px solid #aaa;border-radius:5px;background-color:#fff;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#fff),color-stop(50%,#f6f6f6),color-stop(52%,#eee),color-stop(100%,#f4f4f4));background:-webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-clip:padding-box;box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);color:#444;text-decoration:none;white-space:nowrap;line-height:24px}.chosen-container-single .chosen-default{color:#999}.chosen-container-single .chosen-single span{display:block;overflow:hidden;margin-right:26px;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:6px;right:26px;display:block;width:12px;height:12px;background:url(../images/chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-single .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single.chosen-disabled .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;width:18px;height:100%}.chosen-container-single .chosen-single div b{display:block;width:100%;height:100%;background:url(../images/chosen-sprite.png) no-repeat 0 2px}.chosen-container-single .chosen-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:1px 0;padding:4px 20px 4px 5px;width:100%;height:auto;outline:0;border:1px solid #aaa;background:#fff url(../images/chosen-sprite.png) no-repeat 100% -20px;background:url(../images/chosen-sprite.png) no-repeat 100% -20px;font-size:1em;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-single .chosen-drop{margin-top:-1px;border-radius:0 0 4px 4px;background-clip:padding-box}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;left:-9999px}.chosen-container .chosen-results{position:relative;overflow-x:hidden;overflow-y:auto;margin:0 4px 4px 0;padding:0 0 0 4px;max-height:240px;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;margin:0;padding:5px 6px;list-style:none;line-height:15px;-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{background-color:#3875d7;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#3875d7),color-stop(90%,#2a62bc));background-image:-webkit-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-moz-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-o-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:linear-gradient(#3875d7 20%,#2a62bc 90%);color:#fff}.chosen-container .chosen-results li.no-results{display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;width:100%;height:auto!important;height:1%;border:1px solid #aaa;background-color:#fff;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(1%,#eee),color-stop(15%,#fff));background-image:-webkit-linear-gradient(#eee 1%,#fff 15%);background-image:-moz-linear-gradient(#eee 1%,#fff 15%);background-image:-o-linear-gradient(#eee 1%,#fff 15%);background-image:linear-gradient(#eee 1%,#fff 15%);cursor:text}.chosen-container-multi .chosen-choices li{float:left;list-style:none}.chosen-container-multi .chosen-choices li.search-field{margin:0;padding:0;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{margin:1px 0;padding:5px;height:auto;outline:0;border:0!important;background:0 0!important;box-shadow:none;color:#666;font-size:100%;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-multi .chosen-choices li.search-field .default{color:#999}.chosen-container-multi .chosen-choices li.search-choice{position:relative;margin:3px 0 3px 5px;padding:3px 20px 3px 5px;border:1px solid #aaa;border-radius:3px;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-clip:padding-box;box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);color:#333;line-height:13px;cursor:default}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:4px;right:3px;display:block;width:12px;height:12px;background:url(../images/chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{background-position:-42px -10px}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;border:1px solid #ccc;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);color:#666}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{margin:0;padding:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #aaa;-moz-border-radius-bottomright:0;border-bottom-right-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#eee),color-stop(80%,#fff));background-image:-webkit-linear-gradient(#eee 20%,#fff 80%);background-image:-moz-linear-gradient(#eee 20%,#fff 80%);background-image:-o-linear-gradient(#eee 20%,#fff 80%);background-image:linear-gradient(#eee 20%,#fff 80%);box-shadow:0 1px 0 #fff inset}.chosen-container-active.chosen-with-drop .chosen-single div{border-left:none;background:0 0}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position:-18px 2px}.chosen-container-active .chosen-choices{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#111!important}.chosen-disabled{opacity:.5!important;cursor:default}.chosen-disabled .chosen-single{cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close{cursor:default}.chosen-rtl{text-align:right}.chosen-rtl .chosen-single{overflow:visible;padding:0 8px 0 0}.chosen-rtl .chosen-single span{margin-right:0;margin-left:26px;direction:rtl}.chosen-rtl .chosen-single-with-deselect span{margin-left:38px}.chosen-rtl .chosen-single div{right:auto;left:3px}.chosen-rtl .chosen-single abbr{right:auto;left:26px}.chosen-rtl .chosen-choices li{float:right}.chosen-rtl .chosen-choices li.search-field input[type=text]{direction:rtl}.chosen-rtl .chosen-choices li.search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:4px}.chosen-rtl .chosen-drop,.chosen-rtl.chosen-container-single-nosearch .chosen-search{left:9999px}.chosen-rtl.chosen-container-single .chosen-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chosen-rtl .chosen-results li.group-option{padding-right:15px;padding-left:0}.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div{border-right:none}.chosen-rtl .chosen-search input[type=text]{padding:4px 5px 4px 20px;background:#fff url(../images/chosen-sprite.png) no-repeat -30px -20px;background:url(../images/chosen-sprite.png) no-repeat -30px -20px;direction:rtl}.chosen-rtl.chosen-container-single .chosen-single div b{background-position:6px 2px}.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-resolution:144dpi){.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span,.chosen-container-multi .chosen-choices .search-choice .search-choice-close,.chosen-container-single .chosen-search input[type=text],.chosen-container-single .chosen-single abbr,.chosen-container-single .chosen-single div b,.chosen-rtl .chosen-search input[type=text]{background-image:url(../images/chosen-sprite@2x.png)!important;background-size:52px 37px!important;background-repeat:no-repeat!important}}
|
8 |
|
9 |
MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
|
10 |
This file is generated by `grunt build`, do not edit it by hand.
|
11 |
+
*/.chosen-container{position:relative;display:inline-block;vertical-align:middle;font-size:13px;zoom:1;*display:inline;-webkit-user-select:none;-moz-user-select:none;user-select:none}.chosen-container .chosen-drop{position:absolute;top:100%;left:-9999px;z-index:1010;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;border:1px solid #aaa;border-top:0;background:#fff;box-shadow:0 4px 5px rgba(0,0,0,.15)}.chosen-container.chosen-with-drop .chosen-drop{left:0}.chosen-container a{cursor:pointer}.chosen-container-single .chosen-single{position:relative;display:block;overflow:hidden;padding:0 0 0 8px;height:23px;border:1px solid #aaa;border-radius:5px;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#fff),color-stop(50%,#f6f6f6),color-stop(52%,#eee),color-stop(100%,#f4f4f4));background:-webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-clip:padding-box;box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);color:#444;text-decoration:none;white-space:nowrap;line-height:24px}.chosen-container-single .chosen-default{color:#999}.chosen-container-single .chosen-single span{display:block;overflow:hidden;margin-right:26px;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:6px;right:26px;display:block;width:12px;height:12px;background:url(../images/chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-single .chosen-single abbr:hover,.chosen-container-single.chosen-disabled .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;width:18px;height:100%}.chosen-container-single .chosen-single div b{display:block;width:100%;height:100%;background:url(../images/chosen-sprite.png) no-repeat 0 2px}.chosen-container-single .chosen-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:1px 0;padding:4px 20px 4px 5px;width:100%;height:auto;outline:0;border:1px solid #aaa;background:#fff url(../images/chosen-sprite.png) no-repeat 100% -20px;background:url(../images/chosen-sprite.png) no-repeat 100% -20px;font-size:1em;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-single .chosen-drop{margin-top:-1px;border-radius:0 0 4px 4px;background-clip:padding-box}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;left:-9999px}.chosen-container .chosen-results{position:relative;overflow-x:hidden;overflow-y:auto;margin:0 4px 4px 0;padding:0 0 0 4px;max-height:240px;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;margin:0;padding:5px 6px;list-style:none;line-height:15px;-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{background-color:#3875d7;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#3875d7),color-stop(90%,#2a62bc));background-image:-webkit-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-moz-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-o-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:linear-gradient(#3875d7 20%,#2a62bc 90%);color:#fff}.chosen-container .chosen-results li.no-results{display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;width:100%;height:auto!important;height:1%;border:1px solid #aaa;background-color:#fff;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(1%,#eee),color-stop(15%,#fff));background-image:-webkit-linear-gradient(#eee 1%,#fff 15%);background-image:-moz-linear-gradient(#eee 1%,#fff 15%);background-image:-o-linear-gradient(#eee 1%,#fff 15%);background-image:linear-gradient(#eee 1%,#fff 15%);cursor:text}.chosen-container-multi .chosen-choices li{float:left;list-style:none}.chosen-container-multi .chosen-choices li.search-field{margin:0;padding:0;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{margin:1px 0;padding:5px;height:auto;outline:0;border:0!important;background:transparent!important;box-shadow:none;color:#666;font-size:100%;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-multi .chosen-choices li.search-field .default{color:#999}.chosen-container-multi .chosen-choices li.search-choice{position:relative;margin:3px 0 3px 5px;padding:3px 20px 3px 5px;border:1px solid #aaa;border-radius:3px;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-clip:padding-box;box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);color:#333;line-height:13px;cursor:default}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:4px;right:3px;display:block;width:12px;height:12px;background:url(../images/chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{background-position:-42px -10px}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;border:1px solid #ccc;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);color:#666}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{margin:0;padding:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #aaa;-moz-border-radius-bottomright:0;border-bottom-right-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#eee),color-stop(80%,#fff));background-image:-webkit-linear-gradient(#eee 20%,#fff 80%);background-image:-moz-linear-gradient(#eee 20%,#fff 80%);background-image:-o-linear-gradient(#eee 20%,#fff 80%);background-image:linear-gradient(#eee 20%,#fff 80%);box-shadow:0 1px 0 #fff inset}.chosen-container-active.chosen-with-drop .chosen-single div{border-left:0;background:0 0}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position:-18px 2px}.chosen-container-active .chosen-choices{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#111!important}.chosen-disabled{opacity:.5!important;cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close,.chosen-disabled .chosen-single{cursor:default}.chosen-rtl{text-align:right}.chosen-rtl .chosen-single{overflow:visible;padding:0 8px 0 0}.chosen-rtl .chosen-single span{margin-right:0;margin-left:26px;direction:rtl}.chosen-rtl .chosen-single-with-deselect span{margin-left:38px}.chosen-rtl .chosen-single div{right:auto;left:3px}.chosen-rtl .chosen-single abbr{right:auto;left:26px}.chosen-rtl .chosen-choices li{float:right}.chosen-rtl .chosen-choices li.search-field input[type=text]{direction:rtl}.chosen-rtl .chosen-choices li.search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:4px}.chosen-rtl .chosen-drop,.chosen-rtl.chosen-container-single-nosearch .chosen-search{left:9999px}.chosen-rtl.chosen-container-single .chosen-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chosen-rtl .chosen-results li.group-option{padding-right:15px;padding-left:0}.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div{border-right:0}.chosen-rtl .chosen-search input[type=text]{padding:4px 5px 4px 20px;background:#fff url(../images/chosen-sprite.png) no-repeat -30px -20px;background:url(../images/chosen-sprite.png) no-repeat -30px -20px;direction:rtl}.chosen-rtl.chosen-container-single .chosen-single div b{background-position:6px 2px}.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-resolution:144dpi){.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span,.chosen-container-multi .chosen-choices .search-choice .search-choice-close,.chosen-container-single .chosen-search input[type=text],.chosen-container-single .chosen-single abbr,.chosen-container-single .chosen-single div b,.chosen-rtl .chosen-search input[type=text]{background-image:url(../images/chosen-sprite@2x.png)!important;background-size:52px 37px!important;background-repeat:no-repeat!important}}
|
assets/css/chosen.less
ADDED
@@ -0,0 +1,435 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
Chosen, a Select Box Enhancer for jQuery and Prototype
|
3 |
+
by Patrick Filler for Harvest, http://getharvest.com
|
4 |
+
|
5 |
+
Version 1.1.0
|
6 |
+
Full source at https://github.com/harvesthq/chosen
|
7 |
+
Copyright (c) 2011 Harvest http://getharvest.com
|
8 |
+
|
9 |
+
MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
|
10 |
+
This file is generated by `grunt build`, do not edit it by hand.
|
11 |
+
*/
|
12 |
+
|
13 |
+
/* @group Base */
|
14 |
+
.chosen-container {
|
15 |
+
position: relative;
|
16 |
+
display: inline-block;
|
17 |
+
vertical-align: middle;
|
18 |
+
font-size: 13px;
|
19 |
+
zoom: 1;
|
20 |
+
*display: inline;
|
21 |
+
-webkit-user-select: none;
|
22 |
+
-moz-user-select: none;
|
23 |
+
user-select: none;
|
24 |
+
}
|
25 |
+
.chosen-container .chosen-drop {
|
26 |
+
position: absolute;
|
27 |
+
top: 100%;
|
28 |
+
left: -9999px;
|
29 |
+
z-index: 1010;
|
30 |
+
-webkit-box-sizing: border-box;
|
31 |
+
-moz-box-sizing: border-box;
|
32 |
+
box-sizing: border-box;
|
33 |
+
width: 100%;
|
34 |
+
border: 1px solid #aaa;
|
35 |
+
border-top: 0;
|
36 |
+
background: #fff;
|
37 |
+
box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);
|
38 |
+
}
|
39 |
+
.chosen-container.chosen-with-drop .chosen-drop {
|
40 |
+
left: 0;
|
41 |
+
}
|
42 |
+
.chosen-container a {
|
43 |
+
cursor: pointer;
|
44 |
+
}
|
45 |
+
|
46 |
+
/* @end */
|
47 |
+
/* @group Single Chosen */
|
48 |
+
.chosen-container-single .chosen-single {
|
49 |
+
position: relative;
|
50 |
+
display: block;
|
51 |
+
overflow: hidden;
|
52 |
+
padding: 0 0 0 8px;
|
53 |
+
height: 23px;
|
54 |
+
border: 1px solid #aaa;
|
55 |
+
border-radius: 5px;
|
56 |
+
background-color: #fff;
|
57 |
+
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));
|
58 |
+
background: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
59 |
+
background: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
60 |
+
background: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
61 |
+
background: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
62 |
+
background-clip: padding-box;
|
63 |
+
box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1);
|
64 |
+
color: #444;
|
65 |
+
text-decoration: none;
|
66 |
+
white-space: nowrap;
|
67 |
+
line-height: 24px;
|
68 |
+
}
|
69 |
+
.chosen-container-single .chosen-default {
|
70 |
+
color: #999;
|
71 |
+
}
|
72 |
+
.chosen-container-single .chosen-single span {
|
73 |
+
display: block;
|
74 |
+
overflow: hidden;
|
75 |
+
margin-right: 26px;
|
76 |
+
text-overflow: ellipsis;
|
77 |
+
white-space: nowrap;
|
78 |
+
}
|
79 |
+
.chosen-container-single .chosen-single-with-deselect span {
|
80 |
+
margin-right: 38px;
|
81 |
+
}
|
82 |
+
.chosen-container-single .chosen-single abbr {
|
83 |
+
position: absolute;
|
84 |
+
top: 6px;
|
85 |
+
right: 26px;
|
86 |
+
display: block;
|
87 |
+
width: 12px;
|
88 |
+
height: 12px;
|
89 |
+
background: url('../images/chosen-sprite.png') -42px 1px no-repeat;
|
90 |
+
font-size: 1px;
|
91 |
+
}
|
92 |
+
.chosen-container-single .chosen-single abbr:hover {
|
93 |
+
background-position: -42px -10px;
|
94 |
+
}
|
95 |
+
.chosen-container-single.chosen-disabled .chosen-single abbr:hover {
|
96 |
+
background-position: -42px -10px;
|
97 |
+
}
|
98 |
+
.chosen-container-single .chosen-single div {
|
99 |
+
position: absolute;
|
100 |
+
top: 0;
|
101 |
+
right: 0;
|
102 |
+
display: block;
|
103 |
+
width: 18px;
|
104 |
+
height: 100%;
|
105 |
+
}
|
106 |
+
.chosen-container-single .chosen-single div b {
|
107 |
+
display: block;
|
108 |
+
width: 100%;
|
109 |
+
height: 100%;
|
110 |
+
background: url('../images/chosen-sprite.png') no-repeat 0px 2px;
|
111 |
+
}
|
112 |
+
.chosen-container-single .chosen-search {
|
113 |
+
position: relative;
|
114 |
+
z-index: 1010;
|
115 |
+
margin: 0;
|
116 |
+
padding: 3px 4px;
|
117 |
+
white-space: nowrap;
|
118 |
+
}
|
119 |
+
.chosen-container-single .chosen-search input[type="text"] {
|
120 |
+
-webkit-box-sizing: border-box;
|
121 |
+
-moz-box-sizing: border-box;
|
122 |
+
box-sizing: border-box;
|
123 |
+
margin: 1px 0;
|
124 |
+
padding: 4px 20px 4px 5px;
|
125 |
+
width: 100%;
|
126 |
+
height: auto;
|
127 |
+
outline: 0;
|
128 |
+
border: 1px solid #aaa;
|
129 |
+
background: white url('../images/chosen-sprite.png') no-repeat 100% -20px;
|
130 |
+
background: url('../images/chosen-sprite.png') no-repeat 100% -20px;
|
131 |
+
font-size: 1em;
|
132 |
+
font-family: sans-serif;
|
133 |
+
line-height: normal;
|
134 |
+
border-radius: 0;
|
135 |
+
}
|
136 |
+
.chosen-container-single .chosen-drop {
|
137 |
+
margin-top: -1px;
|
138 |
+
border-radius: 0 0 4px 4px;
|
139 |
+
background-clip: padding-box;
|
140 |
+
}
|
141 |
+
.chosen-container-single.chosen-container-single-nosearch .chosen-search {
|
142 |
+
position: absolute;
|
143 |
+
left: -9999px;
|
144 |
+
}
|
145 |
+
|
146 |
+
/* @end */
|
147 |
+
/* @group Results */
|
148 |
+
.chosen-container .chosen-results {
|
149 |
+
position: relative;
|
150 |
+
overflow-x: hidden;
|
151 |
+
overflow-y: auto;
|
152 |
+
margin: 0 4px 4px 0;
|
153 |
+
padding: 0 0 0 4px;
|
154 |
+
max-height: 240px;
|
155 |
+
-webkit-overflow-scrolling: touch;
|
156 |
+
}
|
157 |
+
.chosen-container .chosen-results li {
|
158 |
+
display: none;
|
159 |
+
margin: 0;
|
160 |
+
padding: 5px 6px;
|
161 |
+
list-style: none;
|
162 |
+
line-height: 15px;
|
163 |
+
-webkit-touch-callout: none;
|
164 |
+
}
|
165 |
+
.chosen-container .chosen-results li.active-result {
|
166 |
+
display: list-item;
|
167 |
+
cursor: pointer;
|
168 |
+
}
|
169 |
+
.chosen-container .chosen-results li.disabled-result {
|
170 |
+
display: list-item;
|
171 |
+
color: #ccc;
|
172 |
+
cursor: default;
|
173 |
+
}
|
174 |
+
.chosen-container .chosen-results li.highlighted {
|
175 |
+
background-color: #3875d7;
|
176 |
+
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
|
177 |
+
background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%);
|
178 |
+
background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%);
|
179 |
+
background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%);
|
180 |
+
background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
|
181 |
+
color: #fff;
|
182 |
+
}
|
183 |
+
.chosen-container .chosen-results li.no-results {
|
184 |
+
display: list-item;
|
185 |
+
background: #f4f4f4;
|
186 |
+
}
|
187 |
+
.chosen-container .chosen-results li.group-result {
|
188 |
+
display: list-item;
|
189 |
+
font-weight: bold;
|
190 |
+
cursor: default;
|
191 |
+
}
|
192 |
+
.chosen-container .chosen-results li.group-option {
|
193 |
+
padding-left: 15px;
|
194 |
+
}
|
195 |
+
.chosen-container .chosen-results li em {
|
196 |
+
font-style: normal;
|
197 |
+
text-decoration: underline;
|
198 |
+
}
|
199 |
+
|
200 |
+
/* @end */
|
201 |
+
/* @group Multi Chosen */
|
202 |
+
.chosen-container-multi .chosen-choices {
|
203 |
+
position: relative;
|
204 |
+
overflow: hidden;
|
205 |
+
-webkit-box-sizing: border-box;
|
206 |
+
-moz-box-sizing: border-box;
|
207 |
+
box-sizing: border-box;
|
208 |
+
margin: 0;
|
209 |
+
padding: 0;
|
210 |
+
width: 100%;
|
211 |
+
height: auto !important;
|
212 |
+
height: 1%;
|
213 |
+
border: 1px solid #aaa;
|
214 |
+
background-color: #fff;
|
215 |
+
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
|
216 |
+
background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
|
217 |
+
background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
|
218 |
+
background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
|
219 |
+
background-image: linear-gradient(#eeeeee 1%, #ffffff 15%);
|
220 |
+
cursor: text;
|
221 |
+
}
|
222 |
+
.chosen-container-multi .chosen-choices li {
|
223 |
+
float: left;
|
224 |
+
list-style: none;
|
225 |
+
}
|
226 |
+
.chosen-container-multi .chosen-choices li.search-field {
|
227 |
+
margin: 0;
|
228 |
+
padding: 0;
|
229 |
+
white-space: nowrap;
|
230 |
+
}
|
231 |
+
.chosen-container-multi .chosen-choices li.search-field input[type="text"] {
|
232 |
+
margin: 1px 0;
|
233 |
+
padding: 5px;
|
234 |
+
height: auto;
|
235 |
+
outline: 0;
|
236 |
+
border: 0 !important;
|
237 |
+
background: transparent !important;
|
238 |
+
box-shadow: none;
|
239 |
+
color: #666;
|
240 |
+
font-size: 100%;
|
241 |
+
font-family: sans-serif;
|
242 |
+
line-height: normal;
|
243 |
+
border-radius: 0;
|
244 |
+
}
|
245 |
+
.chosen-container-multi .chosen-choices li.search-field .default {
|
246 |
+
color: #999;
|
247 |
+
}
|
248 |
+
.chosen-container-multi .chosen-choices li.search-choice {
|
249 |
+
position: relative;
|
250 |
+
margin: 3px 0 3px 5px;
|
251 |
+
padding: 3px 20px 3px 5px;
|
252 |
+
border: 1px solid #aaa;
|
253 |
+
border-radius: 3px;
|
254 |
+
background-color: #e4e4e4;
|
255 |
+
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
|
256 |
+
background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
257 |
+
background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
258 |
+
background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
259 |
+
background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
260 |
+
background-clip: padding-box;
|
261 |
+
box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05);
|
262 |
+
color: #333;
|
263 |
+
line-height: 13px;
|
264 |
+
cursor: default;
|
265 |
+
}
|
266 |
+
.chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
|
267 |
+
position: absolute;
|
268 |
+
top: 4px;
|
269 |
+
right: 3px;
|
270 |
+
display: block;
|
271 |
+
width: 12px;
|
272 |
+
height: 12px;
|
273 |
+
background: url('../images/chosen-sprite.png') -42px 1px no-repeat;
|
274 |
+
font-size: 1px;
|
275 |
+
}
|
276 |
+
.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
|
277 |
+
background-position: -42px -10px;
|
278 |
+
}
|
279 |
+
.chosen-container-multi .chosen-choices li.search-choice-disabled {
|
280 |
+
padding-right: 5px;
|
281 |
+
border: 1px solid #ccc;
|
282 |
+
background-color: #e4e4e4;
|
283 |
+
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
|
284 |
+
background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
285 |
+
background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
286 |
+
background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
287 |
+
background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
288 |
+
color: #666;
|
289 |
+
}
|
290 |
+
.chosen-container-multi .chosen-choices li.search-choice-focus {
|
291 |
+
background: #d4d4d4;
|
292 |
+
}
|
293 |
+
.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close {
|
294 |
+
background-position: -42px -10px;
|
295 |
+
}
|
296 |
+
.chosen-container-multi .chosen-results {
|
297 |
+
margin: 0;
|
298 |
+
padding: 0;
|
299 |
+
}
|
300 |
+
.chosen-container-multi .chosen-drop .result-selected {
|
301 |
+
display: list-item;
|
302 |
+
color: #ccc;
|
303 |
+
cursor: default;
|
304 |
+
}
|
305 |
+
|
306 |
+
/* @end */
|
307 |
+
/* @group Active */
|
308 |
+
.chosen-container-active .chosen-single {
|
309 |
+
border: 1px solid #5897fb;
|
310 |
+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
311 |
+
}
|
312 |
+
.chosen-container-active.chosen-with-drop .chosen-single {
|
313 |
+
border: 1px solid #aaa;
|
314 |
+
-moz-border-radius-bottomright: 0;
|
315 |
+
border-bottom-right-radius: 0;
|
316 |
+
-moz-border-radius-bottomleft: 0;
|
317 |
+
border-bottom-left-radius: 0;
|
318 |
+
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff));
|
319 |
+
background-image: -webkit-linear-gradient(#eeeeee 20%, #ffffff 80%);
|
320 |
+
background-image: -moz-linear-gradient(#eeeeee 20%, #ffffff 80%);
|
321 |
+
background-image: -o-linear-gradient(#eeeeee 20%, #ffffff 80%);
|
322 |
+
background-image: linear-gradient(#eeeeee 20%, #ffffff 80%);
|
323 |
+
box-shadow: 0 1px 0 #fff inset;
|
324 |
+
}
|
325 |
+
.chosen-container-active.chosen-with-drop .chosen-single div {
|
326 |
+
border-left: none;
|
327 |
+
background: transparent;
|
328 |
+
}
|
329 |
+
.chosen-container-active.chosen-with-drop .chosen-single div b {
|
330 |
+
background-position: -18px 2px;
|
331 |
+
}
|
332 |
+
.chosen-container-active .chosen-choices {
|
333 |
+
border: 1px solid #5897fb;
|
334 |
+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
335 |
+
}
|
336 |
+
.chosen-container-active .chosen-choices li.search-field input[type="text"] {
|
337 |
+
color: #111 !important;
|
338 |
+
}
|
339 |
+
|
340 |
+
/* @end */
|
341 |
+
/* @group Disabled Support */
|
342 |
+
.chosen-disabled {
|
343 |
+
opacity: 0.5 !important;
|
344 |
+
cursor: default;
|
345 |
+
}
|
346 |
+
.chosen-disabled .chosen-single {
|
347 |
+
cursor: default;
|
348 |
+
}
|
349 |
+
.chosen-disabled .chosen-choices .search-choice .search-choice-close {
|
350 |
+
cursor: default;
|
351 |
+
}
|
352 |
+
|
353 |
+
/* @end */
|
354 |
+
/* @group Right to Left */
|
355 |
+
.chosen-rtl {
|
356 |
+
text-align: right;
|
357 |
+
}
|
358 |
+
.chosen-rtl .chosen-single {
|
359 |
+
overflow: visible;
|
360 |
+
padding: 0 8px 0 0;
|
361 |
+
}
|
362 |
+
.chosen-rtl .chosen-single span {
|
363 |
+
margin-right: 0;
|
364 |
+
margin-left: 26px;
|
365 |
+
direction: rtl;
|
366 |
+
}
|
367 |
+
.chosen-rtl .chosen-single-with-deselect span {
|
368 |
+
margin-left: 38px;
|
369 |
+
}
|
370 |
+
.chosen-rtl .chosen-single div {
|
371 |
+
right: auto;
|
372 |
+
left: 3px;
|
373 |
+
}
|
374 |
+
.chosen-rtl .chosen-single abbr {
|
375 |
+
right: auto;
|
376 |
+
left: 26px;
|
377 |
+
}
|
378 |
+
.chosen-rtl .chosen-choices li {
|
379 |
+
float: right;
|
380 |
+
}
|
381 |
+
.chosen-rtl .chosen-choices li.search-field input[type="text"] {
|
382 |
+
direction: rtl;
|
383 |
+
}
|
384 |
+
.chosen-rtl .chosen-choices li.search-choice {
|
385 |
+
margin: 3px 5px 3px 0;
|
386 |
+
padding: 3px 5px 3px 19px;
|
387 |
+
}
|
388 |
+
.chosen-rtl .chosen-choices li.search-choice .search-choice-close {
|
389 |
+
right: auto;
|
390 |
+
left: 4px;
|
391 |
+
}
|
392 |
+
.chosen-rtl.chosen-container-single-nosearch .chosen-search,
|
393 |
+
.chosen-rtl .chosen-drop {
|
394 |
+
left: 9999px;
|
395 |
+
}
|
396 |
+
.chosen-rtl.chosen-container-single .chosen-results {
|
397 |
+
margin: 0 0 4px 4px;
|
398 |
+
padding: 0 4px 0 0;
|
399 |
+
}
|
400 |
+
.chosen-rtl .chosen-results li.group-option {
|
401 |
+
padding-right: 15px;
|
402 |
+
padding-left: 0;
|
403 |
+
}
|
404 |
+
.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div {
|
405 |
+
border-right: none;
|
406 |
+
}
|
407 |
+
.chosen-rtl .chosen-search input[type="text"] {
|
408 |
+
padding: 4px 5px 4px 20px;
|
409 |
+
background: white url('../images/chosen-sprite.png') no-repeat -30px -20px;
|
410 |
+
background: url('../images/chosen-sprite.png') no-repeat -30px -20px;
|
411 |
+
direction: rtl;
|
412 |
+
}
|
413 |
+
.chosen-rtl.chosen-container-single .chosen-single div b {
|
414 |
+
background-position: 6px 2px;
|
415 |
+
}
|
416 |
+
.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b {
|
417 |
+
background-position: -12px 2px;
|
418 |
+
}
|
419 |
+
|
420 |
+
/* @end */
|
421 |
+
/* @group Retina compatibility */
|
422 |
+
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) {
|
423 |
+
.chosen-rtl .chosen-search input[type="text"],
|
424 |
+
.chosen-container-single .chosen-single abbr,
|
425 |
+
.chosen-container-single .chosen-single div b,
|
426 |
+
.chosen-container-single .chosen-search input[type="text"],
|
427 |
+
.chosen-container-multi .chosen-choices .search-choice .search-choice-close,
|
428 |
+
.chosen-container .chosen-results-scroll-down span,
|
429 |
+
.chosen-container .chosen-results-scroll-up span {
|
430 |
+
background-image: url('../images/chosen-sprite@2x.png') !important;
|
431 |
+
background-size: 52px 37px !important;
|
432 |
+
background-repeat: no-repeat !important;
|
433 |
+
}
|
434 |
+
}
|
435 |
+
/* @end */
|
assets/css/frontend.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
.clearfix{zoom:1}.clearfix:after,.clearfix:before{content:"";display:table}.clearfix:after{clear:both}@font-face{font-family:job-manager;src:url(../font/job-manager.eot?4963673);src:url(../font/job-manager.eot?4963673#iefix) format('embedded-opentype'),url(../font/job-manager.woff?4963673) format('woff'),url(../font/job-manager.ttf?4963673) format('truetype'),url(../font/job-manager.svg?4963673#job-manager) format('svg');font-weight:400;font-style:normal}@font-face{font-family:jm-logo;src:url(../font/jm-logo/jm.eot?ycsbky);src:url(../font/jm-logo/jm.eot?#iefixycsbky) format('embedded-opentype'),url(../font/jm-logo/jm.woff?ycsbky) format('woff'),url(../font/jm-logo/jm.ttf?ycsbky) format('truetype'),url(../font/jm-logo/jm.svg?ycsbky#icomoon) format('svg');font-weight:400;font-style:normal}.jm-icon{font-family:job-manager!important;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;text-align:center;font-variant:normal;text-transform:none;line-height:1em}.rp4wp-related-job_listing>ul,ul.job_listings{padding:0;margin:0;border-top:1px solid #eee}.rp4wp-related-job_listing>ul.loading,ul.job_listings.loading{min-height:96px;border-bottom:1px solid #eee;background:url(../images/ajax-loader.gif) no-repeat center 32px}.rp4wp-related-job_listing>ul li.job_listing,.rp4wp-related-job_listing>ul li.no_job_listings_found,ul.job_listings li.job_listing,ul.job_listings li.no_job_listings_found{list-style:none outside;padding:0;margin:0;border-bottom:1px solid #eee}.rp4wp-related-job_listing>ul li.job_listing.job_position_filled a,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_filled a,ul.job_listings li.job_listing.job_position_filled a,ul.job_listings li.no_job_listings_found.job_position_filled a{opacity:.25}.rp4wp-related-job_listing>ul li.job_listing.no_job_listings_found,.rp4wp-related-job_listing>ul li.no_job_listings_found.no_job_listings_found,ul.job_listings li.job_listing.no_job_listings_found,ul.job_listings li.no_job_listings_found.no_job_listings_found{padding:1em;border-bottom:1px solid #eee}.rp4wp-related-job_listing>ul li.job_listing a,.rp4wp-related-job_listing>ul li.no_job_listings_found a,ul.job_listings li.job_listing a,ul.job_listings li.no_job_listings_found a{display:block;padding:1em 1em 1em 2em;border:0;overflow:hidden;zoom:1;position:relative;line-height:1.5em;text-decoration:none}.rp4wp-related-job_listing>ul li.job_listing a:focus,.rp4wp-related-job_listing>ul li.job_listing a:hover,.rp4wp-related-job_listing>ul li.no_job_listings_found a:focus,.rp4wp-related-job_listing>ul li.no_job_listings_found a:hover,ul.job_listings li.job_listing a:focus,ul.job_listings li.job_listing a:hover,ul.job_listings li.no_job_listings_found a:focus,ul.job_listings li.no_job_listings_found a:hover{background-color:#fcfcfc}.rp4wp-related-job_listing>ul li.job_listing a img.company_logo,.rp4wp-related-job_listing>ul li.no_job_listings_found a img.company_logo,ul.job_listings li.job_listing a img.company_logo,ul.job_listings li.no_job_listings_found a img.company_logo{width:42px;height:42px;position:absolute;left:1em;float:left;margin-right:1em;vertical-align:middle;box-shadow:none}.rp4wp-related-job_listing>ul li.job_listing a div.location,.rp4wp-related-job_listing>ul li.job_listing a div.position,.rp4wp-related-job_listing>ul li.job_listing a ul.meta,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.location,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position,.rp4wp-related-job_listing>ul li.no_job_listings_found a ul.meta,ul.job_listings li.job_listing a div.location,ul.job_listings li.job_listing a div.position,ul.job_listings li.job_listing a ul.meta,ul.job_listings li.no_job_listings_found a div.location,ul.job_listings li.no_job_listings_found a div.position,ul.job_listings li.no_job_listings_found a ul.meta{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.rp4wp-related-job_listing>ul li.job_listing a div.position,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position,ul.job_listings li.job_listing a div.position,ul.job_listings li.no_job_listings_found a div.position{float:left;width:55%;padding:0 0 0 42px;line-height:1.5em}.rp4wp-related-job_listing>ul li.job_listing a div.position h3,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position h3,ul.job_listings li.job_listing a div.position h3,ul.job_listings li.no_job_listings_found a div.position h3{margin:0;padding:0;line-height:inherit;font-size:inherit}.rp4wp-related-job_listing>ul li.job_listing a div.position .company,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position .company,ul.job_listings li.job_listing a div.position .company,ul.job_listings li.no_job_listings_found a div.position .company{color:#999}.rp4wp-related-job_listing>ul li.job_listing a div.position .company .tagline,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position .company .tagline,ul.job_listings li.job_listing a div.position .company .tagline,ul.job_listings li.no_job_listings_found a div.position .company .tagline{margin-left:.5em}.rp4wp-related-job_listing>ul li.job_listing a div.location,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.location,ul.job_listings li.job_listing a div.location,ul.job_listings li.no_job_listings_found a div.location{float:left;text-align:left;width:25%;padding:0 0 0 1em;color:#999;line-height:1.5em}.rp4wp-related-job_listing>ul li.job_listing a .meta,.rp4wp-related-job_listing>ul li.no_job_listings_found a .meta,ul.job_listings li.job_listing a .meta,ul.job_listings li.no_job_listings_found a .meta{float:right;text-align:right;width:20%;padding:0 0 0 1em;margin:0;line-height:1.5em;color:#999;list-style:none outside}.rp4wp-related-job_listing>ul li.job_listing a .meta li,.rp4wp-related-job_listing>ul li.no_job_listings_found a .meta li,ul.job_listings li.job_listing a .meta li,ul.job_listings li.no_job_listings_found a .meta li{list-style:none outside;display:block;margin:0}.rp4wp-related-job_listing>ul li.job_listing a .meta .job-type,.rp4wp-related-job_listing>ul li.no_job_listings_found a .meta .job-type,ul.job_listings li.job_listing a .meta .job-type,ul.job_listings li.no_job_listings_found a .meta .job-type{font-weight:700}.rp4wp-related-job_listing>ul li.job_listing.job_position_featured a,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_featured a,ul.job_listings li.job_listing.job_position_featured a,ul.job_listings li.no_job_listings_found.job_position_featured a{background:#fefee5}.rp4wp-related-job_listing>ul li.job_listing.job_position_featured a:focus,.rp4wp-related-job_listing>ul li.job_listing.job_position_featured a:hover,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_featured a:focus,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_featured a:hover,ul.job_listings li.job_listing.job_position_featured a:focus,ul.job_listings li.job_listing.job_position_featured a:hover,ul.job_listings li.no_job_listings_found.job_position_featured a:focus,ul.job_listings li.no_job_listings_found.job_position_featured a:hover{background-color:#fefed8}.widget ul.job_listings li.job_listing a{padding:1em 0}.widget ul.job_listings li.job_listing .image{float:left}.widget ul.job_listings li.job_listing .image img{left:0;position:relative}.widget ul.job_listings li.job_listing .content{overflow:hidden}.widget ul.job_listings li.job_listing .position{float:none;width:auto;padding:0}.widget ul.job_listings li.job_listing ul.meta{float:none;width:auto;padding:0;margin:0;text-align:left}.widget ul.job_listings li.job_listing ul.meta li{float:none;display:inline;padding:0;margin:0 .5em 0 0;font-weight:400}.widget ul.job_listings li.job_listing ul.meta li:after{padding:0 0 0 .5em;content:"\2023"}.widget ul.job_listings li.job_listing ul.meta li:last-child:after{content:''}.job-manager .job-type,.job-types .job-type,.job_listing .job-type{color:#f08d3c}.job-manager .full-time,.job-types .full-time,.job_listing .full-time{color:#90da36}.job-manager .part-time,.job-types .part-time,.job_listing .part-time{color:#f08d3c}.job-manager .temporary,.job-types .temporary,.job_listing .temporary{color:#d93674}.job-manager .freelance,.job-types .freelance,.job_listing .freelance{color:#39c}.job-manager .internship,.job-types .internship,.job_listing .internship{color:#6033cc}@media only screen and (max-width:767px){ul.job_listings li.job_listing a,ul.job_listings li.no_job_listings_found a{padding:1em}ul.job_listings li.job_listing a img.company_logo,ul.job_listings li.no_job_listings_found a img.company_logo{visibility:hidden}ul.job_listings li.job_listing a div.position,ul.job_listings li.no_job_listings_found a div.position{float:left;width:60%;padding:0}ul.job_listings li.job_listing a div.location,ul.job_listings li.no_job_listings_found a div.location{float:right;width:40%;line-height:2em;font-size:.75em;padding:0 0 0 1em;text-align:right}ul.job_listings li.job_listing a .meta,ul.job_listings li.no_job_listings_found a .meta{float:right;width:40%;line-height:2em;font-size:.75em}ul.job_listings li.job_listing a .meta li,ul.job_listings li.no_job_listings_found a .meta li{font-size:1em}}.twenty-eleven ul.job_listings li.job_listing,.twenty-eleven ul.job_listings li.no_job_listings_found{padding:0!important}.display-icon{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0}.job-manager-error,.job-manager-info,.job-manager-message{padding:1em 2em 1em 3.5em!important;margin:0 0 2em!important;position:relative;background-color:#fff;color:#666;border-top:3px solid #999;list-style:none outside!important;width:auto;zoom:1;box-shadow:0 1px 1px rgba(0,0,0,.2)}.job-manager-error:after,.job-manager-error:before,.job-manager-info:after,.job-manager-info:before,.job-manager-message:after,.job-manager-message:before{content:"";display:table}.job-manager-error:after,.job-manager-info:after,.job-manager-message:after{clear:both}.job-manager-error:before,.job-manager-info:before,.job-manager-message:before{content:"";font-family:sans-serif;display:inline-block;position:absolute;top:1em;left:1.5em}.job-manager-error li,.job-manager-info li,.job-manager-message li{list-style:none outside!important;padding-left:0!important;margin-left:0!important}.job-manager-error.job-manager-message,.job-manager-info.job-manager-message,.job-manager-message.job-manager-message{border-top-color:#8fae1b}.job-manager-error.job-manager-message:before,.job-manager-info.job-manager-message:before,.job-manager-message.job-manager-message:before{color:#8fae1b;content:"\2713"}.job-manager-error.job-manager-info,.job-manager-info.job-manager-info,.job-manager-message.job-manager-info{border-top-color:#1e85be}.job-manager-error.job-manager-info:before,.job-manager-info.job-manager-info:before,.job-manager-message.job-manager-info:before{color:#1e85be;content:"i";font-family:Times,Georgia,serif;font-style:italic}.job-manager-error.job-manager-error,.job-manager-info.job-manager-error,.job-manager-message.job-manager-error{border-top-color:#b81c23}.job-manager-error.job-manager-error:before,.job-manager-info.job-manager-error:before,.job-manager-message.job-manager-error:before{color:#b81c23;content:"\00d7";font-weight:700}.job-manager-form fieldset{margin:0 0 1em 0;padding:0 0 1em 0;line-height:2em;border:0;border-bottom:1px solid #eee;zoom:1}.job-manager-form fieldset:after,.job-manager-form fieldset:before{content:"";display:table}.job-manager-form fieldset:after{clear:both}.job-manager-form fieldset label{display:block;margin:0;width:29%;float:left;vertical-align:middle}.job-manager-form fieldset label small{opacity:.75;font-size:.83em}.job-manager-form fieldset div.field{width:70%;float:right;vertical-align:middle}.job-manager-form fieldset .wp-editor-container{border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.job-manager-form fieldset .account-sign-in .button{margin-right:.5em}.job-manager-form fieldset .account-sign-in .button:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;content:'\e808'}.job-manager-form fieldset abbr.required{color:red;font-weight:700;border:0}.job-manager-form fieldset input.input-text,.job-manager-form fieldset select,.job-manager-form fieldset textarea{margin:0;vertical-align:middle;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.job-manager-form fieldset small.description{opacity:.75;font-size:.83em;margin:1.2em 0 0 0;display:block;line-height:1.2em}.job-manager-form fieldset .job-manager-uploaded-files{display:table}.job-manager-form fieldset .job-manager-uploaded-files .job-manager-uploaded-file{line-height:2em;font-style:italic;margin-bottom:1em;display:block}.job-manager-form fieldset .job-manager-uploaded-files .job-manager-uploaded-file .job-manager-uploaded-file-preview img{height:64px;margin:0;vertical-align:top}.job-manager-form fieldset .job-manager-uploaded-files .job-manager-uploaded-file .job-manager-uploaded-file-preview a{line-height:64px;display:inline-block;padding:0 0 0 1em}.job-manager-form fieldset .job-manager-uploaded-files .job-manager-uploaded-file .job-manager-uploaded-file-name{display:block}.job-manager-form .submit-job{padding:1em 0}.job-manager-form .job-manager-term-checklist{list-style:none outside;max-height:200px;overflow:auto;margin:0}.job-manager-form .job-manager-term-checklist li{list-style:none outside;margin:0;display:block;float:none}.job-manager-form .job-manager-term-checklist li label{width:auto;float:none}.job-manager-form .job-manager-term-checklist li li{margin:0 0 0 2em}.job-manager-form input[type=submit].disabled,.job-manager-form input[type=submit]:disabled{opacity:.5;cursor:not-allowed}.job-manager-form .spinner{background:url(../../../../../wp-includes/images/spinner.gif) no-repeat;background-size:20px 20px;display:inline-block;visibility:hidden;width:20px;height:20px;margin:0;vertical-align:middle}.job-manager-form .spinner.is-active{visibility:visible}div.job_listings{margin-bottom:1em}div.job_listings ul.job_listings{margin:0}.single_job_listing .company{position:relative;border:1px solid #eee;padding:1em;margin:0 0 2em;display:block;clear:both;min-height:3em;box-shadow:0 1px 1px rgba(0,0,0,.1)}.single_job_listing .company img{width:3em;height:3em;position:absolute;left:1em;float:left;vertical-align:middle;box-shadow:none}.single_job_listing .company .name{margin:0 0 0 3em;padding:0 0 0 1em;line-height:1.5em}.single_job_listing .company .name a{float:right;margin-left:1em}.single_job_listing .company .tagline{display:block;margin:0 0 0 42px;padding:0 0 0 1em;line-height:1.5em;font-style:italic;color:#999}.single_job_listing .company .website:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;content:'\e809'}.single_job_listing .company .company_twitter:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;content:'\e80a'}.single_job_listing .company .company_video{border-top:1px solid #eee;padding:1em 0 0;margin:1em 0 0 0;position:relative;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden}.single_job_listing .company .company_video embed,.single_job_listing .company .company_video iframe,.single_job_listing .company .company_video object{position:absolute;top:0;left:0;width:100%;height:100%;margin:0;display:block}.single_job_listing .meta{list-style:none outside;padding:0;margin:0 0 1.5em;overflow:hidden;zoom:1;clear:both}.single_job_listing .meta li{margin:0 1em 0 0;padding:.5em;float:left;line-height:1em;color:#999}.single_job_listing .meta .job-type{color:#fff;background-color:#f08d3c}.single_job_listing .meta .full-time{background-color:#90da36}.single_job_listing .meta .part-time{background-color:#f08d3c}.single_job_listing .meta .temporary{background-color:#d93674}.single_job_listing .meta .freelance{background-color:#39c}.single_job_listing .meta .internship{background-color:#6033cc}.single_job_listing .meta .listing-expired,.single_job_listing .meta .position-filled{color:#b81c23}.single_job_listing .meta .location:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;content:'\e81d'}.single_job_listing .meta .date-posted:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;content:'\e80f'}.single_job_listing .meta .listing-expired:before,.single_job_listing .meta .position-filled:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;content:'\e80e'}.single_job_listing .job_description{margin:0 0 1.5em}.job-manager-application-wrapper{clear:both;border:1px solid #eee;padding:.75em 1em 0;margin:1em 0;line-height:1.5em;display:block;position:relative;box-shadow:0 1px 1px rgba(0,0,0,.1)}.job-manager-application-wrapper .application,.single_job_listing .application{padding:0;margin:0 0 1em;overflow:hidden}.job-manager-application-wrapper .application .application_button,.job-manager-application-wrapper .application .application_details,.single_job_listing .application .application_button,.single_job_listing .application .application_details{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.job-manager-application-wrapper .application .application_button,.single_job_listing .application .application_button{text-align:center;font-size:1.1em;line-height:1em;display:inline-block;margin:0 .5em 0 0;padding:.90909091em 2em;outline:0}.job-manager-application-wrapper .application .application_details,.single_job_listing .application .application_details{clear:both;border:1px solid #eee;padding:.75em 1em 0;margin:1em 0;line-height:1.5em;display:block;position:relative;box-shadow:0 1px 1px rgba(0,0,0,.1)}.job-manager-application-wrapper .application .application_details p,.single_job_listing .application .application_details p{margin:0 0 .75em}.job-manager-application-wrapper .application .application_details:before,.single_job_listing .application .application_details:before{content:"";position:absolute;margin:-10px 0 0 0;top:0;left:5em;width:0;height:0;border-left:10px solid transparent;border-right:10px solid transparent;border-bottom:10px solid #eee}.job-manager-application-wrapper .application .application_details:after,.single_job_listing .application .application_details:after{content:"";position:absolute;margin:-9px 0 0 1px;left:5em;top:0;width:0;height:0;border-left:9px solid transparent;border-right:9px solid transparent;border-bottom:9px solid #fff}.job_filters{background:#eee;zoom:1}.job_filters:after,.job_filters:before{content:"";display:table}.job_filters:after{clear:both}.job_filters .search_jobs{padding:1em;zoom:1}.job_filters .search_jobs:after,.job_filters .search_jobs:before{content:"";display:table}.job_filters .search_jobs:after{clear:both}.job_filters .search_jobs div{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.job_filters .search_jobs div label{display:none}.job_filters .search_jobs div.filter_first,.job_filters .search_jobs div.search_keywords{float:left;padding-right:.5em;width:50%}.job_filters .search_jobs div.filter_last,.job_filters .search_jobs div.search_location{float:right;padding-left:.5em;width:50%}.job_filters .search_jobs div.filter_wide,.job_filters .search_jobs div.search_categories{padding-top:.5em;clear:both;width:100%}.job_filters .search_jobs div .showing_jobs a{padding:.25em}.job_filters .search_jobs div .showing_jobs a.active{background:#ddd;text-decoration:none}.job_filters .search_jobs input,.job_filters .search_jobs select{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%}.job_filters .job_types{list-style:none outside;margin:0;padding:0;font-size:.83em;background:#f9f9f9;border-top:1px solid #e5e5e5;zoom:1}.job_filters .job_types:after,.job_filters .job_types:before{content:"";display:table}.job_filters .job_types:after{clear:both}.job_filters .job_types li{margin:0;padding:.5em 1em;float:left;border-right:1px solid #eee}.job_filters .job_types li:last-child{border-right:0}.job_filters .showing_jobs{padding:.5em 1em;display:none;font-size:.83em;background:#f9f9f9;border-top:1px solid #e5e5e5}.job_filters .showing_jobs a{float:right;padding-left:10px;border:0}div.job_listings .job-manager-pagination{text-align:center;display:block;padding:1em 0 1em 0;border-bottom:1px solid #eee;line-height:1}div.job_listings .load_previous{border-top:1px solid #eee}div.job_listings .load_more_jobs+ul.job_listings{border-top:0}div.job_listings .load_more_jobs{text-align:center;display:block;padding:1em 1em 1em 2em;border-bottom:1px solid #eee;font-weight:700}div.job_listings .load_more_jobs.loading{background:url(../images/ajax-loader.gif) no-repeat center}div.job_listings .load_more_jobs.loading strong{visibility:hidden}div.job_listings .load_more_jobs:focus,div.job_listings .load_more_jobs:hover{background-color:#fcfcfc;border-bottom:1px solid #eee}.job_listing_preview{padding:0 1em 1em;border:5px solid #eee}.single-job_listing .entry-header .attachment-post-thumbnail,.single-job_listing .job_listing.has-post-thumbnail .post-thumbnail{display:none}.entry-content .job_listing_preview_title,.job_listing_preview_title{padding:.5em 1em;vertical-align:middle;position:relative;background:#eee}.entry-content .job_listing_preview_title h2,.job_listing_preview_title h2{margin:0;clear:none}.entry-content .job_listing_preview_title .button,.job_listing_preview_title .button{float:right;margin-left:.25em}.job_summary_shortcode{border:1px solid #ccc;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;text-align:center;position:relative;box-shadow:0 2px 4px rgba(0,0,0,.1),inset 0 1px 0 rgba(255,255,255,.4);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.job_summary_shortcode.aligncenter{display:block;margin:2em auto 2em}.job_summary_shortcode.alignleft{float:left;margin:0 2em 2em 0}.job_summary_shortcode.alignright{float:right;margin:0 0 2em 2em}.job_summary_shortcode a{text-decoration:none;color:inherit}.job_summary_shortcode img{margin:0;padding:0;display:block;width:100%;-moz-border-radius:0;-webkit-border-radius:0;-moz-border-top-left-radius:3px;-moz-border-top-right-radius:3px;-webkit-border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-radius:0;border-top-left-radius:3px;border-top-right-radius:3px;box-shadow:inset 0 1px 0 rgba(255,255,255,.4)}.job_summary_shortcode .job_summary_content{padding:0 1em}.job_summary_shortcode .meta{font-style:italic;color:#777}.job_summary_shortcode .job-type{-moz-border-radius:1em;-webkit-border-radius:1em;border-radius:1em;color:#fff;text-shadow:0 1px 0 rgba(255,255,255,.5);box-shadow:0 2px 4px rgba(0,0,0,.1),inset 0 1px 0 rgba(255,255,255,.4);position:absolute;top:0;right:0;padding:.5em;height:1em;width:auto;min-width:1em;font-size:1em;text-align:center;vertical-align:middle;line-height:1em;margin:-.5em -.5em 0 0}.job_summary_shortcode .job-type.full-time{background-color:#90da36}.job_summary_shortcode .job-type.part-time{background-color:#f08d3c}.job_summary_shortcode .job-type.temporary{background-color:#d93674}.job_summary_shortcode .job-type.freelance{background-color:#39c}.job_summary_shortcode .job-type.internship{background-color:#6033cc}#job-manager-job-dashboard .account-sign-in .button{margin-right:.5em}#job-manager-job-dashboard .account-sign-in .button:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;content:'\e808'}#job-manager-job-dashboard table ul.job-dashboard-actions{margin:0;padding:0;visibility:hidden;font-size:.92em}#job-manager-job-dashboard table ul.job-dashboard-actions li{float:none;display:inline;padding:0;margin:0 .5em 0 0;font-weight:400;list-style:none outside}#job-manager-job-dashboard table ul.job-dashboard-actions li:after{padding:0 0 0 .5em;content:"\2023"}#job-manager-job-dashboard table ul.job-dashboard-actions li:last-child:after{content:''}#job-manager-job-dashboard table ul.job-dashboard-actions li .job-dashboard-action-delete{color:red}#job-manager-job-dashboard table tr:focus ul.job-dashboard-actions,#job-manager-job-dashboard table tr:hover ul.job-dashboard-actions{visibility:visible}#job-manager-job-dashboard table td,#job-manager-job-dashboard table th{padding:.5em 1em .5em 0}#job-manager-job-dashboard table .job_title small{color:#999}#job-manager-job-dashboard table .featured-job-icon:before{content:'\e803';font-family:job-manager!important;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;text-align:center;font-variant:normal;text-transform:none;line-height:1em}#job-manager-job-dashboard table .applications,#job-manager-job-dashboard table .expires,#job-manager-job-dashboard table .filled{text-align:center}#content nav.job-manager-pagination,nav.job-manager-pagination{text-align:center}#content nav.job-manager-pagination ul,nav.job-manager-pagination ul{display:inline-block;white-space:nowrap;padding:0;clear:both;border-left:1px solid #eee;margin:1px}#content nav.job-manager-pagination ul li,nav.job-manager-pagination ul li{border-right:1px solid #eee;border-top:1px solid #eee;border-bottom:1px solid #eee;padding:0;margin:0;float:left;display:inline;overflow:hidden}#content nav.job-manager-pagination ul li a,#content nav.job-manager-pagination ul li span,nav.job-manager-pagination ul li a,nav.job-manager-pagination ul li span{margin:0;text-decoration:none;padding:0;line-height:1em;font-size:1em;font-weight:400;padding:.5em;min-width:1em;display:block;border:0}#content nav.job-manager-pagination ul li a:focus,#content nav.job-manager-pagination ul li a:hover,#content nav.job-manager-pagination ul li span.current,nav.job-manager-pagination ul li a:focus,nav.job-manager-pagination ul li a:hover,nav.job-manager-pagination ul li span.current{background:#eee;color:#888}.chosen-container{width:100%!important}.twenty-ten .chosen-choices,.twenty-ten .job_types{margin:0!important}.rtl .job-manager-form label{float:right}.rtl .job-manager-form div.field{float:left}.rtl .entry-content .job_listing_preview_title .button,.rtl .job_listing_preview_title .button{float:left}.rtl .single_job_listing .meta li{float:right;margin:0 0 0 1em}
|
1 |
+
.clearfix{zoom:1}.clearfix:after,.clearfix:before{content:"";display:table}.clearfix:after{clear:both}@font-face{font-family:job-manager;src:url(../font/job-manager.eot?4963673);src:url(../font/job-manager.eot?4963673#iefix) format('embedded-opentype'),url(../font/job-manager.woff?4963673) format('woff'),url(../font/job-manager.ttf?4963673) format('truetype'),url(../font/job-manager.svg?4963673#job-manager) format('svg');font-weight:400;font-style:normal}@font-face{font-family:jm-logo;src:url(../font/jm-logo/jm.eot?ycsbky);src:url(../font/jm-logo/jm.eot?#iefixycsbky) format('embedded-opentype'),url(../font/jm-logo/jm.woff?ycsbky) format('woff'),url(../font/jm-logo/jm.ttf?ycsbky) format('truetype'),url(../font/jm-logo/jm.svg?ycsbky#icomoon) format('svg');font-weight:400;font-style:normal}.jm-icon{font-family:job-manager!important;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;text-align:center;font-variant:normal;text-transform:none;line-height:1em}.display-icon{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;*overflow:auto;*zoom:1;*display:inline}.job-manager-error,.job-manager-info,.job-manager-message{padding:1em 2em 1em 3.5em!important;margin:0 0 2em!important;position:relative;background-color:#fff;color:#666;border-top:3px solid #999;list-style:none outside!important;width:auto;zoom:1;box-shadow:0 1px 1px rgba(0,0,0,.2)}.job-manager-error:after,.job-manager-error:before,.job-manager-info:after,.job-manager-info:before,.job-manager-message:after,.job-manager-message:before{content:"";display:table}.job-manager-error:after,.job-manager-info:after,.job-manager-message:after{clear:both}.job-manager-error:before,.job-manager-info:before,.job-manager-message:before{content:"";font-family:sans-serif;display:inline-block;position:absolute;top:1em;left:1.5em}.job-manager-error li,.job-manager-info li,.job-manager-message li{list-style:none outside!important;padding-left:0!important;margin-left:0!important}.job-manager-error.job-manager-message,.job-manager-info.job-manager-message,.job-manager-message.job-manager-message{border-top-color:#8fae1b}.job-manager-error.job-manager-message:before,.job-manager-info.job-manager-message:before,.job-manager-message.job-manager-message:before{color:#8fae1b;content:"\2713"}.job-manager-error.job-manager-info,.job-manager-info.job-manager-info,.job-manager-message.job-manager-info{border-top-color:#1e85be}.job-manager-error.job-manager-info:before,.job-manager-info.job-manager-info:before,.job-manager-message.job-manager-info:before{color:#1e85be;content:"i";font-family:Times,Georgia,serif;font-style:italic}.job-manager-error.job-manager-error,.job-manager-info.job-manager-error,.job-manager-message.job-manager-error{border-top-color:#b81c23}.job-manager-error.job-manager-error:before,.job-manager-info.job-manager-error:before,.job-manager-message.job-manager-error:before{color:#b81c23;content:"\00d7";font-weight:700}.job-manager-form fieldset{margin:0 0 1em;padding:0 0 1em;line-height:2em;border:0;border-bottom:1px solid #eee;zoom:1}.job-manager-form fieldset:after,.job-manager-form fieldset:before{content:"";display:table}.job-manager-form fieldset:after{clear:both}.job-manager-form fieldset label{display:block;margin:0;width:29%;float:left;vertical-align:middle}.job-manager-form fieldset label small{opacity:.75;font-size:.83em}.job-manager-form fieldset div.field{width:70%;float:right;vertical-align:middle}.job-manager-form fieldset .wp-editor-container{border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.job-manager-form fieldset .account-sign-in .button{margin-right:.5em}.job-manager-form fieldset .account-sign-in .button:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;*overflow:auto;*zoom:1;*display:inline;content:'\e808'}.job-manager-form fieldset abbr.required{color:red;font-weight:700;border:0}.job-manager-form fieldset input.input-text,.job-manager-form fieldset select,.job-manager-form fieldset textarea{margin:0;vertical-align:middle;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.job-manager-form fieldset small.description{opacity:.75;font-size:.83em;margin:1.2em 0 0;display:block;line-height:1.2em}.job-manager-form fieldset .job-manager-uploaded-files{display:table}.job-manager-form fieldset .job-manager-uploaded-files .job-manager-uploaded-file{line-height:2em;font-style:italic;margin-bottom:1em;display:block}.job-manager-form fieldset .job-manager-uploaded-files .job-manager-uploaded-file .job-manager-uploaded-file-preview img{height:64px;margin:0;vertical-align:top}.job-manager-form fieldset .job-manager-uploaded-files .job-manager-uploaded-file .job-manager-uploaded-file-preview a{line-height:64px;display:inline-block;padding:0 0 0 1em}.job-manager-form fieldset .job-manager-uploaded-files .job-manager-uploaded-file .job-manager-uploaded-file-name{display:block}.job-manager-form .submit-job{padding:1em 0}.job-manager-form .job-manager-term-checklist{list-style:none outside;max-height:200px;overflow:auto;margin:0}.job-manager-form .job-manager-term-checklist li{list-style:none outside;margin:0;display:block;float:none}.job-manager-form .job-manager-term-checklist li label{width:auto;float:none}.job-manager-form .job-manager-term-checklist li li{margin:0 0 0 2em}div.job_listings{margin-bottom:1em}div.job_listings ul.job_listings{margin:0}.rp4wp-related-job_listing>ul,ul.job_listings{padding:0;margin:0;border-top:1px solid #eee}.rp4wp-related-job_listing>ul.loading,ul.job_listings.loading{min-height:96px;border-bottom:1px solid #eee;background:url(../images/ajax-loader.gif) no-repeat center 32px}.rp4wp-related-job_listing>ul li.job_listing,.rp4wp-related-job_listing>ul li.no_job_listings_found,ul.job_listings li.job_listing,ul.job_listings li.no_job_listings_found{list-style:none outside;padding:0;margin:0;border-bottom:1px solid #eee}.rp4wp-related-job_listing>ul li.job_listing.job_position_filled a,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_filled a,ul.job_listings li.job_listing.job_position_filled a,ul.job_listings li.no_job_listings_found.job_position_filled a{opacity:.25}.rp4wp-related-job_listing>ul li.job_listing.no_job_listings_found,.rp4wp-related-job_listing>ul li.no_job_listings_found.no_job_listings_found,ul.job_listings li.job_listing.no_job_listings_found,ul.job_listings li.no_job_listings_found.no_job_listings_found{padding:1em;border-bottom:1px solid #eee}.rp4wp-related-job_listing>ul li.job_listing a,.rp4wp-related-job_listing>ul li.no_job_listings_found a,ul.job_listings li.job_listing a,ul.job_listings li.no_job_listings_found a{display:block;padding:1em 1em 1em 2em;border:0;overflow:hidden;zoom:1;position:relative;line-height:1.5em;text-decoration:none}.rp4wp-related-job_listing>ul li.job_listing a:focus,.rp4wp-related-job_listing>ul li.job_listing a:hover,.rp4wp-related-job_listing>ul li.no_job_listings_found a:focus,.rp4wp-related-job_listing>ul li.no_job_listings_found a:hover,ul.job_listings li.job_listing a:focus,ul.job_listings li.job_listing a:hover,ul.job_listings li.no_job_listings_found a:focus,ul.job_listings li.no_job_listings_found a:hover{background-color:#fcfcfc}.rp4wp-related-job_listing>ul li.job_listing a img.company_logo,.rp4wp-related-job_listing>ul li.no_job_listings_found a img.company_logo,ul.job_listings li.job_listing a img.company_logo,ul.job_listings li.no_job_listings_found a img.company_logo{width:42px;height:42px;position:absolute;left:1em;float:left;margin-right:1em;vertical-align:middle;box-shadow:none}.rp4wp-related-job_listing>ul li.job_listing a div.location,.rp4wp-related-job_listing>ul li.job_listing a div.position,.rp4wp-related-job_listing>ul li.job_listing a ul.meta,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.location,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position,.rp4wp-related-job_listing>ul li.no_job_listings_found a ul.meta,ul.job_listings li.job_listing a div.location,ul.job_listings li.job_listing a div.position,ul.job_listings li.job_listing a ul.meta,ul.job_listings li.no_job_listings_found a div.location,ul.job_listings li.no_job_listings_found a div.position,ul.job_listings li.no_job_listings_found a ul.meta{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.rp4wp-related-job_listing>ul li.job_listing a div.position,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position,ul.job_listings li.job_listing a div.position,ul.job_listings li.no_job_listings_found a div.position{float:left;width:55%;padding:0 0 0 42px;line-height:1.5em}.rp4wp-related-job_listing>ul li.job_listing a div.position h3,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position h3,ul.job_listings li.job_listing a div.position h3,ul.job_listings li.no_job_listings_found a div.position h3{margin:0;padding:0;line-height:inherit;font-size:inherit}.rp4wp-related-job_listing>ul li.job_listing a div.position .company,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position .company,ul.job_listings li.job_listing a div.position .company,ul.job_listings li.no_job_listings_found a div.position .company{color:#999}.rp4wp-related-job_listing>ul li.job_listing a div.position .company .tagline,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position .company .tagline,ul.job_listings li.job_listing a div.position .company .tagline,ul.job_listings li.no_job_listings_found a div.position .company .tagline{margin-left:.5em}.rp4wp-related-job_listing>ul li.job_listing a div.location,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.location,ul.job_listings li.job_listing a div.location,ul.job_listings li.no_job_listings_found a div.location{float:left;text-align:left;width:25%;padding:0 0 0 1em;color:#999;line-height:1.5em}.rp4wp-related-job_listing>ul li.job_listing a .meta,.rp4wp-related-job_listing>ul li.no_job_listings_found a .meta,ul.job_listings li.job_listing a .meta,ul.job_listings li.no_job_listings_found a .meta{float:right;text-align:right;width:20%;padding:0 0 0 1em;margin:0;line-height:1.5em;color:#999;list-style:none outside}.rp4wp-related-job_listing>ul li.job_listing a .meta li,.rp4wp-related-job_listing>ul li.no_job_listings_found a .meta li,ul.job_listings li.job_listing a .meta li,ul.job_listings li.no_job_listings_found a .meta li{list-style:none outside;display:block;margin:0}.rp4wp-related-job_listing>ul li.job_listing a .meta .job-type,.rp4wp-related-job_listing>ul li.no_job_listings_found a .meta .job-type,ul.job_listings li.job_listing a .meta .job-type,ul.job_listings li.no_job_listings_found a .meta .job-type{font-weight:700}.rp4wp-related-job_listing>ul li.job_listing.job_position_featured a,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_featured a,ul.job_listings li.job_listing.job_position_featured a,ul.job_listings li.no_job_listings_found.job_position_featured a{background:#fefee5}.rp4wp-related-job_listing>ul li.job_listing.job_position_featured a:focus,.rp4wp-related-job_listing>ul li.job_listing.job_position_featured a:hover,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_featured a:focus,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_featured a:hover,ul.job_listings li.job_listing.job_position_featured a:focus,ul.job_listings li.job_listing.job_position_featured a:hover,ul.job_listings li.no_job_listings_found.job_position_featured a:focus,ul.job_listings li.no_job_listings_found.job_position_featured a:hover{background-color:#fefed8}.widget ul.job_listings li.job_listing a{padding:1em 0}.widget ul.job_listings li.job_listing .position{float:none;width:auto;padding:0}.widget ul.job_listings li.job_listing ul.meta{float:none;width:auto;padding:0;margin:0;text-align:left}.widget ul.job_listings li.job_listing ul.meta li{float:none;display:inline;padding:0;margin:0 .5em 0 0;font-weight:400}.widget ul.job_listings li.job_listing ul.meta li:after{padding:0 0 0 .5em;content:"\2023"}.widget ul.job_listings li.job_listing ul.meta li:last-child:after{content:''}.job-manager .job-type,.job-types .job-type,.job_listing .job-type{color:#f08d3c}.job-manager .full-time,.job-types .full-time,.job_listing .full-time{color:#90da36}.job-manager .part-time,.job-types .part-time,.job_listing .part-time{color:#f08d3c}.job-manager .temporary,.job-types .temporary,.job_listing .temporary{color:#d93674}.job-manager .freelance,.job-types .freelance,.job_listing .freelance{color:#39c}.job-manager .internship,.job-types .internship,.job_listing .internship{color:#6033cc}.single_job_listing .company{position:relative;border:1px solid #eee;padding:1em;margin:0 0 2em;display:block;clear:both;min-height:3em;box-shadow:0 1px 1px rgba(0,0,0,.1)}.single_job_listing .company img{width:3em;height:3em;position:absolute;left:1em;float:left;vertical-align:middle;box-shadow:none}.single_job_listing .company .name{margin:0 0 0 3em;padding:0 0 0 1em;line-height:1.5em}.single_job_listing .company .name a{float:right;margin-left:1em}.single_job_listing .company .tagline{display:block;margin:0 0 0 42px;padding:0 0 0 1em;line-height:1.5em;font-style:italic;color:#999}.single_job_listing .company .website:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;*overflow:auto;*zoom:1;*display:inline;content:'\e809'}.single_job_listing .company .company_twitter:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;*overflow:auto;*zoom:1;*display:inline;content:'\e80a'}.single_job_listing .company .company_video{border-top:1px solid #eee;padding:1em 0 0;margin:1em 0 0;position:relative;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden}.single_job_listing .company .company_video embed,.single_job_listing .company .company_video iframe,.single_job_listing .company .company_video object{position:absolute;top:0;left:0;width:100%;height:100%;margin:0;display:block}.single_job_listing .meta{list-style:none outside;padding:0;margin:0 0 1.5em;overflow:hidden;zoom:1;clear:both}.single_job_listing .meta li{margin:0 1em 0 0;padding:.5em;float:left;line-height:1em;color:#999}.single_job_listing .meta .job-type{color:#fff;background-color:#f08d3c}.single_job_listing .meta .full-time{background-color:#90da36}.single_job_listing .meta .part-time{background-color:#f08d3c}.single_job_listing .meta .temporary{background-color:#d93674}.single_job_listing .meta .freelance{background-color:#39c}.single_job_listing .meta .internship{background-color:#6033cc}.single_job_listing .meta .listing-expired,.single_job_listing .meta .position-filled{color:#b81c23}.single_job_listing .meta .location:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;*overflow:auto;*zoom:1;*display:inline;content:'\e81d'}.single_job_listing .meta .date-posted:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;*overflow:auto;*zoom:1;*display:inline;content:'\e80f'}.single_job_listing .meta .listing-expired:before,.single_job_listing .meta .position-filled:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;*overflow:auto;*zoom:1;*display:inline;content:'\e80e'}.single_job_listing .job_description{margin:0 0 1.5em}.job-manager-application-wrapper{clear:both;border:1px solid #eee;padding:.75em 1em 0;margin:1em 0;line-height:1.5em;display:block;position:relative;box-shadow:0 1px 1px rgba(0,0,0,.1)}.job-manager-application-wrapper .application,.single_job_listing .application{padding:0;margin:0 0 1em;overflow:hidden}.job-manager-application-wrapper .application .application_button,.job-manager-application-wrapper .application .application_details,.single_job_listing .application .application_button,.single_job_listing .application .application_details{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.job-manager-application-wrapper .application .application_button,.single_job_listing .application .application_button{text-align:center;font-size:1.1em;line-height:1em;display:inline-block;margin:0 .5em 0 0;padding:.90909091em 2em;outline:0}.job-manager-application-wrapper .application .application_details,.single_job_listing .application .application_details{clear:both;border:1px solid #eee;padding:.75em 1em 0;margin:1em 0;line-height:1.5em;display:block;position:relative;box-shadow:0 1px 1px rgba(0,0,0,.1)}.job-manager-application-wrapper .application .application_details p,.single_job_listing .application .application_details p{margin:0 0 .75em}.job-manager-application-wrapper .application .application_details:before,.single_job_listing .application .application_details:before{content:"";position:absolute;margin:-10px 0 0 0;top:0;left:5em;width:0;height:0;border-left:10px solid transparent;border-right:10px solid transparent;border-bottom:10px solid #eee}.job-manager-application-wrapper .application .application_details:after,.single_job_listing .application .application_details:after{content:"";position:absolute;margin:-9px 0 0 1px;left:5em;top:0;width:0;height:0;border-left:9px solid transparent;border-right:9px solid transparent;border-bottom:9px solid #fff}.job_filters{background:#eee;zoom:1}.job_filters:after,.job_filters:before{content:"";display:table}.job_filters:after{clear:both}.job_filters .search_jobs{padding:1em;zoom:1}.job_filters .search_jobs:after,.job_filters .search_jobs:before{content:"";display:table}.job_filters .search_jobs:after{clear:both}.job_filters .search_jobs div{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.job_filters .search_jobs div label{display:none}.job_filters .search_jobs div.filter_first,.job_filters .search_jobs div.search_keywords{float:left;padding-right:.5em;width:50%}.job_filters .search_jobs div.filter_last,.job_filters .search_jobs div.search_location{float:right;padding-left:.5em;width:50%}.job_filters .search_jobs div.filter_wide,.job_filters .search_jobs div.search_categories{padding-top:.5em;clear:both;width:100%}.job_filters .search_jobs div .showing_jobs a{padding:.25em}.job_filters .search_jobs div .showing_jobs a.active{background:#ddd;text-decoration:none}.job_filters .search_jobs input,.job_filters .search_jobs select{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%}.job_filters .job_types{list-style:none outside;margin:0;padding:0;font-size:.83em;background:#f9f9f9;border-top:1px solid #e5e5e5;zoom:1}.job_filters .job_types:after,.job_filters .job_types:before{content:"";display:table}.job_filters .job_types:after{clear:both}.job_filters .job_types li{margin:0;padding:.5em 1em;float:left;border-right:1px solid #eee}.job_filters .job_types li:last-child{border-right:0}.job_filters .showing_jobs{padding:.5em 1em;display:none;font-size:.83em;background:#f9f9f9;border-top:1px solid #e5e5e5}.job_filters .showing_jobs a{float:right;padding-left:10px;border:0}div.job_listings .job-manager-pagination{text-align:center;display:block;padding:1em 0;border-bottom:1px solid #eee;line-height:1}div.job_listings .load_previous{border-top:1px solid #eee}div.job_listings .load_more_jobs+ul.job_listings{border-top:0}div.job_listings .load_more_jobs{text-align:center;display:block;padding:1em 1em 1em 2em;border-bottom:1px solid #eee;font-weight:700}div.job_listings .load_more_jobs.loading{background:url(../images/ajax-loader.gif) no-repeat center}div.job_listings .load_more_jobs.loading strong{visibility:hidden}div.job_listings .load_more_jobs:focus,div.job_listings .load_more_jobs:hover{background-color:#fcfcfc;border-bottom:1px solid #eee}.job_listing_preview{padding:0 1em 1em;border:5px solid #eee}.single-job_listing .entry-header .attachment-post-thumbnail,.single-job_listing .job_listing.has-post-thumbnail .post-thumbnail{display:none}.entry-content .job_listing_preview_title,.job_listing_preview_title{padding:.5em 1em;vertical-align:middle;position:relative;background:#eee}.entry-content .job_listing_preview_title h2,.job_listing_preview_title h2{margin:0;clear:none}.entry-content .job_listing_preview_title .button,.job_listing_preview_title .button{float:right;margin-left:.25em}.job_summary_shortcode{border:1px solid #ccc;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;text-align:center;position:relative;box-shadow:0 2px 4px rgba(0,0,0,.1),inset 0 1px 0 rgba(255,255,255,.4);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.job_summary_shortcode.aligncenter{display:block;margin:2em auto}.job_summary_shortcode.alignleft{float:left;margin:0 2em 2em 0}.job_summary_shortcode.alignright{float:right;margin:0 0 2em 2em}.job_summary_shortcode a{text-decoration:none;color:inherit}.job_summary_shortcode img{margin:0;padding:0;display:block;width:100%;-moz-border-radius:0;-webkit-border-radius:0;-moz-border-top-left-radius:3px;-moz-border-top-right-radius:3px;-webkit-border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-radius:0;border-top-left-radius:3px;border-top-right-radius:3px;box-shadow:inset 0 1px 0 rgba(255,255,255,.4)}.job_summary_shortcode .job_summary_content{padding:0 1em}.job_summary_shortcode .meta{font-style:italic;color:#777}.job_summary_shortcode .job-type{-moz-border-radius:1em;-webkit-border-radius:1em;border-radius:1em;color:#fff;text-shadow:0 1px 0 rgba(255,255,255,.5);box-shadow:0 2px 4px rgba(0,0,0,.1),inset 0 1px 0 rgba(255,255,255,.4);position:absolute;top:0;right:0;padding:.5em;height:1em;width:auto;min-width:1em;font-size:1em;text-align:center;vertical-align:middle;line-height:1em;margin:-.5em -.5em 0 0}.job_summary_shortcode .job-type.full-time{background-color:#90da36}.job_summary_shortcode .job-type.part-time{background-color:#f08d3c}.job_summary_shortcode .job-type.temporary{background-color:#d93674}.job_summary_shortcode .job-type.freelance{background-color:#39c}.job_summary_shortcode .job-type.internship{background-color:#6033cc}#job-manager-job-dashboard .account-sign-in .button{margin-right:.5em}#job-manager-job-dashboard .account-sign-in .button:before{display:inline-block;width:16px;height:16px;-webkit-font-smoothing:antialiased;font-family:job-manager!important;text-decoration:none;font-weight:400;font-style:normal;vertical-align:top;font-size:16px;margin:0 2px 0 0;*overflow:auto;*zoom:1;*display:inline;content:'\e808'}#job-manager-job-dashboard table ul.job-dashboard-actions{margin:0;padding:0;visibility:hidden;font-size:.92em}#job-manager-job-dashboard table ul.job-dashboard-actions li{float:none;display:inline;padding:0;margin:0 .5em 0 0;font-weight:400;list-style:none outside}#job-manager-job-dashboard table ul.job-dashboard-actions li:after{padding:0 0 0 .5em;content:"\2023"}#job-manager-job-dashboard table ul.job-dashboard-actions li:last-child:after{content:''}#job-manager-job-dashboard table ul.job-dashboard-actions li .job-dashboard-action-delete{color:red}#job-manager-job-dashboard table tr:focus ul.job-dashboard-actions,#job-manager-job-dashboard table tr:hover ul.job-dashboard-actions{visibility:visible}#job-manager-job-dashboard table td,#job-manager-job-dashboard table th{padding:.5em 1em .5em 0}#job-manager-job-dashboard table .job_title small{color:#999}#content nav.job-manager-pagination,#job-manager-job-dashboard table .applications,#job-manager-job-dashboard table .expires,#job-manager-job-dashboard table .filled,nav.job-manager-pagination{text-align:center}#content nav.job-manager-pagination ul,nav.job-manager-pagination ul{display:inline-block;white-space:nowrap;padding:0;clear:both;border-left:1px solid #eee;margin:1px}#content nav.job-manager-pagination ul li,nav.job-manager-pagination ul li{border-right:1px solid #eee;border-top:1px solid #eee;border-bottom:1px solid #eee;padding:0;margin:0;float:left;display:inline;overflow:hidden}#content nav.job-manager-pagination ul li a,#content nav.job-manager-pagination ul li span,nav.job-manager-pagination ul li a,nav.job-manager-pagination ul li span{margin:0;text-decoration:none;line-height:1em;font-size:1em;font-weight:400;padding:.5em;min-width:1em;display:block;border:0}#content nav.job-manager-pagination ul li a:focus,#content nav.job-manager-pagination ul li a:hover,#content nav.job-manager-pagination ul li span.current,nav.job-manager-pagination ul li a:focus,nav.job-manager-pagination ul li a:hover,nav.job-manager-pagination ul li span.current{background:#eee;color:#888}@media only screen and (max-width:767px){ul.job_listings li.job_listing a,ul.job_listings li.no_job_listings_found a{padding:1em}ul.job_listings li.job_listing a img.company_logo,ul.job_listings li.no_job_listings_found a img.company_logo{visibility:hidden}ul.job_listings li.job_listing a div.position,ul.job_listings li.no_job_listings_found a div.position{float:left;width:60%;padding:0}ul.job_listings li.job_listing a div.location,ul.job_listings li.no_job_listings_found a div.location{float:right;width:40%;line-height:2em;font-size:.75em;padding:0 0 0 1em;text-align:right}ul.job_listings li.job_listing a .meta,ul.job_listings li.no_job_listings_found a .meta{float:right;width:40%;line-height:2em;font-size:.75em}ul.job_listings li.job_listing a .meta li,ul.job_listings li.no_job_listings_found a .meta li{font-size:1em}}.chosen-container{width:100%!important}.twenty-eleven ul.job_listings li.job_listing,.twenty-eleven ul.job_listings li.no_job_listings_found{padding:0!important}.twenty-ten .chosen-choices,.twenty-ten .job_types{margin:0!important}.rtl .job-manager-form label{float:right}.rtl .entry-content .job_listing_preview_title .button,.rtl .job-manager-form div.field,.rtl .job_listing_preview_title .button{float:left}.rtl .single_job_listing .meta li{float:right;margin:0 0 0 1em}
|
assets/css/frontend.less
ADDED
@@ -0,0 +1,958 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@import "mixins";
|
2 |
+
@import "icons";
|
3 |
+
|
4 |
+
@primary: #999999; /* Primary colour for buttons (alt) */
|
5 |
+
@primarytext: desaturate(lighten(@primary,50%),18%); /* Text on primary colour bg */
|
6 |
+
|
7 |
+
@secondary: desaturate(lighten(@primary,40%),18%); /* Secondary buttons */
|
8 |
+
@secondarytext: desaturate(darken(@secondary,60%),18%); /* Text on secondary colour bg */
|
9 |
+
|
10 |
+
@highlight: spin( @primary, 150 ); /* Prices, In stock labels, sales flash */
|
11 |
+
@highlightext: desaturate(lighten(@highlight,50%),18%); /* Text on highlight colour bg */
|
12 |
+
|
13 |
+
@contentbg: #fff; /* Content BG - Tabs (active state) */
|
14 |
+
@subtext: #777; /* small, breadcrumbs etc */
|
15 |
+
|
16 |
+
.display-icon {
|
17 |
+
display: inline-block;
|
18 |
+
width: 16px;
|
19 |
+
height: 16px;
|
20 |
+
-webkit-font-smoothing: antialiased;
|
21 |
+
font-size: 16px;
|
22 |
+
font-family: "job-manager" !important;
|
23 |
+
text-decoration: none;
|
24 |
+
font-weight: normal;
|
25 |
+
font-style: normal;
|
26 |
+
vertical-align: top;
|
27 |
+
font-size: 16px;
|
28 |
+
margin: 0 2px 0 0;
|
29 |
+
|
30 |
+
*overflow: auto;
|
31 |
+
*zoom: 1;
|
32 |
+
*display: inline;
|
33 |
+
}
|
34 |
+
|
35 |
+
/* =Global styles/layout
|
36 |
+
-------------------------------------------------------------- */
|
37 |
+
.job-manager-message, .job-manager-error, .job-manager-info {
|
38 |
+
padding: 1em 2em 1em 3.5em !important;
|
39 |
+
margin: 0 0 2em !important;
|
40 |
+
position: relative;
|
41 |
+
background-color: lighten(@secondary,5%);
|
42 |
+
color: @secondarytext;
|
43 |
+
border-top: 3px solid @primary;
|
44 |
+
list-style: none outside !important;
|
45 |
+
width: auto;
|
46 |
+
.clearfix;
|
47 |
+
box-shadow: 0 1px 1px rgba(0,0,0,0.2);
|
48 |
+
&:before {
|
49 |
+
content: "";
|
50 |
+
font-family: sans-serif;
|
51 |
+
display: inline-block;
|
52 |
+
position: absolute;
|
53 |
+
top: 1em;
|
54 |
+
left: 1.5em;
|
55 |
+
}
|
56 |
+
li {
|
57 |
+
list-style: none outside !important;
|
58 |
+
padding-left: 0 !important;
|
59 |
+
margin-left: 0 !important;
|
60 |
+
}
|
61 |
+
&.job-manager-message {
|
62 |
+
border-top-color: #8fae1b;
|
63 |
+
&:before {
|
64 |
+
color:#8fae1b;
|
65 |
+
content: "\2713";
|
66 |
+
}
|
67 |
+
}
|
68 |
+
&.job-manager-info {
|
69 |
+
border-top-color: #1e85be;
|
70 |
+
&:before {
|
71 |
+
color:#1e85be;
|
72 |
+
content: "i";
|
73 |
+
font-family: Times, Georgia, serif;
|
74 |
+
font-style: italic;
|
75 |
+
}
|
76 |
+
}
|
77 |
+
&.job-manager-error {
|
78 |
+
border-top-color: #b81c23;
|
79 |
+
&:before {
|
80 |
+
color:#b81c23;
|
81 |
+
content: "\00d7";
|
82 |
+
font-weight: 700;
|
83 |
+
}
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
.job-manager-form {
|
88 |
+
fieldset {
|
89 |
+
margin: 0 0 1em 0;
|
90 |
+
padding: 0 0 1em 0;
|
91 |
+
line-height: 2em;
|
92 |
+
border: 0;
|
93 |
+
border-bottom: 1px solid #eee;
|
94 |
+
.clearfix;
|
95 |
+
label {
|
96 |
+
display: block;
|
97 |
+
margin: 0;
|
98 |
+
width: 29%;
|
99 |
+
float: left;
|
100 |
+
vertical-align: middle;
|
101 |
+
small {
|
102 |
+
opacity: .75;
|
103 |
+
font-size: 0.83em;
|
104 |
+
}
|
105 |
+
}
|
106 |
+
div.field {
|
107 |
+
width: 70%;
|
108 |
+
float: right;
|
109 |
+
vertical-align: middle;
|
110 |
+
}
|
111 |
+
.wp-editor-container {
|
112 |
+
border: 1px solid #ccc;
|
113 |
+
-webkit-border-radius: 3px;
|
114 |
+
-moz-border-radius: 3px;
|
115 |
+
border-radius: 3px;
|
116 |
+
}
|
117 |
+
.account-sign-in {
|
118 |
+
.button {
|
119 |
+
margin-right: .5em;
|
120 |
+
&:before {
|
121 |
+
.display-icon;
|
122 |
+
content: '\e808';
|
123 |
+
}
|
124 |
+
}
|
125 |
+
}
|
126 |
+
abbr.required {
|
127 |
+
color: red;
|
128 |
+
font-weight: bold;
|
129 |
+
border: 0;
|
130 |
+
}
|
131 |
+
input.input-text, textarea, select {
|
132 |
+
margin: 0;
|
133 |
+
vertical-align: middle;
|
134 |
+
width: 100%;
|
135 |
+
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
136 |
+
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
137 |
+
box-sizing: border-box; /* Opera/IE 8+ */
|
138 |
+
}
|
139 |
+
small.description {
|
140 |
+
opacity: .75;
|
141 |
+
font-size: 0.83em;
|
142 |
+
margin: 1.2em 0 0 0;
|
143 |
+
display: block;
|
144 |
+
line-height: 1.2em;
|
145 |
+
}
|
146 |
+
.job-manager-uploaded-files {
|
147 |
+
display: table;
|
148 |
+
.job-manager-uploaded-file {
|
149 |
+
line-height: 2em;
|
150 |
+
font-style: italic;
|
151 |
+
margin-bottom: 1em;
|
152 |
+
display: block;
|
153 |
+
.job-manager-uploaded-file-preview {
|
154 |
+
img {
|
155 |
+
height: 64px;
|
156 |
+
margin: 0;
|
157 |
+
vertical-align: top;
|
158 |
+
}
|
159 |
+
a {
|
160 |
+
line-height: 64px;
|
161 |
+
display: inline-block;
|
162 |
+
padding: 0 0 0 1em;
|
163 |
+
}
|
164 |
+
}
|
165 |
+
.job-manager-uploaded-file-name {
|
166 |
+
display: block;
|
167 |
+
}
|
168 |
+
}
|
169 |
+
}
|
170 |
+
}
|
171 |
+
.submit-job {
|
172 |
+
padding: 1em 0;
|
173 |
+
}
|
174 |
+
.job-manager-term-checklist {
|
175 |
+
list-style: none outside;
|
176 |
+
max-height: 200px;
|
177 |
+
overflow: auto;
|
178 |
+
margin: 0;
|
179 |
+
li {
|
180 |
+
list-style: none outside;
|
181 |
+
margin: 0;
|
182 |
+
display: block;
|
183 |
+
float: none;
|
184 |
+
label {
|
185 |
+
width: auto;
|
186 |
+
float: none;
|
187 |
+
}
|
188 |
+
li {
|
189 |
+
margin: 0 0 0 2em;
|
190 |
+
}
|
191 |
+
}
|
192 |
+
}
|
193 |
+
}
|
194 |
+
div.job_listings {
|
195 |
+
margin-bottom: 1em;
|
196 |
+
ul.job_listings {
|
197 |
+
margin: 0;
|
198 |
+
}
|
199 |
+
}
|
200 |
+
.rp4wp-related-job_listing > ul,
|
201 |
+
ul.job_listings {
|
202 |
+
padding: 0;
|
203 |
+
margin: 0;
|
204 |
+
border-top: 1px solid #eee;
|
205 |
+
|
206 |
+
&.loading {
|
207 |
+
min-height: 96px;
|
208 |
+
border-bottom: 1px solid #eee;
|
209 |
+
background: url(../images/ajax-loader.gif) no-repeat center 32px;
|
210 |
+
}
|
211 |
+
li.job_listing, li.no_job_listings_found {
|
212 |
+
list-style: none outside;
|
213 |
+
padding: 0;
|
214 |
+
margin: 0;
|
215 |
+
border-bottom: 1px solid #eee;
|
216 |
+
|
217 |
+
&.job_position_filled {
|
218 |
+
a {
|
219 |
+
opacity: 0.25;
|
220 |
+
}
|
221 |
+
}
|
222 |
+
&.no_job_listings_found {
|
223 |
+
padding: 1em;
|
224 |
+
border-bottom: 1px solid #eee;
|
225 |
+
}
|
226 |
+
a {
|
227 |
+
display: block;
|
228 |
+
padding: 1em 1em 1em 2em;
|
229 |
+
border: 0;
|
230 |
+
overflow: hidden;
|
231 |
+
zoom: 1;
|
232 |
+
position: relative;
|
233 |
+
line-height: 1.5em;
|
234 |
+
text-decoration: none;
|
235 |
+
|
236 |
+
&:hover, &:focus {
|
237 |
+
background-color: #fcfcfc;
|
238 |
+
}
|
239 |
+
img.company_logo {
|
240 |
+
width: 42px;
|
241 |
+
height: 42px;
|
242 |
+
position: absolute;
|
243 |
+
left: 1em;
|
244 |
+
float: left;
|
245 |
+
margin-right: 1em;
|
246 |
+
vertical-align: middle;
|
247 |
+
box-shadow: none;
|
248 |
+
}
|
249 |
+
div.position, div.location, ul.meta {
|
250 |
+
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
251 |
+
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
252 |
+
box-sizing: border-box; /* Opera/IE 8+ */
|
253 |
+
}
|
254 |
+
div.position {
|
255 |
+
float: left;
|
256 |
+
width: 55%;
|
257 |
+
padding: 0 0 0 42px;
|
258 |
+
line-height: 1.5em;
|
259 |
+
h3 {
|
260 |
+
margin: 0;
|
261 |
+
padding: 0;
|
262 |
+
line-height: inherit;
|
263 |
+
font-size: inherit;
|
264 |
+
}
|
265 |
+
.company {
|
266 |
+
color: #999;
|
267 |
+
.tagline {
|
268 |
+
margin-left: .5em;
|
269 |
+
}
|
270 |
+
}
|
271 |
+
}
|
272 |
+
div.location {
|
273 |
+
float: left;
|
274 |
+
text-align: left;
|
275 |
+
width: 25%;
|
276 |
+
padding: 0 0 0 1em;
|
277 |
+
color: #999;
|
278 |
+
line-height: 1.5em;
|
279 |
+
}
|
280 |
+
.meta {
|
281 |
+
float: right;
|
282 |
+
text-align: right;
|
283 |
+
width: 20%;
|
284 |
+
padding: 0 0 0 1em;
|
285 |
+
margin: 0;
|
286 |
+
line-height: 1.5em;
|
287 |
+
color: #999;
|
288 |
+
list-style: none outside;
|
289 |
+
li {
|
290 |
+
list-style: none outside;
|
291 |
+
display: block;
|
292 |
+
margin: 0;
|
293 |
+
}
|
294 |
+
.job-type {
|
295 |
+
font-weight: bold;
|
296 |
+
}
|
297 |
+
}
|
298 |
+
}
|
299 |
+
&.job_position_featured {
|
300 |
+
a {
|
301 |
+
background: #fefee5;
|
302 |
+
|
303 |
+
&:hover, &:focus {
|
304 |
+
background-color: #fefed8;
|
305 |
+
}
|
306 |
+
}
|
307 |
+
}
|
308 |
+
}
|
309 |
+
}
|
310 |
+
.widget {
|
311 |
+
ul.job_listings {
|
312 |
+
li.job_listing {
|
313 |
+
a {
|
314 |
+
padding: 1em 0;
|
315 |
+
}
|
316 |
+
.position {
|
317 |
+
float: none;
|
318 |
+
width: auto;
|
319 |
+
padding: 0;
|
320 |
+
}
|
321 |
+
ul.meta {
|
322 |
+
float: none;
|
323 |
+
width: auto;
|
324 |
+
padding: 0;
|
325 |
+
margin: 0;
|
326 |
+
text-align: left;
|
327 |
+
li {
|
328 |
+
float: none;
|
329 |
+
display: inline;
|
330 |
+
padding: 0;
|
331 |
+
margin: 0 .5em 0 0;
|
332 |
+
font-weight: normal;
|
333 |
+
|
334 |
+
&:after {
|
335 |
+
padding: 0 0 0 .5em;
|
336 |
+
content: "\2023";
|
337 |
+
}
|
338 |
+
&:last-child:after {
|
339 |
+
content: '';
|
340 |
+
}
|
341 |
+
}
|
342 |
+
}
|
343 |
+
}
|
344 |
+
}
|
345 |
+
}
|
346 |
+
.job-manager, .job_listing, .job-types {
|
347 |
+
.job-type {
|
348 |
+
color: @part-time;
|
349 |
+
}
|
350 |
+
.full-time {
|
351 |
+
color: @full-time;
|
352 |
+
}
|
353 |
+
.part-time {
|
354 |
+
color: @part-time;
|
355 |
+
}
|
356 |
+
.temporary {
|
357 |
+
color: @temporary;
|
358 |
+
}
|
359 |
+
.freelance {
|
360 |
+
color: @freelance;
|
361 |
+
}
|
362 |
+
.internship {
|
363 |
+
color: @internship;
|
364 |
+
}
|
365 |
+
}
|
366 |
+
.single_job_listing {
|
367 |
+
.company {
|
368 |
+
position: relative;
|
369 |
+
border: 1px solid #eee;
|
370 |
+
padding: 1em;
|
371 |
+
margin: 0 0 2em;
|
372 |
+
display: block;
|
373 |
+
clear: both;
|
374 |
+
min-height: 3em;
|
375 |
+
box-shadow: 0 1px 1px rgba(0,0,0,0.1);
|
376 |
+
|
377 |
+
img {
|
378 |
+
width: 3em;
|
379 |
+
height: 3em;
|
380 |
+
position: absolute;
|
381 |
+
left: 1em;
|
382 |
+
float: left;
|
383 |
+
vertical-align: middle;
|
384 |
+
box-shadow: none;
|
385 |
+
}
|
386 |
+
.name {
|
387 |
+
margin: 0 0 0 3em;
|
388 |
+
padding: 0 0 0 1em;
|
389 |
+
line-height: 1.5em;
|
390 |
+
a {
|
391 |
+
float: right;
|
392 |
+
margin-left: 1em;
|
393 |
+
}
|
394 |
+
}
|
395 |
+
.tagline {
|
396 |
+
display: block;
|
397 |
+
margin: 0 0 0 42px;
|
398 |
+
padding: 0 0 0 1em;
|
399 |
+
line-height: 1.5em;
|
400 |
+
font-style: italic;
|
401 |
+
color: #999;
|
402 |
+
}
|
403 |
+
.website:before {
|
404 |
+
.display-icon;
|
405 |
+
content: '\e809';
|
406 |
+
}
|
407 |
+
.company_twitter:before {
|
408 |
+
.display-icon;
|
409 |
+
content: '\e80a';
|
410 |
+
}
|
411 |
+
.company_video {
|
412 |
+
border-top: 1px solid #eee;
|
413 |
+
padding: 1em 0 0;
|
414 |
+
margin: 1em 0 0 0;
|
415 |
+
position: relative;
|
416 |
+
padding-bottom: 56.25%;
|
417 |
+
padding-top: 30px;
|
418 |
+
height: 0;
|
419 |
+
overflow: hidden;
|
420 |
+
iframe,
|
421 |
+
object,
|
422 |
+
embed {
|
423 |
+
position: absolute;
|
424 |
+
top: 0;
|
425 |
+
left: 0;
|
426 |
+
width: 100%;
|
427 |
+
height: 100%;
|
428 |
+
margin: 0;
|
429 |
+
display: block;
|
430 |
+
}
|
431 |
+
}
|
432 |
+
}
|
433 |
+
.meta {
|
434 |
+
list-style: none outside;
|
435 |
+
padding: 0;
|
436 |
+
margin: 0 0 1.5em;
|
437 |
+
overflow: hidden;
|
438 |
+
zoom: 1;
|
439 |
+
clear: both;
|
440 |
+
li {
|
441 |
+
margin: 0 1em 0 0;
|
442 |
+
padding: .5em;
|
443 |
+
float: left;
|
444 |
+
line-height: 1em;
|
445 |
+
color: #999;
|
446 |
+
}
|
447 |
+
.job-type {
|
448 |
+
color: #fff;
|
449 |
+
background-color: @part-time;
|
450 |
+
}
|
451 |
+
.full-time {
|
452 |
+
background-color: @full-time;
|
453 |
+
}
|
454 |
+
.part-time {
|
455 |
+
background-color: @part-time;
|
456 |
+
}
|
457 |
+
.temporary {
|
458 |
+
background-color: @temporary;
|
459 |
+
}
|
460 |
+
.freelance {
|
461 |
+
background-color: @freelance;
|
462 |
+
}
|
463 |
+
.internship {
|
464 |
+
background-color: @internship;
|
465 |
+
}
|
466 |
+
.position-filled, .listing-expired {
|
467 |
+
color: #b81c23;
|
468 |
+
}
|
469 |
+
.location:before {
|
470 |
+
.display-icon;
|
471 |
+
content: '\e81d';
|
472 |
+
}
|
473 |
+
.date-posted:before {
|
474 |
+
.display-icon;
|
475 |
+
content: '\e80f';
|
476 |
+
}
|
477 |
+
.position-filled:before, .listing-expired:before {
|
478 |
+
.display-icon;
|
479 |
+
content: '\e80e';
|
480 |
+
}
|
481 |
+
}
|
482 |
+
.job_description {
|
483 |
+
margin: 0 0 1.5em;
|
484 |
+
}
|
485 |
+
}
|
486 |
+
.job-manager-application-wrapper {
|
487 |
+
clear: both;
|
488 |
+
border: 1px solid #eee;
|
489 |
+
padding: .75em 1em 0;
|
490 |
+
margin: 1em 0;
|
491 |
+
line-height: 1.5em;
|
492 |
+
display: block;
|
493 |
+
position: relative;
|
494 |
+
box-shadow: 0 1px 1px rgba(0,0,0,0.1);
|
495 |
+
}
|
496 |
+
.single_job_listing, .job-manager-application-wrapper {
|
497 |
+
.application {
|
498 |
+
padding: 0;
|
499 |
+
margin: 0 0 1em;
|
500 |
+
overflow: hidden;
|
501 |
+
|
502 |
+
.application_button, .application_details {
|
503 |
+
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
504 |
+
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
505 |
+
box-sizing: border-box; /* Opera/IE 8+ */
|
506 |
+
}
|
507 |
+
.application_button {
|
508 |
+
text-align: center;
|
509 |
+
font-size: 1.1em;
|
510 |
+
line-height: 1em;
|
511 |
+
display: inline-block;
|
512 |
+
margin: 0 .5em 0 0;
|
513 |
+
padding: 1/1.1em 2em;
|
514 |
+
outline: 0;
|
515 |
+
}
|
516 |
+
.application_details {
|
517 |
+
clear: both;
|
518 |
+
border: 1px solid #eee;
|
519 |
+
padding: .75em 1em 0;
|
520 |
+
margin: 1em 0;
|
521 |
+
line-height: 1.5em;
|
522 |
+
display: block;
|
523 |
+
position: relative;
|
524 |
+
box-shadow: 0 1px 1px rgba(0,0,0,0.1);
|
525 |
+
|
526 |
+
p {
|
527 |
+
margin: 0 0 .75em;
|
528 |
+
}
|
529 |
+
|
530 |
+
&:before {
|
531 |
+
content: "";
|
532 |
+
position: absolute;
|
533 |
+
margin: -10px 0 0 0;
|
534 |
+
top: 0;
|
535 |
+
left: 5em;
|
536 |
+
width: 0;
|
537 |
+
height: 0;
|
538 |
+
border-left: 10px solid transparent;
|
539 |
+
border-right: 10px solid transparent;
|
540 |
+
border-bottom:10px solid #eee;
|
541 |
+
}
|
542 |
+
&:after {
|
543 |
+
content: "";
|
544 |
+
position: absolute;
|
545 |
+
margin: -9px 0 0 1px;
|
546 |
+
left: 5em;
|
547 |
+
top: 0;
|
548 |
+
width: 0;
|
549 |
+
height: 0;
|
550 |
+
border-left: 9px solid transparent;
|
551 |
+
border-right: 9px solid transparent;
|
552 |
+
border-bottom: 9px solid #fff;
|
553 |
+
}
|
554 |
+
}
|
555 |
+
}
|
556 |
+
}
|
557 |
+
.job_filters {
|
558 |
+
background: #eee;
|
559 |
+
.clearfix;
|
560 |
+
|
561 |
+
.search_jobs {
|
562 |
+
padding: 1em;
|
563 |
+
.clearfix;
|
564 |
+
div {
|
565 |
+
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
566 |
+
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
567 |
+
box-sizing: border-box; /* Opera/IE 8+ */
|
568 |
+
|
569 |
+
label {
|
570 |
+
display: none;
|
571 |
+
}
|
572 |
+
&.search_keywords, &.filter_first {
|
573 |
+
float: left;
|
574 |
+
padding-right: .5em;
|
575 |
+
width: 50%;
|
576 |
+
}
|
577 |
+
&.search_location, &.filter_last {
|
578 |
+
float: right;
|
579 |
+
padding-left: .5em;
|
580 |
+
width: 50%;
|
581 |
+
}
|
582 |
+
&.search_categories, &.filter_wide {
|
583 |
+
padding-top: .5em;
|
584 |
+
clear: both;
|
585 |
+
width: 100%;
|
586 |
+
}
|
587 |
+
.showing_jobs {
|
588 |
+
a {
|
589 |
+
padding: .25em;
|
590 |
+
}
|
591 |
+
a.active {
|
592 |
+
background: #ddd;
|
593 |
+
text-decoration: none;
|
594 |
+
}
|
595 |
+
}
|
596 |
+
}
|
597 |
+
input, select {
|
598 |
+
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
599 |
+
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
600 |
+
box-sizing: border-box; /* Opera/IE 8+ */
|
601 |
+
width: 100%;
|
602 |
+
}
|
603 |
+
}
|
604 |
+
.job_types {
|
605 |
+
list-style: none outside;
|
606 |
+
margin: 0;
|
607 |
+
padding: 0;
|
608 |
+
font-size: 0.83em;
|
609 |
+
background: #f9f9f9;
|
610 |
+
border-top: 1px solid #e5e5e5;
|
611 |
+
.clearfix;
|
612 |
+
li {
|
613 |
+
margin: 0;
|
614 |
+
padding: .5em 1em;
|
615 |
+
float: left;
|
616 |
+
border-right: 1px solid #eee;
|
617 |
+
|
618 |
+
&:last-child {
|
619 |
+
border-right: 0;
|
620 |
+
}
|
621 |
+
}
|
622 |
+
}
|
623 |
+
|
624 |
+
.showing_jobs {
|
625 |
+
padding: .5em 1em;
|
626 |
+
display: none;
|
627 |
+
font-size: 0.83em;
|
628 |
+
background: #f9f9f9;
|
629 |
+
border-top: 1px solid #e5e5e5;
|
630 |
+
|
631 |
+
a {
|
632 |
+
float: right;
|
633 |
+
padding-left: 10px;
|
634 |
+
border: 0;
|
635 |
+
}
|
636 |
+
}
|
637 |
+
}
|
638 |
+
div.job_listings {
|
639 |
+
.job-manager-pagination {
|
640 |
+
text-align: center;
|
641 |
+
display: block;
|
642 |
+
padding: 1em 0 1em 0;
|
643 |
+
border-bottom: 1px solid #eee;
|
644 |
+
line-height: 1;
|
645 |
+
}
|
646 |
+
.load_previous {
|
647 |
+
border-top: 1px solid #eee;
|
648 |
+
}
|
649 |
+
.load_more_jobs + ul.job_listings {
|
650 |
+
border-top: 0;
|
651 |
+
}
|
652 |
+
.load_more_jobs {
|
653 |
+
text-align: center;
|
654 |
+
display: block;
|
655 |
+
padding: 1em 1em 1em 2em;
|
656 |
+
border-bottom: 1px solid #eee;
|
657 |
+
font-weight: bold;
|
658 |
+
&.loading {
|
659 |
+
background: url(../images/ajax-loader.gif) no-repeat center;
|
660 |
+
strong {
|
661 |
+
visibility: hidden;
|
662 |
+
}
|
663 |
+
}
|
664 |
+
&:hover, &:focus {
|
665 |
+
background-color: #fcfcfc;
|
666 |
+
border-bottom: 1px solid #eee;
|
667 |
+
}
|
668 |
+
}
|
669 |
+
}
|
670 |
+
.job_listing_preview {
|
671 |
+
padding: 0 1em 1em;
|
672 |
+
border: 5px solid #eee;
|
673 |
+
}
|
674 |
+
.single-job_listing .entry-header .attachment-post-thumbnail,
|
675 |
+
.single-job_listing .job_listing.has-post-thumbnail .post-thumbnail {
|
676 |
+
display: none;
|
677 |
+
}
|
678 |
+
.job_listing_preview_title, .entry-content .job_listing_preview_title {
|
679 |
+
padding: .5em 1em;
|
680 |
+
vertical-align: middle;
|
681 |
+
position: relative;
|
682 |
+
background: #eee;
|
683 |
+
h2 {
|
684 |
+
margin: 0;
|
685 |
+
clear: none;
|
686 |
+
}
|
687 |
+
.button {
|
688 |
+
float: right;
|
689 |
+
margin-left: .25em;
|
690 |
+
}
|
691 |
+
}
|
692 |
+
.job_summary_shortcode {
|
693 |
+
border: 1px solid #ccc;
|
694 |
+
-moz-border-radius: 4px;
|
695 |
+
-webkit-border-radius: 4px;
|
696 |
+
border-radius: 4px;
|
697 |
+
text-align: center;
|
698 |
+
position: relative;
|
699 |
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1),inset 0 1px 0 rgba(255,255,255,0.4);
|
700 |
+
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
701 |
+
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
702 |
+
box-sizing: border-box; /* Opera/IE 8+ */
|
703 |
+
|
704 |
+
&.aligncenter {
|
705 |
+
display: block;
|
706 |
+
margin: 2em auto 2em;
|
707 |
+
}
|
708 |
+
|
709 |
+
&.alignleft {
|
710 |
+
float: left;
|
711 |
+
margin: 0 2em 2em 0;
|
712 |
+
}
|
713 |
+
|
714 |
+
&.alignright {
|
715 |
+
float: right;
|
716 |
+
margin: 0 0 2em 2em;
|
717 |
+
}
|
718 |
+
|
719 |
+
a {
|
720 |
+
text-decoration: none;
|
721 |
+
color: inherit;
|
722 |
+
}
|
723 |
+
|
724 |
+
img {
|
725 |
+
margin: 0;
|
726 |
+
padding: 0;
|
727 |
+
display: block;
|
728 |
+
width: 100%;
|
729 |
+
-moz-border-radius: 0;
|
730 |
+
-webkit-border-radius: 0;
|
731 |
+
-moz-border-top-left-radius: 3px;
|
732 |
+
-moz-border-top-right-radius: 3px;
|
733 |
+
-webkit-border-top-left-radius: 3px;
|
734 |
+
-webkit-border-top-right-radius: 3px;
|
735 |
+
border-radius: 0;
|
736 |
+
border-top-left-radius: 3px;
|
737 |
+
border-top-right-radius: 3px;
|
738 |
+
box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
|
739 |
+
}
|
740 |
+
|
741 |
+
.job_summary_content {
|
742 |
+
padding: 0 1em;
|
743 |
+
}
|
744 |
+
|
745 |
+
.meta {
|
746 |
+
font-style: italic;
|
747 |
+
color: #777;
|
748 |
+
}
|
749 |
+
|
750 |
+
.job-type {
|
751 |
+
-moz-border-radius: 1em;
|
752 |
+
-webkit-border-radius: 1em;
|
753 |
+
border-radius: 1em;
|
754 |
+
color: #fff;
|
755 |
+
text-shadow: 0 1px 0 rgba(255,255,255,0.5);
|
756 |
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1), inset 0 1px 0 rgba(255,255,255,0.4);
|
757 |
+
position: absolute;
|
758 |
+
top: 0;
|
759 |
+
right: 0;
|
760 |
+
padding: .5em;
|
761 |
+
height: 1em;
|
762 |
+
width: auto;
|
763 |
+
min-width: 1em;
|
764 |
+
font-size: 1em;
|
765 |
+
text-align: center;
|
766 |
+
vertical-align: middle;
|
767 |
+
line-height: 1em;
|
768 |
+
margin: -.5em -.5em 0 0;
|
769 |
+
|
770 |
+
&.full-time {
|
771 |
+
background-color: @full-time;
|
772 |
+
}
|
773 |
+
&.part-time {
|
774 |
+
background-color: @part-time;
|
775 |
+
}
|
776 |
+
&.temporary {
|
777 |
+
background-color: @temporary;
|
778 |
+
}
|
779 |
+
&.freelance {
|
780 |
+
background-color: @freelance;
|
781 |
+
}
|
782 |
+
&.internship {
|
783 |
+
background-color: @internship;
|
784 |
+
}
|
785 |
+
}
|
786 |
+
}
|
787 |
+
|
788 |
+
#job-manager-job-dashboard {
|
789 |
+
.account-sign-in {
|
790 |
+
.button {
|
791 |
+
margin-right: .5em;
|
792 |
+
&:before {
|
793 |
+
.display-icon;
|
794 |
+
content: '\e808';
|
795 |
+
}
|
796 |
+
}
|
797 |
+
}
|
798 |
+
table {
|
799 |
+
ul.job-dashboard-actions {
|
800 |
+
margin: 0;
|
801 |
+
padding:0;
|
802 |
+
visibility: hidden;
|
803 |
+
font-size: 0.92em;
|
804 |
+
li {
|
805 |
+
float: none;
|
806 |
+
display: inline;
|
807 |
+
padding: 0;
|
808 |
+
margin: 0 .5em 0 0;
|
809 |
+
font-weight: normal;
|
810 |
+
list-style: none outside;
|
811 |
+
|
812 |
+
&:after {
|
813 |
+
padding: 0 0 0 .5em;
|
814 |
+
content: "\2023";
|
815 |
+
}
|
816 |
+
&:last-child:after {
|
817 |
+
content: '';
|
818 |
+
}
|
819 |
+
.job-dashboard-action-delete {
|
820 |
+
color: red;
|
821 |
+
}
|
822 |
+
}
|
823 |
+
}
|
824 |
+
tr:hover, tr:focus {
|
825 |
+
ul.job-dashboard-actions {
|
826 |
+
visibility: visible;
|
827 |
+
}
|
828 |
+
}
|
829 |
+
td, th {
|
830 |
+
padding: .5em 1em .5em 0;
|
831 |
+
}
|
832 |
+
.job_title small {
|
833 |
+
color: #999;
|
834 |
+
}
|
835 |
+
.filled, .expires, .applications {
|
836 |
+
text-align: center;
|
837 |
+
}
|
838 |
+
}
|
839 |
+
}
|
840 |
+
|
841 |
+
nav.job-manager-pagination, #content nav.job-manager-pagination {
|
842 |
+
text-align: center;
|
843 |
+
ul {
|
844 |
+
display: inline-block;
|
845 |
+
white-space: nowrap;
|
846 |
+
padding:0;
|
847 |
+
clear: both;
|
848 |
+
border-left: 1px solid #eee;
|
849 |
+
margin: 1px;
|
850 |
+
li {
|
851 |
+
border-right: 1px solid #eee;
|
852 |
+
border-top: 1px solid #eee;
|
853 |
+
border-bottom: 1px solid #eee;
|
854 |
+
padding: 0;
|
855 |
+
margin: 0;
|
856 |
+
float: left;
|
857 |
+
display: inline;
|
858 |
+
overflow: hidden;
|
859 |
+
a, span {
|
860 |
+
margin: 0;
|
861 |
+
text-decoration: none;
|
862 |
+
padding: 0;
|
863 |
+
line-height: 1em;
|
864 |
+
font-size: 1em;
|
865 |
+
font-weight: normal;
|
866 |
+
padding: .5em;
|
867 |
+
min-width: 1em;
|
868 |
+
display: block;
|
869 |
+
border: 0;
|
870 |
+
}
|
871 |
+
span.current, a:hover, a:focus {
|
872 |
+
background: #eee;
|
873 |
+
color: darken( #eee, 40 );
|
874 |
+
}
|
875 |
+
}
|
876 |
+
}
|
877 |
+
}
|
878 |
+
|
879 |
+
/**
|
880 |
+
* Mobile styles
|
881 |
+
*/
|
882 |
+
@media only screen and (max-width: 767px) {
|
883 |
+
ul.job_listings {
|
884 |
+
li.job_listing, li.no_job_listings_found {
|
885 |
+
a {
|
886 |
+
padding: 1em;
|
887 |
+
img.company_logo {
|
888 |
+
visibility: hidden;
|
889 |
+
}
|
890 |
+
div.position {
|
891 |
+
float: left;
|
892 |
+
width: 60%;
|
893 |
+
padding: 0;
|
894 |
+
}
|
895 |
+
div.location {
|
896 |
+
float: right;
|
897 |
+
width: 40%;
|
898 |
+
line-height: 2em;
|
899 |
+
font-size: .75em;
|
900 |
+
padding: 0 0 0 1em;
|
901 |
+
text-align: right;
|
902 |
+
}
|
903 |
+
.meta {
|
904 |
+
float: right;
|
905 |
+
width: 40%;
|
906 |
+
line-height: 2em;
|
907 |
+
font-size: .75em;
|
908 |
+
li {
|
909 |
+
font-size: 1em;
|
910 |
+
}
|
911 |
+
}
|
912 |
+
}
|
913 |
+
}
|
914 |
+
}
|
915 |
+
}
|
916 |
+
|
917 |
+
// Chosen fixes
|
918 |
+
.chosen-container {
|
919 |
+
width: 100% !important;
|
920 |
+
}
|
921 |
+
|
922 |
+
// Default theme fixes
|
923 |
+
.twenty-eleven {
|
924 |
+
ul.job_listings {
|
925 |
+
li.job_listing, li.no_job_listings_found {
|
926 |
+
padding: 0 !important;
|
927 |
+
}
|
928 |
+
}
|
929 |
+
}
|
930 |
+
.twenty-ten {
|
931 |
+
.job_types, .chosen-choices {
|
932 |
+
margin: 0 !important;
|
933 |
+
}
|
934 |
+
}
|
935 |
+
|
936 |
+
.rtl {
|
937 |
+
.job-manager-form {
|
938 |
+
label {
|
939 |
+
float: right;
|
940 |
+
}
|
941 |
+
div.field {
|
942 |
+
float: left;
|
943 |
+
}
|
944 |
+
}
|
945 |
+
.job_listing_preview_title, .entry-content .job_listing_preview_title {
|
946 |
+
.button {
|
947 |
+
float: left;
|
948 |
+
}
|
949 |
+
}
|
950 |
+
.single_job_listing {
|
951 |
+
.meta {
|
952 |
+
li {
|
953 |
+
float: right;
|
954 |
+
margin: 0 0 0 1em;
|
955 |
+
}
|
956 |
+
}
|
957 |
+
}
|
958 |
+
}
|
assets/css/icons.less
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@font-face {
|
2 |
+
font-family: 'job-manager';
|
3 |
+
src: url('../font/job-manager.eot?4963673');
|
4 |
+
src: url('../font/job-manager.eot?4963673#iefix') format('embedded-opentype'),
|
5 |
+
url('../font/job-manager.woff?4963673') format('woff'),
|
6 |
+
url('../font/job-manager.ttf?4963673') format('truetype'),
|
7 |
+
url('../font/job-manager.svg?4963673#job-manager') format('svg');
|
8 |
+
font-weight: normal;
|
9 |
+
font-style: normal;
|
10 |
+
}
|
11 |
+
|
12 |
+
@font-face {
|
13 |
+
font-family: 'jm-logo';
|
14 |
+
src:url('../font/jm-logo/jm.eot?ycsbky');
|
15 |
+
src:url('../font/jm-logo/jm.eot?#iefixycsbky') format('embedded-opentype'),
|
16 |
+
url('../font/jm-logo/jm.woff?ycsbky') format('woff'),
|
17 |
+
url('../font/jm-logo/jm.ttf?ycsbky') format('truetype'),
|
18 |
+
url('../font/jm-logo/jm.svg?ycsbky#icomoon') format('svg');
|
19 |
+
font-weight: normal;
|
20 |
+
font-style: normal;
|
21 |
+
}
|
22 |
+
|
23 |
+
.jm-icon {
|
24 |
+
font-family: "job-manager" !important;
|
25 |
+
font-style: normal;
|
26 |
+
font-weight: normal;
|
27 |
+
speak: none;
|
28 |
+
|
29 |
+
display: inline-block;
|
30 |
+
text-decoration: inherit;
|
31 |
+
width: 1em;
|
32 |
+
text-align: center;
|
33 |
+
|
34 |
+
/* For safety - reset parent styles, that can break glyph codes*/
|
35 |
+
font-variant: normal;
|
36 |
+
text-transform: none;
|
37 |
+
|
38 |
+
/* fix buttons height, for twitter bootstrap */
|
39 |
+
line-height: 1em;
|
40 |
+
}
|
assets/css/job-listings.css
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
.clearfix{zoom:1}.clearfix:after,.clearfix:before{content:"";display:table}.clearfix:after{clear:both}.rp4wp-related-job_listing>ul,ul.job_listings{padding:0;margin:0;border-top:1px solid #eee}.rp4wp-related-job_listing>ul.loading,ul.job_listings.loading{min-height:96px;border-bottom:1px solid #eee;background:url(../images/ajax-loader.gif) no-repeat center 32px}.rp4wp-related-job_listing>ul li.job_listing,.rp4wp-related-job_listing>ul li.no_job_listings_found,ul.job_listings li.job_listing,ul.job_listings li.no_job_listings_found{list-style:none outside;padding:0;margin:0;border-bottom:1px solid #eee}.rp4wp-related-job_listing>ul li.job_listing.job_position_filled a,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_filled a,ul.job_listings li.job_listing.job_position_filled a,ul.job_listings li.no_job_listings_found.job_position_filled a{opacity:.25}.rp4wp-related-job_listing>ul li.job_listing.no_job_listings_found,.rp4wp-related-job_listing>ul li.no_job_listings_found.no_job_listings_found,ul.job_listings li.job_listing.no_job_listings_found,ul.job_listings li.no_job_listings_found.no_job_listings_found{padding:1em;border-bottom:1px solid #eee}.rp4wp-related-job_listing>ul li.job_listing a,.rp4wp-related-job_listing>ul li.no_job_listings_found a,ul.job_listings li.job_listing a,ul.job_listings li.no_job_listings_found a{display:block;padding:1em 1em 1em 2em;border:0;overflow:hidden;zoom:1;position:relative;line-height:1.5em;text-decoration:none}.rp4wp-related-job_listing>ul li.job_listing a:focus,.rp4wp-related-job_listing>ul li.job_listing a:hover,.rp4wp-related-job_listing>ul li.no_job_listings_found a:focus,.rp4wp-related-job_listing>ul li.no_job_listings_found a:hover,ul.job_listings li.job_listing a:focus,ul.job_listings li.job_listing a:hover,ul.job_listings li.no_job_listings_found a:focus,ul.job_listings li.no_job_listings_found a:hover{background-color:#fcfcfc}.rp4wp-related-job_listing>ul li.job_listing a img.company_logo,.rp4wp-related-job_listing>ul li.no_job_listings_found a img.company_logo,ul.job_listings li.job_listing a img.company_logo,ul.job_listings li.no_job_listings_found a img.company_logo{width:42px;height:42px;position:absolute;left:1em;float:left;margin-right:1em;vertical-align:middle;box-shadow:none}.rp4wp-related-job_listing>ul li.job_listing a div.location,.rp4wp-related-job_listing>ul li.job_listing a div.position,.rp4wp-related-job_listing>ul li.job_listing a ul.meta,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.location,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position,.rp4wp-related-job_listing>ul li.no_job_listings_found a ul.meta,ul.job_listings li.job_listing a div.location,ul.job_listings li.job_listing a div.position,ul.job_listings li.job_listing a ul.meta,ul.job_listings li.no_job_listings_found a div.location,ul.job_listings li.no_job_listings_found a div.position,ul.job_listings li.no_job_listings_found a ul.meta{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.rp4wp-related-job_listing>ul li.job_listing a div.position,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position,ul.job_listings li.job_listing a div.position,ul.job_listings li.no_job_listings_found a div.position{float:left;width:55%;padding:0 0 0 42px;line-height:1.5em}.rp4wp-related-job_listing>ul li.job_listing a div.position h3,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position h3,ul.job_listings li.job_listing a div.position h3,ul.job_listings li.no_job_listings_found a div.position h3{margin:0;padding:0;line-height:inherit;font-size:inherit}.rp4wp-related-job_listing>ul li.job_listing a div.position .company,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position .company,ul.job_listings li.job_listing a div.position .company,ul.job_listings li.no_job_listings_found a div.position .company{color:#999}.rp4wp-related-job_listing>ul li.job_listing a div.position .company .tagline,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.position .company .tagline,ul.job_listings li.job_listing a div.position .company .tagline,ul.job_listings li.no_job_listings_found a div.position .company .tagline{margin-left:.5em}.rp4wp-related-job_listing>ul li.job_listing a div.location,.rp4wp-related-job_listing>ul li.no_job_listings_found a div.location,ul.job_listings li.job_listing a div.location,ul.job_listings li.no_job_listings_found a div.location{float:left;text-align:left;width:25%;padding:0 0 0 1em;color:#999;line-height:1.5em}.rp4wp-related-job_listing>ul li.job_listing a .meta,.rp4wp-related-job_listing>ul li.no_job_listings_found a .meta,ul.job_listings li.job_listing a .meta,ul.job_listings li.no_job_listings_found a .meta{float:right;text-align:right;width:20%;padding:0 0 0 1em;margin:0;line-height:1.5em;color:#999;list-style:none outside}.rp4wp-related-job_listing>ul li.job_listing a .meta li,.rp4wp-related-job_listing>ul li.no_job_listings_found a .meta li,ul.job_listings li.job_listing a .meta li,ul.job_listings li.no_job_listings_found a .meta li{list-style:none outside;display:block;margin:0}.rp4wp-related-job_listing>ul li.job_listing a .meta .job-type,.rp4wp-related-job_listing>ul li.no_job_listings_found a .meta .job-type,ul.job_listings li.job_listing a .meta .job-type,ul.job_listings li.no_job_listings_found a .meta .job-type{font-weight:700}.rp4wp-related-job_listing>ul li.job_listing.job_position_featured a,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_featured a,ul.job_listings li.job_listing.job_position_featured a,ul.job_listings li.no_job_listings_found.job_position_featured a{background:#fefee5}.rp4wp-related-job_listing>ul li.job_listing.job_position_featured a:focus,.rp4wp-related-job_listing>ul li.job_listing.job_position_featured a:hover,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_featured a:focus,.rp4wp-related-job_listing>ul li.no_job_listings_found.job_position_featured a:hover,ul.job_listings li.job_listing.job_position_featured a:focus,ul.job_listings li.job_listing.job_position_featured a:hover,ul.job_listings li.no_job_listings_found.job_position_featured a:focus,ul.job_listings li.no_job_listings_found.job_position_featured a:hover{background-color:#fefed8}.widget ul.job_listings li.job_listing a{padding:1em 0}.widget ul.job_listings li.job_listing .image{float:left}.widget ul.job_listings li.job_listing .image img{left:0;position:relative}.widget ul.job_listings li.job_listing .content{overflow:hidden}.widget ul.job_listings li.job_listing .position{float:none;width:auto;padding:0}.widget ul.job_listings li.job_listing ul.meta{float:none;width:auto;padding:0;margin:0;text-align:left}.widget ul.job_listings li.job_listing ul.meta li{float:none;display:inline;padding:0;margin:0 .5em 0 0;font-weight:400}.widget ul.job_listings li.job_listing ul.meta li:after{padding:0 0 0 .5em;content:"\2023"}.widget ul.job_listings li.job_listing ul.meta li:last-child:after{content:''}.job-manager .job-type,.job-types .job-type,.job_listing .job-type{color:#f08d3c}.job-manager .full-time,.job-types .full-time,.job_listing .full-time{color:#90da36}.job-manager .part-time,.job-types .part-time,.job_listing .part-time{color:#f08d3c}.job-manager .temporary,.job-types .temporary,.job_listing .temporary{color:#d93674}.job-manager .freelance,.job-types .freelance,.job_listing .freelance{color:#39c}.job-manager .internship,.job-types .internship,.job_listing .internship{color:#6033cc}@media only screen and (max-width:767px){ul.job_listings li.job_listing a,ul.job_listings li.no_job_listings_found a{padding:1em}ul.job_listings li.job_listing a img.company_logo,ul.job_listings li.no_job_listings_found a img.company_logo{visibility:hidden}ul.job_listings li.job_listing a div.position,ul.job_listings li.no_job_listings_found a div.position{float:left;width:60%;padding:0}ul.job_listings li.job_listing a div.location,ul.job_listings li.no_job_listings_found a div.location{float:right;width:40%;line-height:2em;font-size:.75em;padding:0 0 0 1em;text-align:right}ul.job_listings li.job_listing a .meta,ul.job_listings li.no_job_listings_found a .meta{float:right;width:40%;line-height:2em;font-size:.75em}ul.job_listings li.job_listing a .meta li,ul.job_listings li.no_job_listings_found a .meta li{font-size:1em}}.twenty-eleven ul.job_listings li.job_listing,.twenty-eleven ul.job_listings li.no_job_listings_found{padding:0!important}
|
|
assets/css/job-submission.css
CHANGED
@@ -1 +1,11 @@
|
|
1 |
-
#wp-link #search-panel
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#wp-link #search-panel,
|
2 |
+
#wp-link #wplink-link-existing-content {
|
3 |
+
display: none;
|
4 |
+
}
|
5 |
+
div#wp-link-wrap.wp-core-ui {
|
6 |
+
height: 300px;
|
7 |
+
}
|
8 |
+
.wplink-autocomplete.ui-autocomplete {
|
9 |
+
display: none;
|
10 |
+
visibility: hidden;
|
11 |
+
}
|
assets/css/job-submission.less
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#wp-link {
|
2 |
+
#search-panel, #wplink-link-existing-content {
|
3 |
+
display: none;
|
4 |
+
}
|
5 |
+
}
|
6 |
+
|
7 |
+
div#wp-link-wrap.wp-core-ui {
|
8 |
+
height: 300px;
|
9 |
+
}
|
10 |
+
|
11 |
+
.wplink-autocomplete.ui-autocomplete {
|
12 |
+
display: none;
|
13 |
+
visibility: hidden;
|
14 |
+
}
|
assets/css/menu.less
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@import "icons.less";
|
2 |
+
|
3 |
+
/* Menu */
|
4 |
+
#adminmenu {
|
5 |
+
#menu-posts-job_listing {
|
6 |
+
.wp-menu-image:before {
|
7 |
+
content: '\e800';
|
8 |
+
.jm-icon;
|
9 |
+
}
|
10 |
+
}
|
11 |
+
#menu-posts-resume {
|
12 |
+
.wp-menu-image:before {
|
13 |
+
content: '\e806';
|
14 |
+
.jm-icon;
|
15 |
+
}
|
16 |
+
}
|
17 |
+
}
|
assets/css/mixins.less
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@full-time: #90da36;
|
2 |
+
@part-time: #f08d3c;
|
3 |
+
@internship:#6033cc;
|
4 |
+
@freelance: #3399cc;
|
5 |
+
@temporary: #d93674;
|
6 |
+
|
7 |
+
.clearfix {
|
8 |
+
zoom: 1; /* For IE 6/7 (trigger hasLayout) */
|
9 |
+
|
10 |
+
&:before, &:after {
|
11 |
+
content: "";
|
12 |
+
display: table;
|
13 |
+
}
|
14 |
+
&:after {
|
15 |
+
clear: both;
|
16 |
+
}
|
17 |
+
}
|
18 |
+
.border_radius(@radius:4px) {
|
19 |
+
-webkit-border-radius:@radius;
|
20 |
+
border-radius:@radius;
|
21 |
+
}
|
22 |
+
.border_radius_right(@radius:4px) {
|
23 |
+
-webkit-border-top-right-radius: @radius;
|
24 |
+
-webkit-border-bottom-right-radius: @radius;
|
25 |
+
border-top-right-radius: @radius;
|
26 |
+
border-bottom-right-radius: @radius;
|
27 |
+
}
|
28 |
+
.border_radius_left(@radius:4px) {
|
29 |
+
-webkit-border-top-left-radius: @radius;
|
30 |
+
-webkit-border-bottom-left-radius: @radius;
|
31 |
+
border-top-left-radius: @radius;
|
32 |
+
border-bottom-left-radius: @radius;
|
33 |
+
}
|
34 |
+
.border_radius_bottom(@radius:4px) {
|
35 |
+
-webkit-border-bottom-left-radius: @radius;
|
36 |
+
-webkit-border-bottom-right-radius: @radius;
|
37 |
+
border-bottom-left-radius: @radius;
|
38 |
+
border-bottom-right-radius: @radius;
|
39 |
+
}
|
40 |
+
.border_radius_top(@radius:4px) {
|
41 |
+
-webkit-border-top-left-radius: @radius;
|
42 |
+
-webkit-border-top-right-radius: @radius;
|
43 |
+
border-top-left-radius: @radius;
|
44 |
+
border-top-right-radius: @radius;
|
45 |
+
}
|
46 |
+
.opacity(@opacity:0.75) {
|
47 |
+
filter:~"alpha(opacity=@opacity * 100)";
|
48 |
+
-khtml-opacity: @opacity;
|
49 |
+
opacity: @opacity;
|
50 |
+
}
|
51 |
+
.box_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_in:3px, @shadow_color:#888) {
|
52 |
+
box-shadow:@shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
|
53 |
+
-webkit-box-shadow:@shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
|
54 |
+
-moz-box-shadow:@shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
|
55 |
+
}
|
56 |
+
.inset_box_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_in:3px, @shadow_color:#888) {
|
57 |
+
box-shadow:inset @shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
|
58 |
+
-webkit-box-shadow:inset @shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
|
59 |
+
-moz-box-shadow:inset @shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
|
60 |
+
}
|
61 |
+
.text_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_color:#fff) {
|
62 |
+
text-shadow:@shadow_x @shadow_y @shadow_rad @shadow_color;
|
63 |
+
}
|
64 |
+
.vertical_gradient(@from: #000, @to: #FFF) {
|
65 |
+
background: @from;
|
66 |
+
background: -webkit-gradient(linear, left top, left bottom, from(@from), to(@to));
|
67 |
+
background: -webkit-linear-gradient(@from, @to);
|
68 |
+
background: -moz-linear-gradient(center top, @from 0%, @to 100%);
|
69 |
+
background: -moz-gradient(center top, @from 0%, @to 100%);
|
70 |
+
}
|
71 |
+
.transition(@selector:all, @animation:ease-in-out, @duration:.2s) {
|
72 |
+
-webkit-transition:@selector @animation @duration;
|
73 |
+
-moz-transition:@selector @animation @duration;
|
74 |
+
-o-transition:@selector @animation @duration;
|
75 |
+
transition:@selector @animation @duration;
|
76 |
+
}
|
77 |
+
.scale(@ratio:1.5){
|
78 |
+
-webkit-transform:scale(@ratio);
|
79 |
+
-moz-transform:scale(@ratio);
|
80 |
+
-ms-transform:scale(@ratio);
|
81 |
+
-o-transform:scale(@ratio);
|
82 |
+
transform:scale(@ratio);
|
83 |
+
}
|
84 |
+
.borderbox () {
|
85 |
+
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
86 |
+
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
87 |
+
box-sizing: border-box; /* Opera/IE 8+ */
|
88 |
+
}
|
89 |
+
.darkorlighttextshadow ( @a, @opacity: 0.8 ) when (lightness(@a) >= 65%) { .text_shadow( 0, -1px, 0, rgba(0,0,0,@opacity) ); }
|
90 |
+
.darkorlighttextshadow ( @a, @opacity: 0.8 ) when (lightness(@a) < 65%) { .text_shadow( 0, 1px, 0, rgba(255,255,255,@opacity) ); }
|
91 |
+
|
92 |
+
.keyframes(@name; @arguments) {
|
93 |
+
@-o-keyframes @name { @arguments(); }
|
94 |
+
@-ms-keyframes @name { @arguments(); }
|
95 |
+
@-moz-keyframes @name { @arguments(); }
|
96 |
+
@-webkit-keyframes @name { @arguments(); }
|
97 |
+
@keyframes @name { @arguments(); }
|
98 |
+
}
|
99 |
+
|
100 |
+
.animation(@animation) {
|
101 |
+
-o-animation: @animation;
|
102 |
+
-webkit-animation: @animation;
|
103 |
+
-moz-animation: @animation;
|
104 |
+
animation: @animation;
|
105 |
+
}
|
assets/css/setup.less
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.help-page-link {
|
2 |
+
cursor: help;
|
3 |
+
}
|
4 |
+
|
5 |
+
.wp-job-manager-setup-steps {
|
6 |
+
margin: 1em 0 2em;
|
7 |
+
overflow: hidden;
|
8 |
+
li {
|
9 |
+
width: 33.3%;
|
10 |
+
padding: 7px 1em;
|
11 |
+
font-weight: bold;
|
12 |
+
margin: 0;
|
13 |
+
color: #eee;
|
14 |
+
background: #222222;
|
15 |
+
float: left;
|
16 |
+
-moz-box-sizing: border-box;
|
17 |
+
-webkit-box-sizing: border-box;
|
18 |
+
box-sizing: border-box;
|
19 |
+
|
20 |
+
&:first-child {
|
21 |
+
margin-left: 0;
|
22 |
+
}
|
23 |
+
&.wp-job-manager-setup-active-step {
|
24 |
+
background: #0074a2;
|
25 |
+
color: #eee;
|
26 |
+
}
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
.wp-job-manager-shortcodes {
|
31 |
+
td, th {
|
32 |
+
vertical-align: middle;
|
33 |
+
p {
|
34 |
+
margin: 9px 0;
|
35 |
+
}
|
36 |
+
}
|
37 |
+
tr:nth-child(even) {
|
38 |
+
td, th {
|
39 |
+
background: #f9f9f9;
|
40 |
+
}
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
.wp-job-manager-next-steps {
|
45 |
+
font-size: 1.1em;
|
46 |
+
list-style: disc inside;
|
47 |
+
margin: 1.5em 2em;
|
48 |
+
}
|
49 |
+
|
50 |
+
.wp-job-manager-support-the-plugin {
|
51 |
+
background: #fff;
|
52 |
+
padding: 2em;
|
53 |
+
margin: 2em 0;
|
54 |
+
h3 {
|
55 |
+
margin-top: 0;
|
56 |
+
}
|
57 |
+
ul {
|
58 |
+
margin-bottom: 0;
|
59 |
+
}
|
60 |
+
li {
|
61 |
+
line-height: 2em;
|
62 |
+
font-size: 1.1em;
|
63 |
+
a {
|
64 |
+
text-decoration: none;
|
65 |
+
}
|
66 |
+
}
|
67 |
+
li a:before {
|
68 |
+
font-family: "dashicons";
|
69 |
+
font-size: 2em;
|
70 |
+
vertical-align: middle;
|
71 |
+
padding-right: .25em;
|
72 |
+
}
|
73 |
+
li.icon-review {
|
74 |
+
a:before {
|
75 |
+
content: "\f155";
|
76 |
+
}
|
77 |
+
}
|
78 |
+
li.icon-localization {
|
79 |
+
a:before {
|
80 |
+
content: "\f319";
|
81 |
+
}
|
82 |
+
}
|
83 |
+
li.icon-code {
|
84 |
+
a:before {
|
85 |
+
content: "\f111";
|
86 |
+
}
|
87 |
+
}
|
88 |
+
li.icon-forum {
|
89 |
+
a:before {
|
90 |
+
content: "\f328";
|
91 |
+
}
|
92 |
+
}
|
93 |
+
}
|
assets/js/admin.js
ADDED
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* global job_manager_admin */
|
2 |
+
jQuery(document).ready(function($) {
|
3 |
+
// Tooltips
|
4 |
+
$( '.tips, .help_tip' ).tipTip({
|
5 |
+
'attribute' : 'data-tip',
|
6 |
+
'fadeIn' : 50,
|
7 |
+
'fadeOut' : 50,
|
8 |
+
'delay' : 200
|
9 |
+
});
|
10 |
+
|
11 |
+
// Author
|
12 |
+
$( 'p.form-field-author' ).on( 'click', 'a.change-author', function() {
|
13 |
+
$(this).closest( 'p' ).find('.current-author').hide();
|
14 |
+
$(this).closest( 'p' ).find('.change-author').show();
|
15 |
+
return false;
|
16 |
+
});
|
17 |
+
|
18 |
+
// Datepicker
|
19 |
+
$( 'input.job-manager-datepicker, input#_job_expires' ).datepicker({
|
20 |
+
altFormat : 'yy-mm-dd',
|
21 |
+
dateFormat : job_manager_admin.date_format,
|
22 |
+
});
|
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 |
+
|
31 |
+
// Uploading files
|
32 |
+
var file_frame;
|
33 |
+
var file_target_input;
|
34 |
+
var file_target_wrapper;
|
35 |
+
|
36 |
+
$(document).on('click', '.wp_job_manager_add_another_file_button', function( event ){
|
37 |
+
event.preventDefault();
|
38 |
+
|
39 |
+
var field_name = $( this ).data( 'field_name' );
|
40 |
+
var field_placeholder = $( this ).data( 'field_placeholder' );
|
41 |
+
var button_text = $( this ).data( 'uploader_button_text' );
|
42 |
+
var button = $( this ).data( 'uploader_button' );
|
43 |
+
var view_button = $( this ).data( 'view_button' );
|
44 |
+
|
45 |
+
$( this ).before( '<span class="file_url"><input type="text" name="' + field_name + '[]" placeholder="' + field_placeholder + '" /><button class="button button-small wp_job_manager_upload_file_button" data-uploader_button_text="' + button_text + '">' + button + '</button><button class="button button-small wp_job_manager_view_file_button">' + view_button + '</button></span>' );
|
46 |
+
} );
|
47 |
+
|
48 |
+
$(document).on('click', '.wp_job_manager_view_file_button', function ( event ) {
|
49 |
+
event.preventDefault();
|
50 |
+
|
51 |
+
file_target_wrapper = $( this ).closest( '.file_url' );
|
52 |
+
file_target_input = file_target_wrapper.find( 'input' );
|
53 |
+
|
54 |
+
var attachment_url = file_target_input.val();
|
55 |
+
|
56 |
+
if ( attachment_url.indexOf( '://' ) > - 1 ) {
|
57 |
+
window.open( attachment_url, '_blank' );
|
58 |
+
} else {
|
59 |
+
file_target_input.addClass( 'file_no_url' );
|
60 |
+
setTimeout( function () {
|
61 |
+
file_target_input.removeClass( 'file_no_url' );
|
62 |
+
}, 1000 );
|
63 |
+
}
|
64 |
+
|
65 |
+
});
|
66 |
+
|
67 |
+
$(document).on('click', '.wp_job_manager_upload_file_button', function( event ){
|
68 |
+
event.preventDefault();
|
69 |
+
|
70 |
+
file_target_wrapper = $( this ).closest('.file_url');
|
71 |
+
file_target_input = file_target_wrapper.find('input');
|
72 |
+
|
73 |
+
// If the media frame already exists, reopen it.
|
74 |
+
if ( file_frame ) {
|
75 |
+
file_frame.open();
|
76 |
+
return;
|
77 |
+
}
|
78 |
+
|
79 |
+
// Create the media frame.
|
80 |
+
file_frame = wp.media.frames.file_frame = wp.media({
|
81 |
+
title: $( this ).data( 'uploader_title' ),
|
82 |
+
button: {
|
83 |
+
text: $( this ).data( 'uploader_button_text' )
|
84 |
+
},
|
85 |
+
multiple: false // Set to true to allow multiple files to be selected
|
86 |
+
});
|
87 |
+
|
88 |
+
// When an image is selected, run a callback.
|
89 |
+
file_frame.on( 'select', function() {
|
90 |
+
// We set multiple to false so only get one image from the uploader
|
91 |
+
var attachment = file_frame.state().get('selection').first().toJSON();
|
92 |
+
|
93 |
+
$( file_target_input ).val( attachment.url );
|
94 |
+
});
|
95 |
+
|
96 |
+
// Finally, open the modal
|
97 |
+
file_frame.open();
|
98 |
+
});
|
99 |
+
});
|
100 |
+
|
101 |
+
jQuery(document).ready(function($) {
|
102 |
+
var taxonomy = 'job_listing_type';
|
103 |
+
$('#' + taxonomy + 'checklist li :radio, #' + taxonomy + 'checklist-pop :radio').live( 'click', function(){
|
104 |
+
var t = $(this), c = t.is(':checked'), id = t.val();
|
105 |
+
$('#' + taxonomy + 'checklist li :radio, #' + taxonomy + 'checklist-pop :radio').prop('checked',false);
|
106 |
+
$('#in-' + taxonomy + '-' + id + ', #in-popular-' + taxonomy + '-' + id).prop( 'checked', c );
|
107 |
+
});
|
108 |
+
});
|
assets/js/admin.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
jQuery(document).ready(function(
|
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)})});
|
assets/js/ajax-file-upload.js
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* global job_manager_ajax_file_upload */
|
2 |
+
jQuery(function($) {
|
3 |
+
$('.wp-job-manager-file-upload').each(function(){
|
4 |
+
$(this).fileupload({
|
5 |
+
dataType: 'json',
|
6 |
+
dropZone: $(this),
|
7 |
+
url: job_manager_ajax_file_upload.ajax_url.toString().replace( '%%endpoint%%', 'upload_file' ),
|
8 |
+
maxNumberOfFiles: 1,
|
9 |
+
formData: {
|
10 |
+
script: true
|
11 |
+
},
|
12 |
+
add: function (e, data) {
|
13 |
+
var $file_field = $( this );
|
14 |
+
var $form = $file_field.closest( 'form' );
|
15 |
+
var $uploaded_files = $file_field.parent().find('.job-manager-uploaded-files');
|
16 |
+
var uploadErrors = [];
|
17 |
+
|
18 |
+
// Validate type
|
19 |
+
var allowed_types = $(this).data('file_types');
|
20 |
+
|
21 |
+
if ( allowed_types ) {
|
22 |
+
var acceptFileTypes = new RegExp( '(\.|\/)(' + allowed_types + ')$', 'i' );
|
23 |
+
|
24 |
+
if ( data.originalFiles[0].name.length && ! acceptFileTypes.test( data.originalFiles[0].name ) ) {
|
25 |
+
uploadErrors.push( job_manager_ajax_file_upload.i18n_invalid_file_type + ' ' + allowed_types );
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
if ( uploadErrors.length > 0 ) {
|
30 |
+
window.alert( uploadErrors.join( '\n' ) );
|
31 |
+
} else {
|
32 |
+
$form.find(':input[type="submit"]').attr( 'disabled', 'disabled' );
|
33 |
+
data.context = $('<progress value="" max="100"></progress>').appendTo( $uploaded_files );
|
34 |
+
data.submit();
|
35 |
+
}
|
36 |
+
},
|
37 |
+
progress: function (e, data) {
|
38 |
+
var progress = parseInt(data.loaded / data.total * 100, 10);
|
39 |
+
data.context.val( progress );
|
40 |
+
},
|
41 |
+
fail: function (e, data) {
|
42 |
+
var $file_field = $( this );
|
43 |
+
var $form = $file_field.closest( 'form' );
|
44 |
+
|
45 |
+
if ( data.errorThrown ) {
|
46 |
+
window.alert( data.errorThrown );
|
47 |
+
}
|
48 |
+
|
49 |
+
data.context.remove();
|
50 |
+
|
51 |
+
$form.find(':input[type="submit"]').removeAttr( 'disabled' );
|
52 |
+
},
|
53 |
+
done: function (e, data) {
|
54 |
+
var $file_field = $( this );
|
55 |
+
var $form = $file_field.closest( 'form' );
|
56 |
+
var $uploaded_files = $file_field.parent().find('.job-manager-uploaded-files');
|
57 |
+
var multiple = $file_field.attr( 'multiple' ) ? 1 : 0;
|
58 |
+
var image_types = [ 'jpg', 'gif', 'png', 'jpeg', 'jpe' ];
|
59 |
+
|
60 |
+
data.context.remove();
|
61 |
+
|
62 |
+
$.each(data.result.files, function(index, file) {
|
63 |
+
if ( file.error ) {
|
64 |
+
window.alert( file.error );
|
65 |
+
} else {
|
66 |
+
var html;
|
67 |
+
if ( $.inArray( file.extension, image_types ) >= 0 ) {
|
68 |
+
html = $.parseHTML( job_manager_ajax_file_upload.js_field_html_img );
|
69 |
+
$( html ).find('.job-manager-uploaded-file-preview img').attr( 'src', file.url );
|
70 |
+
} else {
|
71 |
+
html = $.parseHTML( job_manager_ajax_file_upload.js_field_html );
|
72 |
+
$( html ).find('.job-manager-uploaded-file-name code').text( file.name );
|
73 |
+
}
|
74 |
+
|
75 |
+
$( html ).find('.input-text').val( file.url );
|
76 |
+
$( html ).find('.input-text').attr( 'name', 'current_' + $file_field.attr( 'name' ) );
|
77 |
+
|
78 |
+
if ( multiple ) {
|
79 |
+
$uploaded_files.append( html );
|
80 |
+
} else {
|
81 |
+
$uploaded_files.html( html );
|
82 |
+
}
|
83 |
+
}
|
84 |
+
});
|
85 |
+
|
86 |
+
$form.find(':input[type="submit"]').removeAttr( 'disabled' );
|
87 |
+
}
|
88 |
+
});
|
89 |
+
});
|
90 |
+
});
|
assets/js/ajax-file-upload.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
jQuery(function(
|
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")}})})});
|
assets/js/ajax-filters.js
ADDED
@@ -0,0 +1,290 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* global job_manager_ajax_filters */
|
2 |
+
jQuery( document ).ready( function ( $ ) {
|
3 |
+
|
4 |
+
var xhr = [];
|
5 |
+
|
6 |
+
$( '.job_listings' ).on( 'update_results', function ( event, page, append, loading_previous ) {
|
7 |
+
var data = '';
|
8 |
+
var target = $( this );
|
9 |
+
var form = target.find( '.job_filters' );
|
10 |
+
var showing = target.find( '.showing_jobs' );
|
11 |
+
var results = target.find( '.job_listings' );
|
12 |
+
var per_page = target.data( 'per_page' );
|
13 |
+
var orderby = target.data( 'orderby' );
|
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 |
+
|
20 |
+
if ( index < 0 ) {
|
21 |
+
return;
|
22 |
+
}
|
23 |
+
|
24 |
+
if ( xhr[index] ) {
|
25 |
+
xhr[index].abort();
|
26 |
+
}
|
27 |
+
|
28 |
+
if ( ! append ) {
|
29 |
+
$( results ).addClass( 'loading' );
|
30 |
+
$( 'li.job_listing, li.no_job_listings_found', results ).css( 'visibility', 'hidden' );
|
31 |
+
|
32 |
+
// Not appending. If page > 1, we should show a load previous button so the user can get to earlier-page listings if needed
|
33 |
+
if ( page > 1 && true !== target.data( 'show_pagination' ) ) {
|
34 |
+
$( results ).before( '<a class="load_more_jobs load_previous" href="#"><strong>' + job_manager_ajax_filters.i18n_load_prev_listings + '</strong></a>' );
|
35 |
+
} else {
|
36 |
+
target.find( '.load_previous' ).remove();
|
37 |
+
}
|
38 |
+
|
39 |
+
target.find( '.load_more_jobs' ).data( 'page', page );
|
40 |
+
}
|
41 |
+
|
42 |
+
if ( true === target.data( 'show_filters' ) ) {
|
43 |
+
|
44 |
+
var filter_job_type = [];
|
45 |
+
|
46 |
+
$( ':input[name="filter_job_type[]"]:checked, :input[name="filter_job_type[]"][type="hidden"], :input[name="filter_job_type"]', form ).each( function () {
|
47 |
+
filter_job_type.push( $( this ).val() );
|
48 |
+
} );
|
49 |
+
|
50 |
+
categories = form.find( ':input[name^="search_categories"]' ).map( function () {
|
51 |
+
return $( this ).val();
|
52 |
+
} ).get();
|
53 |
+
keywords = '';
|
54 |
+
location = '';
|
55 |
+
var $keywords = form.find( ':input[name="search_keywords"]' );
|
56 |
+
var $location = form.find( ':input[name="search_location"]' );
|
57 |
+
|
58 |
+
// Workaround placeholder scripts
|
59 |
+
if ( $keywords.val() !== $keywords.attr( 'placeholder' ) ) {
|
60 |
+
keywords = $keywords.val();
|
61 |
+
}
|
62 |
+
|
63 |
+
if ( $location.val() !== $location.attr( 'placeholder' ) ) {
|
64 |
+
location = $location.val();
|
65 |
+
}
|
66 |
+
|
67 |
+
data = {
|
68 |
+
lang: job_manager_ajax_filters.lang,
|
69 |
+
search_keywords: keywords,
|
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,
|
76 |
+
page: page,
|
77 |
+
featured: featured,
|
78 |
+
filled: filled,
|
79 |
+
show_pagination: target.data( 'show_pagination' ),
|
80 |
+
form_data: form.serialize()
|
81 |
+
};
|
82 |
+
|
83 |
+
} else {
|
84 |
+
|
85 |
+
categories = target.data( 'categories' );
|
86 |
+
keywords = target.data( 'keywords' );
|
87 |
+
location = target.data( 'location' );
|
88 |
+
|
89 |
+
if ( categories ) {
|
90 |
+
categories = categories.split( ',' );
|
91 |
+
}
|
92 |
+
|
93 |
+
data = {
|
94 |
+
lang: job_manager_ajax_filters.lang,
|
95 |
+
search_categories: categories,
|
96 |
+
search_keywords: keywords,
|
97 |
+
search_location: location,
|
98 |
+
per_page: per_page,
|
99 |
+
orderby: orderby,
|
100 |
+
order: order,
|
101 |
+
page: page,
|
102 |
+
featured: featured,
|
103 |
+
filled: filled,
|
104 |
+
show_pagination: target.data( 'show_pagination' )
|
105 |
+
};
|
106 |
+
|
107 |
+
}
|
108 |
+
|
109 |
+
xhr[index] = $.ajax( {
|
110 |
+
type: 'POST',
|
111 |
+
url: job_manager_ajax_filters.ajax_url.toString().replace( '%%endpoint%%', 'get_listings' ),
|
112 |
+
data: data,
|
113 |
+
success: function ( result ) {
|
114 |
+
if ( result ) {
|
115 |
+
try {
|
116 |
+
if ( result.showing ) {
|
117 |
+
$( showing ).show().html( '<span>' + result.showing + '</span>' + result.showing_links );
|
118 |
+
} else {
|
119 |
+
$( showing ).hide();
|
120 |
+
}
|
121 |
+
|
122 |
+
if ( result.showing_all ) {
|
123 |
+
$( showing ).addClass( 'wp-job-manager-showing-all' );
|
124 |
+
} else {
|
125 |
+
$( showing ).removeClass( 'wp-job-manager-showing-all' );
|
126 |
+
}
|
127 |
+
|
128 |
+
if ( result.html ) {
|
129 |
+
if ( append && loading_previous ) {
|
130 |
+
$( results ).prepend( result.html );
|
131 |
+
} else if ( append ) {
|
132 |
+
$( results ).append( result.html );
|
133 |
+
} else {
|
134 |
+
$( results ).html( result.html );
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
if ( true === target.data( 'show_pagination' ) ) {
|
139 |
+
target.find('.job-manager-pagination').remove();
|
140 |
+
|
141 |
+
if ( result.pagination ) {
|
142 |
+
target.append( result.pagination );
|
143 |
+
}
|
144 |
+
} else {
|
145 |
+
if ( ! result.found_jobs || result.max_num_pages <= page ) {
|
146 |
+
$( '.load_more_jobs:not(.load_previous)', target ).hide();
|
147 |
+
} else if ( ! loading_previous ) {
|
148 |
+
$( '.load_more_jobs', target ).show();
|
149 |
+
}
|
150 |
+
$( '.load_more_jobs', target ).removeClass( 'loading' );
|
151 |
+
$( 'li.job_listing', results ).css( 'visibility', 'visible' );
|
152 |
+
}
|
153 |
+
|
154 |
+
$( results ).removeClass( 'loading' );
|
155 |
+
|
156 |
+
target.triggerHandler( 'updated_results', result );
|
157 |
+
|
158 |
+
} catch ( err ) {
|
159 |
+
if ( window.console ) {
|
160 |
+
window.console.log( err );
|
161 |
+
}
|
162 |
+
}
|
163 |
+
}
|
164 |
+
},
|
165 |
+
error: function ( jqXHR, textStatus, error ) {
|
166 |
+
if ( window.console && 'abort' !== textStatus ) {
|
167 |
+
window.console.log( textStatus + ': ' + error );
|
168 |
+
}
|
169 |
+
},
|
170 |
+
statusCode: {
|
171 |
+
404: function() {
|
172 |
+
if ( window.console ) {
|
173 |
+
window.console.log( 'Error 404: Ajax Endpoint cannot be reached. Go to Settings > Permalinks and save to resolve.' );
|
174 |
+
}
|
175 |
+
}
|
176 |
+
}
|
177 |
+
} );
|
178 |
+
} );
|
179 |
+
|
180 |
+
$( '#search_keywords, #search_location, .job_types :input, #search_categories, .job-manager-filter' ).change( function() {
|
181 |
+
var target = $( this ).closest( 'div.job_listings' );
|
182 |
+
target.triggerHandler( 'update_results', [ 1, false ] );
|
183 |
+
job_manager_store_state( target, 1 );
|
184 |
+
} )
|
185 |
+
|
186 |
+
.on( 'keyup', function(e) {
|
187 |
+
if ( e.which === 13 ) {
|
188 |
+
$( this ).trigger( 'change' );
|
189 |
+
}
|
190 |
+
} );
|
191 |
+
|
192 |
+
$( '.job_filters' ).on( 'click', '.reset', function () {
|
193 |
+
var target = $( this ).closest( 'div.job_listings' );
|
194 |
+
var form = $( this ).closest( 'form' );
|
195 |
+
|
196 |
+
form.find( ':input[name="search_keywords"], :input[name="search_location"], .job-manager-filter' ).not(':input[type="hidden"]').val( '' ).trigger( 'chosen:updated' );
|
197 |
+
form.find( ':input[name^="search_categories"]' ).not(':input[type="hidden"]').val( 0 ).trigger( 'chosen:updated' );
|
198 |
+
$( ':input[name="filter_job_type[]"]', form ).not(':input[type="hidden"]').attr( 'checked', 'checked' );
|
199 |
+
|
200 |
+
target.triggerHandler( 'reset' );
|
201 |
+
target.triggerHandler( 'update_results', [ 1, false ] );
|
202 |
+
job_manager_store_state( target, 1 );
|
203 |
+
|
204 |
+
return false;
|
205 |
+
} );
|
206 |
+
|
207 |
+
$( document.body ).on( 'click', '.load_more_jobs', function() {
|
208 |
+
var target = $( this ).closest( 'div.job_listings' );
|
209 |
+
var page = parseInt( ( $( this ).data( 'page' ) || 1 ), 10 );
|
210 |
+
var loading_previous = false;
|
211 |
+
|
212 |
+
$(this).addClass( 'loading' );
|
213 |
+
|
214 |
+
if ( $(this).is('.load_previous') ) {
|
215 |
+
page = page - 1;
|
216 |
+
loading_previous = true;
|
217 |
+
if ( page === 1 ) {
|
218 |
+
$(this).remove();
|
219 |
+
} else {
|
220 |
+
$( this ).data( 'page', page );
|
221 |
+
}
|
222 |
+
} else {
|
223 |
+
page = page + 1;
|
224 |
+
$( this ).data( 'page', page );
|
225 |
+
job_manager_store_state( target, page );
|
226 |
+
}
|
227 |
+
|
228 |
+
target.triggerHandler( 'update_results', [ page, true, loading_previous ] );
|
229 |
+
return false;
|
230 |
+
} );
|
231 |
+
|
232 |
+
$( 'div.job_listings' ).on( 'click', '.job-manager-pagination a', function() {
|
233 |
+
var target = $( this ).closest( 'div.job_listings' );
|
234 |
+
var page = $( this ).data( 'page' );
|
235 |
+
|
236 |
+
job_manager_store_state( target, page );
|
237 |
+
|
238 |
+
target.triggerHandler( 'update_results', [ page, false ] );
|
239 |
+
|
240 |
+
$( 'body, html' ).animate({
|
241 |
+
scrollTop: target.offset().top
|
242 |
+
}, 600 );
|
243 |
+
|
244 |
+
return false;
|
245 |
+
} );
|
246 |
+
|
247 |
+
if ( $.isFunction( $.fn.chosen ) ) {
|
248 |
+
if ( job_manager_ajax_filters.is_rtl === 1 ) {
|
249 |
+
$( 'select[name^="search_categories"]' ).addClass( 'chosen-rtl' );
|
250 |
+
}
|
251 |
+
$( 'select[name^="search_categories"]' ).chosen({ search_contains: true });
|
252 |
+
}
|
253 |
+
|
254 |
+
var $supports_html5_history = false;
|
255 |
+
if ( window.history && window.history.pushState ) {
|
256 |
+
$supports_html5_history = true;
|
257 |
+
}
|
258 |
+
|
259 |
+
var location = document.location.href.split('#')[0];
|
260 |
+
|
261 |
+
function job_manager_store_state( target, page ) {
|
262 |
+
if ( $supports_html5_history ) {
|
263 |
+
var form = target.find( '.job_filters' );
|
264 |
+
var data = $( form ).serialize();
|
265 |
+
var index = $( 'div.job_listings' ).index( target );
|
266 |
+
window.history.replaceState( { id: 'job_manager_state', page: page, data: data, index: index }, '', location + '#s=1' );
|
267 |
+
}
|
268 |
+
}
|
269 |
+
|
270 |
+
// Inital job and form population
|
271 |
+
$(window).on( 'load', function() {
|
272 |
+
$( '.job_filters' ).each( function() {
|
273 |
+
var target = $( this ).closest( 'div.job_listings' );
|
274 |
+
var form = target.find( '.job_filters' );
|
275 |
+
var inital_page = 1;
|
276 |
+
var index = $( 'div.job_listings' ).index( target );
|
277 |
+
|
278 |
+
if ( window.history.state && window.location.hash ) {
|
279 |
+
var state = window.history.state;
|
280 |
+
if ( state.id && 'job_manager_state' === state.id && index === state.index ) {
|
281 |
+
inital_page = state.page;
|
282 |
+
form.deserialize( state.data );
|
283 |
+
form.find( ':input[name^="search_categories"]' ).not(':input[type="hidden"]').trigger( 'chosen:updated' );
|
284 |
+
}
|
285 |
+
}
|
286 |
+
|
287 |
+
target.triggerHandler( 'update_results', [ inital_page, false ] );
|
288 |
+
});
|
289 |
+
});
|
290 |
+
} );
|
assets/js/ajax-filters.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
jQuery(document).ready(function(
|
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])})})});
|
assets/js/datepicker.min.js
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
jQuery(document).ready(function(t){var e={altFormat:"yy-mm-dd"};"undefined"!=typeof job_manager_datepicker&&(e.dateFormat=job_manager_datepicker.date_format),t("input.job-manager-datepicker, input#_job_expires").each(function(){var a=t("<input />",{type:"hidden",name:t(this).attr("name")}).insertAfter(t(this));if(t(this).attr("name",t(this).attr("name")+"-datepicker"),t(this).keyup(function(){""===t(this).val()&&a.val("")}),t(this).datepicker(t.extend({},e,{altField:a})),t(this).val()){var i=t(this).val().split("-");if(3===i.length){var n=new Date(parseInt(i[0],10),parseInt(i[1],10)-1,parseInt(i[2],10));t(this).datepicker("setDate",n)}}})});
|
|
assets/js/job-application.js
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(document).ready(function($) {
|
2 |
+
// Slide toggle
|
3 |
+
$( '.application_details' ).hide();
|
4 |
+
$( '.application_button' ).click(function() {
|
5 |
+
$( '.application_details' ).slideToggle();
|
6 |
+
});
|
7 |
+
});
|
assets/js/job-application.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
jQuery(document).ready(function(
|
1 |
+
jQuery(document).ready(function(a){a(".application_details").hide(),a(".application_button").click(function(){a(".application_details").slideToggle()})});
|
assets/js/job-dashboard.js
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* global job_manager_job_dashboard */
|
2 |
+
jQuery(document).ready(function($) {
|
3 |
+
|
4 |
+
$('.job-dashboard-action-delete').click(function() {
|
5 |
+
return window.confirm( job_manager_job_dashboard.i18n_confirm_delete );
|
6 |
+
});
|
7 |
+
|
8 |
+
});
|
assets/js/job-dashboard.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
jQuery(document).ready(function(
|
1 |
+
jQuery(document).ready(function(a){a(".job-dashboard-action-delete").click(function(){return window.confirm(job_manager_job_dashboard.i18n_confirm_delete)})});
|
assets/js/job-submission.js
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(document).ready(function($) {
|
2 |
+
$('body').on( 'click', '.job-manager-remove-uploaded-file', function() {
|
3 |
+
$(this).closest( '.job-manager-uploaded-file' ).remove();
|
4 |
+
return false;
|
5 |
+
});
|
6 |
+
});
|
assets/js/job-submission.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
jQuery(document).ready(function(
|
1 |
+
jQuery(document).ready(function(a){a("body").on("click",".job-manager-remove-uploaded-file",function(){return a(this).closest(".job-manager-uploaded-file").remove(),!1})});
|
assets/js/jquery-chosen/chosen.jquery.js
ADDED
@@ -0,0 +1,1229 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
Chosen, a Select Box Enhancer for jQuery and Prototype
|
3 |
+
by Patrick Filler for Harvest, http://getharvest.com
|
4 |
+
|
5 |
+
Version 1.2.0
|
6 |
+
Full source at https://github.com/harvesthq/chosen
|
7 |
+
Copyright (c) 2011-2014 Harvest http://getharvest.com
|
8 |
+
|
9 |
+
MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
|
10 |
+
This file is generated by `grunt build`, do not edit it by hand.
|
11 |
+
*/
|
12 |
+
|
13 |
+
(function() {
|
14 |
+
var $, AbstractChosen, Chosen, SelectParser, _ref,
|
15 |
+
__hasProp = {}.hasOwnProperty,
|
16 |
+
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
17 |
+
|
18 |
+
SelectParser = (function() {
|
19 |
+
function SelectParser() {
|
20 |
+
this.options_index = 0;
|
21 |
+
this.parsed = [];
|
22 |
+
}
|
23 |
+
|
24 |
+
SelectParser.prototype.add_node = function(child) {
|
25 |
+
if (child.nodeName.toUpperCase() === "OPTGROUP") {
|
26 |
+
return this.add_group(child);
|
27 |
+
} else {
|
28 |
+
return this.add_option(child);
|
29 |
+
}
|
30 |
+
};
|
31 |
+
|
32 |
+
SelectParser.prototype.add_group = function(group) {
|
33 |
+
var group_position, option, _i, _len, _ref, _results;
|
34 |
+
group_position = this.parsed.length;
|
35 |
+
this.parsed.push({
|
36 |
+
array_index: group_position,
|
37 |
+
group: true,
|
38 |
+
label: this.escapeExpression(group.label),
|
39 |
+
children: 0,
|
40 |
+
disabled: group.disabled
|
41 |
+
});
|
42 |
+
_ref = group.childNodes;
|
43 |
+
_results = [];
|
44 |
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
45 |
+
option = _ref[_i];
|
46 |
+
_results.push(this.add_option(option, group_position, group.disabled));
|
47 |
+
}
|
48 |
+
return _results;
|
49 |
+
};
|
50 |
+
|
51 |
+
SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
|
52 |
+
if (option.nodeName.toUpperCase() === "OPTION") {
|
53 |
+
if (option.text !== "") {
|
54 |
+
if (group_position != null) {
|
55 |
+
this.parsed[group_position].children += 1;
|
56 |
+
}
|
57 |
+
this.parsed.push({
|
58 |
+
array_index: this.parsed.length,
|
59 |
+
options_index: this.options_index,
|
60 |
+
value: option.value,
|
61 |
+
text: option.text,
|
62 |
+
html: option.innerHTML,
|
63 |
+
selected: option.selected,
|
64 |
+
disabled: group_disabled === true ? group_disabled : option.disabled,
|
65 |
+
group_array_index: group_position,
|
66 |
+
classes: option.className,
|
67 |
+
style: option.style.cssText
|
68 |
+
});
|
69 |
+
} else {
|
70 |
+
this.parsed.push({
|
71 |
+
array_index: this.parsed.length,
|
72 |
+
options_index: this.options_index,
|
73 |
+
empty: true
|
74 |
+
});
|
75 |
+
}
|
76 |
+
return this.options_index += 1;
|
77 |
+
}
|
78 |
+
};
|
79 |
+
|
80 |
+
SelectParser.prototype.escapeExpression = function(text) {
|
81 |
+
var map, unsafe_chars;
|
82 |
+
if ((text == null) || text === false) {
|
83 |
+
return "";
|
84 |
+
}
|
85 |
+
if (!/[\&\<\>\"\'\`]/.test(text)) {
|
86 |
+
return text;
|
87 |
+
}
|
88 |
+
map = {
|
89 |
+
"<": "<",
|
90 |
+
">": ">",
|
91 |
+
'"': """,
|
92 |
+
"'": "'",
|
93 |
+
"`": "`"
|
94 |
+
};
|
95 |
+
unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g;
|
96 |
+
return text.replace(unsafe_chars, function(chr) {
|
97 |
+
return map[chr] || "&";
|
98 |
+
});
|
99 |
+
};
|
100 |
+
|
101 |
+
return SelectParser;
|
102 |
+
|
103 |
+
})();
|
104 |
+
|
105 |
+
SelectParser.select_to_array = function(select) {
|
106 |
+
var child, parser, _i, _len, _ref;
|
107 |
+
parser = new SelectParser();
|
108 |
+
_ref = select.childNodes;
|
109 |
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
110 |
+
child = _ref[_i];
|
111 |
+
parser.add_node(child);
|
112 |
+
}
|
113 |
+
return parser.parsed;
|
114 |
+
};
|
115 |
+
|
116 |
+
AbstractChosen = (function() {
|
117 |
+
function AbstractChosen(form_field, options) {
|
118 |
+
this.form_field = form_field;
|
119 |
+
this.options = options != null ? options : {};
|
120 |
+
if (!AbstractChosen.browser_is_supported()) {
|
121 |
+
return;
|
122 |
+
}
|
123 |
+
this.is_multiple = this.form_field.multiple;
|
124 |
+
this.set_default_text();
|
125 |
+
this.set_default_values();
|
126 |
+
this.setup();
|
127 |
+
this.set_up_html();
|
128 |
+
this.register_observers();
|
129 |
+
}
|
130 |
+
|
131 |
+
AbstractChosen.prototype.set_default_values = function() {
|
132 |
+
var _this = this;
|
133 |
+
this.click_test_action = function(evt) {
|
134 |
+
return _this.test_active_click(evt);
|
135 |
+
};
|
136 |
+
this.activate_action = function(evt) {
|
137 |
+
return _this.activate_field(evt);
|
138 |
+
};
|
139 |
+
this.active_field = false;
|
140 |
+
this.mouse_on_container = false;
|
141 |
+
this.results_showing = false;
|
142 |
+
this.result_highlighted = null;
|
143 |
+
this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
|
144 |
+
this.disable_search_threshold = this.options.disable_search_threshold || 0;
|
145 |
+
this.disable_search = this.options.disable_search || false;
|
146 |
+
this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
|
147 |
+
this.group_search = this.options.group_search != null ? this.options.group_search : true;
|
148 |
+
this.search_contains = this.options.search_contains || false;
|
149 |
+
this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true;
|
150 |
+
this.max_selected_options = this.options.max_selected_options || Infinity;
|
151 |
+
this.inherit_select_classes = this.options.inherit_select_classes || false;
|
152 |
+
this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true;
|
153 |
+
return this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true;
|
154 |
+
};
|
155 |
+
|
156 |
+
AbstractChosen.prototype.set_default_text = function() {
|
157 |
+
if (this.form_field.getAttribute("data-placeholder")) {
|
158 |
+
this.default_text = this.form_field.getAttribute("data-placeholder");
|
159 |
+
} else if (this.is_multiple) {
|
160 |
+
this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
|
161 |
+
} else {
|
162 |
+
this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
|
163 |
+
}
|
164 |
+
return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
|
165 |
+
};
|
166 |
+
|
167 |
+
AbstractChosen.prototype.mouse_enter = function() {
|
168 |
+
return this.mouse_on_container = true;
|
169 |
+
};
|
170 |
+
|
171 |
+
AbstractChosen.prototype.mouse_leave = function() {
|
172 |
+
return this.mouse_on_container = false;
|
173 |
+
};
|
174 |
+
|
175 |
+
AbstractChosen.prototype.input_focus = function(evt) {
|
176 |
+
var _this = this;
|
177 |
+
if (this.is_multiple) {
|
178 |
+
if (!this.active_field) {
|
179 |
+
return setTimeout((function() {
|
180 |
+
return _this.container_mousedown();
|
181 |
+
}), 50);
|
182 |
+
}
|
183 |
+
} else {
|
184 |
+
if (!this.active_field) {
|
185 |
+
return this.activate_field();
|
186 |
+
}
|
187 |
+
}
|
188 |
+
};
|
189 |
+
|
190 |
+
AbstractChosen.prototype.input_blur = function(evt) {
|
191 |
+
var _this = this;
|
192 |
+
if (!this.mouse_on_container) {
|
193 |
+
this.active_field = false;
|
194 |
+
return setTimeout((function() {
|
195 |
+
return _this.blur_test();
|
196 |
+
}), 100);
|
197 |
+
}
|
198 |
+
};
|
199 |
+
|
200 |
+
AbstractChosen.prototype.results_option_build = function(options) {
|
201 |
+
var content, data, _i, _len, _ref;
|
202 |
+
content = '';
|
203 |
+
_ref = this.results_data;
|
204 |
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
205 |
+
data = _ref[_i];
|
206 |
+
if (data.group) {
|
207 |
+
content += this.result_add_group(data);
|
208 |
+
} else {
|
209 |
+
content += this.result_add_option(data);
|
210 |
+
}
|
211 |
+
if (options != null ? options.first : void 0) {
|
212 |
+
if (data.selected && this.is_multiple) {
|
213 |
+
this.choice_build(data);
|
214 |
+
} else if (data.selected && !this.is_multiple) {
|
215 |
+
this.single_set_selected_text(data.text);
|
216 |
+
}
|
217 |
+
}
|
218 |
+
}
|
219 |
+
return content;
|
220 |
+
};
|
221 |
+
|
222 |
+
AbstractChosen.prototype.result_add_option = function(option) {
|
223 |
+
var classes, option_el;
|
224 |
+
if (!option.search_match) {
|
225 |
+
return '';
|
226 |
+
}
|
227 |
+
if (!this.include_option_in_results(option)) {
|
228 |
+
return '';
|
229 |
+
}
|
230 |
+
classes = [];
|
231 |
+
if (!option.disabled && !(option.selected && this.is_multiple)) {
|
232 |
+
classes.push("active-result");
|
233 |
+
}
|
234 |
+
if (option.disabled && !(option.selected && this.is_multiple)) {
|
235 |
+
classes.push("disabled-result");
|
236 |
+
}
|
237 |
+
if (option.selected) {
|
238 |
+
classes.push("result-selected");
|
239 |
+
}
|
240 |
+
if (option.group_array_index != null) {
|
241 |
+
classes.push("group-option");
|
242 |
+
}
|
243 |
+
if (option.classes !== "") {
|
244 |
+
classes.push(option.classes);
|
245 |
+
}
|
246 |
+
option_el = document.createElement("li");
|
247 |
+
option_el.className = classes.join(" ");
|
248 |
+
option_el.style.cssText = option.style;
|
249 |
+
option_el.setAttribute("data-option-array-index", option.array_index);
|
250 |
+
option_el.innerHTML = option.search_text;
|
251 |
+
return this.outerHTML(option_el);
|
252 |
+
};
|
253 |
+
|
254 |
+
AbstractChosen.prototype.result_add_group = function(group) {
|
255 |
+
var group_el;
|
256 |
+
if (!(group.search_match || group.group_match)) {
|
257 |
+
return '';
|
258 |
+
}
|
259 |
+
if (!(group.active_options > 0)) {
|
260 |
+
return '';
|
261 |
+
}
|
262 |
+
group_el = document.createElement("li");
|
263 |
+
group_el.className = "group-result";
|
264 |
+
group_el.innerHTML = group.search_text;
|
265 |
+
return this.outerHTML(group_el);
|
266 |
+
};
|
267 |
+
|
268 |
+
AbstractChosen.prototype.results_update_field = function() {
|
269 |
+
this.set_default_text();
|
270 |
+
if (!this.is_multiple) {
|
271 |
+
this.results_reset_cleanup();
|
272 |
+
}
|
273 |
+
this.result_clear_highlight();
|
274 |
+
this.results_build();
|
275 |
+
if (this.results_showing) {
|
276 |
+
return this.winnow_results();
|
277 |
+
}
|
278 |
+
};
|
279 |
+
|
280 |
+
AbstractChosen.prototype.reset_single_select_options = function() {
|
281 |
+
var result, _i, _len, _ref, _results;
|
282 |
+
_ref = this.results_data;
|
283 |
+
_results = [];
|
284 |
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
285 |
+
result = _ref[_i];
|
286 |
+
if (result.selected) {
|
287 |
+
_results.push(result.selected = false);
|
288 |
+
} else {
|
289 |
+
_results.push(void 0);
|
290 |
+
}
|
291 |
+
}
|
292 |
+
return _results;
|
293 |
+
};
|
294 |
+
|
295 |
+
AbstractChosen.prototype.results_toggle = function() {
|
296 |
+
if (this.results_showing) {
|
297 |
+
return this.results_hide();
|
298 |
+
} else {
|
299 |
+
return this.results_show();
|
300 |
+
}
|
301 |
+
};
|
302 |
+
|
303 |
+
AbstractChosen.prototype.results_search = function(evt) {
|
304 |
+
if (this.results_showing) {
|
305 |
+
return this.winnow_results();
|
306 |
+
} else {
|
307 |
+
return this.results_show();
|
308 |
+
}
|
309 |
+
};
|
310 |
+
|
311 |
+
AbstractChosen.prototype.winnow_results = function() {
|
312 |
+
var escapedSearchText, option, regex, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref;
|
313 |
+
this.no_results_clear();
|
314 |
+
results = 0;
|
315 |
+
searchText = this.get_search_text();
|
316 |
+
escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
317 |
+
zregex = new RegExp(escapedSearchText, 'i');
|
318 |
+
regex = this.get_search_regex(escapedSearchText);
|
319 |
+
_ref = this.results_data;
|
320 |
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
321 |
+
option = _ref[_i];
|
322 |
+
option.search_match = false;
|
323 |
+
results_group = null;
|
324 |
+
if (this.include_option_in_results(option)) {
|
325 |
+
if (option.group) {
|
326 |
+
option.group_match = false;
|
327 |
+
option.active_options = 0;
|
328 |
+
}
|
329 |
+
if ((option.group_array_index != null) && this.results_data[option.group_array_index]) {
|
330 |
+
results_group = this.results_data[option.group_array_index];
|
331 |
+
if (results_group.active_options === 0 && results_group.search_match) {
|
332 |
+
results += 1;
|
333 |
+
}
|
334 |
+
results_group.active_options += 1;
|
335 |
+
}
|
336 |
+
if (!(option.group && !this.group_search)) {
|
337 |
+
option.search_text = option.group ? option.label : option.text;
|
338 |
+
option.search_match = this.search_string_match(option.search_text, regex);
|
339 |
+
if (option.search_match && !option.group) {
|
340 |
+
results += 1;
|
341 |
+
}
|
342 |
+
if (option.search_match) {
|
343 |
+
if (searchText.length) {
|
344 |
+
startpos = option.search_text.search(zregex);
|
345 |
+
text = option.search_text.substr(0, startpos + searchText.length) + '</em>' + option.search_text.substr(startpos + searchText.length);
|
346 |
+
option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
|
347 |
+
}
|
348 |
+
if (results_group != null) {
|
349 |
+
results_group.group_match = true;
|
350 |
+
}
|
351 |
+
} else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) {
|
352 |
+
option.search_match = true;
|
353 |
+
}
|
354 |
+
}
|
355 |
+
}
|
356 |
+
}
|
357 |
+
this.result_clear_highlight();
|
358 |
+
if (results < 1 && searchText.length) {
|
359 |
+
this.update_results_content("");
|
360 |
+
return this.no_results(searchText);
|
361 |
+
} else {
|
362 |
+
this.update_results_content(this.results_option_build());
|
363 |
+
return this.winnow_results_set_highlight();
|
364 |
+
}
|
365 |
+
};
|
366 |
+
|
367 |
+
AbstractChosen.prototype.get_search_regex = function(escaped_search_string) {
|
368 |
+
var regex_anchor;
|
369 |
+
regex_anchor = this.search_contains ? "" : "^";
|
370 |
+
return new RegExp(regex_anchor + escaped_search_string, 'i');
|
371 |
+
};
|
372 |
+
|
373 |
+
AbstractChosen.prototype.search_string_match = function(search_string, regex) {
|
374 |
+
var part, parts, _i, _len;
|
375 |
+
if (regex.test(search_string)) {
|
376 |
+
return true;
|
377 |
+
} else if (this.enable_split_word_search && (search_string.indexOf(" ") >= 0 || search_string.indexOf("[") === 0)) {
|
378 |
+
parts = search_string.replace(/\[|\]/g, "").split(" ");
|
379 |
+
if (parts.length) {
|
380 |
+
for (_i = 0, _len = parts.length; _i < _len; _i++) {
|
381 |
+
part = parts[_i];
|
382 |
+
if (regex.test(part)) {
|
383 |
+
return true;
|
384 |
+
}
|
385 |
+
}
|
386 |
+
}
|
387 |
+
}
|
388 |
+
};
|
389 |
+
|
390 |
+
AbstractChosen.prototype.choices_count = function() {
|
391 |
+
var option, _i, _len, _ref;
|
392 |
+
if (this.selected_option_count != null) {
|
393 |
+
return this.selected_option_count;
|
394 |
+
}
|
395 |
+
this.selected_option_count = 0;
|
396 |
+
_ref = this.form_field.options;
|
397 |
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
398 |
+
option = _ref[_i];
|
399 |
+
if (option.selected) {
|
400 |
+
this.selected_option_count += 1;
|
401 |
+
}
|
402 |
+
}
|
403 |
+
return this.selected_option_count;
|
404 |
+
};
|
405 |
+
|
406 |
+
AbstractChosen.prototype.choices_click = function(evt) {
|
407 |
+
evt.preventDefault();
|
408 |
+
if (!(this.results_showing || this.is_disabled)) {
|
409 |
+
return this.results_show();
|
410 |
+
}
|
411 |
+
};
|
412 |
+
|
413 |
+
AbstractChosen.prototype.keyup_checker = function(evt) {
|
414 |
+
var stroke, _ref;
|
415 |
+
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
|
416 |
+
this.search_field_scale();
|
417 |
+
switch (stroke) {
|
418 |
+
case 8:
|
419 |
+
if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {
|
420 |
+
return this.keydown_backstroke();
|
421 |
+
} else if (!this.pending_backstroke) {
|
422 |
+
this.result_clear_highlight();
|
423 |
+
return this.results_search();
|
424 |
+
}
|
425 |
+
break;
|
426 |
+
case 13:
|
427 |
+
evt.preventDefault();
|
428 |
+
if (this.results_showing) {
|
429 |
+
return this.result_select(evt);
|
430 |
+
}
|
431 |
+
break;
|
432 |
+
case 27:
|
433 |
+
if (this.results_showing) {
|
434 |
+
this.results_hide();
|
435 |
+
}
|
436 |
+
return true;
|
437 |
+
case 9:
|
438 |
+
case 38:
|
439 |
+
case 40:
|
440 |
+
case 16:
|
441 |
+
case 91:
|
442 |
+
case 17:
|
443 |
+
break;
|
444 |
+
default:
|
445 |
+
return this.results_search();
|
446 |
+
}
|
447 |
+
};
|
448 |
+
|
449 |
+
AbstractChosen.prototype.clipboard_event_checker = function(evt) {
|
450 |
+
var _this = this;
|
451 |
+
return setTimeout((function() {
|
452 |
+
return _this.results_search();
|
453 |
+
}), 50);
|
454 |
+
};
|
455 |
+
|
456 |
+
AbstractChosen.prototype.container_width = function() {
|
457 |
+
if (this.options.width != null) {
|
458 |
+
return this.options.width;
|
459 |
+
} else {
|
460 |
+
return "" + this.form_field.offsetWidth + "px";
|
461 |
+
}
|
462 |
+
};
|
463 |
+
|
464 |
+
AbstractChosen.prototype.include_option_in_results = function(option) {
|
465 |
+
if (this.is_multiple && (!this.display_selected_options && option.selected)) {
|
466 |
+
return false;
|
467 |
+
}
|
468 |
+
if (!this.display_disabled_options && option.disabled) {
|
469 |
+
return false;
|
470 |
+
}
|
471 |
+
if (option.empty) {
|
472 |
+
return false;
|
473 |
+
}
|
474 |
+
return true;
|
475 |
+
};
|
476 |
+
|
477 |
+
AbstractChosen.prototype.search_results_touchstart = function(evt) {
|
478 |
+
this.touch_started = true;
|
479 |
+
return this.search_results_mouseover(evt);
|
480 |
+
};
|
481 |
+
|
482 |
+
AbstractChosen.prototype.search_results_touchmove = function(evt) {
|
483 |
+
this.touch_started = false;
|
484 |
+
return this.search_results_mouseout(evt);
|
485 |
+
};
|
486 |
+
|
487 |
+
AbstractChosen.prototype.search_results_touchend = function(evt) {
|
488 |
+
if (this.touch_started) {
|
489 |
+
return this.search_results_mouseup(evt);
|
490 |
+
}
|
491 |
+
};
|
492 |
+
|
493 |
+
AbstractChosen.prototype.outerHTML = function(element) {
|
494 |
+
var tmp;
|
495 |
+
if (element.outerHTML) {
|
496 |
+
return element.outerHTML;
|
497 |
+
}
|
498 |
+
tmp = document.createElement("div");
|
499 |
+
tmp.appendChild(element);
|
500 |
+
return tmp.innerHTML;
|
501 |
+
};
|
502 |
+
|
503 |
+
AbstractChosen.browser_is_supported = function() {
|
504 |
+
if (window.navigator.appName === "Microsoft Internet Explorer") {
|
505 |
+
return document.documentMode >= 8;
|
506 |
+
}
|
507 |
+
if (/iP(od|hone)/i.test(window.navigator.userAgent)) {
|
508 |
+
return false;
|
509 |
+
}
|
510 |
+
if (/Android/i.test(window.navigator.userAgent)) {
|
511 |
+
if (/Mobile/i.test(window.navigator.userAgent)) {
|
512 |
+
return false;
|
513 |
+
}
|
514 |
+
}
|
515 |
+
return true;
|
516 |
+
};
|
517 |
+
|
518 |
+
AbstractChosen.default_multiple_text = "Select Some Options";
|
519 |
+
|
520 |
+
AbstractChosen.default_single_text = "Select an Option";
|
521 |
+
|
522 |
+
AbstractChosen.default_no_result_text = "No results match";
|
523 |
+
|
524 |
+
return AbstractChosen;
|
525 |
+
|
526 |
+
})();
|
527 |
+
|
528 |
+
$ = jQuery;
|
529 |
+
|
530 |
+
$.fn.extend({
|
531 |
+
chosen: function(options) {
|
532 |
+
if (!AbstractChosen.browser_is_supported()) {
|
533 |
+
return this;
|
534 |
+
}
|
535 |
+
return this.each(function(input_field) {
|
536 |
+
var $this, chosen;
|
537 |
+
$this = $(this);
|
538 |
+
chosen = $this.data('chosen');
|
539 |
+
if (options === 'destroy' && chosen instanceof Chosen) {
|
540 |
+
chosen.destroy();
|
541 |
+
} else if (!(chosen instanceof Chosen)) {
|
542 |
+
$this.data('chosen', new Chosen(this, options));
|
543 |
+
}
|
544 |
+
});
|
545 |
+
}
|
546 |
+
});
|
547 |
+
|
548 |
+
Chosen = (function(_super) {
|
549 |
+
__extends(Chosen, _super);
|
550 |
+
|
551 |
+
function Chosen() {
|
552 |
+
_ref = Chosen.__super__.constructor.apply(this, arguments);
|
553 |
+
return _ref;
|
554 |
+
}
|
555 |
+
|
556 |
+
Chosen.prototype.setup = function() {
|
557 |
+
this.form_field_jq = $(this.form_field);
|
558 |
+
this.current_selectedIndex = this.form_field.selectedIndex;
|
559 |
+
return this.is_rtl = this.form_field_jq.hasClass("chosen-rtl");
|
560 |
+
};
|
561 |
+
|
562 |
+
Chosen.prototype.set_up_html = function() {
|
563 |
+
var container_classes, container_props;
|
564 |
+
container_classes = ["chosen-container"];
|
565 |
+
container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single"));
|
566 |
+
if (this.inherit_select_classes && this.form_field.className) {
|
567 |
+
container_classes.push(this.form_field.className);
|
568 |
+
}
|
569 |
+
if (this.is_rtl) {
|
570 |
+
container_classes.push("chosen-rtl");
|
571 |
+
}
|
572 |
+
container_props = {
|
573 |
+
'class': container_classes.join(' '),
|
574 |
+
'style': "width: " + (this.container_width()) + ";",
|
575 |
+
'title': this.form_field.title
|
576 |
+
};
|
577 |
+
if (this.form_field.id.length) {
|
578 |
+
container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen";
|
579 |
+
}
|
580 |
+
this.container = $("<div />", container_props);
|
581 |
+
if (this.is_multiple) {
|
582 |
+
this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>');
|
583 |
+
} else {
|
584 |
+
this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>');
|
585 |
+
}
|
586 |
+
this.form_field_jq.hide().after(this.container);
|
587 |
+
this.dropdown = this.container.find('div.chosen-drop').first();
|
588 |
+
this.search_field = this.container.find('input').first();
|
589 |
+
this.search_results = this.container.find('ul.chosen-results').first();
|
590 |
+
this.search_field_scale();
|
591 |
+
this.search_no_results = this.container.find('li.no-results').first();
|
592 |
+
if (this.is_multiple) {
|
593 |
+
this.search_choices = this.container.find('ul.chosen-choices').first();
|
594 |
+
this.search_container = this.container.find('li.search-field').first();
|
595 |
+
} else {
|
596 |
+
this.search_container = this.container.find('div.chosen-search').first();
|
597 |
+
this.selected_item = this.container.find('.chosen-single').first();
|
598 |
+
}
|
599 |
+
this.results_build();
|
600 |
+
this.set_tab_index();
|
601 |
+
this.set_label_behavior();
|
602 |
+
return this.form_field_jq.trigger("chosen:ready", {
|
603 |
+
chosen: this
|
604 |
+
});
|
605 |
+
};
|
606 |
+
|
607 |
+
Chosen.prototype.register_observers = function() {
|
608 |
+
var _this = this;
|
609 |
+
this.container.bind('touchstart.chosen', function(evt) {
|
610 |
+
_this.container_mousedown(evt);
|
611 |
+
});
|
612 |
+
this.container.bind('touchend.chosen', function(evt) {
|
613 |
+
_this.container_mouseup(evt);
|
614 |
+
});
|
615 |
+
this.container.bind('mousedown.chosen', function(evt) {
|
616 |
+
_this.container_mousedown(evt);
|
617 |
+
});
|
618 |
+
this.container.bind('mouseup.chosen', function(evt) {
|
619 |
+
_this.container_mouseup(evt);
|
620 |
+
});
|
621 |
+
this.container.bind('mouseenter.chosen', function(evt) {
|
622 |
+
_this.mouse_enter(evt);
|
623 |
+
});
|
624 |
+
this.container.bind('mouseleave.chosen', function(evt) {
|
625 |
+
_this.mouse_leave(evt);
|
626 |
+
});
|
627 |
+
this.search_results.bind('mouseup.chosen', function(evt) {
|
628 |
+
_this.search_results_mouseup(evt);
|
629 |
+
});
|
630 |
+
this.search_results.bind('mouseover.chosen', function(evt) {
|
631 |
+
_this.search_results_mouseover(evt);
|
632 |
+
});
|
633 |
+
this.search_results.bind('mouseout.chosen', function(evt) {
|
634 |
+
_this.search_results_mouseout(evt);
|
635 |
+
});
|
636 |
+
this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) {
|
637 |
+
_this.search_results_mousewheel(evt);
|
638 |
+
});
|
639 |
+
this.search_results.bind('touchstart.chosen', function(evt) {
|
640 |
+
_this.search_results_touchstart(evt);
|
641 |
+
});
|
642 |
+
this.search_results.bind('touchmove.chosen', function(evt) {
|
643 |
+
_this.search_results_touchmove(evt);
|
644 |
+
});
|
645 |
+
this.search_results.bind('touchend.chosen', function(evt) {
|
646 |
+
_this.search_results_touchend(evt);
|
647 |
+
});
|
648 |
+
this.form_field_jq.bind("chosen:updated.chosen", function(evt) {
|
649 |
+
_this.results_update_field(evt);
|
650 |
+
});
|
651 |
+
this.form_field_jq.bind("chosen:activate.chosen", function(evt) {
|
652 |
+
_this.activate_field(evt);
|
653 |
+
});
|
654 |
+
this.form_field_jq.bind("chosen:open.chosen", function(evt) {
|
655 |
+
_this.container_mousedown(evt);
|
656 |
+
});
|
657 |
+
this.form_field_jq.bind("chosen:close.chosen", function(evt) {
|
658 |
+
_this.input_blur(evt);
|
659 |
+
});
|
660 |
+
this.search_field.bind('blur.chosen', function(evt) {
|
661 |
+
_this.input_blur(evt);
|
662 |
+
});
|
663 |
+
this.search_field.bind('keyup.chosen', function(evt) {
|
664 |
+
_this.keyup_checker(evt);
|
665 |
+
});
|
666 |
+
this.search_field.bind('keydown.chosen', function(evt) {
|
667 |
+
_this.keydown_checker(evt);
|
668 |
+
});
|
669 |
+
this.search_field.bind('focus.chosen', function(evt) {
|
670 |
+
_this.input_focus(evt);
|
671 |
+
});
|
672 |
+
this.search_field.bind('cut.chosen', function(evt) {
|
673 |
+
_this.clipboard_event_checker(evt);
|
674 |
+
});
|
675 |
+
this.search_field.bind('paste.chosen', function(evt) {
|
676 |
+
_this.clipboard_event_checker(evt);
|
677 |
+
});
|
678 |
+
if (this.is_multiple) {
|
679 |
+
return this.search_choices.bind('click.chosen', function(evt) {
|
680 |
+
_this.choices_click(evt);
|
681 |
+
});
|
682 |
+
} else {
|
683 |
+
return this.container.bind('click.chosen', function(evt) {
|
684 |
+
evt.preventDefault();
|
685 |
+
});
|
686 |
+
}
|
687 |
+
};
|
688 |
+
|
689 |
+
Chosen.prototype.destroy = function() {
|
690 |
+
$(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
|
691 |
+
if (this.search_field[0].tabIndex) {
|
692 |
+
this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex;
|
693 |
+
}
|
694 |
+
this.container.remove();
|
695 |
+
this.form_field_jq.removeData('chosen');
|
696 |
+
return this.form_field_jq.show();
|
697 |
+
};
|
698 |
+
|
699 |
+
Chosen.prototype.search_field_disabled = function() {
|
700 |
+
this.is_disabled = this.form_field_jq[0].disabled;
|
701 |
+
if (this.is_disabled) {
|
702 |
+
this.container.addClass('chosen-disabled');
|
703 |
+
this.search_field[0].disabled = true;
|
704 |
+
if (!this.is_multiple) {
|
705 |
+
this.selected_item.unbind("focus.chosen", this.activate_action);
|
706 |
+
}
|
707 |
+
return this.close_field();
|
708 |
+
} else {
|
709 |
+
this.container.removeClass('chosen-disabled');
|
710 |
+
this.search_field[0].disabled = false;
|
711 |
+
if (!this.is_multiple) {
|
712 |
+
return this.selected_item.bind("focus.chosen", this.activate_action);
|
713 |
+
}
|
714 |
+
}
|
715 |
+
};
|
716 |
+
|
717 |
+
Chosen.prototype.container_mousedown = function(evt) {
|
718 |
+
if (!this.is_disabled) {
|
719 |
+
if (evt && evt.type === "mousedown" && !this.results_showing) {
|
720 |
+
evt.preventDefault();
|
721 |
+
}
|
722 |
+
if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
|
723 |
+
if (!this.active_field) {
|
724 |
+
if (this.is_multiple) {
|
725 |
+
this.search_field.val("");
|
726 |
+
}
|
727 |
+
$(this.container[0].ownerDocument).bind('click.chosen', this.click_test_action);
|
728 |
+
this.results_show();
|
729 |
+
} else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) {
|
730 |
+
evt.preventDefault();
|
731 |
+
this.results_toggle();
|
732 |
+
}
|
733 |
+
return this.activate_field();
|
734 |
+
}
|
735 |
+
}
|
736 |
+
};
|
737 |
+
|
738 |
+
Chosen.prototype.container_mouseup = function(evt) {
|
739 |
+
if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
|
740 |
+
return this.results_reset(evt);
|
741 |
+
}
|
742 |
+
};
|
743 |
+
|
744 |
+
Chosen.prototype.search_results_mousewheel = function(evt) {
|
745 |
+
var delta;
|
746 |
+
if (evt.originalEvent) {
|
747 |
+
delta = evt.originalEvent.deltaY || -evt.originalEvent.wheelDelta || evt.originalEvent.detail;
|
748 |
+
}
|
749 |
+
if (delta != null) {
|
750 |
+
evt.preventDefault();
|
751 |
+
if (evt.type === 'DOMMouseScroll') {
|
752 |
+
delta = delta * 40;
|
753 |
+
}
|
754 |
+
return this.search_results.scrollTop(delta + this.search_results.scrollTop());
|
755 |
+
}
|
756 |
+
};
|
757 |
+
|
758 |
+
Chosen.prototype.blur_test = function(evt) {
|
759 |
+
if (!this.active_field && this.container.hasClass("chosen-container-active")) {
|
760 |
+
return this.close_field();
|
761 |
+
}
|
762 |
+
};
|
763 |
+
|
764 |
+
Chosen.prototype.close_field = function() {
|
765 |
+
$(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
|
766 |
+
this.active_field = false;
|
767 |
+
this.results_hide();
|
768 |
+
this.container.removeClass("chosen-container-active");
|
769 |
+
this.clear_backstroke();
|
770 |
+
this.show_search_field_default();
|
771 |
+
return this.search_field_scale();
|
772 |
+
};
|
773 |
+
|
774 |
+
Chosen.prototype.activate_field = function() {
|
775 |
+
this.container.addClass("chosen-container-active");
|
776 |
+
this.active_field = true;
|
777 |
+
this.search_field.val(this.search_field.val());
|
778 |
+
return this.search_field.focus();
|
779 |
+
};
|
780 |
+
|
781 |
+
Chosen.prototype.test_active_click = function(evt) {
|
782 |
+
var active_container;
|
783 |
+
active_container = $(evt.target).closest('.chosen-container');
|
784 |
+
if (active_container.length && this.container[0] === active_container[0]) {
|
785 |
+
return this.active_field = true;
|
786 |
+
} else {
|
787 |
+
return this.close_field();
|
788 |
+
}
|
789 |
+
};
|
790 |
+
|
791 |
+
Chosen.prototype.results_build = function() {
|
792 |
+
this.parsing = true;
|
793 |
+
this.selected_option_count = null;
|
794 |
+
this.results_data = SelectParser.select_to_array(this.form_field);
|
795 |
+
if (this.is_multiple) {
|
796 |
+
this.search_choices.find("li.search-choice").remove();
|
797 |
+
} else if (!this.is_multiple) {
|
798 |
+
this.single_set_selected_text();
|
799 |
+
if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
|
800 |
+
this.search_field[0].readOnly = true;
|
801 |
+
this.container.addClass("chosen-container-single-nosearch");
|
802 |
+
} else {
|
803 |
+
this.search_field[0].readOnly = false;
|
804 |
+
this.container.removeClass("chosen-container-single-nosearch");
|
805 |
+
}
|
806 |
+
}
|
807 |
+
this.update_results_content(this.results_option_build({
|
808 |
+
first: true
|
809 |
+
}));
|
810 |
+
this.search_field_disabled();
|
811 |
+
this.show_search_field_default();
|
812 |
+
this.search_field_scale();
|
813 |
+
return this.parsing = false;
|
814 |
+
};
|
815 |
+
|
816 |
+
Chosen.prototype.result_do_highlight = function(el) {
|
817 |
+
var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
|
818 |
+
if (el.length) {
|
819 |
+
this.result_clear_highlight();
|
820 |
+
this.result_highlight = el;
|
821 |
+
this.result_highlight.addClass("highlighted");
|
822 |
+
maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
|
823 |
+
visible_top = this.search_results.scrollTop();
|
824 |
+
visible_bottom = maxHeight + visible_top;
|
825 |
+
high_top = this.result_highlight.position().top + this.search_results.scrollTop();
|
826 |
+
high_bottom = high_top + this.result_highlight.outerHeight();
|
827 |
+
if (high_bottom >= visible_bottom) {
|
828 |
+
return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
|
829 |
+
} else if (high_top < visible_top) {
|
830 |
+
return this.search_results.scrollTop(high_top);
|
831 |
+
}
|
832 |
+
}
|
833 |
+
};
|
834 |
+
|
835 |
+
Chosen.prototype.result_clear_highlight = function() {
|
836 |
+
if (this.result_highlight) {
|
837 |
+
this.result_highlight.removeClass("highlighted");
|
838 |
+
}
|
839 |
+
return this.result_highlight = null;
|
840 |
+
};
|
841 |
+
|
842 |
+
Chosen.prototype.results_show = function() {
|
843 |
+
if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
|
844 |
+
this.form_field_jq.trigger("chosen:maxselected", {
|
845 |
+
chosen: this
|
846 |
+
});
|
847 |
+
return false;
|
848 |
+
}
|
849 |
+
this.container.addClass("chosen-with-drop");
|
850 |
+
this.results_showing = true;
|
851 |
+
this.search_field.focus();
|
852 |
+
this.search_field.val(this.search_field.val());
|
853 |
+
this.winnow_results();
|
854 |
+
return this.form_field_jq.trigger("chosen:showing_dropdown", {
|
855 |
+
chosen: this
|
856 |
+
});
|
857 |
+
};
|
858 |
+
|
859 |
+
Chosen.prototype.update_results_content = function(content) {
|
860 |
+
return this.search_results.html(content);
|
861 |
+
};
|
862 |
+
|
863 |
+
Chosen.prototype.results_hide = function() {
|
864 |
+
if (this.results_showing) {
|
865 |
+
this.result_clear_highlight();
|
866 |
+
this.container.removeClass("chosen-with-drop");
|
867 |
+
this.form_field_jq.trigger("chosen:hiding_dropdown", {
|
868 |
+
chosen: this
|
869 |
+
});
|
870 |
+
}
|
871 |
+
return this.results_showing = false;
|
872 |
+
};
|
873 |
+
|
874 |
+
Chosen.prototype.set_tab_index = function(el) {
|
875 |
+
var ti;
|
876 |
+
if (this.form_field.tabIndex) {
|
877 |
+
ti = this.form_field.tabIndex;
|
878 |
+
this.form_field.tabIndex = -1;
|
879 |
+
return this.search_field[0].tabIndex = ti;
|
880 |
+
}
|
881 |
+
};
|
882 |
+
|
883 |
+
Chosen.prototype.set_label_behavior = function() {
|
884 |
+
var _this = this;
|
885 |
+
this.form_field_label = this.form_field_jq.parents("label");
|
886 |
+
if (!this.form_field_label.length && this.form_field.id.length) {
|
887 |
+
this.form_field_label = $("label[for='" + this.form_field.id + "']");
|
888 |
+
}
|
889 |
+
if (this.form_field_label.length > 0) {
|
890 |
+
return this.form_field_label.bind('click.chosen', function(evt) {
|
891 |
+
if (_this.is_multiple) {
|
892 |
+
return _this.container_mousedown(evt);
|
893 |
+
} else {
|
894 |
+
return _this.activate_field();
|
895 |
+
}
|
896 |
+
});
|
897 |
+
}
|
898 |
+
};
|
899 |
+
|
900 |
+
Chosen.prototype.show_search_field_default = function() {
|
901 |
+
if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {
|
902 |
+
this.search_field.val(this.default_text);
|
903 |
+
return this.search_field.addClass("default");
|
904 |
+
} else {
|
905 |
+
this.search_field.val("");
|
906 |
+
return this.search_field.removeClass("default");
|
907 |
+
}
|
908 |
+
};
|
909 |
+
|
910 |
+
Chosen.prototype.search_results_mouseup = function(evt) {
|
911 |
+
var target;
|
912 |
+
target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
|
913 |
+
if (target.length) {
|
914 |
+
this.result_highlight = target;
|
915 |
+
this.result_select(evt);
|
916 |
+
return this.search_field.focus();
|
917 |
+
}
|
918 |
+
};
|
919 |
+
|
920 |
+
Chosen.prototype.search_results_mouseover = function(evt) {
|
921 |
+
var target;
|
922 |
+
target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
|
923 |
+
if (target) {
|
924 |
+
return this.result_do_highlight(target);
|
925 |
+
}
|
926 |
+
};
|
927 |
+
|
928 |
+
Chosen.prototype.search_results_mouseout = function(evt) {
|
929 |
+
if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
|
930 |
+
return this.result_clear_highlight();
|
931 |
+
}
|
932 |
+
};
|
933 |
+
|
934 |
+
Chosen.prototype.choice_build = function(item) {
|
935 |
+
var choice, close_link,
|
936 |
+
_this = this;
|
937 |
+
choice = $('<li />', {
|
938 |
+
"class": "search-choice"
|
939 |
+
}).html("<span>" + item.html + "</span>");
|
940 |
+
if (item.disabled) {
|
941 |
+
choice.addClass('search-choice-disabled');
|
942 |
+
} else {
|
943 |
+
close_link = $('<a />', {
|
944 |
+
"class": 'search-choice-close',
|
945 |
+
'data-option-array-index': item.array_index
|
946 |
+
});
|
947 |
+
close_link.bind('click.chosen', function(evt) {
|
948 |
+
return _this.choice_destroy_link_click(evt);
|
949 |
+
});
|
950 |
+
choice.append(close_link);
|
951 |
+
}
|
952 |
+
return this.search_container.before(choice);
|
953 |
+
};
|
954 |
+
|
955 |
+
Chosen.prototype.choice_destroy_link_click = function(evt) {
|
956 |
+
evt.preventDefault();
|
957 |
+
evt.stopPropagation();
|
958 |
+
if (!this.is_disabled) {
|
959 |
+
return this.choice_destroy($(evt.target));
|
960 |
+
}
|
961 |
+
};
|
962 |
+
|
963 |
+
Chosen.prototype.choice_destroy = function(link) {
|
964 |
+
if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) {
|
965 |
+
this.show_search_field_default();
|
966 |
+
if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) {
|
967 |
+
this.results_hide();
|
968 |
+
}
|
969 |
+
link.parents('li').first().remove();
|
970 |
+
return this.search_field_scale();
|
971 |
+
}
|
972 |
+
};
|
973 |
+
|
974 |
+
Chosen.prototype.results_reset = function() {
|
975 |
+
this.reset_single_select_options();
|
976 |
+
this.form_field.options[0].selected = true;
|
977 |
+
this.single_set_selected_text();
|
978 |
+
this.show_search_field_default();
|
979 |
+
this.results_reset_cleanup();
|
980 |
+
this.form_field_jq.trigger("change");
|
981 |
+
if (this.active_field) {
|
982 |
+
return this.results_hide();
|
983 |
+
}
|
984 |
+
};
|
985 |
+
|
986 |
+
Chosen.prototype.results_reset_cleanup = function() {
|
987 |
+
this.current_selectedIndex = this.form_field.selectedIndex;
|
988 |
+
return this.selected_item.find("abbr").remove();
|
989 |
+
};
|
990 |
+
|
991 |
+
Chosen.prototype.result_select = function(evt) {
|
992 |
+
var high, item;
|
993 |
+
if (this.result_highlight) {
|
994 |
+
high = this.result_highlight;
|
995 |
+
this.result_clear_highlight();
|
996 |
+
if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
|
997 |
+
this.form_field_jq.trigger("chosen:maxselected", {
|
998 |
+
chosen: this
|
999 |
+
});
|
1000 |
+
return false;
|
1001 |
+
}
|
1002 |
+
if (this.is_multiple) {
|
1003 |
+
high.removeClass("active-result");
|
1004 |
+
} else {
|
1005 |
+
this.reset_single_select_options();
|
1006 |
+
}
|
1007 |
+
item = this.results_data[high[0].getAttribute("data-option-array-index")];
|
1008 |
+
item.selected = true;
|
1009 |
+
this.form_field.options[item.options_index].selected = true;
|
1010 |
+
this.selected_option_count = null;
|
1011 |
+
if (this.is_multiple) {
|
1012 |
+
this.choice_build(item);
|
1013 |
+
} else {
|
1014 |
+
this.single_set_selected_text(item.text);
|
1015 |
+
}
|
1016 |
+
if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
|
1017 |
+
this.results_hide();
|
1018 |
+
}
|
1019 |
+
this.search_field.val("");
|
1020 |
+
if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
|
1021 |
+
this.form_field_jq.trigger("change", {
|
1022 |
+
'selected': this.form_field.options[item.options_index].value
|
1023 |
+
});
|
1024 |
+
}
|
1025 |
+
this.current_selectedIndex = this.form_field.selectedIndex;
|
1026 |
+
return this.search_field_scale();
|
1027 |
+
}
|
1028 |
+
};
|
1029 |
+
|
1030 |
+
Chosen.prototype.single_set_selected_text = function(text) {
|
1031 |
+
if (text == null) {
|
1032 |
+
text = this.default_text;
|
1033 |
+
}
|
1034 |
+
if (text === this.default_text) {
|
1035 |
+
this.selected_item.addClass("chosen-default");
|
1036 |
+
} else {
|
1037 |
+
this.single_deselect_control_build();
|
1038 |
+
this.selected_item.removeClass("chosen-default");
|
1039 |
+
}
|
1040 |
+
return this.selected_item.find("span").text(text);
|
1041 |
+
};
|
1042 |
+
|
1043 |
+
Chosen.prototype.result_deselect = function(pos) {
|
1044 |
+
var result_data;
|
1045 |
+
result_data = this.results_data[pos];
|
1046 |
+
if (!this.form_field.options[result_data.options_index].disabled) {
|
1047 |
+
result_data.selected = false;
|
1048 |
+
this.form_field.options[result_data.options_index].selected = false;
|
1049 |
+
this.selected_option_count = null;
|
1050 |
+
this.result_clear_highlight();
|
1051 |
+
if (this.results_showing) {
|
1052 |
+
this.winnow_results();
|
1053 |
+
}
|
1054 |
+
this.form_field_jq.trigger("change", {
|
1055 |
+
deselected: this.form_field.options[result_data.options_index].value
|
1056 |
+
});
|
1057 |
+
this.search_field_scale();
|
1058 |
+
return true;
|
1059 |
+
} else {
|
1060 |
+
return false;
|
1061 |
+
}
|
1062 |
+
};
|
1063 |
+
|
1064 |
+
Chosen.prototype.single_deselect_control_build = function() {
|
1065 |
+
if (!this.allow_single_deselect) {
|
1066 |
+
return;
|
1067 |
+
}
|
1068 |
+
if (!this.selected_item.find("abbr").length) {
|
1069 |
+
this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
|
1070 |
+
}
|
1071 |
+
return this.selected_item.addClass("chosen-single-with-deselect");
|
1072 |
+
};
|
1073 |
+
|
1074 |
+
Chosen.prototype.get_search_text = function() {
|
1075 |
+
if (this.search_field.val() === this.default_text) {
|
1076 |
+
return "";
|
1077 |
+
} else {
|
1078 |
+
return $('<div/>').text($.trim(this.search_field.val())).html();
|
1079 |
+
}
|
1080 |
+
};
|
1081 |
+
|
1082 |
+
Chosen.prototype.winnow_results_set_highlight = function() {
|
1083 |
+
var do_high, selected_results;
|
1084 |
+
selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
|
1085 |
+
do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
|
1086 |
+
if (do_high != null) {
|
1087 |
+
return this.result_do_highlight(do_high);
|
1088 |
+
}
|
1089 |
+
};
|
1090 |
+
|
1091 |
+
Chosen.prototype.no_results = function(terms) {
|
1092 |
+
var no_results_html;
|
1093 |
+
no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
|
1094 |
+
no_results_html.find("span").first().html(terms);
|
1095 |
+
this.search_results.append(no_results_html);
|
1096 |
+
return this.form_field_jq.trigger("chosen:no_results", {
|
1097 |
+
chosen: this
|
1098 |
+
});
|
1099 |
+
};
|
1100 |
+
|
1101 |
+
Chosen.prototype.no_results_clear = function() {
|
1102 |
+
return this.search_results.find(".no-results").remove();
|
1103 |
+
};
|
1104 |
+
|
1105 |
+
Chosen.prototype.keydown_arrow = function() {
|
1106 |
+
var next_sib;
|
1107 |
+
if (this.results_showing && this.result_highlight) {
|
1108 |
+
next_sib = this.result_highlight.nextAll("li.active-result").first();
|
1109 |
+
if (next_sib) {
|
1110 |
+
return this.result_do_highlight(next_sib);
|
1111 |
+
}
|
1112 |
+
} else {
|
1113 |
+
return this.results_show();
|
1114 |
+
}
|
1115 |
+
};
|
1116 |
+
|
1117 |
+
Chosen.prototype.keyup_arrow = function() {
|
1118 |
+
var prev_sibs;
|
1119 |
+
if (!this.results_showing && !this.is_multiple) {
|
1120 |
+
return this.results_show();
|
1121 |
+
} else if (this.result_highlight) {
|
1122 |
+
prev_sibs = this.result_highlight.prevAll("li.active-result");
|
1123 |
+
if (prev_sibs.length) {
|
1124 |
+
return this.result_do_highlight(prev_sibs.first());
|
1125 |
+
} else {
|
1126 |
+
if (this.choices_count() > 0) {
|
1127 |
+
this.results_hide();
|
1128 |
+
}
|
1129 |
+
return this.result_clear_highlight();
|
1130 |
+
}
|
1131 |
+
}
|
1132 |
+
};
|
1133 |
+
|
1134 |
+
Chosen.prototype.keydown_backstroke = function() {
|
1135 |
+
var next_available_destroy;
|
1136 |
+
if (this.pending_backstroke) {
|
1137 |
+
this.choice_destroy(this.pending_backstroke.find("a").first());
|
1138 |
+
return this.clear_backstroke();
|
1139 |
+
} else {
|
1140 |
+
next_available_destroy = this.search_container.siblings("li.search-choice").last();
|
1141 |
+
if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
|
1142 |
+
this.pending_backstroke = next_available_destroy;
|
1143 |
+
if (this.single_backstroke_delete) {
|
1144 |
+
return this.keydown_backstroke();
|
1145 |
+
} else {
|
1146 |
+
return this.pending_backstroke.addClass("search-choice-focus");
|
1147 |
+
}
|
1148 |
+
}
|
1149 |
+
}
|
1150 |
+
};
|
1151 |
+
|
1152 |
+
Chosen.prototype.clear_backstroke = function() {
|
1153 |
+
if (this.pending_backstroke) {
|
1154 |
+
this.pending_backstroke.removeClass("search-choice-focus");
|
1155 |
+
}
|
1156 |
+
return this.pending_backstroke = null;
|
1157 |
+
};
|
1158 |
+
|
1159 |
+
Chosen.prototype.keydown_checker = function(evt) {
|
1160 |
+
var stroke, _ref1;
|
1161 |
+
stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode;
|
1162 |
+
this.search_field_scale();
|
1163 |
+
if (stroke !== 8 && this.pending_backstroke) {
|
1164 |
+
this.clear_backstroke();
|
1165 |
+
}
|
1166 |
+
switch (stroke) {
|
1167 |
+
case 8:
|
1168 |
+
this.backstroke_length = this.search_field.val().length;
|
1169 |
+
break;
|
1170 |
+
case 9:
|
1171 |
+
if (this.results_showing && !this.is_multiple) {
|
1172 |
+
this.result_select(evt);
|
1173 |
+
}
|
1174 |
+
this.mouse_on_container = false;
|
1175 |
+
break;
|
1176 |
+
case 13:
|
1177 |
+
if (this.results_showing) {
|
1178 |
+
evt.preventDefault();
|
1179 |
+
}
|
1180 |
+
break;
|
1181 |
+
case 32:
|
1182 |
+
if (this.disable_search) {
|
1183 |
+
evt.preventDefault();
|
1184 |
+
}
|
1185 |
+
break;
|
1186 |
+
case 38:
|
1187 |
+
evt.preventDefault();
|
1188 |
+
this.keyup_arrow();
|
1189 |
+
break;
|
1190 |
+
case 40:
|
1191 |
+
evt.preventDefault();
|
1192 |
+
this.keydown_arrow();
|
1193 |
+
break;
|
1194 |
+
}
|
1195 |
+
};
|
1196 |
+
|
1197 |
+
Chosen.prototype.search_field_scale = function() {
|
1198 |
+
var div, f_width, h, style, style_block, styles, w, _i, _len;
|
1199 |
+
if (this.is_multiple) {
|
1200 |
+
h = 0;
|
1201 |
+
w = 0;
|
1202 |
+
style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
|
1203 |
+
styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
|
1204 |
+
for (_i = 0, _len = styles.length; _i < _len; _i++) {
|
1205 |
+
style = styles[_i];
|
1206 |
+
style_block += style + ":" + this.search_field.css(style) + ";";
|
1207 |
+
}
|
1208 |
+
div = $('<div />', {
|
1209 |
+
'style': style_block
|
1210 |
+
});
|
1211 |
+
div.text(this.search_field.val());
|
1212 |
+
$('body').append(div);
|
1213 |
+
w = div.width() + 25;
|
1214 |
+
div.remove();
|
1215 |
+
f_width = this.container.outerWidth();
|
1216 |
+
if (w > f_width - 10) {
|
1217 |
+
w = f_width - 10;
|
1218 |
+
}
|
1219 |
+
return this.search_field.css({
|
1220 |
+
'width': w + 'px'
|
1221 |
+
});
|
1222 |
+
}
|
1223 |
+
};
|
1224 |
+
|
1225 |
+
return Chosen;
|
1226 |
+
|
1227 |
+
})(AbstractChosen);
|
1228 |
+
|
1229 |
+
}).call(this);
|
assets/js/jquery-tiptip/jquery.tipTip.js
ADDED
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* TipTip
|
3 |
+
* Copyright 2010 Drew Wilson
|
4 |
+
* www.drewwilson.com
|
5 |
+
* code.drewwilson.com/entry/tiptip-jquery-plugin
|
6 |
+
*
|
7 |
+
* Version 1.3 - Updated: Mar. 23, 2010
|
8 |
+
*
|
9 |
+
* This Plug-In will create a custom tooltip to replace the default
|
10 |
+
* browser tooltip. It is extremely lightweight and very smart in
|
11 |
+
* that it detects the edges of the browser window and will make sure
|
12 |
+
* the tooltip stays within the current window size. As a result the
|
13 |
+
* tooltip will adjust itself to be displayed above, below, to the left
|
14 |
+
* or to the right depending on what is necessary to stay within the
|
15 |
+
* browser window. It is completely customizable as well via CSS.
|
16 |
+
*
|
17 |
+
* This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
|
18 |
+
* http://www.opensource.org/licenses/mit-license.php
|
19 |
+
* http://www.gnu.org/licenses/gpl.html
|
20 |
+
*/
|
21 |
+
|
22 |
+
(function($){
|
23 |
+
$.fn.tipTip = function(options) {
|
24 |
+
var defaults = {
|
25 |
+
activation: "hover",
|
26 |
+
keepAlive: false,
|
27 |
+
maxWidth: "200px",
|
28 |
+
edgeOffset: 3,
|
29 |
+
defaultPosition: "bottom",
|
30 |
+
delay: 400,
|
31 |
+
fadeIn: 200,
|
32 |
+
fadeOut: 200,
|
33 |
+
attribute: "title",
|
34 |
+
content: false, // HTML or String to fill TipTIp with
|
35 |
+
enter: function(){},
|
36 |
+
exit: function(){}
|
37 |
+
};
|
38 |
+
var opts = $.extend(defaults, options);
|
39 |
+
|
40 |
+
// Setup tip tip elements and render them to the DOM
|
41 |
+
if($("#tiptip_holder").length <= 0){
|
42 |
+
var tiptip_holder = $('<div id="tiptip_holder" style="max-width:'+ opts.maxWidth +';"></div>');
|
43 |
+
var tiptip_content = $('<div id="tiptip_content"></div>');
|
44 |
+
var tiptip_arrow = $('<div id="tiptip_arrow"></div>');
|
45 |
+
$("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')));
|
46 |
+
} else {
|
47 |
+
var tiptip_holder = $("#tiptip_holder");
|
48 |
+
var tiptip_content = $("#tiptip_content");
|
49 |
+
var tiptip_arrow = $("#tiptip_arrow");
|
50 |
+
}
|
51 |
+
|
52 |
+
return this.each(function(){
|
53 |
+
var org_elem = $(this);
|
54 |
+
if(opts.content){
|
55 |
+
var org_title = opts.content;
|
56 |
+
} else {
|
57 |
+
var org_title = org_elem.attr(opts.attribute);
|
58 |
+
}
|
59 |
+
if(org_title != ""){
|
60 |
+
if(!opts.content){
|
61 |
+
org_elem.removeAttr(opts.attribute); //remove original Attribute
|
62 |
+
}
|
63 |
+
var timeout = false;
|
64 |
+
|
65 |
+
if(opts.activation == "hover"){
|
66 |
+
org_elem.hover(function(){
|
67 |
+
active_tiptip();
|
68 |
+
}, function(){
|
69 |
+
if(!opts.keepAlive){
|
70 |
+
deactive_tiptip();
|
71 |
+
}
|
72 |
+
});
|
73 |
+
if(opts.keepAlive){
|
74 |
+
tiptip_holder.hover(function(){}, function(){
|
75 |
+
deactive_tiptip();
|
76 |
+
});
|
77 |
+
}
|
78 |
+
} else if(opts.activation == "focus"){
|
79 |
+
org_elem.focus(function(){
|
80 |
+
active_tiptip();
|
81 |
+
}).blur(function(){
|
82 |
+
deactive_tiptip();
|
83 |
+
});
|
84 |
+
} else if(opts.activation == "click"){
|
85 |
+
org_elem.click(function(){
|
86 |
+
active_tiptip();
|
87 |
+
return false;
|
88 |
+
}).hover(function(){},function(){
|
89 |
+
if(!opts.keepAlive){
|
90 |
+
deactive_tiptip();
|
91 |
+
}
|
92 |
+
});
|
93 |
+
if(opts.keepAlive){
|
94 |
+
tiptip_holder.hover(function(){}, function(){
|
95 |
+
deactive_tiptip();
|
96 |
+
});
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
function active_tiptip(){
|
101 |
+
opts.enter.call(this);
|
102 |
+
tiptip_content.html(org_title);
|
103 |
+
tiptip_holder.hide().removeAttr("class").css("margin","0");
|
104 |
+
tiptip_arrow.removeAttr("style");
|
105 |
+
|
106 |
+
var top = parseInt(org_elem.offset()['top']);
|
107 |
+
var left = parseInt(org_elem.offset()['left']);
|
108 |
+
var org_width = parseInt(org_elem.outerWidth());
|
109 |
+
var org_height = parseInt(org_elem.outerHeight());
|
110 |
+
var tip_w = tiptip_holder.outerWidth();
|
111 |
+
var tip_h = tiptip_holder.outerHeight();
|
112 |
+
var w_compare = Math.round((org_width - tip_w) / 2);
|
113 |
+
var h_compare = Math.round((org_height - tip_h) / 2);
|
114 |
+
var marg_left = Math.round(left + w_compare);
|
115 |
+
var marg_top = Math.round(top + org_height + opts.edgeOffset);
|
116 |
+
var t_class = "";
|
117 |
+
var arrow_top = "";
|
118 |
+
var arrow_left = Math.round(tip_w - 12) / 2;
|
119 |
+
|
120 |
+
if(opts.defaultPosition == "bottom"){
|
121 |
+
t_class = "_bottom";
|
122 |
+
} else if(opts.defaultPosition == "top"){
|
123 |
+
t_class = "_top";
|
124 |
+
} else if(opts.defaultPosition == "left"){
|
125 |
+
t_class = "_left";
|
126 |
+
} else if(opts.defaultPosition == "right"){
|
127 |
+
t_class = "_right";
|
128 |
+
}
|
129 |
+
|
130 |
+
var right_compare = (w_compare + left) < parseInt($(window).scrollLeft());
|
131 |
+
var left_compare = (tip_w + left) > parseInt($(window).width());
|
132 |
+
|
133 |
+
if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){
|
134 |
+
t_class = "_right";
|
135 |
+
arrow_top = Math.round(tip_h - 13) / 2;
|
136 |
+
arrow_left = -12;
|
137 |
+
marg_left = Math.round(left + org_width + opts.edgeOffset);
|
138 |
+
marg_top = Math.round(top + h_compare);
|
139 |
+
} else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){
|
140 |
+
t_class = "_left";
|
141 |
+
arrow_top = Math.round(tip_h - 13) / 2;
|
142 |
+
arrow_left = Math.round(tip_w);
|
143 |
+
marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5));
|
144 |
+
marg_top = Math.round(top + h_compare);
|
145 |
+
}
|
146 |
+
|
147 |
+
var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop());
|
148 |
+
var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0;
|
149 |
+
|
150 |
+
if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){
|
151 |
+
if(t_class == "_top" || t_class == "_bottom"){
|
152 |
+
t_class = "_top";
|
153 |
+
} else {
|
154 |
+
t_class = t_class+"_top";
|
155 |
+
}
|
156 |
+
arrow_top = tip_h;
|
157 |
+
marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset));
|
158 |
+
} else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){
|
159 |
+
if(t_class == "_top" || t_class == "_bottom"){
|
160 |
+
t_class = "_bottom";
|
161 |
+
} else {
|
162 |
+
t_class = t_class+"_bottom";
|
163 |
+
}
|
164 |
+
arrow_top = -12;
|
165 |
+
marg_top = Math.round(top + org_height + opts.edgeOffset);
|
166 |
+
}
|
167 |
+
|
168 |
+
if(t_class == "_right_top" || t_class == "_left_top"){
|
169 |
+
marg_top = marg_top + 5;
|
170 |
+
} else if(t_class == "_right_bottom" || t_class == "_left_bottom"){
|
171 |
+
marg_top = marg_top - 5;
|
172 |
+
}
|
173 |
+
if(t_class == "_left_top" || t_class == "_left_bottom"){
|
174 |
+
marg_left = marg_left + 5;
|
175 |
+
}
|
176 |
+
tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"});
|
177 |
+
tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class);
|
178 |
+
|
179 |
+
if (timeout){ clearTimeout(timeout); }
|
180 |
+
timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay);
|
181 |
+
}
|
182 |
+
|
183 |
+
function deactive_tiptip(){
|
184 |
+
opts.exit.call(this);
|
185 |
+
if (timeout){ clearTimeout(timeout); }
|
186 |
+
tiptip_holder.fadeOut(opts.fadeOut);
|
187 |
+
}
|
188 |
+
}
|
189 |
+
});
|
190 |
+
}
|
191 |
+
})(jQuery);
|
assets/js/jquery-tiptip/jquery.tipTip.min.js
CHANGED
@@ -17,4 +17,4 @@
|
|
17 |
* This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
|
18 |
* http://www.opensource.org/licenses/mit-license.php
|
19 |
* http://www.gnu.org/licenses/gpl.html
|
20 |
-
|
17 |
* This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
|
18 |
* http://www.opensource.org/licenses/mit-license.php
|
19 |
* http://www.gnu.org/licenses/gpl.html
|
20 |
+
*/(function(e){e.fn.tipTip=function(t){var n={activation:"hover",keepAlive:!1,maxWidth:"200px",edgeOffset:3,defaultPosition:"bottom",delay:400,fadeIn:200,fadeOut:200,attribute:"title",content:!1,enter:function(){},exit:function(){}},r=e.extend(n,t);if(e("#tiptip_holder").length<=0){var i=e('<div id="tiptip_holder" style="max-width:'+r.maxWidth+';"></div>'),s=e('<div id="tiptip_content"></div>'),o=e('<div id="tiptip_arrow"></div>');e("body").append(i.html(s).prepend(o.html('<div id="tiptip_arrow_inner"></div>')))}else var i=e("#tiptip_holder"),s=e("#tiptip_content"),o=e("#tiptip_arrow");return this.each(function(){var t=e(this);if(r.content)var n=r.content;else var n=t.attr(r.attribute);if(n!=""){r.content||t.removeAttr(r.attribute);var u=!1;if(r.activation=="hover"){t.hover(function(){a()},function(){r.keepAlive||f()});r.keepAlive&&i.hover(function(){},function(){f()})}else if(r.activation=="focus")t.focus(function(){a()}).blur(function(){f()});else if(r.activation=="click"){t.click(function(){a();return!1}).hover(function(){},function(){r.keepAlive||f()});r.keepAlive&&i.hover(function(){},function(){f()})}function a(){r.enter.call(this);s.html(n);i.hide().removeAttr("class").css("margin","0");o.removeAttr("style");var a=parseInt(t.offset().top),f=parseInt(t.offset().left),l=parseInt(t.outerWidth()),c=parseInt(t.outerHeight()),h=i.outerWidth(),p=i.outerHeight(),d=Math.round((l-h)/2),v=Math.round((c-p)/2),m=Math.round(f+d),g=Math.round(a+c+r.edgeOffset),y="",b="",w=Math.round(h-12)/2;r.defaultPosition=="bottom"?y="_bottom":r.defaultPosition=="top"?y="_top":r.defaultPosition=="left"?y="_left":r.defaultPosition=="right"&&(y="_right");var E=d+f<parseInt(e(window).scrollLeft()),S=h+f>parseInt(e(window).width());if(E&&d<0||y=="_right"&&!S||y=="_left"&&f<h+r.edgeOffset+5){y="_right";b=Math.round(p-13)/2;w=-12;m=Math.round(f+l+r.edgeOffset);g=Math.round(a+v)}else if(S&&d<0||y=="_left"&&!E){y="_left";b=Math.round(p-13)/2;w=Math.round(h);m=Math.round(f-(h+r.edgeOffset+5));g=Math.round(a+v)}var x=a+c+r.edgeOffset+p+8>parseInt(e(window).height()+e(window).scrollTop()),T=a+c-(r.edgeOffset+p+8)<0;if(x||y=="_bottom"&&x||y=="_top"&&!T){y=="_top"||y=="_bottom"?y="_top":y+="_top";b=p;g=Math.round(a-(p+5+r.edgeOffset))}else if(T|(y=="_top"&&T)||y=="_bottom"&&!x){y=="_top"||y=="_bottom"?y="_bottom":y+="_bottom";b=-12;g=Math.round(a+c+r.edgeOffset)}if(y=="_right_top"||y=="_left_top")g+=5;else if(y=="_right_bottom"||y=="_left_bottom")g-=5;if(y=="_left_top"||y=="_left_bottom")m+=5;o.css({"margin-left":w+"px","margin-top":b+"px"});i.css({"margin-left":m+"px","margin-top":g+"px"}).attr("class","tip"+y);u&&clearTimeout(u);u=setTimeout(function(){i.stop(!0,!0).fadeIn(r.fadeIn)},r.delay)}function f(){r.exit.call(this);u&&clearTimeout(u);i.fadeOut(r.fadeOut)}}})}})(jQuery);
|
assets/js/multiselect.js
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
/* global job_manager_chosen_multiselect_args */
|
2 |
+
jQuery(function(){
|
3 |
+
jQuery( '.job-manager-multiselect' ).chosen( job_manager_chosen_multiselect_args );
|
4 |
+
});
|
assets/js/term-multiselect.js
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
/* global job_manager_chosen_multiselect_args */
|
2 |
+
jQuery(function(){
|
3 |
+
jQuery( '.job-manager-category-dropdown' ).chosen( job_manager_chosen_multiselect_args );
|
4 |
+
});
|
changelog.txt
CHANGED
@@ -1,151 +1,28 @@
|
|
1 |
-
= 1.31.2 =
|
2 |
-
* Fix: Adds missing quote from WP admin taxonomy fields. (@redpik)
|
3 |
-
|
4 |
-
= 1.31.1 =
|
5 |
-
* Enhancement: Add option to show company logo in Recent Jobs widget. (@RajeebTheGreat)
|
6 |
-
* Enhancement: Suggest additional cookie information on Privacy Policy page.
|
7 |
-
* Enhancement: Add WPJM related meta data to user data extract.
|
8 |
-
* Fix: Tightened the security of the plugin with additional string escaping.
|
9 |
-
* Fix: Issue with map link in admin backend. (@RajeebTheGreat)
|
10 |
-
* Fix: No longer auto-expire job listings in Draft status.
|
11 |
-
* Fix: Issue with undefined index error in WP admin. (@albionselimaj)
|
12 |
-
* Fix: Issue with duplicate usernames preventing submission of job listings. (@timothyjensen)
|
13 |
-
* Dev: Widespread code formatting cleanup throughout the plugin.
|
14 |
-
|
15 |
-
= 1.31.0 =
|
16 |
-
* Change: Minimum WordPress version is now 4.7.0.
|
17 |
-
* Enhancement: Add email notifications with initial support for new jobs, updated jobs, and expiring listings.
|
18 |
-
* Enhancement: For GDPR, scrub WPJM data from database on uninstall if option is enabled.
|
19 |
-
* Enhancement: Filter by Filled and Featured status in WP admin.
|
20 |
-
* Enhancement: Simplify the display of application URLs.
|
21 |
-
* Enhancement: When using WPML, prevent changes to page options when on a non-default language. (@vukvukovich)
|
22 |
-
* Enhancement: Include company logo in structured data. (@RajeebTheGreat)
|
23 |
-
* Enhancement: Use more efficient jQuery selectors in scripts. (@RajeebTheGreat)
|
24 |
-
* Enhancement: Use proper `<h2>` tag in `content-summary-job_listing.php` template for the job title. (@abdullah1908)
|
25 |
-
* Enhancement: Hide empty categories on `[job]` filter.
|
26 |
-
* Fix: Update calls to `get_terms()` to use the new format.
|
27 |
-
* Fix: Maintain the current tab when saving settings in WP Admin.
|
28 |
-
* Fix: Enqueue the date picker CSS when used on the front-end.
|
29 |
-
* Fix: Remove errors when widget instance was created without setting defaults.
|
30 |
-
* REST API Pre-release: Add support for job category taxonomy endpoints.
|
31 |
-
* Dev: Add `$job_id` parameter to `job_manager_job_dashboard_do_action_{$action}` action hook. (@jonasvogel)
|
32 |
-
* Dev: Add support for hidden WPJM settings in WP Admin.
|
33 |
-
|
34 |
-
= 1.30.2 =
|
35 |
-
* Enhancement: Show notice when user is using an older version of WordPress.
|
36 |
-
* Enhancement: Hide unnecessary view mode in WP Admin's Job Listings page. (@RajeebTheGreat)
|
37 |
-
* Enhancement: Add support for the `paged` parameter in the RSS feed. (@RajeebTheGreat)
|
38 |
-
* Fix: Minor PHP 7.2 compatibility fixes.
|
39 |
-
* Dev: Allow `parent` attribute to be passed to `job_manager_dropdown_categories()`. (@RajeebTheGreat)
|
40 |
-
|
41 |
-
= 1.30.1 =
|
42 |
-
* Fix: Minor issue with a strict standard error being displayed on some instances.
|
43 |
-
|
44 |
-
= 1.30.0 =
|
45 |
-
* Enhancement: Adds ability to have a reCAPTCHA field to check if job listing author is human.
|
46 |
-
* Enhancement: Allows for option to make edits to job listings force listing back into pending approval status.
|
47 |
-
* Enhancement: Adds spinner and disables form when user submits job listing.
|
48 |
-
* Enhancement: Update the add-ons page of the plugin.
|
49 |
-
* Enhancement: Added the ability to sort jobs randomly on the Featured Jobs Widget.
|
50 |
-
* Enhancement: Improved handling of alternative date formats when editing job expiration field in WP admin.
|
51 |
-
* Enhancement: Added star indicator next to featured listings on `[job_dashboard]`.
|
52 |
-
* Enhancement: Opt-in to usage tracking so we can better improve the plugin.
|
53 |
-
* Enhancement: Introduced new asset enqueuing strategy that will be turned on in 1.32.0. Requires plugin and theme updates. (Dev notes: https://github.com/Automattic/WP-Job-Manager/pull/1354)
|
54 |
-
* Fix: Use WordPress core checks for image formats to not confuse `docx` as an image. (@tripflex)
|
55 |
-
* Fix: Issue with `[jobs]` shortcode when `categories` argument is provided.
|
56 |
-
* Fix: Issue with double encoding HTML entities in custom text area fields.
|
57 |
-
* Fix: Updates `job-dashboard.php` template with `colspan` fix on no active listings message.
|
58 |
-
* Fix: Clear job listings cache when deleting a user and their job listings.
|
59 |
-
* Dev: Adds `is_wpjm()` and related functions to test if we're on a WPJM related page.
|
60 |
-
* Dev: Adds `job_manager_user_edit_job_listing` action that fires after a user edits a job listing.
|
61 |
-
* Dev: Adds `job_manager_enable_job_archive_page` filter to enable job archive page.
|
62 |
-
* Dev: Adds `date` field for custom job listing form fields.
|
63 |
-
|
64 |
-
= 1.29.3 =
|
65 |
-
* Fix: When retrieving job listing results, cache only the post results and not all of `WP_Query` (props slavco)
|
66 |
-
|
67 |
-
= 1.29.2 =
|
68 |
-
* Fix: PHP Notice when sanitizing multiple inputs (bug in 1.29.1 release). (@albionselimaj)
|
69 |
-
|
70 |
-
= 1.29.1 =
|
71 |
-
* Enhancement: When retrieving listings in `[jobs]` shortcode, setting `orderby` to `rand_featured` will still place featured listings at the top.
|
72 |
-
* Enhancement: Scroll to show application details when clicking on "Apply for Job" button.
|
73 |
-
* Change: Updates `account-signin.php` template to warn users email will be confirmed only if that is enabled.
|
74 |
-
* Fix: Sanitize URLs and emails differently on the application method job listing field.
|
75 |
-
* Fix: Remove PHP notice in Featured Jobs widget. (@himanshuahuja96)
|
76 |
-
* Fix: String fix for consistent spelling of "license" when appearing in strings. (@garrett-eclipse)
|
77 |
-
* Fix: Issue with paid add-on licenses not showing up when some third-party plugins were installed.
|
78 |
-
* Dev: Runs new actions (`job_manager_recent_jobs_widget_before` and `job_manager_recent_jobs_widget_after`) inside Recent Jobs widget.
|
79 |
-
* Dev: Change `wpjm_get_the_job_types()` to return an empty array when job types are disabled.
|
80 |
-
* See all: https://github.com/Automattic/WP-Job-Manager/milestone/15?closed=1
|
81 |
-
|
82 |
-
= 1.29.0 =
|
83 |
-
* Enhancement: Moves license and update management for official add-ons to the core plugin.
|
84 |
-
* Enhancement: Update language for setup wizard with more clear descriptions.
|
85 |
-
* Fix: Prevent duplicate attachments to job listing posts for non-image media. (@tripflex)
|
86 |
-
* Fix: PHP error on registration form due to missing placeholder text.
|
87 |
-
* Fix: Apply `the_job_application_method` filter even when no default is available. (@turtlepod)
|
88 |
-
* Fix: Properly reset category selector on `[jobs]` shortcode.
|
89 |
-
|
90 |
-
= 1.28.0 =
|
91 |
-
* Enhancement: Improves support for Google Job Search by adding `JobPosting` structured data.
|
92 |
-
* Enhancement: Adds ability for job types to be mapped to an employment type as defined for Google Job Search.
|
93 |
-
* Enhancement: Requests search engines no longer index expired and filled job listings.
|
94 |
-
* Enhancement: Improves support with third-party sitemap generation in Jetpack, Yoast SEO, and All in One SEO.
|
95 |
-
* Enhancement: Updated descriptions and help text on settings page.
|
96 |
-
* Enhancement: Lower cache expiration times across plugin and limit use of autoloaded cache transients.
|
97 |
-
* Fix: Localization issue with WPML in the [jobs] shortcode.
|
98 |
-
* Fix: Show job listings' published date in localized format.
|
99 |
-
* Fix: Job submission form allows users to select multiple job types when they go back a step.
|
100 |
-
* Fix: Some themes that overloaded functions would break in previous release.
|
101 |
-
* Dev: Adds versions to template files so it is easier to tell when they are updated.
|
102 |
-
* Dev: Adds a new `wpjm_notify_new_user` action that allows you to override default behavior.
|
103 |
-
* Dev: Early version of REST API is bundled but disabled by default. Requires PHP 5.3+ and `WPJM_REST_API_ENABLED` constant must be set to true. Do not use in production; endpoints may change. (@pkg)
|
104 |
-
|
105 |
-
= 1.27.0 =
|
106 |
-
* Enhancement: Admins can now allow users to specify an account password when posting their first job listing.
|
107 |
-
* Enhancement: Pending job listing counts are now cached for improved WP Admin performance. (@tripflex)
|
108 |
-
* Enhancement: Allows users to override permalink slugs in WP Admin's Permalink Settings screen.
|
109 |
-
* Enhancement: Allows admins to perform bulk updating of jobs as filled/not filled.
|
110 |
-
* Enhancement: Adds job listing status CSS classes on single job listings.
|
111 |
-
* Enhancement: Adds `wpjm_the_job_title` filter for inserting non-escaped HTML alongside job titles in templates.
|
112 |
-
* Enhancement: Allows admins to filter by `post_status` in `[jobs]` shortcode.
|
113 |
-
* Enhancement: Allows accessing settings tab from hash in URL. (@tripflex)
|
114 |
-
* Fix: Make sure cron jobs for checking/cleaning expired listings are always in place.
|
115 |
-
* Fix: Better handling of multiple job types. (@spencerfinnell)
|
116 |
-
* Fix: Issue with deleting company logos from job listings submission form.
|
117 |
-
* Fix: Warning thrown on job submission form when user not logged in. (@piersb)
|
118 |
-
* Fix: Issue with WPML not syncing some meta fields.
|
119 |
-
* Fix: Better handling of AJAX upload errors. (@tripflex)
|
120 |
-
* Fix: Remove job posting cookies on logout.
|
121 |
-
* Fix: Expiration date can be cleared if default job duration option is empty. (@spencerfinnell)
|
122 |
-
* Fix: Issue with Safari and expiration datepicker.
|
123 |
-
|
124 |
= 1.26.2 =
|
125 |
-
* 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.
|
126 |
-
* Fix: Escape post title in WP Admin's Job Listings page and template segments. (Props to @EhsanCod3r)
|
127 |
|
128 |
= 1.26.1 =
|
129 |
-
* Enhancement: Add language using WordPress's current locale to geocode requests.
|
130 |
-
* Fix: Allow attempts to use Google Maps Geocode API without an API key. (@spencerfinnell)
|
131 |
-
* Fix: Issue affecting job expiry date when editing a job listing. (@spencerfinnell)
|
132 |
-
* Fix: Show correct total count of results on `[jobs]` shortcode.
|
133 |
|
134 |
= 1.26.0 =
|
135 |
-
* Enhancement: Warn the user if they're editing an existing job.
|
136 |
-
* Enhancement: WP Admin Job Listing page's table is now responsive. (@turtlepod)
|
137 |
-
* Enhancement: New setting for hiding expired listings from `[jobs]` filter. (@turtlepod)
|
138 |
-
* Enhancement: Use WP Query's built in search function to improve searching in `[jobs]`.
|
139 |
-
* Fix: Job Listing filter only searches meta fields with relevant content. Add custom fields with `job_listing_searchable_meta_keys` filter. (@turtlepod)
|
140 |
-
* Fix: Improved support for WPML and Polylang.
|
141 |
-
* Fix: Expired field no longer forces admins to choose a date in the future. (@turtlepod)
|
142 |
-
* Fix: Listings with expiration date in past will immediately expire; moving to Active status will extend if necessary. (@turtlepod)
|
143 |
-
* Fix: Google Maps API key setting added to fix geolocation retrieval on new sites.
|
144 |
-
* Fix: Issue when duplicating a job listing with a field for multiple file uploads. (@turtlepod)
|
145 |
-
* Fix: Hide page results when adding links in the `[submit_job_form]` shortcode.
|
146 |
-
* Fix: Job feed now loads when a site has no posts.
|
147 |
-
* Fix: No error is thrown when deleting a user. (@tripflex)
|
148 |
-
* Dev: Plugins and themes can now retrieve JSON of Job Listings results without HTML. (@spencerfinnell)
|
149 |
* Dev: Updated inline documentation.
|
150 |
|
151 |
= 1.25.3 =
|
@@ -160,30 +37,30 @@
|
|
160 |
* Fix: Fixed taxonomy search conditions. See https://github.com/automattic/wp-job-manager/pull/859/ Props Jonas Vogel.
|
161 |
|
162 |
= 1.25.2 =
|
163 |
-
* Fix - The date format of the expiry date picker was incorrect in translations so we added a comment to clarify, and fixed translations.
|
164 |
-
* Fix - Changing the date of an expired job would forget the date, even though the job would become active.
|
165 |
-
* Fix - Site owner can allow jobs to have only one or more than one types.
|
166 |
-
* Fix - Show expired jobs if that setting is enabled.
|
167 |
-
* Fix - Simplify the search message on the jobs page to avoid translation problems.
|
168 |
-
* Fix - The uploader would ignore WordPress created image sizes.
|
169 |
-
* Fix - setup.css was loaded on all admin pages.
|
170 |
-
* Fix - The preview of a listing could be edited or viewed by anyone. Props @tripflex
|
171 |
-
* Fix - When users were deleted their jobs weren't.
|
172 |
-
* Fix - OrderBy Rand wasn't working.
|
173 |
-
* Dev - Add upload filters and update PHPDocs, props @tripflex
|
174 |
-
* Fix - Stop using jQuery.live, props @tripflex
|
175 |
|
176 |
= 1.25.1 =
|
177 |
-
* Feature - Adds a view button to the Admin UI for easy access to submitted files or URLs. Props tripflex
|
178 |
* Fix - Add hardening to file uploads to prevent accepting unexpected file times. Previously, other WP-allowed types were sometimes accepted.
|
179 |
-
* Fix - Job post form categories are now properly cached and displayed per language when using WPML or Polylang.
|
180 |
-
* Fix - Refactored WPML workaround, which was causing no job listings on non-default languages.
|
181 |
-
* Fix - Allow employers to edit job listings when a listing is pending payment.
|
182 |
-
* Fix - No longer display Job Taxonomies in the WordPress tag cloud.
|
183 |
-
* Fix - Migrate away from jQuery.live, which is no longer supported.
|
184 |
-
* Tweak - Updated incorrect settings description.
|
185 |
-
* Dev - Adds hook to add items in a job's RSS feed item.
|
186 |
-
* Dev - Adds filter to disable Job Listings cache
|
187 |
* Dev - Inline docs and coding standards improvements.
|
188 |
|
189 |
= 1.25.0 =
|
@@ -191,7 +68,7 @@
|
|
191 |
* Fix - Support WP_EMBED in job descriptions.
|
192 |
* Fix - Ensure logo is displayed on edit, before submission.
|
193 |
* Fix - Attachment URLs on multisite.
|
194 |
-
* Fix - Refactored WPML workaround, which was causing no job listings on non-default languages.
|
195 |
* Fix - No need to decode URLs anymore https://core.trac.wordpress.org/ticket/23605.
|
196 |
* Dev - submit_job_form_end/submit_job_form_start actions.
|
197 |
* Dev - job-manager-datepicker class for backend date fields.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
4 |
|
5 |
= 1.26.1 =
|
6 |
+
* Enhancement: Add language using WordPress's current locale to geocode requests. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1007)
|
7 |
+
* Fix: Allow attempts to use Google Maps Geocode API without an API key. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/998)
|
8 |
+
* Fix: Issue affecting job expiry date when editing a job listing. (@spencerfinnell, @jom; https://github.com/Automattic/WP-Job-Manager/pull/1008)
|
9 |
+
* Fix: Show correct total count of results on `[jobs]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/1006)
|
10 |
|
11 |
= 1.26.0 =
|
12 |
+
* Enhancement: Warn the user if they're editing an existing job. (@donnchawp; https://github.com/Automattic/WP-Job-Manager/pull/847)
|
13 |
+
* Enhancement: WP Admin Job Listing page's table is now responsive. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/906)
|
14 |
+
* Enhancement: New setting for hiding expired listings from `[jobs]` filter. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/903)
|
15 |
+
* Enhancement: Use WP Query's built in search function to improve searching in `[jobs]`. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/960)
|
16 |
+
* Fix: Job Listing filter only searches meta fields with relevant content. Add custom fields with `job_listing_searchable_meta_keys` filter. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/910)
|
17 |
+
* Fix: Improved support for WPML and Polylang. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/963)
|
18 |
+
* Fix: Expired field no longer forces admins to choose a date in the future. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/903)
|
19 |
+
* Fix: Listings with expiration date in past will immediately expire; moving to Active status will extend if necessary. (@turtlepod, @jom; https://github.com/Automattic/WP-Job-Manager/pull/903, https://github.com/Automattic/WP-Job-Manager/pull/975)
|
20 |
+
* Fix: Google Maps API key setting added to fix geolocation retrieval on new sites. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/912)
|
21 |
+
* Fix: Issue when duplicating a job listing with a field for multiple file uploads. (@turtlepod; https://github.com/Automattic/WP-Job-Manager/pull/911)
|
22 |
+
* Fix: Hide page results when adding links in the `[submit_job_form]` shortcode. (@jom; https://github.com/Automattic/WP-Job-Manager/pull/922)
|
23 |
+
* Fix: Job feed now loads when a site has no posts. (@dbtlr; https://github.com/Automattic/WP-Job-Manager/pull/870)
|
24 |
+
* Fix: No error is thrown when deleting a user. (@tripflex; https://github.com/Automattic/WP-Job-Manager/pull/875)
|
25 |
+
* Dev: Plugins and themes can now retrieve JSON of Job Listings results without HTML. (@spencerfinnell; https://github.com/Automattic/WP-Job-Manager/pull/888)
|
26 |
* Dev: Updated inline documentation.
|
27 |
|
28 |
= 1.25.3 =
|
37 |
* Fix: Fixed taxonomy search conditions. See https://github.com/automattic/wp-job-manager/pull/859/ Props Jonas Vogel.
|
38 |
|
39 |
= 1.25.2 =
|
40 |
+
* Fix - The date format of the expiry date picker was incorrect in translations so we added a comment to clarify, and fixed translations. (https://github.com/Automattic/WP-Job-Manager/issues/697)
|
41 |
+
* Fix - Changing the date of an expired job would forget the date, even though the job would become active. (https://github.com/Automattic/WP-Job-Manager/issues/653)
|
42 |
+
* Fix - Site owner can allow jobs to have only one or more than one types. (https://github.com/Automattic/WP-Job-Manager/issues/549)
|
43 |
+
* Fix - Show expired jobs if that setting is enabled. (https://github.com/Automattic/WP-Job-Manager/issues/703)
|
44 |
+
* Fix - Simplify the search message on the jobs page to avoid translation problems. (https://github.com/Automattic/WP-Job-Manager/issues/647)
|
45 |
+
* Fix - The uploader would ignore WordPress created image sizes. (https://github.com/Automattic/WP-Job-Manager/issues/706)
|
46 |
+
* Fix - setup.css was loaded on all admin pages. (https://github.com/Automattic/WP-Job-Manager/issues/728)
|
47 |
+
* Fix - The preview of a listing could be edited or viewed by anyone. Props @tripflex (https://github.com/Automattic/WP-Job-Manager/issues/690)
|
48 |
+
* Fix - When users were deleted their jobs weren't. (https://github.com/Automattic/WP-Job-Manager/issues/675)
|
49 |
+
* Fix - OrderBy Rand wasn't working. (https://github.com/Automattic/WP-Job-Manager/issues/714)
|
50 |
+
* Dev - Add upload filters and update PHPDocs, props @tripflex (https://github.com/Automattic/WP-Job-Manager/pull/747)
|
51 |
+
* Fix - Stop using jQuery.live, props @tripflex (https://github.com/Automattic/WP-Job-Manager/pull/664)
|
52 |
|
53 |
= 1.25.1 =
|
54 |
+
* Feature - Adds a view button to the Admin UI for easy access to submitted files or URLs. Props tripflex (https://github.com/Automattic/WP-Job-Manager/pull/650)
|
55 |
* Fix - Add hardening to file uploads to prevent accepting unexpected file times. Previously, other WP-allowed types were sometimes accepted.
|
56 |
+
* Fix - Job post form categories are now properly cached and displayed per language when using WPML or Polylang. (https://github.com/Automattic/WP-Job-Manager/issues/692)
|
57 |
+
* Fix - Refactored WPML workaround, which was causing no job listings on non-default languages. (https://github.com/Automattic/WP-Job-Manager/issues/617)
|
58 |
+
* Fix - Allow employers to edit job listings when a listing is pending payment. (https://github.com/Automattic/WP-Job-Manager/pull/664)
|
59 |
+
* Fix - No longer display Job Taxonomies in the WordPress tag cloud. (https://github.com/Automattic/WP-Job-Manager/pull/658)
|
60 |
+
* Fix - Migrate away from jQuery.live, which is no longer supported. ( https://github.com/Automattic/WP-Job-Manager/pull/664 )
|
61 |
+
* Tweak - Updated incorrect settings description. (https://github.com/Automattic/WP-Job-Manager/pull/632)
|
62 |
+
* Dev - Adds hook to add items in a job's RSS feed item. (https://github.com/Automattic/WP-Job-Manager/pull/636)
|
63 |
+
* Dev - Adds filter to disable Job Listings cache (https://github.com/Automattic/WP-Job-Manager/pull/684)
|
64 |
* Dev - Inline docs and coding standards improvements.
|
65 |
|
66 |
= 1.25.0 =
|
68 |
* Fix - Support WP_EMBED in job descriptions.
|
69 |
* Fix - Ensure logo is displayed on edit, before submission.
|
70 |
* Fix - Attachment URLs on multisite.
|
71 |
+
* Fix - Refactored WPML workaround, which was causing no job listings on non-default languages. (https://github.com/Automattic/WP-Job-Manager/issues/617)
|
72 |
* Fix - No need to decode URLs anymore https://core.trac.wordpress.org/ticket/23605.
|
73 |
* Dev - submit_job_form_end/submit_job_form_start actions.
|
74 |
* Dev - job-manager-datepicker class for backend date fields.
|
includes/3rd-party/3rd-party.php
CHANGED
@@ -2,10 +2,5 @@
|
|
2 |
/**
|
3 |
* Load 3rd party compatibility tweaks.
|
4 |
*/
|
5 |
-
require_once JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/
|
6 |
-
require_once JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/
|
7 |
-
require_once JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/polylang.php';
|
8 |
-
require_once JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/yoast.php';
|
9 |
-
require_once JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/all-in-one-seo-pack.php';
|
10 |
-
require_once JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/rp4wp.php';
|
11 |
-
require_once JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/wp-all-import.php';
|
2 |
/**
|
3 |
* Load 3rd party compatibility tweaks.
|
4 |
*/
|
5 |
+
require_once( JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/wpml.php' );
|
6 |
+
require_once( JOB_MANAGER_PLUGIN_DIR . '/includes/3rd-party/polylang.php' );
|
|
|
|
|
|
|
|
|
|
includes/3rd-party/all-in-one-seo-pack.php
DELETED
@@ -1,25 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Adds additional compatibility with All in One SEO Pack.
|
4 |
-
*
|
5 |
-
* @package wp-job-manager
|
6 |
-
*/
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Skip filled job listings.
|
10 |
-
*
|
11 |
-
* @param WP_Post[] $posts
|
12 |
-
* @return WP_Post[]
|
13 |
-
*/
|
14 |
-
function wpjm_aiosp_sitemap_filter_filled_jobs( $posts ) {
|
15 |
-
foreach ( $posts as $index => $post ) {
|
16 |
-
if ( $post instanceof WP_Post && 'job_listing' !== $post->post_type ) {
|
17 |
-
continue;
|
18 |
-
}
|
19 |
-
if ( is_position_filled( $post ) ) {
|
20 |
-
unset( $posts[ $index ] );
|
21 |
-
}
|
22 |
-
}
|
23 |
-
return $posts;
|
24 |
-
}
|
25 |
-
add_action( 'aiosp_sitemap_post_filter', 'wpjm_aiosp_sitemap_filter_filled_jobs', 10, 3 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/3rd-party/jetpack.php
DELETED
@@ -1,38 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Adds additional compatibility with Jetpack.
|
4 |
-
*
|
5 |
-
* @package wp-job-manager
|
6 |
-
*/
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Skip filled job listings.
|
10 |
-
*
|
11 |
-
* @param bool $skip_post
|
12 |
-
* @param WP_Post $post
|
13 |
-
* @return bool
|
14 |
-
*/
|
15 |
-
function wpjm_jetpack_skip_filled_job_listings( $skip_post, $post ) {
|
16 |
-
if ( 'job_listing' !== $post->post_type ) {
|
17 |
-
return $skip_post;
|
18 |
-
}
|
19 |
-
|
20 |
-
if ( is_position_filled( $post ) ) {
|
21 |
-
return true;
|
22 |
-
}
|
23 |
-
|
24 |
-
return $skip_post;
|
25 |
-
}
|
26 |
-
add_action( 'jetpack_sitemap_skip_post', 'wpjm_jetpack_skip_filled_job_listings', 10, 2 );
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Add `job_listing` post type to sitemap.
|
30 |
-
*
|
31 |
-
* @param array $post_types
|
32 |
-
* @return array
|
33 |
-
*/
|
34 |
-
function wpjm_jetpack_add_post_type( $post_types ) {
|
35 |
-
$post_types[] = 'job_listing';
|
36 |
-
return $post_types;
|
37 |
-
}
|
38 |
-
add_filter( 'jetpack_sitemap_post_types', 'wpjm_jetpack_add_post_type' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/3rd-party/polylang.php
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
* Only load these if Polylang plugin is installed and active.
|
4 |
-
*
|
5 |
-
* @package wp-job-manager
|
6 |
*/
|
7 |
|
8 |
/**
|
@@ -13,26 +11,9 @@
|
|
13 |
function polylang_wpjm_init() {
|
14 |
add_filter( 'wpjm_lang', 'polylang_wpjm_get_job_listings_lang' );
|
15 |
add_filter( 'wpjm_page_id', 'polylang_wpjm_page_id' );
|
16 |
-
add_action( 'get_job_listings_query_args', 'polylang_wpjm_query_language' );
|
17 |
}
|
18 |
add_action( 'pll_init', 'polylang_wpjm_init' );
|
19 |
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Sets the current language when running job listings query.
|
23 |
-
*
|
24 |
-
* @since 1.29.1
|
25 |
-
*
|
26 |
-
* @param array $query_args
|
27 |
-
* @return array
|
28 |
-
*/
|
29 |
-
function polylang_wpjm_query_language( $query_args ) {
|
30 |
-
if ( isset( $_POST['lang'] ) ) {
|
31 |
-
$query_args['lang'] = $_POST['lang'];
|
32 |
-
}
|
33 |
-
return $query_args;
|
34 |
-
}
|
35 |
-
|
36 |
/**
|
37 |
* Returns Polylang's current language.
|
38 |
*
|
@@ -43,8 +24,8 @@ function polylang_wpjm_query_language( $query_args ) {
|
|
43 |
*/
|
44 |
function polylang_wpjm_get_job_listings_lang( $lang ) {
|
45 |
if ( function_exists( 'pll_current_language' )
|
46 |
-
|
47 |
-
|
48 |
return pll_current_language();
|
49 |
}
|
50 |
return $lang;
|
1 |
<?php
|
2 |
/**
|
3 |
* Only load these if Polylang plugin is installed and active.
|
|
|
|
|
4 |
*/
|
5 |
|
6 |
/**
|
11 |
function polylang_wpjm_init() {
|
12 |
add_filter( 'wpjm_lang', 'polylang_wpjm_get_job_listings_lang' );
|
13 |
add_filter( 'wpjm_page_id', 'polylang_wpjm_page_id' );
|
|
|
14 |
}
|
15 |
add_action( 'pll_init', 'polylang_wpjm_init' );
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
/**
|
18 |
* Returns Polylang's current language.
|
19 |
*
|
24 |
*/
|
25 |
function polylang_wpjm_get_job_listings_lang( $lang ) {
|
26 |
if ( function_exists( 'pll_current_language' )
|
27 |
+
&& function_exists( 'pll_is_translated_post_type' )
|
28 |
+
&& pll_is_translated_post_type( 'job_listing' ) ) {
|
29 |
return pll_current_language();
|
30 |
}
|
31 |
return $lang;
|
includes/3rd-party/rp4wp.php
DELETED
@@ -1,56 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Adds additional compatibility with Related Post for WordPress.
|
4 |
-
*
|
5 |
-
* @package wp-job-manager
|
6 |
-
*/
|
7 |
-
|
8 |
-
add_filter( 'rp4wp_get_template', 'wpjm_rp4wp_template', 10, 3 );
|
9 |
-
add_filter( 'rp4wp_related_meta_fields', 'wpjm_rp4wp_related_meta_fields', 10, 3 );
|
10 |
-
add_filter( 'rp4wp_related_meta_fields_weight', 'wpjm_rp4wp_related_meta_fields_weight', 10, 3 );
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Replaces RP4WP template with the template from Job Manager.
|
14 |
-
*
|
15 |
-
* @param string $located
|
16 |
-
* @param string $template_name
|
17 |
-
* @param array $args
|
18 |
-
* @return string
|
19 |
-
*/
|
20 |
-
function wpjm_rp4wp_template( $located, $template_name, $args ) {
|
21 |
-
if ( 'related-post-default.php' === $template_name && 'job_listing' === $args['related_post']->post_type ) {
|
22 |
-
return JOB_MANAGER_PLUGIN_DIR . '/templates/content-job_listing.php';
|
23 |
-
}
|
24 |
-
return $located;
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Adds meta fields for RP4WP to relate jobs by.
|
29 |
-
*
|
30 |
-
* @param array $meta_fields
|
31 |
-
* @param int $post_id
|
32 |
-
* @param WP_Post $post
|
33 |
-
* @return array
|
34 |
-
*/
|
35 |
-
function wpjm_rp4wp_related_meta_fields( $meta_fields, $post_id, $post ) {
|
36 |
-
if ( 'job_listing' === $post->post_type ) {
|
37 |
-
$meta_fields[] = '_company_name';
|
38 |
-
$meta_fields[] = '_job_location';
|
39 |
-
}
|
40 |
-
return $meta_fields;
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Adds meta fields for RP4WP to relate jobs by.
|
45 |
-
*
|
46 |
-
* @param int $weight
|
47 |
-
* @param WP_Post $post
|
48 |
-
* @param string $meta_field
|
49 |
-
* @return int
|
50 |
-
*/
|
51 |
-
function wpjm_rp4wp_related_meta_fields_weight( $weight, $post, $meta_field ) {
|
52 |
-
if ( 'job_listing' === $post->post_type ) {
|
53 |
-
$weight = 100;
|
54 |
-
}
|
55 |
-
return $weight;
|
56 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/3rd-party/wp-all-import.php
DELETED
@@ -1,25 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Adds additional compatibility with WP All Import.
|
4 |
-
*
|
5 |
-
* @package wp-job-manager
|
6 |
-
*/
|
7 |
-
|
8 |
-
add_action( 'pmxi_saved_post', 'wpjm_pmxi_saved_post', 10, 1 );
|
9 |
-
|
10 |
-
/**
|
11 |
-
* After importing via WP All Import, adds default meta data.
|
12 |
-
*
|
13 |
-
* @param int $post_id
|
14 |
-
*/
|
15 |
-
function wpjm_pmxi_saved_post( $post_id ) {
|
16 |
-
if ( 'job_listing' === get_post_type( $post_id ) ) {
|
17 |
-
WP_Job_Manager_Post_Types::instance()->maybe_add_default_meta_data( $post_id );
|
18 |
-
if ( ! WP_Job_Manager_Geocode::has_location_data( $post_id ) ) {
|
19 |
-
$location = get_post_meta( $post_id, '_job_location', true );
|
20 |
-
if ( $location ) {
|
21 |
-
WP_Job_Manager_Geocode::generate_location_data( $post_id, $location );
|
22 |
-
}
|
23 |
-
}
|
24 |
-
}
|
25 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/3rd-party/wpml.php
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
* Only load these if WPML plugin is installed and active.
|
4 |
-
*
|
5 |
-
* @package wp-job-manager
|
6 |
*/
|
7 |
|
8 |
/**
|
@@ -14,25 +12,11 @@ function wpml_wpjm_init() {
|
|
14 |
add_action( 'get_job_listings_init', 'wpml_wpjm_set_language' );
|
15 |
add_filter( 'wpjm_lang', 'wpml_wpjm_get_job_listings_lang' );
|
16 |
add_filter( 'wpjm_page_id', 'wpml_wpjm_page_id' );
|
17 |
-
|
18 |
-
$default_lang = apply_filters( 'wpml_default_language', null );
|
19 |
-
$current_lang = apply_filters( 'wpml_current_language', null );
|
20 |
-
|
21 |
-
// Add filter only for non default languages.
|
22 |
-
if ( $current_lang !== $default_lang ) {
|
23 |
-
add_filter( 'job_manager_settings', 'wpml_wpjm_hide_page_selection' );
|
24 |
-
}
|
25 |
}
|
26 |
-
|
27 |
add_action( 'wpml_loaded', 'wpml_wpjm_init' );
|
28 |
-
add_action( 'wpml_loaded', 'wpml_wpjm_set_language' );
|
29 |
|
30 |
/**
|
31 |
* Sets WPJM's language if it is sent in the Ajax request.
|
32 |
-
* Note: This is hooked into both `wpml_loaded` and `get_job_listings_init`. As of WPML 3.7.1, if it was hooked
|
33 |
-
* into just `wpml_loaded` the query doesn't get the correct language for job listings. If it is just hooked into
|
34 |
-
* `get_job_listings_init` the locale doesn't get set correctly and the string translations are only loaded from
|
35 |
-
* the default language.
|
36 |
*
|
37 |
* @since 1.26.0
|
38 |
*/
|
@@ -48,7 +32,6 @@ function wpml_wpjm_set_language() {
|
|
48 |
* @since 1.26.0
|
49 |
*
|
50 |
* @param string $lang
|
51 |
-
*
|
52 |
* @return string
|
53 |
*/
|
54 |
function wpml_wpjm_get_job_listings_lang( $lang ) {
|
@@ -59,45 +42,8 @@ function wpml_wpjm_get_job_listings_lang( $lang ) {
|
|
59 |
* Returns the page ID for the current language.
|
60 |
*
|
61 |
* @param int $page_id
|
62 |
-
*
|
63 |
* @return int
|
64 |
*/
|
65 |
function wpml_wpjm_page_id( $page_id ) {
|
66 |
return apply_filters( 'wpml_object_id', $page_id, 'page', true );
|
67 |
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Set WPJM page options to hidden for non default languages.
|
71 |
-
*
|
72 |
-
* @since 1.31.0
|
73 |
-
*
|
74 |
-
* @param array $settings
|
75 |
-
*
|
76 |
-
* @return array
|
77 |
-
*/
|
78 |
-
function wpml_wpjm_hide_page_selection( $settings ) {
|
79 |
-
foreach ( $settings['job_pages'][1] as $key => $setting ) {
|
80 |
-
if ( 'page' !== $setting['type'] ) {
|
81 |
-
continue;
|
82 |
-
}
|
83 |
-
$setting['type'] = 'hidden';
|
84 |
-
$setting['human_value'] = __( 'Page Not Set', 'wp-job-manager' );
|
85 |
-
$current_value = get_option( $setting['name'] );
|
86 |
-
if ( $current_value ) {
|
87 |
-
$page = get_post( apply_filters( 'wpml_object_id', $current_value, 'page' ) );
|
88 |
-
|
89 |
-
if ( $page ) {
|
90 |
-
$setting['human_value'] = $page->post_title;
|
91 |
-
}
|
92 |
-
}
|
93 |
-
|
94 |
-
$default_lang = apply_filters( 'wpml_default_language', null );
|
95 |
-
$url_to_edit_page = admin_url( 'edit.php?post_type=job_listing&page=job-manager-settings&lang=' . $default_lang . '#settings-job_pages' );
|
96 |
-
|
97 |
-
// translators: Placeholder (%s) is the URL to edit the primary language in WPML.
|
98 |
-
$setting['desc'] = sprintf( __( '<a href="%s">Switch to primary language</a> to edit this setting.', 'wp-job-manager' ), $url_to_edit_page );
|
99 |
-
$settings['job_pages'][1][ $key ] = $setting;
|
100 |
-
}
|
101 |
-
|
102 |
-
return $settings;
|
103 |
-
}
|
1 |
<?php
|
2 |
/**
|
3 |
* Only load these if WPML plugin is installed and active.
|
|
|
|
|
4 |
*/
|
5 |
|
6 |
/**
|
12 |
add_action( 'get_job_listings_init', 'wpml_wpjm_set_language' );
|
13 |
add_filter( 'wpjm_lang', 'wpml_wpjm_get_job_listings_lang' );
|
14 |
add_filter( 'wpjm_page_id', 'wpml_wpjm_page_id' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
}
|
|
|
16 |
add_action( 'wpml_loaded', 'wpml_wpjm_init' );
|
|
|
17 |
|
18 |
/**
|
19 |
* Sets WPJM's language if it is sent in the Ajax request.
|
|
|
|
|
|
|
|
|
20 |
*
|
21 |
* @since 1.26.0
|
22 |
*/
|
32 |
* @since 1.26.0
|
33 |
*
|
34 |
* @param string $lang
|
|
|
35 |
* @return string
|
36 |
*/
|
37 |
function wpml_wpjm_get_job_listings_lang( $lang ) {
|
42 |
* Returns the page ID for the current language.
|
43 |
*
|
44 |
* @param int $page_id
|
|
|
45 |
* @return int
|
46 |
*/
|
47 |
function wpml_wpjm_page_id( $page_id ) {
|
48 |
return apply_filters( 'wpml_object_id', $page_id, 'page', true );
|
49 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/3rd-party/yoast.php
DELETED
@@ -1,29 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Adds additional compatibility with Yoast SEO.
|
4 |
-
*
|
5 |
-
* Yoast SEO will by default include the `job_listing` post type because it is flagged as public.
|
6 |
-
*
|
7 |
-
* @package wp-job-manager
|
8 |
-
*/
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Skip filled job listings.
|
12 |
-
*
|
13 |
-
* @param array $url Array of URL parts.
|
14 |
-
* @param string $type URL type.
|
15 |
-
* @param object $post Post object.
|
16 |
-
* @return string|bool False if we're skipping.
|
17 |
-
*/
|
18 |
-
function wpjm_yoast_skip_filled_job_listings( $url, $type, $post ) {
|
19 |
-
if ( 'job_listing' !== $post->post_type ) {
|
20 |
-
return $url;
|
21 |
-
}
|
22 |
-
|
23 |
-
if ( is_position_filled( $post ) ) {
|
24 |
-
return false;
|
25 |
-
}
|
26 |
-
|
27 |
-
return $url;
|
28 |
-
}
|
29 |
-
add_action( 'wpseo_sitemap_entry', 'wpjm_yoast_skip_filled_job_listings', 10, 3 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/abstracts/abstract-wp-job-manager-email-template.php
DELETED
@@ -1,133 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Abstract class for an email notification built using templates.
|
4 |
-
*
|
5 |
-
* @package wp-job-manager
|
6 |
-
*
|
7 |
-
* @since 1.31.0
|
8 |
-
*/
|
9 |
-
|
10 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
-
exit; // Exit if accessed directly.
|
12 |
-
}
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Class WP_Job_Manager_Email_Template
|
16 |
-
*/
|
17 |
-
abstract class WP_Job_Manager_Email_Template extends WP_Job_Manager_Email {
|
18 |
-
/**
|
19 |
-
* Get the template path for overriding templates.
|
20 |
-
*
|
21 |
-
* @type abstract
|
22 |
-
* @return string
|
23 |
-
*/
|
24 |
-
public static function get_template_path() {
|
25 |
-
return 'job_manager';
|
26 |
-
}
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Get the default template path that WP Job Manager should look for the templates.
|
30 |
-
*
|
31 |
-
* @type abstract
|
32 |
-
* @return string
|
33 |
-
*/
|
34 |
-
public static function get_template_default_path() {
|
35 |
-
return '';
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Get the rich text version of the email content.
|
40 |
-
*
|
41 |
-
* @return string
|
42 |
-
*/
|
43 |
-
public function get_rich_content() {
|
44 |
-
return $this->get_template( false );
|
45 |
-
}
|
46 |
-
|
47 |
-
/**
|
48 |
-
* Get the plaintext version of the email content.
|
49 |
-
*
|
50 |
-
* @return string
|
51 |
-
*/
|
52 |
-
public function get_plain_content() {
|
53 |
-
if ( $this->has_template( true ) ) {
|
54 |
-
return $this->get_template( true );
|
55 |
-
}
|
56 |
-
return parent::get_plain_content();
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Get the contents of a template.
|
61 |
-
*
|
62 |
-
* @param bool $plain_text
|
63 |
-
* @return string
|
64 |
-
*/
|
65 |
-
public function get_template( $plain_text = false ) {
|
66 |
-
$template_file = $this->locate_template( $plain_text );
|
67 |
-
if ( ! $template_file ) {
|
68 |
-
return '';
|
69 |
-
}
|
70 |
-
$args = $this->get_args();
|
71 |
-
$email = $this;
|
72 |
-
|
73 |
-
ob_start();
|
74 |
-
include $template_file;
|
75 |
-
return ob_get_clean();
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Check to see if a template exists for this email.
|
80 |
-
*
|
81 |
-
* @param bool $plain_text
|
82 |
-
* @return bool
|
83 |
-
*/
|
84 |
-
public function has_template( $plain_text = false ) {
|
85 |
-
$template_file = $this->locate_template( $plain_text );
|
86 |
-
return $template_file && file_exists( $template_file );
|
87 |
-
}
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Locate template for this email.
|
91 |
-
*
|
92 |
-
* @param bool $plain_text
|
93 |
-
* @return string
|
94 |
-
*/
|
95 |
-
protected function locate_template( $plain_text ) {
|
96 |
-
$class_name = get_class( $this );
|
97 |
-
$template_path = call_user_func( array( $class_name, 'get_template_path' ) );
|
98 |
-
$template_default_path = call_user_func( array( $class_name, 'get_template_default_path' ) );
|
99 |
-
return locate_job_manager_template( $this->get_template_file_name( $plain_text ), $template_path, $template_default_path );
|
100 |
-
}
|
101 |
-
|
102 |
-
/**
|
103 |
-
* Generate the file name for the email template.
|
104 |
-
*
|
105 |
-
* @param bool $plain_text
|
106 |
-
* @return string
|
107 |
-
*/
|
108 |
-
protected function get_template_file_name( $plain_text = false ) {
|
109 |
-
$class_name = get_class( $this );
|
110 |
-
// PHP 5.2: Using `call_user_func()` but `$class_name::get_key()` preferred.
|
111 |
-
$email_notification_key = call_user_func( array( $class_name, 'get_key' ) );
|
112 |
-
$template_name = str_replace( '_', '-', $email_notification_key );
|
113 |
-
return self::generate_template_file_name( $template_name, $plain_text );
|
114 |
-
}
|
115 |
-
|
116 |
-
/**
|
117 |
-
* Generate the file name for the email template.
|
118 |
-
*
|
119 |
-
* @param string $template_name
|
120 |
-
* @param bool $plain_text
|
121 |
-
* @return string
|
122 |
-
*/
|
123 |
-
public static function generate_template_file_name( $template_name, $plain_text = false ) {
|
124 |
-
$file_name_parts = array( 'emails' );
|
125 |
-
if ( $plain_text ) {
|
126 |
-
$file_name_parts[] = 'plain';
|
127 |
-
}
|
128 |
-
|
129 |
-
$file_name_parts[] = $template_name . '.php';
|
130 |
-
|
131 |
-
return implode( '/', $file_name_parts );
|
132 |
-
}
|
133 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/abstracts/abstract-wp-job-manager-email.php
DELETED
@@ -1,231 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Abstract email notification class.
|
4 |
-
*
|
5 |
-
* @package wp-job-manager
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit; // Exit if accessed directly.
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Abstract class for an email notification.
|
14 |
-
*
|
15 |
-
* Do not rely on WordPress global variables or functions that rely on global variables such as `wp_get_current_user()`.
|
16 |
-
* Email might be generated when no longer in scope. Instead, pass the values on as an argument when initiating the email
|
17 |
-
* notification.
|
18 |
-
*
|
19 |
-
* Additionally, inside of plugins and themes, load email notification files based on this class inside the
|
20 |
-
* `job_manager_email_init` hook. This will prevent unnecessary loading and won't include the files if this abstract
|
21 |
-
* class isn't available.
|
22 |
-
*
|
23 |
-
* Example:
|
24 |
-
* ```
|
25 |
-
* add_action( 'job_manager_email_init', 'custom_plugin_include_emails' );
|
26 |
-
* function custom_plugin_include_emails() {
|
27 |
-
* include_once 'emails/custom-plugin-sent-resume.php`;
|
28 |
-
* }
|
29 |
-
* ```
|
30 |
-
*
|
31 |
-
* @package wp-job-manager
|
32 |
-
*
|
33 |
-
* @since 1.31.0
|
34 |
-
*/
|
35 |
-
abstract class WP_Job_Manager_Email {
|
36 |
-
/**
|
37 |
-
* Arguments used in an instance of an email notification.
|
38 |
-
*
|
39 |
-
* @var array
|
40 |
-
*/
|
41 |
-
private $args = array();
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Settings for this email notification.
|
45 |
-
*
|
46 |
-
* @var array
|
47 |
-
*/
|
48 |
-
private $settings = array();
|
49 |
-
|
50 |
-
/**
|
51 |
-
* WP_Job_Manager_Email constructor.
|
52 |
-
*
|
53 |
-
* @param array $args Arguments used in forming email notification.
|
54 |
-
* @param array $settings Settings for this notification.
|
55 |
-
*/
|
56 |
-
final public function __construct( $args, $settings ) {
|
57 |
-
$this->args = $this->prepare_args( (array) $args );
|
58 |
-
$this->settings = (array) $settings;
|
59 |
-
}
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Get the unique email notification key.
|
63 |
-
*
|
64 |
-
* @type abstract
|
65 |
-
*
|
66 |
-
* @return string
|
67 |
-
*/
|
68 |
-
public static function get_key() {
|
69 |
-
return false;
|
70 |
-
}
|
71 |
-
|
72 |
-
/**
|
73 |
-
* Get the friendly name for this email notification.
|
74 |
-
*
|
75 |
-
* @type abstract
|
76 |
-
* @return string
|
77 |
-
*/
|
78 |
-
public static function get_name() {
|
79 |
-
return false;
|
80 |
-
}
|
81 |
-
|
82 |
-
/**
|
83 |
-
* Get the description for this email notification.
|
84 |
-
*
|
85 |
-
* @type abstract
|
86 |
-
* @return string
|
87 |
-
*/
|
88 |
-
public static function get_description() {
|
89 |
-
return '';
|
90 |
-
}
|
91 |
-
|
92 |
-
/**
|
93 |
-
* Get the context for where this email notification is used. Used to direct which admin settings to show.
|
94 |
-
*
|
95 |
-
* @type abstract
|
96 |
-
* @return string
|
97 |
-
*/
|
98 |
-
public static function get_context() {
|
99 |
-
return 'job_manager';
|
100 |
-
}
|
101 |
-
|
102 |
-
/**
|
103 |
-
* Get the email subject.
|
104 |
-
*
|
105 |
-
* @return string
|
106 |
-
*/
|
107 |
-
abstract public function get_subject();
|
108 |
-
|
109 |
-
/**
|
110 |
-
* Get `From:` address header value. Can be simple email or formatted `Firstname Lastname <email@example.com>`.
|
111 |
-
*
|
112 |
-
* @return string|bool Email from value or false to use WordPress' default.
|
113 |
-
*/
|
114 |
-
abstract public function get_from();
|
115 |
-
|
116 |
-
/**
|
117 |
-
* Get array or comma-separated list of email addresses to send message.
|
118 |
-
*
|
119 |
-
* @return string|array
|
120 |
-
*/
|
121 |
-
abstract public function get_to();
|
122 |
-
|
123 |
-
/**
|
124 |
-
* Get the rich text version of the email content.
|
125 |
-
*
|
126 |
-
* @return string
|
127 |
-
*/
|
128 |
-
abstract public function get_rich_content();
|
129 |
-
|
130 |
-
/**
|
131 |
-
* Expand arguments as necessary for the generation of the email.
|
132 |
-
*
|
133 |
-
* @param array $args Arguments used to generate the email.
|
134 |
-
* @return array
|
135 |
-
*/
|
136 |
-
protected function prepare_args( $args ) {
|
137 |
-
if ( isset( $args['job_id'] ) ) {
|
138 |
-
$job = get_post( $args['job_id'] );
|
139 |
-
if ( $job instanceof WP_Post ) {
|
140 |
-
$args['job'] = $job;
|
141 |
-
}
|
142 |
-
}
|
143 |
-
if ( isset( $args['job'] ) && $args['job'] instanceof WP_Post ) {
|
144 |
-
$author = get_user_by( 'ID', $args['job']->post_author );
|
145 |
-
if ( $author instanceof WP_User ) {
|
146 |
-
$args['author'] = $author;
|
147 |
-
}
|
148 |
-
}
|
149 |
-
|
150 |
-
return $args;
|
151 |
-
}
|
152 |
-
|
153 |
-
/**
|
154 |
-
* Checks the arguments and returns whether the email notification is properly set up.
|
155 |
-
*
|
156 |
-
* @return bool
|
157 |
-
*/
|
158 |
-
abstract public function is_valid();
|
159 |
-
|
160 |
-
/**
|
161 |
-
* Returns the list of file paths to attach to an email.
|
162 |
-
*
|
163 |
-
* @return array
|
164 |
-
*/
|
165 |
-
public function get_attachments() {
|
166 |
-
return array();
|
167 |
-
}
|
168 |
-
|
169 |
-
/**
|
170 |
-
* Returns the value of the CC header, if needed.
|
171 |
-
*
|
172 |
-
* @return string|null
|
173 |
-
*/
|
174 |
-
public function get_cc() {
|
175 |
-
return null;
|
176 |
-
}
|
177 |
-
|
178 |
-
/**
|
179 |
-
* Get the base headers for the email. No need to add CC or From headers. Content-type is added when sending rich-text.
|
180 |
-
*
|
181 |
-
* @return array
|
182 |
-
*/
|
183 |
-
public function get_headers() {
|
184 |
-
return array();
|
185 |
-
}
|
186 |
-
|
187 |
-
/**
|
188 |
-
* Get the plaintext version of the email content.
|
189 |
-
*
|
190 |
-
* @return string
|
191 |
-
*/
|
192 |
-
public function get_plain_content() {
|
193 |
-
return strip_tags( $this->get_rich_content() );
|
194 |
-
}
|
195 |
-
|
196 |
-
/**
|
197 |
-
* Get the settings for this email notifications.
|
198 |
-
*
|
199 |
-
* @return array
|
200 |
-
*/
|
201 |
-
public static function get_setting_fields() {
|
202 |
-
return array();
|
203 |
-
}
|
204 |
-
|
205 |
-
/**
|
206 |
-
* Is this email notification enabled by default?
|
207 |
-
*
|
208 |
-
* @return bool
|
209 |
-
*/
|
210 |
-
public static function is_default_enabled() {
|
211 |
-
return true;
|
212 |
-
}
|
213 |
-
|
214 |
-
/**
|
215 |
-
* Returns the args that the email notification was sent with.
|
216 |
-
*
|
217 |
-
* @return array
|
218 |
-
*/
|
219 |
-
final protected function get_args() {
|
220 |
-
return $this->args;
|
221 |
-
}
|
222 |
-
|
223 |
-
/**
|
224 |
-
* Returns the settings values.
|
225 |
-
*
|
226 |
-
* @return array
|
227 |
-
*/
|
228 |
-
final protected function get_settings() {
|
229 |
-
return $this->settings;
|
230 |
-
}
|
231 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/abstracts/abstract-wp-job-manager-form.php
CHANGED
@@ -76,17 +76,17 @@ abstract class WP_Job_Manager_Form {
|
|
76 |
*/
|
77 |
public function process() {
|
78 |
|
79 |
-
// reset cookie
|
80 |
if (
|
81 |
-
isset( $_GET['new'] ) &&
|
82 |
-
isset( $_COOKIE['wp-job-manager-submitting-job-id'] ) &&
|
83 |
-
isset( $_COOKIE['wp-job-manager-submitting-job-key'] ) &&
|
84 |
-
get_post_meta( $_COOKIE['wp-job-manager-submitting-job-id'], '_submitting_key', true )
|
85 |
) {
|
86 |
-
delete_post_meta( $_COOKIE['wp-job-manager-submitting-job-id'], '_submitting_key' );
|
87 |
setcookie( 'wp-job-manager-submitting-job-id', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN, false );
|
88 |
setcookie( 'wp-job-manager-submitting-job-key', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN, false );
|
89 |
-
wp_redirect( remove_query_arg( array( 'new', 'key' ), $_SERVER['REQUEST_URI'] ) );
|
90 |
}
|
91 |
|
92 |
$step_key = $this->get_step_key( $this->step );
|
@@ -109,7 +109,6 @@ abstract class WP_Job_Manager_Form {
|
|
109 |
* @param array $atts Attributes to use in the view handler.
|
110 |
*/
|
111 |
public function output( $atts = array() ) {
|
112 |
-
$this->enqueue_scripts();
|
113 |
$step_key = $this->get_step_key( $this->step );
|
114 |
$this->show_errors();
|
115 |
|
@@ -132,7 +131,7 @@ abstract class WP_Job_Manager_Form {
|
|
132 |
*/
|
133 |
public function show_errors() {
|
134 |
foreach ( $this->errors as $error ) {
|
135 |
-
echo '<div class="job-manager-error">' .
|
136 |
}
|
137 |
}
|
138 |
|
@@ -237,10 +236,10 @@ abstract class WP_Job_Manager_Form {
|
|
237 |
* @return int
|
238 |
*/
|
239 |
protected function sort_by_priority( $a, $b ) {
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
}
|
245 |
|
246 |
/**
|
@@ -250,105 +249,10 @@ abstract class WP_Job_Manager_Form {
|
|
250 |
$this->fields = array();
|
251 |
}
|
252 |
|
253 |
-
/**
|
254 |
-
* Enqueue the scripts for the form.
|
255 |
-
*/
|
256 |
-
public function enqueue_scripts() {
|
257 |
-
if ( $this->use_recaptcha_field() ) {
|
258 |
-
wp_enqueue_script( 'recaptcha', 'https://www.google.com/recaptcha/api.js' );
|
259 |
-
}
|
260 |
-
}
|
261 |
-
|
262 |
-
/**
|
263 |
-
* Checks whether reCAPTCHA has been set up and is available.
|
264 |
-
*
|
265 |
-
* @return bool
|
266 |
-
*/
|
267 |
-
public function is_recaptcha_available() {
|
268 |
-
$site_key = get_option( 'job_manager_recaptcha_site_key' );
|
269 |
-
$secret_key = get_option( 'job_manager_recaptcha_secret_key' );
|
270 |
-
$is_recaptcha_available = ! empty( $site_key ) && ! empty( $secret_key );
|
271 |
-
|
272 |
-
/**
|
273 |
-
* Filter whether reCAPTCHA should be available for this form.
|
274 |
-
*
|
275 |
-
* @since 1.30.0
|
276 |
-
*
|
277 |
-
* @param bool $is_recaptcha_available
|
278 |
-
*/
|
279 |
-
return apply_filters( 'job_manager_is_recaptcha_available', $is_recaptcha_available );
|
280 |
-
}
|
281 |
-
|
282 |
-
/**
|
283 |
-
* Show reCAPTCHA field on the form.
|
284 |
-
*
|
285 |
-
* @return bool
|
286 |
-
*/
|
287 |
-
public function use_recaptcha_field() {
|
288 |
-
return false;
|
289 |
-
}
|
290 |
-
|
291 |
-
/**
|
292 |
-
* Output the reCAPTCHA field.
|
293 |
-
*/
|
294 |
-
public function display_recaptcha_field() {
|
295 |
-
$field = array();
|
296 |
-
$field['label'] = get_option( 'job_manager_recaptcha_label' );
|
297 |
-
$field['required'] = true;
|
298 |
-
$field['site_key'] = get_option( 'job_manager_recaptcha_site_key' );
|
299 |
-
get_job_manager_template(
|
300 |
-
'form-fields/recaptcha-field.php',
|
301 |
-
array(
|
302 |
-
'key' => 'recaptcha',
|
303 |
-
'field' => $field,
|
304 |
-
)
|
305 |
-
);
|
306 |
-
}
|
307 |
-
|
308 |
-
/**
|
309 |
-
* Validate a reCAPTCHA field.
|
310 |
-
*
|
311 |
-
* @param bool $success
|
312 |
-
*
|
313 |
-
* @return bool|WP_Error
|
314 |
-
*/
|
315 |
-
public function validate_recaptcha_field( $success ) {
|
316 |
-
$recaptcha_field_label = get_option( 'job_manager_recaptcha_label' );
|
317 |
-
if ( empty( $_POST['g-recaptcha-response'] ) ) {
|
318 |
-
// translators: Placeholder is for the label of the reCAPTCHA field.
|
319 |
-
return new WP_Error( 'validation-error', sprintf( esc_html__( '"%s" check failed. Please try again.', 'wp-job-manager' ), $recaptcha_field_label ) );
|
320 |
-
}
|
321 |
-
|
322 |
-
$response = wp_remote_get(
|
323 |
-
add_query_arg(
|
324 |
-
array(
|
325 |
-
'secret' => get_option( 'job_manager_recaptcha_secret_key' ),
|
326 |
-
'response' => isset( $_POST['g-recaptcha-response'] ) ? $_POST['g-recaptcha-response'] : '',
|
327 |
-
'remoteip' => isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'],
|
328 |
-
),
|
329 |
-
'https://www.google.com/recaptcha/api/siteverify'
|
330 |
-
)
|
331 |
-
);
|
332 |
-
|
333 |
-
// translators: %s is the name of the form validation that failed.
|
334 |
-
$validation_error = new WP_Error( 'validation-error', sprintf( esc_html__( '"%s" check failed. Please try again.', 'wp-job-manager' ), $recaptcha_field_label ) );
|
335 |
-
|
336 |
-
if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
|
337 |
-
return $validation_error;
|
338 |
-
}
|
339 |
-
|
340 |
-
$json = json_decode( $response['body'] );
|
341 |
-
if ( ! $json || ! $json->success ) {
|
342 |
-
return $validation_error;
|
343 |
-
}
|
344 |
-
|
345 |
-
return $success;
|
346 |
-
}
|
347 |
-
|
348 |
/**
|
349 |
* Gets post data for fields.
|
350 |
*
|
351 |
-
* @return array of data
|
352 |
*/
|
353 |
protected function get_posted_fields() {
|
354 |
$this->init_fields();
|
@@ -357,11 +261,10 @@ abstract class WP_Job_Manager_Form {
|
|
357 |
|
358 |
foreach ( $this->fields as $group_key => $group_fields ) {
|
359 |
foreach ( $group_fields as $key => $field ) {
|
360 |
-
// Get the value
|
361 |
$field_type = str_replace( '-', '_', $field['type'] );
|
362 |
-
$handler = apply_filters( "job_manager_get_posted_{$field_type}_field", false );
|
363 |
|
364 |
-
if ( $handler ) {
|
365 |
$values[ $group_key ][ $key ] = call_user_func( $handler, $key, $field );
|
366 |
} elseif ( method_exists( $this, "get_posted_{$field_type}_field" ) ) {
|
367 |
$values[ $group_key ][ $key ] = call_user_func( array( $this, "get_posted_{$field_type}_field" ), $key, $field );
|
@@ -369,7 +272,7 @@ abstract class WP_Job_Manager_Form {
|
|
369 |
$values[ $group_key ][ $key ] = $this->get_posted_field( $key, $field );
|
370 |
}
|
371 |
|
372 |
-
// Set fields value
|
373 |
$this->fields[ $group_key ][ $key ]['value'] = $values[ $group_key ][ $key ];
|
374 |
}
|
375 |
}
|
@@ -380,44 +283,14 @@ abstract class WP_Job_Manager_Form {
|
|
380 |
/**
|
381 |
* Navigates through an array and sanitizes the field.
|
382 |
*
|
383 |
-
* @
|
384 |
-
* @
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
* @return array|string $value The sanitized array (or string from the callback).
|
390 |
-
*/
|
391 |
-
protected function sanitize_posted_field( $value, $sanitizer = null ) {
|
392 |
-
// Sanitize value.
|
393 |
-
if ( is_array( $value ) ) {
|
394 |
-
foreach ( $value as $key => $val ) {
|
395 |
-
$value[ $key ] = $this->sanitize_posted_field( $val, $sanitizer );
|
396 |
-
}
|
397 |
-
|
398 |
-
return $value;
|
399 |
-
}
|
400 |
-
|
401 |
-
$value = trim( $value );
|
402 |
-
|
403 |
-
if ( 'url' === $sanitizer ) {
|
404 |
-
return esc_url_raw( $value );
|
405 |
-
} elseif ( 'email' === $sanitizer ) {
|
406 |
-
return sanitize_email( $value );
|
407 |
-
} elseif ( 'url_or_email' === $sanitizer ) {
|
408 |
-
if ( null !== wp_parse_url( $value, PHP_URL_HOST ) ) {
|
409 |
-
// Sanitize as URL.
|
410 |
-
return esc_url_raw( $value );
|
411 |
-
}
|
412 |
-
|
413 |
-
// Sanitize as email.
|
414 |
-
return sanitize_email( $value );
|
415 |
-
} elseif ( is_callable( $sanitizer ) ) {
|
416 |
-
return call_user_func( $sanitizer, $value );
|
417 |
-
}
|
418 |
|
419 |
-
|
420 |
-
return sanitize_text_field( stripslashes( $value ) );
|
421 |
}
|
422 |
|
423 |
/**
|
@@ -428,11 +301,7 @@ abstract class WP_Job_Manager_Form {
|
|
428 |
* @return string|array
|
429 |
*/
|
430 |
protected function get_posted_field( $key, $field ) {
|
431 |
-
|
432 |
-
if ( ! isset( $field['sanitizer'] ) ) {
|
433 |
-
$field['sanitizer'] = null;
|
434 |
-
}
|
435 |
-
return isset( $_POST[ $key ] ) ? $this->sanitize_posted_field( $_POST[ $key ], $field['sanitizer'] ) : '';
|
436 |
}
|
437 |
|
438 |
/**
|
@@ -451,9 +320,7 @@ abstract class WP_Job_Manager_Form {
|
|
451 |
*
|
452 |
* @param string $key
|
453 |
* @param array $field
|
454 |
-
*
|
455 |
* @return string|array
|
456 |
-
* @throws Exception When the upload fails.
|
457 |
*/
|
458 |
protected function get_posted_file_field( $key, $field ) {
|
459 |
$file = $this->upload_file( $key, $field );
|
@@ -497,8 +364,8 @@ abstract class WP_Job_Manager_Form {
|
|
497 |
* @return array
|
498 |
*/
|
499 |
protected function get_posted_term_checklist_field( $key, $field ) {
|
500 |
-
if ( isset( $_POST['tax_input'] ) && isset( $_POST['tax_input'][ $field['taxonomy'] ] ) ) {
|
501 |
-
return array_map( 'absint', $_POST['tax_input'][ $field['taxonomy'] ] );
|
502 |
} else {
|
503 |
return array();
|
504 |
}
|
@@ -509,7 +376,7 @@ abstract class WP_Job_Manager_Form {
|
|
509 |
*
|
510 |
* @param string $key
|
511 |
* @param array $field
|
512 |
-
* @return
|
513 |
*/
|
514 |
protected function get_posted_term_multiselect_field( $key, $field ) {
|
515 |
return isset( $_POST[ $key ] ) ? array_map( 'absint', $_POST[ $key ] ) : array();
|
@@ -531,7 +398,7 @@ abstract class WP_Job_Manager_Form {
|
|
531 |
*
|
532 |
* @param string $field_key
|
533 |
* @param array $field
|
534 |
-
* @throws Exception When file upload failed
|
535 |
* @return string|array
|
536 |
*/
|
537 |
protected function upload_file( $field_key, $field ) {
|
@@ -546,13 +413,10 @@ abstract class WP_Job_Manager_Form {
|
|
546 |
$files_to_upload = job_manager_prepare_uploaded_files( $_FILES[ $field_key ] );
|
547 |
|
548 |
foreach ( $files_to_upload as $file_to_upload ) {
|
549 |
-
$uploaded_file = job_manager_upload_file(
|
550 |
-
$
|
551 |
-
|
552 |
-
|
553 |
-
'allowed_mime_types' => $allowed_mime_types,
|
554 |
-
)
|
555 |
-
);
|
556 |
|
557 |
if ( is_wp_error( $uploaded_file ) ) {
|
558 |
throw new Exception( $uploaded_file->get_error_message() );
|
76 |
*/
|
77 |
public function process() {
|
78 |
|
79 |
+
// reset cookie
|
80 |
if (
|
81 |
+
isset( $_GET[ 'new' ] ) &&
|
82 |
+
isset( $_COOKIE[ 'wp-job-manager-submitting-job-id' ] ) &&
|
83 |
+
isset( $_COOKIE[ 'wp-job-manager-submitting-job-key' ] ) &&
|
84 |
+
get_post_meta( $_COOKIE[ 'wp-job-manager-submitting-job-id' ], '_submitting_key', true ) == $_COOKIE['wp-job-manager-submitting-job-key']
|
85 |
) {
|
86 |
+
delete_post_meta( $_COOKIE[ 'wp-job-manager-submitting-job-id' ], '_submitting_key' );
|
87 |
setcookie( 'wp-job-manager-submitting-job-id', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN, false );
|
88 |
setcookie( 'wp-job-manager-submitting-job-key', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN, false );
|
89 |
+
wp_redirect( remove_query_arg( array( 'new', 'key' ), $_SERVER[ 'REQUEST_URI' ] ) );
|
90 |
}
|
91 |
|
92 |
$step_key = $this->get_step_key( $this->step );
|
109 |
* @param array $atts Attributes to use in the view handler.
|
110 |
*/
|
111 |
public function output( $atts = array() ) {
|
|
|
112 |
$step_key = $this->get_step_key( $this->step );
|
113 |
$this->show_errors();
|
114 |
|
131 |
*/
|
132 |
public function show_errors() {
|
133 |
foreach ( $this->errors as $error ) {
|
134 |
+
echo '<div class="job-manager-error">' . $error . '</div>';
|
135 |
}
|
136 |
}
|
137 |
|
236 |
* @return int
|
237 |
*/
|
238 |
protected function sort_by_priority( $a, $b ) {
|
239 |
+
if ( $a['priority'] == $b['priority'] ) {
|
240 |
+
return 0;
|
241 |
+
}
|
242 |
+
return ( $a['priority'] < $b['priority'] ) ? -1 : 1;
|
243 |
}
|
244 |
|
245 |
/**
|
249 |
$this->fields = array();
|
250 |
}
|
251 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
252 |
/**
|
253 |
* Gets post data for fields.
|
254 |
*
|
255 |
+
* @return array of data
|
256 |
*/
|
257 |
protected function get_posted_fields() {
|
258 |
$this->init_fields();
|
261 |
|
262 |
foreach ( $this->fields as $group_key => $group_fields ) {
|
263 |
foreach ( $group_fields as $key => $field ) {
|
264 |
+
// Get the value
|
265 |
$field_type = str_replace( '-', '_', $field['type'] );
|
|
|
266 |
|
267 |
+
if ( $handler = apply_filters( "job_manager_get_posted_{$field_type}_field", false ) ) {
|
268 |
$values[ $group_key ][ $key ] = call_user_func( $handler, $key, $field );
|
269 |
} elseif ( method_exists( $this, "get_posted_{$field_type}_field" ) ) {
|
270 |
$values[ $group_key ][ $key ] = call_user_func( array( $this, "get_posted_{$field_type}_field" ), $key, $field );
|
272 |
$values[ $group_key ][ $key ] = $this->get_posted_field( $key, $field );
|
273 |
}
|
274 |
|
275 |
+
// Set fields value
|
276 |
$this->fields[ $group_key ][ $key ]['value'] = $values[ $group_key ][ $key ];
|
277 |
}
|
278 |
}
|
283 |
/**
|
284 |
* Navigates through an array and sanitizes the field.
|
285 |
*
|
286 |
+
* @param array|string $value The array or string to be sanitized.
|
287 |
+
* @return array|string $value The sanitized array (or string from the callback).
|
288 |
+
*/
|
289 |
+
protected function sanitize_posted_field( $value ) {
|
290 |
+
// Santize value
|
291 |
+
$value = is_array( $value ) ? array_map( array( $this, 'sanitize_posted_field' ), $value ) : sanitize_text_field( stripslashes( trim( $value ) ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
|
293 |
+
return $value;
|
|
|
294 |
}
|
295 |
|
296 |
/**
|
301 |
* @return string|array
|
302 |
*/
|
303 |
protected function get_posted_field( $key, $field ) {
|
304 |
+
return isset( $_POST[ $key ] ) ? $this->sanitize_posted_field( $_POST[ $key ] ) : '';
|
|
|
|
|
|
|
|
|
305 |
}
|
306 |
|
307 |
/**
|
320 |
*
|
321 |
* @param string $key
|
322 |
* @param array $field
|
|
|
323 |
* @return string|array
|
|
|
324 |
*/
|
325 |
protected function get_posted_file_field( $key, $field ) {
|
326 |
$file = $this->upload_file( $key, $field );
|
364 |
* @return array
|
365 |
*/
|
366 |
protected function get_posted_term_checklist_field( $key, $field ) {
|
367 |
+
if ( isset( $_POST[ 'tax_input' ] ) && isset( $_POST[ 'tax_input' ][ $field['taxonomy'] ] ) ) {
|
368 |
+
return array_map( 'absint', $_POST[ 'tax_input' ][ $field['taxonomy'] ] );
|
369 |
} else {
|
370 |
return array();
|
371 |
}
|
376 |
*
|
377 |
* @param string $key
|
378 |
* @param array $field
|
379 |
+
* @return int
|
380 |
*/
|
381 |
protected function get_posted_term_multiselect_field( $key, $field ) {
|
382 |
return isset( $_POST[ $key ] ) ? array_map( 'absint', $_POST[ $key ] ) : array();
|
398 |
*
|
399 |
* @param string $field_key
|
400 |
* @param array $field
|
401 |
+
* @throws Exception When file upload failed
|
402 |
* @return string|array
|
403 |
*/
|
404 |
protected function upload_file( $field_key, $field ) {
|
413 |
$files_to_upload = job_manager_prepare_uploaded_files( $_FILES[ $field_key ] );
|
414 |
|
415 |
foreach ( $files_to_upload as $file_to_upload ) {
|
416 |
+
$uploaded_file = job_manager_upload_file( $file_to_upload, array(
|
417 |
+
'file_key' => $field_key,
|
418 |
+
'allowed_mime_types' => $allowed_mime_types,
|
419 |
+
) );
|
|
|
|
|
|
|
420 |
|
421 |
if ( is_wp_error( $uploaded_file ) ) {
|
422 |
throw new Exception( $uploaded_file->get_error_message() );
|
includes/admin/class-wp-job-manager-addons.php
CHANGED
@@ -1,13 +1,11 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Addons Page
|
4 |
-
*
|
5 |
-
* @package wp-job-manager
|
6 |
*/
|
7 |
|
8 |
-
if ( ! defined( 'ABSPATH' ) )
|
9 |
-
|
10 |
-
|
11 |
|
12 |
/**
|
13 |
* Handles the admin add-ons page.
|
@@ -16,20 +14,19 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
16 |
* @since 1.1.0
|
17 |
*/
|
18 |
class WP_Job_Manager_Addons {
|
19 |
-
const WPJM_COM_PRODUCTS_API_BASE_URL = 'https://wpjobmanager.com/wp-json/wpjmcom-products/1.0';
|
20 |
|
21 |
/**
|
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 |
*/
|
@@ -41,110 +38,57 @@ class WP_Job_Manager_Addons {
|
|
41 |
}
|
42 |
|
43 |
/**
|
44 |
-
*
|
45 |
-
*
|
46 |
-
* @since 1.30.0
|
47 |
-
*
|
48 |
-
* @param string $category
|
49 |
-
*
|
50 |
-
* @return array of add-ons.
|
51 |
*/
|
52 |
-
|
53 |
-
$raw_add_ons = wp_remote_get(
|
54 |
-
add_query_arg( array( array( 'category' => $category ) ), self::WPJM_COM_PRODUCTS_API_BASE_URL . '/search' )
|
55 |
-
);
|
56 |
-
if ( ! is_wp_error( $raw_add_ons ) ) {
|
57 |
-
$add_ons = json_decode( wp_remote_retrieve_body( $raw_add_ons ) )->products;
|
58 |
-
}
|
59 |
-
return $add_ons;
|
60 |
-
}
|
61 |
|
62 |
-
|
63 |
-
* Get categories for the add-ons screen
|
64 |
-
*
|
65 |
-
* @since 1.30.0
|
66 |
-
*
|
67 |
-
* @return array of objects.
|
68 |
-
*/
|
69 |
-
private function get_categories() {
|
70 |
-
$add_on_categories = get_transient( 'jm_wpjmcom_add_on_categories' );
|
71 |
-
if ( false === ( $add_on_categories ) ) {
|
72 |
-
$raw_categories = wp_safe_remote_get( self::WPJM_COM_PRODUCTS_API_BASE_URL . '/categories' );
|
73 |
-
if ( ! is_wp_error( $raw_categories ) ) {
|
74 |
-
$add_on_categories = json_decode( wp_remote_retrieve_body( $raw_categories ) );
|
75 |
-
if ( $add_on_categories ) {
|
76 |
-
set_transient( 'jm_wpjmcom_add_on_categories', $add_on_categories, WEEK_IN_SECONDS );
|
77 |
-
}
|
78 |
-
}
|
79 |
-
}
|
80 |
-
return apply_filters( 'job_manager_add_on_categories', $add_on_categories );
|
81 |
-
}
|
82 |
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
*/
|
90 |
-
private function get_messages() {
|
91 |
-
$add_on_messages = get_transient( 'jm_wpjmcom_add_on_messages' );
|
92 |
-
if ( false === ( $add_on_messages ) ) {
|
93 |
-
$raw_messages = wp_safe_remote_get(
|
94 |
-
add_query_arg(
|
95 |
-
array(
|
96 |
-
'version' => JOB_MANAGER_VERSION,
|
97 |
-
'lang' => get_locale(),
|
98 |
-
), self::WPJM_COM_PRODUCTS_API_BASE_URL . '/messages'
|
99 |
)
|
100 |
);
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
}
|
106 |
}
|
107 |
}
|
108 |
-
return apply_filters( 'job_manager_add_on_messages', $add_on_messages );
|
109 |
-
}
|
110 |
|
111 |
-
/**
|
112 |
-
* Handles output of the reports page in admin.
|
113 |
-
*/
|
114 |
-
public function output() {
|
115 |
?>
|
116 |
-
<div class="wrap wp_job_manager
|
117 |
-
<
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
}
|
123 |
-
?>
|
124 |
-
"><?php esc_html_e( 'WP Job Manager Add-ons', 'wp-job-manager' ); ?></a>
|
125 |
-
<?php if ( current_user_can( 'update_plugins' ) ) : ?>
|
126 |
-
<a href="<?php echo esc_url( admin_url( 'edit.php?post_type=job_listing&page=job-manager-addons§ion=helper' ) ); ?>" class="nav-tab
|
127 |
-
<?php
|
128 |
-
if ( isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) {
|
129 |
-
echo ' nav-tab-active'; }
|
130 |
-
?>
|
131 |
-
"><?php esc_html_e( 'Licenses', 'wp-job-manager' ); ?></a>
|
132 |
-
<?php endif; ?>
|
133 |
-
</nav>
|
134 |
-
<?php
|
135 |
-
if ( isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) {
|
136 |
-
do_action( 'job_manager_helper_output' );
|
137 |
-
} else {
|
138 |
-
$category = isset( $_GET['category'] ) ? sanitize_text_field( $_GET['category'] ) : null;
|
139 |
-
$messages = $this->get_messages();
|
140 |
-
$categories = $this->get_categories();
|
141 |
-
$add_ons = $this->get_add_ons( $category );
|
142 |
-
include_once dirname( __FILE__ ) . '/views/html-admin-page-addons.php';
|
143 |
-
}
|
144 |
-
?>
|
145 |
</div>
|
146 |
<?php
|
147 |
}
|
148 |
}
|
149 |
|
|
|
|
|
150 |
return WP_Job_Manager_Addons::instance();
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Addons Page
|
|
|
|
|
4 |
*/
|
5 |
|
6 |
+
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
7 |
+
|
8 |
+
if ( ! class_exists( 'WP_Job_Manager_Addons' ) ) :
|
9 |
|
10 |
/**
|
11 |
* Handles the admin add-ons page.
|
14 |
* @since 1.1.0
|
15 |
*/
|
16 |
class WP_Job_Manager_Addons {
|
|
|
17 |
|
18 |
/**
|
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 |
*/
|
38 |
}
|
39 |
|
40 |
/**
|
41 |
+
* Handles output of the reports page in admin.
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
*/
|
43 |
+
public function output() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
+
if ( false === ( $addons = get_transient( 'wp_job_manager_addons_html' ) ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
|
47 |
+
$raw_addons = wp_remote_get(
|
48 |
+
'https://wpjobmanager.com/add-ons/',
|
49 |
+
array(
|
50 |
+
'timeout' => 10,
|
51 |
+
'redirection' => 5,
|
52 |
+
'sslverify' => false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
)
|
54 |
);
|
55 |
+
|
56 |
+
if ( ! is_wp_error( $raw_addons ) ) {
|
57 |
+
|
58 |
+
$raw_addons = wp_remote_retrieve_body( $raw_addons );
|
59 |
+
|
60 |
+
// Get Products
|
61 |
+
$dom = new DOMDocument();
|
62 |
+
libxml_use_internal_errors(true);
|
63 |
+
$dom->loadHTML( $raw_addons );
|
64 |
+
|
65 |
+
$xpath = new DOMXPath( $dom );
|
66 |
+
$tags = $xpath->query('//ul[@class="products"]');
|
67 |
+
foreach ( $tags as $tag ) {
|
68 |
+
$addons = $tag->ownerDocument->saveXML( $tag );
|
69 |
+
break;
|
70 |
+
}
|
71 |
+
|
72 |
+
$addons = wp_kses_post( $addons );
|
73 |
+
|
74 |
+
if ( $addons ) {
|
75 |
+
set_transient( 'wp_job_manager_addons_html', $addons, 60*60*24*7 ); // Cached for a week
|
76 |
}
|
77 |
}
|
78 |
}
|
|
|
|
|
79 |
|
|
|
|
|
|
|
|
|
80 |
?>
|
81 |
+
<div class="wrap wp_job_manager wp_job_manager_addons_wrap">
|
82 |
+
<h2><?php _e( 'WP Job Manager Add-ons', 'wp-job-manager' ); ?></h2>
|
83 |
+
|
84 |
+
<div id="job-manager-addons-banner" class="notice updated below-h2"><strong><?php _e( 'Do you need multiple add-ons?', 'wp-job-manager' ); ?></strong> <a href="https://wpjobmanager.com/add-ons/bundle/" class="button"><?php _e( 'Check out the core add-on bundle →', 'wp-job-manager' ); ?></a></div>
|
85 |
+
|
86 |
+
<?php echo $addons; ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
</div>
|
88 |
<?php
|
89 |
}
|
90 |
}
|
91 |
|
92 |
+
endif;
|
93 |
+
|
94 |
return WP_Job_Manager_Addons::instance();
|
includes/admin/class-wp-job-manager-admin.php
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
if ( ! defined( 'ABSPATH' ) )
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
|
7 |
/**
|
8 |
* Handles front admin page for WP Job Manager.
|
@@ -16,14 +14,14 @@ class WP_Job_Manager_Admin {
|
|
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 |
*/
|
@@ -38,108 +36,37 @@ class WP_Job_Manager_Admin {
|
|
38 |
* Constructor.
|
39 |
*/
|
40 |
public function __construct() {
|
41 |
-
|
42 |
-
|
43 |
-
include_once
|
44 |
-
|
45 |
-
include_once dirname( __FILE__ ) . '/class-wp-job-manager-cpt-legacy.php';
|
46 |
-
WP_Job_Manager_CPT_Legacy::instance();
|
47 |
-
} else {
|
48 |
-
WP_Job_Manager_CPT::instance();
|
49 |
-
}
|
50 |
-
include_once dirname( __FILE__ ) . '/class-wp-job-manager-settings.php';
|
51 |
-
include_once dirname( __FILE__ ) . '/class-wp-job-manager-writepanels.php';
|
52 |
-
include_once dirname( __FILE__ ) . '/class-wp-job-manager-setup.php';
|
53 |
|
54 |
$this->settings_page = WP_Job_Manager_Settings::instance();
|
55 |
|
56 |
-
add_action( 'admin_init', array( $this, 'admin_init' ) );
|
57 |
-
add_action( 'current_screen', array( $this, 'conditional_includes' ) );
|
58 |
add_action( 'admin_menu', array( $this, 'admin_menu' ), 12 );
|
59 |
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
|
60 |
}
|
61 |
|
62 |
-
/**
|
63 |
-
* Set up actions during admin initialization.
|
64 |
-
*/
|
65 |
-
public function admin_init() {
|
66 |
-
global $wp_version;
|
67 |
-
|
68 |
-
include_once dirname( __FILE__ ) . '/class-wp-job-manager-taxonomy-meta.php';
|
69 |
-
|
70 |
-
if ( version_compare( $wp_version, JOB_MANAGER_MINIMUM_WP_VERSION, '<' ) ) {
|
71 |
-
add_action( 'admin_notices', array( $this, 'wp_version_admin_notice' ) );
|
72 |
-
add_filter( 'plugin_action_links_' . JOB_MANAGER_PLUGIN_BASENAME, array( $this, 'wp_version_plugin_action_notice' ) );
|
73 |
-
}
|
74 |
-
}
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Display notice if WordPress core is out-of-date in admin notice section.
|
78 |
-
*/
|
79 |
-
public function wp_version_admin_notice() {
|
80 |
-
// We only want to show the notices on the plugins page and WPJM admin pages.
|
81 |
-
$screen = get_current_screen();
|
82 |
-
$valid_screens = array( 'plugins', 'edit-job_listing', 'job_listing_page_job-manager-settings', 'edit-job_listing_type', 'edit-job_listing_category', 'job_listing' );
|
83 |
-
if ( null === $screen || ! in_array( $screen->id, $valid_screens, true ) ) {
|
84 |
-
return;
|
85 |
-
}
|
86 |
-
|
87 |
-
echo '<div class="error">';
|
88 |
-
// translators: %s is the URL for the page where users can go to update WordPress.
|
89 |
-
echo '<p>' . wp_kses_post( sprintf( __( '<strong>WP Job Manager</strong> requires a more recent version of WordPress. <a href="%s">Please update WordPresse</a> to avoid issues.', 'wp-job-manager' ), esc_url( self_admin_url( 'update-core.php' ) ) ) ) . '</p>';
|
90 |
-
echo '</div>';
|
91 |
-
}
|
92 |
-
|
93 |
-
/**
|
94 |
-
* Add admin notice when WP upgrade is required.
|
95 |
-
*
|
96 |
-
* @param array $actions
|
97 |
-
* @return array
|
98 |
-
*/
|
99 |
-
public function wp_version_plugin_action_notice( $actions ) {
|
100 |
-
// translators: Placeholder (%s) is the URL where users can go to update WordPress.
|
101 |
-
$actions[] = wp_kses_post( sprintf( __( '<a href="%s" style="color: red">WordPress Update Required</a>', 'wp-job-manager' ), esc_url( self_admin_url( 'update-core.php' ) ) ) );
|
102 |
-
return $actions;
|
103 |
-
}
|
104 |
-
|
105 |
-
/**
|
106 |
-
* Include admin files conditionally.
|
107 |
-
*/
|
108 |
-
public function conditional_includes() {
|
109 |
-
$screen = get_current_screen();
|
110 |
-
if ( ! $screen ) {
|
111 |
-
return;
|
112 |
-
}
|
113 |
-
switch ( $screen->id ) {
|
114 |
-
case 'options-permalink':
|
115 |
-
include 'class-wp-job-manager-permalink-settings.php';
|
116 |
-
break;
|
117 |
-
}
|
118 |
-
}
|
119 |
-
|
120 |
/**
|
121 |
* Enqueues CSS and JS assets.
|
122 |
*/
|
123 |
public function admin_enqueue_scripts() {
|
|
|
|
|
124 |
$screen = get_current_screen();
|
125 |
|
126 |
-
if ( in_array( $screen->id, apply_filters( 'job_manager_admin_screen_ids', array( 'edit-job_listing', '
|
127 |
-
|
|
|
|
|
128 |
wp_enqueue_style( 'job_manager_admin_css', JOB_MANAGER_PLUGIN_URL . '/assets/css/admin.css', array(), JOB_MANAGER_VERSION );
|
129 |
-
wp_register_script( 'jquery-tiptip', JOB_MANAGER_PLUGIN_URL
|
130 |
-
wp_enqueue_script( '
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
'job_manager_datepicker',
|
137 |
-
array(
|
138 |
-
/* translators: jQuery date format, see http://api.jqueryui.com/datepicker/#utility-formatDate */
|
139 |
-
'date_format' => _x( 'yy-mm-dd', 'Date format for jQuery datepicker.', 'wp-job-manager' ),
|
140 |
-
)
|
141 |
-
);
|
142 |
-
}
|
143 |
}
|
144 |
|
145 |
wp_enqueue_style( 'job_manager_admin_menu_css', JOB_MANAGER_PLUGIN_URL . '/assets/css/menu.css', array(), JOB_MANAGER_VERSION );
|
@@ -151,16 +78,15 @@ class WP_Job_Manager_Admin {
|
|
151 |
public function admin_menu() {
|
152 |
add_submenu_page( 'edit.php?post_type=job_listing', __( 'Settings', 'wp-job-manager' ), __( 'Settings', 'wp-job-manager' ), 'manage_options', 'job-manager-settings', array( $this->settings_page, 'output' ) );
|
153 |
|
154 |
-
if (
|
155 |
-
add_submenu_page(
|
156 |
-
}
|
157 |
}
|
158 |
|
159 |
/**
|
160 |
* Displays addons page.
|
161 |
*/
|
162 |
public function addons_page() {
|
163 |
-
$addons = include 'class-wp-job-manager-addons.php';
|
164 |
$addons->output();
|
165 |
}
|
166 |
}
|
1 |
<?php
|
2 |
|
3 |
+
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
4 |
|
5 |
/**
|
6 |
* Handles front admin page for WP Job Manager.
|
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 |
* 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 |
*/
|
53 |
public function admin_enqueue_scripts() {
|
54 |
+
global $wp_scripts;
|
55 |
+
|
56 |
$screen = get_current_screen();
|
57 |
|
58 |
+
if ( in_array( $screen->id, apply_filters( 'job_manager_admin_screen_ids', array( 'edit-job_listing', 'job_listing', 'job_listing_page_job-manager-settings', 'job_listing_page_job-manager-addons' ) ) ) ) {
|
59 |
+
$jquery_version = isset( $wp_scripts->registered['jquery-ui-core']->ver ) ? $wp_scripts->registered['jquery-ui-core']->ver : '1.9.2';
|
60 |
+
|
61 |
+
wp_enqueue_style( 'jquery-ui-style', '//code.jquery.com/ui/' . $jquery_version . '/themes/smoothness/jquery-ui.css', array(), $jquery_version );
|
62 |
wp_enqueue_style( 'job_manager_admin_css', JOB_MANAGER_PLUGIN_URL . '/assets/css/admin.css', array(), JOB_MANAGER_VERSION );
|
63 |
+
wp_register_script( 'jquery-tiptip', JOB_MANAGER_PLUGIN_URL. '/assets/js/jquery-tiptip/jquery.tipTip.min.js', array( 'jquery' ), JOB_MANAGER_VERSION, true );
|
64 |
+
wp_enqueue_script( 'job_manager_admin_js', JOB_MANAGER_PLUGIN_URL. '/assets/js/admin.min.js', array( 'jquery', 'jquery-tiptip', 'jquery-ui-datepicker' ), JOB_MANAGER_VERSION, true );
|
65 |
+
|
66 |
+
wp_localize_script( 'job_manager_admin_js', 'job_manager_admin', array(
|
67 |
+
/* translators: jQuery date format, see http://api.jqueryui.com/datepicker/#utility-formatDate */
|
68 |
+
'date_format' => _x( 'yy-mm-dd', 'Date format for jQuery datepicker.', 'wp-job-manager' )
|
69 |
+
) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
}
|
71 |
|
72 |
wp_enqueue_style( 'job_manager_admin_menu_css', JOB_MANAGER_PLUGIN_URL . '/assets/css/menu.css', array(), JOB_MANAGER_VERSION );
|
78 |
public function admin_menu() {
|
79 |
add_submenu_page( 'edit.php?post_type=job_listing', __( 'Settings', 'wp-job-manager' ), __( 'Settings', 'wp-job-manager' ), 'manage_options', 'job-manager-settings', array( $this->settings_page, 'output' ) );
|
80 |
|
81 |
+
if ( apply_filters( 'job_manager_show_addons_page', true ) )
|
82 |
+
add_submenu_page( 'edit.php?post_type=job_listing', __( 'WP Job Manager Add-ons', 'wp-job-manager' ), __( 'Add-ons', 'wp-job-manager' ) , 'manage_options', 'job-manager-addons', array( $this, 'addons_page' ) );
|
|
|
83 |
}
|
84 |
|
85 |
/**
|
86 |
* Displays addons page.
|
87 |
*/
|
88 |
public function addons_page() {
|
89 |
+
$addons = include( 'class-wp-job-manager-addons.php' );
|
90 |
$addons->output();
|
91 |
}
|
92 |
}
|
includes/admin/class-wp-job-manager-cpt-legacy.php
DELETED
@@ -1,91 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Handles legacy actions and filters specific to the custom post type for Job Listings.
|
9 |
-
*
|
10 |
-
* @package wp-job-manager
|
11 |
-
* @since 1.27.0
|
12 |
-
*/
|
13 |
-
class WP_Job_Manager_CPT_Legacy extends WP_Job_Manager_CPT {
|
14 |
-
/**
|
15 |
-
* The single instance of the class.
|
16 |
-
*
|
17 |
-
* @var self
|
18 |
-
* @since 1.27.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.27.0
|
26 |
-
* @static
|
27 |
-
* @return self Main instance.
|
28 |
-
*/
|
29 |
-
public static function instance() {
|
30 |
-
if ( is_null( self::$_instance ) ) {
|
31 |
-
self::$_instance = new self();
|
32 |
-
}
|
33 |
-
|
34 |
-
return self::$_instance;
|
35 |
-
}
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Constructor.
|
39 |
-
*/
|
40 |
-
public function __construct() {
|
41 |
-
parent::__construct();
|
42 |
-
add_action( 'admin_footer-edit.php', array( $this, 'add_bulk_actions_legacy' ) );
|
43 |
-
add_action( 'load-edit.php', array( $this, 'do_bulk_actions_legacy' ) );
|
44 |
-
remove_action( 'bulk_actions-edit-job_listing', array( $this, 'add_bulk_actions' ) );
|
45 |
-
}
|
46 |
-
|
47 |
-
/**
|
48 |
-
* Adds bulk actions to drop downs on Job Listing admin page.
|
49 |
-
*/
|
50 |
-
public function add_bulk_actions_legacy() {
|
51 |
-
global $post_type, $wp_post_types;
|
52 |
-
|
53 |
-
$bulk_actions = array();
|
54 |
-
foreach ( $this->get_bulk_actions() as $key => $bulk_action ) {
|
55 |
-
$bulk_actions[] = array(
|
56 |
-
'key' => $key,
|
57 |
-
'label' => sprintf( $bulk_action['label'], $wp_post_types['job_listing']->labels->name ),
|
58 |
-
);
|
59 |
-
}
|
60 |
-
|
61 |
-
if ( 'job_listing' === $post_type ) {
|
62 |
-
?>
|
63 |
-
<script type="text/javascript">
|
64 |
-
jQuery(document).ready(function() {
|
65 |
-
var actions = <?php echo wp_json_encode( $bulk_actions ); ?>;
|
66 |
-
actions.forEach(function(el){
|
67 |
-
jQuery( '<option>').val( el.key ).text(el.label).appendTo("select[name='action']");
|
68 |
-
jQuery( '<option>').val( el.key ).text(el.label).appendTo("select[name='action2']");
|
69 |
-
});
|
70 |
-
});
|
71 |
-
</script>
|
72 |
-
<?php
|
73 |
-
}
|
74 |
-
}
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Performs bulk actions on Job Listing admin page.
|
78 |
-
*/
|
79 |
-
public function do_bulk_actions_legacy() {
|
80 |
-
$wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
|
81 |
-
$action = $wp_list_table->current_action();
|
82 |
-
$actions_handled = $this->get_bulk_actions();
|
83 |
-
if ( isset( $actions_handled[ $action ] ) && isset( $actions_handled[ $action ]['handler'] ) ) {
|
84 |
-
check_admin_referer( 'bulk-posts' );
|
85 |
-
$post_ids = array_map( 'absint', array_filter( (array) $_GET['post'] ) );
|
86 |
-
if ( ! empty( $post_ids ) ) {
|
87 |
-
$this->do_bulk_actions( admin_url( 'edit.php?post_type=job_listing' ), $action, $post_ids );
|
88 |
-
}
|
89 |
-
}
|
90 |
-
}
|
91 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/admin/class-wp-job-manager-cpt.php
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
if ( ! defined( 'ABSPATH' ) )
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
|
7 |
/**
|
8 |
* Handles actions and filters specific to the custom post type for Job Listings.
|
@@ -16,14 +14,14 @@ class WP_Job_Manager_CPT {
|
|
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 |
*/
|
@@ -46,191 +44,94 @@ class WP_Job_Manager_CPT {
|
|
46 |
add_filter( 'manage_edit-job_listing_sortable_columns', array( $this, 'sortable_columns' ) );
|
47 |
add_filter( 'request', array( $this, 'sort_columns' ) );
|
48 |
add_action( 'parse_query', array( $this, 'search_meta' ) );
|
49 |
-
add_action( 'parse_query', array( $this, 'filter_meta' ) );
|
50 |
add_filter( 'get_search_query', array( $this, 'search_meta_label' ) );
|
51 |
add_filter( 'post_updated_messages', array( $this, 'post_updated_messages' ) );
|
52 |
-
add_action( '
|
53 |
-
add_action( '
|
54 |
add_action( 'admin_init', array( $this, 'approve_job' ) );
|
55 |
-
add_action( 'admin_notices', array( $this, '
|
56 |
-
add_action( '
|
57 |
|
58 |
if ( get_option( 'job_manager_enable_categories' ) ) {
|
59 |
-
add_action(
|
60 |
}
|
61 |
-
add_action( 'restrict_manage_posts', array( $this, 'jobs_meta_filters' ) );
|
62 |
|
63 |
foreach ( array( 'post', 'post-new' ) as $hook ) {
|
64 |
-
add_action( "admin_footer-{$hook}.php", array( $this,
|
65 |
}
|
66 |
}
|
67 |
|
68 |
-
/**
|
69 |
-
* Returns the list of bulk actions that can be performed on job listings.
|
70 |
-
*
|
71 |
-
* @return array
|
72 |
-
*/
|
73 |
-
public function get_bulk_actions() {
|
74 |
-
$actions_handled = array();
|
75 |
-
$actions_handled['approve_jobs'] = array(
|
76 |
-
// translators: Placeholder (%s) is the plural name of the job listings post type.
|
77 |
-
'label' => __( 'Approve %s', 'wp-job-manager' ),
|
78 |
-
// translators: Placeholder (%s) is the plural name of the job listings post type.
|
79 |
-
'notice' => __( '%s approved', 'wp-job-manager' ),
|
80 |
-
'handler' => array( $this, 'bulk_action_handle_approve_job' ),
|
81 |
-
);
|
82 |
-
$actions_handled['expire_jobs'] = array(
|
83 |
-
// translators: Placeholder (%s) is the plural name of the job listings post type.
|
84 |
-
'label' => __( 'Expire %s', 'wp-job-manager' ),
|
85 |
-
// translators: Placeholder (%s) is the plural name of the job listings post type.
|
86 |
-
'notice' => __( '%s expired', 'wp-job-manager' ),
|
87 |
-
'handler' => array( $this, 'bulk_action_handle_expire_job' ),
|
88 |
-
);
|
89 |
-
$actions_handled['mark_jobs_filled'] = array(
|
90 |
-
// translators: Placeholder (%s) is the plural name of the job listings post type.
|
91 |
-
'label' => __( 'Mark %s Filled', 'wp-job-manager' ),
|
92 |
-
// translators: Placeholder (%s) is the plural name of the job listings post type.
|
93 |
-
'notice' => __( '%s marked as filled', 'wp-job-manager' ),
|
94 |
-
'handler' => array( $this, 'bulk_action_handle_mark_job_filled' ),
|
95 |
-
);
|
96 |
-
$actions_handled['mark_jobs_not_filled'] = array(
|
97 |
-
// translators: Placeholder (%s) is the plural name of the job listings post type.
|
98 |
-
'label' => __( 'Mark %s Not Filled', 'wp-job-manager' ),
|
99 |
-
// translators: Placeholder (%s) is the plural name of the job listings post type.
|
100 |
-
'notice' => __( '%s marked as not filled', 'wp-job-manager' ),
|
101 |
-
'handler' => array( $this, 'bulk_action_handle_mark_job_not_filled' ),
|
102 |
-
);
|
103 |
-
|
104 |
-
/**
|
105 |
-
* Filters the bulk actions that can be applied to job listings.
|
106 |
-
*
|
107 |
-
* @since 1.27.0
|
108 |
-
*
|
109 |
-
* @param array $actions_handled {
|
110 |
-
* Bulk actions that can be handled, indexed by a unique key name (approve_jobs, expire_jobs, etc). Handlers
|
111 |
-
* are responsible for checking abilities (`current_user_can( 'manage_job_listings', $post_id )`) before
|
112 |
-
* performing action.
|
113 |
-
*
|
114 |
-
* @type string $label Label for the bulk actions dropdown. Passed through sprintf with label name of job listing post type.
|
115 |
-
* @type string $notice Success notice shown after performing the action. Passed through sprintf with title(s) of affected job listings.
|
116 |
-
* @type callback $handler Callable handler for performing action. Passed one argument (int $post_id) and should return true on success and false on failure.
|
117 |
-
* }
|
118 |
-
*/
|
119 |
-
return apply_filters( 'wpjm_job_listing_bulk_actions', $actions_handled );
|
120 |
-
}
|
121 |
-
|
122 |
/**
|
123 |
* Adds bulk actions to drop downs on Job Listing admin page.
|
124 |
-
*
|
125 |
-
* @param array $bulk_actions
|
126 |
-
* @return array
|
127 |
*/
|
128 |
-
public function add_bulk_actions(
|
129 |
-
global $wp_post_types
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
}
|
136 |
-
return $bulk_actions;
|
137 |
}
|
138 |
|
139 |
/**
|
140 |
* Performs bulk actions on Job Listing admin page.
|
141 |
-
*
|
142 |
-
* @since 1.27.0
|
143 |
-
*
|
144 |
-
* @param string $redirect_url The redirect URL.
|
145 |
-
* @param string $action The action being taken.
|
146 |
-
* @param array $post_ids The posts to take the action on.
|
147 |
*/
|
148 |
-
public function do_bulk_actions(
|
149 |
-
$
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
}
|
158 |
-
}
|
159 |
-
wp_redirect( add_query_arg( 'handled_jobs', $handled_jobs, add_query_arg( 'action_performed', $action, $redirect_url ) ) );
|
160 |
-
exit;
|
161 |
-
}
|
162 |
-
}
|
163 |
-
}
|
164 |
-
|
165 |
-
/**
|
166 |
-
* Performs bulk action to approve a single job listing.
|
167 |
-
*
|
168 |
-
* @param int $post_id Post ID.
|
169 |
-
*
|
170 |
-
* @return bool
|
171 |
-
*/
|
172 |
-
public function bulk_action_handle_approve_job( $post_id ) {
|
173 |
-
$job_data = array(
|
174 |
-
'ID' => $post_id,
|
175 |
-
'post_status' => 'publish',
|
176 |
-
);
|
177 |
-
if ( in_array( get_post_status( $post_id ), array( 'pending', 'pending_payment' ), true )
|
178 |
-
&& current_user_can( 'publish_post', $post_id )
|
179 |
-
&& wp_update_post( $job_data )
|
180 |
-
) {
|
181 |
-
return true;
|
182 |
-
}
|
183 |
-
return false;
|
184 |
-
}
|
185 |
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
* @param int $post_id Post ID.
|
209 |
-
*
|
210 |
-
* @return bool
|
211 |
-
*/
|
212 |
-
public function bulk_action_handle_mark_job_filled( $post_id ) {
|
213 |
-
if ( current_user_can( 'manage_job_listings', $post_id )
|
214 |
-
&& update_post_meta( $post_id, '_filled', 1 )
|
215 |
-
) {
|
216 |
-
return true;
|
217 |
}
|
218 |
-
return false;
|
219 |
-
}
|
220 |
|
221 |
-
|
222 |
-
* Performs bulk action to mark a single job listing as not filled.
|
223 |
-
*
|
224 |
-
* @param int $post_id Post ID.
|
225 |
-
* @return bool
|
226 |
-
*/
|
227 |
-
public function bulk_action_handle_mark_job_not_filled( $post_id ) {
|
228 |
-
if ( current_user_can( 'manage_job_listings', $post_id )
|
229 |
-
&& update_post_meta( $post_id, '_filled', 0 )
|
230 |
-
) {
|
231 |
-
return true;
|
232 |
-
}
|
233 |
-
return false;
|
234 |
}
|
235 |
|
236 |
/**
|
@@ -238,43 +139,53 @@ class WP_Job_Manager_CPT {
|
|
238 |
*/
|
239 |
public function approve_job() {
|
240 |
if ( ! empty( $_GET['approve_job'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'approve_job' ) && current_user_can( 'publish_post', $_GET['approve_job'] ) ) {
|
241 |
-
$post_id
|
242 |
$job_data = array(
|
243 |
'ID' => $post_id,
|
244 |
-
'post_status' => 'publish'
|
245 |
);
|
246 |
wp_update_post( $job_data );
|
247 |
-
wp_redirect( remove_query_arg( 'approve_job', add_query_arg( '
|
248 |
exit;
|
249 |
}
|
250 |
}
|
251 |
|
252 |
/**
|
253 |
-
* Shows a notice if we did a bulk action.
|
254 |
*/
|
255 |
-
public function
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
276 |
} else {
|
277 |
-
echo '<div class="updated"><p>' .
|
278 |
}
|
279 |
}
|
280 |
}
|
@@ -285,114 +196,32 @@ class WP_Job_Manager_CPT {
|
|
285 |
public function jobs_by_category() {
|
286 |
global $typenow, $wp_query;
|
287 |
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
|
292 |
-
|
293 |
|
294 |
$r = array();
|
295 |
-
$r['taxonomy'] = 'job_listing_category';
|
296 |
$r['pad_counts'] = 1;
|
297 |
$r['hierarchical'] = 1;
|
298 |
$r['hide_empty'] = 0;
|
299 |
$r['show_count'] = 1;
|
300 |
$r['selected'] = ( isset( $wp_query->query['job_listing_category'] ) ) ? $wp_query->query['job_listing_category'] : '';
|
301 |
$r['menu_order'] = false;
|
302 |
-
$terms = get_terms( $r );
|
303 |
-
$walker = new WP_Job_Manager_Category_Walker
|
304 |
|
305 |
if ( ! $terms ) {
|
306 |
return;
|
307 |
}
|
308 |
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
}
|
315 |
-
|
316 |
-
/**
|
317 |
-
* Output dropdowns for filters based on post meta.
|
318 |
-
*
|
319 |
-
* @since 1.31.0
|
320 |
-
*/
|
321 |
-
public function jobs_meta_filters() {
|
322 |
-
global $typenow;
|
323 |
-
|
324 |
-
// Only add the filters for job_listings.
|
325 |
-
if ( 'job_listing' !== $typenow ) {
|
326 |
-
return;
|
327 |
-
}
|
328 |
-
|
329 |
-
// Filter by Filled.
|
330 |
-
$this->jobs_filter_dropdown(
|
331 |
-
'job_listing_filled',
|
332 |
-
array(
|
333 |
-
array(
|
334 |
-
'value' => '',
|
335 |
-
'text' => __( 'Select Filled', 'wp-job-manager' ),
|
336 |
-
),
|
337 |
-
array(
|
338 |
-
'value' => '1',
|
339 |
-
'text' => __( 'Filled', 'wp-job-manager' ),
|
340 |
-
),
|
341 |
-
array(
|
342 |
-
'value' => '0',
|
343 |
-
'text' => __( 'Not Filled', 'wp-job-manager' ),
|
344 |
-
),
|
345 |
-
)
|
346 |
-
);
|
347 |
-
|
348 |
-
// Filter by Featured.
|
349 |
-
$this->jobs_filter_dropdown(
|
350 |
-
'job_listing_featured',
|
351 |
-
array(
|
352 |
-
array(
|
353 |
-
'value' => '',
|
354 |
-
'text' => __( 'Select Featured', 'wp-job-manager' ),
|
355 |
-
),
|
356 |
-
array(
|
357 |
-
'value' => '1',
|
358 |
-
'text' => __( 'Featured', 'wp-job-manager' ),
|
359 |
-
),
|
360 |
-
array(
|
361 |
-
'value' => '0',
|
362 |
-
'text' => __( 'Not Featured', 'wp-job-manager' ),
|
363 |
-
),
|
364 |
-
)
|
365 |
-
);
|
366 |
-
}
|
367 |
-
|
368 |
-
/**
|
369 |
-
* Shows dropdown to filter by the given URL parameter. The dropdown will
|
370 |
-
* have three options: "Select $name", "$name", and "Not $name".
|
371 |
-
*
|
372 |
-
* The $options element should be an array of arrays, each with the
|
373 |
-
* attributes needed to create an <option> HTML element. The attributes are
|
374 |
-
* as follows:
|
375 |
-
*
|
376 |
-
* $options[i]['value'] The value for the <option> HTML element.
|
377 |
-
* $options[i]['text'] The text for the <option> HTML element.
|
378 |
-
*
|
379 |
-
* @since 1.31.0
|
380 |
-
*
|
381 |
-
* @param string $param The URL parameter.
|
382 |
-
* @param array $options The options for the dropdown. See the description above.
|
383 |
-
*/
|
384 |
-
private function jobs_filter_dropdown( $param, $options ) {
|
385 |
-
$selected = isset( $_GET[ $param ] ) ? $_GET[ $param ] : '';
|
386 |
-
|
387 |
-
echo '<select name="' . esc_attr( $param ) . '" id="dropdown_' . esc_attr( $param ) . '">';
|
388 |
-
|
389 |
-
foreach ( $options as $option ) {
|
390 |
-
echo '<option value="' . esc_attr( $option['value'] ) . '"'
|
391 |
-
. ( $selected === $option['value'] ? ' selected' : '' )
|
392 |
-
. '>' . esc_html( $option['text'] ) . '</option>';
|
393 |
-
}
|
394 |
-
echo '</select>';
|
395 |
|
|
|
396 |
}
|
397 |
|
398 |
/**
|
@@ -403,9 +232,8 @@ class WP_Job_Manager_CPT {
|
|
403 |
* @return string
|
404 |
*/
|
405 |
public function enter_title_here( $text, $post ) {
|
406 |
-
if (
|
407 |
-
return
|
408 |
-
}
|
409 |
return $text;
|
410 |
}
|
411 |
|
@@ -419,30 +247,18 @@ class WP_Job_Manager_CPT {
|
|
419 |
global $post, $post_ID, $wp_post_types;
|
420 |
|
421 |
$messages['job_listing'] = array(
|
422 |
-
0
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
7 => sprintf( esc_html__( '%s saved.', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name ),
|
435 |
-
// translators: %1$s is the singular name of the job listing post type; %2$s is the URL to preview the listing.
|
436 |
-
8 => sprintf( __( '%1$s submitted. <a target="_blank" href="%2$s">Preview</a>', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name, esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) ),
|
437 |
-
9 => sprintf(
|
438 |
-
// translators: %1$s is the singular name of the post type; %2$s is the date the post will be published; %3$s is the URL to preview the listing.
|
439 |
-
__( '%1$s scheduled for: <strong>%2$s</strong>. <a target="_blank" href="%3$s">Preview</a>', 'wp-job-manager' ),
|
440 |
-
$wp_post_types['job_listing']->labels->singular_name,
|
441 |
-
date_i18n( get_option( 'date_format' ) . ' @ ' . get_option( 'time_format' ), strtotime( $post->post_date ) ),
|
442 |
-
esc_url( get_permalink( $post_ID ) )
|
443 |
-
),
|
444 |
-
// translators: %1$s is the singular name of the job listing post type; %2$s is the URL to view the listing.
|
445 |
-
10 => sprintf( __( '%1$s draft updated. <a target="_blank" href="%2$s">Preview</a>', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name, esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) ),
|
446 |
);
|
447 |
|
448 |
return $messages;
|
@@ -461,23 +277,23 @@ class WP_Job_Manager_CPT {
|
|
461 |
|
462 |
unset( $columns['title'], $columns['date'], $columns['author'] );
|
463 |
|
464 |
-
$columns[
|
465 |
-
$columns[
|
466 |
-
$columns[
|
467 |
-
$columns['job_status'] = '<span class="tips" data-tip="' . __(
|
468 |
-
$columns[
|
469 |
-
$columns[
|
470 |
-
$columns[
|
471 |
-
$columns['featured_job'] = '<span class="tips" data-tip="' . __(
|
472 |
-
$columns['filled'] = '<span class="tips" data-tip="' . __(
|
473 |
-
$columns['job_actions'] = __(
|
474 |
|
475 |
if ( ! get_option( 'job_manager_enable_categories' ) ) {
|
476 |
-
unset( $columns[
|
477 |
}
|
478 |
|
479 |
if ( ! get_option( 'job_manager_enable_types' ) ) {
|
480 |
-
unset( $columns[
|
481 |
}
|
482 |
|
483 |
return $columns;
|
@@ -508,7 +324,7 @@ class WP_Job_Manager_CPT {
|
|
508 |
* @return array
|
509 |
*/
|
510 |
public function row_actions( $actions ) {
|
511 |
-
if ( 'job_listing'
|
512 |
return array();
|
513 |
}
|
514 |
return $actions;
|
@@ -523,19 +339,14 @@ class WP_Job_Manager_CPT {
|
|
523 |
global $post;
|
524 |
|
525 |
switch ( $column ) {
|
526 |
-
case
|
527 |
-
$
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
}
|
533 |
-
}
|
534 |
-
break;
|
535 |
-
case 'job_position':
|
536 |
echo '<div class="job_position">';
|
537 |
-
|
538 |
-
echo '<a href="' . esc_url( admin_url( 'post.php?post=' . $post->ID . '&action=edit' ) ) . '" class="tips job_title" data-tip="' . sprintf( esc_html__( 'ID: %d', 'wp-job-manager' ), intval( $post->ID ) ) . '">' . esc_html( wpjm_get_the_job_title() ) . '</a>';
|
539 |
|
540 |
echo '<div class="company">';
|
541 |
|
@@ -550,78 +361,63 @@ class WP_Job_Manager_CPT {
|
|
550 |
the_company_logo();
|
551 |
echo '</div>';
|
552 |
echo '<button type="button" class="toggle-row"><span class="screen-reader-text">Show more details</span></button>';
|
553 |
-
|
554 |
-
case
|
555 |
-
the_job_location(
|
556 |
-
|
557 |
-
case
|
558 |
-
$terms = get_the_term_list( $post->ID, $column, '', ', ', '' );
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
echo '✔';
|
575 |
-
} else {
|
576 |
echo '–';
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
echo ( empty( $post->post_author ) ? esc_html__( 'by a guest', 'wp-job-manager' ) : sprintf( esc_html__( 'by %s', 'wp-job-manager' ), '<a href="' . esc_url( add_query_arg( 'author', $post->post_author ) ) . '">' . esc_html( get_the_author() ) . '</a>' ) ) . '</span>';
|
583 |
-
break;
|
584 |
-
case 'job_expires':
|
585 |
-
if ( $post->_job_expires ) {
|
586 |
-
echo '<strong>' . esc_html( date_i18n( get_option( 'date_format' ), strtotime( $post->_job_expires ) ) ) . '</strong>';
|
587 |
-
} else {
|
588 |
-
echo '–';
|
589 |
-
}
|
590 |
-
break;
|
591 |
-
case 'job_status':
|
592 |
-
echo '<span data-tip="' . esc_attr( get_the_job_status( $post ) ) . '" class="tips status-' . esc_attr( $post->post_status ) . '">' . esc_html( get_the_job_status( $post ) ) . '</span>';
|
593 |
-
break;
|
594 |
-
case 'job_actions':
|
595 |
echo '<div class="actions">';
|
596 |
$admin_actions = apply_filters( 'post_row_actions', array(), $post );
|
597 |
|
598 |
-
if ( in_array( $post->post_status, array( 'pending', 'pending_payment' )
|
599 |
-
$admin_actions['approve']
|
600 |
-
'action'
|
601 |
-
'name'
|
602 |
-
'url'
|
603 |
);
|
604 |
}
|
605 |
-
if (
|
606 |
if ( current_user_can( 'read_post', $post->ID ) ) {
|
607 |
-
$admin_actions['view']
|
608 |
-
'action'
|
609 |
-
'name'
|
610 |
-
'url'
|
611 |
);
|
612 |
}
|
613 |
if ( current_user_can( 'edit_post', $post->ID ) ) {
|
614 |
-
$admin_actions['edit']
|
615 |
-
'action'
|
616 |
-
'name'
|
617 |
-
'url'
|
618 |
);
|
619 |
}
|
620 |
if ( current_user_can( 'delete_post', $post->ID ) ) {
|
621 |
$admin_actions['delete'] = array(
|
622 |
-
'action'
|
623 |
-
'name'
|
624 |
-
'url'
|
625 |
);
|
626 |
}
|
627 |
}
|
@@ -630,15 +426,15 @@ class WP_Job_Manager_CPT {
|
|
630 |
|
631 |
foreach ( $admin_actions as $action ) {
|
632 |
if ( is_array( $action ) ) {
|
633 |
-
printf( '<a class="button button-icon tips icon-%1$s" href="%2$s" data-tip="%3$s">%4$s</a>',
|
634 |
} else {
|
635 |
-
echo
|
636 |
}
|
637 |
}
|
638 |
|
639 |
echo '</div>';
|
640 |
|
641 |
-
|
642 |
}
|
643 |
}
|
644 |
|
@@ -653,7 +449,7 @@ class WP_Job_Manager_CPT {
|
|
653 |
'job_posted' => 'date',
|
654 |
'job_position' => 'title',
|
655 |
'job_location' => 'job_location',
|
656 |
-
'job_expires' => 'job_expires'
|
657 |
);
|
658 |
return wp_parse_args( $custom, $columns );
|
659 |
}
|
@@ -661,27 +457,21 @@ class WP_Job_Manager_CPT {
|
|
661 |
/**
|
662 |
* Sorts the admin listing of Job Listings by updating the main query in the request.
|
663 |
*
|
664 |
-
* @param mixed $vars
|
665 |
* @return array
|
666 |
*/
|
667 |
public function sort_columns( $vars ) {
|
668 |
if ( isset( $vars['orderby'] ) ) {
|
669 |
if ( 'job_expires' === $vars['orderby'] ) {
|
670 |
-
$vars = array_merge(
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
'orderby' => 'meta_value',
|
675 |
-
)
|
676 |
-
);
|
677 |
} elseif ( 'job_location' === $vars['orderby'] ) {
|
678 |
-
$vars = array_merge(
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
'orderby' => 'meta_value',
|
683 |
-
)
|
684 |
-
);
|
685 |
}
|
686 |
}
|
687 |
return $vars;
|
@@ -699,71 +489,29 @@ class WP_Job_Manager_CPT {
|
|
699 |
return;
|
700 |
}
|
701 |
|
702 |
-
$post_ids = array_unique(
|
703 |
-
|
704 |
-
$wpdb->
|
705 |
-
$wpdb->prepare(
|
706 |
-
"
|
707 |
SELECT posts.ID
|
708 |
FROM {$wpdb->posts} posts
|
709 |
INNER JOIN {$wpdb->postmeta} p1 ON posts.ID = p1.post_id
|
710 |
-
WHERE p1.meta_value LIKE
|
711 |
-
OR posts.post_title LIKE
|
712 |
-
OR posts.post_content LIKE
|
713 |
AND posts.post_type = 'job_listing'
|
714 |
",
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
);
|
723 |
|
724 |
-
// Adjust the query vars
|
725 |
unset( $wp->query_vars['s'] );
|
726 |
$wp->query_vars['job_listing_search'] = true;
|
727 |
-
$wp->query_vars['post__in']
|
728 |
-
}
|
729 |
-
|
730 |
-
/**
|
731 |
-
* Filters by meta fields.
|
732 |
-
*
|
733 |
-
* @param WP_Query $wp
|
734 |
-
*/
|
735 |
-
public function filter_meta( $wp ) {
|
736 |
-
global $pagenow;
|
737 |
-
|
738 |
-
if ( 'edit.php' !== $pagenow || empty( $wp->query_vars['post_type'] ) || 'job_listing' !== $wp->query_vars['post_type'] ) {
|
739 |
-
return;
|
740 |
-
}
|
741 |
-
|
742 |
-
$meta_query = $wp->get( 'meta_query' );
|
743 |
-
if ( ! is_array( $meta_query ) ) {
|
744 |
-
$meta_query = array();
|
745 |
-
}
|
746 |
-
|
747 |
-
// Filter on _filled meta.
|
748 |
-
if ( isset( $_GET['job_listing_filled'] ) && '' !== $_GET['job_listing_filled'] ) {
|
749 |
-
$meta_query[] = array(
|
750 |
-
'key' => '_filled',
|
751 |
-
'value' => $_GET['job_listing_filled'],
|
752 |
-
);
|
753 |
-
}
|
754 |
-
|
755 |
-
// Filter on _featured meta.
|
756 |
-
if ( isset( $_GET['job_listing_featured'] ) && '' !== $_GET['job_listing_featured'] ) {
|
757 |
-
$meta_query[] = array(
|
758 |
-
'key' => '_featured',
|
759 |
-
'value' => $_GET['job_listing_featured'],
|
760 |
-
);
|
761 |
-
}
|
762 |
-
|
763 |
-
// Set new meta query.
|
764 |
-
if ( ! empty( $meta_query ) ) {
|
765 |
-
$wp->set( 'meta_query', $meta_query );
|
766 |
-
}
|
767 |
}
|
768 |
|
769 |
/**
|
@@ -775,7 +523,7 @@ class WP_Job_Manager_CPT {
|
|
775 |
public function search_meta_label( $query ) {
|
776 |
global $pagenow, $typenow;
|
777 |
|
778 |
-
if ( 'edit.php' !== $pagenow || 'job_listing'
|
779 |
return $query;
|
780 |
}
|
781 |
|
@@ -788,47 +536,35 @@ class WP_Job_Manager_CPT {
|
|
788 |
public function extend_submitdiv_post_status() {
|
789 |
global $post, $post_type;
|
790 |
|
791 |
-
// Abort if we're on the wrong post type, but only if we got a restriction
|
792 |
if ( 'job_listing' !== $post_type ) {
|
793 |
return;
|
794 |
}
|
795 |
|
796 |
-
// Get all non-builtin post status and add them as <option
|
797 |
-
$options = '';
|
798 |
-
$display = '';
|
799 |
foreach ( get_job_listing_post_statuses() as $status => $name ) {
|
800 |
$selected = selected( $post->post_status, $status, false );
|
801 |
|
802 |
-
// If we one of our custom post status is selected, remember it
|
803 |
-
|
804 |
-
$display = $name;
|
805 |
-
}
|
806 |
|
807 |
-
// Build the options
|
808 |
-
$options .= "<option{$selected} value='{$status}'>
|
809 |
}
|
810 |
?>
|
811 |
<script type="text/javascript">
|
812 |
jQuery( document ).ready( function($) {
|
813 |
<?php if ( ! empty( $display ) ) : ?>
|
814 |
-
jQuery( '#post-status-display' ).html( <?php echo
|
815 |
<?php endif; ?>
|
816 |
|
817 |
var select = jQuery( '#post-status-select' ).find( 'select' );
|
818 |
-
jQuery( select ).html( <?php echo
|
819 |
} );
|
820 |
</script>
|
821 |
<?php
|
822 |
}
|
823 |
-
|
824 |
-
/**
|
825 |
-
* Removes job_listing from the list of post types that support "View Mode" option
|
826 |
-
*
|
827 |
-
* @param array $post_types Array of post types that support view mode.
|
828 |
-
* @return array Array of post types that support view mode, without job_listing post type.
|
829 |
-
*/
|
830 |
-
public function disable_view_mode( $post_types ) {
|
831 |
-
unset( $post_types['job_listing'] );
|
832 |
-
return $post_types;
|
833 |
-
}
|
834 |
}
|
|
|
|
1 |
<?php
|
2 |
|
3 |
+
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
4 |
|
5 |
/**
|
6 |
* Handles actions and filters specific to the custom post type for Job Listings.
|
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 |
*/
|
44 |
add_filter( 'manage_edit-job_listing_sortable_columns', array( $this, 'sortable_columns' ) );
|
45 |
add_filter( 'request', array( $this, 'sort_columns' ) );
|
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" ) );
|
57 |
}
|
|
|
58 |
|
59 |
foreach ( array( 'post', 'post-new' ) as $hook ) {
|
60 |
+
add_action( "admin_footer-{$hook}.php", array( $this,'extend_submitdiv_post_status' ) );
|
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 |
/**
|
139 |
*/
|
140 |
public function approve_job() {
|
141 |
if ( ! empty( $_GET['approve_job'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'approve_job' ) && current_user_can( 'publish_post', $_GET['approve_job'] ) ) {
|
142 |
+
$post_id = absint( $_GET['approve_job'] );
|
143 |
$job_data = array(
|
144 |
'ID' => $post_id,
|
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' ), '"' . implode( '", "', $titles ) . '"' ) . '</p></div>';
|
167 |
+
} else {
|
168 |
+
echo '<div class="updated"><p>' . sprintf( __( '%s approved', 'wp-job-manager' ), '"' . get_the_title( $approved_jobs ) . '"' ) . '</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' ), '"' . implode( '", "', $titles ) . '"' ) . '</p></div>';
|
187 |
} else {
|
188 |
+
echo '<div class="updated"><p>' . sprintf( __( '%s expired', 'wp-job-manager' ), '"' . get_the_title( $expired_jobs ) . '"' ) . '</p></div>';
|
189 |
}
|
190 |
}
|
191 |
}
|
196 |
public function jobs_by_category() {
|
197 |
global $typenow, $wp_query;
|
198 |
|
199 |
+
if ( $typenow != 'job_listing' || ! taxonomy_exists( 'job_listing_category' ) ) {
|
200 |
+
return;
|
201 |
+
}
|
202 |
|
203 |
+
include_once( JOB_MANAGER_PLUGIN_DIR . '/includes/class-wp-job-manager-category-walker.php' );
|
204 |
|
205 |
$r = array();
|
|
|
206 |
$r['pad_counts'] = 1;
|
207 |
$r['hierarchical'] = 1;
|
208 |
$r['hide_empty'] = 0;
|
209 |
$r['show_count'] = 1;
|
210 |
$r['selected'] = ( isset( $wp_query->query['job_listing_category'] ) ) ? $wp_query->query['job_listing_category'] : '';
|
211 |
$r['menu_order'] = false;
|
212 |
+
$terms = get_terms( 'job_listing_category', $r );
|
213 |
+
$walker = new WP_Job_Manager_Category_Walker;
|
214 |
|
215 |
if ( ! $terms ) {
|
216 |
return;
|
217 |
}
|
218 |
|
219 |
+
$output = "<select name='job_listing_category' id='dropdown_job_listing_category'>";
|
220 |
+
$output .= '<option value="" ' . selected( isset( $_GET['job_listing_category'] ) ? $_GET['job_listing_category'] : '', '', false ) . '>' . __( 'Select category', 'wp-job-manager' ) . '</option>';
|
221 |
+
$output .= $walker->walk( $terms, 0, $r );
|
222 |
+
$output .= "</select>";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
|
224 |
+
echo $output;
|
225 |
}
|
226 |
|
227 |
/**
|
232 |
* @return string
|
233 |
*/
|
234 |
public function enter_title_here( $text, $post ) {
|
235 |
+
if ( $post->post_type == 'job_listing' )
|
236 |
+
return __( 'Position', 'wp-job-manager' );
|
|
|
237 |
return $text;
|
238 |
}
|
239 |
|
247 |
global $post, $post_ID, $wp_post_types;
|
248 |
|
249 |
$messages['job_listing'] = array(
|
250 |
+
0 => '',
|
251 |
+
1 => sprintf( __( '%s updated. <a href="%s">View</a>', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name, esc_url( get_permalink( $post_ID ) ) ),
|
252 |
+
2 => __( 'Custom field updated.', 'wp-job-manager' ),
|
253 |
+
3 => __( 'Custom field deleted.', 'wp-job-manager' ),
|
254 |
+
4 => sprintf( __( '%s updated.', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name ),
|
255 |
+
5 => isset( $_GET['revision'] ) ? sprintf( __( '%s restored to revision from %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name, wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
256 |
+
6 => sprintf( __( '%s published. <a href="%s">View</a>', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name, esc_url( get_permalink( $post_ID ) ) ),
|
257 |
+
7 => sprintf( __( '%s saved.', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name ),
|
258 |
+
8 => sprintf( __( '%s submitted. <a target="_blank" href="%s">Preview</a>', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name, esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
|
259 |
+
9 => sprintf( __( '%s scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview</a>', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name,
|
260 |
+
date_i18n( __( 'M j, Y @ G:i', 'wp-job-manager' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post_ID ) ) ),
|
261 |
+
10 => sprintf( __( '%s draft updated. <a target="_blank" href="%s">Preview</a>', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name, esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) ),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
);
|
263 |
|
264 |
return $messages;
|
277 |
|
278 |
unset( $columns['title'], $columns['date'], $columns['author'] );
|
279 |
|
280 |
+
$columns["job_position"] = __( "Position", 'wp-job-manager' );
|
281 |
+
$columns["job_listing_type"] = __( "Type", 'wp-job-manager' );
|
282 |
+
$columns["job_location"] = __( "Location", 'wp-job-manager' );
|
283 |
+
$columns['job_status'] = '<span class="tips" data-tip="' . __( "Status", 'wp-job-manager' ) . '">' . __( "Status", 'wp-job-manager' ) . '</span>';
|
284 |
+
$columns["job_posted"] = __( "Posted", 'wp-job-manager' );
|
285 |
+
$columns["job_expires"] = __( "Expires", 'wp-job-manager' );
|
286 |
+
$columns["job_listing_category"] = __( "Categories", 'wp-job-manager' );
|
287 |
+
$columns['featured_job'] = '<span class="tips" data-tip="' . __( "Featured?", 'wp-job-manager' ) . '">' . __( "Featured?", 'wp-job-manager' ) . '</span>';
|
288 |
+
$columns['filled'] = '<span class="tips" data-tip="' . __( "Filled?", 'wp-job-manager' ) . '">' . __( "Filled?", 'wp-job-manager' ) . '</span>';
|
289 |
+
$columns['job_actions'] = __( "Actions", 'wp-job-manager' );
|
290 |
|
291 |
if ( ! get_option( 'job_manager_enable_categories' ) ) {
|
292 |
+
unset( $columns["job_listing_category"] );
|
293 |
}
|
294 |
|
295 |
if ( ! get_option( 'job_manager_enable_types' ) ) {
|
296 |
+
unset( $columns["job_listing_type"] );
|
297 |
}
|
298 |
|
299 |
return $columns;
|
324 |
* @return array
|
325 |
*/
|
326 |
public function row_actions( $actions ) {
|
327 |
+
if ( 'job_listing' == get_post_type() ) {
|
328 |
return array();
|
329 |
}
|
330 |
return $actions;
|
339 |
global $post;
|
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 |
|
361 |
the_company_logo();
|
362 |
echo '</div>';
|
363 |
echo '<button type="button" class="toggle-row"><span class="screen-reader-text">Show more details</span></button>';
|
364 |
+
break;
|
365 |
+
case "job_location" :
|
366 |
+
the_job_location( $post );
|
367 |
+
break;
|
368 |
+
case "job_listing_category" :
|
369 |
+
if ( ! $terms = get_the_term_list( $post->ID, $column, '', ', ', '' ) ) echo '<span class="na">–</span>'; else echo $terms;
|
370 |
+
break;
|
371 |
+
case "filled" :
|
372 |
+
if ( is_position_filled( $post ) ) echo '✔'; else echo '–';
|
373 |
+
break;
|
374 |
+
case "featured_job" :
|
375 |
+
if ( is_position_featured( $post ) ) echo '✔'; else echo '–';
|
376 |
+
break;
|
377 |
+
case "job_posted" :
|
378 |
+
echo '<strong>' . date_i18n( __( 'M j, Y', 'wp-job-manager' ), strtotime( $post->post_date ) ) . '</strong><span>';
|
379 |
+
echo ( empty( $post->post_author ) ? __( 'by a guest', 'wp-job-manager' ) : sprintf( __( 'by %s', 'wp-job-manager' ), '<a href="' . esc_url( add_query_arg( 'author', $post->post_author ) ) . '">' . get_the_author() . '</a>' ) ) . '</span>';
|
380 |
+
break;
|
381 |
+
case "job_expires" :
|
382 |
+
if ( $post->_job_expires )
|
383 |
+
echo '<strong>' . date_i18n( __( 'M j, Y', 'wp-job-manager' ), strtotime( $post->_job_expires ) ) . '</strong>';
|
384 |
+
else
|
|
|
|
|
385 |
echo '–';
|
386 |
+
break;
|
387 |
+
case "job_status" :
|
388 |
+
echo '<span data-tip="' . esc_attr( get_the_job_status( $post ) ) . '" class="tips status-' . esc_attr( $post->post_status ) . '">' . get_the_job_status( $post ) . '</span>';
|
389 |
+
break;
|
390 |
+
case "job_actions" :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
echo '<div class="actions">';
|
392 |
$admin_actions = apply_filters( 'post_row_actions', array(), $post );
|
393 |
|
394 |
+
if ( in_array( $post->post_status, array( 'pending', 'pending_payment' ) ) && current_user_can ( 'publish_post', $post->ID ) ) {
|
395 |
+
$admin_actions['approve'] = array(
|
396 |
+
'action' => 'approve',
|
397 |
+
'name' => __( 'Approve', 'wp-job-manager' ),
|
398 |
+
'url' => wp_nonce_url( add_query_arg( 'approve_job', $post->ID ), 'approve_job' )
|
399 |
);
|
400 |
}
|
401 |
+
if ( $post->post_status !== 'trash' ) {
|
402 |
if ( current_user_can( 'read_post', $post->ID ) ) {
|
403 |
+
$admin_actions['view'] = array(
|
404 |
+
'action' => 'view',
|
405 |
+
'name' => __( 'View', 'wp-job-manager' ),
|
406 |
+
'url' => get_permalink( $post->ID )
|
407 |
);
|
408 |
}
|
409 |
if ( current_user_can( 'edit_post', $post->ID ) ) {
|
410 |
+
$admin_actions['edit'] = array(
|
411 |
+
'action' => 'edit',
|
412 |
+
'name' => __( 'Edit', 'wp-job-manager' ),
|
413 |
+
'url' => get_edit_post_link( $post->ID )
|
414 |
);
|
415 |
}
|
416 |
if ( current_user_can( 'delete_post', $post->ID ) ) {
|
417 |
$admin_actions['delete'] = array(
|
418 |
+
'action' => 'delete',
|
419 |
+
'name' => __( 'Delete', 'wp-job-manager' ),
|
420 |
+
'url' => get_delete_post_link( $post->ID )
|
421 |
);
|
422 |
}
|
423 |
}
|
426 |
|
427 |
foreach ( $admin_actions as $action ) {
|
428 |
if ( is_array( $action ) ) {
|
429 |
+
printf( '<a class="button button-icon tips icon-%1$s" href="%2$s" data-tip="%3$s">%4$s</a>', $action['action'], esc_url( $action['url'] ), esc_attr( $action['name'] ), esc_html( $action['name'] ) );
|
430 |
} else {
|
431 |
+
echo str_replace( 'class="', 'class="button ', $action );
|
432 |
}
|
433 |
}
|
434 |
|
435 |
echo '</div>';
|
436 |
|
437 |
+
break;
|
438 |
}
|
439 |
}
|
440 |
|
449 |
'job_posted' => 'date',
|
450 |
'job_position' => 'title',
|
451 |
'job_location' => 'job_location',
|
452 |
+
'job_expires' => 'job_expires'
|
453 |
);
|
454 |
return wp_parse_args( $custom, $columns );
|
455 |
}
|
457 |
/**
|
458 |
* Sorts the admin listing of Job Listings by updating the main query in the request.
|
459 |
*
|
460 |
+
* @param mixed $vars
|
461 |
* @return array
|
462 |
*/
|
463 |
public function sort_columns( $vars ) {
|
464 |
if ( isset( $vars['orderby'] ) ) {
|
465 |
if ( 'job_expires' === $vars['orderby'] ) {
|
466 |
+
$vars = array_merge( $vars, array(
|
467 |
+
'meta_key' => '_job_expires',
|
468 |
+
'orderby' => 'meta_value'
|
469 |
+
) );
|
|
|
|
|
|
|
470 |
} elseif ( 'job_location' === $vars['orderby'] ) {
|
471 |
+
$vars = array_merge( $vars, array(
|
472 |
+
'meta_key' => '_job_location',
|
473 |
+
'orderby' => 'meta_value'
|
474 |
+
) );
|
|
|
|
|
|
|
475 |
}
|
476 |
}
|
477 |
return $vars;
|
489 |
return;
|
490 |
}
|
491 |
|
492 |
+
$post_ids = array_unique( array_merge(
|
493 |
+
$wpdb->get_col(
|
494 |
+
$wpdb->prepare( "
|
|
|
|
|
495 |
SELECT posts.ID
|
496 |
FROM {$wpdb->posts} posts
|
497 |
INNER JOIN {$wpdb->postmeta} p1 ON posts.ID = p1.post_id
|
498 |
+
WHERE p1.meta_value LIKE '%%%s%%'
|
499 |
+
OR posts.post_title LIKE '%%%s%%'
|
500 |
+
OR posts.post_content LIKE '%%%s%%'
|
501 |
AND posts.post_type = 'job_listing'
|
502 |
",
|
503 |
+
esc_sql( $wp->query_vars['s'] ),
|
504 |
+
esc_sql( $wp->query_vars['s'] ),
|
505 |
+
esc_sql( $wp->query_vars['s'] )
|
506 |
+
)
|
507 |
+
),
|
508 |
+
array( 0 )
|
509 |
+
) );
|
|
|
510 |
|
511 |
+
// Adjust the query vars
|
512 |
unset( $wp->query_vars['s'] );
|
513 |
$wp->query_vars['job_listing_search'] = true;
|
514 |
+
$wp->query_vars['post__in'] = $post_ids;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
515 |
}
|
516 |
|
517 |
/**
|
523 |
public function search_meta_label( $query ) {
|
524 |
global $pagenow, $typenow;
|
525 |
|
526 |
+
if ( 'edit.php' !== $pagenow || $typenow !== 'job_listing' || ! get_query_var( 'job_listing_search' ) ) {
|
527 |
return $query;
|
528 |
}
|
529 |
|
536 |
public function extend_submitdiv_post_status() {
|
537 |
global $post, $post_type;
|
538 |
|
539 |
+
// Abort if we're on the wrong post type, but only if we got a restriction
|
540 |
if ( 'job_listing' !== $post_type ) {
|
541 |
return;
|
542 |
}
|
543 |
|
544 |
+
// Get all non-builtin post status and add them as <option>
|
545 |
+
$options = $display = '';
|
|
|
546 |
foreach ( get_job_listing_post_statuses() as $status => $name ) {
|
547 |
$selected = selected( $post->post_status, $status, false );
|
548 |
|
549 |
+
// If we one of our custom post status is selected, remember it
|
550 |
+
$selected AND $display = $name;
|
|
|
|
|
551 |
|
552 |
+
// Build the options
|
553 |
+
$options .= "<option{$selected} value='{$status}'>{$name}</option>";
|
554 |
}
|
555 |
?>
|
556 |
<script type="text/javascript">
|
557 |
jQuery( document ).ready( function($) {
|
558 |
<?php if ( ! empty( $display ) ) : ?>
|
559 |
+
jQuery( '#post-status-display' ).html( '<?php echo $display; ?>' );
|
560 |
<?php endif; ?>
|
561 |
|
562 |
var select = jQuery( '#post-status-select' ).find( 'select' );
|
563 |
+
jQuery( select ).html( "<?php echo $options; ?>" );
|
564 |
} );
|
565 |
</script>
|
566 |
<?php
|
567 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
568 |
}
|
569 |
+
|
570 |
+
WP_Job_Manager_CPT::instance();
|
includes/admin/class-wp-job-manager-permalink-settings.php
DELETED
@@ -1,135 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Handles front admin page for WP Job Manager.
|
9 |
-
*
|
10 |
-
* @package wp-job-manager
|
11 |
-
* @see https://github.com/woocommerce/woocommerce/blob/3.0.8/includes/admin/class-wc-admin-permalink-settings.php Based on WooCommerce's implementation.
|
12 |
-
* @since 1.27.0
|
13 |
-
*/
|
14 |
-
class WP_Job_Manager_Permalink_Settings {
|
15 |
-
/**
|
16 |
-
* The single instance of the class.
|
17 |
-
*
|
18 |
-
* @var self
|
19 |
-
* @since 1.27.0
|
20 |
-
*/
|
21 |
-
private static $_instance = null;
|
22 |
-
|
23 |
-
/**
|
24 |
-
* Permalink settings.
|
25 |
-
*
|
26 |
-
* @var array
|
27 |
-
* @since 1.27.0
|
28 |
-
*/
|
29 |
-
private $permalinks = array();
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Allows for accessing single instance of class. Class should only be constructed once per call.
|
33 |
-
*
|
34 |
-
* @since 1.27.0
|
35 |
-
* @static
|
36 |
-
* @return self Main instance.
|
37 |
-
*/
|
38 |
-
public static function instance() {
|
39 |
-
if ( is_null( self::$_instance ) ) {
|
40 |
-
self::$_instance = new self();
|
41 |
-
}
|
42 |
-
return self::$_instance;
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Constructor.
|
47 |
-
*/
|
48 |
-
public function __construct() {
|
49 |
-
$this->setup_fields();
|
50 |
-
$this->settings_save();
|
51 |
-
$this->permalinks = WP_Job_Manager_Post_Types::get_permalink_structure();
|
52 |
-
}
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Add setting fields related to permalinks.
|
56 |
-
*/
|
57 |
-
public function setup_fields() {
|
58 |
-
add_settings_field(
|
59 |
-
'wpjm_job_base_slug',
|
60 |
-
__( 'Job base', 'wp-job-manager' ),
|
61 |
-
array( $this, 'job_base_slug_input' ),
|
62 |
-
'permalink',
|
63 |
-
'optional'
|
64 |
-
);
|
65 |
-
add_settings_field(
|
66 |
-
'wpjm_job_category_slug',
|
67 |
-
__( 'Job category base', 'wp-job-manager' ),
|
68 |
-
array( $this, 'job_category_slug_input' ),
|
69 |
-
'permalink',
|
70 |
-
'optional'
|
71 |
-
);
|
72 |
-
add_settings_field(
|
73 |
-
'wpjm_job_type_slug',
|
74 |
-
__( 'Job type base', 'wp-job-manager' ),
|
75 |
-
array( $this, 'job_type_slug_input' ),
|
76 |
-
'permalink',
|
77 |
-
'optional'
|
78 |
-
);
|
79 |
-
}
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Show a slug input box for job post type slug.
|
83 |
-
*/
|
84 |
-
public function job_base_slug_input() {
|
85 |
-
?>
|
86 |
-
<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' ); ?>" />
|
87 |
-
<?php
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Show a slug input box for job category slug.
|
92 |
-
*/
|
93 |
-
public function job_category_slug_input() {
|
94 |
-
?>
|
95 |
-
<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' ); ?>" />
|
96 |
-
<?php
|
97 |
-
}
|
98 |
-
|
99 |
-
/**
|
100 |
-
* Show a slug input box for job type slug.
|
101 |
-
*/
|
102 |
-
public function job_type_slug_input() {
|
103 |
-
?>
|
104 |
-
<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' ); ?>" />
|
105 |
-
<?php
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Save the settings.
|
110 |
-
*/
|
111 |
-
public function settings_save() {
|
112 |
-
if ( ! is_admin() ) {
|
113 |
-
return;
|
114 |
-
}
|
115 |
-
|
116 |
-
if ( isset( $_POST['permalink_structure'] ) ) {
|
117 |
-
if ( function_exists( 'switch_to_locale' ) ) {
|
118 |
-
switch_to_locale( get_locale() );
|
119 |
-
}
|
120 |
-
|
121 |
-
$permalinks = (array) get_option( 'wpjm_permalinks', array() );
|
122 |
-
$permalinks['job_base'] = sanitize_title_with_dashes( $_POST['wpjm_job_base_slug'] );
|
123 |
-
$permalinks['category_base'] = sanitize_title_with_dashes( $_POST['wpjm_job_category_slug'] );
|
124 |
-
$permalinks['type_base'] = sanitize_title_with_dashes( $_POST['wpjm_job_type_slug'] );
|
125 |
-
|
126 |
-
update_option( 'wpjm_permalinks', $permalinks );
|
127 |
-
|
128 |
-
if ( function_exists( 'restore_current_locale' ) ) {
|
129 |
-
restore_current_locale();
|
130 |
-
}
|
131 |
-
}
|
132 |
-
}
|
133 |
-
}
|
134 |
-
|
135 |
-
WP_Job_Manager_Permalink_Settings::instance();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/admin/class-wp-job-manager-settings.php
CHANGED
@@ -1,7 +1,6 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
|
4 |
-
}
|
5 |
|
6 |
/**
|
7 |
* Handles the management of plugin settings.
|
@@ -15,21 +14,14 @@ class WP_Job_Manager_Settings {
|
|
15 |
* The single instance of the class.
|
16 |
*
|
17 |
* @var self
|
18 |
-
* @since 1.26
|
19 |
*/
|
20 |
private static $_instance = null;
|
21 |
|
22 |
-
/**
|
23 |
-
* Our Settings.
|
24 |
-
*
|
25 |
-
* @var array Settings.
|
26 |
-
*/
|
27 |
-
protected $settings = array();
|
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 |
*/
|
@@ -48,72 +40,26 @@ class WP_Job_Manager_Settings {
|
|
48 |
add_action( 'admin_init', array( $this, 'register_settings' ) );
|
49 |
}
|
50 |
|
51 |
-
/**
|
52 |
-
* Get Job Manager Settings
|
53 |
-
*
|
54 |
-
* @return array
|
55 |
-
*/
|
56 |
-
public function get_settings() {
|
57 |
-
if ( 0 === count( $this->settings ) ) {
|
58 |
-
$this->init_settings();
|
59 |
-
}
|
60 |
-
return $this->settings;
|
61 |
-
}
|
62 |
-
|
63 |
/**
|
64 |
* Initializes the configuration for the plugin's setting fields.
|
65 |
*
|
66 |
* @access protected
|
67 |
*/
|
68 |
protected function init_settings() {
|
69 |
-
// Prepare roles option
|
70 |
$roles = get_editable_roles();
|
71 |
$account_roles = array();
|
72 |
|
73 |
foreach ( $roles as $key => $role ) {
|
74 |
-
if ( 'administrator'
|
75 |
continue;
|
76 |
}
|
77 |
$account_roles[ $key ] = $role['name'];
|
78 |
}
|
79 |
|
80 |
-
$this->settings = apply_filters(
|
81 |
-
'job_manager_settings',
|
82 |
array(
|
83 |
-
'
|
84 |
-
__( 'General', 'wp-job-manager' ),
|
85 |
-
array(
|
86 |
-
array(
|
87 |
-
'name' => 'job_manager_date_format',
|
88 |
-
'std' => 'relative',
|
89 |
-
'label' => __( 'Date Format', 'wp-job-manager' ),
|
90 |
-
'desc' => __( 'Choose how you want the published date for jobs to be displayed on the front-end.', 'wp-job-manager' ),
|
91 |
-
'type' => 'radio',
|
92 |
-
'options' => array(
|
93 |
-
'relative' => __( 'Relative to the current date (e.g., 1 day, 1 week, 1 month ago)', 'wp-job-manager' ),
|
94 |
-
'default' => __( 'Default date format as defined in Settings', 'wp-job-manager' ),
|
95 |
-
),
|
96 |
-
),
|
97 |
-
array(
|
98 |
-
'name' => 'job_manager_google_maps_api_key',
|
99 |
-
'std' => '',
|
100 |
-
'label' => __( 'Google Maps API Key', 'wp-job-manager' ),
|
101 |
-
// translators: Placeholder %s is URL to set up a Google Maps API key.
|
102 |
-
'desc' => sprintf( __( 'Google requires an API key to retrieve location information for job listings. Acquire an API key from the <a href="%s">Google Maps API developer site</a>.', 'wp-job-manager' ), 'https://developers.google.com/maps/documentation/geocoding/get-api-key' ),
|
103 |
-
'attributes' => array(),
|
104 |
-
),
|
105 |
-
array(
|
106 |
-
'name' => 'job_manager_delete_data_on_uninstall',
|
107 |
-
'std' => '0',
|
108 |
-
'label' => __( 'Delete Data On Uninstall', 'wp-job-manager' ),
|
109 |
-
'cb_label' => __( 'Delete WP Job Manager data when the plugin is deleted. Once removed, this data cannot be restored.', 'wp-job-manager' ),
|
110 |
-
'desc' => '',
|
111 |
-
'type' => 'checkbox',
|
112 |
-
'attributes' => array(),
|
113 |
-
),
|
114 |
-
),
|
115 |
-
),
|
116 |
-
'job_listings' => array(
|
117 |
__( 'Job Listings', 'wp-job-manager' ),
|
118 |
array(
|
119 |
array(
|
@@ -121,82 +67,100 @@ class WP_Job_Manager_Settings {
|
|
121 |
'std' => '10',
|
122 |
'placeholder' => '',
|
123 |
'label' => __( 'Listings Per Page', 'wp-job-manager' ),
|
124 |
-
'desc' => __( '
|
125 |
-
'attributes' => array()
|
126 |
),
|
127 |
array(
|
128 |
'name' => 'job_manager_hide_filled_positions',
|
129 |
'std' => '0',
|
130 |
'label' => __( 'Filled Positions', 'wp-job-manager' ),
|
131 |
'cb_label' => __( 'Hide filled positions', 'wp-job-manager' ),
|
132 |
-
'desc' => __( '
|
133 |
'type' => 'checkbox',
|
134 |
-
'attributes' => array()
|
135 |
),
|
136 |
array(
|
137 |
'name' => 'job_manager_hide_expired',
|
138 |
-
'std' => get_option( 'job_manager_hide_expired_content' ) ? '1' : '0', // back compat
|
139 |
'label' => __( 'Hide Expired Listings', 'wp-job-manager' ),
|
140 |
-
'cb_label' => __( 'Hide expired listings in job
|
141 |
-
'desc' => __( '
|
142 |
'type' => 'checkbox',
|
143 |
-
'attributes' => array()
|
144 |
),
|
145 |
array(
|
146 |
'name' => 'job_manager_hide_expired_content',
|
147 |
'std' => '1',
|
148 |
'label' => __( 'Hide Expired Listings Content', 'wp-job-manager' ),
|
149 |
-
'cb_label' => __( 'Hide content in
|
150 |
-
'desc' => __( '
|
151 |
'type' => 'checkbox',
|
152 |
-
'attributes' => array()
|
153 |
),
|
154 |
array(
|
155 |
'name' => 'job_manager_enable_categories',
|
156 |
'std' => '0',
|
157 |
'label' => __( 'Categories', 'wp-job-manager' ),
|
158 |
-
'cb_label' => __( 'Enable
|
159 |
-
'desc' => __( '
|
160 |
'type' => 'checkbox',
|
161 |
-
'attributes' => array()
|
162 |
),
|
163 |
array(
|
164 |
'name' => 'job_manager_enable_default_category_multiselect',
|
165 |
'std' => '0',
|
166 |
'label' => __( 'Multi-select Categories', 'wp-job-manager' ),
|
167 |
-
'cb_label' => __( '
|
168 |
-
'desc' => __( '
|
169 |
'type' => 'checkbox',
|
170 |
-
'attributes' => array()
|
171 |
),
|
172 |
array(
|
173 |
-
'name'
|
174 |
-
'std'
|
175 |
-
'label'
|
176 |
-
'desc'
|
177 |
-
'type'
|
178 |
'options' => array(
|
179 |
-
'any'
|
180 |
'all' => __( 'Jobs will be shown if within ALL selected categories', 'wp-job-manager' ),
|
181 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
182 |
),
|
183 |
array(
|
184 |
'name' => 'job_manager_enable_types',
|
185 |
'std' => '1',
|
186 |
'label' => __( 'Types', 'wp-job-manager' ),
|
187 |
-
'cb_label' => __( 'Enable
|
188 |
-
'desc' => __( '
|
189 |
'type' => 'checkbox',
|
190 |
-
'attributes' => array()
|
191 |
),
|
192 |
array(
|
193 |
'name' => 'job_manager_multi_job_type',
|
194 |
'std' => '0',
|
195 |
'label' => __( 'Multi-select Listing Types', 'wp-job-manager' ),
|
196 |
-
'cb_label' => __( '
|
197 |
-
'desc' => __( '
|
198 |
'type' => 'checkbox',
|
199 |
-
'attributes' => array()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
),
|
201 |
),
|
202 |
),
|
@@ -207,165 +171,102 @@ class WP_Job_Manager_Settings {
|
|
207 |
'name' => 'job_manager_user_requires_account',
|
208 |
'std' => '1',
|
209 |
'label' => __( 'Account Required', 'wp-job-manager' ),
|
210 |
-
'cb_label' => __( '
|
211 |
-
'desc' => __( '
|
212 |
'type' => 'checkbox',
|
213 |
-
'attributes' => array()
|
214 |
),
|
215 |
array(
|
216 |
'name' => 'job_manager_enable_registration',
|
217 |
'std' => '1',
|
218 |
'label' => __( 'Account Creation', 'wp-job-manager' ),
|
219 |
-
'cb_label' => __( '
|
220 |
-
'desc' => __( '
|
221 |
'type' => 'checkbox',
|
222 |
-
'attributes' => array()
|
223 |
),
|
224 |
array(
|
225 |
'name' => 'job_manager_generate_username_from_email',
|
226 |
'std' => '1',
|
227 |
'label' => __( 'Account Username', 'wp-job-manager' ),
|
228 |
-
'cb_label' => __( 'Generate
|
229 |
-
'desc' => __( '
|
230 |
'type' => 'checkbox',
|
231 |
-
'attributes' => array()
|
232 |
),
|
233 |
array(
|
234 |
-
'name' => '
|
235 |
-
'std' => '
|
236 |
-
'label' => __( 'Account
|
237 |
-
'
|
238 |
-
'
|
239 |
-
'
|
240 |
-
'attributes' => array(),
|
241 |
-
),
|
242 |
-
array(
|
243 |
-
'name' => 'job_manager_registration_role',
|
244 |
-
'std' => 'employer',
|
245 |
-
'label' => __( 'Account Role', 'wp-job-manager' ),
|
246 |
-
'desc' => __( 'Any new accounts created during submission will have this role. If you haven\'t enabled account creation during submission in the options above, your own method of assigning roles will apply.', 'wp-job-manager' ),
|
247 |
-
'type' => 'select',
|
248 |
-
'options' => $account_roles,
|
249 |
),
|
250 |
array(
|
251 |
'name' => 'job_manager_submission_requires_approval',
|
252 |
'std' => '1',
|
253 |
'label' => __( 'Moderate New Listings', 'wp-job-manager' ),
|
254 |
-
'cb_label' => __( '
|
255 |
-
'desc' => __( '
|
256 |
'type' => 'checkbox',
|
257 |
-
'attributes' => array()
|
258 |
),
|
259 |
array(
|
260 |
'name' => 'job_manager_user_can_edit_pending_submissions',
|
261 |
'std' => '0',
|
262 |
'label' => __( 'Allow Pending Edits', 'wp-job-manager' ),
|
263 |
-
'cb_label' => __( '
|
264 |
-
'desc' => __( '
|
265 |
'type' => 'checkbox',
|
266 |
-
'attributes' => array()
|
267 |
-
),
|
268 |
-
array(
|
269 |
-
'name' => 'job_manager_user_edit_published_submissions',
|
270 |
-
'std' => 'yes',
|
271 |
-
'label' => __( 'Allow Published Edits', 'wp-job-manager' ),
|
272 |
-
'cb_label' => __( 'Allow editing of published listings', 'wp-job-manager' ),
|
273 |
-
'desc' => __( 'Choose whether published job listings can be edited and if edits require admin approval. When moderation is required, the original job listings will be unpublished while edits await admin approval.', 'wp-job-manager' ),
|
274 |
-
'type' => 'radio',
|
275 |
-
'options' => array(
|
276 |
-
'no' => __( 'Users cannot edit', 'wp-job-manager' ),
|
277 |
-
'yes' => __( 'Users can edit without admin approval', 'wp-job-manager' ),
|
278 |
-
'yes_moderated' => __( 'Users can edit, but edits require admin approval', 'wp-job-manager' ),
|
279 |
-
),
|
280 |
-
'attributes' => array(),
|
281 |
),
|
282 |
array(
|
283 |
'name' => 'job_manager_submission_duration',
|
284 |
'std' => '30',
|
285 |
'label' => __( 'Listing Duration', 'wp-job-manager' ),
|
286 |
-
'desc' => __( '
|
287 |
-
'attributes' => array()
|
288 |
),
|
289 |
array(
|
290 |
-
'name'
|
291 |
-
'std'
|
292 |
-
'label'
|
293 |
-
'desc'
|
294 |
-
'type'
|
295 |
-
'options'
|
296 |
'' => __( 'Email address or website URL', 'wp-job-manager' ),
|
297 |
'email' => __( 'Email addresses only', 'wp-job-manager' ),
|
298 |
'url' => __( 'Website URLs only', 'wp-job-manager' ),
|
299 |
-
)
|
300 |
-
),
|
301 |
-
),
|
302 |
-
),
|
303 |
-
'recaptcha' => array(
|
304 |
-
__( 'reCAPTCHA', 'wp-job-manager' ),
|
305 |
-
array(
|
306 |
-
array(
|
307 |
-
'name' => 'job_manager_recaptcha_label',
|
308 |
-
'std' => __( 'Are you human?', 'wp-job-manager' ),
|
309 |
-
'placeholder' => '',
|
310 |
-
'label' => __( 'Field Label', 'wp-job-manager' ),
|
311 |
-
'desc' => __( 'The label used for the reCAPTCHA field on forms.', 'wp-job-manager' ),
|
312 |
-
'attributes' => array(),
|
313 |
),
|
314 |
-
|
315 |
-
'name' => 'job_manager_recaptcha_site_key',
|
316 |
-
'std' => '',
|
317 |
-
'placeholder' => '',
|
318 |
-
'label' => __( 'Site Key', 'wp-job-manager' ),
|
319 |
-
// translators: Placeholder %s is URL to set up Google reCAPTCHA API key.
|
320 |
-
'desc' => sprintf( __( 'You can retrieve your site key from <a href="%s">Google\'s reCAPTCHA admin dashboard</a>.', 'wp-job-manager' ), 'https://www.google.com/recaptcha/admin#list' ),
|
321 |
-
'attributes' => array(),
|
322 |
-
),
|
323 |
-
array(
|
324 |
-
'name' => 'job_manager_recaptcha_secret_key',
|
325 |
-
'std' => '',
|
326 |
-
'placeholder' => '',
|
327 |
-
'label' => __( 'Secret Key', 'wp-job-manager' ),
|
328 |
-
// translators: Placeholder %s is URL to set up Google reCAPTCHA API key.
|
329 |
-
'desc' => sprintf( __( 'You can retrieve your secret key from <a href="%s">Google\'s reCAPTCHA admin dashboard</a>.', 'wp-job-manager' ), 'https://www.google.com/recaptcha/admin#list' ),
|
330 |
-
'attributes' => array(),
|
331 |
-
),
|
332 |
-
array(
|
333 |
-
'name' => 'job_manager_enable_recaptcha_job_submission',
|
334 |
-
'std' => '0',
|
335 |
-
'label' => __( 'Job Submission Form', 'wp-job-manager' ),
|
336 |
-
'cb_label' => __( 'Display a reCAPTCHA field on job submission form.', 'wp-job-manager' ),
|
337 |
-
'desc' => sprintf( __( 'This will help prevent bots from submitting job listings. You must have entered a valid site key and secret key above.', 'wp-job-manager' ), 'https://www.google.com/recaptcha/admin#list' ),
|
338 |
-
'type' => 'checkbox',
|
339 |
-
'attributes' => array(),
|
340 |
-
),
|
341 |
-
),
|
342 |
),
|
343 |
-
'job_pages'
|
344 |
__( 'Pages', 'wp-job-manager' ),
|
345 |
array(
|
346 |
array(
|
347 |
-
'name'
|
348 |
-
'std'
|
349 |
-
'label'
|
350 |
-
'desc'
|
351 |
-
'type'
|
352 |
),
|
353 |
array(
|
354 |
-
'name'
|
355 |
-
'std'
|
356 |
-
'label'
|
357 |
-
'desc'
|
358 |
-
'type'
|
359 |
),
|
360 |
array(
|
361 |
-
'name'
|
362 |
-
'std'
|
363 |
-
'label'
|
364 |
-
'desc'
|
365 |
-
'type'
|
366 |
),
|
367 |
-
)
|
368 |
-
)
|
369 |
)
|
370 |
);
|
371 |
}
|
@@ -378,9 +279,8 @@ class WP_Job_Manager_Settings {
|
|
378 |
|
379 |
foreach ( $this->settings as $section ) {
|
380 |
foreach ( $section[1] as $option ) {
|
381 |
-
if ( isset( $option['std'] ) )
|
382 |
add_option( $option['name'], $option['std'] );
|
383 |
-
}
|
384 |
register_setting( $this->settings_group, $option['name'] );
|
385 |
}
|
386 |
}
|
@@ -393,474 +293,155 @@ class WP_Job_Manager_Settings {
|
|
393 |
$this->init_settings();
|
394 |
?>
|
395 |
<div class="wrap job-manager-settings-wrap">
|
396 |
-
<form
|
397 |
|
398 |
<?php settings_fields( $this->settings_group ); ?>
|
399 |
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
|
408 |
<?php
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
}
|
413 |
-
|
414 |
-
foreach ( $this->settings as $key => $section ) {
|
415 |
-
$section_args = isset( $section[2] ) ? (array) $section[2] : array();
|
416 |
-
echo '<div id="settings-' . esc_attr( sanitize_title( $key ) ) . '" class="settings_panel">';
|
417 |
-
if ( ! empty( $section_args['before'] ) ) {
|
418 |
-
echo '<p class="before-settings">' . wp_kses_post( $section_args['before'] ) . '</p>';
|
419 |
}
|
420 |
-
echo '<table class="form-table settings parent-settings">';
|
421 |
|
422 |
-
foreach ( $
|
423 |
-
$value = get_option( $option['name'] );
|
424 |
-
$this->output_field( $option, $value );
|
425 |
-
}
|
426 |
|
427 |
-
|
428 |
-
if ( ! empty( $section_args['after'] ) ) {
|
429 |
-
echo '<p class="after-settings">' . wp_kses_post( $section_args['after'] ) . '</p>';
|
430 |
-
}
|
431 |
-
echo '</div>';
|
432 |
|
433 |
-
|
434 |
-
?>
|
435 |
-
<p class="submit">
|
436 |
-
<input type="submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes', 'wp-job-manager' ); ?>" />
|
437 |
-
</p>
|
438 |
-
</form>
|
439 |
-
</div>
|
440 |
-
<script type="text/javascript">
|
441 |
-
jQuery('.nav-tab-wrapper a').click(function() {
|
442 |
-
if ( '#' !== jQuery(this).attr( 'href' ).substr( 0, 1 ) ) {
|
443 |
-
return false;
|
444 |
-
}
|
445 |
-
jQuery('.settings_panel').hide();
|
446 |
-
jQuery('.nav-tab-active').removeClass('nav-tab-active');
|
447 |
-
jQuery( jQuery(this).attr('href') ).show();
|
448 |
-
jQuery(this).addClass('nav-tab-active');
|
449 |
-
window.location.hash = jQuery(this).attr('href');
|
450 |
-
jQuery( 'form.job-manager-options' ).attr( 'action', 'options.php' + jQuery(this).attr( 'href' ) );
|
451 |
-
window.scrollTo( 0, 0 );
|
452 |
-
return false;
|
453 |
-
});
|
454 |
-
var goto_hash = window.location.hash;
|
455 |
-
if ( '#' === goto_hash.substr( 0, 1 ) ) {
|
456 |
-
jQuery( 'form.job-manager-options' ).attr( 'action', 'options.php' + jQuery(this).attr( 'href' ) );
|
457 |
-
}
|
458 |
-
if ( goto_hash ) {
|
459 |
-
var the_tab = jQuery( 'a[href="' + goto_hash + '"]' );
|
460 |
-
if ( the_tab.length > 0 ) {
|
461 |
-
the_tab.click();
|
462 |
-
} else {
|
463 |
-
jQuery( '.nav-tab-wrapper a:first' ).click();
|
464 |
-
}
|
465 |
-
} else {
|
466 |
-
jQuery( '.nav-tab-wrapper a:first' ).click();
|
467 |
-
}
|
468 |
-
var $use_standard_password_setup_email = jQuery('#setting-job_manager_use_standard_password_setup_email');
|
469 |
-
var $generate_username_from_email = jQuery('#setting-job_manager_generate_username_from_email');
|
470 |
-
var $job_manager_registration_role = jQuery('#setting-job_manager_registration_role');
|
471 |
|
472 |
-
|
473 |
-
if ( jQuery( this ).is(':checked') ) {
|
474 |
-
$job_manager_registration_role.closest('tr').show();
|
475 |
-
$use_standard_password_setup_email.closest('tr').show();
|
476 |
-
$generate_username_from_email.closest('tr').show();
|
477 |
-
} else {
|
478 |
-
$job_manager_registration_role.closest('tr').hide();
|
479 |
-
$use_standard_password_setup_email.closest('tr').hide();
|
480 |
-
$generate_username_from_email.closest('tr').hide();
|
481 |
-
}
|
482 |
-
}).change();
|
483 |
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
} else {
|
494 |
-
$use_standard_password_setup_email.prop('disabled', false);
|
495 |
-
if ( undefined !== $use_standard_password_setup_email.data('original-state') ) {
|
496 |
-
$use_standard_password_setup_email.prop('checked', $use_standard_password_setup_email.data('original-state'));
|
497 |
-
}
|
498 |
-
}
|
499 |
-
}).change();
|
500 |
|
501 |
-
|
502 |
-
var $expandable = jQuery(this).parent().siblings( '.sub-settings-expandable' );
|
503 |
-
var checked = jQuery(this).is( ':checked' );
|
504 |
-
if ( checked ) {
|
505 |
-
$expandable.addClass( 'expanded' );
|
506 |
-
} else {
|
507 |
-
$expandable.removeClass( 'expanded' );
|
508 |
-
}
|
509 |
-
} ).trigger( 'change' );
|
510 |
-
</script>
|
511 |
-
<?php
|
512 |
-
}
|
513 |
|
514 |
-
|
515 |
-
* Checkbox input field.
|
516 |
-
*
|
517 |
-
* @param array $option
|
518 |
-
* @param array $attributes
|
519 |
-
* @param mixed $value
|
520 |
-
* @param string $ignored_placeholder
|
521 |
-
*/
|
522 |
-
protected function input_checkbox( $option, $attributes, $value, $ignored_placeholder ) {
|
523 |
-
?>
|
524 |
-
<label>
|
525 |
-
<input type="hidden" name="<?php echo esc_attr( $option['name'] ); ?>" value="0" />
|
526 |
-
<input
|
527 |
-
id="setting-<?php echo esc_attr( $option['name'] ); ?>"
|
528 |
-
name="<?php echo esc_attr( $option['name'] ); ?>"
|
529 |
-
type="checkbox"
|
530 |
-
value="1"
|
531 |
-
<?php
|
532 |
-
echo implode( ' ', $attributes ) . ' '; // WPCS: XSS ok.
|
533 |
-
checked( '1', $value );
|
534 |
-
?>
|
535 |
-
/> <?php echo wp_kses_post( $option['cb_label'] ); ?></label>
|
536 |
-
<?php
|
537 |
-
if ( ! empty( $option['desc'] ) ) {
|
538 |
-
echo ' <p class="description">' . wp_kses_post( $option['desc'] ) . '</p>';
|
539 |
-
}
|
540 |
-
}
|
541 |
|
542 |
-
|
543 |
-
* Text area input field.
|
544 |
-
*
|
545 |
-
* @param array $option
|
546 |
-
* @param array $attributes
|
547 |
-
* @param mixed $value
|
548 |
-
* @param string $placeholder
|
549 |
-
*/
|
550 |
-
protected function input_textarea( $option, $attributes, $value, $placeholder ) {
|
551 |
-
?>
|
552 |
-
<textarea
|
553 |
-
id="setting-<?php echo esc_attr( $option['name'] ); ?>"
|
554 |
-
class="large-text"
|
555 |
-
cols="50"
|
556 |
-
rows="3"
|
557 |
-
name="<?php echo esc_attr( $option['name'] ); ?>"
|
558 |
-
<?php
|
559 |
-
echo implode( ' ', $attributes ) . ' '; // WPCS: XSS ok.
|
560 |
-
echo $placeholder; // WPCS: XSS ok.
|
561 |
-
?>
|
562 |
-
>
|
563 |
-
<?php echo esc_textarea( $value ); ?>
|
564 |
-
</textarea>
|
565 |
-
<?php
|
566 |
|
567 |
-
|
568 |
-
echo ' <p class="description">' . wp_kses_post( $option['desc'] ) . '</p>';
|
569 |
-
}
|
570 |
-
}
|
571 |
|
572 |
-
|
573 |
-
|
574 |
-
*
|
575 |
-
* @param array $option
|
576 |
-
* @param array $attributes
|
577 |
-
* @param mixed $value
|
578 |
-
* @param string $ignored_placeholder
|
579 |
-
*/
|
580 |
-
protected function input_select( $option, $attributes, $value, $ignored_placeholder ) {
|
581 |
-
?>
|
582 |
-
<select
|
583 |
-
id="setting-<?php echo esc_attr( $option['name'] ); ?>"
|
584 |
-
class="regular-text"
|
585 |
-
name="<?php echo esc_attr( $option['name'] ); ?>"
|
586 |
-
<?php
|
587 |
-
echo implode( ' ', $attributes ); // WPCS: XSS ok.
|
588 |
-
?>
|
589 |
-
>
|
590 |
-
<?php
|
591 |
-
foreach ( $option['options'] as $key => $name ) {
|
592 |
-
echo '<option value="' . esc_attr( $key ) . '" ' . selected( $value, $key, false ) . '>' . esc_html( $name ) . '</option>';
|
593 |
-
}
|
594 |
-
?>
|
595 |
-
</select>
|
596 |
-
<?php
|
597 |
|
598 |
-
|
599 |
-
|
600 |
-
}
|
601 |
-
}
|
602 |
|
603 |
-
|
604 |
-
* Radio input field.
|
605 |
-
*
|
606 |
-
* @param array $option
|
607 |
-
* @param array $ignored_attributes
|
608 |
-
* @param mixed $value
|
609 |
-
* @param string $ignored_placeholder
|
610 |
-
*/
|
611 |
-
protected function input_radio( $option, $ignored_attributes, $value, $ignored_placeholder ) {
|
612 |
-
?>
|
613 |
-
<fieldset>
|
614 |
-
<legend class="screen-reader-text">
|
615 |
-
<span><?php echo esc_html( $option['label'] ); ?></span>
|
616 |
-
</legend>
|
617 |
-
<?php
|
618 |
-
if ( ! empty( $option['desc'] ) ) {
|
619 |
-
echo ' <p class="description">' . wp_kses_post( $option['desc'] ) . '</p>';
|
620 |
-
}
|
621 |
|
622 |
-
|
623 |
-
|
624 |
-
}
|
625 |
-
?>
|
626 |
-
</fieldset>
|
627 |
-
<?php
|
628 |
-
}
|
629 |
|
630 |
-
|
631 |
-
|
632 |
-
*
|
633 |
-
* @param array $option
|
634 |
-
* @param array $ignored_attributes
|
635 |
-
* @param mixed $value
|
636 |
-
* @param string $ignored_placeholder
|
637 |
-
*/
|
638 |
-
protected function input_page( $option, $ignored_attributes, $value, $ignored_placeholder ) {
|
639 |
-
$args = array(
|
640 |
-
'name' => $option['name'],
|
641 |
-
'id' => $option['name'],
|
642 |
-
'sort_column' => 'menu_order',
|
643 |
-
'sort_order' => 'ASC',
|
644 |
-
'show_option_none' => __( '--no page--', 'wp-job-manager' ),
|
645 |
-
'echo' => false,
|
646 |
-
'selected' => absint( $value ),
|
647 |
-
);
|
648 |
|
649 |
-
|
|
|
|
|
|
|
650 |
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
}
|
655 |
|
656 |
-
|
657 |
-
|
658 |
-
*
|
659 |
-
* @param array $option
|
660 |
-
* @param array $attributes
|
661 |
-
* @param mixed $value
|
662 |
-
* @param string $ignored_placeholder
|
663 |
-
*/
|
664 |
-
protected function input_hidden( $option, $attributes, $value, $ignored_placeholder ) {
|
665 |
-
$human_value = $value;
|
666 |
-
if ( $option['human_value'] ) {
|
667 |
-
$human_value = $option['human_value'];
|
668 |
-
}
|
669 |
-
?>
|
670 |
-
<input
|
671 |
-
id="setting-<?php echo esc_attr( $option['name'] ); ?>"
|
672 |
-
type="hidden"
|
673 |
-
name="<?php echo esc_attr( $option['name'] ); ?>"
|
674 |
-
value="<?php echo esc_attr( $value ); ?>"
|
675 |
-
<?php
|
676 |
-
echo implode( ' ', $attributes ); // WPCS: XSS ok.
|
677 |
-
?>
|
678 |
-
/><strong><?php echo esc_html( $human_value ); ?></strong>
|
679 |
-
<?php
|
680 |
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
|
|
|
|
|
|
|
|
|
|
685 |
|
686 |
-
|
687 |
-
* Password input field.
|
688 |
-
*
|
689 |
-
* @param array $option
|
690 |
-
* @param array $attributes
|
691 |
-
* @param mixed $value
|
692 |
-
* @param string $placeholder
|
693 |
-
*/
|
694 |
-
protected function input_password( $option, $attributes, $value, $placeholder ) {
|
695 |
-
?>
|
696 |
-
<input
|
697 |
-
id="setting-<?php echo esc_attr( $option['name'] ); ?>"
|
698 |
-
class="regular-text"
|
699 |
-
type="password"
|
700 |
-
name="<?php echo esc_attr( $option['name'] ); ?>"
|
701 |
-
value="<?php echo esc_attr( $value ); ?>"
|
702 |
-
<?php
|
703 |
-
echo implode( ' ', $attributes ) . ' '; // WPCS: XSS ok.
|
704 |
-
echo $placeholder; // WPCS: XSS ok.
|
705 |
-
?>
|
706 |
-
/>
|
707 |
-
<?php
|
708 |
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
}
|
713 |
|
714 |
-
|
715 |
-
|
716 |
-
*
|
717 |
-
* @param array $option
|
718 |
-
* @param array $attributes
|
719 |
-
* @param mixed $value
|
720 |
-
* @param string $placeholder
|
721 |
-
*/
|
722 |
-
protected function input_number( $option, $attributes, $value, $placeholder ) {
|
723 |
-
echo isset( $option['before'] ) ? wp_kses_post( $option['before'] ) : '';
|
724 |
-
?>
|
725 |
-
<input
|
726 |
-
id="setting-<?php echo esc_attr( $option['name'] ); ?>"
|
727 |
-
class="small-text"
|
728 |
-
type="number"
|
729 |
-
name="<?php echo esc_attr( $option['name'] ); ?>"
|
730 |
-
value="<?php echo esc_attr( $value ); ?>"
|
731 |
-
<?php
|
732 |
-
echo implode( ' ', $attributes ) . ' '; // WPCS: XSS ok.
|
733 |
-
echo $placeholder; // WPCS: XSS ok.
|
734 |
-
?>
|
735 |
-
/>
|
736 |
-
<?php
|
737 |
-
echo isset( $option['after'] ) ? wp_kses_post( $option['after'] ) : '';
|
738 |
-
if ( ! empty( $option['desc'] ) ) {
|
739 |
-
echo ' <p class="description">' . wp_kses_post( $option['desc'] ) . '</p>';
|
740 |
-
}
|
741 |
-
}
|
742 |
|
743 |
-
|
744 |
-
* Text input field.
|
745 |
-
*
|
746 |
-
* @param array $option
|
747 |
-
* @param array $attributes
|
748 |
-
* @param mixed $value
|
749 |
-
* @param string $placeholder
|
750 |
-
*/
|
751 |
-
protected function input_text( $option, $attributes, $value, $placeholder ) {
|
752 |
-
?>
|
753 |
-
<input
|
754 |
-
id="setting-<?php echo esc_attr( $option['name'] ); ?>"
|
755 |
-
class="regular-text"
|
756 |
-
type="text"
|
757 |
-
name="<?php echo esc_attr( $option['name'] ); ?>"
|
758 |
-
value="<?php echo esc_attr( $value ); ?>"
|
759 |
-
<?php
|
760 |
-
echo implode( ' ', $attributes ) . ' '; // WPCS: XSS ok.
|
761 |
-
echo $placeholder; // WPCS: XSS ok.
|
762 |
-
?>
|
763 |
-
/>
|
764 |
-
<?php
|
765 |
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
}
|
770 |
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
* @param array $option
|
775 |
-
* @param mixed $value
|
776 |
-
*/
|
777 |
-
protected function output_field( $option, $value ) {
|
778 |
-
$placeholder = ( ! empty( $option['placeholder'] ) ) ? 'placeholder="' . esc_attr( $option['placeholder'] ) . '"' : '';
|
779 |
-
$class = ! empty( $option['class'] ) ? $option['class'] : '';
|
780 |
-
$option['type'] = ! empty( $option['type'] ) ? $option['type'] : 'text';
|
781 |
-
$attributes = array();
|
782 |
-
if ( ! empty( $option['attributes'] ) && is_array( $option['attributes'] ) ) {
|
783 |
-
foreach ( $option['attributes'] as $attribute_name => $attribute_value ) {
|
784 |
-
$attributes[] = esc_attr( $attribute_name ) . '="' . esc_attr( $attribute_value ) . '"';
|
785 |
-
}
|
786 |
-
}
|
787 |
|
788 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
789 |
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
|
|
|
|
795 |
|
796 |
-
|
797 |
-
if ( method_exists( $this, $method_name ) ) {
|
798 |
-
$this->$method_name( $option, $attributes, $value, $placeholder );
|
799 |
-
} else {
|
800 |
-
/**
|
801 |
-
* Allows for custom fields in admin setting panes.
|
802 |
-
*
|
803 |
-
* @since 1.14.0
|
804 |
-
*
|
805 |
-
* @param string $option Field name.
|
806 |
-
* @param array $attributes Array of attributes.
|
807 |
-
* @param mixed $value Field value.
|
808 |
-
* @param string $value Placeholder text.
|
809 |
-
*/
|
810 |
-
do_action( 'wp_job_manager_admin_field_' . $option['type'], $option, $attributes, $value, $placeholder );
|
811 |
-
}
|
812 |
-
echo '</td></tr>';
|
813 |
-
}
|
814 |
|
815 |
-
|
816 |
-
|
817 |
-
*
|
818 |
-
* @param array $option
|
819 |
-
* @param array $attributes
|
820 |
-
* @param array $values
|
821 |
-
* @param string $placeholder
|
822 |
-
*/
|
823 |
-
protected function input_multi_enable_expand( $option, $attributes, $values, $placeholder ) {
|
824 |
-
echo '<div class="setting-enable-expand">';
|
825 |
-
$enable_option = $option['enable_field'];
|
826 |
-
$enable_option['name'] = $option['name'] . '[' . $enable_option['name'] . ']';
|
827 |
-
$enable_option['type'] = 'checkbox';
|
828 |
-
$enable_option['attributes'] = array( 'class="sub-settings-expander"' );
|
829 |
-
$this->input_checkbox( $enable_option, $enable_option['attributes'], $values[ $option['enable_field']['name'] ], null );
|
830 |
-
|
831 |
-
echo '<div class="sub-settings-expandable">';
|
832 |
-
$this->input_multi( $option, $attributes, $values, $placeholder );
|
833 |
-
echo '</div>';
|
834 |
-
echo '</div>';
|
835 |
-
}
|
836 |
|
837 |
-
|
838 |
-
* Multiple settings stored in one setting array.
|
839 |
-
*
|
840 |
-
* @param array $option
|
841 |
-
* @param array $ignored_attributes
|
842 |
-
* @param array $values
|
843 |
-
* @param string $ignored_placeholder
|
844 |
-
*/
|
845 |
-
protected function input_multi( $option, $ignored_attributes, $values, $ignored_placeholder ) {
|
846 |
-
echo '<table class="form-table settings child-settings">';
|
847 |
-
foreach ( $option['settings'] as $sub_option ) {
|
848 |
-
$value = isset( $values[ $sub_option['name'] ] ) ? $values[ $sub_option['name'] ] : $sub_option['std'];
|
849 |
-
$sub_option['name'] = $option['name'] . '[' . $sub_option['name'] . ']';
|
850 |
-
$this->output_field( $sub_option, $value );
|
851 |
-
}
|
852 |
-
echo '</table>';
|
853 |
-
}
|
854 |
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
865 |
}
|
866 |
}
|
1 |
<?php
|
2 |
+
|
3 |
+
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
4 |
|
5 |
/**
|
6 |
* Handles the management of plugin 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 |
*/
|
40 |
add_action( 'admin_init', array( $this, 'register_settings' ) );
|
41 |
}
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
/**
|
44 |
* Initializes the configuration for the plugin's setting fields.
|
45 |
*
|
46 |
* @access protected
|
47 |
*/
|
48 |
protected function init_settings() {
|
49 |
+
// Prepare roles option
|
50 |
$roles = get_editable_roles();
|
51 |
$account_roles = array();
|
52 |
|
53 |
foreach ( $roles as $key => $role ) {
|
54 |
+
if ( $key == 'administrator' ) {
|
55 |
continue;
|
56 |
}
|
57 |
$account_roles[ $key ] = $role['name'];
|
58 |
}
|
59 |
|
60 |
+
$this->settings = apply_filters( 'job_manager_settings',
|
|
|
61 |
array(
|
62 |
+
'job_listings' => array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
__( 'Job Listings', 'wp-job-manager' ),
|
64 |
array(
|
65 |
array(
|
67 |
'std' => '10',
|
68 |
'placeholder' => '',
|
69 |
'label' => __( 'Listings Per Page', 'wp-job-manager' ),
|
70 |
+
'desc' => __( 'How many listings should be shown per page by default?', 'wp-job-manager' ),
|
71 |
+
'attributes' => array()
|
72 |
),
|
73 |
array(
|
74 |
'name' => 'job_manager_hide_filled_positions',
|
75 |
'std' => '0',
|
76 |
'label' => __( 'Filled Positions', 'wp-job-manager' ),
|
77 |
'cb_label' => __( 'Hide filled positions', 'wp-job-manager' ),
|
78 |
+
'desc' => __( 'If enabled, filled positions will be hidden from archives.', 'wp-job-manager' ),
|
79 |
'type' => 'checkbox',
|
80 |
+
'attributes' => array()
|
81 |
),
|
82 |
array(
|
83 |
'name' => 'job_manager_hide_expired',
|
84 |
+
'std' => get_option( 'job_manager_hide_expired_content' ) ? '1' : '0', // back compat
|
85 |
'label' => __( 'Hide Expired Listings', 'wp-job-manager' ),
|
86 |
+
'cb_label' => __( 'Hide expired listings in job archive/search', 'wp-job-manager' ),
|
87 |
+
'desc' => __( 'If enabled, expired job listing is not searchable.', 'wp-job-manager' ),
|
88 |
'type' => 'checkbox',
|
89 |
+
'attributes' => array()
|
90 |
),
|
91 |
array(
|
92 |
'name' => 'job_manager_hide_expired_content',
|
93 |
'std' => '1',
|
94 |
'label' => __( 'Hide Expired Listings Content', 'wp-job-manager' ),
|
95 |
+
'cb_label' => __( 'Hide expired listing content in single job listing (singular)', 'wp-job-manager' ),
|
96 |
+
'desc' => __( 'If enabled, the content within expired listings will be hidden. Otherwise, expired listings will be displayed as normal (without the application area).', 'wp-job-manager' ),
|
97 |
'type' => 'checkbox',
|
98 |
+
'attributes' => array()
|
99 |
),
|
100 |
array(
|
101 |
'name' => 'job_manager_enable_categories',
|
102 |
'std' => '0',
|
103 |
'label' => __( 'Categories', 'wp-job-manager' ),
|
104 |
+
'cb_label' => __( 'Enable categories for listings', 'wp-job-manager' ),
|
105 |
+
'desc' => __( 'Choose whether to enable categories. Categories must be setup by an admin to allow users to choose them during submission.', 'wp-job-manager' ),
|
106 |
'type' => 'checkbox',
|
107 |
+
'attributes' => array()
|
108 |
),
|
109 |
array(
|
110 |
'name' => 'job_manager_enable_default_category_multiselect',
|
111 |
'std' => '0',
|
112 |
'label' => __( 'Multi-select Categories', 'wp-job-manager' ),
|
113 |
+
'cb_label' => __( 'Enable category multiselect by default', 'wp-job-manager' ),
|
114 |
+
'desc' => __( 'If enabled, the category select box will default to a multiselect on the [jobs] shortcode.', 'wp-job-manager' ),
|
115 |
'type' => 'checkbox',
|
116 |
+
'attributes' => array()
|
117 |
),
|
118 |
array(
|
119 |
+
'name' => 'job_manager_category_filter_type',
|
120 |
+
'std' => 'any',
|
121 |
+
'label' => __( 'Category Filter Type', 'wp-job-manager' ),
|
122 |
+
'desc' => __( 'Determines the logic used to display jobs when selecting multiple categories.', 'wp-job-manager' ),
|
123 |
+
'type' => 'select',
|
124 |
'options' => array(
|
125 |
+
'any' => __( 'Jobs will be shown if within ANY selected category', 'wp-job-manager' ),
|
126 |
'all' => __( 'Jobs will be shown if within ALL selected categories', 'wp-job-manager' ),
|
127 |
+
)
|
128 |
+
),
|
129 |
+
array(
|
130 |
+
'name' => 'job_manager_date_format',
|
131 |
+
'std' => 'relative',
|
132 |
+
'label' => __( 'Date Format', 'wp-job-manager' ),
|
133 |
+
'desc' => __( 'Choose how you want the published date for jobs to be displayed on the front-end.', 'wp-job-manager' ),
|
134 |
+
'type' => 'select',
|
135 |
+
'options' => array(
|
136 |
+
'relative' => __( 'Relative to the current date (e.g., 1 day, 1 week, 1 month ago)', 'wp-job-manager' ),
|
137 |
+
'default' => __( 'Default date format as defined in Setttings', 'wp-job-manager' ),
|
138 |
+
)
|
139 |
),
|
140 |
array(
|
141 |
'name' => 'job_manager_enable_types',
|
142 |
'std' => '1',
|
143 |
'label' => __( 'Types', 'wp-job-manager' ),
|
144 |
+
'cb_label' => __( 'Enable types for listings', 'wp-job-manager' ),
|
145 |
+
'desc' => __( 'Choose whether to enable types. Types must be setup by an admin to allow users to choose them during submission.', 'wp-job-manager' ),
|
146 |
'type' => 'checkbox',
|
147 |
+
'attributes' => array()
|
148 |
),
|
149 |
array(
|
150 |
'name' => 'job_manager_multi_job_type',
|
151 |
'std' => '0',
|
152 |
'label' => __( 'Multi-select Listing Types', 'wp-job-manager' ),
|
153 |
+
'cb_label' => __( 'Enable multiple types for listings', 'wp-job-manager' ),
|
154 |
+
'desc' => __( 'If enabled each job can have more than one type. The metabox on the post editor and the select box on the frontend job submission form are changed by this.', 'wp-job-manager' ),
|
155 |
'type' => 'checkbox',
|
156 |
+
'attributes' => array()
|
157 |
+
),
|
158 |
+
array(
|
159 |
+
'name' => 'job_manager_google_maps_api_key',
|
160 |
+
'std' => '',
|
161 |
+
'label' => __( 'Google Maps API Key', 'wp-job-manager' ),
|
162 |
+
'desc' => sprintf( __( 'Google requires an API key to retrieve location information for job listings. Acquire an API key from the <a href="%s">Google Maps API developer site</a>.', 'wp-job-manager' ), 'https://developers.google.com/maps/documentation/geocoding/get-api-key' ),
|
163 |
+
'attributes' => array()
|
164 |
),
|
165 |
),
|
166 |
),
|
171 |
'name' => 'job_manager_user_requires_account',
|
172 |
'std' => '1',
|
173 |
'label' => __( 'Account Required', 'wp-job-manager' ),
|
174 |
+
'cb_label' => __( 'Submitting listings requires an account', 'wp-job-manager' ),
|
175 |
+
'desc' => __( 'If disabled, non-logged in users will be able to submit listings without creating an account.', 'wp-job-manager' ),
|
176 |
'type' => 'checkbox',
|
177 |
+
'attributes' => array()
|
178 |
),
|
179 |
array(
|
180 |
'name' => 'job_manager_enable_registration',
|
181 |
'std' => '1',
|
182 |
'label' => __( 'Account Creation', 'wp-job-manager' ),
|
183 |
+
'cb_label' => __( 'Allow account creation', 'wp-job-manager' ),
|
184 |
+
'desc' => __( 'If enabled, non-logged in users will be able to create an account by entering their email address on the submission form.', 'wp-job-manager' ),
|
185 |
'type' => 'checkbox',
|
186 |
+
'attributes' => array()
|
187 |
),
|
188 |
array(
|
189 |
'name' => 'job_manager_generate_username_from_email',
|
190 |
'std' => '1',
|
191 |
'label' => __( 'Account Username', 'wp-job-manager' ),
|
192 |
+
'cb_label' => __( 'Automatically Generate Username from Email Address', 'wp-job-manager' ),
|
193 |
+
'desc' => __( 'If enabled, a username will be generated from the first part of the user email address. Otherwise, a username field will be shown.', 'wp-job-manager' ),
|
194 |
'type' => 'checkbox',
|
195 |
+
'attributes' => array()
|
196 |
),
|
197 |
array(
|
198 |
+
'name' => 'job_manager_registration_role',
|
199 |
+
'std' => 'employer',
|
200 |
+
'label' => __( 'Account Role', 'wp-job-manager' ),
|
201 |
+
'desc' => __( 'If you enable registration on your submission form, choose a role for the new user.', 'wp-job-manager' ),
|
202 |
+
'type' => 'select',
|
203 |
+
'options' => $account_roles
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
),
|
205 |
array(
|
206 |
'name' => 'job_manager_submission_requires_approval',
|
207 |
'std' => '1',
|
208 |
'label' => __( 'Moderate New Listings', 'wp-job-manager' ),
|
209 |
+
'cb_label' => __( 'New listing submissions require admin approval', 'wp-job-manager' ),
|
210 |
+
'desc' => __( 'If enabled, new submissions will be inactive, pending admin approval.', 'wp-job-manager' ),
|
211 |
'type' => 'checkbox',
|
212 |
+
'attributes' => array()
|
213 |
),
|
214 |
array(
|
215 |
'name' => 'job_manager_user_can_edit_pending_submissions',
|
216 |
'std' => '0',
|
217 |
'label' => __( 'Allow Pending Edits', 'wp-job-manager' ),
|
218 |
+
'cb_label' => __( 'Submissions awaiting approval can be edited', 'wp-job-manager' ),
|
219 |
+
'desc' => __( 'If enabled, submissions awaiting admin approval can be edited by the user.', 'wp-job-manager' ),
|
220 |
'type' => 'checkbox',
|
221 |
+
'attributes' => array()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
),
|
223 |
array(
|
224 |
'name' => 'job_manager_submission_duration',
|
225 |
'std' => '30',
|
226 |
'label' => __( 'Listing Duration', 'wp-job-manager' ),
|
227 |
+
'desc' => __( 'How many <strong>days</strong> listings are live before expiring. Can be left blank to never expire.', 'wp-job-manager' ),
|
228 |
+
'attributes' => array()
|
229 |
),
|
230 |
array(
|
231 |
+
'name' => 'job_manager_allowed_application_method',
|
232 |
+
'std' => '',
|
233 |
+
'label' => __( 'Application Method', 'wp-job-manager' ),
|
234 |
+
'desc' => __( 'Choose the contact method for listings.', 'wp-job-manager' ),
|
235 |
+
'type' => 'select',
|
236 |
+
'options' => array(
|
237 |
'' => __( 'Email address or website URL', 'wp-job-manager' ),
|
238 |
'email' => __( 'Email addresses only', 'wp-job-manager' ),
|
239 |
'url' => __( 'Website URLs only', 'wp-job-manager' ),
|
240 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
241 |
),
|
242 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
),
|
244 |
+
'job_pages' => array(
|
245 |
__( 'Pages', 'wp-job-manager' ),
|
246 |
array(
|
247 |
array(
|
248 |
+
'name' => 'job_manager_submit_job_form_page_id',
|
249 |
+
'std' => '',
|
250 |
+
'label' => __( 'Submit Job Form Page', 'wp-job-manager' ),
|
251 |
+
'desc' => __( 'Select the page where you have placed the [submit_job_form] shortcode. This lets the plugin know where the form is located.', 'wp-job-manager' ),
|
252 |
+
'type' => 'page'
|
253 |
),
|
254 |
array(
|
255 |
+
'name' => 'job_manager_job_dashboard_page_id',
|
256 |
+
'std' => '',
|
257 |
+
'label' => __( 'Job Dashboard Page', 'wp-job-manager' ),
|
258 |
+
'desc' => __( 'Select the page where you have placed the [job_dashboard] shortcode. This lets the plugin know where the dashboard is located.', 'wp-job-manager' ),
|
259 |
+
'type' => 'page'
|
260 |
),
|
261 |
array(
|
262 |
+
'name' => 'job_manager_jobs_page_id',
|
263 |
+
'std' => '',
|
264 |
+
'label' => __( 'Job Listings Page', 'wp-job-manager' ),
|
265 |
+
'desc' => __( 'Select the page where you have placed the [jobs] shortcode. This lets the plugin know where the job listings page is located.', 'wp-job-manager' ),
|
266 |
+
'type' => 'page'
|
267 |
),
|
268 |
+
)
|
269 |
+
)
|
270 |
)
|
271 |
);
|
272 |
}
|
279 |
|
280 |
foreach ( $this->settings as $section ) {
|
281 |
foreach ( $section[1] as $option ) {
|
282 |
+
if ( isset( $option['std'] ) )
|
283 |
add_option( $option['name'], $option['std'] );
|
|
|
284 |
register_setting( $this->settings_group, $option['name'] );
|
285 |
}
|
286 |
}
|
293 |
$this->init_settings();
|
294 |
?>
|
295 |
<div class="wrap job-manager-settings-wrap">
|
296 |
+
<form method="post" action="options.php">
|
297 |
|
298 |
<?php settings_fields( $this->settings_group ); ?>
|
299 |
|
300 |
+
<h2 class="nav-tab-wrapper">
|
301 |
+
<?php
|
302 |
+
foreach ( $this->settings as $key => $section ) {
|
303 |
+
echo '<a href="#settings-' . sanitize_title( $key ) . '" class="nav-tab">' . esc_html( $section[0] ) . '</a>';
|
304 |
+
}
|
305 |
+
?>
|
306 |
+
</h2>
|
307 |
|
308 |
<?php
|
309 |
+
if ( ! empty( $_GET['settings-updated'] ) ) {
|
310 |
+
flush_rewrite_rules();
|
311 |
+
echo '<div class="updated fade job-manager-updated"><p>' . __( 'Settings successfully saved', 'wp-job-manager' ) . '</p></div>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
312 |
}
|
|
|
313 |
|
314 |
+
foreach ( $this->settings as $key => $section ) {
|
|
|
|
|
|
|
315 |
|
316 |
+
echo '<div id="settings-' . sanitize_title( $key ) . '" class="settings_panel">';
|
|
|
|
|
|
|
|
|
317 |
|
318 |
+
echo '<table class="form-table">';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
319 |
|
320 |
+
foreach ( $section[1] as $option ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
321 |
|
322 |
+
$placeholder = ( ! empty( $option['placeholder'] ) ) ? 'placeholder="' . $option['placeholder'] . '"' : '';
|
323 |
+
$class = ! empty( $option['class'] ) ? $option['class'] : '';
|
324 |
+
$value = get_option( $option['name'] );
|
325 |
+
$option['type'] = ! empty( $option['type'] ) ? $option['type'] : '';
|
326 |
+
$attributes = array();
|
327 |
|
328 |
+
if ( ! empty( $option['attributes'] ) && is_array( $option['attributes'] ) )
|
329 |
+
foreach ( $option['attributes'] as $attribute_name => $attribute_value )
|
330 |
+
$attributes[] = esc_attr( $attribute_name ) . '="' . esc_attr( $attribute_value ) . '"';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
331 |
|
332 |
+
echo '<tr valign="top" class="' . $class . '"><th scope="row"><label for="setting-' . $option['name'] . '">' . $option['label'] . '</a></th><td>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
333 |
|
334 |
+
switch ( $option['type'] ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
335 |
|
336 |
+
case "checkbox" :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
337 |
|
338 |
+
?><label><input id="setting-<?php echo $option['name']; ?>" name="<?php echo $option['name']; ?>" type="checkbox" value="1" <?php echo implode( ' ', $attributes ); ?> <?php checked( '1', $value ); ?> /> <?php echo $option['cb_label']; ?></label><?php
|
|
|
|
|
|
|
339 |
|
340 |
+
if ( $option['desc'] )
|
341 |
+
echo ' <p class="description">' . $option['desc'] . '</p>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
342 |
|
343 |
+
break;
|
344 |
+
case "textarea" :
|
|
|
|
|
345 |
|
346 |
+
?><textarea id="setting-<?php echo $option['name']; ?>" class="large-text" cols="50" rows="3" name="<?php echo $option['name']; ?>" <?php echo implode( ' ', $attributes ); ?> <?php echo $placeholder; ?>><?php echo esc_textarea( $value ); ?></textarea><?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
347 |
|
348 |
+
if ( $option['desc'] )
|
349 |
+
echo ' <p class="description">' . $option['desc'] . '</p>';
|
|
|
|
|
|
|
|
|
|
|
350 |
|
351 |
+
break;
|
352 |
+
case "select" :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
|
354 |
+
?><select id="setting-<?php echo $option['name']; ?>" class="regular-text" name="<?php echo $option['name']; ?>" <?php echo implode( ' ', $attributes ); ?>><?php
|
355 |
+
foreach( $option['options'] as $key => $name )
|
356 |
+
echo '<option value="' . esc_attr( $key ) . '" ' . selected( $value, $key, false ) . '>' . esc_html( $name ) . '</option>';
|
357 |
+
?></select><?php
|
358 |
|
359 |
+
if ( $option['desc'] ) {
|
360 |
+
echo ' <p class="description">' . $option['desc'] . '</p>';
|
361 |
+
}
|
|
|
362 |
|
363 |
+
break;
|
364 |
+
case "page" :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
365 |
|
366 |
+
$args = array(
|
367 |
+
'name' => $option['name'],
|
368 |
+
'id' => $option['name'],
|
369 |
+
'sort_column' => 'menu_order',
|
370 |
+
'sort_order' => 'ASC',
|
371 |
+
'show_option_none' => __( '--no page--', 'wp-job-manager' ),
|
372 |
+
'echo' => false,
|
373 |
+
'selected' => absint( $value )
|
374 |
+
);
|
375 |
|
376 |
+
echo str_replace(' id=', " data-placeholder='" . __( 'Select a page…', 'wp-job-manager' ) . "' id=", wp_dropdown_pages( $args ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
377 |
|
378 |
+
if ( $option['desc'] ) {
|
379 |
+
echo ' <p class="description">' . $option['desc'] . '</p>';
|
380 |
+
}
|
|
|
381 |
|
382 |
+
break;
|
383 |
+
case "password" :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
384 |
|
385 |
+
?><input id="setting-<?php echo $option['name']; ?>" class="regular-text" type="password" name="<?php echo $option['name']; ?>" value="<?php echo esc_attr( $value ); ?>" <?php echo implode( ' ', $attributes ); ?> <?php echo $placeholder; ?> /><?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
386 |
|
387 |
+
if ( $option['desc'] ) {
|
388 |
+
echo ' <p class="description">' . $option['desc'] . '</p>';
|
389 |
+
}
|
|
|
390 |
|
391 |
+
break;
|
392 |
+
case "number" :
|
393 |
+
?><input id="setting-<?php echo $option['name']; ?>" class="regular-text" type="number" name="<?php echo $option['name']; ?>" value="<?php echo esc_attr( $value ); ?>" <?php echo implode( ' ', $attributes ); ?> <?php echo $placeholder; ?> /><?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
394 |
|
395 |
+
if ( $option['desc'] ) {
|
396 |
+
echo ' <p class="description">' . $option['desc'] . '</p>';
|
397 |
+
}
|
398 |
+
break;
|
399 |
+
case "" :
|
400 |
+
case "input" :
|
401 |
+
case "text" :
|
402 |
+
?><input id="setting-<?php echo $option['name']; ?>" class="regular-text" type="text" name="<?php echo $option['name']; ?>" value="<?php echo esc_attr( $value ); ?>" <?php echo implode( ' ', $attributes ); ?> <?php echo $placeholder; ?> /><?php
|
403 |
|
404 |
+
if ( $option['desc'] ) {
|
405 |
+
echo ' <p class="description">' . $option['desc'] . '</p>';
|
406 |
+
}
|
407 |
+
break;
|
408 |
+
default :
|
409 |
+
do_action( 'wp_job_manager_admin_field_' . $option['type'], $option, $attributes, $value, $placeholder );
|
410 |
+
break;
|
411 |
|
412 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
413 |
|
414 |
+
echo '</td></tr>';
|
415 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
416 |
|
417 |
+
echo '</table></div>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
418 |
|
419 |
+
}
|
420 |
+
?>
|
421 |
+
<p class="submit">
|
422 |
+
<input type="submit" class="button-primary" value="<?php _e( 'Save Changes', 'wp-job-manager' ); ?>" />
|
423 |
+
</p>
|
424 |
+
</form>
|
425 |
+
</div>
|
426 |
+
<script type="text/javascript">
|
427 |
+
jQuery('.nav-tab-wrapper a').click(function() {
|
428 |
+
jQuery('.settings_panel').hide();
|
429 |
+
jQuery('.nav-tab-active').removeClass('nav-tab-active');
|
430 |
+
jQuery( jQuery(this).attr('href') ).show();
|
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>
|
445 |
+
<?php
|
446 |
}
|
447 |
}
|
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 |
*/
|
@@ -40,16 +40,15 @@ class WP_Job_Manager_Setup {
|
|
40 |
add_action( 'admin_menu', array( $this, 'admin_menu' ), 12 );
|
41 |
add_action( 'admin_head', array( $this, 'admin_head' ) );
|
42 |
add_action( 'admin_init', array( $this, 'redirect' ) );
|
43 |
-
if ( isset( $_GET['page'] ) && 'job-manager-setup'
|
44 |
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 12 );
|
45 |
-
}
|
46 |
}
|
47 |
|
48 |
/**
|
49 |
* Adds setup link to admin dashboard menu briefly so the page callback is registered.
|
50 |
*/
|
51 |
public function admin_menu() {
|
52 |
-
add_dashboard_page( __( 'Setup', 'wp-job-manager' ), __( 'Setup', 'wp-job-manager' ), 'manage_options', 'job-manager-setup', array( $this, '
|
53 |
}
|
54 |
|
55 |
/**
|
@@ -63,24 +62,24 @@ class WP_Job_Manager_Setup {
|
|
63 |
* Sends user to the setup page on first activation.
|
64 |
*/
|
65 |
public function redirect() {
|
66 |
-
// Bail if no activation redirect transient is set
|
67 |
-
|
68 |
return;
|
69 |
-
|
70 |
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
|
75 |
-
// Delete the redirect transient
|
76 |
delete_transient( '_job_manager_activation_redirect' );
|
77 |
|
78 |
-
// Bail if activating from network, or bulk, or within an iFrame
|
79 |
if ( is_network_admin() || isset( $_GET['activate-multi'] ) || defined( 'IFRAME_REQUEST' ) ) {
|
80 |
return;
|
81 |
}
|
82 |
|
83 |
-
if ( ( isset( $_GET['action'] ) && 'upgrade-plugin'
|
84 |
return;
|
85 |
}
|
86 |
|
@@ -111,70 +110,15 @@ class WP_Job_Manager_Setup {
|
|
111 |
'post_title' => $title,
|
112 |
'post_content' => $content,
|
113 |
'post_parent' => 0,
|
114 |
-
'comment_status' => 'closed'
|
115 |
);
|
116 |
-
$page_id
|
117 |
|
118 |
if ( $option ) {
|
119 |
update_option( $option, $page_id );
|
120 |
}
|
121 |
}
|
122 |
|
123 |
-
/**
|
124 |
-
* Handle request to the setup page.
|
125 |
-
*/
|
126 |
-
public function setup_page() {
|
127 |
-
$usage_tracking = WP_Job_Manager_Usage_Tracking::get_instance();
|
128 |
-
|
129 |
-
if ( 'POST' === $_SERVER['REQUEST_METHOD'] ) {
|
130 |
-
$enable = isset( $_POST['job_manager_usage_tracking_enabled'] )
|
131 |
-
&& '1' === $_POST['job_manager_usage_tracking_enabled'];
|
132 |
-
|
133 |
-
$nonce = isset( $_POST['nonce'] ) ? $_POST['nonce'] : null;
|
134 |
-
$valid_nonce = wp_verify_nonce( $nonce, 'enable-usage-tracking' );
|
135 |
-
|
136 |
-
if ( $valid_nonce ) {
|
137 |
-
$usage_tracking->set_tracking_enabled( $enable );
|
138 |
-
$usage_tracking->hide_tracking_opt_in();
|
139 |
-
}
|
140 |
-
}
|
141 |
-
|
142 |
-
$this->output();
|
143 |
-
}
|
144 |
-
|
145 |
-
/**
|
146 |
-
* Usage tracking opt in text for setup page.
|
147 |
-
*/
|
148 |
-
private function opt_in_text() {
|
149 |
-
return WP_Job_Manager_Usage_Tracking::get_instance()->opt_in_checkbox_text();
|
150 |
-
}
|
151 |
-
|
152 |
-
/**
|
153 |
-
* Output opt-in checkbox if usage tracking isn't already enabled.
|
154 |
-
*/
|
155 |
-
private function maybe_output_opt_in_checkbox() {
|
156 |
-
// Only show the checkbox if we aren't already opted in.
|
157 |
-
$usage_tracking = WP_Job_Manager_Usage_Tracking::get_instance();
|
158 |
-
if ( ! $usage_tracking->get_tracking_enabled() ) {
|
159 |
-
?>
|
160 |
-
<p>
|
161 |
-
<label>
|
162 |
-
<input
|
163 |
-
type="checkbox"
|
164 |
-
name="job_manager_usage_tracking_enabled"
|
165 |
-
value="1" />
|
166 |
-
<?php
|
167 |
-
echo wp_kses(
|
168 |
-
$this->opt_in_text(),
|
169 |
-
$usage_tracking->opt_in_dialog_text_allowed_html()
|
170 |
-
);
|
171 |
-
?>
|
172 |
-
</label>
|
173 |
-
</p>
|
174 |
-
<?php
|
175 |
-
}
|
176 |
-
}
|
177 |
-
|
178 |
/**
|
179 |
* Displays setup page.
|
180 |
*/
|
@@ -182,15 +126,14 @@ class WP_Job_Manager_Setup {
|
|
182 |
$step = ! empty( $_GET['step'] ) ? absint( $_GET['step'] ) : 1;
|
183 |
|
184 |
if ( 3 === $step && ! empty( $_POST ) ) {
|
185 |
-
if ( false
|
186 |
wp_die( 'Error in nonce. Try again.', 'wp-job-manager' );
|
187 |
-
}
|
188 |
$create_pages = isset( $_POST['wp-job-manager-create-page'] ) ? $_POST['wp-job-manager-create-page'] : array();
|
189 |
$page_titles = $_POST['wp-job-manager-page-title'];
|
190 |
$pages_to_create = array(
|
191 |
'submit_job_form' => '[submit_job_form]',
|
192 |
'job_dashboard' => '[job_dashboard]',
|
193 |
-
'jobs' => '[jobs]'
|
194 |
);
|
195 |
|
196 |
foreach ( $pages_to_create as $page => $content ) {
|
@@ -202,60 +145,33 @@ class WP_Job_Manager_Setup {
|
|
202 |
}
|
203 |
?>
|
204 |
<div class="wrap wp_job_manager wp_job_manager_addons_wrap">
|
205 |
-
<h2><?php
|
206 |
|
207 |
<ul class="wp-job-manager-setup-steps">
|
208 |
-
<?php
|
209 |
-
|
210 |
-
|
211 |
-
?>
|
212 |
-
<li class="<?php echo sanitize_html_class( $step_classes[1] ); ?>"><?php esc_html_e( '1. Introduction', 'wp-job-manager' ); ?></li>
|
213 |
-
<li class="<?php echo sanitize_html_class( $step_classes[2] ); ?>"><?php esc_html_e( '2. Page Setup', 'wp-job-manager' ); ?></li>
|
214 |
-
<li class="<?php echo sanitize_html_class( $step_classes[3] ); ?>"><?php esc_html_e( '3. Done', 'wp-job-manager' ); ?></li>
|
215 |
</ul>
|
216 |
|
217 |
<?php if ( 1 === $step ) : ?>
|
218 |
|
219 |
-
<h3><?php
|
220 |
-
|
221 |
-
<p><?php echo wp_kses_post( __( 'Thanks for installing <em>WP Job Manager</em>! Let\'s get your site ready to accept job listings.', 'wp-job-manager' ) ); ?></p>
|
222 |
-
<p><?php echo wp_kses_post( __( 'This setup wizard will walk you through the process of creating pages for job submissions, management, and listings.', 'wp-job-manager' ) ); ?></p>
|
223 |
-
<p>
|
224 |
-
<?php
|
225 |
-
// translators: Placeholder %s is the path to WPJM documentation site.
|
226 |
-
echo wp_kses_post( sprintf( __( 'If you\'d prefer to skip this and set up your pages manually, our <a href="%s">documentation</a> will walk you through each step.', 'wp-job-manager' ), 'https://wpjobmanager.com/documentation/' ) );
|
227 |
-
?>
|
228 |
-
</p>
|
229 |
|
230 |
-
<
|
231 |
-
|
|
|
232 |
|
233 |
-
|
234 |
-
|
235 |
-
<
|
236 |
-
|
237 |
-
<a href="<?php echo esc_url( add_query_arg( 'skip-job-manager-setup', 1, admin_url( 'index.php?page=job-manager-setup&step=3' ) ) ); ?>" class="button"><?php esc_html_e( 'Skip setup. I will set up the plugin manually.', 'wp-job-manager' ); ?></a>
|
238 |
-
</p>
|
239 |
-
</form>
|
240 |
|
241 |
<?php endif; ?>
|
242 |
<?php if ( 2 === $step ) : ?>
|
243 |
|
244 |
-
<h3><?php
|
245 |
-
|
246 |
-
<p><?php
|
247 |
-
<p>
|
248 |
-
<?php
|
249 |
-
echo wp_kses_post( sprintf(
|
250 |
-
// translators: %1$s is URL to WordPress core shortcode documentation. %2$s is URL to WPJM specific shortcode reference.
|
251 |
-
__( '(These pages are created using <a href="%1$s" title="What is a shortcode?" target="_blank" class="help-page-link">shortcodes</a>,
|
252 |
-
which we take care of in this step. If you\'d like to build these pages yourself or want to add one of these options to an existing
|
253 |
-
page on your site, you can skip this step and take a look at <a href="%2$s" target="_blank" class="help-page-link">shortcode documentation</a> for detailed instructions.)', 'wp-job-manager' ),
|
254 |
-
'http://codex.wordpress.org/Shortcode',
|
255 |
-
'https://wpjobmanager.com/document/shortcode-reference/'
|
256 |
-
) );
|
257 |
-
?>
|
258 |
-
</p>
|
259 |
|
260 |
<form action="<?php echo esc_url( add_query_arg( 'step', 3 ) ); ?>" method="post">
|
261 |
<?php wp_nonce_field( 'step_3', 'setup_wizard' ); ?>
|
@@ -263,9 +179,9 @@ class WP_Job_Manager_Setup {
|
|
263 |
<thead>
|
264 |
<tr>
|
265 |
<th> </th>
|
266 |
-
<th><?php
|
267 |
-
<th><?php
|
268 |
-
<th><?php
|
269 |
</tr>
|
270 |
</thead>
|
271 |
<tbody>
|
@@ -273,7 +189,9 @@ class WP_Job_Manager_Setup {
|
|
273 |
<td><input type="checkbox" checked="checked" name="wp-job-manager-create-page[submit_job_form]" /></td>
|
274 |
<td><input type="text" value="<?php echo esc_attr( _x( 'Post a Job', 'Default page title (wizard)', 'wp-job-manager' ) ); ?>" name="wp-job-manager-page-title[submit_job_form]" /></td>
|
275 |
<td>
|
276 |
-
<p><?php
|
|
|
|
|
277 |
</td>
|
278 |
<td><code>[submit_job_form]</code></td>
|
279 |
</tr>
|
@@ -281,14 +199,16 @@ class WP_Job_Manager_Setup {
|
|
281 |
<td><input type="checkbox" checked="checked" name="wp-job-manager-create-page[job_dashboard]" /></td>
|
282 |
<td><input type="text" value="<?php echo esc_attr( _x( 'Job Dashboard', 'Default page title (wizard)', 'wp-job-manager' ) ); ?>" name="wp-job-manager-page-title[job_dashboard]" /></td>
|
283 |
<td>
|
284 |
-
<p><?php
|
|
|
|
|
285 |
</td>
|
286 |
<td><code>[job_dashboard]</code></td>
|
287 |
</tr>
|
288 |
<tr>
|
289 |
<td><input type="checkbox" checked="checked" name="wp-job-manager-create-page[jobs]" /></td>
|
290 |
<td><input type="text" value="<?php echo esc_attr( _x( 'Jobs', 'Default page title (wizard)', 'wp-job-manager' ) ); ?>" name="wp-job-manager-page-title[jobs]" /></td>
|
291 |
-
<td><?php
|
292 |
<td><code>[jobs]</code></td>
|
293 |
</tr>
|
294 |
</tbody>
|
@@ -296,7 +216,7 @@ class WP_Job_Manager_Setup {
|
|
296 |
<tr>
|
297 |
<th colspan="4">
|
298 |
<input type="submit" class="button button-primary" value="Create selected pages" />
|
299 |
-
<a href="<?php echo esc_url( add_query_arg( 'step', 3 ) ); ?>" class="button"><?php
|
300 |
</th>
|
301 |
</tr>
|
302 |
</tfoot>
|
@@ -306,64 +226,43 @@ class WP_Job_Manager_Setup {
|
|
306 |
<?php endif; ?>
|
307 |
<?php if ( 3 === $step ) : ?>
|
308 |
|
309 |
-
<h3><?php
|
310 |
|
311 |
-
<p><?php
|
312 |
|
313 |
<ul class="wp-job-manager-next-steps">
|
314 |
-
<li><a href="<?php echo
|
315 |
-
<li><a href="<?php echo
|
316 |
-
|
317 |
-
$permalink = job_manager_get_permalink( '
|
318 |
-
|
319 |
-
|
320 |
-
<li><a href="
|
321 |
-
<?php
|
322 |
-
|
323 |
-
<?php
|
324 |
-
|
325 |
-
<?php
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
<?php
|
335 |
-
$permalink = job_manager_get_permalink( 'job_dashboard' );
|
336 |
-
if ( $permalink ) {
|
337 |
-
?>
|
338 |
-
<li><a href="<?php echo esc_url( $permalink ); ?>"><?php esc_html_e( 'View the job dashboard', 'wp-job-manager' ); ?></a></li>
|
339 |
-
<?php } else { ?>
|
340 |
-
<li><a href="https://wpjobmanager.com/document/the-job-dashboard/"><?php esc_html_e( 'Learn to use the front-end job dashboard', 'wp-job-manager' ); ?></a></li>
|
341 |
-
<?php } ?>
|
342 |
</ul>
|
343 |
|
344 |
-
<p>
|
345 |
-
<?php
|
346 |
-
echo wp_kses_post(
|
347 |
-
sprintf(
|
348 |
-
// translators: %1$s is the URL to WPJM support documentation; %2$s is the URL to WPJM support forums.
|
349 |
-
__( 'If you need help, you can find more detail in our
|
350 |
-
<a href="%1$s">support documentation</a> or post your question on the
|
351 |
-
<a href="%2$s">WP Job Manager support forums</a>. Happy hiring!', 'wp-job-manager' ),
|
352 |
-
'https://wpjobmanager.com/documentation/',
|
353 |
-
'https://wordpress.org/support/plugin/wp-job-manager'
|
354 |
-
)
|
355 |
-
);
|
356 |
-
?>
|
357 |
-
</p>
|
358 |
|
359 |
<div class="wp-job-manager-support-the-plugin">
|
360 |
-
<h3><?php
|
361 |
-
<p><?php
|
362 |
<ul>
|
363 |
-
<li class="icon-review"><a href="https://wordpress.org/support/view/plugin-reviews/wp-job-manager#postform"><?php
|
364 |
-
<li class="icon-localization"><a href="https://translate.wordpress.org/projects/wp-plugins/wp-job-manager"><?php
|
365 |
-
<li class="icon-code"><a href="https://github.com/mikejolley/WP-Job-Manager"><?php
|
366 |
-
<li class="icon-forum"><a href="https://wordpress.org/support/plugin/wp-job-manager"><?php
|
367 |
</ul>
|
368 |
</div>
|
369 |
|
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 |
*/
|
40 |
add_action( 'admin_menu', array( $this, 'admin_menu' ), 12 );
|
41 |
add_action( 'admin_head', array( $this, 'admin_head' ) );
|
42 |
add_action( 'admin_init', array( $this, 'redirect' ) );
|
43 |
+
if ( isset( $_GET[ 'page' ] ) && $_GET[ 'page' ] == 'job-manager-setup' )
|
44 |
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 12 );
|
|
|
45 |
}
|
46 |
|
47 |
/**
|
48 |
* Adds setup link to admin dashboard menu briefly so the page callback is registered.
|
49 |
*/
|
50 |
public function admin_menu() {
|
51 |
+
add_dashboard_page( __( 'Setup', 'wp-job-manager' ), __( 'Setup', 'wp-job-manager' ), 'manage_options', 'job-manager-setup', array( $this, 'output' ) );
|
52 |
}
|
53 |
|
54 |
/**
|
62 |
* Sends user to the setup page on first activation.
|
63 |
*/
|
64 |
public function redirect() {
|
65 |
+
// Bail if no activation redirect transient is set
|
66 |
+
if ( ! get_transient( '_job_manager_activation_redirect' ) ) {
|
67 |
return;
|
68 |
+
}
|
69 |
|
70 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
71 |
+
return;
|
72 |
+
}
|
73 |
|
74 |
+
// Delete the redirect transient
|
75 |
delete_transient( '_job_manager_activation_redirect' );
|
76 |
|
77 |
+
// Bail if activating from network, or bulk, or within an iFrame
|
78 |
if ( is_network_admin() || isset( $_GET['activate-multi'] ) || defined( 'IFRAME_REQUEST' ) ) {
|
79 |
return;
|
80 |
}
|
81 |
|
82 |
+
if ( ( isset( $_GET['action'] ) && 'upgrade-plugin' == $_GET['action'] ) && ( isset( $_GET['plugin'] ) && strstr( $_GET['plugin'], 'wp-job-manager.php' ) ) ) {
|
83 |
return;
|
84 |
}
|
85 |
|
110 |
'post_title' => $title,
|
111 |
'post_content' => $content,
|
112 |
'post_parent' => 0,
|
113 |
+
'comment_status' => 'closed'
|
114 |
);
|
115 |
+
$page_id = wp_insert_post( $page_data );
|
116 |
|
117 |
if ( $option ) {
|
118 |
update_option( $option, $page_id );
|
119 |
}
|
120 |
}
|
121 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
/**
|
123 |
* Displays setup page.
|
124 |
*/
|
126 |
$step = ! empty( $_GET['step'] ) ? absint( $_GET['step'] ) : 1;
|
127 |
|
128 |
if ( 3 === $step && ! empty( $_POST ) ) {
|
129 |
+
if ( false == wp_verify_nonce( $_REQUEST[ 'setup_wizard' ], 'step_3' ) )
|
130 |
wp_die( 'Error in nonce. Try again.', 'wp-job-manager' );
|
|
|
131 |
$create_pages = isset( $_POST['wp-job-manager-create-page'] ) ? $_POST['wp-job-manager-create-page'] : array();
|
132 |
$page_titles = $_POST['wp-job-manager-page-title'];
|
133 |
$pages_to_create = array(
|
134 |
'submit_job_form' => '[submit_job_form]',
|
135 |
'job_dashboard' => '[job_dashboard]',
|
136 |
+
'jobs' => '[jobs]'
|
137 |
);
|
138 |
|
139 |
foreach ( $pages_to_create as $page => $content ) {
|
145 |
}
|
146 |
?>
|
147 |
<div class="wrap wp_job_manager wp_job_manager_addons_wrap">
|
148 |
+
<h2><?php _e( 'WP Job Manager Setup', 'wp-job-manager' ); ?></h2>
|
149 |
|
150 |
<ul class="wp-job-manager-setup-steps">
|
151 |
+
<li class="<?php if ( $step === 1 ) echo 'wp-job-manager-setup-active-step'; ?>"><?php _e( '1. Introduction', 'wp-job-manager' ); ?></li>
|
152 |
+
<li class="<?php if ( $step === 2 ) echo 'wp-job-manager-setup-active-step'; ?>"><?php _e( '2. Page Setup', 'wp-job-manager' ); ?></li>
|
153 |
+
<li class="<?php if ( $step === 3 ) echo 'wp-job-manager-setup-active-step'; ?>"><?php _e( '3. Done', 'wp-job-manager' ); ?></li>
|
|
|
|
|
|
|
|
|
154 |
</ul>
|
155 |
|
156 |
<?php if ( 1 === $step ) : ?>
|
157 |
|
158 |
+
<h3><?php _e( 'Setup Wizard Introduction', 'wp-job-manager' ); ?></h3>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
159 |
|
160 |
+
<p><?php _e( 'Thanks for installing <em>WP Job Manager</em>!', 'wp-job-manager' ); ?></p>
|
161 |
+
<p><?php _e( 'This setup wizard will help you get started by creating the pages for job submission, job management, and listing your jobs.', 'wp-job-manager' ); ?></p>
|
162 |
+
<p><?php printf( __( 'If you want to skip the wizard and setup the pages and shortcodes yourself manually, the process is still relatively simple. Refer to the %sdocumentation%s for help.', 'wp-job-manager' ), '<a href="https://wpjobmanager.com/documentation/">', '</a>' ); ?></p>
|
163 |
|
164 |
+
<p class="submit">
|
165 |
+
<a href="<?php echo esc_url( add_query_arg( 'step', 2 ) ); ?>" class="button button-primary"><?php _e( 'Continue to page setup', 'wp-job-manager' ); ?></a>
|
166 |
+
<a href="<?php echo esc_url( add_query_arg( 'skip-job-manager-setup', 1, admin_url( 'index.php?page=job-manager-setup&step=3' ) ) ); ?>" class="button"><?php _e( 'Skip setup. I will setup the plugin manually', 'wp-job-manager' ); ?></a>
|
167 |
+
</p>
|
|
|
|
|
|
|
168 |
|
169 |
<?php endif; ?>
|
170 |
<?php if ( 2 === $step ) : ?>
|
171 |
|
172 |
+
<h3><?php _e( 'Page Setup', 'wp-job-manager' ); ?></h3>
|
173 |
+
|
174 |
+
<p><?php printf( __( '<em>WP Job Manager</em> includes %1$sshortcodes%2$s which can be used within your %3$spages%2$s to output content. These can be created for you below. For more information on the job shortcodes view the %4$sshortcode documentation%2$s.', 'wp-job-manager' ), '<a href="http://codex.wordpress.org/Shortcode" title="What is a shortcode?" target="_blank" class="help-page-link">', '</a>', '<a href="http://codex.wordpress.org/Pages" target="_blank" class="help-page-link">', '<a href="https://wpjobmanager.com/document/shortcode-reference/" target="_blank" class="help-page-link">' ); ?></p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
|
176 |
<form action="<?php echo esc_url( add_query_arg( 'step', 3 ) ); ?>" method="post">
|
177 |
<?php wp_nonce_field( 'step_3', 'setup_wizard' ); ?>
|
179 |
<thead>
|
180 |
<tr>
|
181 |
<th> </th>
|
182 |
+
<th><?php _e( 'Page Title', 'wp-job-manager' ); ?></th>
|
183 |
+
<th><?php _e( 'Page Description', 'wp-job-manager' ); ?></th>
|
184 |
+
<th><?php _e( 'Content Shortcode', 'wp-job-manager' ); ?></th>
|
185 |
</tr>
|
186 |
</thead>
|
187 |
<tbody>
|
189 |
<td><input type="checkbox" checked="checked" name="wp-job-manager-create-page[submit_job_form]" /></td>
|
190 |
<td><input type="text" value="<?php echo esc_attr( _x( 'Post a Job', 'Default page title (wizard)', 'wp-job-manager' ) ); ?>" name="wp-job-manager-page-title[submit_job_form]" /></td>
|
191 |
<td>
|
192 |
+
<p><?php _e( 'This page allows employers to post jobs to your website from the front-end.', 'wp-job-manager' ); ?></p>
|
193 |
+
|
194 |
+
<p><?php _e( 'If you do not want to accept submissions from users in this way (for example you just want to post jobs from the admin dashboard) you can skip creating this page.', 'wp-job-manager' ); ?></p>
|
195 |
</td>
|
196 |
<td><code>[submit_job_form]</code></td>
|
197 |
</tr>
|
199 |
<td><input type="checkbox" checked="checked" name="wp-job-manager-create-page[job_dashboard]" /></td>
|
200 |
<td><input type="text" value="<?php echo esc_attr( _x( 'Job Dashboard', 'Default page title (wizard)', 'wp-job-manager' ) ); ?>" name="wp-job-manager-page-title[job_dashboard]" /></td>
|
201 |
<td>
|
202 |
+
<p><?php _e( 'This page allows employers to manage and edit their own jobs from the front-end.', 'wp-job-manager' ); ?></p>
|
203 |
+
|
204 |
+
<p><?php _e( 'If you plan on managing all listings from the admin dashboard you can skip creating this page.', 'wp-job-manager' ); ?></p>
|
205 |
</td>
|
206 |
<td><code>[job_dashboard]</code></td>
|
207 |
</tr>
|
208 |
<tr>
|
209 |
<td><input type="checkbox" checked="checked" name="wp-job-manager-create-page[jobs]" /></td>
|
210 |
<td><input type="text" value="<?php echo esc_attr( _x( 'Jobs', 'Default page title (wizard)', 'wp-job-manager' ) ); ?>" name="wp-job-manager-page-title[jobs]" /></td>
|
211 |
+
<td><?php _e( 'This page allows users to browse, search, and filter job listings on the front-end of your site.', 'wp-job-manager' ); ?></td>
|
212 |
<td><code>[jobs]</code></td>
|
213 |
</tr>
|
214 |
</tbody>
|
216 |
<tr>
|
217 |
<th colspan="4">
|
218 |
<input type="submit" class="button button-primary" value="Create selected pages" />
|
219 |
+
<a href="<?php echo esc_url( add_query_arg( 'step', 3 ) ); ?>" class="button"><?php _e( 'Skip this step', 'wp-job-manager' ); ?></a>
|
220 |
</th>
|
221 |
</tr>
|
222 |
</tfoot>
|
226 |
<?php endif; ?>
|
227 |
<?php if ( 3 === $step ) : ?>
|
228 |
|
229 |
+
<h3><?php _e( 'All Done!', 'wp-job-manager' ); ?></h3>
|
230 |
|
231 |
+
<p><?php _e( 'Looks like you\'re all set to start using the plugin. In case you\'re wondering where to go next:', 'wp-job-manager' ); ?></p>
|
232 |
|
233 |
<ul class="wp-job-manager-next-steps">
|
234 |
+
<li><a href="<?php echo admin_url( 'edit.php?post_type=job_listing&page=job-manager-settings' ); ?>"><?php _e( 'Tweak the plugin settings', 'wp-job-manager' ); ?></a></li>
|
235 |
+
<li><a href="<?php echo admin_url( 'post-new.php?post_type=job_listing' ); ?>"><?php _e( 'Add a job via the back-end', 'wp-job-manager' ); ?></a></li>
|
236 |
+
|
237 |
+
<?php if ( $permalink = job_manager_get_permalink( 'submit_job_form' ) ) : ?>
|
238 |
+
<li><a href="<?php echo esc_url( $permalink ); ?>"><?php _e( 'Add a job via the front-end', 'wp-job-manager' ); ?></a></li>
|
239 |
+
<?php else : ?>
|
240 |
+
<li><a href="https://wpjobmanager.com/document/the-job-submission-form/"><?php _e( 'Find out more about the front-end job submission form', 'wp-job-manager' ); ?></a></li>
|
241 |
+
<?php endif; ?>
|
242 |
+
|
243 |
+
<?php if ( $permalink = job_manager_get_permalink( 'jobs' ) ) : ?>
|
244 |
+
<li><a href="<?php echo esc_url( $permalink ); ?>"><?php _e( 'View submitted job listings', 'wp-job-manager' ); ?></a></li>
|
245 |
+
<?php else : ?>
|
246 |
+
<li><a href="https://wpjobmanager.com/document/shortcode-reference/#section-1"><?php _e( 'Add the [jobs] shortcode to a page to list jobs', 'wp-job-manager' ); ?></a></li>
|
247 |
+
<?php endif; ?>
|
248 |
+
|
249 |
+
<?php if ( $permalink = job_manager_get_permalink( 'job_dashboard' ) ) : ?>
|
250 |
+
<li><a href="<?php echo esc_url( $permalink ); ?>"><?php _e( 'View the job dashboard', 'wp-job-manager' ); ?></a></li>
|
251 |
+
<?php else : ?>
|
252 |
+
<li><a href="https://wpjobmanager.com/document/the-job-dashboard/"><?php _e( 'Find out more about the front-end job dashboard', 'wp-job-manager' ); ?></a></li>
|
253 |
+
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
254 |
</ul>
|
255 |
|
256 |
+
<p><?php printf( __( 'And don\'t forget, if you need any more help using <em>WP Job Manager</em> you can consult the %1$sdocumentation%2$s or %3$spost on the forums%2$s!', 'wp-job-manager' ), '<a href="https://wpjobmanager.com/documentation/">', '</a>', '<a href="https://wordpress.org/support/plugin/wp-job-manager">' ); ?></p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
|
258 |
<div class="wp-job-manager-support-the-plugin">
|
259 |
+
<h3><?php _e( 'Support the Ongoing Development of this Plugin', 'wp-job-manager' ); ?></h3>
|
260 |
+
<p><?php _e( 'There are many ways to support open-source projects such as WP Job Manager, for example code contribution, translation, or even telling your friends how awesome the plugin (hopefully) is. Thanks in advance for your support - it is much appreciated!', 'wp-job-manager' ); ?></p>
|
261 |
<ul>
|
262 |
+
<li class="icon-review"><a href="https://wordpress.org/support/view/plugin-reviews/wp-job-manager#postform"><?php _e( 'Leave a positive review', 'wp-job-manager' ); ?></a></li>
|
263 |
+
<li class="icon-localization"><a href="https://translate.wordpress.org/projects/wp-plugins/wp-job-manager"><?php _e( 'Contribute a localization', 'wp-job-manager' ); ?></a></li>
|
264 |
+
<li class="icon-code"><a href="https://github.com/mikejolley/WP-Job-Manager"><?php _e( 'Contribute code or report a bug', 'wp-job-manager' ); ?></a></li>
|
265 |
+
<li class="icon-forum"><a href="https://wordpress.org/support/plugin/wp-job-manager"><?php _e( 'Help other users on the forums', 'wp-job-manager' ); ?></a></li>
|
266 |
</ul>
|
267 |
</div>
|
268 |
|
includes/admin/class-wp-job-manager-taxonomy-meta.php
DELETED
@@ -1,158 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
-
exit;
|
4 |
-
}
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Handles taxonomy meta custom fields. Just used for job type.
|
8 |
-
*
|
9 |
-
* @package wp-job-manager
|
10 |
-
* @since 1.28.0
|
11 |
-
*/
|
12 |
-
class WP_Job_Manager_Taxonomy_Meta {
|
13 |
-
/**
|
14 |
-
* The single instance of the class.
|
15 |
-
*
|
16 |
-
* @var self
|
17 |
-
* @since 1.28.0
|
18 |
-
*/
|
19 |
-
private static $_instance = null;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Allows for accessing single instance of class. Class should only be constructed once per call.
|
23 |
-
*
|
24 |
-
* @since 1.28.0
|
25 |
-
* @static
|
26 |
-
* @return self Main instance.
|
27 |
-
*/
|
28 |
-
public static function instance() {
|
29 |
-
if ( is_null( self::$_instance ) ) {
|
30 |
-
self::$_instance = new self();
|
31 |
-
}
|
32 |
-
return self::$_instance;
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* WP_Job_Manager_Taxonomy_Meta constructor.
|
37 |
-
*/
|
38 |
-
public function __construct() {
|
39 |
-
if ( wpjm_job_listing_employment_type_enabled() ) {
|
40 |
-
add_action( 'job_listing_type_edit_form_fields', array( $this, 'display_schema_org_employment_type_field' ), 10, 2 );
|
41 |
-
add_action( 'job_listing_type_add_form_fields', array( $this, 'add_form_display_schema_org_employment_type_field' ), 10 );
|
42 |
-
add_action( 'edited_job_listing_type', array( $this, 'set_schema_org_employment_type_field' ), 10, 2 );
|
43 |
-
add_action( 'created_job_listing_type', array( $this, 'set_schema_org_employment_type_field' ), 10, 2 );
|
44 |
-
add_filter( 'manage_edit-job_listing_type_columns', array( $this, 'add_employment_type_column' ) );
|
45 |
-
add_filter( 'manage_job_listing_type_custom_column', array( $this, 'add_employment_type_column_content' ), 10, 3 );
|
46 |
-
add_filter( 'manage_edit-job_listing_type_sortable_columns', array( $this, 'add_employment_type_column_sortable' ) );
|
47 |
-
}
|
48 |
-
}
|
49 |
-
|
50 |
-
/**
|
51 |
-
* Set the employment type field when creating/updating a job type item.
|
52 |
-
*
|
53 |
-
* @param int $term_id Term ID.
|
54 |
-
* @param int $tt_id Taxonomy type ID.
|
55 |
-
*/
|
56 |
-
public function set_schema_org_employment_type_field( $term_id, $tt_id ) {
|
57 |
-
$employment_types = wpjm_job_listing_employment_type_options();
|
58 |
-
if ( isset( $_POST['employment_type'] ) && isset( $employment_types[ $_POST['employment_type'] ] ) ) {
|
59 |
-
update_term_meta( $term_id, 'employment_type', $_POST['employment_type'] );
|
60 |
-
} elseif ( isset( $_POST['employment_type'] ) ) {
|
61 |
-
delete_term_meta( $term_id, 'employment_type' );
|
62 |
-
}
|
63 |
-
}
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Add the option to select schema.org employmentType for job type on the edit meta field form.
|
67 |
-
*
|
68 |
-
* @param WP_Term $term Term object.
|
69 |
-
* @param string $taxonomy Taxonomy slug.
|
70 |
-
*/
|
71 |
-
public function display_schema_org_employment_type_field( $term, $taxonomy ) {
|
72 |
-
$employment_types = wpjm_job_listing_employment_type_options();
|
73 |
-
$current_employment_type = get_term_meta( $term->term_id, 'employment_type', true );
|
74 |
-
|
75 |
-
if ( ! empty( $employment_types ) ) {
|
76 |
-
?>
|
77 |
-
<tr class="form-field term-group-wrap">
|
78 |
-
<th scope="row"><label for="feature-group"><?php esc_html_e( 'Employment Type', 'wp-job-manager' ); ?></label></th>
|
79 |
-
<td><select class="postform" id="employment_type" name="employment_type">
|
80 |
-
<option value=""></option>
|
81 |
-
<?php foreach ( $employment_types as $key => $employment_type ) : ?>
|
82 |
-
<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $current_employment_type, $key ); ?>><?php echo esc_html( $employment_type ); ?></option>
|
83 |
-
<?php endforeach; ?>
|
84 |
-
</select></td>
|
85 |
-
</tr>
|
86 |
-
<?php
|
87 |
-
}
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Add the option to select schema.org employmentType for job type on the add meta field form.
|
92 |
-
*
|
93 |
-
* @param string $taxonomy Taxonomy slug.
|
94 |
-
*/
|
95 |
-
public function add_form_display_schema_org_employment_type_field( $taxonomy ) {
|
96 |
-
$employment_types = wpjm_job_listing_employment_type_options();
|
97 |
-
|
98 |
-
if ( ! empty( $employment_types ) ) {
|
99 |
-
?>
|
100 |
-
<div class="form-field term-group">
|
101 |
-
<label for="feature-group"><?php esc_html_e( 'Employment Type', 'wp-job-manager' ); ?></label>
|
102 |
-
<select class="postform" id="employment_type" name="employment_type">
|
103 |
-
<option value=""></option>
|
104 |
-
<?php foreach ( $employment_types as $key => $employment_type ) : ?>
|
105 |
-
<option value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $employment_type ); ?></option>
|
106 |
-
<?php endforeach; ?>
|
107 |
-
</select>
|
108 |
-
</div>
|
109 |
-
<?php
|
110 |
-
}
|
111 |
-
}
|
112 |
-
|
113 |
-
/**
|
114 |
-
* Adds the Employment Type column when listing job type terms in WP Admin.
|
115 |
-
*
|
116 |
-
* @param array $columns
|
117 |
-
* @return array
|
118 |
-
*/
|
119 |
-
public function add_employment_type_column( $columns ) {
|
120 |
-
$columns['employment_type'] = __( 'Employment Type', 'wp-job-manager' );
|
121 |
-
return $columns;
|
122 |
-
}
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Adds the Employment Type column as a sortable column when listing job type terms in WP Admin.
|
126 |
-
*
|
127 |
-
* @param array $sortable
|
128 |
-
* @return array
|
129 |
-
*/
|
130 |
-
public function add_employment_type_column_sortable( $sortable ) {
|
131 |
-
$sortable['employment_type'] = 'employment_type';
|
132 |
-
return $sortable;
|
133 |
-
}
|
134 |
-
|
135 |
-
/**
|
136 |
-
* Adds the Employment Type column content when listing job type terms in WP Admin.
|
137 |
-
*
|
138 |
-
* @param string $content
|
139 |
-
* @param string $column_name
|
140 |
-
* @param int $term_id
|
141 |
-
* @return string
|
142 |
-
*/
|
143 |
-
public function add_employment_type_column_content( $content, $column_name, $term_id ) {
|
144 |
-
if ( 'employment_type' !== $column_name ) {
|
145 |
-
return $content;
|
146 |
-
}
|
147 |
-
$employment_types = wpjm_job_listing_employment_type_options();
|
148 |
-
$term_id = absint( $term_id );
|
149 |
-
$term_employment_type = get_term_meta( $term_id, 'employment_type', true );
|
150 |
-
|
151 |
-
if ( ! empty( $term_employment_type ) && isset( $employment_types[ $term_employment_type ] ) ) {
|
152 |
-
$content .= esc_attr( $employment_types[ $term_employment_type ] );
|
153 |
-
}
|
154 |
-
return $content;
|
155 |
-
}
|
156 |
-
}
|
157 |
-
|
158 |
-
WP_Job_Manager_Taxonomy_Meta::instance();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/admin/class-wp-job-manager-writepanels.php
CHANGED
@@ -1,7 +1,5 @@
|
|
1 |
<?php
|
2 |
-
if ( ! defined( 'ABSPATH' ) )
|
3 |
-
exit; // Exit if accessed directly.
|
4 |
-
}
|
5 |
|
6 |
/**
|
7 |
* Handles the management of Job Listing meta fields.
|
@@ -15,14 +13,14 @@ class WP_Job_Manager_Writepanels {
|
|
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 |
*/
|
@@ -53,86 +51,78 @@ class WP_Job_Manager_Writepanels {
|
|
53 |
$current_user = wp_get_current_user();
|
54 |
|
55 |
$fields = array(
|
56 |
-
'_job_location'
|
57 |
-
'label'
|
58 |
'placeholder' => __( 'e.g. "London"', 'wp-job-manager' ),
|
59 |
'description' => __( 'Leave this blank if the location is not important.', 'wp-job-manager' ),
|
60 |
-
'priority' => 1
|
61 |
),
|
62 |
-
'_application'
|
63 |
'label' => __( 'Application Email or URL', 'wp-job-manager' ),
|
64 |
'placeholder' => __( 'URL or email which applicants use to apply', 'wp-job-manager' ),
|
65 |
'description' => __( 'This field is required for the "application" area to appear beneath the listing.', 'wp-job-manager' ),
|
66 |
'value' => metadata_exists( 'post', $post->ID, '_application' ) ? get_post_meta( $post->ID, '_application', true ) : $current_user->user_email,
|
67 |
-
'priority' => 2
|
68 |
),
|
69 |
-
'_company_name'
|
70 |
'label' => __( 'Company Name', 'wp-job-manager' ),
|
71 |
'placeholder' => '',
|
72 |
-
'priority' => 3
|
73 |
),
|
74 |
'_company_website' => array(
|
75 |
'label' => __( 'Company Website', 'wp-job-manager' ),
|
76 |
'placeholder' => '',
|
77 |
-
'priority' => 4
|
78 |
),
|
79 |
'_company_tagline' => array(
|
80 |
'label' => __( 'Company Tagline', 'wp-job-manager' ),
|
81 |
'placeholder' => __( 'Brief description about the company', 'wp-job-manager' ),
|
82 |
-
'priority' => 5
|
83 |
),
|
84 |
'_company_twitter' => array(
|
85 |
'label' => __( 'Company Twitter', 'wp-job-manager' ),
|
86 |
'placeholder' => '@yourcompany',
|
87 |
-
'priority' => 6
|
88 |
),
|
89 |
-
'_company_video'
|
90 |
'label' => __( 'Company Video', 'wp-job-manager' ),
|
91 |
'placeholder' => __( 'URL to the company video', 'wp-job-manager' ),
|
92 |
'type' => 'file',
|
93 |
-
'priority' => 8
|
94 |
),
|
95 |
-
'_filled'
|
96 |
'label' => __( 'Position Filled', 'wp-job-manager' ),
|
97 |
'type' => 'checkbox',
|
98 |
'priority' => 9,
|
99 |
'description' => __( 'Filled listings will no longer accept applications.', 'wp-job-manager' ),
|
100 |
-
)
|
101 |
);
|
102 |
if ( $current_user->has_cap( 'manage_job_listings' ) ) {
|
103 |
-
$fields['_featured']
|
104 |
'label' => __( 'Featured Listing', 'wp-job-manager' ),
|
105 |
'type' => 'checkbox',
|
106 |
'description' => __( 'Featured listings will be sticky during searches, and can be styled differently.', 'wp-job-manager' ),
|
107 |
-
'priority' => 10
|
108 |
);
|
109 |
-
$job_expires
|
110 |
$fields['_job_expires'] = array(
|
111 |
'label' => __( 'Listing Expiry Date', 'wp-job-manager' ),
|
112 |
'priority' => 11,
|
113 |
'classes' => array( 'job-manager-datepicker' ),
|
114 |
-
|
115 |
-
'
|
|
|
116 |
);
|
117 |
}
|
118 |
if ( $current_user->has_cap( 'edit_others_job_listings' ) ) {
|
119 |
$fields['_job_author'] = array(
|
120 |
'label' => __( 'Posted by', 'wp-job-manager' ),
|
121 |
'type' => 'author',
|
122 |
-
'priority' => 12
|
123 |
);
|
124 |
}
|
125 |
|
126 |
-
|
127 |
-
* Filters job listing data fields for WP Admin post editor.
|
128 |
-
*
|
129 |
-
* @since 1.0.0
|
130 |
-
* @since 1.27.0 $post_id was added
|
131 |
-
*
|
132 |
-
* @param array $fields
|
133 |
-
* @param int $post_id
|
134 |
-
*/
|
135 |
-
$fields = apply_filters( 'job_manager_job_listing_data_fields', $fields, $post->ID );
|
136 |
|
137 |
uasort( $fields, array( $this, 'sort_by_priority' ) );
|
138 |
|
@@ -147,10 +137,10 @@ class WP_Job_Manager_Writepanels {
|
|
147 |
* @return int
|
148 |
*/
|
149 |
protected function sort_by_priority( $a, $b ) {
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
}
|
155 |
|
156 |
/**
|
@@ -159,14 +149,13 @@ class WP_Job_Manager_Writepanels {
|
|
159 |
public function add_meta_boxes() {
|
160 |
global $wp_post_types;
|
161 |
|
162 |
-
// translators: Placeholder %s is the singular name for a job listing post type.
|
163 |
add_meta_box( 'job_listing_data', sprintf( __( '%s Data', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name ), array( $this, 'job_listing_data' ), 'job_listing', 'normal', 'high' );
|
164 |
-
if ( ! get_option( 'job_manager_enable_types' ) ||
|
165 |
-
remove_meta_box( 'job_listing_typediv', 'job_listing', 'side'
|
166 |
-
} elseif ( false
|
167 |
-
remove_meta_box( 'job_listing_typediv', 'job_listing', 'side'
|
168 |
$job_listing_type = get_taxonomy( 'job_listing_type' );
|
169 |
-
add_meta_box( 'job_listing_type', $job_listing_type->labels->menu_name, array( $this, 'job_listing_metabox' ),
|
170 |
}
|
171 |
}
|
172 |
|
@@ -176,71 +165,54 @@ class WP_Job_Manager_Writepanels {
|
|
176 |
* @param int|WP_Post $post
|
177 |
*/
|
178 |
public function job_listing_metabox( $post ) {
|
179 |
-
// Set up the taxonomy object and get terms
|
180 |
$taxonomy = 'job_listing_type';
|
181 |
-
$tax
|
182 |
|
183 |
-
// The name of the form
|
184 |
$name = 'tax_input[' . $taxonomy . ']';
|
185 |
|
186 |
-
// Get all the terms for this taxonomy
|
187 |
-
$terms
|
188 |
-
array(
|
189 |
-
'taxonomy' => $taxonomy,
|
190 |
-
'hide_empty' => 0,
|
191 |
-
)
|
192 |
-
);
|
193 |
$postterms = get_the_terms( $post->ID, $taxonomy );
|
194 |
-
$current
|
195 |
-
$current
|
196 |
-
// Get current and popular terms
|
197 |
-
$popular
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
'order' => 'DESC',
|
202 |
-
'number' => 10,
|
203 |
-
'hierarchical' => false,
|
204 |
-
)
|
205 |
-
);
|
206 |
-
$postterms = get_the_terms( $post->ID, $taxonomy );
|
207 |
-
$current = ( $postterms ? array_pop( $postterms ) : false );
|
208 |
-
$current = ( $current ? $current->term_id : 0 );
|
209 |
?>
|
210 |
|
211 |
-
<div id="taxonomy-<?php echo
|
212 |
|
213 |
<!-- Display tabs-->
|
214 |
-
<ul id="<?php echo
|
215 |
-
<li class="tabs"><a href="#<?php echo
|
216 |
-
<li class="hide-if-no-js"><a href="#<?php echo
|
217 |
</ul>
|
218 |
|
219 |
<!-- Display taxonomy terms -->
|
220 |
-
<div id="<?php echo
|
221 |
-
<ul id="<?php echo
|
222 |
-
<?php
|
223 |
-
|
224 |
-
$id =
|
225 |
-
echo
|
226 |
-
|
227 |
-
|
228 |
-
}
|
229 |
-
?>
|
230 |
</ul>
|
231 |
</div>
|
232 |
|
233 |
<!-- Display popular taxonomy terms -->
|
234 |
-
<div id="<?php echo
|
235 |
-
<ul id="<?php echo
|
236 |
-
<?php
|
237 |
-
|
238 |
-
|
239 |
-
echo
|
240 |
-
echo
|
241 |
-
|
242 |
-
}
|
243 |
-
?>
|
244 |
</ul>
|
245 |
</div>
|
246 |
|
@@ -270,27 +242,17 @@ class WP_Job_Manager_Writepanels {
|
|
270 |
}
|
271 |
?>
|
272 |
<p class="form-field">
|
273 |
-
<label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html(
|
274 |
-
<?php if ( ! empty( $field['description'] ) ) : ?>
|
275 |
-
<span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span>
|
276 |
-
<?php endif; ?>
|
277 |
-
</label>
|
278 |
<?php
|
279 |
if ( ! empty( $field['multiple'] ) ) {
|
280 |
foreach ( (array) $field['value'] as $value ) {
|
281 |
-
?>
|
282 |
-
<span class="file_url"><input type="text" name="<?php echo esc_attr( $name ); ?>[]" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo esc_attr( $value ); ?>" /><button class="button button-small wp_job_manager_upload_file_button" data-uploader_button_text="<?php esc_attr_e( 'Use file', 'wp-job-manager' ); ?>"><?php esc_html_e( 'Upload', 'wp-job-manager' ); ?></button><button class="button button-small wp_job_manager_view_file_button"><?php esc_html_e( 'View', 'wp-job-manager' ); ?></button></span>
|
283 |
-
<?php
|
284 |
}
|
285 |
} else {
|
286 |
-
?>
|
287 |
-
<span class="file_url"><input type="text" name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo esc_attr( $field['value'] ); ?>" /><button class="button button-small wp_job_manager_upload_file_button" data-uploader_button_text="<?php esc_attr_e( 'Use file', 'wp-job-manager' ); ?>"><?php esc_html_e( 'Upload', 'wp-job-manager' ); ?></button><button class="button button-small wp_job_manager_view_file_button"><?php esc_html_e( 'View', 'wp-job-manager' ); ?></button></span>
|
288 |
-
<?php
|
289 |
}
|
290 |
if ( ! empty( $field['multiple'] ) ) {
|
291 |
-
?>
|
292 |
-
<button class="button button-small wp_job_manager_add_another_file_button" data-field_name="<?php echo esc_attr( $key ); ?>" data-field_placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" data-uploader_button_text="<?php esc_attr_e( 'Use file', 'wp-job-manager' ); ?>" data-uploader_button="<?php esc_attr_e( 'Upload', 'wp-job-manager' ); ?>" data-view_button="<?php esc_attr_e( 'View', 'wp-job-manager' ); ?>"><?php esc_html_e( 'Add file', 'wp-job-manager' ); ?></button>
|
293 |
-
<?php
|
294 |
}
|
295 |
?>
|
296 |
</p>
|
@@ -321,73 +283,12 @@ class WP_Job_Manager_Writepanels {
|
|
321 |
}
|
322 |
?>
|
323 |
<p class="form-field">
|
324 |
-
<label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html(
|
325 |
-
<?php if ( ! empty( $field['description'] ) ) : ?>
|
326 |
-
<span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span>
|
327 |
-
<?php endif; ?>
|
328 |
-
</label>
|
329 |
<input type="text" autocomplete="off" name="<?php echo esc_attr( $name ); ?>" class="<?php echo esc_attr( $classes ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo esc_attr( $field['value'] ); ?>" />
|
330 |
</p>
|
331 |
<?php
|
332 |
}
|
333 |
|
334 |
-
/**
|
335 |
-
* Just displays information.
|
336 |
-
*
|
337 |
-
* @since 1.27.0
|
338 |
-
*
|
339 |
-
* @param string $key
|
340 |
-
* @param array $field
|
341 |
-
*/
|
342 |
-
public static function input_info( $key, $field ) {
|
343 |
-
self::input_hidden( $key, $field );
|
344 |
-
}
|
345 |
-
|
346 |
-
/**
|
347 |
-
* Displays information and/or hidden input.
|
348 |
-
*
|
349 |
-
* @since 1.27.0
|
350 |
-
*
|
351 |
-
* @param string $key
|
352 |
-
* @param array $field
|
353 |
-
*/
|
354 |
-
public static function input_hidden( $key, $field ) {
|
355 |
-
global $thepostid;
|
356 |
-
|
357 |
-
if ( 'hidden' === $field['type'] && ! isset( $field['value'] ) ) {
|
358 |
-
$field['value'] = get_post_meta( $thepostid, $key, true );
|
359 |
-
}
|
360 |
-
if ( ! empty( $field['name'] ) ) {
|
361 |
-
$name = $field['name'];
|
362 |
-
} else {
|
363 |
-
$name = $key;
|
364 |
-
}
|
365 |
-
if ( ! empty( $field['classes'] ) ) {
|
366 |
-
$classes = implode( ' ', is_array( $field['classes'] ) ? $field['classes'] : array( $field['classes'] ) );
|
367 |
-
} else {
|
368 |
-
$classes = '';
|
369 |
-
}
|
370 |
-
if ( 'hidden' === $field['type'] ) {
|
371 |
-
if ( empty( $field['label'] ) ) {
|
372 |
-
echo '<input type="hidden" name="' . esc_attr( $name ) . '" class="' . esc_attr( $classes ) . '" id="' . esc_attr( $key ) . '" value="' . esc_attr( $field['value'] ) . '" />';
|
373 |
-
return;
|
374 |
-
}
|
375 |
-
}
|
376 |
-
?>
|
377 |
-
<p class="form-field">
|
378 |
-
<label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( wp_strip_all_tags( $field['label'] ) ); ?>:
|
379 |
-
<?php if ( ! empty( $field['description'] ) ) : ?>
|
380 |
-
<span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span>
|
381 |
-
<?php endif; ?>
|
382 |
-
</label>
|
383 |
-
<?php if ( ! empty( $field['information'] ) ) : ?>
|
384 |
-
<span class="information"><?php echo wp_kses( $field['information'], array( 'a' => array( 'href' => array() ) ) ); ?></span>
|
385 |
-
<?php endif; ?>
|
386 |
-
<?php echo '<input type="hidden" name="' . esc_attr( $name ) . '" class="' . esc_attr( $classes ) . '" id="' . esc_attr( $key ) . '" value="' . esc_attr( $field['value'] ) . '" />'; ?>
|
387 |
-
</p>
|
388 |
-
<?php
|
389 |
-
}
|
390 |
-
|
391 |
/**
|
392 |
* Displays label and textarea input field.
|
393 |
*
|
@@ -407,11 +308,7 @@ class WP_Job_Manager_Writepanels {
|
|
407 |
}
|
408 |
?>
|
409 |
<p class="form-field">
|
410 |
-
<label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html(
|
411 |
-
<?php if ( ! empty( $field['description'] ) ) : ?>
|
412 |
-
<span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span>
|
413 |
-
<?php endif; ?>
|
414 |
-
</label>
|
415 |
<textarea name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>"><?php echo esc_html( $field['value'] ); ?></textarea>
|
416 |
</p>
|
417 |
<?php
|
@@ -436,22 +333,10 @@ class WP_Job_Manager_Writepanels {
|
|
436 |
}
|
437 |
?>
|
438 |
<p class="form-field">
|
439 |
-
<label for="<?php echo esc_attr( $key ); ?>">
|
440 |
-
<?php echo esc_html( wp_strip_all_tags( $field['label'] ) ); ?>:
|
441 |
-
<?php if ( ! empty( $field['description'] ) ) : ?>
|
442 |
-
<span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span>
|
443 |
-
<?php endif; ?>
|
444 |
-
</label>
|
445 |
<select name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>">
|
446 |
<?php foreach ( $field['options'] as $key => $value ) : ?>
|
447 |
-
|
448 |
-
value="<?php echo esc_attr( $key ); ?>"
|
449 |
-
<?php
|
450 |
-
if ( isset( $field['value'] ) ) {
|
451 |
-
selected( $field['value'], $key );
|
452 |
-
}
|
453 |
-
?>
|
454 |
-
><?php echo esc_html( $value ); ?></option>
|
455 |
<?php endforeach; ?>
|
456 |
</select>
|
457 |
</p>
|
@@ -477,21 +362,10 @@ class WP_Job_Manager_Writepanels {
|
|
477 |
}
|
478 |
?>
|
479 |
<p class="form-field">
|
480 |
-
<label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html(
|
481 |
-
<?php if ( ! empty( $field['description'] ) ) : ?>
|
482 |
-
<span class="tips" data-tip="<?php echo esc_attr( $field['description'] ); ?>">[?]</span>
|
483 |
-
<?php endif; ?>
|
484 |
-
</label>
|
485 |
<select multiple="multiple" name="<?php echo esc_attr( $name ); ?>[]" id="<?php echo esc_attr( $key ); ?>">
|
486 |
<?php foreach ( $field['options'] as $key => $value ) : ?>
|
487 |
-
<option value="<?php echo esc_attr( $key ); ?>"
|
488 |
-
<?php
|
489 |
-
if ( ! empty( $field['value'] ) && is_array( $field['value'] ) ) {
|
490 |
-
// phpcs:ignore WordPress.PHP.StrictInArray
|
491 |
-
selected( in_array( $key, $field['value'] ), true );
|
492 |
-
}
|
493 |
-
?>
|
494 |
-
><?php echo esc_html( $value ); ?></option>
|
495 |
<?php endforeach; ?>
|
496 |
</select>
|
497 |
</p>
|
@@ -517,11 +391,9 @@ class WP_Job_Manager_Writepanels {
|
|
517 |
}
|
518 |
?>
|
519 |
<p class="form-field form-field-checkbox">
|
520 |
-
<label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html(
|
521 |
<input type="checkbox" class="checkbox" name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" value="1" <?php checked( $field['value'], 1 ); ?> />
|
522 |
-
<?php if ( ! empty( $field['description'] ) ) : ?>
|
523 |
-
<span class="description"><?php echo wp_kses_post( $field['description'] ); ?></span>
|
524 |
-
<?php endif; ?>
|
525 |
</p>
|
526 |
<?php
|
527 |
}
|
@@ -547,20 +419,19 @@ class WP_Job_Manager_Writepanels {
|
|
547 |
$name = ! empty( $field['name'] ) ? $field['name'] : $key;
|
548 |
?>
|
549 |
<p class="form-field form-field-author">
|
550 |
-
<label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html(
|
551 |
<span class="current-author">
|
552 |
<?php
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
?>
|
559 |
-
<a href="#" class="change-author button button-small"><?php esc_html_e( 'Change', 'wp-job-manager' ); ?></a>
|
560 |
</span>
|
561 |
<span class="hidden change-author">
|
562 |
<input type="number" name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" step="1" value="<?php echo esc_attr( $author_id ); ?>" style="width: 4em;" />
|
563 |
-
<span class="description"><?php
|
564 |
</span>
|
565 |
</p>
|
566 |
<?php
|
@@ -585,13 +456,11 @@ class WP_Job_Manager_Writepanels {
|
|
585 |
}
|
586 |
?>
|
587 |
<p class="form-field form-field-checkbox">
|
588 |
-
<label><?php echo esc_html(
|
589 |
<?php foreach ( $field['options'] as $option_key => $value ) : ?>
|
590 |
<label><input type="radio" class="radio" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" value="<?php echo esc_attr( $option_key ); ?>" <?php checked( $field['value'], $option_key ); ?> /> <?php echo esc_html( $value ); ?></label>
|
591 |
<?php endforeach; ?>
|
592 |
-
<?php if ( ! empty( $field['description'] ) ) : ?>
|
593 |
-
<span class="description"><?php echo wp_kses_post( $field['description'] ); ?></span>
|
594 |
-
<?php endif; ?>
|
595 |
</p>
|
596 |
<?php
|
597 |
}
|
@@ -602,7 +471,7 @@ class WP_Job_Manager_Writepanels {
|
|
602 |
* @param int|WP_Post $post
|
603 |
*/
|
604 |
public function job_listing_data( $post ) {
|
605 |
-
global $post, $thepostid
|
606 |
|
607 |
$thepostid = $post->ID;
|
608 |
|
@@ -622,14 +491,6 @@ class WP_Job_Manager_Writepanels {
|
|
622 |
}
|
623 |
}
|
624 |
|
625 |
-
$user_edited_date = get_post_meta( $post->ID, '_job_edited', true );
|
626 |
-
if ( $user_edited_date ) {
|
627 |
-
echo '<p class="form-field">';
|
628 |
-
// translators: %1$s is placeholder for singular name of the job listing post type; %2$s is the intl formatted date the listing was last modified.
|
629 |
-
echo '<em>' . sprintf( esc_html__( '%1$s was last modified by the user on %2$s.', 'wp-job-manager' ), esc_html( $wp_post_types['job_listing']->labels->singular_name ), esc_html( date_i18n( get_option( 'date_format' ), $user_edited_date ) ) ) . '</em>';
|
630 |
-
echo '</p>';
|
631 |
-
}
|
632 |
-
|
633 |
do_action( 'job_manager_job_listing_data_end', $thepostid );
|
634 |
|
635 |
echo '</div>';
|
@@ -642,27 +503,13 @@ class WP_Job_Manager_Writepanels {
|
|
642 |
* @param WP_Post $post
|
643 |
*/
|
644 |
public function save_post( $post_id, $post ) {
|
645 |
-
if ( empty( $post_id ) || empty( $post ) || empty( $_POST ) )
|
646 |
-
|
647 |
-
|
648 |
-
if (
|
649 |
-
|
650 |
-
|
651 |
-
if (
|
652 |
-
return;
|
653 |
-
}
|
654 |
-
if ( is_int( wp_is_post_autosave( $post ) ) ) {
|
655 |
-
return;
|
656 |
-
}
|
657 |
-
if ( empty( $_POST['job_manager_nonce'] ) || ! wp_verify_nonce( $_POST['job_manager_nonce'], 'save_meta_data' ) ) {
|
658 |
-
return;
|
659 |
-
}
|
660 |
-
if ( ! current_user_can( 'edit_post', $post_id ) ) {
|
661 |
-
return;
|
662 |
-
}
|
663 |
-
if ( 'job_listing' !== $post->post_type ) {
|
664 |
-
return;
|
665 |
-
}
|
666 |
|
667 |
do_action( 'job_manager_save_job_listing', $post_id, $post );
|
668 |
}
|
@@ -671,59 +518,59 @@ class WP_Job_Manager_Writepanels {
|
|
671 |
* Handles the actual saving of job listing data fields.
|
672 |
*
|
673 |
* @param int $post_id
|
674 |
-
* @param WP_Post $post (Unused)
|
675 |
*/
|
676 |
public function save_job_listing_data( $post_id, $post ) {
|
677 |
global $wpdb;
|
678 |
|
679 |
-
// These need to exist
|
680 |
add_post_meta( $post_id, '_filled', 0, true );
|
681 |
add_post_meta( $post_id, '_featured', 0, true );
|
682 |
|
683 |
-
// Save fields
|
684 |
foreach ( $this->job_listing_fields() as $key => $field ) {
|
685 |
-
|
686 |
-
continue;
|
687 |
-
}
|
688 |
-
|
689 |
-
// Expirey date.
|
690 |
if ( '_job_expires' === $key ) {
|
691 |
-
if ( empty( $_POST[ $key ] ) ) {
|
692 |
-
if ( get_option( 'job_manager_submission_duration' ) ) {
|
693 |
-
update_post_meta( $post_id, $key, calculate_job_expiry( $post_id ) );
|
694 |
-
} else {
|
695 |
-
delete_post_meta( $post_id, $key );
|
696 |
-
}
|
697 |
-
} else {
|
698 |
update_post_meta( $post_id, $key, date( 'Y-m-d', strtotime( sanitize_text_field( $_POST[ $key ] ) ) ) );
|
|
|
|
|
699 |
}
|
700 |
-
}
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
|
|
|
|
705 |
WP_Job_Manager_Geocode::generate_location_data( $post_id, sanitize_text_field( $_POST[ $key ] ) );
|
706 |
}
|
707 |
-
}
|
|
|
|
|
708 |
$wpdb->update( $wpdb->posts, array( 'post_author' => $_POST[ $key ] > 0 ? absint( $_POST[ $key ] ) : 0 ), array( 'ID' => $post_id ) );
|
709 |
-
}
|
|
|
|
|
710 |
update_post_meta( $post_id, $key, sanitize_text_field( is_email( $_POST[ $key ] ) ? $_POST[ $key ] : urldecode( $_POST[ $key ] ) ) );
|
711 |
-
}
|
712 |
-
|
|
|
|
|
713 |
$type = ! empty( $field['type'] ) ? $field['type'] : '';
|
714 |
|
715 |
switch ( $type ) {
|
716 |
-
case 'textarea':
|
717 |
update_post_meta( $post_id, $key, wp_kses_post( stripslashes( $_POST[ $key ] ) ) );
|
718 |
-
|
719 |
-
case 'checkbox':
|
720 |
if ( isset( $_POST[ $key ] ) ) {
|
721 |
update_post_meta( $post_id, $key, 1 );
|
722 |
} else {
|
723 |
update_post_meta( $post_id, $key, 0 );
|
724 |
}
|
725 |
-
|
726 |
-
default:
|
727 |
if ( ! isset( $_POST[ $key ] ) ) {
|
728 |
continue;
|
729 |
} elseif ( is_array( $_POST[ $key ] ) ) {
|
@@ -731,18 +578,18 @@ class WP_Job_Manager_Writepanels {
|
|
731 |
} else {
|
732 |
update_post_meta( $post_id, $key, sanitize_text_field( $_POST[ $key ] ) );
|
733 |
}
|
734 |
-
|
735 |
}
|
736 |
}
|
737 |
}
|
738 |
|
739 |
/* Set Post Status To Expired If Already Expired */
|
740 |
-
$expiry_date
|
741 |
-
$today_date
|
742 |
$is_job_listing_expired = $expiry_date && $today_date > $expiry_date;
|
743 |
-
if
|
744 |
remove_action( 'job_manager_save_job_listing', array( $this, 'save_job_listing_data' ), 20, 2 );
|
745 |
-
if ( $this->
|
746 |
update_post_meta( $post_id, '_job_expires', calculate_job_expiry( $post_id ) );
|
747 |
} else {
|
748 |
$job_data = array(
|
@@ -756,22 +603,15 @@ class WP_Job_Manager_Writepanels {
|
|
756 |
}
|
757 |
|
758 |
/**
|
759 |
-
* Checks if the job listing
|
760 |
-
*
|
761 |
-
* @param string|null $from_status Status to test if it is changing from. NULL if anything.
|
762 |
-
* @param string $to_status Status to test if it is changing to.
|
763 |
*
|
764 |
-
* @return bool True if
|
765 |
*/
|
766 |
-
|
767 |
return isset( $_POST['post_status'] )
|
768 |
&& isset( $_POST['original_post_status'] )
|
769 |
-
&&
|
770 |
-
&&
|
771 |
-
null === $from_status
|
772 |
-
|| $from_status === $_POST['original_post_status']
|
773 |
-
)
|
774 |
-
&& $to_status === $_POST['post_status'];
|
775 |
}
|
776 |
}
|
777 |
|
1 |
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
3 |
|
4 |
/**
|
5 |
* Handles the management of Job Listing meta fields.
|
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 |
*/
|
51 |
$current_user = wp_get_current_user();
|
52 |
|
53 |
$fields = array(
|
54 |
+
'_job_location' => array(
|
55 |
+
'label' => __( 'Location', 'wp-job-manager' ),
|
56 |
'placeholder' => __( 'e.g. "London"', 'wp-job-manager' ),
|
57 |
'description' => __( 'Leave this blank if the location is not important.', 'wp-job-manager' ),
|
58 |
+
'priority' => 1
|
59 |
),
|
60 |
+
'_application' => array(
|
61 |
'label' => __( 'Application Email or URL', 'wp-job-manager' ),
|
62 |
'placeholder' => __( 'URL or email which applicants use to apply', 'wp-job-manager' ),
|
63 |
'description' => __( 'This field is required for the "application" area to appear beneath the listing.', 'wp-job-manager' ),
|
64 |
'value' => metadata_exists( 'post', $post->ID, '_application' ) ? get_post_meta( $post->ID, '_application', true ) : $current_user->user_email,
|
65 |
+
'priority' => 2
|
66 |
),
|
67 |
+
'_company_name' => array(
|
68 |
'label' => __( 'Company Name', 'wp-job-manager' ),
|
69 |
'placeholder' => '',
|
70 |
+
'priority' => 3
|
71 |
),
|
72 |
'_company_website' => array(
|
73 |
'label' => __( 'Company Website', 'wp-job-manager' ),
|
74 |
'placeholder' => '',
|
75 |
+
'priority' => 4
|
76 |
),
|
77 |
'_company_tagline' => array(
|
78 |
'label' => __( 'Company Tagline', 'wp-job-manager' ),
|
79 |
'placeholder' => __( 'Brief description about the company', 'wp-job-manager' ),
|
80 |
+
'priority' => 5
|
81 |
),
|
82 |
'_company_twitter' => array(
|
83 |
'label' => __( 'Company Twitter', 'wp-job-manager' ),
|
84 |
'placeholder' => '@yourcompany',
|
85 |
+
'priority' => 6
|
86 |
),
|
87 |
+
'_company_video' => array(
|
88 |
'label' => __( 'Company Video', 'wp-job-manager' ),
|
89 |
'placeholder' => __( 'URL to the company video', 'wp-job-manager' ),
|
90 |
'type' => 'file',
|
91 |
+
'priority' => 8
|
92 |
),
|
93 |
+
'_filled' => array(
|
94 |
'label' => __( 'Position Filled', 'wp-job-manager' ),
|
95 |
'type' => 'checkbox',
|
96 |
'priority' => 9,
|
97 |
'description' => __( 'Filled listings will no longer accept applications.', 'wp-job-manager' ),
|
98 |
+
)
|
99 |
);
|
100 |
if ( $current_user->has_cap( 'manage_job_listings' ) ) {
|
101 |
+
$fields['_featured'] = array(
|
102 |
'label' => __( 'Featured Listing', 'wp-job-manager' ),
|
103 |
'type' => 'checkbox',
|
104 |
'description' => __( 'Featured listings will be sticky during searches, and can be styled differently.', 'wp-job-manager' ),
|
105 |
+
'priority' => 10
|
106 |
);
|
107 |
+
$job_expires = get_post_meta( $post->ID, '_job_expires', true );
|
108 |
$fields['_job_expires'] = array(
|
109 |
'label' => __( 'Listing Expiry Date', 'wp-job-manager' ),
|
110 |
'priority' => 11,
|
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' ) ) {
|
118 |
$fields['_job_author'] = array(
|
119 |
'label' => __( 'Posted by', 'wp-job-manager' ),
|
120 |
'type' => 'author',
|
121 |
+
'priority' => 12
|
122 |
);
|
123 |
}
|
124 |
|
125 |
+
$fields = apply_filters( 'job_manager_job_listing_data_fields', $fields );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
|
127 |
uasort( $fields, array( $this, 'sort_by_priority' ) );
|
128 |
|
137 |
* @return int
|
138 |
*/
|
139 |
protected function sort_by_priority( $a, $b ) {
|
140 |
+
if ( ! isset( $a['priority'] ) || ! isset( $b['priority'] ) || $a['priority'] === $b['priority'] ) {
|
141 |
+
return 0;
|
142 |
+
}
|
143 |
+
return ( $a['priority'] < $b['priority'] ) ? -1 : 1;
|
144 |
}
|
145 |
|
146 |
/**
|
149 |
public function add_meta_boxes() {
|
150 |
global $wp_post_types;
|
151 |
|
|
|
152 |
add_meta_box( 'job_listing_data', sprintf( __( '%s Data', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->singular_name ), array( $this, 'job_listing_data' ), 'job_listing', 'normal', 'high' );
|
153 |
+
if ( ! get_option( 'job_manager_enable_types' ) || wp_count_terms( 'job_listing_type' ) == 0 ) {
|
154 |
+
remove_meta_box( 'job_listing_typediv', 'job_listing', 'side');
|
155 |
+
} elseif ( false == job_manager_multi_job_type() ) {
|
156 |
+
remove_meta_box( 'job_listing_typediv', 'job_listing', 'side');
|
157 |
$job_listing_type = get_taxonomy( 'job_listing_type' );
|
158 |
+
add_meta_box( 'job_listing_type', $job_listing_type->labels->menu_name, array( $this, 'job_listing_metabox' ),'job_listing' ,'side','core');
|
159 |
}
|
160 |
}
|
161 |
|
165 |
* @param int|WP_Post $post
|
166 |
*/
|
167 |
public function job_listing_metabox( $post ) {
|
168 |
+
// Set up the taxonomy object and get terms
|
169 |
$taxonomy = 'job_listing_type';
|
170 |
+
$tax = get_taxonomy( $taxonomy );// This is the taxonomy object
|
171 |
|
172 |
+
// The name of the form
|
173 |
$name = 'tax_input[' . $taxonomy . ']';
|
174 |
|
175 |
+
// Get all the terms for this taxonomy
|
176 |
+
$terms = get_terms( $taxonomy, array( 'hide_empty' => 0 ) );
|
|
|
|
|
|
|
|
|
|
|
177 |
$postterms = get_the_terms( $post->ID, $taxonomy );
|
178 |
+
$current = ( $postterms ? array_pop( $postterms ) : false );
|
179 |
+
$current = ( $current ? $current->term_id : 0 );
|
180 |
+
// Get current and popular terms
|
181 |
+
$popular = get_terms( $taxonomy, array( 'orderby' => 'count', 'order' => 'DESC', 'number' => 10, 'hierarchical' => false ) );
|
182 |
+
$postterms = get_the_terms( $post->ID,$taxonomy );
|
183 |
+
$current = ($postterms ? array_pop($postterms) : false);
|
184 |
+
$current = ($current ? $current->term_id : 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
?>
|
186 |
|
187 |
+
<div id="taxonomy-<?php echo $taxonomy; ?>" class="categorydiv">
|
188 |
|
189 |
<!-- Display tabs-->
|
190 |
+
<ul id="<?php echo $taxonomy; ?>-tabs" class="category-tabs">
|
191 |
+
<li class="tabs"><a href="#<?php echo $taxonomy; ?>-all" tabindex="3"><?php echo $tax->labels->all_items; ?></a></li>
|
192 |
+
<li class="hide-if-no-js"><a href="#<?php echo $taxonomy; ?>-pop" tabindex="3"><?php _e( 'Most Used' ); ?></a></li>
|
193 |
</ul>
|
194 |
|
195 |
<!-- Display taxonomy terms -->
|
196 |
+
<div id="<?php echo $taxonomy; ?>-all" class="tabs-panel">
|
197 |
+
<ul id="<?php echo $taxonomy; ?>checklist" class="list:<?php echo $taxonomy?> categorychecklist form-no-clear">
|
198 |
+
<?php foreach($terms as $term){
|
199 |
+
$id = $taxonomy.'-'.$term->term_id;
|
200 |
+
echo "<li id='$id'><label class='selectit'>";
|
201 |
+
echo "<input type='radio' id='in-$id' name='{$name}'".checked($current,$term->term_id,false)."value='$term->term_id' />$term->name<br />";
|
202 |
+
echo "</label></li>";
|
203 |
+
}?>
|
|
|
|
|
204 |
</ul>
|
205 |
</div>
|
206 |
|
207 |
<!-- Display popular taxonomy terms -->
|
208 |
+
<div id="<?php echo $taxonomy; ?>-pop" class="tabs-panel" style="display: none;">
|
209 |
+
<ul id="<?php echo $taxonomy; ?>checklist-pop" class="categorychecklist form-no-clear" >
|
210 |
+
<?php foreach($popular as $term){
|
211 |
+
$id = 'popular-'.$taxonomy.'-'.$term->term_id;
|
212 |
+
echo "<li id='$id'><label class='selectit'>";
|
213 |
+
echo "<input type='radio' id='in-$id'".checked($current,$term->term_id,false)."value='$term->term_id' />$term->name<br />";
|
214 |
+
echo "</label></li>";
|
215 |
+
}?>
|
|
|
|
|
216 |
</ul>
|
217 |
</div>
|
218 |
|
242 |
}
|
243 |
?>
|
244 |
<p class="form-field">
|
245 |
+
<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>
|
|
|
|
|
|
|
|
|
246 |
<?php
|
247 |
if ( ! empty( $field['multiple'] ) ) {
|
248 |
foreach ( (array) $field['value'] as $value ) {
|
249 |
+
?><span class="file_url"><input type="text" name="<?php echo esc_attr( $name ); ?>[]" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo esc_attr( $value ); ?>" /><button class="button button-small wp_job_manager_upload_file_button" data-uploader_button_text="<?php _e( 'Use file', 'wp-job-manager' ); ?>"><?php _e( 'Upload', 'wp-job-manager' ); ?></button><button class="button button-small wp_job_manager_view_file_button"><?php _e( 'View', 'wp-job-manager' ); ?></button></span><?php
|
|
|
|
|
250 |
}
|
251 |
} else {
|
252 |
+
?><span class="file_url"><input type="text" name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo esc_attr( $field['value'] ); ?>" /><button class="button button-small wp_job_manager_upload_file_button" data-uploader_button_text="<?php _e( 'Use file', 'wp-job-manager' ); ?>"><?php _e( 'Upload', 'wp-job-manager' ); ?></button><button class="button button-small wp_job_manager_view_file_button"><?php _e( 'View', 'wp-job-manager' ); ?></button></span><?php
|
|
|
|
|
253 |
}
|
254 |
if ( ! empty( $field['multiple'] ) ) {
|
255 |
+
?><button class="button button-small wp_job_manager_add_another_file_button" data-field_name="<?php echo esc_attr( $key ); ?>" data-field_placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" data-uploader_button_text="<?php _e( 'Use file', 'wp-job-manager' ); ?>" data-uploader_button="<?php _e( 'Upload', 'wp-job-manager' ); ?>" data-view_button="<?php _e( 'View', 'wp-job-manager' ); ?>"><?php _e( 'Add file', 'wp-job-manager' ); ?></button><?php
|
|
|
|
|
256 |
}
|
257 |
?>
|
258 |
</p>
|
283 |
}
|
284 |
?>
|
285 |
<p class="form-field">
|
286 |
+
<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>
|
|
|
|
|
|
|
|
|
287 |
<input type="text" autocomplete="off" name="<?php echo esc_attr( $name ); ?>" class="<?php echo esc_attr( $classes ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo esc_attr( $field['value'] ); ?>" />
|
288 |
</p>
|
289 |
<?php
|
290 |
}
|
291 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
/**
|
293 |
* Displays label and textarea input field.
|
294 |
*
|
308 |
}
|
309 |
?>
|
310 |
<p class="form-field">
|
311 |
+
<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>
|
|
|
|
|
|
|
|
|
312 |
<textarea name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>"><?php echo esc_html( $field['value'] ); ?></textarea>
|
313 |
</p>
|
314 |
<?php
|
333 |
}
|
334 |
?>
|
335 |
<p class="form-field">
|
336 |
+
<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>
|
|
|
|
|
|
|
|
|
|
|
337 |
<select name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>">
|
338 |
<?php foreach ( $field['options'] as $key => $value ) : ?>
|
339 |
+
<option value="<?php echo esc_attr( $key ); ?>" <?php if ( isset( $field['value'] ) ) selected( $field['value'], $key ); ?>><?php echo esc_html( $value ); ?></option>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
340 |
<?php endforeach; ?>
|
341 |
</select>
|
342 |
</p>
|
362 |
}
|
363 |
?>
|
364 |
<p class="form-field">
|
365 |
+
<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>
|
|
|
|
|
|
|
|
|
366 |
<select multiple="multiple" name="<?php echo esc_attr( $name ); ?>[]" id="<?php echo esc_attr( $key ); ?>">
|
367 |
<?php foreach ( $field['options'] as $key => $value ) : ?>
|
368 |
+
<option value="<?php echo esc_attr( $key ); ?>" <?php if ( ! empty( $field['value'] ) && is_array( $field['value'] ) ) selected( in_array( $key, $field['value'] ), true ); ?>><?php echo esc_html( $value ); ?></option>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
369 |
<?php endforeach; ?>
|
370 |
</select>
|
371 |
</p>
|
391 |
}
|
392 |
?>
|
393 |
<p class="form-field form-field-checkbox">
|
394 |
+
<label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ) ; ?></label>
|
395 |
<input type="checkbox" class="checkbox" name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" value="1" <?php checked( $field['value'], 1 ); ?> />
|
396 |
+
<?php if ( ! empty( $field['description'] ) ) : ?><span class="description"><?php echo $field['description']; ?></span><?php endif; ?>
|
|
|
|
|
397 |
</p>
|
398 |
<?php
|
399 |
}
|
419 |
$name = ! empty( $field['name'] ) ? $field['name'] : $key;
|
420 |
?>
|
421 |
<p class="form-field form-field-author">
|
422 |
+
<label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ) ; ?>:</label>
|
423 |
<span class="current-author">
|
424 |
<?php
|
425 |
+
if ( $posted_by ) {
|
426 |
+
echo '<a href="' . admin_url( 'user-edit.php?user_id=' . absint( $author_id ) ) . '">#' . absint( $author_id ) . ' – ' . $posted_by->user_login . '</a>';
|
427 |
+
} else {
|
428 |
+
_e( 'Guest User', 'wp-job-manager' );
|
429 |
+
}
|
430 |
+
?> <a href="#" class="change-author button button-small"><?php _e( 'Change', 'wp-job-manager' ); ?></a>
|
|
|
431 |
</span>
|
432 |
<span class="hidden change-author">
|
433 |
<input type="number" name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $key ); ?>" step="1" value="<?php echo esc_attr( $author_id ); ?>" style="width: 4em;" />
|
434 |
+
<span class="description"><?php _e( 'Enter the ID of the user, or leave blank if submitted by a guest.', 'wp-job-manager' ) ?></span>
|
435 |
</span>
|
436 |
</p>
|
437 |
<?php
|
456 |
}
|
457 |
?>
|
458 |
<p class="form-field form-field-checkbox">
|
459 |
+
<label><?php echo esc_html( $field['label'] ) ; ?></label>
|
460 |
<?php foreach ( $field['options'] as $option_key => $value ) : ?>
|
461 |
<label><input type="radio" class="radio" name="<?php echo esc_attr( isset( $field['name'] ) ? $field['name'] : $key ); ?>" value="<?php echo esc_attr( $option_key ); ?>" <?php checked( $field['value'], $option_key ); ?> /> <?php echo esc_html( $value ); ?></label>
|
462 |
<?php endforeach; ?>
|
463 |
+
<?php if ( ! empty( $field['description'] ) ) : ?><span class="description"><?php echo $field['description']; ?></span><?php endif; ?>
|
|
|
|
|
464 |
</p>
|
465 |
<?php
|
466 |
}
|
471 |
* @param int|WP_Post $post
|
472 |
*/
|
473 |
public function job_listing_data( $post ) {
|
474 |
+
global $post, $thepostid;
|
475 |
|
476 |
$thepostid = $post->ID;
|
477 |
|
491 |
}
|
492 |
}
|
493 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
494 |
do_action( 'job_manager_job_listing_data_end', $thepostid );
|
495 |
|
496 |
echo '</div>';
|
503 |
* @param WP_Post $post
|
504 |
*/
|
505 |
public function save_post( $post_id, $post ) {
|
506 |
+
if ( empty( $post_id ) || empty( $post ) || empty( $_POST ) ) return;
|
507 |
+
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return;
|
508 |
+
if ( is_int( wp_is_post_revision( $post ) ) ) return;
|
509 |
+
if ( is_int( wp_is_post_autosave( $post ) ) ) return;
|
510 |
+
if ( empty($_POST['job_manager_nonce']) || ! wp_verify_nonce( $_POST['job_manager_nonce'], 'save_meta_data' ) ) return;
|
511 |
+
if ( ! current_user_can( 'edit_post', $post_id ) ) return;
|
512 |
+
if ( $post->post_type != 'job_listing' ) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
513 |
|
514 |
do_action( 'job_manager_save_job_listing', $post_id, $post );
|
515 |
}
|
518 |
* Handles the actual saving of job listing data fields.
|
519 |
*
|
520 |
* @param int $post_id
|
521 |
+
* @param WP_Post $post (Unused)
|
522 |
*/
|
523 |
public function save_job_listing_data( $post_id, $post ) {
|
524 |
global $wpdb;
|
525 |
|
526 |
+
// These need to exist
|
527 |
add_post_meta( $post_id, '_filled', 0, true );
|
528 |
add_post_meta( $post_id, '_featured', 0, true );
|
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 |
+
|
541 |
+
// Locations
|
542 |
+
elseif ( '_job_location' === $key ) {
|
543 |
+
if ( update_post_meta( $post_id, $key, sanitize_text_field( $_POST[ $key ] ) ) ) {
|
544 |
+
// Location data will be updated by hooked in methods
|
545 |
+
} elseif ( apply_filters( 'job_manager_geolocation_enabled', true ) && ! WP_Job_Manager_Geocode::has_location_data( $post_id ) ) {
|
546 |
WP_Job_Manager_Geocode::generate_location_data( $post_id, sanitize_text_field( $_POST[ $key ] ) );
|
547 |
}
|
548 |
+
}
|
549 |
+
|
550 |
+
elseif ( '_job_author' === $key ) {
|
551 |
$wpdb->update( $wpdb->posts, array( 'post_author' => $_POST[ $key ] > 0 ? absint( $_POST[ $key ] ) : 0 ), array( 'ID' => $post_id ) );
|
552 |
+
}
|
553 |
+
|
554 |
+
elseif ( '_application' === $key ) {
|
555 |
update_post_meta( $post_id, $key, sanitize_text_field( is_email( $_POST[ $key ] ) ? $_POST[ $key ] : urldecode( $_POST[ $key ] ) ) );
|
556 |
+
}
|
557 |
+
|
558 |
+
// Everything else
|
559 |
+
else {
|
560 |
$type = ! empty( $field['type'] ) ? $field['type'] : '';
|
561 |
|
562 |
switch ( $type ) {
|
563 |
+
case 'textarea' :
|
564 |
update_post_meta( $post_id, $key, wp_kses_post( stripslashes( $_POST[ $key ] ) ) );
|
565 |
+
break;
|
566 |
+
case 'checkbox' :
|
567 |
if ( isset( $_POST[ $key ] ) ) {
|
568 |
update_post_meta( $post_id, $key, 1 );
|
569 |
} else {
|
570 |
update_post_meta( $post_id, $key, 0 );
|
571 |
}
|
572 |
+
break;
|
573 |
+
default :
|
574 |
if ( ! isset( $_POST[ $key ] ) ) {
|
575 |
continue;
|
576 |
} elseif ( is_array( $_POST[ $key ] ) ) {
|
578 |
} else {
|
579 |
update_post_meta( $post_id, $key, sanitize_text_field( $_POST[ $key ] ) );
|
580 |
}
|
581 |
+
break;
|
582 |
}
|
583 |
}
|
584 |
}
|
585 |
|
586 |
/* Set Post Status To Expired If Already Expired */
|
587 |
+
$expiry_date = get_post_meta( $post_id, '_job_expires', true );
|
588 |
+
$today_date = date( 'Y-m-d', current_time( 'timestamp' ) );
|
589 |
$is_job_listing_expired = $expiry_date && $today_date > $expiry_date;
|
590 |
+
if( $is_job_listing_expired ) {
|
591 |
remove_action( 'job_manager_save_job_listing', array( $this, 'save_job_listing_data' ), 20, 2 );
|
592 |
+
if ( $this->is_job_listing_being_reactivated() ) {
|
593 |
update_post_meta( $post_id, '_job_expires', calculate_job_expiry( $post_id ) );
|
594 |
} else {
|
595 |
$job_data = array(
|
603 |
}
|
604 |
|
605 |
/**
|
606 |
+
* Checks if the job listing is being reactivated from an expired state.
|
|
|
|
|
|
|
607 |
*
|
608 |
+
* @return bool True if being reactivated.
|
609 |
*/
|
610 |
+
protected function is_job_listing_being_reactivated() {
|
611 |
return isset( $_POST['post_status'] )
|
612 |
&& isset( $_POST['original_post_status'] )
|
613 |
+
&& 'expired' === $_POST['original_post_status']
|
614 |
+
&& 'publish' === $_POST['post_status'];
|
|
|
|
|
|
|
|
|
615 |
}
|
616 |
}
|
617 |
|
includes/admin/views/html-admin-page-addons.php
DELETED
@@ -1,72 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
echo '<h1 class="screen-reader-text">' . esc_html__( 'WP Job Manager Add-ons', 'wp-job-manager' ) . '</h1>';
|
3 |
-
if ( ! empty( $messages ) ) {
|
4 |
-
foreach ( $messages as $message ) {
|
5 |
-
if ( empty( $message->message ) ) {
|
6 |
-
continue;
|
7 |
-
}
|
8 |
-
$type = 'info';
|
9 |
-
if ( isset( $message->type )
|
10 |
-
&& in_array( $message->type, array( 'info', 'success', 'warning', 'error' ), true ) ) {
|
11 |
-
$type = $message->type;
|
12 |
-
}
|
13 |
-
$action_label = isset( $message->action_label ) ? esc_attr( $message->action_label ) : __( 'More Information →', 'wp-job-manager' );
|
14 |
-
$action_url = isset( $message->action_url ) ? esc_url( $message->action_url, array( 'http', 'https' ) ) : false;
|
15 |
-
$action_target = isset( $message->action_target ) && 'self' === $message->action_target ? '_self' : '_blank';
|
16 |
-
$action_str = '';
|
17 |
-
if ( $action_url ) {
|
18 |
-
$action_str = ' <a href="' . esc_url( $action_url ) . '" target="' . esc_attr( $action_target ) . '" class="button">' . esc_html( $action_label ) . '</a>';
|
19 |
-
}
|
20 |
-
|
21 |
-
echo '<div class="notice notice-' . esc_attr( $type ) . ' below-h2"><p><strong>' . esc_html( $message->message ) . '</strong>' . wp_kses_post( $action_str ) . '</p></div>';
|
22 |
-
}
|
23 |
-
}
|
24 |
-
if ( ! empty( $categories ) ) {
|
25 |
-
$current_category = isset( $_GET['category'] ) ? $_GET['category'] : '_all';
|
26 |
-
echo '<ul class="subsubsub">';
|
27 |
-
foreach ( $categories as $category ) {
|
28 |
-
?>
|
29 |
-
<li>
|
30 |
-
<a class="<?php echo $current_category === $category->slug ? 'current' : ''; ?>"
|
31 |
-
href="<?php echo esc_url( admin_url( 'edit.php?post_type=job_listing&page=job-manager-addons&category=' . esc_attr( $category->slug ) ) ); ?>">
|
32 |
-
<?php echo esc_html( $category->label ); ?>
|
33 |
-
</a>
|
34 |
-
</li>
|
35 |
-
<?php
|
36 |
-
}
|
37 |
-
echo '</ul>';
|
38 |
-
}
|
39 |
-
|
40 |
-
echo '<br class="clear" />';
|
41 |
-
|
42 |
-
if ( empty( $add_ons ) ) {
|
43 |
-
echo '<div class="notice notice-warning below-h2"><p><strong>' . esc_html__( 'No add-ons were found.', 'wp-job-manager' ) . '</strong></p></div>';
|
44 |
-
} else {
|
45 |
-
echo '<ul class="products">';
|
46 |
-
foreach ( $add_ons as $add_on ) {
|
47 |
-
$url = add_query_arg(
|
48 |
-
array(
|
49 |
-
'utm_source' => 'product',
|
50 |
-
'utm_medium' => 'addonpage',
|
51 |
-
'utm_campaign' => 'wpjmplugin',
|
52 |
-
'utm_content' => 'listing',
|
53 |
-
), $add_on->link
|
54 |
-
);
|
55 |
-
?>
|
56 |
-
<li class="product">
|
57 |
-
<a href="<?php echo esc_url( $url, array( 'http', 'https' ) ); ?>">
|
58 |
-
<?php if ( ! empty( $add_on->image ) ) : ?>
|
59 |
-
<img src="<?php echo esc_url( $add_on->image ); ?>" />
|
60 |
-
<?php endif; ?>
|
61 |
-
<h2><?php echo esc_html( $add_on->title ); ?></h2>
|
62 |
-
<p><?php echo esc_html( $add_on->excerpt ); ?>
|
63 |
-
<?php if ( ! empty( $add_on->price ) ) : ?>
|
64 |
-
<span class="price"><?php echo esc_html( $add_on->price ); ?></span>
|
65 |
-
<?php endif; ?>
|
66 |
-
</p>
|
67 |
-
</a>
|
68 |
-
</li>
|
69 |
-
<?php
|
70 |
-
}
|
71 |
-
echo '</ul>';
|
72 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-wp-job-manager-ajax.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
|
3 |
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly
|
5 |
}
|
6 |
|
7 |
/**
|
@@ -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 |
*/
|
@@ -41,11 +41,11 @@ class WP_Job_Manager_Ajax {
|
|
41 |
add_action( 'init', array( __CLASS__, 'add_endpoint' ) );
|
42 |
add_action( 'template_redirect', array( __CLASS__, 'do_jm_ajax' ), 0 );
|
43 |
|
44 |
-
// JM Ajax endpoints
|
45 |
add_action( 'job_manager_ajax_get_listings', array( $this, 'get_listings' ) );
|
46 |
add_action( 'job_manager_ajax_upload_file', array( $this, 'upload_file' ) );
|
47 |
|
48 |
-
// BW compatible handlers
|
49 |
add_action( 'wp_ajax_nopriv_job_manager_get_listings', array( $this, 'get_listings' ) );
|
50 |
add_action( 'wp_ajax_job_manager_get_listings', array( $this, 'get_listings' ) );
|
51 |
add_action( 'wp_ajax_nopriv_job_manager_upload_file', array( $this, 'upload_file' ) );
|
@@ -64,8 +64,8 @@ class WP_Job_Manager_Ajax {
|
|
64 |
/**
|
65 |
* Gets Job Manager's Ajax Endpoint.
|
66 |
*
|
67 |
-
* @param string $request Optional
|
68 |
-
* @param string $ssl (Unused) Optional
|
69 |
* @return string
|
70 |
*/
|
71 |
public static function get_endpoint( $request = '%%endpoint%%', $ssl = null ) {
|
@@ -89,13 +89,12 @@ class WP_Job_Manager_Ajax {
|
|
89 |
$wp_query->set( 'jm-ajax', sanitize_text_field( $_GET['jm-ajax'] ) );
|
90 |
}
|
91 |
|
92 |
-
$action = $wp_query->get( 'jm-ajax' )
|
93 |
-
if ( $action ) {
|
94 |
if ( ! defined( 'DOING_AJAX' ) ) {
|
95 |
define( 'DOING_AJAX', true );
|
96 |
}
|
97 |
|
98 |
-
// Not home - this is an ajax endpoint
|
99 |
$wp_query->is_home = false;
|
100 |
|
101 |
/**
|
@@ -115,15 +114,14 @@ class WP_Job_Manager_Ajax {
|
|
115 |
public function get_listings() {
|
116 |
global $wp_post_types;
|
117 |
|
118 |
-
$result
|
119 |
-
$search_location
|
120 |
-
$search_keywords
|
121 |
-
$search_categories
|
122 |
-
$filter_job_types
|
123 |
-
$
|
124 |
-
$
|
125 |
-
$
|
126 |
-
$orderby = sanitize_text_field( $_REQUEST['orderby'] );
|
127 |
|
128 |
if ( is_array( $search_categories ) ) {
|
129 |
$search_categories = array_filter( array_map( 'sanitize_text_field', array_map( 'stripslashes', $search_categories ) ) );
|
@@ -132,23 +130,22 @@ class WP_Job_Manager_Ajax {
|
|
132 |
}
|
133 |
|
134 |
$args = array(
|
135 |
-
'search_location'
|
136 |
-
'search_keywords'
|
137 |
-
'search_categories'
|
138 |
-
'job_types'
|
139 |
-
'
|
140 |
-
'
|
141 |
-
'
|
142 |
-
'
|
143 |
-
'posts_per_page' => max( 1, absint( $_REQUEST['per_page'] ) ),
|
144 |
);
|
145 |
|
146 |
-
if ( isset( $_REQUEST['filled'] ) && (
|
147 |
-
$args['filled'] = '
|
148 |
}
|
149 |
|
150 |
-
if ( isset( $_REQUEST['featured'] ) && (
|
151 |
-
$args['featured'] = '
|
152 |
$args['orderby'] = 'featured' === $orderby ? 'date' : $orderby;
|
153 |
}
|
154 |
|
@@ -157,19 +154,18 @@ class WP_Job_Manager_Ajax {
|
|
157 |
*
|
158 |
* @since 1.0.0
|
159 |
*
|
160 |
-
* @param array $args Arguments used for generating Job Listing query (see `get_job_listings()`)
|
161 |
*/
|
162 |
$jobs = get_job_listings( apply_filters( 'job_manager_get_listings_args', $args ) );
|
163 |
|
164 |
$result = array(
|
165 |
-
'found_jobs'
|
166 |
-
'showing'
|
167 |
'max_num_pages' => $jobs->max_num_pages,
|
168 |
);
|
169 |
|
170 |
if ( $jobs->post_count && ( $search_location || $search_keywords || $search_categories ) ) {
|
171 |
-
|
172 |
-
$message = sprintf( _n( 'Search completed. Found %d matching record.', 'Search completed. Found %d matching records.', $jobs->found_posts, 'wp-job-manager' ), $jobs->found_posts );
|
173 |
$result['showing_all'] = true;
|
174 |
} else {
|
175 |
$message = '';
|
@@ -197,15 +193,13 @@ class WP_Job_Manager_Ajax {
|
|
197 |
*/
|
198 |
$result['showing'] = apply_filters( 'job_manager_get_listings_custom_filter_text', $message, $search_values );
|
199 |
|
200 |
-
// Generate RSS link
|
201 |
-
$result['showing_links'] = job_manager_get_filtered_links(
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
)
|
208 |
-
);
|
209 |
|
210 |
/**
|
211 |
* Send back a response to the AJAX request without creating HTML.
|
@@ -238,19 +232,24 @@ class WP_Job_Manager_Ajax {
|
|
238 |
|
239 |
ob_start();
|
240 |
|
241 |
-
if ( $result['found_jobs'] )
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
|
|
|
|
|
|
|
|
|
|
249 |
|
250 |
$result['html'] = ob_get_clean();
|
251 |
|
252 |
-
// Generate pagination
|
253 |
-
if ( isset( $_REQUEST['show_pagination'] ) &&
|
254 |
$result['pagination'] = get_job_listing_pagination( $jobs->max_num_pages, absint( $_REQUEST['page'] ) );
|
255 |
}
|
256 |
|
@@ -265,7 +264,7 @@ class WP_Job_Manager_Ajax {
|
|
265 |
*/
|
266 |
public function upload_file() {
|
267 |
if ( ! job_manager_user_can_upload_file_via_ajax() ) {
|
268 |
-
wp_send_json_error( __( 'You must be logged in to upload files using this method.', 'wp-job-manager' ) );
|
269 |
return;
|
270 |
}
|
271 |
$data = array(
|
@@ -276,12 +275,9 @@ class WP_Job_Manager_Ajax {
|
|
276 |
foreach ( $_FILES as $file_key => $file ) {
|
277 |
$files_to_upload = job_manager_prepare_uploaded_files( $file );
|
278 |
foreach ( $files_to_upload as $file_to_upload ) {
|
279 |
-
$uploaded_file = job_manager_upload_file(
|
280 |
-
$
|
281 |
-
|
282 |
-
'file_key' => $file_key,
|
283 |
-
)
|
284 |
-
);
|
285 |
|
286 |
if ( is_wp_error( $uploaded_file ) ) {
|
287 |
$data['files'][] = array(
|
1 |
<?php
|
2 |
|
3 |
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
+
exit; // Exit if accessed directly
|
5 |
}
|
6 |
|
7 |
/**
|
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 |
*/
|
41 |
add_action( 'init', array( __CLASS__, 'add_endpoint' ) );
|
42 |
add_action( 'template_redirect', array( __CLASS__, 'do_jm_ajax' ), 0 );
|
43 |
|
44 |
+
// JM Ajax endpoints
|
45 |
add_action( 'job_manager_ajax_get_listings', array( $this, 'get_listings' ) );
|
46 |
add_action( 'job_manager_ajax_upload_file', array( $this, 'upload_file' ) );
|
47 |
|
48 |
+
// BW compatible handlers
|
49 |
add_action( 'wp_ajax_nopriv_job_manager_get_listings', array( $this, 'get_listings' ) );
|
50 |
add_action( 'wp_ajax_job_manager_get_listings', array( $this, 'get_listings' ) );
|
51 |
add_action( 'wp_ajax_nopriv_job_manager_upload_file', array( $this, 'upload_file' ) );
|
64 |
/**
|
65 |
* Gets Job Manager's Ajax Endpoint.
|
66 |
*
|
67 |
+
* @param string $request Optional
|
68 |
+
* @param string $ssl (Unused) Optional
|
69 |
* @return string
|
70 |
*/
|
71 |
public static function get_endpoint( $request = '%%endpoint%%', $ssl = null ) {
|
89 |
$wp_query->set( 'jm-ajax', sanitize_text_field( $_GET['jm-ajax'] ) );
|
90 |
}
|
91 |
|
92 |
+
if ( $action = $wp_query->get( 'jm-ajax' ) ) {
|
|
|
93 |
if ( ! defined( 'DOING_AJAX' ) ) {
|
94 |
define( 'DOING_AJAX', true );
|
95 |
}
|
96 |
|
97 |
+
// Not home - this is an ajax endpoint
|
98 |
$wp_query->is_home = false;
|
99 |
|
100 |
/**
|
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 ) ) );
|
130 |
}
|
131 |
|
132 |
$args = array(
|
133 |
+
'search_location' => $search_location,
|
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'] ),
|
140 |
+
'posts_per_page' => absint( $_REQUEST['per_page'] ),
|
|
|
141 |
);
|
142 |
|
143 |
+
if ( isset( $_REQUEST['filled'] ) && ( $_REQUEST['filled'] === 'true' || $_REQUEST['filled'] === 'false' ) ) {
|
144 |
+
$args['filled'] = $_REQUEST['filled'] === 'true' ? true : false;
|
145 |
}
|
146 |
|
147 |
+
if ( isset( $_REQUEST['featured'] ) && ( $_REQUEST['featured'] === 'true' || $_REQUEST['featured'] === 'false' ) ) {
|
148 |
+
$args['featured'] = $_REQUEST['featured'] === 'true' ? true : false;
|
149 |
$args['orderby'] = 'featured' === $orderby ? 'date' : $orderby;
|
150 |
}
|
151 |
|
154 |
*
|
155 |
* @since 1.0.0
|
156 |
*
|
157 |
+
* @param array $args Arguments used for generating Job Listing query (see `get_job_listings()`)
|
158 |
*/
|
159 |
$jobs = get_job_listings( apply_filters( 'job_manager_get_listings_args', $args ) );
|
160 |
|
161 |
$result = array(
|
162 |
+
'found_jobs' => $jobs->have_posts(),
|
163 |
+
'showing' => '',
|
164 |
'max_num_pages' => $jobs->max_num_pages,
|
165 |
);
|
166 |
|
167 |
if ( $jobs->post_count && ( $search_location || $search_keywords || $search_categories ) ) {
|
168 |
+
$message = sprintf( _n( 'Search completed. Found %d matching record.', 'Search completed. Found %d matching records.', $jobs->found_posts, 'wp-job-manager' ), $jobs->found_posts );
|
|
|
169 |
$result['showing_all'] = true;
|
170 |
} else {
|
171 |
$message = '';
|
193 |
*/
|
194 |
$result['showing'] = apply_filters( 'job_manager_get_listings_custom_filter_text', $message, $search_values );
|
195 |
|
196 |
+
// Generate RSS link
|
197 |
+
$result['showing_links'] = job_manager_get_filtered_links( array(
|
198 |
+
'filter_job_types' => $filter_job_types,
|
199 |
+
'search_location' => $search_location,
|
200 |
+
'search_categories' => $search_categories,
|
201 |
+
'search_keywords' => $search_keywords,
|
202 |
+
) );
|
|
|
|
|
203 |
|
204 |
/**
|
205 |
* Send back a response to the AJAX request without creating HTML.
|
232 |
|
233 |
ob_start();
|
234 |
|
235 |
+
if ( $result['found_jobs'] ) : ?>
|
236 |
+
|
237 |
+
<?php while ( $jobs->have_posts() ) : $jobs->the_post(); ?>
|
238 |
+
|
239 |
+
<?php get_job_manager_template_part( 'content', 'job_listing' ); ?>
|
240 |
+
|
241 |
+
<?php endwhile; ?>
|
242 |
+
|
243 |
+
<?php else : ?>
|
244 |
+
|
245 |
+
<?php get_job_manager_template_part( 'content', 'no-jobs-found' ); ?>
|
246 |
+
|
247 |
+
<?php endif;
|
248 |
|
249 |
$result['html'] = ob_get_clean();
|
250 |
|
251 |
+
// Generate pagination
|
252 |
+
if ( isset( $_REQUEST['show_pagination'] ) && $_REQUEST['show_pagination'] === 'true' ) {
|
253 |
$result['pagination'] = get_job_listing_pagination( $jobs->max_num_pages, absint( $_REQUEST['page'] ) );
|
254 |
}
|
255 |
|
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(
|
275 |
foreach ( $_FILES as $file_key => $file ) {
|
276 |
$files_to_upload = job_manager_prepare_uploaded_files( $file );
|
277 |
foreach ( $files_to_upload as $file_to_upload ) {
|
278 |
+
$uploaded_file = job_manager_upload_file( $file_to_upload, array(
|
279 |
+
'file_key' => $file_key,
|
280 |
+
) );
|
|
|
|
|
|
|
281 |
|
282 |
if ( is_wp_error( $uploaded_file ) ) {
|
283 |
$data['files'][] = array(
|
includes/class-wp-job-manager-api.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
|
3 |
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly
|
5 |
}
|
6 |
|
7 |
/**
|
@@ -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 |
*/
|
@@ -45,7 +45,7 @@ class WP_Job_Manager_API {
|
|
45 |
/**
|
46 |
* Adds query vars used in API calls.
|
47 |
*
|
48 |
-
* @param array $vars the query vars
|
49 |
* @return array
|
50 |
*/
|
51 |
public function add_query_vars( $vars ) {
|
@@ -71,13 +71,13 @@ class WP_Job_Manager_API {
|
|
71 |
}
|
72 |
|
73 |
if ( ! empty( $wp->query_vars['job-manager-api'] ) ) {
|
74 |
-
// Buffer, we won't want any output here
|
75 |
ob_start();
|
76 |
|
77 |
-
// Get API trigger
|
78 |
$api = strtolower( esc_attr( $wp->query_vars['job-manager-api'] ) );
|
79 |
|
80 |
-
// Load class if exists
|
81 |
if ( has_action( 'job_manager_api_' . $api ) && class_exists( $api ) ) {
|
82 |
$api_class = new $api();
|
83 |
}
|
@@ -90,7 +90,7 @@ class WP_Job_Manager_API {
|
|
90 |
*/
|
91 |
do_action( 'job_manager_api_' . $api );
|
92 |
|
93 |
-
// Done, clear buffer and exit
|
94 |
ob_end_clean();
|
95 |
wp_die();
|
96 |
}
|
1 |
<?php
|
2 |
|
3 |
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
+
exit; // Exit if accessed directly
|
5 |
}
|
6 |
|
7 |
/**
|
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 |
*/
|
45 |
/**
|
46 |
* Adds query vars used in API calls.
|
47 |
*
|
48 |
+
* @param array $vars the query vars
|
49 |
* @return array
|
50 |
*/
|
51 |
public function add_query_vars( $vars ) {
|
71 |
}
|
72 |
|
73 |
if ( ! empty( $wp->query_vars['job-manager-api'] ) ) {
|
74 |
+
// Buffer, we won't want any output here
|
75 |
ob_start();
|
76 |
|
77 |
+
// Get API trigger
|
78 |
$api = strtolower( esc_attr( $wp->query_vars['job-manager-api'] ) );
|
79 |
|
80 |
+
// Load class if exists
|
81 |
if ( has_action( 'job_manager_api_' . $api ) && class_exists( $api ) ) {
|
82 |
$api_class = new $api();
|
83 |
}
|
90 |
*/
|
91 |
do_action( 'job_manager_api_' . $api );
|
92 |
|
93 |
+
// Done, clear buffer and exit
|
94 |
ob_end_clean();
|
95 |
wp_die();
|
96 |
}
|
includes/class-wp-job-manager-cache-helper.php
CHANGED
@@ -17,15 +17,12 @@ class WP_Job_Manager_Cache_Helper {
|
|
17 |
*/
|
18 |
public static function init() {
|
19 |
add_action( 'save_post', array( __CLASS__, 'flush_get_job_listings_cache' ) );
|
20 |
-
add_action( 'delete_post', array( __CLASS__, 'flush_get_job_listings_cache' ) );
|
21 |
-
add_action( 'trash_post', array( __CLASS__, 'flush_get_job_listings_cache' ) );
|
22 |
add_action( 'job_manager_my_job_do_action', array( __CLASS__, 'job_manager_my_job_do_action' ) );
|
23 |
add_action( 'set_object_terms', array( __CLASS__, 'set_term' ), 10, 4 );
|
24 |
add_action( 'edited_term', array( __CLASS__, 'edited_term' ), 10, 3 );
|
25 |
add_action( 'create_term', array( __CLASS__, 'edited_term' ), 10, 3 );
|
26 |
add_action( 'delete_term', array( __CLASS__, 'edited_term' ), 10, 3 );
|
27 |
add_action( 'job_manager_clear_expired_transients', array( __CLASS__, 'clear_expired_transients' ), 10 );
|
28 |
-
add_action( 'transition_post_status', array( __CLASS__, 'maybe_clear_count_transients' ), 10, 3 );
|
29 |
}
|
30 |
|
31 |
/**
|
@@ -111,7 +108,7 @@ class WP_Job_Manager_Cache_Helper {
|
|
111 |
private static function delete_version_transients( $version ) {
|
112 |
if ( ! wp_using_ext_object_cache() && ! empty( $version ) ) {
|
113 |
global $wpdb;
|
114 |
-
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s;",
|
115 |
}
|
116 |
}
|
117 |
|
@@ -122,125 +119,15 @@ class WP_Job_Manager_Cache_Helper {
|
|
122 |
global $wpdb;
|
123 |
|
124 |
if ( ! wp_using_ext_object_cache() && ! defined( 'WP_SETUP_CONFIG' ) && ! defined( 'WP_INSTALLING' ) ) {
|
125 |
-
$
|
126 |
DELETE a, b FROM $wpdb->options a, $wpdb->options b
|
127 |
WHERE a.option_name LIKE %s
|
128 |
AND a.option_name NOT LIKE %s
|
129 |
AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )
|
130 |
-
AND b.option_value < %s;"
|
131 |
-
|
132 |
-
$wpdb->esc_like( '_transient_timeout_jm_' ) . '%',
|
133 |
-
time()
|
134 |
-
) );
|
135 |
}
|
136 |
}
|
137 |
-
|
138 |
-
/**
|
139 |
-
* Maybe remove pending count transients
|
140 |
-
*
|
141 |
-
* When a supported post type status is updated, check if any cached count transients
|
142 |
-
* need to be removed, and remove the
|
143 |
-
*
|
144 |
-
* @since 1.27.0
|
145 |
-
*
|
146 |
-
* @param string $new_status New post status.
|
147 |
-
* @param string $old_status Old post status.
|
148 |
-
* @param WP_Post $post Post object.
|
149 |
-
*/
|
150 |
-
public static function maybe_clear_count_transients( $new_status, $old_status, $post ) {
|
151 |
-
global $wpdb;
|
152 |
-
|
153 |
-
/**
|
154 |
-
* Get supported post types for count caching
|
155 |
-
*
|
156 |
-
* @since 1.27.0
|
157 |
-
*
|
158 |
-
* @param array $post_types Post types that should be cached.
|
159 |
-
* @param string $new_status New post status.
|
160 |
-
* @param string $old_status Old post status.
|
161 |
-
* @param WP_Post $post Post object.
|
162 |
-
*/
|
163 |
-
$post_types = apply_filters( 'wpjm_count_cache_supported_post_types', array( 'job_listing' ), $new_status, $old_status, $post );
|
164 |
-
|
165 |
-
// Only proceed when statuses do not match, and post type is supported post type.
|
166 |
-
if ( $new_status === $old_status || ! in_array( $post->post_type, $post_types, true ) ) {
|
167 |
-
return;
|
168 |
-
}
|
169 |
-
|
170 |
-
/**
|
171 |
-
* Get supported post statuses for count caching
|
172 |
-
*
|
173 |
-
* @since 1.27.0
|
174 |
-
*
|
175 |
-
* @param array $post_statuses Post statuses that should be cached.
|
176 |
-
* @param string $new_status New post status.
|
177 |
-
* @param string $old_status Old post status.
|
178 |
-
* @param WP_Post $post Post object.
|
179 |
-
*/
|
180 |
-
$valid_statuses = apply_filters( 'wpjm_count_cache_supported_statuses', array( 'pending' ), $new_status, $old_status, $post );
|
181 |
-
|
182 |
-
$rlike = array();
|
183 |
-
// New status transient option name.
|
184 |
-
if ( in_array( $new_status, $valid_statuses, true ) ) {
|
185 |
-
$rlike[] = "^_transient_jm_{$new_status}_{$post->post_type}_count_user_";
|
186 |
-
}
|
187 |
-
// Old status transient option name.
|
188 |
-
if ( in_array( $old_status, $valid_statuses, true ) ) {
|
189 |
-
$rlike[] = "^_transient_jm_{$old_status}_{$post->post_type}_count_user_";
|
190 |
-
}
|
191 |
-
|
192 |
-
if ( empty( $rlike ) ) {
|
193 |
-
return;
|
194 |
-
}
|
195 |
-
|
196 |
-
$transients = $wpdb->get_col( $wpdb->prepare(
|
197 |
-
"SELECT option_name FROM $wpdb->options WHERE option_name RLIKE %s",
|
198 |
-
implode( '|', $rlike )
|
199 |
-
) );
|
200 |
-
|
201 |
-
// For each transient...
|
202 |
-
foreach ( $transients as $transient ) {
|
203 |
-
// Strip away the WordPress prefix in order to arrive at the transient key.
|
204 |
-
$key = str_replace( '_transient_', '', $transient );
|
205 |
-
// Now that we have the key, use WordPress core to the delete the transient.
|
206 |
-
delete_transient( $key );
|
207 |
-
}
|
208 |
-
|
209 |
-
// Sometimes transients are not in the DB, so we have to do this too:.
|
210 |
-
wp_cache_flush();
|
211 |
-
}
|
212 |
-
|
213 |
-
/**
|
214 |
-
* Get Listings Count from Cache
|
215 |
-
*
|
216 |
-
* @since 1.27.0
|
217 |
-
*
|
218 |
-
* @param string $post_type
|
219 |
-
* @param string $status
|
220 |
-
* @param bool $force Force update cache.
|
221 |
-
*
|
222 |
-
* @return int
|
223 |
-
*/
|
224 |
-
public static function get_listings_count( $post_type = 'job_listing', $status = 'pending', $force = false ) {
|
225 |
-
|
226 |
-
// Get user based cache transient.
|
227 |
-
$user_id = get_current_user_id();
|
228 |
-
$transient = "jm_{$status}_{$post_type}_count_user_{$user_id}";
|
229 |
-
|
230 |
-
// Set listings_count value from cache if exists, otherwise set to 0 as default.
|
231 |
-
$cached_count = get_transient( $transient );
|
232 |
-
$status_count = $cached_count ? $cached_count : 0;
|
233 |
-
|
234 |
-
// $cached_count will be false if transient does not exist.
|
235 |
-
if ( false === $cached_count || $force ) {
|
236 |
-
$count_posts = wp_count_posts( $post_type, 'readable' );
|
237 |
-
// Default to 0 $status if object does not have a value.
|
238 |
-
$status_count = isset( $count_posts->$status ) ? $count_posts->$status : 0;
|
239 |
-
set_transient( $transient, $status_count, DAY_IN_SECONDS * 7 );
|
240 |
-
}
|
241 |
-
|
242 |
-
return $status_count;
|
243 |
-
}
|
244 |
}
|
245 |
|
246 |
WP_Job_Manager_Cache_Helper::init();
|
17 |
*/
|
18 |
public static function init() {
|
19 |
add_action( 'save_post', array( __CLASS__, 'flush_get_job_listings_cache' ) );
|
|
|
|
|
20 |
add_action( 'job_manager_my_job_do_action', array( __CLASS__, 'job_manager_my_job_do_action' ) );
|
21 |
add_action( 'set_object_terms', array( __CLASS__, 'set_term' ), 10, 4 );
|
22 |
add_action( 'edited_term', array( __CLASS__, 'edited_term' ), 10, 3 );
|
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 |
/**
|
108 |
private static function delete_version_transients( $version ) {
|
109 |
if ( ! wp_using_ext_object_cache() && ! empty( $version ) ) {
|
110 |
global $wpdb;
|
111 |
+
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s;", "\_transient\_%" . $version ) );
|
112 |
}
|
113 |
}
|
114 |
|
119 |
global $wpdb;
|
120 |
|
121 |
if ( ! wp_using_ext_object_cache() && ! defined( 'WP_SETUP_CONFIG' ) && ! defined( 'WP_INSTALLING' ) ) {
|
122 |
+
$sql = "
|
123 |
DELETE a, b FROM $wpdb->options a, $wpdb->options b
|
124 |
WHERE a.option_name LIKE %s
|
125 |
AND a.option_name NOT LIKE %s
|
126 |
AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )
|
127 |
+
AND b.option_value < %s;";
|
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();
|
includes/class-wp-job-manager-category-walker.php
CHANGED
@@ -1,7 +1,5 @@
|
|
1 |
<?php
|
2 |
-
if ( ! defined( 'ABSPATH' ) )
|
3 |
-
exit; // Exit if accessed directly.
|
4 |
-
}
|
5 |
|
6 |
/**
|
7 |
* Walks through categories.
|
@@ -24,15 +22,9 @@ class WP_Job_Manager_Category_Walker extends Walker {
|
|
24 |
*
|
25 |
* @var array
|
26 |
*/
|
27 |
-
public $db_fields = array(
|
28 |
-
'parent' => 'parent',
|
29 |
-
'id' => 'term_id',
|
30 |
-
'slug' => 'slug',
|
31 |
-
);
|
32 |
|
33 |
/**
|
34 |
-
* Start the list walker.
|
35 |
-
*
|
36 |
* @see Walker::start_el()
|
37 |
* @since 2.1.0
|
38 |
*
|
@@ -44,32 +36,26 @@ class WP_Job_Manager_Category_Walker extends Walker {
|
|
44 |
*/
|
45 |
public function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
|
46 |
|
47 |
-
if ( ! empty( $args['hierarchical'] ) )
|
48 |
-
$pad = str_repeat(
|
49 |
-
|
50 |
$pad = '';
|
51 |
-
}
|
52 |
|
53 |
$cat_name = apply_filters( 'list_product_cats', $object->name, $object );
|
54 |
|
55 |
-
$value = isset( $args['value'] ) &&
|
56 |
|
57 |
-
$output .= "\t<option class=\"level
|
58 |
|
59 |
-
if (
|
60 |
-
$value == $args['selected'] // phpcs:ignore WordPress.PHP.StrictComparisons
|
61 |
-
|| ( is_array( $args['selected'] ) && in_array( $value, $args['selected'] ) ) // phpcs:ignore WordPress.PHP.StrictInArray
|
62 |
-
)
|
63 |
-
) {
|
64 |
$output .= ' selected="selected"';
|
65 |
-
}
|
66 |
|
67 |
$output .= '>';
|
68 |
|
69 |
-
$output .= $pad .
|
70 |
|
71 |
if ( ! empty( $args['show_count'] ) ) {
|
72 |
-
$output .= ' (' .
|
73 |
}
|
74 |
|
75 |
$output .= "</option>\n";
|
1 |
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
3 |
|
4 |
/**
|
5 |
* Walks through categories.
|
22 |
*
|
23 |
* @var array
|
24 |
*/
|
25 |
+
public $db_fields = array ('parent' => 'parent', 'id' => 'term_id', 'slug' => 'slug' );
|
|
|
|
|
|
|
|
|
26 |
|
27 |
/**
|
|
|
|
|
28 |
* @see Walker::start_el()
|
29 |
* @since 2.1.0
|
30 |
*
|
36 |
*/
|
37 |
public function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
|
38 |
|
39 |
+
if ( ! empty( $args['hierarchical'] ) )
|
40 |
+
$pad = str_repeat(' ', $depth * 3);
|
41 |
+
else
|
42 |
$pad = '';
|
|
|
43 |
|
44 |
$cat_name = apply_filters( 'list_product_cats', $object->name, $object );
|
45 |
|
46 |
+
$value = isset( $args['value'] ) && $args['value'] == 'id' ? $object->term_id : $object->slug;
|
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 .= '>';
|
54 |
|
55 |
+
$output .= $pad . $cat_name;
|
56 |
|
57 |
if ( ! empty( $args['show_count'] ) ) {
|
58 |
+
$output .= ' (' . $object->count . ')';
|
59 |
}
|
60 |
|
61 |
$output .= "</option>\n";
|
includes/class-wp-job-manager-data-cleaner.php
DELETED
@@ -1,367 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Defines a class with methods for cleaning up plugin data. To be used when
|
4 |
-
* the plugin is deleted.
|
5 |
-
*
|
6 |
-
* @package Core
|
7 |
-
*/
|
8 |
-
|
9 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
-
// Exit if accessed directly.
|
11 |
-
exit;
|
12 |
-
}
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Methods for cleaning up all plugin data.
|
16 |
-
*
|
17 |
-
* @author Automattic
|
18 |
-
* @since 1.31.0
|
19 |
-
*/
|
20 |
-
class WP_Job_Manager_Data_Cleaner {
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Custom post types to be deleted.
|
24 |
-
*
|
25 |
-
* @var $custom_post_types
|
26 |
-
*/
|
27 |
-
private static $custom_post_types = array(
|
28 |
-
'job_listing',
|
29 |
-
);
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Taxonomies to be deleted.
|
33 |
-
*
|
34 |
-
* @var $taxonomies
|
35 |
-
*/
|
36 |
-
private static $taxonomies = array(
|
37 |
-
'job_listing_category',
|
38 |
-
'job_listing_type',
|
39 |
-
);
|
40 |
-
|
41 |
-
/** Cron jobs to be unscheduled.
|
42 |
-
*
|
43 |
-
* @var $cron_jobs
|
44 |
-
*/
|
45 |
-
private static $cron_jobs = array(
|
46 |
-
'job_manager_check_for_expired_jobs',
|
47 |
-
'job_manager_delete_old_previews',
|
48 |
-
'job_manager_clear_expired_transients',
|
49 |
-
'job_manager_email_daily_notices',
|
50 |
-
'job_manager_usage_tracking_send_usage_data',
|
51 |
-
);
|
52 |
-
|
53 |
-
/**
|
54 |
-
* Options to be deleted.
|
55 |
-
*
|
56 |
-
* @var $options
|
57 |
-
*/
|
58 |
-
private static $options = array(
|
59 |
-
'wp_job_manager_version',
|
60 |
-
'job_manager_installed_terms',
|
61 |
-
'wpjm_permalinks',
|
62 |
-
'job_manager_helper',
|
63 |
-
'job_manager_date_format',
|
64 |
-
'job_manager_google_maps_api_key',
|
65 |
-
'job_manager_usage_tracking_enabled',
|
66 |
-
'job_manager_usage_tracking_opt_in_hide',
|
67 |
-
'job_manager_per_page',
|
68 |
-
'job_manager_hide_filled_positions',
|
69 |
-
'job_manager_hide_expired',
|
70 |
-
'job_manager_hide_expired_content',
|
71 |
-
'job_manager_enable_categories',
|
72 |
-
'job_manager_enable_default_category_multiselect',
|
73 |
-
'job_manager_category_filter_type',
|
74 |
-
'job_manager_enable_types',
|
75 |
-
'job_manager_multi_job_type',
|
76 |
-
'job_manager_user_requires_account',
|
77 |
-
'job_manager_enable_registration',
|
78 |
-
'job_manager_generate_username_from_email',
|
79 |
-
'job_manager_use_standard_password_setup_email',
|
80 |
-
'job_manager_registration_role',
|
81 |
-
'job_manager_submission_requires_approval',
|
82 |
-
'job_manager_user_can_edit_pending_submissions',
|
83 |
-
'job_manager_user_edit_published_submissions',
|
84 |
-
'job_manager_submission_duration',
|
85 |
-
'job_manager_allowed_application_method',
|
86 |
-
'job_manager_recaptcha_label',
|
87 |
-
'job_manager_recaptcha_site_key',
|
88 |
-
'job_manager_recaptcha_secret_key',
|
89 |
-
'job_manager_enable_recaptcha_job_submission',
|
90 |
-
'job_manager_submit_job_form_page_id',
|
91 |
-
'job_manager_job_dashboard_page_id',
|
92 |
-
'job_manager_jobs_page_id',
|
93 |
-
'job_manager_submit_page_slug',
|
94 |
-
'job_manager_job_dashboard_page_slug',
|
95 |
-
'job_manager_delete_data_on_uninstall',
|
96 |
-
'job_manager_email_admin_updated_job',
|
97 |
-
'job_manager_email_admin_new_job',
|
98 |
-
'job_manager_email_admin_expiring_job',
|
99 |
-
'job_manager_email_employer_expiring_job',
|
100 |
-
);
|
101 |
-
|
102 |
-
/**
|
103 |
-
* Site options to be deleted.
|
104 |
-
*
|
105 |
-
* @var $site_options
|
106 |
-
*/
|
107 |
-
private static $site_options = array(
|
108 |
-
'job_manager_helper',
|
109 |
-
);
|
110 |
-
|
111 |
-
/**
|
112 |
-
* Transient names (as MySQL regexes) to be deleted. The prefixes
|
113 |
-
* "_transient_" and "_transient_timeout_" will be prepended.
|
114 |
-
*
|
115 |
-
* @var $transients
|
116 |
-
*/
|
117 |
-
private static $transients = array(
|
118 |
-
'_job_manager_activation_redirect',
|
119 |
-
'get_job_listings-transient-version',
|
120 |
-
'jm_.*',
|
121 |
-
);
|
122 |
-
|
123 |
-
/**
|
124 |
-
* Role to be removed.
|
125 |
-
*
|
126 |
-
* @var $role
|
127 |
-
*/
|
128 |
-
private static $role = 'employer';
|
129 |
-
|
130 |
-
/**
|
131 |
-
* Capabilities to be deleted.
|
132 |
-
*
|
133 |
-
* @var $caps
|
134 |
-
*/
|
135 |
-
private static $caps = array(
|
136 |
-
'manage_job_listings',
|
137 |
-
'edit_job_listing',
|
138 |
-
'read_job_listing',
|
139 |
-
'delete_job_listing',
|
140 |
-
'edit_job_listings',
|
141 |
-
'edit_others_job_listings',
|
142 |
-
'publish_job_listings',
|
143 |
-
'read_private_job_listings',
|
144 |
-
'delete_job_listings',
|
145 |
-
'delete_private_job_listings',
|
146 |
-
'delete_published_job_listings',
|
147 |
-
'delete_others_job_listings',
|
148 |
-
'edit_private_job_listings',
|
149 |
-
'edit_published_job_listings',
|
150 |
-
'manage_job_listing_terms',
|
151 |
-
'edit_job_listing_terms',
|
152 |
-
'delete_job_listing_terms',
|
153 |
-
'assign_job_listing_terms',
|
154 |
-
);
|
155 |
-
|
156 |
-
/**
|
157 |
-
* User meta key names to be deleted.
|
158 |
-
*
|
159 |
-
* @var array $user_meta_keys
|
160 |
-
*/
|
161 |
-
private static $user_meta_keys = array(
|
162 |
-
'_company_logo',
|
163 |
-
'_company_name',
|
164 |
-
'_company_website',
|
165 |
-
'_company_tagline',
|
166 |
-
'_company_twitter',
|
167 |
-
'_company_video',
|
168 |
-
);
|
169 |
-
|
170 |
-
/**
|
171 |
-
* Cleanup all data.
|
172 |
-
*
|
173 |
-
* @access public
|
174 |
-
*/
|
175 |
-
public static function cleanup_all() {
|
176 |
-
self::cleanup_custom_post_types();
|
177 |
-
self::cleanup_taxonomies();
|
178 |
-
self::cleanup_pages();
|
179 |
-
self::cleanup_cron_jobs();
|
180 |
-
self::cleanup_roles_and_caps();
|
181 |
-
self::cleanup_transients();
|
182 |
-
self::cleanup_user_meta();
|
183 |
-
self::cleanup_options();
|
184 |
-
self::cleanup_site_options();
|
185 |
-
}
|
186 |
-
|
187 |
-
/**
|
188 |
-
* Cleanup data for custom post types.
|
189 |
-
*
|
190 |
-
* @access private
|
191 |
-
*/
|
192 |
-
private static function cleanup_custom_post_types() {
|
193 |
-
foreach ( self::$custom_post_types as $post_type ) {
|
194 |
-
$items = get_posts(
|
195 |
-
array(
|
196 |
-
'post_type' => $post_type,
|
197 |
-
'post_status' => 'any',
|
198 |
-
'numberposts' => -1,
|
199 |
-
'fields' => 'ids',
|
200 |
-
)
|
201 |
-
);
|
202 |
-
|
203 |
-
foreach ( $items as $item ) {
|
204 |
-
wp_trash_post( $item );
|
205 |
-
}
|
206 |
-
}
|
207 |
-
}
|
208 |
-
|
209 |
-
/**
|
210 |
-
* Cleanup data for taxonomies.
|
211 |
-
*
|
212 |
-
* @access private
|
213 |
-
*/
|
214 |
-
private static function cleanup_taxonomies() {
|
215 |
-
global $wpdb;
|
216 |
-
|
217 |
-
foreach ( self::$taxonomies as $taxonomy ) {
|
218 |
-
$terms = $wpdb->get_results(
|
219 |
-
$wpdb->prepare(
|
220 |
-
"SELECT term_id, term_taxonomy_id FROM $wpdb->term_taxonomy WHERE taxonomy = %s",
|
221 |
-
$taxonomy
|
222 |
-
)
|
223 |
-
);
|
224 |
-
|
225 |
-
// Delete all data for each term.
|
226 |
-
foreach ( $terms as $term ) {
|
227 |
-
$wpdb->delete( $wpdb->term_relationships, array( 'term_taxonomy_id' => $term->term_taxonomy_id ) );
|
228 |
-
$wpdb->delete( $wpdb->term_taxonomy, array( 'term_taxonomy_id' => $term->term_taxonomy_id ) );
|
229 |
-
$wpdb->delete( $wpdb->terms, array( 'term_id' => $term->term_id ) );
|
230 |
-
$wpdb->delete( $wpdb->termmeta, array( 'term_id' => $term->term_id ) );
|
231 |
-
}
|
232 |
-
|
233 |
-
if ( function_exists( 'clean_taxonomy_cache' ) ) {
|
234 |
-
clean_taxonomy_cache( $taxonomy );
|
235 |
-
}
|
236 |
-
}
|
237 |
-
}
|
238 |
-
|
239 |
-
/**
|
240 |
-
* Cleanup data for pages.
|
241 |
-
*
|
242 |
-
* @access private
|
243 |
-
*/
|
244 |
-
private static function cleanup_pages() {
|
245 |
-
// Trash the Submit Job page.
|
246 |
-
$submit_job_form_page_id = get_option( 'job_manager_submit_job_form_page_id' );
|
247 |
-
if ( $submit_job_form_page_id ) {
|
248 |
-
wp_trash_post( $submit_job_form_page_id );
|
249 |
-
}
|
250 |
-
|
251 |
-
// Trash the Job Dashboard page.
|
252 |
-
$job_dashboard_page_id = get_option( 'job_manager_job_dashboard_page_id' );
|
253 |
-
if ( $job_dashboard_page_id ) {
|
254 |
-
wp_trash_post( $job_dashboard_page_id );
|
255 |
-
}
|
256 |
-
|
257 |
-
// Trash the Jobs page.
|
258 |
-
$jobs_page_id = get_option( 'job_manager_jobs_page_id' );
|
259 |
-
if ( $jobs_page_id ) {
|
260 |
-
wp_trash_post( $jobs_page_id );
|
261 |
-
}
|
262 |
-
}
|
263 |
-
|
264 |
-
/**
|
265 |
-
* Cleanup data for options.
|
266 |
-
*
|
267 |
-
* @access private
|
268 |
-
*/
|
269 |
-
private static function cleanup_options() {
|
270 |
-
foreach ( self::$options as $option ) {
|
271 |
-
delete_option( $option );
|
272 |
-
}
|
273 |
-
}
|
274 |
-
|
275 |
-
/**
|
276 |
-
* Cleanup data for site options.
|
277 |
-
*
|
278 |
-
* @access private
|
279 |
-
*/
|
280 |
-
private static function cleanup_site_options() {
|
281 |
-
foreach ( self::$site_options as $option ) {
|
282 |
-
delete_site_option( $option );
|
283 |
-
}
|
284 |
-
}
|
285 |
-
|
286 |
-
/**
|
287 |
-
* Cleanup transients from the database.
|
288 |
-
*
|
289 |
-
* @access private
|
290 |
-
*/
|
291 |
-
private static function cleanup_transients() {
|
292 |
-
global $wpdb;
|
293 |
-
|
294 |
-
foreach ( array( '_transient_', '_transient_timeout_' ) as $prefix ) {
|
295 |
-
foreach ( self::$transients as $transient ) {
|
296 |
-
$wpdb->query(
|
297 |
-
$wpdb->prepare(
|
298 |
-
"DELETE FROM $wpdb->options WHERE option_name RLIKE %s",
|
299 |
-
$prefix . $transient
|
300 |
-
)
|
301 |
-
);
|
302 |
-
}
|
303 |
-
}
|
304 |
-
}
|
305 |
-
|
306 |
-
/**
|
307 |
-
* Cleanup data for roles and caps.
|
308 |
-
*
|
309 |
-
* @access private
|
310 |
-
*/
|
311 |
-
private static function cleanup_roles_and_caps() {
|
312 |
-
global $wp_roles;
|
313 |
-
|
314 |
-
// Remove caps from roles.
|
315 |
-
$role_names = array_keys( $wp_roles->roles );
|
316 |
-
foreach ( $role_names as $role_name ) {
|
317 |
-
$role = get_role( $role_name );
|
318 |
-
self::remove_all_job_manager_caps( $role );
|
319 |
-
}
|
320 |
-
|
321 |
-
// Remove caps and role from users.
|
322 |
-
$users = get_users( array() );
|
323 |
-
foreach ( $users as $user ) {
|
324 |
-
self::remove_all_job_manager_caps( $user );
|
325 |
-
$user->remove_role( self::$role );
|
326 |
-
}
|
327 |
-
|
328 |
-
// Remove role.
|
329 |
-
remove_role( self::$role );
|
330 |
-
}
|
331 |
-
|
332 |
-
/**
|
333 |
-
* Helper method to remove WPJM caps from a user or role object.
|
334 |
-
*
|
335 |
-
* @param (WP_User|WP_Role) $object the user or role object.
|
336 |
-
*/
|
337 |
-
private static function remove_all_job_manager_caps( $object ) {
|
338 |
-
foreach ( self::$caps as $cap ) {
|
339 |
-
$object->remove_cap( $cap );
|
340 |
-
}
|
341 |
-
}
|
342 |
-
|
343 |
-
/**
|
344 |
-
* Cleanup user meta from the database.
|
345 |
-
*
|
346 |
-
* @access private
|
347 |
-
*/
|
348 |
-
private static function cleanup_user_meta() {
|
349 |
-
global $wpdb;
|
350 |
-
|
351 |
-
foreach ( self::$user_meta_keys as $meta_key ) {
|
352 |
-
$wpdb->delete( $wpdb->usermeta, array( 'meta_key' => $meta_key ) );
|
353 |
-
}
|
354 |
-
}
|
355 |
-
|
356 |
-
/**
|
357 |
-
* Cleanup cron jobs. Note that this should be done on deactivation, but
|
358 |
-
* doing it here as well for safety.
|
359 |
-
*
|
360 |
-
* @access private
|
361 |
-
*/
|
362 |
-
private static function cleanup_cron_jobs() {
|
363 |
-
foreach ( self::$cron_jobs as $job ) {
|
364 |
-
wp_clear_scheduled_hook( $job );
|
365 |
-
}
|
366 |
-
}
|
367 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-wp-job-manager-data-exporter.php
DELETED
@@ -1,89 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Defines a class to handle the user data export
|
4 |
-
*
|
5 |
-
* @package wp-job-manager
|
6 |
-
* @since 1.31.1
|
7 |
-
*/
|
8 |
-
|
9 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
-
exit; // Exit if accessed directly.
|
11 |
-
}
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Handles the user data export.
|
15 |
-
*
|
16 |
-
* @package
|
17 |
-
* @since
|
18 |
-
*/
|
19 |
-
class WP_Job_Manager_Data_Exporter {
|
20 |
-
/**
|
21 |
-
* Register the user data exporter method
|
22 |
-
*
|
23 |
-
* @param array $exporters The exporter array.
|
24 |
-
* @return array $exporters The exporter array.
|
25 |
-
*/
|
26 |
-
public static function register_wpjm_user_data_exporter( $exporters ) {
|
27 |
-
$exporters['wp-job-manager'] = array(
|
28 |
-
'exporter_friendly_name' => __( 'WP Job Manager', 'wp-job-manager' ),
|
29 |
-
'callback' => array( __CLASS__, 'user_data_exporter' ),
|
30 |
-
);
|
31 |
-
return $exporters;
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Data exporter
|
36 |
-
*
|
37 |
-
* @param string $email_address User email address.
|
38 |
-
* @return array
|
39 |
-
*/
|
40 |
-
public static function user_data_exporter( $email_address ) {
|
41 |
-
$user = get_user_by( 'email', $email_address );
|
42 |
-
if ( false === $user ) {
|
43 |
-
return;
|
44 |
-
}
|
45 |
-
|
46 |
-
$export_items = array();
|
47 |
-
$user_data_to_export = array();
|
48 |
-
$user_meta_keys = array(
|
49 |
-
'_company_logo' => __( 'Company Logo', 'wp-job-manager' ),
|
50 |
-
'_company_name' => __( 'Company Name', 'wp-job-manager' ),
|
51 |
-
'_company_website' => __( 'Company Website', 'wp-job-manager' ),
|
52 |
-
'_company_tagline' => __( 'Company Tagline', 'wp-job-manager' ),
|
53 |
-
'_company_twitter' => __( 'Company Twitter', 'wp-job-manager' ),
|
54 |
-
'_company_video' => __( 'Company Video', 'wp-job-manager' ),
|
55 |
-
);
|
56 |
-
|
57 |
-
foreach ( $user_meta_keys as $user_meta_key => $name ) {
|
58 |
-
$user_meta = get_user_meta( $user->ID, $user_meta_key, true );
|
59 |
-
|
60 |
-
if ( empty( $user_meta ) ) {
|
61 |
-
continue;
|
62 |
-
}
|
63 |
-
|
64 |
-
if ( '_company_logo' === $user_meta_key ) {
|
65 |
-
$user_meta = wp_get_attachment_url( $user_meta );
|
66 |
-
if ( false === $user_meta ) {
|
67 |
-
continue;
|
68 |
-
}
|
69 |
-
}
|
70 |
-
|
71 |
-
$user_data_to_export[] = array(
|
72 |
-
'name' => $name,
|
73 |
-
'value' => $user_meta,
|
74 |
-
);
|
75 |
-
}
|
76 |
-
|
77 |
-
$export_items[] = array(
|
78 |
-
'group_id' => 'wpjm-user-data',
|
79 |
-
'group_label' => __( 'WP Job Manager User Data', 'wp-job-manager' ),
|
80 |
-
'item_id' => "wpjm-user-data-{$user->ID}",
|
81 |
-
'data' => $user_data_to_export,
|
82 |
-
);
|
83 |
-
|
84 |
-
return array(
|
85 |
-
'data' => $export_items,
|
86 |
-
'done' => true,
|
87 |
-
);
|
88 |
-
}
|
89 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-wp-job-manager-email-notifications.php
DELETED
@@ -1,827 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Base class for WP Job Manager's email notification system.
|
9 |
-
*
|
10 |
-
* @package wp-job-manager
|
11 |
-
* @since 1.31.0
|
12 |
-
*/
|
13 |
-
final class WP_Job_Manager_Email_Notifications {
|
14 |
-
const EMAIL_SETTING_PREFIX = 'job_manager_email_';
|
15 |
-
const EMAIL_SETTING_ENABLED = 'enabled';
|
16 |
-
const EMAIL_SETTING_PLAIN_TEXT = 'plain_text';
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Notifications to be scheduled.
|
20 |
-
*
|
21 |
-
* @var array
|
22 |
-
*/
|
23 |
-
private static $deferred_notifications = array();
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Sets up initial hooks.
|
27 |
-
*
|
28 |
-
* @static
|
29 |
-
*/
|
30 |
-
public static function init() {
|
31 |
-
add_action( 'job_manager_send_notification', array( __CLASS__, 'schedule_notification' ), 10, 2 );
|
32 |
-
add_action( 'job_manager_email_init', array( __CLASS__, 'lazy_init' ) );
|
33 |
-
add_action( 'job_manager_email_job_details', array( __CLASS__, 'output_job_details' ), 10, 4 );
|
34 |
-
add_action( 'job_manager_email_header', array( __CLASS__, 'output_header' ), 10, 3 );
|
35 |
-
add_action( 'job_manager_email_footer', array( __CLASS__, 'output_footer' ), 10, 3 );
|
36 |
-
add_action( 'job_manager_email_daily_notices', array( __CLASS__, 'send_employer_expiring_notice' ) );
|
37 |
-
add_action( 'job_manager_email_daily_notices', array( __CLASS__, 'send_admin_expiring_notice' ) );
|
38 |
-
add_filter( 'job_manager_settings', array( __CLASS__, 'add_job_manager_email_settings' ), 1 );
|
39 |
-
add_action( 'job_manager_job_submitted', array( __CLASS__, 'send_new_job_notification' ) );
|
40 |
-
add_action( 'job_manager_user_edit_job_listing', array( __CLASS__, 'send_updated_job_notification' ) );
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Gets list of email notifications handled by WP Job Manager core.
|
45 |
-
*
|
46 |
-
* @return array
|
47 |
-
*/
|
48 |
-
public static function core_email_notifications() {
|
49 |
-
return array(
|
50 |
-
'WP_Job_Manager_Email_Admin_New_Job',
|
51 |
-
'WP_Job_Manager_Email_Admin_Updated_Job',
|
52 |
-
'WP_Job_Manager_Email_Admin_Expiring_Job',
|
53 |
-
'WP_Job_Manager_Email_Employer_Expiring_Job',
|
54 |
-
);
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Sets up an email notification to be sent at the end of the script's execution.
|
59 |
-
*
|
60 |
-
* Do not call manually.
|
61 |
-
*
|
62 |
-
* @access private
|
63 |
-
*
|
64 |
-
* @param string $notification
|
65 |
-
* @param array $args
|
66 |
-
*/
|
67 |
-
public static function schedule_notification( $notification, $args = array() ) {
|
68 |
-
self::maybe_init();
|
69 |
-
|
70 |
-
self::$deferred_notifications[] = array( $notification, $args );
|
71 |
-
}
|
72 |
-
|
73 |
-
/**
|
74 |
-
* Sends all notifications collected during execution.
|
75 |
-
*
|
76 |
-
* Do not call manually.
|
77 |
-
*
|
78 |
-
* @access private
|
79 |
-
*/
|
80 |
-
public static function send_deferred_notifications() {
|
81 |
-
$email_notifications = self::get_email_notifications( true );
|
82 |
-
foreach ( self::$deferred_notifications as $email ) {
|
83 |
-
if (
|
84 |
-
! is_string( $email[0] )
|
85 |
-
|| ! isset( $email_notifications[ $email[0] ] )
|
86 |
-
) {
|
87 |
-
continue;
|
88 |
-
}
|
89 |
-
|
90 |
-
$email_class = $email_notifications[ $email[0] ];
|
91 |
-
$email_notification_key = $email[0];
|
92 |
-
$email_args = is_array( $email[1] ) ? $email[1] : array();
|
93 |
-
|
94 |
-
self::send_email( $email[0], new $email_class( $email_args, self::get_email_settings( $email_notification_key ) ) );
|
95 |
-
}
|
96 |
-
}
|
97 |
-
|
98 |
-
/**
|
99 |
-
* Initialize if necessary.
|
100 |
-
*/
|
101 |
-
public static function maybe_init() {
|
102 |
-
if ( 0 === did_action( 'job_manager_email_init' ) ) {
|
103 |
-
/**
|
104 |
-
* Lazily load remaining files needed for email notifications. Do this here instead of in
|
105 |
-
* `shutdown` for proper logging in case of syntax errors.
|
106 |
-
*
|
107 |
-
* @since 1.31.0
|
108 |
-
*/
|
109 |
-
do_action( 'job_manager_email_init' );
|
110 |
-
}
|
111 |
-
}
|
112 |
-
|
113 |
-
/**
|
114 |
-
* Include email files.
|
115 |
-
*
|
116 |
-
* Do not call manually.
|
117 |
-
*
|
118 |
-
* @access private
|
119 |
-
*/
|
120 |
-
public static function lazy_init() {
|
121 |
-
add_action( 'shutdown', array( __CLASS__, 'send_deferred_notifications' ) );
|
122 |
-
|
123 |
-
include_once JOB_MANAGER_PLUGIN_DIR . '/includes/emails/class-wp-job-manager-email-admin-new-job.php';
|
124 |
-
include_once JOB_MANAGER_PLUGIN_DIR . '/includes/emails/class-wp-job-manager-email-admin-updated-job.php';
|
125 |
-
include_once JOB_MANAGER_PLUGIN_DIR . '/includes/emails/class-wp-job-manager-email-employer-expiring-job.php';
|
126 |
-
include_once JOB_MANAGER_PLUGIN_DIR . '/includes/emails/class-wp-job-manager-email-admin-expiring-job.php';
|
127 |
-
|
128 |
-
if ( ! class_exists( 'Emogrifier' ) && class_exists( 'DOMDocument' ) ) {
|
129 |
-
include_once JOB_MANAGER_PLUGIN_DIR . '/lib/emogrifier/class-emogrifier.php';
|
130 |
-
}
|
131 |
-
}
|
132 |
-
|
133 |
-
/**
|
134 |
-
* Clear the deferred notifications email array.
|
135 |
-
*
|
136 |
-
* Do not call manually. Only for help with tests.
|
137 |
-
*
|
138 |
-
* @access private
|
139 |
-
*/
|
140 |
-
public static function clear_deferred_notifications() {
|
141 |
-
if ( ! defined( 'PHPUNIT_WPJM_TESTSUITE' ) || ! PHPUNIT_WPJM_TESTSUITE ) {
|
142 |
-
die( 'This is just for use while testing' );
|
143 |
-
}
|
144 |
-
self::$deferred_notifications = array();
|
145 |
-
}
|
146 |
-
|
147 |
-
/**
|
148 |
-
* Gets a list of all email notifications that WP Job Manager handles.
|
149 |
-
*
|
150 |
-
* @param bool $enabled_notifications_only
|
151 |
-
* @return array
|
152 |
-
*/
|
153 |
-
public static function get_email_notifications( $enabled_notifications_only = false ) {
|
154 |
-
self::maybe_init();
|
155 |
-
|
156 |
-
/**
|
157 |
-
* Retrieves all email notifications to be sent.
|
158 |
-
*
|
159 |
-
* @since 1.31.0
|
160 |
-
*
|
161 |
-
* @param array $email_notifications All the email notifications to be registered.
|
162 |
-
*/
|
163 |
-
$email_notification_classes = array_unique( apply_filters( 'job_manager_email_notifications', self::core_email_notifications() ) );
|
164 |
-
$email_notifications = array();
|
165 |
-
|
166 |
-
/**
|
167 |
-
* Email class in loop.
|
168 |
-
*
|
169 |
-
* @var WP_Job_Manager_Email $email_class
|
170 |
-
*/
|
171 |
-
foreach ( $email_notification_classes as $email_class ) {
|
172 |
-
// Check to make sure email notification is valid.
|
173 |
-
if ( ! self::is_email_notification_valid( $email_class ) ) {
|
174 |
-
continue;
|
175 |
-
}
|
176 |
-
|
177 |
-
// PHP 5.2: Using `call_user_func()` but `$email_class::get_key()` preferred.
|
178 |
-
$email_notification_key = call_user_func( array( $email_class, 'get_key' ) );
|
179 |
-
if (
|
180 |
-
isset( $email_notifications[ $email_notification_key ] )
|
181 |
-
|| ( $enabled_notifications_only && ! self::is_email_notification_enabled( $email_notification_key ) )
|
182 |
-
) {
|
183 |
-
continue;
|
184 |
-
}
|
185 |
-
|
186 |
-
$email_notifications[ $email_notification_key ] = $email_class;
|
187 |
-
}
|
188 |
-
|
189 |
-
return $email_notifications;
|
190 |
-
}
|
191 |
-
|
192 |
-
/**
|
193 |
-
* Show details about the job listing.
|
194 |
-
*
|
195 |
-
* @param WP_Post $job The job listing to show details for.
|
196 |
-
* @param WP_Job_Manager_Email $email Email object for the notification.
|
197 |
-
* @param bool $sent_to_admin True if this is being sent to an administrator.
|
198 |
-
* @param bool $plain_text True if the email is being sent as plain text.
|
199 |
-
*/
|
200 |
-
public static function output_job_details( $job, $email, $sent_to_admin, $plain_text = false ) {
|
201 |
-
$template_segment = self::locate_template_file( 'email-job-details', $plain_text );
|
202 |
-
if ( ! file_exists( $template_segment ) ) {
|
203 |
-
return;
|
204 |
-
}
|
205 |
-
|
206 |
-
$fields = self::get_job_detail_fields( $job, $sent_to_admin, $plain_text );
|
207 |
-
|
208 |
-
include $template_segment;
|
209 |
-
}
|
210 |
-
|
211 |
-
/**
|
212 |
-
* Get the job fields to show in email templates.
|
213 |
-
*
|
214 |
-
* @param WP_Post $job
|
215 |
-
* @param bool $sent_to_admin
|
216 |
-
* @param bool $plain_text
|
217 |
-
* @return array
|
218 |
-
*/
|
219 |
-
private static function get_job_detail_fields( WP_Post $job, $sent_to_admin, $plain_text = false ) {
|
220 |
-
$fields = array();
|
221 |
-
|
222 |
-
$fields['job_title'] = array(
|
223 |
-
'label' => __( 'Job title', 'wp-job-manager' ),
|
224 |
-
'value' => $job->post_title,
|
225 |
-
);
|
226 |
-
|
227 |
-
if ( $sent_to_admin || 'publish' === $job->post_status ) {
|
228 |
-
$fields['job_title']['url'] = get_permalink( $job );
|
229 |
-
}
|
230 |
-
|
231 |
-
$job_location = get_the_job_location( $job );
|
232 |
-
if ( ! empty( $job_location ) ) {
|
233 |
-
$fields['job_location'] = array(
|
234 |
-
'label' => __( 'Location', 'wp-job-manager' ),
|
235 |
-
'value' => $job_location,
|
236 |
-
);
|
237 |
-
}
|
238 |
-
|
239 |
-
if ( get_option( 'job_manager_enable_types' ) && wp_count_terms( 'job_listing_type' ) > 0 ) {
|
240 |
-
$job_types = wpjm_get_the_job_types( $job );
|
241 |
-
if ( ! empty( $job_types ) ) {
|
242 |
-
$fields['job_type'] = array(
|
243 |
-
'label' => __( 'Job type', 'wp-job-manager' ),
|
244 |
-
'value' => implode( ', ', wp_list_pluck( $job_types, 'name' ) ),
|
245 |
-
);
|
246 |
-
}
|
247 |
-
}
|
248 |
-
|
249 |
-
if ( get_option( 'job_manager_enable_categories' ) && wp_count_terms( 'job_listing_category' ) > 0 ) {
|
250 |
-
$job_categories = wpjm_get_the_job_categories( $job );
|
251 |
-
if ( ! empty( $job_categories ) ) {
|
252 |
-
$fields['job_category'] = array(
|
253 |
-
'label' => __( 'Job category', 'wp-job-manager' ),
|
254 |
-
'value' => implode( ', ', wp_list_pluck( $job_categories, 'name' ) ),
|
255 |
-
);
|
256 |
-
}
|
257 |
-
}
|
258 |
-
|
259 |
-
$company_name = get_the_company_name( $job );
|
260 |
-
if ( ! empty( $company_name ) ) {
|
261 |
-
$fields['company_name'] = array(
|
262 |
-
'label' => __( 'Company name', 'wp-job-manager' ),
|
263 |
-
'value' => $company_name,
|
264 |
-
);
|
265 |
-
}
|
266 |
-
|
267 |
-
$company_website = get_the_company_website( $job );
|
268 |
-
if ( ! empty( $company_website ) ) {
|
269 |
-
$fields['company_website'] = array(
|
270 |
-
'label' => __( 'Company website', 'wp-job-manager' ),
|
271 |
-
'value' => $plain_text ? $company_website : sprintf( '<a href="%1$s">%1$s</a>', esc_url( $company_website, array( 'http', 'https' ) ) ),
|
272 |
-
);
|
273 |
-
}
|
274 |
-
|
275 |
-
$job_expires = get_post_meta( $job->ID, '_job_expires', true );
|
276 |
-
if ( ! empty( $job_expires ) ) {
|
277 |
-
$job_expires_str = date_i18n( get_option( 'date_format' ), strtotime( $job_expires ) );
|
278 |
-
$fields['job_expires'] = array(
|
279 |
-
'label' => __( 'Listing expires', 'wp-job-manager' ),
|
280 |
-
'value' => $job_expires_str,
|
281 |
-
);
|
282 |
-
}
|
283 |
-
|
284 |
-
if ( $sent_to_admin ) {
|
285 |
-
$author = get_user_by( 'ID', $job->post_author );
|
286 |
-
if ( $author instanceof WP_User ) {
|
287 |
-
$fields['author'] = array(
|
288 |
-
'label' => __( 'Posted by', 'wp-job-manager' ),
|
289 |
-
'value' => $author->user_nicename,
|
290 |
-
'url' => 'mailto:' . $author->user_email,
|
291 |
-
);
|
292 |
-
}
|
293 |
-
}
|
294 |
-
|
295 |
-
/**
|
296 |
-
* Modify the fields shown in email notifications in the details summary a job listing.
|
297 |
-
*
|
298 |
-
* @since 1.31.0
|
299 |
-
*
|
300 |
-
* @param array $fields {
|
301 |
-
* Array of fields. Each field is keyed with a unique identifier.
|
302 |
-
* {
|
303 |
-
* @type string $label Label to show next to field.
|
304 |
-
* @type string $value Value for field.
|
305 |
-
* @type string $url URL to provide with the value (optional).
|
306 |
-
* }
|
307 |
-
* }
|
308 |
-
* @param WP_Post $job Job listing.
|
309 |
-
* @param bool $sent_to_admin True if being sent in an admin notification.
|
310 |
-
* @param bool $plain_text True if being sent as plain text.
|
311 |
-
*/
|
312 |
-
return apply_filters( 'job_manager_emails_job_detail_fields', $fields, $job, $sent_to_admin, $plain_text );
|
313 |
-
}
|
314 |
-
|
315 |
-
/**
|
316 |
-
* Output email header.
|
317 |
-
*
|
318 |
-
* @param string $email_notification_key Email notification key for email being sent.
|
319 |
-
* @param bool $sent_to_admin True if this is being sent to an administrator.
|
320 |
-
* @param bool $plain_text True if the email is being sent as plain text.
|
321 |
-
*/
|
322 |
-
public static function output_header( $email_notification_key, $sent_to_admin, $plain_text = false ) {
|
323 |
-
$template_segment = self::email_template_path_alternative( $email_notification_key, 'email-header', $plain_text );
|
324 |
-
if ( false === $template_segment ) {
|
325 |
-
$template_segment = self::locate_template_file( 'email-header', $plain_text );
|
326 |
-
}
|
327 |
-
if ( ! $template_segment || ! file_exists( $template_segment ) ) {
|
328 |
-
return;
|
329 |
-
}
|
330 |
-
include $template_segment;
|
331 |
-
}
|
332 |
-
|
333 |
-
/**
|
334 |
-
* Output email footer.
|
335 |
-
*
|
336 |
-
* @param string $email_notification_key Email notification key for email being sent.
|
337 |
-
* @param bool $sent_to_admin True if this is being sent to an administrator.
|
338 |
-
* @param bool $plain_text True if the email is being sent as plain text.
|
339 |
-
*/
|
340 |
-
public static function output_footer( $email_notification_key, $sent_to_admin, $plain_text = false ) {
|
341 |
-
$template_segment = self::email_template_path_alternative( $email_notification_key, 'email-footer', $plain_text );
|
342 |
-
if ( false === $template_segment ) {
|
343 |
-
$template_segment = self::locate_template_file( 'email-footer', $plain_text );
|
344 |
-
}
|
345 |
-
if ( ! $template_segment || ! file_exists( $template_segment ) ) {
|
346 |
-
return;
|
347 |
-
}
|
348 |
-
include $template_segment;
|
349 |
-
}
|
350 |
-
|
351 |
-
/**
|
352 |
-
* Checks for an alternative email template segment in the template path specified by the current email.
|
353 |
-
* Useful to provide alternative email headers and footers for a specific WPJM extension plugin.
|
354 |
-
*
|
355 |
-
* @param string $email_notification_key Email notification key for email being sent.
|
356 |
-
* @param string $template_name Name of the template to check.
|
357 |
-
* @param bool $plain_text True if the email is being sent as plain text.
|
358 |
-
* @return bool|string Returns path to template path alternative or false if none exists.
|
359 |
-
*/
|
360 |
-
private static function email_template_path_alternative( $email_notification_key, $template_name, $plain_text ) {
|
361 |
-
$email_class = self::get_email_class( $email_notification_key );
|
362 |
-
if ( ! $email_class || ! is_subclass_of( $email_class, 'WP_Job_Manager_Email_Template' ) ) {
|
363 |
-
return false;
|
364 |
-
}
|
365 |
-
|
366 |
-
$template_default_path = call_user_func( array( $email_class, 'get_template_default_path' ) );
|
367 |
-
if ( '' === $template_default_path ) {
|
368 |
-
return false;
|
369 |
-
}
|
370 |
-
|
371 |
-
$template_path = call_user_func( array( $email_class, 'get_template_path' ) );
|
372 |
-
$template = self::locate_template_file( $template_name, $plain_text, $template_path, $template_default_path );
|
373 |
-
if ( '' === $template ) {
|
374 |
-
return false;
|
375 |
-
}
|
376 |
-
|
377 |
-
return $template;
|
378 |
-
}
|
379 |
-
|
380 |
-
/**
|
381 |
-
* Locate template file.
|
382 |
-
*
|
383 |
-
* @param string $template_name
|
384 |
-
* @param bool $plain_text
|
385 |
-
* @param string $template_path
|
386 |
-
* @param string $default_path
|
387 |
-
* @return string
|
388 |
-
*/
|
389 |
-
public static function locate_template_file( $template_name, $plain_text = false, $template_path = 'job_manager', $default_path = '' ) {
|
390 |
-
return locate_job_manager_template( WP_Job_Manager_Email_Template::generate_template_file_name( $template_name, $plain_text ), $template_path, $default_path );
|
391 |
-
}
|
392 |
-
|
393 |
-
/**
|
394 |
-
* Add email notification settings for the job manager context.
|
395 |
-
*
|
396 |
-
* @param array $settings
|
397 |
-
* @return array
|
398 |
-
*/
|
399 |
-
public static function add_job_manager_email_settings( $settings ) {
|
400 |
-
return self::add_email_settings( $settings, WP_Job_Manager_Email::get_context() );
|
401 |
-
}
|
402 |
-
|
403 |
-
/**
|
404 |
-
* Add email notification settings for a context.
|
405 |
-
*
|
406 |
-
* @param array $settings
|
407 |
-
* @param string $context
|
408 |
-
* @return array
|
409 |
-
*/
|
410 |
-
public static function add_email_settings( $settings, $context ) {
|
411 |
-
$email_notifications = self::get_email_notifications( false );
|
412 |
-
$email_settings = array();
|
413 |
-
|
414 |
-
foreach ( $email_notifications as $email_notification_key => $email_class ) {
|
415 |
-
$email_notification_context = call_user_func( array( $email_class, 'get_context' ) );
|
416 |
-
if ( $context !== $email_notification_context ) {
|
417 |
-
continue;
|
418 |
-
}
|
419 |
-
|
420 |
-
$email_settings[] = array(
|
421 |
-
'type' => 'multi_enable_expand',
|
422 |
-
'class' => 'email-setting-row no-separator',
|
423 |
-
'name' => self::EMAIL_SETTING_PREFIX . call_user_func( array( $email_class, 'get_key' ) ),
|
424 |
-
'enable_field' => array(
|
425 |
-
'name' => self::EMAIL_SETTING_ENABLED,
|
426 |
-
'cb_label' => call_user_func( array( $email_class, 'get_name' ) ),
|
427 |
-
'desc' => call_user_func( array( $email_class, 'get_description' ) ),
|
428 |
-
),
|
429 |
-
'label' => false,
|
430 |
-
'std' => self::get_email_setting_defaults( $email_notification_key ),
|
431 |
-
'settings' => self::get_email_setting_fields( $email_notification_key ),
|
432 |
-
);
|
433 |
-
}
|
434 |
-
|
435 |
-
if ( ! empty( $email_settings ) ) {
|
436 |
-
$settings['email_notifications'] = array(
|
437 |
-
__( 'Email Notifications', 'wp-job-manager' ),
|
438 |
-
$email_settings,
|
439 |
-
array(
|
440 |
-
'before' => __( 'Select the email notifications to enable.', 'wp-job-manager' ),
|
441 |
-
),
|
442 |
-
);
|
443 |
-
}
|
444 |
-
|
445 |
-
return $settings;
|
446 |
-
}
|
447 |
-
|
448 |
-
/**
|
449 |
-
* Checks if a particular notification is enabled or not.
|
450 |
-
*
|
451 |
-
* @param string $email_notification_key
|
452 |
-
* @return bool
|
453 |
-
*/
|
454 |
-
public static function is_email_notification_enabled( $email_notification_key ) {
|
455 |
-
$settings = self::get_email_settings( $email_notification_key );
|
456 |
-
|
457 |
-
$is_email_notification_enabled = ! empty( $settings[ self::EMAIL_SETTING_ENABLED ] );
|
458 |
-
|
459 |
-
/**
|
460 |
-
* Filter whether an notification email is enabled.
|
461 |
-
*
|
462 |
-
* @since 1.31.0
|
463 |
-
*
|
464 |
-
* @param bool $is_email_notification_enabled
|
465 |
-
* @param string $email_notification_key
|
466 |
-
*/
|
467 |
-
return apply_filters( 'job_manager_email_is_email_notification_enabled', $is_email_notification_enabled, $email_notification_key );
|
468 |
-
}
|
469 |
-
|
470 |
-
/**
|
471 |
-
* Checks if we should send emails using plain text.
|
472 |
-
*
|
473 |
-
* @param string $email_notification_key
|
474 |
-
* @return bool
|
475 |
-
*/
|
476 |
-
public static function send_as_plain_text( $email_notification_key ) {
|
477 |
-
$settings = self::get_email_settings( $email_notification_key );
|
478 |
-
|
479 |
-
$send_as_plain_text = ! empty( $settings[ self::EMAIL_SETTING_PLAIN_TEXT ] );
|
480 |
-
|
481 |
-
/**
|
482 |
-
* Filter whether to send emails as plain text.
|
483 |
-
*
|
484 |
-
* @since 1.31.0
|
485 |
-
*
|
486 |
-
* @param bool $send_as_plain_text
|
487 |
-
* @param string $email_notification_key
|
488 |
-
*/
|
489 |
-
return apply_filters( 'job_manager_email_send_as_plain_text', $send_as_plain_text, $email_notification_key );
|
490 |
-
}
|
491 |
-
|
492 |
-
/**
|
493 |
-
* Sending notices to employers for expiring job listings.
|
494 |
-
*/
|
495 |
-
public static function send_employer_expiring_notice() {
|
496 |
-
self::maybe_init();
|
497 |
-
|
498 |
-
$email_key = WP_Job_Manager_Email_Employer_Expiring_Job::get_key();
|
499 |
-
if ( ! self::is_email_notification_enabled( $email_key ) ) {
|
500 |
-
return;
|
501 |
-
}
|
502 |
-
$settings = self::get_email_settings( $email_key );
|
503 |
-
$days_notice = WP_Job_Manager_Email_Employer_Expiring_Job::get_notice_period( $settings );
|
504 |
-
self::send_expiring_notice( $email_key, $days_notice );
|
505 |
-
}
|
506 |
-
|
507 |
-
/**
|
508 |
-
* Sending notices to the site administrator for expiring job listings.
|
509 |
-
*/
|
510 |
-
public static function send_admin_expiring_notice() {
|
511 |
-
self::maybe_init();
|
512 |
-
|
513 |
-
$email_key = WP_Job_Manager_Email_Admin_Expiring_Job::get_key();
|
514 |
-
if ( ! self::is_email_notification_enabled( $email_key ) ) {
|
515 |
-
return;
|
516 |
-
}
|
517 |
-
$settings = self::get_email_settings( $email_key );
|
518 |
-
$days_notice = WP_Job_Manager_Email_Admin_Expiring_Job::get_notice_period( $settings );
|
519 |
-
self::send_expiring_notice( $email_key, $days_notice );
|
520 |
-
}
|
521 |
-
|
522 |
-
/**
|
523 |
-
* Fire the action to send a new job notification to the admin.
|
524 |
-
*
|
525 |
-
* @param int $job_id
|
526 |
-
*/
|
527 |
-
public static function send_new_job_notification( $job_id ) {
|
528 |
-
do_action( 'job_manager_send_notification', 'admin_new_job', array( 'job_id' => $job_id ) );
|
529 |
-
}
|
530 |
-
|
531 |
-
/**
|
532 |
-
* Fire the action to send a updated job notification to the admin.
|
533 |
-
*
|
534 |
-
* @param int $job_id
|
535 |
-
*/
|
536 |
-
public static function send_updated_job_notification( $job_id ) {
|
537 |
-
do_action( 'job_manager_send_notification', 'admin_updated_job', array( 'job_id' => $job_id ) );
|
538 |
-
}
|
539 |
-
|
540 |
-
/**
|
541 |
-
* Send notice based on job expiration date.
|
542 |
-
*
|
543 |
-
* @param string $email_notification_key
|
544 |
-
* @param int $days_notice
|
545 |
-
*/
|
546 |
-
private static function send_expiring_notice( $email_notification_key, $days_notice ) {
|
547 |
-
global $wpdb;
|
548 |
-
|
549 |
-
$notice_before_ts = current_time( 'timestamp' ) + ( DAY_IN_SECONDS * $days_notice );
|
550 |
-
$job_ids = $wpdb->get_col( $wpdb->prepare(
|
551 |
-
"
|
552 |
-
SELECT postmeta.post_id FROM {$wpdb->postmeta} as postmeta
|
553 |
-
LEFT JOIN {$wpdb->posts} as posts ON postmeta.post_id = posts.ID
|
554 |
-
WHERE postmeta.meta_key = '_job_expires'
|
555 |
-
AND postmeta.meta_value = %s
|
556 |
-
AND posts.post_status = 'publish'
|
557 |
-
AND posts.post_type = 'job_listing'
|
558 |
-
", date( 'Y-m-d', $notice_before_ts )
|
559 |
-
) );
|
560 |
-
|
561 |
-
if ( $job_ids ) {
|
562 |
-
foreach ( $job_ids as $job_id ) {
|
563 |
-
do_action( 'job_manager_send_notification', $email_notification_key, array( 'job_id' => $job_id ) );
|
564 |
-
}
|
565 |
-
}
|
566 |
-
}
|
567 |
-
|
568 |
-
/**
|
569 |
-
* Get the setting fields for an email.
|
570 |
-
*
|
571 |
-
* @param string $email_notification_key
|
572 |
-
* @return array
|
573 |
-
*/
|
574 |
-
private static function get_email_setting_fields( $email_notification_key ) {
|
575 |
-
$email_class = self::get_email_class( $email_notification_key );
|
576 |
-
$core_settings = array(
|
577 |
-
array(
|
578 |
-
'name' => 'plain_text',
|
579 |
-
'std' => '0',
|
580 |
-
'label' => __( 'Format', 'wp-job-manager' ),
|
581 |
-
'type' => 'radio',
|
582 |
-
'options' => array(
|
583 |
-
'1' => __( 'Send plain text email', 'wp-job-manager' ),
|
584 |
-
'0' => __( 'Send rich text email', 'wp-job-manager' ),
|
585 |
-
),
|
586 |
-
),
|
587 |
-
);
|
588 |
-
$email_settings = call_user_func( array( $email_class, 'get_setting_fields' ) );
|
589 |
-
return array_merge( $core_settings, $email_settings );
|
590 |
-
}
|
591 |
-
|
592 |
-
/**
|
593 |
-
* Get the settings for the email.
|
594 |
-
*
|
595 |
-
* @param string $email_notification_key
|
596 |
-
* @return array
|
597 |
-
*/
|
598 |
-
private static function get_email_settings( $email_notification_key ) {
|
599 |
-
$option_name = self::EMAIL_SETTING_PREFIX . $email_notification_key;
|
600 |
-
$option_value = get_option( $option_name );
|
601 |
-
if ( empty( $option_value ) || ! is_array( $option_value ) ) {
|
602 |
-
$option_value = array();
|
603 |
-
}
|
604 |
-
$default_settings = self::get_email_setting_defaults( $email_notification_key );
|
605 |
-
|
606 |
-
return array_merge( $default_settings, $option_value );
|
607 |
-
}
|
608 |
-
|
609 |
-
/**
|
610 |
-
* Gets the default values for the email notification.
|
611 |
-
*
|
612 |
-
* @param string $email_notification_key
|
613 |
-
* @return array
|
614 |
-
*/
|
615 |
-
private static function get_email_setting_defaults( $email_notification_key ) {
|
616 |
-
$settings = self::get_email_setting_fields( $email_notification_key );
|
617 |
-
$email_class = self::get_email_class( $email_notification_key );
|
618 |
-
|
619 |
-
$defaults = array();
|
620 |
-
$defaults[ self::EMAIL_SETTING_ENABLED ] = call_user_func( array( $email_class, 'is_default_enabled' ) ) ? '1' : '0';
|
621 |
-
|
622 |
-
foreach ( $settings as $setting ) {
|
623 |
-
$defaults[ $setting['name'] ] = null;
|
624 |
-
if ( isset( $setting['std'] ) ) {
|
625 |
-
$defaults[ $setting['name'] ] = $setting['std'];
|
626 |
-
}
|
627 |
-
}
|
628 |
-
|
629 |
-
return $defaults;
|
630 |
-
}
|
631 |
-
|
632 |
-
/**
|
633 |
-
* Get the email class from the unique key.
|
634 |
-
*
|
635 |
-
* @param string $email_notification_key
|
636 |
-
* @return bool|string
|
637 |
-
*/
|
638 |
-
private static function get_email_class( $email_notification_key ) {
|
639 |
-
$email_notifications = self::get_email_notifications( false );
|
640 |
-
|
641 |
-
return isset( $email_notifications[ $email_notification_key ] ) ? $email_notifications[ $email_notification_key ] : false;
|
642 |
-
}
|
643 |
-
|
644 |
-
/**
|
645 |
-
* Returns the total number of deferred notifications to be sent.
|
646 |
-
*
|
647 |
-
* Do not use. Used just in unit tests.
|
648 |
-
*
|
649 |
-
* @access private
|
650 |
-
*
|
651 |
-
* @return int
|
652 |
-
*/
|
653 |
-
public static function get_deferred_notification_count() {
|
654 |
-
return count( self::$deferred_notifications );
|
655 |
-
}
|
656 |
-
|
657 |
-
/**
|
658 |
-
* Confirms an email notification is valid.
|
659 |
-
*
|
660 |
-
* @access private
|
661 |
-
*
|
662 |
-
* @param string $email_class
|
663 |
-
* @return bool
|
664 |
-
*/
|
665 |
-
private static function is_email_notification_valid( $email_class ) {
|
666 |
-
// PHP 5.2: Using `call_user_func()` but `$email_class::get_key()` preferred.
|
667 |
-
return is_string( $email_class )
|
668 |
-
&& class_exists( $email_class )
|
669 |
-
&& is_subclass_of( $email_class, 'WP_Job_Manager_Email' )
|
670 |
-
&& false !== call_user_func( array( $email_class, 'get_key' ) )
|
671 |
-
&& false !== call_user_func( array( $email_class, 'get_name' ) );
|
672 |
-
}
|
673 |
-
|
674 |
-
/**
|
675 |
-
* Sends an email notification.
|
676 |
-
*
|
677 |
-
* @access private
|
678 |
-
*
|
679 |
-
* @param string $email_notification_key
|
680 |
-
* @param WP_Job_Manager_Email $email
|
681 |
-
* @return bool
|
682 |
-
*/
|
683 |
-
private static function send_email( $email_notification_key, WP_Job_Manager_Email $email ) {
|
684 |
-
if ( ! $email->is_valid() ) {
|
685 |
-
return false;
|
686 |
-
}
|
687 |
-
|
688 |
-
$fields = array( 'to', 'from', 'subject', 'rich_content', 'plain_content', 'attachments', 'cc', 'headers' );
|
689 |
-
$args = array();
|
690 |
-
foreach ( $fields as $field ) {
|
691 |
-
$method = 'get_' . $field;
|
692 |
-
|
693 |
-
/**
|
694 |
-
* Filter email values for job manager notifications.
|
695 |
-
*
|
696 |
-
* @since 1.31.0
|
697 |
-
*
|
698 |
-
* @param mixed $email_field_value Value to be filtered.
|
699 |
-
* @param WP_Job_Manager_Email $email Email notification object.
|
700 |
-
*/
|
701 |
-
$args[ $field ] = apply_filters( "job_manager_email_{$email_notification_key}_{$field}", $email->$method(), $email );
|
702 |
-
}
|
703 |
-
|
704 |
-
$headers = is_array( $args['headers'] ) ? $args['headers'] : array();
|
705 |
-
|
706 |
-
if ( ! empty( $args['from'] ) ) {
|
707 |
-
$headers[] = 'From: ' . $args['from'];
|
708 |
-
}
|
709 |
-
|
710 |
-
if ( ! self::send_as_plain_text( $email_notification_key ) ) {
|
711 |
-
$headers[] = 'Content-Type: text/html';
|
712 |
-
}
|
713 |
-
|
714 |
-
$content = self::get_email_content( $email_notification_key, $args );
|
715 |
-
|
716 |
-
/**
|
717 |
-
* Allows for short-circuiting the actual sending of email notifications.
|
718 |
-
*
|
719 |
-
* @since 1.31.0
|
720 |
-
*
|
721 |
-
* @param bool $do_send_notification True if we should send the notification.
|
722 |
-
* @param WP_Job_Manager_Email $email Email notification object.
|
723 |
-
* @param array $args Email arguments for generating email.
|
724 |
-
* @param string $content Email content.
|
725 |
-
* @param array $headers Email headers.
|
726 |
-
* @param
|
727 |
-
*/
|
728 |
-
if ( ! apply_filters( 'job_manager_email_do_send_notification', true, $email, $args, $content, $headers ) ) {
|
729 |
-
return false;
|
730 |
-
}
|
731 |
-
return wp_mail( $args['to'], $args['subject'], $content, $headers, $args['attachments'] );
|
732 |
-
}
|
733 |
-
|
734 |
-
/**
|
735 |
-
* Generates the content for an email.
|
736 |
-
*
|
737 |
-
* @access private
|
738 |
-
*
|
739 |
-
* @param string $email_notification_key
|
740 |
-
* @param array $args
|
741 |
-
* @return string
|
742 |
-
*/
|
743 |
-
private static function get_email_content( $email_notification_key, $args ) {
|
744 |
-
$plain_text = self::send_as_plain_text( $email_notification_key );
|
745 |
-
|
746 |
-
ob_start();
|
747 |
-
|
748 |
-
/**
|
749 |
-
* Output the header for all job manager emails.
|
750 |
-
*
|
751 |
-
* @since 1.31.0
|
752 |
-
*
|
753 |
-
* @param string $email_notification_key Unique email notification key.
|
754 |
-
* @param array $args Arguments passed for generating email.
|
755 |
-
* @param bool $plain_text True if sending plain text email.
|
756 |
-
*/
|
757 |
-
do_action( 'job_manager_email_header', $email_notification_key, $args, $plain_text );
|
758 |
-
|
759 |
-
if ( $plain_text ) {
|
760 |
-
echo wp_kses_post( html_entity_decode( wptexturize( $args['plain_content'] ) ) );
|
761 |
-
} else {
|
762 |
-
echo wp_kses_post( wpautop( wptexturize( $args['rich_content'] ) ) );
|
763 |
-
}
|
764 |
-
|
765 |
-
/**
|
766 |
-
* Output the footer for all job manager emails.
|
767 |
-
*
|
768 |
-
* @since 1.31.0
|
769 |
-
*
|
770 |
-
* @param string $email_notification_key Unique email notification key.
|
771 |
-
* @param array $args Arguments passed for generating email.
|
772 |
-
* @param bool $plain_text True if sending plain text email.
|
773 |
-
*/
|
774 |
-
do_action( 'job_manager_email_footer', $email_notification_key, $args, $plain_text );
|
775 |
-
|
776 |
-
$content = ob_get_clean();
|
777 |
-
if ( ! $plain_text ) {
|
778 |
-
$content = self::inject_styles( $content );
|
779 |
-
}
|
780 |
-
|
781 |
-
/**
|
782 |
-
* Filter the content of the email.
|
783 |
-
*
|
784 |
-
* @since 1.31.0
|
785 |
-
*
|
786 |
-
* @param string $content Email content.
|
787 |
-
* @param string $email_notification_key Unique email notification key.
|
788 |
-
* @param array $args Arguments passed for generating email.
|
789 |
-
* @param bool $plain_text True if sending plain text email.
|
790 |
-
*/
|
791 |
-
return apply_filters( 'job_manager_email_content', $content, $email_notification_key, $args, $plain_text );
|
792 |
-
}
|
793 |
-
|
794 |
-
/**
|
795 |
-
* Inject inline styles into email content.
|
796 |
-
*
|
797 |
-
* @param string $content
|
798 |
-
* @return string
|
799 |
-
*/
|
800 |
-
private static function inject_styles( $content ) {
|
801 |
-
if ( class_exists( 'Emogrifier' ) ) {
|
802 |
-
try {
|
803 |
-
$emogrifier = new Emogrifier( $content, self::get_styles() );
|
804 |
-
$content = $emogrifier->emogrify();
|
805 |
-
} catch ( Exception $e ) {
|
806 |
-
trigger_error( 'Unable to inject styles into email notification: ' . $e->getMessage() ); // @codingStandardsIgnoreLine
|
807 |
-
}
|
808 |
-
}
|
809 |
-
return $content;
|
810 |
-
}
|
811 |
-
|
812 |
-
/**
|
813 |
-
* Gets the CSS styles to be used in email notifications.
|
814 |
-
*
|
815 |
-
* @return bool|string
|
816 |
-
*/
|
817 |
-
private static function get_styles() {
|
818 |
-
$email_styles_template = self::locate_template_file( 'email-styles' );
|
819 |
-
if ( ! file_exists( $email_styles_template ) ) {
|
820 |
-
return false;
|
821 |
-
}
|
822 |
-
ob_start();
|
823 |
-
include $email_styles_template;
|
824 |
-
return ob_get_clean();
|
825 |
-
}
|
826 |
-
|
827 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
*/
|
@@ -49,16 +49,16 @@ class WP_Job_Manager_Forms {
|
|
49 |
* Load a form's class
|
50 |
*
|
51 |
* @param string $form_name
|
52 |
-
* @return string class name on success, false on failure
|
53 |
*/
|
54 |
private function load_form_class( $form_name ) {
|
55 |
if ( ! class_exists( 'WP_Job_Manager_Form' ) ) {
|
56 |
-
include 'abstracts/abstract-wp-job-manager-form.php';
|
57 |
}
|
58 |
|
59 |
-
// Now try to load the form_name
|
60 |
-
$form_class
|
61 |
-
$form_file
|
62 |
|
63 |
if ( class_exists( $form_class ) ) {
|
64 |
return call_user_func( array( $form_class, 'instance' ) );
|
@@ -72,7 +72,7 @@ class WP_Job_Manager_Forms {
|
|
72 |
include $form_file;
|
73 |
}
|
74 |
|
75 |
-
// Init the form
|
76 |
return call_user_func( array( $form_class, 'instance' ) );
|
77 |
}
|
78 |
|
@@ -80,12 +80,11 @@ class WP_Job_Manager_Forms {
|
|
80 |
* Returns the form content.
|
81 |
*
|
82 |
* @param string $form_name
|
83 |
-
* @param array $atts Optional passed attributes
|
84 |
* @return string|null
|
85 |
*/
|
86 |
public function get_form( $form_name, $atts = array() ) {
|
87 |
-
$form = $this->load_form_class( $form_name )
|
88 |
-
if ( $form ) {
|
89 |
ob_start();
|
90 |
$form->output( $atts );
|
91 |
return ob_get_clean();
|
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 |
*/
|
49 |
* Load a form's class
|
50 |
*
|
51 |
* @param string $form_name
|
52 |
+
* @return string class name on success, false on failure
|
53 |
*/
|
54 |
private function load_form_class( $form_name ) {
|
55 |
if ( ! class_exists( 'WP_Job_Manager_Form' ) ) {
|
56 |
+
include( 'abstracts/abstract-wp-job-manager-form.php' );
|
57 |
}
|
58 |
|
59 |
+
// Now try to load the form_name
|
60 |
+
$form_class = 'WP_Job_Manager_Form_' . str_replace( '-', '_', $form_name );
|
61 |
+
$form_file = JOB_MANAGER_PLUGIN_DIR . '/includes/forms/class-wp-job-manager-form-' . $form_name . '.php';
|
62 |
|
63 |
if ( class_exists( $form_class ) ) {
|
64 |
return call_user_func( array( $form_class, 'instance' ) );
|
72 |
include $form_file;
|
73 |
}
|
74 |
|
75 |
+
// Init the form
|
76 |
return call_user_func( array( $form_class, 'instance' ) );
|
77 |
}
|
78 |
|
80 |
* Returns the form content.
|
81 |
*
|
82 |
* @param string $form_name
|
83 |
+
* @param array $atts Optional passed attributes
|
84 |
* @return string|null
|
85 |
*/
|
86 |
public function get_form( $form_name, $atts = array() ) {
|
87 |
+
if ( $form = $this->load_form_class( $form_name ) ) {
|
|
|
88 |
ob_start();
|
89 |
$form->output( $atts );
|
90 |
return ob_get_clean();
|
includes/class-wp-job-manager-geocode.php
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
if ( ! defined( 'ABSPATH' ) )
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
|
7 |
/**
|
8 |
* Obtains Geolocation data for posted jobs from Google.
|
@@ -18,14 +16,14 @@ class WP_Job_Manager_Geocode {
|
|
18 |
* The single instance of the class.
|
19 |
*
|
20 |
* @var self
|
21 |
-
* @since 1.26
|
22 |
*/
|
23 |
private static $_instance = null;
|
24 |
|
25 |
/**
|
26 |
* Allows for accessing single instance of class. Class should only be constructed once per call.
|
27 |
*
|
28 |
-
* @since 1.26
|
29 |
* @static
|
30 |
* @return self Main instance.
|
31 |
*/
|
@@ -80,7 +78,7 @@ class WP_Job_Manager_Geocode {
|
|
80 |
* @return boolean
|
81 |
*/
|
82 |
public static function has_location_data( $job_id ) {
|
83 |
-
return
|
84 |
}
|
85 |
|
86 |
/**
|
@@ -154,19 +152,19 @@ class WP_Job_Manager_Geocode {
|
|
154 |
$api_key = apply_filters( 'job_manager_geolocation_api_key', '', $raw_address );
|
155 |
|
156 |
if ( '' !== $api_key ) {
|
157 |
-
$geocode_endpoint_url = add_query_arg( 'key',
|
158 |
}
|
159 |
|
160 |
-
$geocode_endpoint_url = add_query_arg( 'address',
|
161 |
|
162 |
$locale = get_locale();
|
163 |
if ( $locale ) {
|
164 |
-
$geocode_endpoint_url = add_query_arg( 'language',
|
165 |
}
|
166 |
|
167 |
$region = apply_filters( 'job_manager_geolocation_region_cctld', '', $raw_address );
|
168 |
if ( '' !== $region ) {
|
169 |
-
$geocode_endpoint_url = add_query_arg( 'region',
|
170 |
}
|
171 |
|
172 |
return $geocode_endpoint_url;
|
@@ -178,18 +176,10 @@ class WP_Job_Manager_Geocode {
|
|
178 |
* Based on code by Eyal Fitoussi.
|
179 |
*
|
180 |
* @param string $raw_address
|
181 |
-
* @return array|bool location data
|
182 |
-
* @throws Exception After geocoding error.
|
183 |
*/
|
184 |
public static function get_location_data( $raw_address ) {
|
185 |
-
$invalid_chars = array(
|
186 |
-
' ' => '+',
|
187 |
-
',' => '',
|
188 |
-
'?' => '',
|
189 |
-
'&' => '',
|
190 |
-
'=' => '',
|
191 |
-
'#' => '',
|
192 |
-
);
|
193 |
$raw_address = trim( strtolower( str_replace( array_keys( $invalid_chars ), array_values( $invalid_chars ), $raw_address ) ) );
|
194 |
|
195 |
if ( empty( $raw_address ) ) {
|
@@ -200,7 +190,7 @@ class WP_Job_Manager_Geocode {
|
|
200 |
$geocoded_address = get_transient( $transient_name );
|
201 |
$jm_geocode_over_query_limit = get_transient( 'jm_geocode_over_query_limit' );
|
202 |
|
203 |
-
// Query limit reached - don't geocode for a while
|
204 |
if ( $jm_geocode_over_query_limit && false === $geocoded_address ) {
|
205 |
return false;
|
206 |
}
|
@@ -212,32 +202,41 @@ class WP_Job_Manager_Geocode {
|
|
212 |
|
213 |
try {
|
214 |
if ( false === $geocoded_address || empty( $geocoded_address->results[0] ) ) {
|
215 |
-
$result
|
216 |
$geocode_api_url,
|
217 |
array(
|
218 |
'timeout' => 5,
|
219 |
'redirection' => 1,
|
220 |
'httpversion' => '1.1',
|
221 |
'user-agent' => 'WordPress/WP-Job-Manager-' . JOB_MANAGER_VERSION . '; ' . get_bloginfo( 'url' ),
|
222 |
-
'sslverify' => false
|
223 |
)
|
224 |
);
|
225 |
$result = wp_remote_retrieve_body( $result );
|
226 |
$geocoded_address = json_decode( $result );
|
227 |
|
228 |
if ( $geocoded_address->status ) {
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
238 |
}
|
239 |
} else {
|
240 |
-
throw new Exception( __(
|
241 |
}
|
242 |
}
|
243 |
} catch ( Exception $e ) {
|
@@ -262,29 +261,29 @@ class WP_Job_Manager_Geocode {
|
|
262 |
|
263 |
foreach ( $address_data as $data ) {
|
264 |
switch ( $data->types[0] ) {
|
265 |
-
case 'street_number':
|
266 |
$address['street_number'] = sanitize_text_field( $data->long_name );
|
267 |
-
|
268 |
-
case 'route':
|
269 |
-
$address['street']
|
270 |
-
|
271 |
-
case 'sublocality_level_1':
|
272 |
-
case 'locality':
|
273 |
-
case 'postal_town':
|
274 |
-
$address['city']
|
275 |
-
|
276 |
-
case 'administrative_area_level_1':
|
277 |
-
case 'administrative_area_level_2':
|
278 |
-
$address['state_short']
|
279 |
-
$address['state_long']
|
280 |
-
|
281 |
-
case 'postal_code':
|
282 |
-
$address['postcode']
|
283 |
-
|
284 |
-
case 'country':
|
285 |
$address['country_short'] = sanitize_text_field( $data->short_name );
|
286 |
$address['country_long'] = sanitize_text_field( $data->long_name );
|
287 |
-
|
288 |
}
|
289 |
}
|
290 |
}
|
1 |
<?php
|
2 |
|
3 |
+
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
4 |
|
5 |
/**
|
6 |
* Obtains Geolocation data for posted jobs from Google.
|
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 |
*/
|
78 |
* @return boolean
|
79 |
*/
|
80 |
public static function has_location_data( $job_id ) {
|
81 |
+
return get_post_meta( $job_id, 'geolocated', true ) == 1;
|
82 |
}
|
83 |
|
84 |
/**
|
152 |
$api_key = apply_filters( 'job_manager_geolocation_api_key', '', $raw_address );
|
153 |
|
154 |
if ( '' !== $api_key ) {
|
155 |
+
$geocode_endpoint_url = add_query_arg( 'key', urlencode( $api_key ), $geocode_endpoint_url );
|
156 |
}
|
157 |
|
158 |
+
$geocode_endpoint_url = add_query_arg( 'address', urlencode( $raw_address ), $geocode_endpoint_url );
|
159 |
|
160 |
$locale = get_locale();
|
161 |
if ( $locale ) {
|
162 |
+
$geocode_endpoint_url = add_query_arg( 'language', substr( $locale, 0, 2 ), $geocode_endpoint_url );
|
163 |
}
|
164 |
|
165 |
$region = apply_filters( 'job_manager_geolocation_region_cctld', '', $raw_address );
|
166 |
if ( '' !== $region ) {
|
167 |
+
$geocode_endpoint_url = add_query_arg( 'region', urlencode( $region ), $geocode_endpoint_url );
|
168 |
}
|
169 |
|
170 |
return $geocode_endpoint_url;
|
176 |
* Based on code by Eyal Fitoussi.
|
177 |
*
|
178 |
* @param string $raw_address
|
179 |
+
* @return array|bool location data
|
|
|
180 |
*/
|
181 |
public static function get_location_data( $raw_address ) {
|
182 |
+
$invalid_chars = array( " " => "+", "," => "", "?" => "", "&" => "", "=" => "" , "#" => "" );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
$raw_address = trim( strtolower( str_replace( array_keys( $invalid_chars ), array_values( $invalid_chars ), $raw_address ) ) );
|
184 |
|
185 |
if ( empty( $raw_address ) ) {
|
190 |
$geocoded_address = get_transient( $transient_name );
|
191 |
$jm_geocode_over_query_limit = get_transient( 'jm_geocode_over_query_limit' );
|
192 |
|
193 |
+
// Query limit reached - don't geocode for a while
|
194 |
if ( $jm_geocode_over_query_limit && false === $geocoded_address ) {
|
195 |
return false;
|
196 |
}
|
202 |
|
203 |
try {
|
204 |
if ( false === $geocoded_address || empty( $geocoded_address->results[0] ) ) {
|
205 |
+
$result = wp_remote_get(
|
206 |
$geocode_api_url,
|
207 |
array(
|
208 |
'timeout' => 5,
|
209 |
'redirection' => 1,
|
210 |
'httpversion' => '1.1',
|
211 |
'user-agent' => 'WordPress/WP-Job-Manager-' . JOB_MANAGER_VERSION . '; ' . get_bloginfo( 'url' ),
|
212 |
+
'sslverify' => false
|
213 |
)
|
214 |
);
|
215 |
$result = wp_remote_retrieve_body( $result );
|
216 |
$geocoded_address = json_decode( $result );
|
217 |
|
218 |
if ( $geocoded_address->status ) {
|
219 |
+
switch ( $geocoded_address->status ) {
|
220 |
+
case 'ZERO_RESULTS' :
|
221 |
+
throw new Exception( __( "No results found", 'wp-job-manager' ) );
|
222 |
+
break;
|
223 |
+
case 'OVER_QUERY_LIMIT' :
|
224 |
+
set_transient( 'jm_geocode_over_query_limit', 1, HOUR_IN_SECONDS );
|
225 |
+
throw new Exception( __( "Query limit reached", 'wp-job-manager' ) );
|
226 |
+
break;
|
227 |
+
case 'OK' :
|
228 |
+
if ( ! empty( $geocoded_address->results[0] ) ) {
|
229 |
+
set_transient( $transient_name, $geocoded_address, 24 * HOUR_IN_SECONDS * 365 );
|
230 |
+
} else {
|
231 |
+
throw new Exception( __( "Geocoding error", 'wp-job-manager' ) );
|
232 |
+
}
|
233 |
+
break;
|
234 |
+
default :
|
235 |
+
throw new Exception( __( "Geocoding error", 'wp-job-manager' ) );
|
236 |
+
break;
|
237 |
}
|
238 |
} else {
|
239 |
+
throw new Exception( __( "Geocoding error", 'wp-job-manager' ) );
|
240 |
}
|
241 |
}
|
242 |
} catch ( Exception $e ) {
|
261 |
|
262 |
foreach ( $address_data as $data ) {
|
263 |
switch ( $data->types[0] ) {
|
264 |
+
case 'street_number' :
|
265 |
$address['street_number'] = sanitize_text_field( $data->long_name );
|
266 |
+
break;
|
267 |
+
case 'route' :
|
268 |
+
$address['street'] = sanitize_text_field( $data->long_name );
|
269 |
+
break;
|
270 |
+
case 'sublocality_level_1' :
|
271 |
+
case 'locality' :
|
272 |
+
case 'postal_town' :
|
273 |
+
$address['city'] = sanitize_text_field( $data->long_name );
|
274 |
+
break;
|
275 |
+
case 'administrative_area_level_1' :
|
276 |
+
case 'administrative_area_level_2' :
|
277 |
+
$address['state_short'] = sanitize_text_field( $data->short_name );
|
278 |
+
$address['state_long'] = sanitize_text_field( $data->long_name );
|
279 |
+
break;
|
280 |
+
case 'postal_code' :
|
281 |
+
$address['postcode'] = sanitize_text_field( $data->long_name );
|
282 |
+
break;
|
283 |
+
case 'country' :
|
284 |
$address['country_short'] = sanitize_text_field( $data->short_name );
|
285 |
$address['country_long'] = sanitize_text_field( $data->long_name );
|
286 |
+
break;
|
287 |
}
|
288 |
}
|
289 |
}
|
includes/class-wp-job-manager-install.php
CHANGED
@@ -5,7 +5,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
5 |
}
|
6 |
|
7 |
/**
|
8 |
-
* Handles the installation of the WP Job Manager plugin.
|
9 |
*
|
10 |
* @package wp-job-manager
|
11 |
* @since 1.0.0
|
@@ -20,24 +20,20 @@ class WP_Job_Manager_Install {
|
|
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' ) ) {
|
26 |
set_transient( '_job_manager_activation_redirect', 1, HOUR_IN_SECONDS );
|
27 |
}
|
28 |
|
29 |
-
// Update featured posts ordering
|
30 |
if ( version_compare( get_option( 'wp_job_manager_version', JOB_MANAGER_VERSION ), '1.22.0', '<' ) ) {
|
31 |
$wpdb->query( "UPDATE {$wpdb->posts} p SET p.menu_order = 0 WHERE p.post_type='job_listing';" );
|
32 |
$wpdb->query( "UPDATE {$wpdb->posts} p LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id SET p.menu_order = -1 WHERE pm.meta_key = '_featured' AND pm.meta_value='1' AND p.post_type='job_listing';" );
|
33 |
}
|
34 |
|
35 |
-
// Update
|
36 |
-
if ( version_compare( get_option( 'wp_job_manager_version', JOB_MANAGER_VERSION ), '1.28.0', '<' ) ) {
|
37 |
-
self::add_employment_types();
|
38 |
-
}
|
39 |
-
|
40 |
-
// Update legacy options.
|
41 |
if ( false === get_option( 'job_manager_submit_job_form_page_id', false ) && get_option( 'job_manager_submit_page_slug' ) ) {
|
42 |
$page_id = get_page_by_path( get_option( 'job_manager_submit_page_slug' ) )->ID;
|
43 |
update_option( 'job_manager_submit_job_form_page_id', $page_id );
|
@@ -58,19 +54,15 @@ class WP_Job_Manager_Install {
|
|
58 |
global $wp_roles;
|
59 |
|
60 |
if ( class_exists( 'WP_Roles' ) && ! isset( $wp_roles ) ) {
|
61 |
-
$wp_roles = new WP_Roles();
|
62 |
}
|
63 |
|
64 |
if ( is_object( $wp_roles ) ) {
|
65 |
-
add_role(
|
66 |
-
'
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
'edit_posts' => false,
|
71 |
-
'delete_posts' => false,
|
72 |
-
)
|
73 |
-
);
|
74 |
|
75 |
$capabilities = self::get_core_capabilities();
|
76 |
|
@@ -89,49 +81,53 @@ class WP_Job_Manager_Install {
|
|
89 |
*/
|
90 |
private static function get_core_capabilities() {
|
91 |
return array(
|
92 |
-
'core'
|
93 |
-
'manage_job_listings'
|
94 |
),
|
95 |
'job_listing' => array(
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
)
|
114 |
);
|
115 |
}
|
116 |
|
117 |
/**
|
118 |
-
*
|
119 |
*/
|
120 |
private static function default_terms() {
|
121 |
-
if (
|
122 |
return;
|
123 |
}
|
124 |
|
125 |
-
$taxonomies =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
foreach ( $taxonomies as $taxonomy => $terms ) {
|
127 |
-
foreach ( $terms as $term
|
128 |
if ( ! get_term_by( 'slug', sanitize_title( $term ), $taxonomy ) ) {
|
129 |
-
|
130 |
-
if ( is_array( $tt_package ) && isset( $tt_package['term_id'] ) && ! empty( $meta ) ) {
|
131 |
-
foreach ( $meta as $meta_key => $meta_value ) {
|
132 |
-
add_term_meta( $tt_package['term_id'], $meta_key, $meta_value );
|
133 |
-
}
|
134 |
-
}
|
135 |
}
|
136 |
}
|
137 |
}
|
@@ -140,48 +136,14 @@ class WP_Job_Manager_Install {
|
|
140 |
}
|
141 |
|
142 |
/**
|
143 |
-
*
|
144 |
-
*
|
145 |
-
* @return array Default taxonomy terms.
|
146 |
-
*/
|
147 |
-
private static function get_default_taxonomy_terms() {
|
148 |
-
return array(
|
149 |
-
'job_listing_type' => array(
|
150 |
-
'Full Time' => array(
|
151 |
-
'employment_type' => 'FULL_TIME',
|
152 |
-
),
|
153 |
-
'Part Time' => array(
|
154 |
-
'employment_type' => 'PART_TIME',
|
155 |
-
),
|
156 |
-
'Temporary' => array(
|
157 |
-
'employment_type' => 'TEMPORARY',
|
158 |
-
),
|
159 |
-
'Freelance' => array(
|
160 |
-
'employment_type' => 'CONTRACTOR',
|
161 |
-
),
|
162 |
-
'Internship' => array(
|
163 |
-
'employment_type' => 'INTERN',
|
164 |
-
),
|
165 |
-
),
|
166 |
-
);
|
167 |
-
}
|
168 |
-
|
169 |
-
/**
|
170 |
-
* Adds the employment type to default job types when updating from a previous WP Job Manager version.
|
171 |
*/
|
172 |
-
private static function
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
foreach ( $meta as $meta_key => $meta_value ) {
|
180 |
-
if ( ! get_term_meta( (int) $term->term_id, $meta_key, true ) ) {
|
181 |
-
add_term_meta( (int) $term->term_id, $meta_key, $meta_value );
|
182 |
-
}
|
183 |
-
}
|
184 |
-
}
|
185 |
-
}
|
186 |
}
|
187 |
}
|
5 |
}
|
6 |
|
7 |
/**
|
8 |
+
* Handles the installation of the WP Job Manager plugin.s
|
9 |
*
|
10 |
* @package wp-job-manager
|
11 |
* @since 1.0.0
|
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' ) ) {
|
27 |
set_transient( '_job_manager_activation_redirect', 1, HOUR_IN_SECONDS );
|
28 |
}
|
29 |
|
30 |
+
// Update featured posts ordering
|
31 |
if ( version_compare( get_option( 'wp_job_manager_version', JOB_MANAGER_VERSION ), '1.22.0', '<' ) ) {
|
32 |
$wpdb->query( "UPDATE {$wpdb->posts} p SET p.menu_order = 0 WHERE p.post_type='job_listing';" );
|
33 |
$wpdb->query( "UPDATE {$wpdb->posts} p LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id SET p.menu_order = -1 WHERE pm.meta_key = '_featured' AND pm.meta_value='1' AND p.post_type='job_listing';" );
|
34 |
}
|
35 |
|
36 |
+
// Update legacy options
|
|
|
|
|
|
|
|
|
|
|
37 |
if ( false === get_option( 'job_manager_submit_job_form_page_id', false ) && get_option( 'job_manager_submit_page_slug' ) ) {
|
38 |
$page_id = get_page_by_path( get_option( 'job_manager_submit_page_slug' ) )->ID;
|
39 |
update_option( 'job_manager_submit_job_form_page_id', $page_id );
|
54 |
global $wp_roles;
|
55 |
|
56 |
if ( class_exists( 'WP_Roles' ) && ! isset( $wp_roles ) ) {
|
57 |
+
$wp_roles = new WP_Roles();
|
58 |
}
|
59 |
|
60 |
if ( is_object( $wp_roles ) ) {
|
61 |
+
add_role( 'employer', __( 'Employer', 'wp-job-manager' ), array(
|
62 |
+
'read' => true,
|
63 |
+
'edit_posts' => false,
|
64 |
+
'delete_posts' => false
|
65 |
+
) );
|
|
|
|
|
|
|
|
|
66 |
|
67 |
$capabilities = self::get_core_capabilities();
|
68 |
|
81 |
*/
|
82 |
private static function get_core_capabilities() {
|
83 |
return array(
|
84 |
+
'core' => array(
|
85 |
+
'manage_job_listings'
|
86 |
),
|
87 |
'job_listing' => array(
|
88 |
+
"edit_job_listing",
|
89 |
+
"read_job_listing",
|
90 |
+
"delete_job_listing",
|
91 |
+
"edit_job_listings",
|
92 |
+
"edit_others_job_listings",
|
93 |
+
"publish_job_listings",
|
94 |
+
"read_private_job_listings",
|
95 |
+
"delete_job_listings",
|
96 |
+
"delete_private_job_listings",
|
97 |
+
"delete_published_job_listings",
|
98 |
+
"delete_others_job_listings",
|
99 |
+
"edit_private_job_listings",
|
100 |
+
"edit_published_job_listings",
|
101 |
+
"manage_job_listing_terms",
|
102 |
+
"edit_job_listing_terms",
|
103 |
+
"delete_job_listing_terms",
|
104 |
+
"assign_job_listing_terms"
|
105 |
+
)
|
106 |
);
|
107 |
}
|
108 |
|
109 |
/**
|
110 |
+
* Returns the default Job Manager terms.
|
111 |
*/
|
112 |
private static function default_terms() {
|
113 |
+
if ( get_option( 'job_manager_installed_terms' ) == 1 ) {
|
114 |
return;
|
115 |
}
|
116 |
|
117 |
+
$taxonomies = array(
|
118 |
+
'job_listing_type' => array(
|
119 |
+
'Full Time',
|
120 |
+
'Part Time',
|
121 |
+
'Temporary',
|
122 |
+
'Freelance',
|
123 |
+
'Internship'
|
124 |
+
)
|
125 |
+
);
|
126 |
+
|
127 |
foreach ( $taxonomies as $taxonomy => $terms ) {
|
128 |
+
foreach ( $terms as $term ) {
|
129 |
if ( ! get_term_by( 'slug', sanitize_title( $term ), $taxonomy ) ) {
|
130 |
+
wp_insert_term( $term, $taxonomy );
|
|
|
|
|
|
|
|
|
|
|
131 |
}
|
132 |
}
|
133 |
}
|
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 |
}
|
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 |
*/
|
@@ -44,14 +44,11 @@ class WP_Job_Manager_Post_Types {
|
|
44 |
add_action( 'auto-draft_to_publish', array( $this, 'set_expiry' ) );
|
45 |
add_action( 'expired_to_publish', array( $this, 'set_expiry' ) );
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
add_filter( 'the_job_description', '
|
51 |
-
add_filter( 'the_job_description', '
|
52 |
-
add_filter( 'the_job_description', 'convert_chars' );
|
53 |
-
add_filter( 'the_job_description', 'wpautop' );
|
54 |
-
add_filter( 'the_job_description', 'shortcode_unautop' );
|
55 |
add_filter( 'the_job_description', 'prepend_attachment' );
|
56 |
if ( ! empty( $GLOBALS['wp_embed'] ) ) {
|
57 |
add_filter( 'the_job_description', array( $GLOBALS['wp_embed'], 'run_shortcode' ), 8 );
|
@@ -68,7 +65,15 @@ class WP_Job_Manager_Post_Types {
|
|
68 |
|
69 |
add_action( 'parse_query', array( $this, 'add_feed_query_args' ) );
|
70 |
|
71 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
$this->job_content_filter( true );
|
73 |
}
|
74 |
|
@@ -76,217 +81,167 @@ class WP_Job_Manager_Post_Types {
|
|
76 |
* Registers the custom post type and taxonomies.
|
77 |
*/
|
78 |
public function register_post_types() {
|
79 |
-
if ( post_type_exists(
|
80 |
return;
|
81 |
-
}
|
82 |
|
83 |
$admin_capability = 'manage_job_listings';
|
84 |
|
85 |
-
$permalink_structure = WP_Job_Manager_Post_Types::get_permalink_structure();
|
86 |
-
|
87 |
/**
|
88 |
* Taxonomies
|
89 |
*/
|
90 |
if ( get_option( 'job_manager_enable_categories' ) ) {
|
91 |
-
$singular
|
92 |
-
$plural
|
93 |
|
94 |
if ( current_theme_supports( 'job-manager-templates' ) ) {
|
95 |
-
$rewrite
|
96 |
-
'slug' =>
|
97 |
'with_front' => false,
|
98 |
-
'hierarchical' => false
|
99 |
);
|
100 |
-
$public
|
101 |
} else {
|
102 |
-
$rewrite
|
103 |
-
$public
|
104 |
}
|
105 |
|
106 |
-
register_taxonomy(
|
107 |
-
'job_listing_category',
|
108 |
apply_filters( 'register_taxonomy_job_listing_category_object_type', array( 'job_listing' ) ),
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
'
|
115 |
-
'
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
'public' => $public,
|
139 |
-
'capabilities' => array(
|
140 |
-
'manage_terms' => $admin_capability,
|
141 |
-
'edit_terms' => $admin_capability,
|
142 |
-
'delete_terms' => $admin_capability,
|
143 |
-
'assign_terms' => $admin_capability,
|
144 |
-
),
|
145 |
-
'rewrite' => $rewrite,
|
146 |
-
)
|
147 |
-
)
|
148 |
-
);
|
149 |
}
|
150 |
|
151 |
if ( get_option( 'job_manager_enable_types' ) ) {
|
152 |
-
$singular
|
153 |
-
$plural
|
154 |
|
155 |
if ( current_theme_supports( 'job-manager-templates' ) ) {
|
156 |
-
$rewrite
|
157 |
-
'slug' =>
|
158 |
'with_front' => false,
|
159 |
-
'hierarchical' => false
|
160 |
);
|
161 |
-
$public
|
162 |
} else {
|
163 |
-
$rewrite
|
164 |
-
$public
|
165 |
}
|
166 |
|
167 |
-
register_taxonomy(
|
168 |
-
'job_listing_type',
|
169 |
apply_filters( 'register_taxonomy_job_listing_type_object_type', array( 'job_listing' ) ),
|
170 |
-
apply_filters(
|
171 |
-
'
|
172 |
-
|
173 |
-
|
174 |
-
'
|
175 |
-
'
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
'show_tagcloud' => false,
|
198 |
-
'public' => $public,
|
199 |
-
'capabilities' => array(
|
200 |
-
'manage_terms' => $admin_capability,
|
201 |
-
'edit_terms' => $admin_capability,
|
202 |
-
'delete_terms' => $admin_capability,
|
203 |
-
'assign_terms' => $admin_capability,
|
204 |
-
),
|
205 |
-
'rewrite' => $rewrite,
|
206 |
-
)
|
207 |
-
)
|
208 |
);
|
209 |
}
|
210 |
|
211 |
-
|
212 |
* Post types
|
213 |
*/
|
214 |
-
$singular
|
215 |
-
$plural
|
216 |
|
217 |
-
|
218 |
-
* Set whether to add archive page support when registering the job listing post type.
|
219 |
-
*
|
220 |
-
* @since 1.30.0
|
221 |
-
*
|
222 |
-
* @param bool $enable_job_archive_page
|
223 |
-
*/
|
224 |
-
if ( apply_filters( 'job_manager_enable_job_archive_page', current_theme_supports( 'job-manager-templates' ) ) ) {
|
225 |
$has_archive = _x( 'jobs', 'Post type archive slug - resave permalinks after changing this', 'wp-job-manager' );
|
226 |
} else {
|
227 |
$has_archive = false;
|
228 |
}
|
229 |
|
230 |
-
$rewrite
|
231 |
-
'slug' =>
|
232 |
'with_front' => false,
|
233 |
'feeds' => true,
|
234 |
-
'pages' => false
|
235 |
);
|
236 |
|
237 |
-
register_post_type(
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
'
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
'description' => sprintf( __( 'This is where you can create and manage %s.', 'wp-job-manager' ), $plural ),
|
275 |
-
'public' => true,
|
276 |
-
'show_ui' => true,
|
277 |
-
'capability_type' => 'job_listing',
|
278 |
-
'map_meta_cap' => true,
|
279 |
-
'publicly_queryable' => true,
|
280 |
-
'exclude_from_search' => false,
|
281 |
-
'hierarchical' => false,
|
282 |
-
'rewrite' => $rewrite,
|
283 |
-
'query_var' => true,
|
284 |
-
'supports' => array( 'title', 'editor', 'custom-fields', 'publicize', 'thumbnail' ),
|
285 |
-
'has_archive' => $has_archive,
|
286 |
-
'show_in_nav_menus' => false,
|
287 |
-
'delete_with_user' => true,
|
288 |
-
)
|
289 |
-
)
|
290 |
);
|
291 |
|
292 |
/**
|
@@ -297,31 +252,23 @@ class WP_Job_Manager_Post_Types {
|
|
297 |
/**
|
298 |
* Post status
|
299 |
*/
|
300 |
-
register_post_status(
|
301 |
-
'
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
'
|
315 |
-
|
316 |
-
|
317 |
-
'public' => false,
|
318 |
-
'exclude_from_search' => true,
|
319 |
-
'show_in_admin_all_list' => false,
|
320 |
-
'show_in_admin_status_list' => true,
|
321 |
-
// translators: Placeholder %s is the number of posts in a preview state.
|
322 |
-
'label_count' => _n_noop( 'Preview <span class="count">(%s)</span>', 'Preview <span class="count">(%s)</span>', 'wp-job-manager' ),
|
323 |
-
)
|
324 |
-
);
|
325 |
}
|
326 |
|
327 |
/**
|
@@ -330,21 +277,17 @@ class WP_Job_Manager_Post_Types {
|
|
330 |
public function admin_head() {
|
331 |
global $menu;
|
332 |
|
333 |
-
$
|
334 |
-
|
335 |
-
// No need to go further if no pending jobs, menu is not set, or is not an array.
|
336 |
-
if ( empty( $pending_jobs ) || empty( $menu ) || ! is_array( $menu ) ) {
|
337 |
-
return;
|
338 |
-
}
|
339 |
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
}
|
349 |
}
|
350 |
}
|
@@ -394,16 +337,13 @@ class WP_Job_Manager_Post_Types {
|
|
394 |
* Generates the RSS feed for Job Listings.
|
395 |
*/
|
396 |
public function job_feed() {
|
397 |
-
global $job_manager_keyword;
|
398 |
-
|
399 |
$query_args = array(
|
400 |
'post_type' => 'job_listing',
|
401 |
'post_status' => 'publish',
|
402 |
'ignore_sticky_posts' => 1,
|
403 |
'posts_per_page' => isset( $_GET['posts_per_page'] ) ? absint( $_GET['posts_per_page'] ) : 10,
|
404 |
-
'paged' => absint( get_query_var( 'paged', 1 ) ),
|
405 |
'tax_query' => array(),
|
406 |
-
'meta_query' => array()
|
407 |
);
|
408 |
|
409 |
if ( ! empty( $_GET['search_location'] ) ) {
|
@@ -413,7 +353,7 @@ class WP_Job_Manager_Post_Types {
|
|
413 |
$location_search[] = array(
|
414 |
'key' => $meta_key,
|
415 |
'value' => sanitize_text_field( $_GET['search_location'] ),
|
416 |
-
'compare' => 'like'
|
417 |
);
|
418 |
}
|
419 |
$query_args['meta_query'][] = $location_search;
|
@@ -423,25 +363,25 @@ class WP_Job_Manager_Post_Types {
|
|
423 |
$query_args['tax_query'][] = array(
|
424 |
'taxonomy' => 'job_listing_type',
|
425 |
'field' => 'slug',
|
426 |
-
'terms' => explode( ',', sanitize_text_field( $_GET['job_types'] ) ) + array( 0 )
|
427 |
);
|
428 |
}
|
429 |
|
430 |
if ( ! empty( $_GET['job_categories'] ) ) {
|
431 |
-
$cats
|
432 |
-
$field
|
433 |
-
$operator
|
434 |
$query_args['tax_query'][] = array(
|
435 |
'taxonomy' => 'job_listing_category',
|
436 |
'field' => $field,
|
437 |
'terms' => $cats,
|
438 |
-
'include_children' => 'AND'
|
439 |
-
'operator' => $operator
|
440 |
);
|
441 |
}
|
442 |
|
443 |
$job_manager_keyword = isset( $_GET['search_keywords'] ) ? sanitize_text_field( $_GET['search_keywords'] ) : '';
|
444 |
-
if ( !
|
445 |
$query_args['s'] = $job_manager_keyword;
|
446 |
add_filter( 'posts_search', 'get_job_listings_keyword_search' );
|
447 |
}
|
@@ -454,7 +394,7 @@ class WP_Job_Manager_Post_Types {
|
|
454 |
unset( $query_args['tax_query'] );
|
455 |
}
|
456 |
|
457 |
-
query_posts( apply_filters( 'job_feed_args', $query_args ) );
|
458 |
add_action( 'rss2_ns', array( $this, 'job_feed_namespace' ) );
|
459 |
add_action( 'rss2_item', array( $this, 'job_feed_item' ) );
|
460 |
do_feed_rss2( false );
|
@@ -468,7 +408,7 @@ class WP_Job_Manager_Post_Types {
|
|
468 |
*/
|
469 |
public function add_feed_query_args( $wp ) {
|
470 |
|
471 |
-
// Let's leave if not the job feed
|
472 |
if ( ! isset( $wp->query_vars['feed'] ) || 'job_feed' !== $wp->query_vars['feed'] ) {
|
473 |
return;
|
474 |
}
|
@@ -490,27 +430,26 @@ class WP_Job_Manager_Post_Types {
|
|
490 |
* Adds a custom namespace to the job feed.
|
491 |
*/
|
492 |
public function job_feed_namespace() {
|
493 |
-
echo 'xmlns:job_listing="' .
|
494 |
}
|
495 |
|
496 |
/**
|
497 |
* Adds custom data to the job feed.
|
498 |
*/
|
499 |
public function job_feed_item() {
|
500 |
-
$post_id
|
501 |
-
$location
|
502 |
-
$
|
503 |
-
$
|
504 |
|
505 |
if ( $location ) {
|
506 |
-
echo
|
507 |
}
|
508 |
-
if (
|
509 |
-
|
510 |
-
echo '<job_listing:job_type><![CDATA[' . esc_html( $job_types_names ) . "]]></job_listing:job_type>\n";
|
511 |
}
|
512 |
if ( $company ) {
|
513 |
-
echo
|
514 |
}
|
515 |
|
516 |
/**
|
@@ -527,40 +466,34 @@ class WP_Job_Manager_Post_Types {
|
|
527 |
public function check_for_expired_jobs() {
|
528 |
global $wpdb;
|
529 |
|
530 |
-
// Change status to expired
|
531 |
-
$job_ids = $wpdb->get_col(
|
532 |
-
$wpdb->
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
date( 'Y-m-d', current_time( 'timestamp' ) )
|
541 |
-
)
|
542 |
-
);
|
543 |
|
544 |
if ( $job_ids ) {
|
545 |
foreach ( $job_ids as $job_id ) {
|
546 |
-
$job_data
|
547 |
-
$job_data['ID']
|
548 |
$job_data['post_status'] = 'expired';
|
549 |
wp_update_post( $job_data );
|
550 |
}
|
551 |
}
|
552 |
|
553 |
-
// Delete old expired jobs
|
554 |
if ( apply_filters( 'job_manager_delete_expired_jobs', false ) ) {
|
555 |
-
$job_ids = $wpdb->get_col(
|
556 |
-
$wpdb->
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
date( 'Y-m-d', strtotime( '-' . apply_filters( 'job_manager_delete_expired_jobs_days', 30 ) . ' days', current_time( 'timestamp' ) ) )
|
562 |
-
)
|
563 |
-
);
|
564 |
|
565 |
if ( $job_ids ) {
|
566 |
foreach ( $job_ids as $job_id ) {
|
@@ -576,16 +509,13 @@ class WP_Job_Manager_Post_Types {
|
|
576 |
public function delete_old_previews() {
|
577 |
global $wpdb;
|
578 |
|
579 |
-
// Delete old expired jobs
|
580 |
-
$job_ids = $wpdb->get_col(
|
581 |
-
$wpdb->
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
date( 'Y-m-d', strtotime( '-30 days', current_time( 'timestamp' ) ) )
|
587 |
-
)
|
588 |
-
);
|
589 |
|
590 |
if ( $job_ids ) {
|
591 |
foreach ( $job_ids as $job_id ) {
|
@@ -598,11 +528,9 @@ class WP_Job_Manager_Post_Types {
|
|
598 |
* Typo wrapper for `set_expiry` method.
|
599 |
*
|
600 |
* @param WP_Post $post
|
601 |
-
* @
|
602 |
-
* @deprecated 1.0.1
|
603 |
*/
|
604 |
public function set_expirey( $post ) {
|
605 |
-
_deprecated_function( __METHOD__, '1.0.1', 'WP_Job_Manager_Post_Types::set_expiry' );
|
606 |
$this->set_expiry( $post );
|
607 |
}
|
608 |
|
@@ -612,11 +540,11 @@ class WP_Job_Manager_Post_Types {
|
|
612 |
* @param WP_Post $post
|
613 |
*/
|
614 |
public function set_expiry( $post ) {
|
615 |
-
if (
|
616 |
return;
|
617 |
}
|
618 |
|
619 |
-
// See if it is already set
|
620 |
if ( metadata_exists( 'post', $post->ID, '_job_expires' ) ) {
|
621 |
$expires = get_post_meta( $post->ID, '_job_expires', true );
|
622 |
if ( $expires && strtotime( $expires ) < current_time( 'timestamp' ) ) {
|
@@ -624,17 +552,18 @@ class WP_Job_Manager_Post_Types {
|
|
624 |
}
|
625 |
}
|
626 |
|
627 |
-
// See if the user has set the expiry manually
|
628 |
-
if ( ! empty( $_POST['_job_expires'] ) ) {
|
629 |
-
update_post_meta( $post->ID, '_job_expires', date( 'Y-m-d', strtotime( sanitize_text_field( $_POST['_job_expires'] ) ) ) );
|
630 |
-
|
631 |
-
|
|
|
632 |
$expires = calculate_job_expiry( $post->ID );
|
633 |
update_post_meta( $post->ID, '_job_expires', $expires );
|
634 |
|
635 |
-
// In case we are saving a post, ensure post data is updated so the field is not overridden
|
636 |
-
if ( isset( $_POST['_job_expires'] ) ) {
|
637 |
-
$_POST['_job_expires'] = $expires;
|
638 |
}
|
639 |
}
|
640 |
}
|
@@ -665,48 +594,10 @@ class WP_Job_Manager_Post_Types {
|
|
665 |
* @return array
|
666 |
*/
|
667 |
public function fix_post_name( $data, $postarr ) {
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
) {
|
673 |
-
$data['post_name'] = $postarr['post_name'];
|
674 |
-
}
|
675 |
-
return $data;
|
676 |
-
}
|
677 |
-
|
678 |
-
/**
|
679 |
-
* Retrieves permalink settings.
|
680 |
-
*
|
681 |
-
* @see https://github.com/woocommerce/woocommerce/blob/3.0.8/includes/wc-core-functions.php#L1573
|
682 |
-
* @since 1.28.0
|
683 |
-
* @return array
|
684 |
-
*/
|
685 |
-
public static function get_permalink_structure() {
|
686 |
-
// Switch to the site's default locale, bypassing the active user's locale.
|
687 |
-
if ( function_exists( 'switch_to_locale' ) && did_action( 'admin_init' ) ) {
|
688 |
-
switch_to_locale( get_locale() );
|
689 |
-
}
|
690 |
-
|
691 |
-
$permalinks = wp_parse_args(
|
692 |
-
(array) get_option( 'wpjm_permalinks', array() ),
|
693 |
-
array(
|
694 |
-
'job_base' => '',
|
695 |
-
'category_base' => '',
|
696 |
-
'type_base' => '',
|
697 |
-
)
|
698 |
-
);
|
699 |
-
|
700 |
-
// Ensure rewrite slugs are set.
|
701 |
-
$permalinks['job_rewrite_slug'] = untrailingslashit( empty( $permalinks['job_base'] ) ? _x( 'job', 'Job permalink - resave permalinks after changing this', 'wp-job-manager' ) : $permalinks['job_base'] );
|
702 |
-
$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'] );
|
703 |
-
$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'] );
|
704 |
-
|
705 |
-
// Restore the original locale.
|
706 |
-
if ( function_exists( 'restore_current_locale' ) && did_action( 'admin_init' ) ) {
|
707 |
-
restore_current_locale();
|
708 |
-
}
|
709 |
-
return $permalinks;
|
710 |
}
|
711 |
|
712 |
/**
|
@@ -734,12 +625,12 @@ class WP_Job_Manager_Post_Types {
|
|
734 |
public function update_post_meta( $meta_id, $object_id, $meta_key, $meta_value ) {
|
735 |
if ( 'job_listing' === get_post_type( $object_id ) ) {
|
736 |
switch ( $meta_key ) {
|
737 |
-
case '_job_location':
|
738 |
$this->maybe_update_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value );
|
739 |
-
|
740 |
-
case '_featured':
|
741 |
$this->maybe_update_menu_order( $meta_id, $object_id, $meta_key, $meta_value );
|
742 |
-
|
743 |
}
|
744 |
}
|
745 |
}
|
@@ -747,9 +638,9 @@ class WP_Job_Manager_Post_Types {
|
|
747 |
/**
|
748 |
* Generates location data if a post is updated.
|
749 |
*
|
750 |
-
* @param int $meta_id (Unused)
|
751 |
* @param int $object_id
|
752 |
-
* @param string $meta_key (Unused)
|
753 |
* @param mixed $meta_value
|
754 |
*/
|
755 |
public function maybe_update_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value ) {
|
@@ -759,29 +650,18 @@ class WP_Job_Manager_Post_Types {
|
|
759 |
/**
|
760 |
* Maybe sets menu_order if the featured status of a job is changed.
|
761 |
*
|
762 |
-
* @param int $meta_id (Unused)
|
763 |
* @param int $object_id
|
764 |
-
* @param string $meta_key (Unused)
|
765 |
* @param mixed $meta_value
|
766 |
*/
|
767 |
public function maybe_update_menu_order( $meta_id, $object_id, $meta_key, $meta_value ) {
|
768 |
global $wpdb;
|
769 |
|
770 |
-
if ( 1
|
771 |
-
$wpdb->update(
|
772 |
-
$wpdb->posts,
|
773 |
-
array( 'menu_order' => -1 ),
|
774 |
-
array( 'ID' => $object_id )
|
775 |
-
);
|
776 |
} else {
|
777 |
-
$wpdb->update(
|
778 |
-
$wpdb->posts,
|
779 |
-
array( 'menu_order' => 0 ),
|
780 |
-
array(
|
781 |
-
'ID' => $object_id,
|
782 |
-
'menu_order' => -1,
|
783 |
-
)
|
784 |
-
);
|
785 |
}
|
786 |
|
787 |
clean_post_cache( $object_id );
|
@@ -797,7 +677,6 @@ class WP_Job_Manager_Post_Types {
|
|
797 |
* @deprecated 1.19.1
|
798 |
*/
|
799 |
public function maybe_generate_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value ) {
|
800 |
-
_deprecated_function( __METHOD__, '1.19.1', 'WP_Job_Manager_Post_Types::maybe_update_geolocation_data' );
|
801 |
$this->maybe_update_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value );
|
802 |
}
|
803 |
|
@@ -815,41 +694,62 @@ class WP_Job_Manager_Post_Types {
|
|
815 |
}
|
816 |
|
817 |
/**
|
818 |
-
*
|
|
|
|
|
819 |
*/
|
820 |
-
public function
|
821 |
-
if (
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
if ( ! $post || 'job_listing' !== $post->post_type ) {
|
827 |
-
return;
|
828 |
-
}
|
829 |
-
|
830 |
-
if ( wpjm_allow_indexing_job_listing() ) {
|
831 |
-
return;
|
832 |
}
|
833 |
-
|
834 |
-
wp_no_robots();
|
835 |
}
|
836 |
|
837 |
/**
|
838 |
-
*
|
|
|
|
|
|
|
|
|
|
|
839 |
*/
|
840 |
-
public function
|
841 |
-
if (
|
842 |
-
return;
|
843 |
}
|
|
|
|
|
844 |
|
845 |
-
|
846 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
847 |
}
|
|
|
|
|
848 |
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
853 |
}
|
|
|
854 |
}
|
855 |
}
|
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 |
*/
|
44 |
add_action( 'auto-draft_to_publish', array( $this, 'set_expiry' ) );
|
45 |
add_action( 'expired_to_publish', array( $this, 'set_expiry' ) );
|
46 |
|
47 |
+
add_filter( 'the_job_description', 'wptexturize' );
|
48 |
+
add_filter( 'the_job_description', 'convert_smilies' );
|
49 |
+
add_filter( 'the_job_description', 'convert_chars' );
|
50 |
+
add_filter( 'the_job_description', 'wpautop' );
|
51 |
+
add_filter( 'the_job_description', 'shortcode_unautop' );
|
|
|
|
|
|
|
52 |
add_filter( 'the_job_description', 'prepend_attachment' );
|
53 |
if ( ! empty( $GLOBALS['wp_embed'] ) ) {
|
54 |
add_filter( 'the_job_description', array( $GLOBALS['wp_embed'], 'run_shortcode' ), 8 );
|
65 |
|
66 |
add_action( 'parse_query', array( $this, 'add_feed_query_args' ) );
|
67 |
|
68 |
+
// WP ALL Import
|
69 |
+
add_action( 'pmxi_saved_post', array( $this, 'pmxi_saved_post' ), 10, 1 );
|
70 |
+
|
71 |
+
// RP4WP
|
72 |
+
add_filter( 'rp4wp_get_template', array( $this, 'rp4wp_template' ), 10, 3 );
|
73 |
+
add_filter( 'rp4wp_related_meta_fields', array( $this, 'rp4wp_related_meta_fields' ), 10, 3 );
|
74 |
+
add_filter( 'rp4wp_related_meta_fields_weight', array( $this, 'rp4wp_related_meta_fields_weight' ), 10, 3 );
|
75 |
+
|
76 |
+
// Single job content
|
77 |
$this->job_content_filter( true );
|
78 |
}
|
79 |
|
81 |
* Registers the custom post type and taxonomies.
|
82 |
*/
|
83 |
public function register_post_types() {
|
84 |
+
if ( post_type_exists( "job_listing" ) )
|
85 |
return;
|
|
|
86 |
|
87 |
$admin_capability = 'manage_job_listings';
|
88 |
|
|
|
|
|
89 |
/**
|
90 |
* Taxonomies
|
91 |
*/
|
92 |
if ( get_option( 'job_manager_enable_categories' ) ) {
|
93 |
+
$singular = __( 'Job category', 'wp-job-manager' );
|
94 |
+
$plural = __( 'Job categories', 'wp-job-manager' );
|
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 |
);
|
102 |
+
$public = true;
|
103 |
} else {
|
104 |
+
$rewrite = false;
|
105 |
+
$public = false;
|
106 |
}
|
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 ),
|
118 |
+
'search_items' => sprintf( __( 'Search %s', 'wp-job-manager' ), $plural ),
|
119 |
+
'all_items' => sprintf( __( 'All %s', 'wp-job-manager' ), $plural ),
|
120 |
+
'parent_item' => sprintf( __( 'Parent %s', 'wp-job-manager' ), $singular ),
|
121 |
+
'parent_item_colon' => sprintf( __( 'Parent %s:', 'wp-job-manager' ), $singular ),
|
122 |
+
'edit_item' => sprintf( __( 'Edit %s', 'wp-job-manager' ), $singular ),
|
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' ) ) {
|
142 |
+
$singular = __( 'Job type', 'wp-job-manager' );
|
143 |
+
$plural = __( 'Job types', 'wp-job-manager' );
|
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 |
);
|
151 |
+
$public = true;
|
152 |
} else {
|
153 |
+
$rewrite = false;
|
154 |
+
$public = false;
|
155 |
}
|
156 |
|
157 |
+
register_taxonomy( "job_listing_type",
|
|
|
158 |
apply_filters( 'register_taxonomy_job_listing_type_object_type', array( 'job_listing' ) ),
|
159 |
+
apply_filters( 'register_taxonomy_job_listing_type_args', array(
|
160 |
+
'hierarchical' => true,
|
161 |
+
'label' => $plural,
|
162 |
+
'labels' => array(
|
163 |
+
'name' => $plural,
|
164 |
+
'singular_name' => $singular,
|
165 |
+
'menu_name' => ucwords( $plural ),
|
166 |
+
'search_items' => sprintf( __( 'Search %s', 'wp-job-manager' ), $plural ),
|
167 |
+
'all_items' => sprintf( __( 'All %s', 'wp-job-manager' ), $plural ),
|
168 |
+
'parent_item' => sprintf( __( 'Parent %s', 'wp-job-manager' ), $singular ),
|
169 |
+
'parent_item_colon' => sprintf( __( 'Parent %s:', 'wp-job-manager' ), $singular ),
|
170 |
+
'edit_item' => sprintf( __( 'Edit %s', 'wp-job-manager' ), $singular ),
|
171 |
+
'update_item' => sprintf( __( 'Update %s', 'wp-job-manager' ), $singular ),
|
172 |
+
'add_new_item' => sprintf( __( 'Add New %s', 'wp-job-manager' ), $singular ),
|
173 |
+
'new_item_name' => sprintf( __( 'New %s Name', 'wp-job-manager' ), $singular )
|
174 |
+
),
|
175 |
+
'show_ui' => true,
|
176 |
+
'show_tagcloud' => false,
|
177 |
+
'public' => $public,
|
178 |
+
'capabilities' => array(
|
179 |
+
'manage_terms' => $admin_capability,
|
180 |
+
'edit_terms' => $admin_capability,
|
181 |
+
'delete_terms' => $admin_capability,
|
182 |
+
'assign_terms' => $admin_capability,
|
183 |
+
),
|
184 |
+
'rewrite' => $rewrite,
|
185 |
+
) )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
);
|
187 |
}
|
188 |
|
189 |
+
/**
|
190 |
* Post types
|
191 |
*/
|
192 |
+
$singular = __( 'Job', 'wp-job-manager' );
|
193 |
+
$plural = __( 'Jobs', 'wp-job-manager' );
|
194 |
|
195 |
+
if ( current_theme_supports( 'job-manager-templates' ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
$has_archive = _x( 'jobs', 'Post type archive slug - resave permalinks after changing this', 'wp-job-manager' );
|
197 |
} else {
|
198 |
$has_archive = false;
|
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
|
206 |
);
|
207 |
|
208 |
+
register_post_type( "job_listing",
|
209 |
+
apply_filters( "register_post_type_job_listing", array(
|
210 |
+
'labels' => array(
|
211 |
+
'name' => $plural,
|
212 |
+
'singular_name' => $singular,
|
213 |
+
'menu_name' => __( 'Job Listings', 'wp-job-manager' ),
|
214 |
+
'all_items' => sprintf( __( 'All %s', 'wp-job-manager' ), $plural ),
|
215 |
+
'add_new' => __( 'Add New', 'wp-job-manager' ),
|
216 |
+
'add_new_item' => sprintf( __( 'Add %s', 'wp-job-manager' ), $singular ),
|
217 |
+
'edit' => __( 'Edit', 'wp-job-manager' ),
|
218 |
+
'edit_item' => sprintf( __( 'Edit %s', 'wp-job-manager' ), $singular ),
|
219 |
+
'new_item' => sprintf( __( 'New %s', 'wp-job-manager' ), $singular ),
|
220 |
+
'view' => sprintf( __( 'View %s', 'wp-job-manager' ), $singular ),
|
221 |
+
'view_item' => sprintf( __( 'View %s', 'wp-job-manager' ), $singular ),
|
222 |
+
'search_items' => sprintf( __( 'Search %s', 'wp-job-manager' ), $plural ),
|
223 |
+
'not_found' => sprintf( __( 'No %s found', 'wp-job-manager' ), $plural ),
|
224 |
+
'not_found_in_trash' => sprintf( __( 'No %s found in trash', 'wp-job-manager' ), $plural ),
|
225 |
+
'parent' => sprintf( __( 'Parent %s', 'wp-job-manager' ), $singular ),
|
226 |
+
'featured_image' => __( 'Company Logo', 'wp-job-manager' ),
|
227 |
+
'set_featured_image' => __( 'Set company logo', 'wp-job-manager' ),
|
228 |
+
'remove_featured_image' => __( 'Remove company logo', 'wp-job-manager' ),
|
229 |
+
'use_featured_image' => __( 'Use as company logo', 'wp-job-manager' ),
|
230 |
+
),
|
231 |
+
'description' => sprintf( __( 'This is where you can create and manage %s.', 'wp-job-manager' ), $plural ),
|
232 |
+
'public' => true,
|
233 |
+
'show_ui' => true,
|
234 |
+
'capability_type' => 'job_listing',
|
235 |
+
'map_meta_cap' => true,
|
236 |
+
'publicly_queryable' => true,
|
237 |
+
'exclude_from_search' => false,
|
238 |
+
'hierarchical' => false,
|
239 |
+
'rewrite' => $rewrite,
|
240 |
+
'query_var' => true,
|
241 |
+
'supports' => array( 'title', 'editor', 'custom-fields', 'publicize', 'thumbnail' ),
|
242 |
+
'has_archive' => $has_archive,
|
243 |
+
'show_in_nav_menus' => false
|
244 |
+
) )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
);
|
246 |
|
247 |
/**
|
252 |
/**
|
253 |
* Post status
|
254 |
*/
|
255 |
+
register_post_status( 'expired', array(
|
256 |
+
'label' => _x( 'Expired', 'post status', 'wp-job-manager' ),
|
257 |
+
'public' => true,
|
258 |
+
'protected' => true,
|
259 |
+
'exclude_from_search' => true,
|
260 |
+
'show_in_admin_all_list' => true,
|
261 |
+
'show_in_admin_status_list' => true,
|
262 |
+
'label_count' => _n_noop( 'Expired <span class="count">(%s)</span>', 'Expired <span class="count">(%s)</span>', 'wp-job-manager' ),
|
263 |
+
) );
|
264 |
+
register_post_status( 'preview', array(
|
265 |
+
'label' => _x( 'Preview', 'post status', 'wp-job-manager' ),
|
266 |
+
'public' => false,
|
267 |
+
'exclude_from_search' => true,
|
268 |
+
'show_in_admin_all_list' => false,
|
269 |
+
'show_in_admin_status_list' => true,
|
270 |
+
'label_count' => _n_noop( 'Preview <span class="count">(%s)</span>', 'Preview <span class="count">(%s)</span>', 'wp-job-manager' ),
|
271 |
+
) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
272 |
}
|
273 |
|
274 |
/**
|
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 |
}
|
337 |
* Generates the RSS feed for Job Listings.
|
338 |
*/
|
339 |
public function job_feed() {
|
|
|
|
|
340 |
$query_args = array(
|
341 |
'post_type' => 'job_listing',
|
342 |
'post_status' => 'publish',
|
343 |
'ignore_sticky_posts' => 1,
|
344 |
'posts_per_page' => isset( $_GET['posts_per_page'] ) ? absint( $_GET['posts_per_page'] ) : 10,
|
|
|
345 |
'tax_query' => array(),
|
346 |
+
'meta_query' => array()
|
347 |
);
|
348 |
|
349 |
if ( ! empty( $_GET['search_location'] ) ) {
|
353 |
$location_search[] = array(
|
354 |
'key' => $meta_key,
|
355 |
'value' => sanitize_text_field( $_GET['search_location'] ),
|
356 |
+
'compare' => 'like'
|
357 |
);
|
358 |
}
|
359 |
$query_args['meta_query'][] = $location_search;
|
363 |
$query_args['tax_query'][] = array(
|
364 |
'taxonomy' => 'job_listing_type',
|
365 |
'field' => 'slug',
|
366 |
+
'terms' => explode( ',', sanitize_text_field( $_GET['job_types'] ) ) + array( 0 )
|
367 |
);
|
368 |
}
|
369 |
|
370 |
if ( ! empty( $_GET['job_categories'] ) ) {
|
371 |
+
$cats = explode( ',', sanitize_text_field( $_GET['job_categories'] ) ) + array( 0 );
|
372 |
+
$field = is_numeric( $cats ) ? 'term_id' : 'slug';
|
373 |
+
$operator = 'all' === get_option( 'job_manager_category_filter_type', 'all' ) && sizeof( $args['search_categories'] ) > 1 ? 'AND' : 'IN';
|
374 |
$query_args['tax_query'][] = array(
|
375 |
'taxonomy' => 'job_listing_category',
|
376 |
'field' => $field,
|
377 |
'terms' => $cats,
|
378 |
+
'include_children' => $operator !== 'AND' ,
|
379 |
+
'operator' => $operator
|
380 |
);
|
381 |
}
|
382 |
|
383 |
$job_manager_keyword = isset( $_GET['search_keywords'] ) ? sanitize_text_field( $_GET['search_keywords'] ) : '';
|
384 |
+
if ( !empty( $job_manager_keyword ) ) {
|
385 |
$query_args['s'] = $job_manager_keyword;
|
386 |
add_filter( 'posts_search', 'get_job_listings_keyword_search' );
|
387 |
}
|
394 |
unset( $query_args['tax_query'] );
|
395 |
}
|
396 |
|
397 |
+
query_posts( apply_filters( 'job_feed_args', $query_args ) );
|
398 |
add_action( 'rss2_ns', array( $this, 'job_feed_namespace' ) );
|
399 |
add_action( 'rss2_item', array( $this, 'job_feed_item' ) );
|
400 |
do_feed_rss2( false );
|
408 |
*/
|
409 |
public function add_feed_query_args( $wp ) {
|
410 |
|
411 |
+
// Let's leave if not the job feed
|
412 |
if ( ! isset( $wp->query_vars['feed'] ) || 'job_feed' !== $wp->query_vars['feed'] ) {
|
413 |
return;
|
414 |
}
|
430 |
* Adds a custom namespace to the job feed.
|
431 |
*/
|
432 |
public function job_feed_namespace() {
|
433 |
+
echo 'xmlns:job_listing="' . site_url() . '"' . "\n";
|
434 |
}
|
435 |
|
436 |
/**
|
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";
|
453 |
}
|
454 |
|
455 |
/**
|
466 |
public function check_for_expired_jobs() {
|
467 |
global $wpdb;
|
468 |
|
469 |
+
// Change status to expired
|
470 |
+
$job_ids = $wpdb->get_col( $wpdb->prepare( "
|
471 |
+
SELECT postmeta.post_id FROM {$wpdb->postmeta} as postmeta
|
472 |
+
LEFT JOIN {$wpdb->posts} as posts ON postmeta.post_id = posts.ID
|
473 |
+
WHERE postmeta.meta_key = '_job_expires'
|
474 |
+
AND postmeta.meta_value > 0
|
475 |
+
AND postmeta.meta_value < %s
|
476 |
+
AND posts.post_status = 'publish'
|
477 |
+
AND posts.post_type = 'job_listing'
|
478 |
+
", date( 'Y-m-d', current_time( 'timestamp' ) ) ) );
|
|
|
|
|
|
|
479 |
|
480 |
if ( $job_ids ) {
|
481 |
foreach ( $job_ids as $job_id ) {
|
482 |
+
$job_data = array();
|
483 |
+
$job_data['ID'] = $job_id;
|
484 |
$job_data['post_status'] = 'expired';
|
485 |
wp_update_post( $job_data );
|
486 |
}
|
487 |
}
|
488 |
|
489 |
+
// Delete old expired jobs
|
490 |
if ( apply_filters( 'job_manager_delete_expired_jobs', false ) ) {
|
491 |
+
$job_ids = $wpdb->get_col( $wpdb->prepare( "
|
492 |
+
SELECT posts.ID FROM {$wpdb->posts} as posts
|
493 |
+
WHERE posts.post_type = 'job_listing'
|
494 |
+
AND posts.post_modified < %s
|
495 |
+
AND posts.post_status = 'expired'
|
496 |
+
", date( 'Y-m-d', strtotime( '-' . apply_filters( 'job_manager_delete_expired_jobs_days', 30 ) . ' days', current_time( 'timestamp' ) ) ) ) );
|
|
|
|
|
|
|
497 |
|
498 |
if ( $job_ids ) {
|
499 |
foreach ( $job_ids as $job_id ) {
|
509 |
public function delete_old_previews() {
|
510 |
global $wpdb;
|
511 |
|
512 |
+
// Delete old expired jobs
|
513 |
+
$job_ids = $wpdb->get_col( $wpdb->prepare( "
|
514 |
+
SELECT posts.ID FROM {$wpdb->posts} as posts
|
515 |
+
WHERE posts.post_type = 'job_listing'
|
516 |
+
AND posts.post_modified < %s
|
517 |
+
AND posts.post_status = 'preview'
|
518 |
+
", date( 'Y-m-d', strtotime( '-30 days', current_time( 'timestamp' ) ) ) ) );
|
|
|
|
|
|
|
519 |
|
520 |
if ( $job_ids ) {
|
521 |
foreach ( $job_ids as $job_id ) {
|
528 |
* Typo wrapper for `set_expiry` method.
|
529 |
*
|
530 |
* @param WP_Post $post
|
531 |
+
* @deprecated
|
|
|
532 |
*/
|
533 |
public function set_expirey( $post ) {
|
|
|
534 |
$this->set_expiry( $post );
|
535 |
}
|
536 |
|
540 |
* @param WP_Post $post
|
541 |
*/
|
542 |
public function set_expiry( $post ) {
|
543 |
+
if ( $post->post_type !== 'job_listing' ) {
|
544 |
return;
|
545 |
}
|
546 |
|
547 |
+
// See if it is already set
|
548 |
if ( metadata_exists( 'post', $post->ID, '_job_expires' ) ) {
|
549 |
$expires = get_post_meta( $post->ID, '_job_expires', true );
|
550 |
if ( $expires && strtotime( $expires ) < current_time( 'timestamp' ) ) {
|
552 |
}
|
553 |
}
|
554 |
|
555 |
+
// See if the user has set the expiry manually:
|
556 |
+
if ( ! empty( $_POST[ '_job_expires' ] ) ) {
|
557 |
+
update_post_meta( $post->ID, '_job_expires', date( 'Y-m-d', strtotime( sanitize_text_field( $_POST[ '_job_expires' ] ) ) ) );
|
558 |
+
|
559 |
+
// No manual setting? Lets generate a date if there isn't already one
|
560 |
+
} elseif ( false == isset( $expires ) ) {
|
561 |
$expires = calculate_job_expiry( $post->ID );
|
562 |
update_post_meta( $post->ID, '_job_expires', $expires );
|
563 |
|
564 |
+
// In case we are saving a post, ensure post data is updated so the field is not overridden
|
565 |
+
if ( isset( $_POST[ '_job_expires' ] ) ) {
|
566 |
+
$_POST[ '_job_expires' ] = $expires;
|
567 |
}
|
568 |
}
|
569 |
}
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
601 |
}
|
602 |
|
603 |
/**
|
625 |
public function update_post_meta( $meta_id, $object_id, $meta_key, $meta_value ) {
|
626 |
if ( 'job_listing' === get_post_type( $object_id ) ) {
|
627 |
switch ( $meta_key ) {
|
628 |
+
case '_job_location' :
|
629 |
$this->maybe_update_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value );
|
630 |
+
break;
|
631 |
+
case '_featured' :
|
632 |
$this->maybe_update_menu_order( $meta_id, $object_id, $meta_key, $meta_value );
|
633 |
+
break;
|
634 |
}
|
635 |
}
|
636 |
}
|
638 |
/**
|
639 |
* Generates location data if a post is updated.
|
640 |
*
|
641 |
+
* @param int $meta_id (Unused)
|
642 |
* @param int $object_id
|
643 |
+
* @param string $meta_key (Unused)
|
644 |
* @param mixed $meta_value
|
645 |
*/
|
646 |
public function maybe_update_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value ) {
|
650 |
/**
|
651 |
* Maybe sets menu_order if the featured status of a job is changed.
|
652 |
*
|
653 |
+
* @param int $meta_id (Unused)
|
654 |
* @param int $object_id
|
655 |
+
* @param string $meta_key (Unused)
|
656 |
* @param mixed $meta_value
|
657 |
*/
|
658 |
public function maybe_update_menu_order( $meta_id, $object_id, $meta_key, $meta_value ) {
|
659 |
global $wpdb;
|
660 |
|
661 |
+
if ( '1' == $meta_value ) {
|
662 |
+
$wpdb->update( $wpdb->posts, array( 'menu_order' => -1 ), array( 'ID' => $object_id ) );
|
|
|
|
|
|
|
|
|
663 |
} else {
|
664 |
+
$wpdb->update( $wpdb->posts, array( 'menu_order' => 0 ), array( 'ID' => $object_id, 'menu_order' => -1 ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
665 |
}
|
666 |
|
667 |
clean_post_cache( $object_id );
|
677 |
* @deprecated 1.19.1
|
678 |
*/
|
679 |
public function maybe_generate_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value ) {
|
|
|
680 |
$this->maybe_update_geolocation_data( $meta_id, $object_id, $meta_key, $meta_value );
|
681 |
}
|
682 |
|
694 |
}
|
695 |
|
696 |
/**
|
697 |
+
* After importing via WP All Import, adds default meta data.
|
698 |
+
*
|
699 |
+
* @param int $post_id
|
700 |
*/
|
701 |
+
public function pmxi_saved_post( $post_id ) {
|
702 |
+
if ( 'job_listing' === get_post_type( $post_id ) ) {
|
703 |
+
$this->maybe_add_default_meta_data( $post_id );
|
704 |
+
if ( ! WP_Job_Manager_Geocode::has_location_data( $post_id ) && ( $location = get_post_meta( $post_id, '_job_location', true ) ) ) {
|
705 |
+
WP_Job_Manager_Geocode::generate_location_data( $post_id, $location );
|
706 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
707 |
}
|
|
|
|
|
708 |
}
|
709 |
|
710 |
/**
|
711 |
+
* Replaces RP4WP template with the template from Job Manager.
|
712 |
+
*
|
713 |
+
* @param string $located
|
714 |
+
* @param string $template_name
|
715 |
+
* @param array $args
|
716 |
+
* @return string
|
717 |
*/
|
718 |
+
public function rp4wp_template( $located, $template_name, $args ) {
|
719 |
+
if ( 'related-post-default.php' === $template_name && 'job_listing' === $args['related_post']->post_type ) {
|
720 |
+
return JOB_MANAGER_PLUGIN_DIR . '/templates/content-job_listing.php';
|
721 |
}
|
722 |
+
return $located;
|
723 |
+
}
|
724 |
|
725 |
+
/**
|
726 |
+
* Adds meta fields for RP4WP to relate jobs by.
|
727 |
+
*
|
728 |
+
* @param array $meta_fields
|
729 |
+
* @param int $post_id
|
730 |
+
* @param WP_Post $post
|
731 |
+
* @return array
|
732 |
+
*/
|
733 |
+
public function rp4wp_related_meta_fields( $meta_fields, $post_id, $post ) {
|
734 |
+
if ( 'job_listing' === $post->post_type ) {
|
735 |
+
$meta_fields[] = '_company_name';
|
736 |
+
$meta_fields[] = '_job_location';
|
737 |
}
|
738 |
+
return $meta_fields;
|
739 |
+
}
|
740 |
|
741 |
+
/**
|
742 |
+
* Adds meta fields for RP4WP to relate jobs by.
|
743 |
+
*
|
744 |
+
* @param int $weight
|
745 |
+
* @param WP_Post $post
|
746 |
+
* @param string $meta_field
|
747 |
+
* @return int
|
748 |
+
*/
|
749 |
+
public function rp4wp_related_meta_fields_weight( $weight, $post, $meta_field ) {
|
750 |
+
if ( 'job_listing' === $post->post_type ) {
|
751 |
+
$weight = 100;
|
752 |
}
|
753 |
+
return $weight;
|
754 |
}
|
755 |
}
|
includes/class-wp-job-manager-shortcodes.php
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
if ( ! defined( 'ABSPATH' ) )
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
|
7 |
/**
|
8 |
* Handles the shortcodes for WP Job Manager.
|
@@ -24,14 +22,14 @@ class WP_Job_Manager_Shortcodes {
|
|
24 |
* The single instance of the class.
|
25 |
*
|
26 |
* @var self
|
27 |
-
* @since 1.26
|
28 |
*/
|
29 |
private static $_instance = null;
|
30 |
|
31 |
/**
|
32 |
* Allows for accessing single instance of class. Class should only be constructed once per call.
|
33 |
*
|
34 |
-
* @since 1.26
|
35 |
* @static
|
36 |
* @return self Main instance.
|
37 |
*/
|
@@ -65,7 +63,7 @@ class WP_Job_Manager_Shortcodes {
|
|
65 |
public function shortcode_action_handler() {
|
66 |
global $post;
|
67 |
|
68 |
-
if ( is_page() && has_shortcode(
|
69 |
$this->job_dashboard_handler();
|
70 |
}
|
71 |
}
|
@@ -82,8 +80,6 @@ class WP_Job_Manager_Shortcodes {
|
|
82 |
|
83 |
/**
|
84 |
* Handles actions on job dashboard.
|
85 |
-
*
|
86 |
-
* @throws Exception On action handling error.
|
87 |
*/
|
88 |
public function job_dashboard_handler() {
|
89 |
if ( ! empty( $_REQUEST['action'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'job_manager_my_job_actions' ) ) {
|
@@ -92,51 +88,47 @@ class WP_Job_Manager_Shortcodes {
|
|
92 |
$job_id = absint( $_REQUEST['job_id'] );
|
93 |
|
94 |
try {
|
95 |
-
// Get Job
|
96 |
-
$job
|
97 |
|
98 |
-
// Check ownership
|
99 |
if ( ! job_manager_user_can_edit_job( $job_id ) ) {
|
100 |
throw new Exception( __( 'Invalid ID', 'wp-job-manager' ) );
|
101 |
}
|
102 |
|
103 |
switch ( $action ) {
|
104 |
-
case 'mark_filled':
|
105 |
-
// Check status
|
106 |
-
if (
|
107 |
throw new Exception( __( 'This position has already been filled', 'wp-job-manager' ) );
|
108 |
-
}
|
109 |
|
110 |
-
// Update
|
111 |
update_post_meta( $job_id, '_filled', 1 );
|
112 |
|
113 |
-
// Message
|
114 |
-
|
115 |
-
$this->job_dashboard_message = '<div class="job-manager-message">' . esc_html( sprintf( __( '%s has been filled', 'wp-job-manager' ), wpjm_get_the_job_title( $job ) ) ) . '</div>';
|
116 |
break;
|
117 |
-
case 'mark_not_filled':
|
118 |
-
// Check status
|
119 |
-
if (
|
120 |
throw new Exception( __( 'This position is not filled', 'wp-job-manager' ) );
|
121 |
}
|
122 |
|
123 |
-
// Update
|
124 |
update_post_meta( $job_id, '_filled', 0 );
|
125 |
|
126 |
-
// Message
|
127 |
-
|
128 |
-
$this->job_dashboard_message = '<div class="job-manager-message">' . esc_html( sprintf( __( '%s has been marked as not filled', 'wp-job-manager' ), wpjm_get_the_job_title( $job ) ) ) . '</div>';
|
129 |
break;
|
130 |
-
case 'delete':
|
131 |
-
// Trash it
|
132 |
wp_trash_post( $job_id );
|
133 |
|
134 |
-
// Message
|
135 |
-
|
136 |
-
$this->job_dashboard_message = '<div class="job-manager-message">' . esc_html( sprintf( __( '%s has been deleted', 'wp-job-manager' ), wpjm_get_the_job_title( $job ) ) ) . '</div>';
|
137 |
|
138 |
break;
|
139 |
-
case 'duplicate':
|
140 |
if ( ! job_manager_get_permalink( 'submit_job_form' ) ) {
|
141 |
throw new Exception( __( 'Missing submission page.', 'wp-job-manager' ) );
|
142 |
}
|
@@ -149,38 +141,25 @@ class WP_Job_Manager_Shortcodes {
|
|
149 |
}
|
150 |
|
151 |
break;
|
152 |
-
case 'relist':
|
153 |
if ( ! job_manager_get_permalink( 'submit_job_form' ) ) {
|
154 |
throw new Exception( __( 'Missing submission page.', 'wp-job-manager' ) );
|
155 |
}
|
156 |
|
157 |
-
// redirect to post page
|
158 |
wp_redirect( add_query_arg( array( 'job_id' => absint( $job_id ) ), job_manager_get_permalink( 'submit_job_form' ) ) );
|
159 |
exit;
|
160 |
-
|
161 |
-
|
|
|
|
|
162 |
break;
|
163 |
}
|
164 |
|
165 |
do_action( 'job_manager_my_job_do_action', $action, $job_id );
|
166 |
|
167 |
-
/**
|
168 |
-
* Set a success message for a custom dashboard action handler.
|
169 |
-
*
|
170 |
-
* When left empty, no success message will be shown.
|
171 |
-
*
|
172 |
-
* @since 1.31.1
|
173 |
-
*
|
174 |
-
* @param string $message Text for the success message. Default: empty string.
|
175 |
-
* @param string $action The name of the custom action.
|
176 |
-
* @param int $job_id The ID for the job that's been altered.
|
177 |
-
*/
|
178 |
-
$success_message = apply_filters( 'job_manager_job_dashboard_success_message', '', $action, $job_id );
|
179 |
-
if ( $success_message ) {
|
180 |
-
$this->job_dashboard_message = '<div class="job-manager-message">' . $success_message . '</div>';
|
181 |
-
}
|
182 |
} catch ( Exception $e ) {
|
183 |
-
$this->job_dashboard_message = '<div class="job-manager-error">' .
|
184 |
}
|
185 |
}
|
186 |
}
|
@@ -198,12 +177,9 @@ class WP_Job_Manager_Shortcodes {
|
|
198 |
return ob_get_clean();
|
199 |
}
|
200 |
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
), $atts
|
205 |
-
);
|
206 |
-
$posts_per_page = $new_atts['posts_per_page'];
|
207 |
|
208 |
wp_enqueue_script( 'wp-job-manager-job-dashboard' );
|
209 |
|
@@ -213,7 +189,7 @@ class WP_Job_Manager_Shortcodes {
|
|
213 |
if ( ! empty( $_REQUEST['action'] ) ) {
|
214 |
$action = sanitize_title( $_REQUEST['action'] );
|
215 |
|
216 |
-
// Show alternative content if a plugin wants to
|
217 |
if ( has_action( 'job_manager_job_dashboard_content_' . $action ) ) {
|
218 |
do_action( 'job_manager_job_dashboard_content_' . $action, $atts );
|
219 |
|
@@ -221,43 +197,30 @@ class WP_Job_Manager_Shortcodes {
|
|
221 |
}
|
222 |
}
|
223 |
|
224 |
-
// ....If not show the job dashboard
|
225 |
-
$args
|
226 |
-
'
|
227 |
-
array(
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
'author' => get_current_user_id(),
|
236 |
-
)
|
237 |
-
);
|
238 |
|
239 |
-
$jobs = new WP_Query
|
240 |
|
241 |
-
echo
|
242 |
|
243 |
-
$job_dashboard_columns = apply_filters(
|
244 |
-
'
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
'expires' => __( 'Listing Expires', 'wp-job-manager' ),
|
250 |
-
)
|
251 |
-
);
|
252 |
|
253 |
-
get_job_manager_template(
|
254 |
-
'job-dashboard.php',
|
255 |
-
array(
|
256 |
-
'jobs' => $jobs->query( $args ),
|
257 |
-
'max_num_pages' => $jobs->max_num_pages,
|
258 |
-
'job_dashboard_columns' => $job_dashboard_columns,
|
259 |
-
)
|
260 |
-
);
|
261 |
|
262 |
return ob_get_clean();
|
263 |
}
|
@@ -268,7 +231,7 @@ class WP_Job_Manager_Shortcodes {
|
|
268 |
public function edit_job() {
|
269 |
global $job_manager;
|
270 |
|
271 |
-
echo $job_manager->forms->get_form( 'edit-job' );
|
272 |
}
|
273 |
|
274 |
/**
|
@@ -280,162 +243,136 @@ class WP_Job_Manager_Shortcodes {
|
|
280 |
public function output_jobs( $atts ) {
|
281 |
ob_start();
|
282 |
|
283 |
-
$atts = shortcode_atts(
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
'keywords' => '',
|
308 |
-
'selected_category' => '',
|
309 |
-
'selected_job_types' => implode( ',', array_values( get_job_listing_types( 'id=>slug' ) ) ),
|
310 |
-
)
|
311 |
-
), $atts
|
312 |
-
);
|
313 |
|
314 |
if ( ! get_option( 'job_manager_enable_categories' ) ) {
|
315 |
-
$
|
316 |
}
|
317 |
|
318 |
-
// String and bool handling
|
319 |
-
$
|
320 |
-
$
|
321 |
-
$
|
322 |
-
$
|
323 |
-
$
|
324 |
|
325 |
-
if ( ! is_null( $
|
326 |
-
$
|
327 |
}
|
328 |
|
329 |
-
if ( ! is_null( $
|
330 |
-
$
|
331 |
}
|
332 |
|
333 |
-
// Array handling
|
334 |
-
$
|
335 |
-
$
|
336 |
-
$
|
337 |
-
$atts['selected_job_types'] = is_array( $atts['selected_job_types'] ) ? $atts['selected_job_types'] : array_filter( array_map( 'trim', explode( ',', $atts['selected_job_types'] ) ) );
|
338 |
|
339 |
-
// Get keywords and location from querystring if set
|
340 |
if ( ! empty( $_GET['search_keywords'] ) ) {
|
341 |
-
$
|
342 |
}
|
343 |
if ( ! empty( $_GET['search_location'] ) ) {
|
344 |
-
$
|
345 |
}
|
346 |
if ( ! empty( $_GET['search_category'] ) ) {
|
347 |
-
$
|
348 |
}
|
349 |
|
350 |
-
$
|
351 |
-
|
352 |
-
'
|
353 |
-
'show_filters' => $atts['show_filters'] ? 'true' : 'false',
|
354 |
-
'show_pagination' => $atts['show_pagination'] ? 'true' : 'false',
|
355 |
-
'per_page' => $atts['per_page'],
|
356 |
-
'orderby' => $atts['orderby'],
|
357 |
-
'order' => $atts['order'],
|
358 |
-
'categories' => implode( ',', $atts['categories'] ),
|
359 |
-
);
|
360 |
-
if ( $atts['show_filters'] ) {
|
361 |
-
|
362 |
-
get_job_manager_template(
|
363 |
-
'job-filters.php',
|
364 |
-
array(
|
365 |
-
'per_page' => $atts['per_page'],
|
366 |
-
'orderby' => $atts['orderby'],
|
367 |
-
'order' => $atts['order'],
|
368 |
-
'show_categories' => $atts['show_categories'],
|
369 |
-
'categories' => $atts['categories'],
|
370 |
-
'selected_category' => $atts['selected_category'],
|
371 |
-
'job_types' => $atts['job_types'],
|
372 |
-
'atts' => $atts,
|
373 |
-
'location' => $atts['location'],
|
374 |
-
'keywords' => $atts['keywords'],
|
375 |
-
'selected_job_types' => $atts['selected_job_types'],
|
376 |
-
'show_category_multiselect' => $atts['show_category_multiselect'],
|
377 |
-
)
|
378 |
-
);
|
379 |
|
380 |
get_job_manager_template( 'job-listings-start.php' );
|
381 |
get_job_manager_template( 'job-listings-end.php' );
|
382 |
|
383 |
-
if ( ! $
|
384 |
-
echo '<a class="load_more_jobs" href="#" style="display:none;"><strong>' .
|
385 |
}
|
|
|
386 |
} else {
|
387 |
-
$jobs = get_job_listings(
|
388 |
-
apply_filters(
|
389 |
-
'job_manager_output_jobs_args',
|
390 |
-
array(
|
391 |
-
'search_location' => $atts['location'],
|
392 |
-
'search_keywords' => $atts['keywords'],
|
393 |
-
'post_status' => $atts['post_status'],
|
394 |
-
'search_categories' => $atts['categories'],
|
395 |
-
'job_types' => $atts['job_types'],
|
396 |
-
'orderby' => $atts['orderby'],
|
397 |
-
'order' => $atts['order'],
|
398 |
-
'posts_per_page' => $atts['per_page'],
|
399 |
-
'featured' => $atts['featured'],
|
400 |
-
'filled' => $atts['filled'],
|
401 |
-
)
|
402 |
-
)
|
403 |
-
);
|
404 |
-
|
405 |
-
if ( ! empty( $atts['job_types'] ) ) {
|
406 |
-
$data_attributes['job_types'] = implode( ',', $atts['job_types'] );
|
407 |
-
}
|
408 |
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
425 |
do_action( 'job_manager_output_jobs_no_results' );
|
426 |
-
|
|
|
427 |
wp_reset_postdata();
|
428 |
}
|
429 |
|
430 |
$data_attributes_string = '';
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
436 |
}
|
437 |
-
if ( !
|
438 |
-
$data_attributes['
|
439 |
}
|
440 |
foreach ( $data_attributes as $key => $value ) {
|
441 |
$data_attributes_string .= 'data-' . esc_attr( $key ) . '="' . esc_attr( $value ) . '" ';
|
@@ -460,7 +397,7 @@ class WP_Job_Manager_Shortcodes {
|
|
460 |
* @return bool
|
461 |
*/
|
462 |
public function string_to_bool( $value ) {
|
463 |
-
return ( is_bool( $value ) && $value ) || in_array( $value, array(
|
464 |
}
|
465 |
|
466 |
/**
|
@@ -469,17 +406,12 @@ class WP_Job_Manager_Shortcodes {
|
|
469 |
* @param array $atts
|
470 |
*/
|
471 |
public function job_filter_job_types( $atts ) {
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
'job_types' => $job_types,
|
479 |
-
'atts' => $atts,
|
480 |
-
'selected_job_types' => $selected_job_types,
|
481 |
-
)
|
482 |
-
);
|
483 |
}
|
484 |
|
485 |
/**
|
@@ -496,13 +428,11 @@ class WP_Job_Manager_Shortcodes {
|
|
496 |
* @return string|null
|
497 |
*/
|
498 |
public function output_job( $atts ) {
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
), $atts
|
503 |
-
);
|
504 |
|
505 |
-
if ( ! $
|
506 |
return;
|
507 |
}
|
508 |
|
@@ -511,18 +441,22 @@ class WP_Job_Manager_Shortcodes {
|
|
511 |
$args = array(
|
512 |
'post_type' => 'job_listing',
|
513 |
'post_status' => 'publish',
|
514 |
-
'p' => $
|
515 |
);
|
516 |
|
517 |
$jobs = new WP_Query( $args );
|
518 |
|
519 |
-
if ( $jobs->have_posts() )
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
|
|
|
|
|
|
|
|
526 |
|
527 |
wp_reset_postdata();
|
528 |
|
@@ -536,50 +470,50 @@ class WP_Job_Manager_Shortcodes {
|
|
536 |
* @return string
|
537 |
*/
|
538 |
public function output_job_summary( $atts ) {
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
), $atts
|
547 |
-
);
|
548 |
|
549 |
ob_start();
|
550 |
|
551 |
$args = array(
|
552 |
'post_type' => 'job_listing',
|
553 |
-
'post_status' => 'publish'
|
554 |
);
|
555 |
|
556 |
-
if ( ! $
|
557 |
-
$args['posts_per_page'] = $
|
558 |
$args['orderby'] = 'rand';
|
559 |
-
if ( ! is_null( $
|
560 |
-
$args['meta_query'] = array(
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
),
|
566 |
-
);
|
567 |
}
|
568 |
} else {
|
569 |
-
$args['p'] = absint( $
|
570 |
}
|
571 |
|
572 |
$jobs = new WP_Query( $args );
|
573 |
|
574 |
-
if ( $jobs->have_posts() )
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
|
|
|
|
|
|
|
|
583 |
|
584 |
wp_reset_postdata();
|
585 |
|
@@ -593,18 +527,15 @@ class WP_Job_Manager_Shortcodes {
|
|
593 |
* @return string
|
594 |
*/
|
595 |
public function output_job_apply( $atts ) {
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
), $atts
|
600 |
-
);
|
601 |
-
$id = $new_atts['id'];
|
602 |
|
603 |
ob_start();
|
604 |
|
605 |
$args = array(
|
606 |
'post_type' => 'job_listing',
|
607 |
-
'post_status' => 'publish'
|
608 |
);
|
609 |
|
610 |
if ( ! $id ) {
|
@@ -615,20 +546,28 @@ class WP_Job_Manager_Shortcodes {
|
|
615 |
|
616 |
$jobs = new WP_Query( $args );
|
617 |
|
618 |
-
if ( $jobs->have_posts() )
|
619 |
-
|
|
|
620 |
$jobs->the_post();
|
621 |
$apply = get_the_job_application_method();
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
632 |
|
633 |
return ob_get_clean();
|
634 |
}
|
1 |
<?php
|
2 |
|
3 |
+
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
4 |
|
5 |
/**
|
6 |
* Handles the shortcodes for WP Job Manager.
|
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 |
*/
|
63 |
public function shortcode_action_handler() {
|
64 |
global $post;
|
65 |
|
66 |
+
if ( is_page() && has_shortcode($post->post_content, 'job_dashboard' ) ) {
|
67 |
$this->job_dashboard_handler();
|
68 |
}
|
69 |
}
|
80 |
|
81 |
/**
|
82 |
* Handles actions on job dashboard.
|
|
|
|
|
83 |
*/
|
84 |
public function job_dashboard_handler() {
|
85 |
if ( ! empty( $_REQUEST['action'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'job_manager_my_job_actions' ) ) {
|
88 |
$job_id = absint( $_REQUEST['job_id'] );
|
89 |
|
90 |
try {
|
91 |
+
// Get Job
|
92 |
+
$job = get_post( $job_id );
|
93 |
|
94 |
+
// Check ownership
|
95 |
if ( ! job_manager_user_can_edit_job( $job_id ) ) {
|
96 |
throw new Exception( __( 'Invalid ID', 'wp-job-manager' ) );
|
97 |
}
|
98 |
|
99 |
switch ( $action ) {
|
100 |
+
case 'mark_filled' :
|
101 |
+
// Check status
|
102 |
+
if ( $job->_filled == 1 )
|
103 |
throw new Exception( __( 'This position has already been filled', 'wp-job-manager' ) );
|
|
|
104 |
|
105 |
+
// Update
|
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
|
113 |
+
if ( $job->_filled != 1 ) {
|
114 |
throw new Exception( __( 'This position is not filled', 'wp-job-manager' ) );
|
115 |
}
|
116 |
|
117 |
+
// Update
|
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' :
|
132 |
if ( ! job_manager_get_permalink( 'submit_job_form' ) ) {
|
133 |
throw new Exception( __( 'Missing submission page.', 'wp-job-manager' ) );
|
134 |
}
|
141 |
}
|
142 |
|
143 |
break;
|
144 |
+
case 'relist' :
|
145 |
if ( ! job_manager_get_permalink( 'submit_job_form' ) ) {
|
146 |
throw new Exception( __( 'Missing submission page.', 'wp-job-manager' ) );
|
147 |
}
|
148 |
|
149 |
+
// redirect to post page
|
150 |
wp_redirect( add_query_arg( array( 'job_id' => absint( $job_id ) ), job_manager_get_permalink( 'submit_job_form' ) ) );
|
151 |
exit;
|
152 |
+
|
153 |
+
break;
|
154 |
+
default :
|
155 |
+
do_action( 'job_manager_job_dashboard_do_action_' . $action );
|
156 |
break;
|
157 |
}
|
158 |
|
159 |
do_action( 'job_manager_my_job_do_action', $action, $job_id );
|
160 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
} catch ( Exception $e ) {
|
162 |
+
$this->job_dashboard_message = '<div class="job-manager-error">' . $e->getMessage() . '</div>';
|
163 |
}
|
164 |
}
|
165 |
}
|
177 |
return ob_get_clean();
|
178 |
}
|
179 |
|
180 |
+
extract( shortcode_atts( array(
|
181 |
+
'posts_per_page' => '25',
|
182 |
+
), $atts ) );
|
|
|
|
|
|
|
183 |
|
184 |
wp_enqueue_script( 'wp-job-manager-job-dashboard' );
|
185 |
|
189 |
if ( ! empty( $_REQUEST['action'] ) ) {
|
190 |
$action = sanitize_title( $_REQUEST['action'] );
|
191 |
|
192 |
+
// Show alternative content if a plugin wants to
|
193 |
if ( has_action( 'job_manager_job_dashboard_content_' . $action ) ) {
|
194 |
do_action( 'job_manager_job_dashboard_content_' . $action, $atts );
|
195 |
|
197 |
}
|
198 |
}
|
199 |
|
200 |
+
// ....If not show the job dashboard
|
201 |
+
$args = apply_filters( 'job_manager_get_dashboard_jobs_args', array(
|
202 |
+
'post_type' => 'job_listing',
|
203 |
+
'post_status' => array( 'publish', 'expired', 'pending' ),
|
204 |
+
'ignore_sticky_posts' => 1,
|
205 |
+
'posts_per_page' => $posts_per_page,
|
206 |
+
'offset' => ( max( 1, get_query_var('paged') ) - 1 ) * $posts_per_page,
|
207 |
+
'orderby' => 'date',
|
208 |
+
'order' => 'desc',
|
209 |
+
'author' => get_current_user_id()
|
210 |
+
) );
|
|
|
|
|
|
|
211 |
|
212 |
+
$jobs = new WP_Query;
|
213 |
|
214 |
+
echo $this->job_dashboard_message;
|
215 |
|
216 |
+
$job_dashboard_columns = apply_filters( 'job_manager_job_dashboard_columns', array(
|
217 |
+
'job_title' => __( 'Title', 'wp-job-manager' ),
|
218 |
+
'filled' => __( 'Filled?', 'wp-job-manager' ),
|
219 |
+
'date' => __( 'Date Posted', 'wp-job-manager' ),
|
220 |
+
'expires' => __( 'Listing Expires', 'wp-job-manager' )
|
221 |
+
) );
|
|
|
|
|
|
|
222 |
|
223 |
+
get_job_manager_template( 'job-dashboard.php', array( 'jobs' => $jobs->query( $args ), 'max_num_pages' => $jobs->max_num_pages, 'job_dashboard_columns' => $job_dashboard_columns ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
|
225 |
return ob_get_clean();
|
226 |
}
|
231 |
public function edit_job() {
|
232 |
global $job_manager;
|
233 |
|
234 |
+
echo $job_manager->forms->get_form( 'edit-job' );
|
235 |
}
|
236 |
|
237 |
/**
|
243 |
public function output_jobs( $atts ) {
|
244 |
ob_start();
|
245 |
|
246 |
+
extract( $atts = shortcode_atts( apply_filters( 'job_manager_output_jobs_defaults', array(
|
247 |
+
'per_page' => get_option( 'job_manager_per_page' ),
|
248 |
+
'orderby' => 'featured',
|
249 |
+
'order' => 'DESC',
|
250 |
+
|
251 |
+
// Filters + cats
|
252 |
+
'show_filters' => true,
|
253 |
+
'show_categories' => true,
|
254 |
+
'show_category_multiselect' => get_option( 'job_manager_enable_default_category_multiselect', false ),
|
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 |
+
|
264 |
+
// Default values for filters
|
265 |
+
'location' => '',
|
266 |
+
'keywords' => '',
|
267 |
+
'selected_category' => '',
|
268 |
+
'selected_job_types' => implode( ',', array_values( get_job_listing_types( 'id=>slug' ) ) ),
|
269 |
+
) ), $atts ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
270 |
|
271 |
if ( ! get_option( 'job_manager_enable_categories' ) ) {
|
272 |
+
$show_categories = false;
|
273 |
}
|
274 |
|
275 |
+
// String and bool handling
|
276 |
+
$show_filters = $this->string_to_bool( $show_filters );
|
277 |
+
$show_categories = $this->string_to_bool( $show_categories );
|
278 |
+
$show_category_multiselect = $this->string_to_bool( $show_category_multiselect );
|
279 |
+
$show_more = $this->string_to_bool( $show_more );
|
280 |
+
$show_pagination = $this->string_to_bool( $show_pagination );
|
281 |
|
282 |
+
if ( ! is_null( $featured ) ) {
|
283 |
+
$featured = ( is_bool( $featured ) && $featured ) || in_array( $featured, array( '1', 'true', 'yes' ) ) ? true : false;
|
284 |
}
|
285 |
|
286 |
+
if ( ! is_null( $filled ) ) {
|
287 |
+
$filled = ( is_bool( $filled ) && $filled ) || in_array( $filled, array( '1', 'true', 'yes' ) ) ? true : false;
|
288 |
}
|
289 |
|
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
|
296 |
if ( ! empty( $_GET['search_keywords'] ) ) {
|
297 |
+
$keywords = sanitize_text_field( $_GET['search_keywords'] );
|
298 |
}
|
299 |
if ( ! empty( $_GET['search_location'] ) ) {
|
300 |
+
$location = sanitize_text_field( $_GET['search_location'] );
|
301 |
}
|
302 |
if ( ! empty( $_GET['search_category'] ) ) {
|
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 ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
309 |
|
310 |
get_job_manager_template( 'job-listings-start.php' );
|
311 |
get_job_manager_template( 'job-listings-end.php' );
|
312 |
|
313 |
+
if ( ! $show_pagination && $show_more ) {
|
314 |
+
echo '<a class="load_more_jobs" href="#" style="display:none;"><strong>' . __( 'Load more listings', 'wp-job-manager' ) . '</strong></a>';
|
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,
|
325 |
+
'order' => $order,
|
326 |
+
'posts_per_page' => $per_page,
|
327 |
+
'featured' => $featured,
|
328 |
+
'filled' => $filled
|
329 |
+
) ) );
|
330 |
+
|
331 |
+
if ( $jobs->have_posts() ) : ?>
|
332 |
+
|
333 |
+
<?php get_job_manager_template( 'job-listings-start.php' ); ?>
|
334 |
+
|
335 |
+
<?php while ( $jobs->have_posts() ) : $jobs->the_post(); ?>
|
336 |
+
<?php get_job_manager_template_part( 'content', 'job_listing' ); ?>
|
337 |
+
<?php endwhile; ?>
|
338 |
+
|
339 |
+
<?php get_job_manager_template( 'job-listings-end.php' ); ?>
|
340 |
+
|
341 |
+
<?php if ( $jobs->found_posts > $per_page && $show_more ) : ?>
|
342 |
+
|
343 |
+
<?php wp_enqueue_script( 'wp-job-manager-ajax-filters' ); ?>
|
344 |
+
|
345 |
+
<?php if ( $show_pagination ) : ?>
|
346 |
+
<?php echo get_job_listing_pagination( $jobs->max_num_pages ); ?>
|
347 |
+
<?php else : ?>
|
348 |
+
<a class="load_more_jobs" href="#"><strong><?php _e( 'Load more listings', 'wp-job-manager' ); ?></strong></a>
|
349 |
+
<?php endif; ?>
|
350 |
+
|
351 |
+
<?php endif; ?>
|
352 |
+
|
353 |
+
<?php else :
|
354 |
do_action( 'job_manager_output_jobs_no_results' );
|
355 |
+
endif;
|
356 |
+
|
357 |
wp_reset_postdata();
|
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 ) . '" ';
|
397 |
* @return bool
|
398 |
*/
|
399 |
public function string_to_bool( $value ) {
|
400 |
+
return ( is_bool( $value ) && $value ) || in_array( $value, array( '1', 'true', 'yes' ) ) ? true : false;
|
401 |
}
|
402 |
|
403 |
/**
|
406 |
* @param array $atts
|
407 |
*/
|
408 |
public function job_filter_job_types( $atts ) {
|
409 |
+
extract( $atts );
|
410 |
+
|
411 |
+
$job_types = array_filter( array_map( 'trim', explode( ',', $job_types ) ) );
|
412 |
+
$selected_job_types = array_filter( array_map( 'trim', explode( ',', $selected_job_types ) ) );
|
413 |
+
|
414 |
+
get_job_manager_template( 'job-filter-job-types.php', array( 'job_types' => $job_types, 'atts' => $atts, 'selected_job_types' => $selected_job_types ) );
|
|
|
|
|
|
|
|
|
|
|
415 |
}
|
416 |
|
417 |
/**
|
428 |
* @return string|null
|
429 |
*/
|
430 |
public function output_job( $atts ) {
|
431 |
+
extract( shortcode_atts( array(
|
432 |
+
'id' => '',
|
433 |
+
), $atts ) );
|
|
|
|
|
434 |
|
435 |
+
if ( ! $id ) {
|
436 |
return;
|
437 |
}
|
438 |
|
441 |
$args = array(
|
442 |
'post_type' => 'job_listing',
|
443 |
'post_status' => 'publish',
|
444 |
+
'p' => $id
|
445 |
);
|
446 |
|
447 |
$jobs = new WP_Query( $args );
|
448 |
|
449 |
+
if ( $jobs->have_posts() ) : ?>
|
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 |
+
|
457 |
+
<?php endwhile; ?>
|
458 |
+
|
459 |
+
<?php endif;
|
460 |
|
461 |
wp_reset_postdata();
|
462 |
|
470 |
* @return string
|
471 |
*/
|
472 |
public function output_job_summary( $atts ) {
|
473 |
+
extract( shortcode_atts( array(
|
474 |
+
'id' => '',
|
475 |
+
'width' => '250px',
|
476 |
+
'align' => 'left',
|
477 |
+
'featured' => null, // True to show only featured, false to hide featured, leave null to show both (when leaving out id)
|
478 |
+
'limit' => 1
|
479 |
+
), $atts ) );
|
|
|
|
|
480 |
|
481 |
ob_start();
|
482 |
|
483 |
$args = array(
|
484 |
'post_type' => 'job_listing',
|
485 |
+
'post_status' => 'publish'
|
486 |
);
|
487 |
|
488 |
+
if ( ! $id ) {
|
489 |
+
$args['posts_per_page'] = $limit;
|
490 |
$args['orderby'] = 'rand';
|
491 |
+
if ( ! is_null( $featured ) ) {
|
492 |
+
$args['meta_query'] = array( array(
|
493 |
+
'key' => '_featured',
|
494 |
+
'value' => '1',
|
495 |
+
'compare' => $featured ? '=' : '!='
|
496 |
+
) );
|
|
|
|
|
497 |
}
|
498 |
} else {
|
499 |
+
$args['p'] = absint( $id );
|
500 |
}
|
501 |
|
502 |
$jobs = new WP_Query( $args );
|
503 |
|
504 |
+
if ( $jobs->have_posts() ) : ?>
|
505 |
+
|
506 |
+
<?php while ( $jobs->have_posts() ) : $jobs->the_post(); ?>
|
507 |
+
|
508 |
+
<div class="job_summary_shortcode align<?php echo $align ?>" style="width: <?php echo $width ? $width : auto; ?>">
|
509 |
+
|
510 |
+
<?php get_job_manager_template_part( 'content-summary', 'job_listing' ); ?>
|
511 |
+
|
512 |
+
</div>
|
513 |
+
|
514 |
+
<?php endwhile; ?>
|
515 |
+
|
516 |
+
<?php endif;
|
517 |
|
518 |
wp_reset_postdata();
|
519 |
|
527 |
* @return string
|
528 |
*/
|
529 |
public function output_job_apply( $atts ) {
|
530 |
+
extract( shortcode_atts( array(
|
531 |
+
'id' => ''
|
532 |
+
), $atts ) );
|
|
|
|
|
|
|
533 |
|
534 |
ob_start();
|
535 |
|
536 |
$args = array(
|
537 |
'post_type' => 'job_listing',
|
538 |
+
'post_status' => 'publish'
|
539 |
);
|
540 |
|
541 |
if ( ! $id ) {
|
546 |
|
547 |
$jobs = new WP_Query( $args );
|
548 |
|
549 |
+
if ( $jobs->have_posts() ) : ?>
|
550 |
+
|
551 |
+
<?php while ( $jobs->have_posts() ) :
|
552 |
$jobs->the_post();
|
553 |
$apply = get_the_job_application_method();
|
554 |
+
?>
|
555 |
+
|
556 |
+
<?php do_action( 'job_manager_before_job_apply_' . absint( $id ) ); ?>
|
557 |
+
|
558 |
+
<?php if ( apply_filters( 'job_manager_show_job_apply_' . absint( $id ), true ) ) : ?>
|
559 |
+
<div class="job-manager-application-wrapper">
|
560 |
+
<?php do_action( 'job_manager_application_details_' . $apply->type, $apply ); ?>
|
561 |
+
</div>
|
562 |
+
<?php endif; ?>
|
563 |
+
|
564 |
+
<?php do_action( 'job_manager_after_job_apply_' . absint( $id ) ); ?>
|
565 |
+
|
566 |
+
<?php endwhile; ?>
|
567 |
+
|
568 |
+
<?php endif;
|
569 |
+
|
570 |
+
wp_reset_postdata();
|
571 |
|
572 |
return ob_get_clean();
|
573 |
}
|
includes/class-wp-job-manager-usage-tracking-data.php
DELETED
@@ -1,315 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Usage tracking data
|
4 |
-
*
|
5 |
-
* @package Usage Tracking
|
6 |
-
**/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Supplies the usage tracking data for logging.
|
14 |
-
*
|
15 |
-
* @package Usage Tracking
|
16 |
-
* @since 1.30.0
|
17 |
-
*/
|
18 |
-
class WP_Job_Manager_Usage_Tracking_Data {
|
19 |
-
/**
|
20 |
-
* Get the usage tracking data to send.
|
21 |
-
*
|
22 |
-
* @since 1.30.0
|
23 |
-
*
|
24 |
-
* @return array Usage data.
|
25 |
-
**/
|
26 |
-
public static function get_usage_data() {
|
27 |
-
$categories = 0;
|
28 |
-
$count_posts = wp_count_posts( 'job_listing' );
|
29 |
-
|
30 |
-
if ( taxonomy_exists( 'job_listing_category' ) ) {
|
31 |
-
$categories = wp_count_terms( 'job_listing_category', array( 'hide_empty' => false ) );
|
32 |
-
}
|
33 |
-
|
34 |
-
return array(
|
35 |
-
'employers' => self::get_employer_count(),
|
36 |
-
'job_categories' => $categories,
|
37 |
-
'job_categories_desc' => self::get_job_category_has_description_count(),
|
38 |
-
'job_types' => wp_count_terms( 'job_listing_type', array( 'hide_empty' => false ) ),
|
39 |
-
'job_types_desc' => self::get_job_type_has_description_count(),
|
40 |
-
'job_types_emp_type' => self::get_job_type_has_employment_type_count(),
|
41 |
-
'jobs_type' => self::get_job_type_count(),
|
42 |
-
'jobs_logo' => self::get_company_logo_count(),
|
43 |
-
'jobs_status_expired' => isset( $count_posts->expired ) ? $count_posts->expired : 0,
|
44 |
-
'jobs_status_pending' => $count_posts->pending,
|
45 |
-
'jobs_status_pending_payment' => isset( $count_posts->pending_payment ) ? $count_posts->pending_payment : 0,
|
46 |
-
'jobs_status_preview' => isset( $count_posts->preview ) ? $count_posts->preview : 0,
|
47 |
-
'jobs_status_publish' => $count_posts->publish,
|
48 |
-
'jobs_location' => self::get_jobs_count_with_meta( '_job_location' ),
|
49 |
-
'jobs_app_contact' => self::get_jobs_count_with_meta( '_application' ),
|
50 |
-
'jobs_company_name' => self::get_jobs_count_with_meta( '_company_name' ),
|
51 |
-
'jobs_company_site' => self::get_jobs_count_with_meta( '_company_website' ),
|
52 |
-
'jobs_company_tagline' => self::get_jobs_count_with_meta( '_company_tagline' ),
|
53 |
-
'jobs_company_twitter' => self::get_jobs_count_with_meta( '_company_twitter' ),
|
54 |
-
'jobs_company_video' => self::get_jobs_count_with_meta( '_company_video' ),
|
55 |
-
'jobs_expiry' => self::get_jobs_count_with_meta( '_job_expires' ),
|
56 |
-
'jobs_featured' => self::get_jobs_count_with_checked_meta( '_featured' ),
|
57 |
-
'jobs_filled' => self::get_jobs_count_with_checked_meta( '_filled' ),
|
58 |
-
'jobs_freelance' => self::get_jobs_by_type_count( 'freelance' ),
|
59 |
-
'jobs_full_time' => self::get_jobs_by_type_count( 'full-time' ),
|
60 |
-
'jobs_intern' => self::get_jobs_by_type_count( 'internship' ),
|
61 |
-
'jobs_part_time' => self::get_jobs_by_type_count( 'part-time' ),
|
62 |
-
'jobs_temp' => self::get_jobs_by_type_count( 'temporary' ),
|
63 |
-
'jobs_by_guests' => self::get_jobs_by_guests(),
|
64 |
-
);
|
65 |
-
}
|
66 |
-
|
67 |
-
/**
|
68 |
-
* Get the total number of users with the "employer" role.
|
69 |
-
*
|
70 |
-
* @return int the number of "employers".
|
71 |
-
*/
|
72 |
-
private static function get_employer_count() {
|
73 |
-
$employer_query = new WP_User_Query(
|
74 |
-
array(
|
75 |
-
'fields' => 'ID',
|
76 |
-
'role' => 'employer',
|
77 |
-
)
|
78 |
-
);
|
79 |
-
|
80 |
-
return $employer_query->total_users;
|
81 |
-
}
|
82 |
-
|
83 |
-
/**
|
84 |
-
* Get the number of job categories that have a description.
|
85 |
-
*
|
86 |
-
* @since 1.30.0
|
87 |
-
*
|
88 |
-
* @return int Number of job categories with a description.
|
89 |
-
**/
|
90 |
-
private static function get_job_category_has_description_count() {
|
91 |
-
if ( ! taxonomy_exists( 'job_listing_category' ) ) {
|
92 |
-
return 0;
|
93 |
-
}
|
94 |
-
|
95 |
-
$count = 0;
|
96 |
-
$terms = get_terms(
|
97 |
-
array(
|
98 |
-
'taxonomy' => 'job_listing_category',
|
99 |
-
'hide_empty' => false,
|
100 |
-
)
|
101 |
-
);
|
102 |
-
|
103 |
-
foreach ( $terms as $term ) {
|
104 |
-
$description = isset( $term->description ) ? trim( $term->description ) : '';
|
105 |
-
|
106 |
-
if ( ! empty( $description ) ) {
|
107 |
-
$count++;
|
108 |
-
}
|
109 |
-
}
|
110 |
-
|
111 |
-
return $count;
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* Get the number of job types that have a description.
|
116 |
-
*
|
117 |
-
* @since 1.30.0
|
118 |
-
*
|
119 |
-
* @return int Number of job types with a description.
|
120 |
-
**/
|
121 |
-
private static function get_job_type_has_description_count() {
|
122 |
-
$count = 0;
|
123 |
-
$terms = get_terms(
|
124 |
-
array(
|
125 |
-
'taxonomy' => 'job_listing_type',
|
126 |
-
'hide_empty' => false,
|
127 |
-
)
|
128 |
-
);
|
129 |
-
|
130 |
-
foreach ( $terms as $term ) {
|
131 |
-
$description = isset( $term->description ) ? trim( $term->description ) : '';
|
132 |
-
|
133 |
-
if ( ! empty( $description ) ) {
|
134 |
-
$count++;
|
135 |
-
}
|
136 |
-
}
|
137 |
-
|
138 |
-
return $count;
|
139 |
-
}
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Get the number of job types that have Employment Type set.
|
143 |
-
*
|
144 |
-
* @since 1.30.0
|
145 |
-
*
|
146 |
-
* @return int Number of job types with an employment type.
|
147 |
-
**/
|
148 |
-
private static function get_job_type_has_employment_type_count() {
|
149 |
-
$count = 0;
|
150 |
-
$terms = get_terms(
|
151 |
-
array(
|
152 |
-
'taxonomy' => 'job_listing_type',
|
153 |
-
'hide_empty' => false,
|
154 |
-
)
|
155 |
-
);
|
156 |
-
|
157 |
-
foreach ( $terms as $term ) {
|
158 |
-
$employment_type = get_term_meta( $term->term_id, 'employment_type', true );
|
159 |
-
|
160 |
-
if ( ! empty( $employment_type ) ) {
|
161 |
-
$count++;
|
162 |
-
}
|
163 |
-
}
|
164 |
-
|
165 |
-
return $count;
|
166 |
-
}
|
167 |
-
|
168 |
-
/**
|
169 |
-
* Get the total number of published or expired jobs for a particular job type.
|
170 |
-
*
|
171 |
-
* @since 1.30.0
|
172 |
-
*
|
173 |
-
* @param string $job_type Job type to search for.
|
174 |
-
*
|
175 |
-
* @return int Number of published or expired jobs for a particular job type.
|
176 |
-
**/
|
177 |
-
private static function get_jobs_by_type_count( $job_type ) {
|
178 |
-
$query = new WP_Query(
|
179 |
-
array(
|
180 |
-
'post_type' => 'job_listing',
|
181 |
-
'post_status' => array( 'expired', 'publish' ),
|
182 |
-
'fields' => 'ids',
|
183 |
-
'tax_query' => array(
|
184 |
-
array(
|
185 |
-
'field' => 'slug',
|
186 |
-
'taxonomy' => 'job_listing_type',
|
187 |
-
'terms' => $job_type,
|
188 |
-
),
|
189 |
-
),
|
190 |
-
)
|
191 |
-
);
|
192 |
-
|
193 |
-
return $query->found_posts;
|
194 |
-
}
|
195 |
-
|
196 |
-
/**
|
197 |
-
* Get the number of job listings that have a company logo.
|
198 |
-
*
|
199 |
-
* @since 1.30.0
|
200 |
-
*
|
201 |
-
* @return int Number of job listings with a company logo.
|
202 |
-
*/
|
203 |
-
private static function get_company_logo_count() {
|
204 |
-
$query = new WP_Query(
|
205 |
-
array(
|
206 |
-
'post_type' => 'job_listing',
|
207 |
-
'post_status' => array( 'expired', 'publish' ),
|
208 |
-
'fields' => 'ids',
|
209 |
-
'meta_query' => array(
|
210 |
-
array(
|
211 |
-
'key' => '_thumbnail_id',
|
212 |
-
'compare' => 'EXISTS',
|
213 |
-
),
|
214 |
-
),
|
215 |
-
)
|
216 |
-
);
|
217 |
-
|
218 |
-
return $query->found_posts;
|
219 |
-
}
|
220 |
-
|
221 |
-
/**
|
222 |
-
* Get the total number of job listings that have one or more job types selected.
|
223 |
-
*
|
224 |
-
* @since 1.30.0
|
225 |
-
*
|
226 |
-
* @return int Number of job listings associated with at least one job type.
|
227 |
-
**/
|
228 |
-
private static function get_job_type_count() {
|
229 |
-
$query = new WP_Query(
|
230 |
-
array(
|
231 |
-
'post_type' => 'job_listing',
|
232 |
-
'post_status' => array( 'expired', 'publish' ),
|
233 |
-
'fields' => 'ids',
|
234 |
-
'tax_query' => array(
|
235 |
-
array(
|
236 |
-
'taxonomy' => 'job_listing_type',
|
237 |
-
'operator' => 'EXISTS',
|
238 |
-
),
|
239 |
-
),
|
240 |
-
)
|
241 |
-
);
|
242 |
-
|
243 |
-
return $query->found_posts;
|
244 |
-
}
|
245 |
-
|
246 |
-
/**
|
247 |
-
* Get the number of job listings where the given meta value is non-empty.
|
248 |
-
*
|
249 |
-
* @param string $meta_key the key for the meta value to check.
|
250 |
-
*
|
251 |
-
* @return int the number of job listings.
|
252 |
-
*/
|
253 |
-
private static function get_jobs_count_with_meta( $meta_key ) {
|
254 |
-
$query = new WP_Query(
|
255 |
-
array(
|
256 |
-
'post_type' => 'job_listing',
|
257 |
-
'post_status' => array( 'publish', 'expired' ),
|
258 |
-
'fields' => 'ids',
|
259 |
-
'meta_query' => array(
|
260 |
-
array(
|
261 |
-
'key' => $meta_key,
|
262 |
-
'value' => '[^[:space:]]',
|
263 |
-
'compare' => 'REGEXP',
|
264 |
-
),
|
265 |
-
),
|
266 |
-
)
|
267 |
-
);
|
268 |
-
|
269 |
-
return $query->found_posts;
|
270 |
-
}
|
271 |
-
|
272 |
-
/**
|
273 |
-
* Get the number of job listings where the given checkbox meta value is
|
274 |
-
* checked.
|
275 |
-
*
|
276 |
-
* @param string $meta_key the key for the meta value to check.
|
277 |
-
*
|
278 |
-
* @return int the number of job listings.
|
279 |
-
*/
|
280 |
-
private static function get_jobs_count_with_checked_meta( $meta_key ) {
|
281 |
-
$query = new WP_Query(
|
282 |
-
array(
|
283 |
-
'post_type' => 'job_listing',
|
284 |
-
'post_status' => array( 'publish', 'expired' ),
|
285 |
-
'fields' => 'ids',
|
286 |
-
'meta_query' => array(
|
287 |
-
array(
|
288 |
-
'key' => $meta_key,
|
289 |
-
'value' => '1',
|
290 |
-
),
|
291 |
-
),
|
292 |
-
)
|
293 |
-
);
|
294 |
-
|
295 |
-
return $query->found_posts;
|
296 |
-
}
|
297 |
-
|
298 |
-
/**
|
299 |
-
* Get the number of job listings posted by guests.
|
300 |
-
*
|
301 |
-
* @return int the number of job listings.
|
302 |
-
*/
|
303 |
-
private static function get_jobs_by_guests() {
|
304 |
-
$query = new WP_Query(
|
305 |
-
array(
|
306 |
-
'post_type' => 'job_listing',
|
307 |
-
'post_status' => array( 'publish', 'expired' ),
|
308 |
-
'fields' => 'ids',
|
309 |
-
'author__in' => array( 0 ),
|
310 |
-
)
|
311 |
-
);
|
312 |
-
|
313 |
-
return $query->found_posts;
|
314 |
-
}
|
315 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-wp-job-manager-usage-tracking.php
DELETED
@@ -1,219 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit;
|
5 |
-
}
|
6 |
-
|
7 |
-
require dirname( __FILE__ ) . '/../lib/usage-tracking/class-usage-tracking-base.php';
|
8 |
-
|
9 |
-
/**
|
10 |
-
* WPJM Usage Tracking subclass.
|
11 |
-
*/
|
12 |
-
class WP_Job_Manager_Usage_Tracking extends WP_Job_Manager_Usage_Tracking_Base {
|
13 |
-
|
14 |
-
const WPJM_SETTING_NAME = 'job_manager_usage_tracking_enabled';
|
15 |
-
|
16 |
-
const WPJM_TRACKING_INFO_URL = 'https://wpjobmanager.com/document/what-data-does-wpjm-track';
|
17 |
-
|
18 |
-
/**
|
19 |
-
* WP_Job_Manager_Usage_Tracking constructor.
|
20 |
-
*/
|
21 |
-
protected function __construct() {
|
22 |
-
parent::__construct();
|
23 |
-
|
24 |
-
// Add filter for settings.
|
25 |
-
add_filter( 'job_manager_settings', array( $this, 'add_setting_field' ) );
|
26 |
-
|
27 |
-
// In the setup wizard, do not display the normal opt-in dialog.
|
28 |
-
if ( isset( $_GET['page'] ) && 'job-manager-setup' === $_GET['page'] ) {
|
29 |
-
remove_action( 'admin_notices', array( $this, 'maybe_display_tracking_opt_in' ) );
|
30 |
-
}
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Implementation for abstract functions.
|
35 |
-
*/
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Return the instance of this class.
|
39 |
-
*
|
40 |
-
* @return object
|
41 |
-
*/
|
42 |
-
public static function get_instance() {
|
43 |
-
return self::get_instance_for_subclass( get_class() );
|
44 |
-
}
|
45 |
-
|
46 |
-
/**
|
47 |
-
* Get prefix for the usage data setting.
|
48 |
-
*
|
49 |
-
* @return string
|
50 |
-
*/
|
51 |
-
protected function get_prefix() {
|
52 |
-
return 'job_manager';
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Get prefix for the event sent for usage tracking.
|
57 |
-
*
|
58 |
-
* @return string
|
59 |
-
*/
|
60 |
-
protected function get_event_prefix() {
|
61 |
-
return 'wpjm';
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Get the text domain used in the plugin.
|
66 |
-
*
|
67 |
-
* @return string
|
68 |
-
*/
|
69 |
-
protected function get_text_domain() {
|
70 |
-
return 'wp-job-manager';
|
71 |
-
}
|
72 |
-
|
73 |
-
/**
|
74 |
-
* Get the status of usage tracking.
|
75 |
-
*
|
76 |
-
* @return bool
|
77 |
-
*/
|
78 |
-
public function get_tracking_enabled() {
|
79 |
-
return get_option( self::WPJM_SETTING_NAME ) || false;
|
80 |
-
}
|
81 |
-
|
82 |
-
/**
|
83 |
-
* Set whether or not usage tracking is enabled.
|
84 |
-
*
|
85 |
-
* @param bool $enable
|
86 |
-
*/
|
87 |
-
public function set_tracking_enabled( $enable ) {
|
88 |
-
update_option( self::WPJM_SETTING_NAME, $enable );
|
89 |
-
}
|
90 |
-
|
91 |
-
/**
|
92 |
-
* Check if the current user can manage usage tracking settings.
|
93 |
-
*
|
94 |
-
* @return bool
|
95 |
-
*/
|
96 |
-
protected function current_user_can_manage_tracking() {
|
97 |
-
return current_user_can( 'manage_options' );
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* Get the text to show in the opt-in dialog.
|
102 |
-
*
|
103 |
-
* @return string
|
104 |
-
*/
|
105 |
-
protected function opt_in_dialog_text() {
|
106 |
-
return sprintf(
|
107 |
-
// translators: Placeholder %s is a URL to the document on wpjobmanager.com with info on usage tracking.
|
108 |
-
__(
|
109 |
-
'We\'d love if you helped us make WP Job Manager better by allowing us to collect
|
110 |
-
<a href="%s" target="_blank">usage tracking data</a>. No sensitive information is
|
111 |
-
collected, and you can opt out at any time.',
|
112 |
-
'wp-job-manager'
|
113 |
-
), self::WPJM_TRACKING_INFO_URL
|
114 |
-
);
|
115 |
-
}
|
116 |
-
|
117 |
-
/**
|
118 |
-
* Check if we should track the status of a plugin.
|
119 |
-
*
|
120 |
-
* @param string $plugin_slug
|
121 |
-
* @return bool
|
122 |
-
*/
|
123 |
-
protected function do_track_plugin( $plugin_slug ) {
|
124 |
-
if ( 1 === preg_match( '/^wp-job-manager/', $plugin_slug ) ) {
|
125 |
-
return true;
|
126 |
-
}
|
127 |
-
$third_party_plugins = array(
|
128 |
-
'all-in-one-seo-pack',
|
129 |
-
'polylang',
|
130 |
-
'jetpack',
|
131 |
-
'wordpress-seo', // Yoast.
|
132 |
-
'sitepress-multilingual-cms', // WPML.
|
133 |
-
'bibblio-related-posts', // Related Posts for WordPress.
|
134 |
-
);
|
135 |
-
if ( in_array( $plugin_slug, $third_party_plugins, true ) ) {
|
136 |
-
return true;
|
137 |
-
}
|
138 |
-
return false;
|
139 |
-
}
|
140 |
-
|
141 |
-
|
142 |
-
/*
|
143 |
-
* Public functions.
|
144 |
-
*/
|
145 |
-
|
146 |
-
/**
|
147 |
-
* Hide the opt-in for enabling usage tracking.
|
148 |
-
**/
|
149 |
-
public function hide_tracking_opt_in() { // phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod
|
150 |
-
parent::hide_tracking_opt_in();
|
151 |
-
}
|
152 |
-
|
153 |
-
/**
|
154 |
-
* Allowed html tags, used by wp_kses, for the translated opt-in dialog
|
155 |
-
* text.
|
156 |
-
*
|
157 |
-
* @return array the html tags.
|
158 |
-
**/
|
159 |
-
public function opt_in_dialog_text_allowed_html() { // phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod
|
160 |
-
return parent::opt_in_dialog_text_allowed_html();
|
161 |
-
}
|
162 |
-
|
163 |
-
/**
|
164 |
-
* Get the opt-in text.
|
165 |
-
*
|
166 |
-
* @return string
|
167 |
-
*/
|
168 |
-
public function opt_in_checkbox_text() {
|
169 |
-
return sprintf(
|
170 |
-
|
171 |
-
/*
|
172 |
-
* translators: the href tag contains the URL for the page
|
173 |
-
* telling users what data WPJM tracks.
|
174 |
-
*/
|
175 |
-
__(
|
176 |
-
'Help us make WP Job Manager better by allowing us to collect
|
177 |
-
<a href="%s" target="_blank">usage tracking data</a>.
|
178 |
-
No sensitive information is collected.', 'wp-job-manager'
|
179 |
-
), self::WPJM_TRACKING_INFO_URL
|
180 |
-
);
|
181 |
-
}
|
182 |
-
|
183 |
-
|
184 |
-
/**
|
185 |
-
* Hooks.
|
186 |
-
*/
|
187 |
-
|
188 |
-
/**
|
189 |
-
* Add tracking setting field to general settings.
|
190 |
-
*
|
191 |
-
* @param array $fields
|
192 |
-
* @return array
|
193 |
-
*/
|
194 |
-
public function add_setting_field( $fields ) {
|
195 |
-
$fields['general'][1][] = array(
|
196 |
-
'name' => self::WPJM_SETTING_NAME,
|
197 |
-
'std' => '0',
|
198 |
-
'type' => 'checkbox',
|
199 |
-
'desc' => '',
|
200 |
-
'label' => __( 'Enable Usage Tracking', 'wp-job-manager' ),
|
201 |
-
'cb_label' => $this->opt_in_checkbox_text(),
|
202 |
-
);
|
203 |
-
|
204 |
-
return $fields;
|
205 |
-
}
|
206 |
-
|
207 |
-
|
208 |
-
/**
|
209 |
-
* Helpers.
|
210 |
-
*/
|
211 |
-
|
212 |
-
/**
|
213 |
-
* Clear options used for usage tracking.
|
214 |
-
*/
|
215 |
-
public function clear_options() {
|
216 |
-
delete_option( self::WPJM_SETTING_NAME );
|
217 |
-
delete_option( $this->hide_tracking_opt_in_option_name );
|
218 |
-
}
|
219 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-wp-job-manager-widget.php
CHANGED
@@ -83,7 +83,7 @@ class WP_Job_Manager_Widget extends WP_Widget {
|
|
83 |
}
|
84 |
|
85 |
if ( isset( $cache[ $args['widget_id'] ] ) ) {
|
86 |
-
echo $cache[ $args['widget_id'] ];
|
87 |
return true;
|
88 |
}
|
89 |
|
@@ -151,61 +151,24 @@ class WP_Job_Manager_Widget extends WP_Widget {
|
|
151 |
$value = isset( $instance[ $key ] ) ? $instance[ $key ] : $setting['std'];
|
152 |
|
153 |
switch ( $setting['type'] ) {
|
154 |
-
case 'text':
|
155 |
?>
|
156 |
<p>
|
157 |
-
<label for="<?php echo
|
158 |
-
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" name="<?php echo
|
159 |
</p>
|
160 |
<?php
|
161 |
-
|
162 |
-
case 'number':
|
163 |
?>
|
164 |
<p>
|
165 |
-
<label for="<?php echo
|
166 |
-
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" name="<?php echo
|
167 |
</p>
|
168 |
<?php
|
169 |
-
|
170 |
-
case 'select':
|
171 |
-
?>
|
172 |
-
<p>
|
173 |
-
<label for="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>"><?php echo esc_html( $setting['label'] ); ?></label>
|
174 |
-
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( $key ) ); ?>">
|
175 |
-
<?php foreach ( $setting['options'] as $option_key => $option_label ) : ?>
|
176 |
-
<option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( $value, $option_key ); ?>><?php echo esc_html( $option_label ); ?></option>
|
177 |
-
<?php endforeach; ?></select>
|
178 |
-
</p>
|
179 |
-
<?php
|
180 |
-
break;
|
181 |
-
case 'checkbox':
|
182 |
-
?>
|
183 |
-
<p>
|
184 |
-
<label for="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>"><?php echo esc_html( $setting['label'] ); ?></label>
|
185 |
-
<input class="checkbox" id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( $key ) ); ?>" type="checkbox" value="1" <?php checked( $value, 1 ); ?> />
|
186 |
-
</p>
|
187 |
-
<?php
|
188 |
-
break;
|
189 |
-
}
|
190 |
-
}
|
191 |
-
}
|
192 |
-
|
193 |
-
/**
|
194 |
-
* Gets the instance with the default values for all settings.
|
195 |
-
*
|
196 |
-
* @return array
|
197 |
-
*/
|
198 |
-
protected function get_default_instance() {
|
199 |
-
$defaults = array();
|
200 |
-
if ( ! empty( $this->settings ) ) {
|
201 |
-
foreach ( $this->settings as $key => $setting ) {
|
202 |
-
$defaults[ $key ] = null;
|
203 |
-
if ( isset( $setting['std'] ) ) {
|
204 |
-
$defaults[ $key ] = $setting['std'];
|
205 |
-
}
|
206 |
}
|
207 |
}
|
208 |
-
return $defaults;
|
209 |
}
|
210 |
|
211 |
/**
|
83 |
}
|
84 |
|
85 |
if ( isset( $cache[ $args['widget_id'] ] ) ) {
|
86 |
+
echo $cache[ $args['widget_id'] ];
|
87 |
return true;
|
88 |
}
|
89 |
|
151 |
$value = isset( $instance[ $key ] ) ? $instance[ $key ] : $setting['std'];
|
152 |
|
153 |
switch ( $setting['type'] ) {
|
154 |
+
case 'text' :
|
155 |
?>
|
156 |
<p>
|
157 |
+
<label for="<?php echo $this->get_field_id( $key ); ?>"><?php echo $setting['label']; ?></label>
|
158 |
+
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" name="<?php echo $this->get_field_name( $key ); ?>" type="text" value="<?php echo esc_attr( $value ); ?>" />
|
159 |
</p>
|
160 |
<?php
|
161 |
+
break;
|
162 |
+
case 'number' :
|
163 |
?>
|
164 |
<p>
|
165 |
+
<label for="<?php echo $this->get_field_id( $key ); ?>"><?php echo $setting['label']; ?></label>
|
166 |
+
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>" name="<?php echo $this->get_field_name( $key ); ?>" type="number" step="<?php echo esc_attr( $setting['step'] ); ?>" min="<?php echo esc_attr( $setting['min'] ); ?>" max="<?php echo esc_attr( $setting['max'] ); ?>" value="<?php echo esc_attr( $value ); ?>" />
|
167 |
</p>
|
168 |
<?php
|
169 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
}
|
171 |
}
|
|
|
172 |
}
|
173 |
|
174 |
/**
|
includes/emails/class-wp-job-manager-email-admin-expiring-job.php
DELETED
@@ -1,52 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Email notification to the site administrator when a job is expiring.
|
9 |
-
*
|
10 |
-
* @package wp-job-manager
|
11 |
-
* @since 1.31.0
|
12 |
-
* @extends WP_Job_Manager_Email
|
13 |
-
*/
|
14 |
-
class WP_Job_Manager_Email_Admin_Expiring_Job extends WP_Job_Manager_Email_Employer_Expiring_Job {
|
15 |
-
/**
|
16 |
-
* Get the unique email notification key.
|
17 |
-
*
|
18 |
-
* @return string
|
19 |
-
*/
|
20 |
-
public static function get_key() {
|
21 |
-
return 'admin_expiring_job';
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Get the friendly name for this email notification.
|
26 |
-
*
|
27 |
-
* @return string
|
28 |
-
*/
|
29 |
-
public static function get_name() {
|
30 |
-
return __( 'Admin Notice of Expiring Job Listings', 'wp-job-manager' );
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Get the description for this email notification.
|
35 |
-
*
|
36 |
-
* @type abstract
|
37 |
-
* @return string
|
38 |
-
*/
|
39 |
-
public static function get_description() {
|
40 |
-
return __( 'Send notices to the site administrator before a job listing expires.', 'wp-job-manager' );
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Get array or comma-separated list of email addresses to send message.
|
45 |
-
*
|
46 |
-
* @return string|array
|
47 |
-
*/
|
48 |
-
public function get_to() {
|
49 |
-
return get_option( 'admin_email', false );
|
50 |
-
}
|
51 |
-
|
52 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/emails/class-wp-job-manager-email-admin-new-job.php
DELETED
@@ -1,91 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Email notification to administrator when a new job is submitted.
|
9 |
-
*
|
10 |
-
* @package wp-job-manager
|
11 |
-
* @since 1.31.0
|
12 |
-
* @extends WP_Job_Manager_Email
|
13 |
-
*/
|
14 |
-
class WP_Job_Manager_Email_Admin_New_Job extends WP_Job_Manager_Email_Template {
|
15 |
-
/**
|
16 |
-
* Get the unique email notification key.
|
17 |
-
*
|
18 |
-
* @return string
|
19 |
-
*/
|
20 |
-
public static function get_key() {
|
21 |
-
return 'admin_new_job';
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Get the friendly name for this email notification.
|
26 |
-
*
|
27 |
-
* @return string
|
28 |
-
*/
|
29 |
-
public static function get_name() {
|
30 |
-
return __( 'Admin Notice of New Listing', 'wp-job-manager' );
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Get the description for this email notification.
|
35 |
-
*
|
36 |
-
* @type abstract
|
37 |
-
* @return string
|
38 |
-
*/
|
39 |
-
public static function get_description() {
|
40 |
-
return __( 'Send a notice to the site administrator when a new job is submitted on the frontend.', 'wp-job-manager' );
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Get the email subject.
|
45 |
-
*
|
46 |
-
* @return string
|
47 |
-
*/
|
48 |
-
public function get_subject() {
|
49 |
-
$args = $this->get_args();
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Job listing post object.
|
53 |
-
*
|
54 |
-
* @var WP_Post $job
|
55 |
-
*/
|
56 |
-
$job = $args['job'];
|
57 |
-
|
58 |
-
// translators: Placeholder %s is the job listing post title.
|
59 |
-
return sprintf( __( 'New Job Listing Submitted: %s', 'wp-job-manager' ), $job->post_title );
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Get `From:` address header value. Can be simple email or formatted `Firstname Lastname <email@example.com>`.
|
64 |
-
*
|
65 |
-
* @return string|bool Email from value or false to use WordPress' default.
|
66 |
-
*/
|
67 |
-
public function get_from() {
|
68 |
-
return false;
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* Get array or comma-separated list of email addresses to send message.
|
73 |
-
*
|
74 |
-
* @return string|array
|
75 |
-
*/
|
76 |
-
public function get_to() {
|
77 |
-
return get_option( 'admin_email', false );
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
* Checks the arguments and returns whether the email notification is properly set up.
|
82 |
-
*
|
83 |
-
* @return bool
|
84 |
-
*/
|
85 |
-
public function is_valid() {
|
86 |
-
$args = $this->get_args();
|
87 |
-
return isset( $args['job'] )
|
88 |
-
&& $args['job'] instanceof WP_Post
|
89 |
-
&& $this->get_to();
|
90 |
-
}
|
91 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/emails/class-wp-job-manager-email-admin-updated-job.php
DELETED
@@ -1,91 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Email notification to administrator when a job is updated.
|
9 |
-
*
|
10 |
-
* @package wp-job-manager
|
11 |
-
* @since 1.31.0
|
12 |
-
* @extends WP_Job_Manager_Email
|
13 |
-
*/
|
14 |
-
class WP_Job_Manager_Email_Admin_Updated_Job extends WP_Job_Manager_Email_Template {
|
15 |
-
/**
|
16 |
-
* Get the unique email notification key.
|
17 |
-
*
|
18 |
-
* @return string
|
19 |
-
*/
|
20 |
-
public static function get_key() {
|
21 |
-
return 'admin_updated_job';
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Get the friendly name for this email notification.
|
26 |
-
*
|
27 |
-
* @return string
|
28 |
-
*/
|
29 |
-
public static function get_name() {
|
30 |
-
return __( 'Admin Notice of Updated Listing', 'wp-job-manager' );
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Get the description for this email notification.
|
35 |
-
*
|
36 |
-
* @type abstract
|
37 |
-
* @return string
|
38 |
-
*/
|
39 |
-
public static function get_description() {
|
40 |
-
return __( 'Send a notice to the site administrator when a job is updated on the frontend.', 'wp-job-manager' );
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Get the email subject.
|
45 |
-
*
|
46 |
-
* @return string
|
47 |
-
*/
|
48 |
-
public function get_subject() {
|
49 |
-
$args = $this->get_args();
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Job listing post object.
|
53 |
-
*
|
54 |
-
* @var WP_Post $job
|
55 |
-
*/
|
56 |
-
$job = $args['job'];
|
57 |
-
|
58 |
-
// translators: Placeholder %s is the job listing post title.
|
59 |
-
return sprintf( __( 'Job Listing Updated: %s', 'wp-job-manager' ), $job->post_title );
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Get `From:` address header value. Can be simple email or formatted `Firstname Lastname <email@example.com>`.
|
64 |
-
*
|
65 |
-
* @return string|bool Email from value or false to use WordPress' default.
|
66 |
-
*/
|
67 |
-
public function get_from() {
|
68 |
-
return false;
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* Get array or comma-separated list of email addresses to send message.
|
73 |
-
*
|
74 |
-
* @return string|array
|
75 |
-
*/
|
76 |
-
public function get_to() {
|
77 |
-
return get_option( 'admin_email', false );
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
* Checks the arguments and returns whether the email notification is properly set up.
|
82 |
-
*
|
83 |
-
* @return bool
|
84 |
-
*/
|
85 |
-
public function is_valid() {
|
86 |
-
$args = $this->get_args();
|
87 |
-
return isset( $args['job'] )
|
88 |
-
&& $args['job'] instanceof WP_Post
|
89 |
-
&& $this->get_to();
|
90 |
-
}
|
91 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/emails/class-wp-job-manager-email-employer-expiring-job.php
DELETED
@@ -1,159 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Email notification to employers when a job is expiring.
|
9 |
-
*
|
10 |
-
* @package wp-job-manager
|
11 |
-
* @since 1.31.0
|
12 |
-
* @extends WP_Job_Manager_Email
|
13 |
-
*/
|
14 |
-
class WP_Job_Manager_Email_Employer_Expiring_Job extends WP_Job_Manager_Email_Template {
|
15 |
-
const SETTING_NOTICE_PERIOD_NAME = 'notice_period_days';
|
16 |
-
const SETTING_NOTICE_PERIOD_DEFAULT = '1';
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Get the unique email notification key.
|
20 |
-
*
|
21 |
-
* @return string
|
22 |
-
*/
|
23 |
-
public static function get_key() {
|
24 |
-
return 'employer_expiring_job';
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Get the friendly name for this email notification.
|
29 |
-
*
|
30 |
-
* @return string
|
31 |
-
*/
|
32 |
-
public static function get_name() {
|
33 |
-
return __( 'Employer Notice of Expiring Job Listings', 'wp-job-manager' );
|
34 |
-
}
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Get the description for this email notification.
|
38 |
-
*
|
39 |
-
* @type abstract
|
40 |
-
* @return string
|
41 |
-
*/
|
42 |
-
public static function get_description() {
|
43 |
-
return __( 'Send notices to employers before a job listing expires.', 'wp-job-manager' );
|
44 |
-
}
|
45 |
-
|
46 |
-
/**
|
47 |
-
* Get the notice period in days from the notification settings.
|
48 |
-
*
|
49 |
-
* @param array $settings
|
50 |
-
* @return int
|
51 |
-
*/
|
52 |
-
public static function get_notice_period( $settings ) {
|
53 |
-
if ( isset( $settings[ self::SETTING_NOTICE_PERIOD_NAME ] ) ) {
|
54 |
-
return absint( $settings[ self::SETTING_NOTICE_PERIOD_NAME ] );
|
55 |
-
}
|
56 |
-
return absint( self::SETTING_NOTICE_PERIOD_DEFAULT );
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Get the email subject.
|
61 |
-
*
|
62 |
-
* @return string
|
63 |
-
*/
|
64 |
-
public function get_subject() {
|
65 |
-
$args = $this->get_args();
|
66 |
-
|
67 |
-
/**
|
68 |
-
* Job listing post object.
|
69 |
-
*
|
70 |
-
* @var WP_Post $job
|
71 |
-
*/
|
72 |
-
$job = $args['job'];
|
73 |
-
|
74 |
-
// translators: Placeholder %s is the job listing post title.
|
75 |
-
return sprintf( __( 'Job Listing Expiring: %s', 'wp-job-manager' ), $job->post_title );
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Get `From:` address header value. Can be simple email or formatted `Firstname Lastname <email@example.com>`.
|
80 |
-
*
|
81 |
-
* @return string|bool Email from value or false to use WordPress' default.
|
82 |
-
*/
|
83 |
-
public function get_from() {
|
84 |
-
return false;
|
85 |
-
}
|
86 |
-
|
87 |
-
/**
|
88 |
-
* Get array or comma-separated list of email addresses to send message.
|
89 |
-
*
|
90 |
-
* @return string|array
|
91 |
-
*/
|
92 |
-
public function get_to() {
|
93 |
-
$args = $this->get_args();
|
94 |
-
return $args['author']->user_email;
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Expand arguments as necessary for the generation of the email.
|
99 |
-
*
|
100 |
-
* @param array $args
|
101 |
-
* @return mixed
|
102 |
-
*/
|
103 |
-
protected function prepare_args( $args ) {
|
104 |
-
$args = parent::prepare_args( $args );
|
105 |
-
|
106 |
-
if ( isset( $args['job'] ) ) {
|
107 |
-
$args['expiring_today'] = false;
|
108 |
-
$today = date( 'Y-m-d', current_time( 'timestamp' ) );
|
109 |
-
$expiring_date = date( 'Y-m-d', strtotime( $args['job']->_job_expires ) );
|
110 |
-
if ( ! empty( $args['job']->_job_expires ) && $today === $expiring_date ) {
|
111 |
-
$args['expiring_today'] = true;
|
112 |
-
}
|
113 |
-
}
|
114 |
-
|
115 |
-
return $args;
|
116 |
-
}
|
117 |
-
|
118 |
-
/**
|
119 |
-
* Get the settings for this email notifications.
|
120 |
-
*
|
121 |
-
* @return array
|
122 |
-
*/
|
123 |
-
public static function get_setting_fields() {
|
124 |
-
$fields = parent::get_setting_fields();
|
125 |
-
$fields[] = array(
|
126 |
-
'name' => self::SETTING_NOTICE_PERIOD_NAME,
|
127 |
-
'std' => self::SETTING_NOTICE_PERIOD_DEFAULT,
|
128 |
-
'label' => __( 'Notice Period', 'wp-job-manager' ),
|
129 |
-
'type' => 'number',
|
130 |
-
'after' => ' ' . __( 'days', 'wp-job-manager' ),
|
131 |
-
'attributes' => array( 'min' => 0 ),
|
132 |
-
);
|
133 |
-
return $fields;
|
134 |
-
}
|
135 |
-
|
136 |
-
/**
|
137 |
-
* Is this email notification enabled by default?
|
138 |
-
*
|
139 |
-
* @return bool
|
140 |
-
*/
|
141 |
-
public static function is_default_enabled() {
|
142 |
-
return false;
|
143 |
-
}
|
144 |
-
|
145 |
-
/**
|
146 |
-
* Checks the arguments and returns whether the email notification is properly set up.
|
147 |
-
*
|
148 |
-
* @return bool
|
149 |
-
*/
|
150 |
-
public function is_valid() {
|
151 |
-
$args = $this->get_args();
|
152 |
-
return isset( $args['job'] )
|
153 |
-
&& $args['job'] instanceof WP_Post
|
154 |
-
&& isset( $args['author'] )
|
155 |
-
&& $args['author'] instanceof WP_User
|
156 |
-
&& ! empty( $args['author']->user_email );
|
157 |
-
}
|
158 |
-
|
159 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/forms/class-wp-job-manager-form-edit-job.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
|
5 |
/**
|
6 |
* Handles the editing of Job Listings from the public facing frontend (from within `[job_dashboard]` shortcode).
|
@@ -18,20 +18,6 @@ class WP_Job_Manager_Form_Edit_Job extends WP_Job_Manager_Form_Submit_Job {
|
|
18 |
*/
|
19 |
public $form_name = 'edit-job';
|
20 |
|
21 |
-
/**
|
22 |
-
* Messaged shown on save.
|
23 |
-
*
|
24 |
-
* @var bool|string
|
25 |
-
*/
|
26 |
-
private $save_message = false;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Message shown on error.
|
30 |
-
*
|
31 |
-
* @var bool|string
|
32 |
-
*/
|
33 |
-
private $save_error = false;
|
34 |
-
|
35 |
/**
|
36 |
* Instance
|
37 |
*
|
@@ -54,36 +40,20 @@ class WP_Job_Manager_Form_Edit_Job extends WP_Job_Manager_Form_Submit_Job {
|
|
54 |
* Constructor
|
55 |
*/
|
56 |
public function __construct() {
|
57 |
-
|
58 |
-
$this->job_id = ! empty( $_REQUEST['job_id'] ) ? absint( $_REQUEST['job_id'] ) : 0;
|
59 |
|
60 |
-
if
|
61 |
$this->job_id = 0;
|
62 |
}
|
63 |
-
|
64 |
-
if ( ! empty( $this->job_id ) ) {
|
65 |
-
$post_status = get_post_status( $this->job_id );
|
66 |
-
if (
|
67 |
-
( 'publish' === $post_status && ! wpjm_user_can_edit_published_submissions() )
|
68 |
-
|| ( 'publish' !== $post_status && ! job_manager_user_can_edit_pending_submissions() )
|
69 |
-
) {
|
70 |
-
$this->job_id = 0;
|
71 |
-
}
|
72 |
-
}
|
73 |
}
|
74 |
|
75 |
/**
|
76 |
-
*
|
77 |
*
|
78 |
* @param array $atts
|
79 |
*/
|
80 |
public function output( $atts = array() ) {
|
81 |
-
|
82 |
-
echo '<div class="job-manager-message">' . wp_kses_post( $this->save_message ) . '</div>';
|
83 |
-
}
|
84 |
-
if ( ! empty( $this->save_error ) ) {
|
85 |
-
echo '<div class="job-manager-error">' . wp_kses_post( $this->save_error ) . '</div>';
|
86 |
-
}
|
87 |
$this->submit();
|
88 |
}
|
89 |
|
@@ -93,8 +63,8 @@ class WP_Job_Manager_Form_Edit_Job extends WP_Job_Manager_Form_Submit_Job {
|
|
93 |
public function submit() {
|
94 |
$job = get_post( $this->job_id );
|
95 |
|
96 |
-
if ( empty( $this->job_id ) ) {
|
97 |
-
echo
|
98 |
return;
|
99 |
}
|
100 |
|
@@ -124,34 +94,21 @@ class WP_Job_Manager_Form_Edit_Job extends WP_Job_Manager_Form_Submit_Job {
|
|
124 |
|
125 |
$this->fields = apply_filters( 'submit_job_form_fields_get_job_data', $this->fields, $job );
|
126 |
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
'job-submit.php',
|
139 |
-
array(
|
140 |
-
'form' => $this->form_name,
|
141 |
-
'job_id' => $this->get_job_id(),
|
142 |
-
'action' => $this->get_action(),
|
143 |
-
'job_fields' => $this->get_fields( 'job' ),
|
144 |
-
'company_fields' => $this->get_fields( 'company' ),
|
145 |
-
'step' => $this->get_step(),
|
146 |
-
'submit_button_text' => $save_button_text,
|
147 |
-
)
|
148 |
-
);
|
149 |
}
|
150 |
|
151 |
/**
|
152 |
-
* Submit Step is posted
|
153 |
-
*
|
154 |
-
* @throws Exception When invalid fields are submitted.
|
155 |
*/
|
156 |
public function submit_handler() {
|
157 |
if ( empty( $_POST['submit_job'] ) ) {
|
@@ -160,73 +117,31 @@ class WP_Job_Manager_Form_Edit_Job extends WP_Job_Manager_Form_Submit_Job {
|
|
160 |
|
161 |
try {
|
162 |
|
163 |
-
// Get posted values
|
164 |
$values = $this->get_posted_fields();
|
165 |
|
166 |
-
// Validate required
|
167 |
-
$
|
168 |
-
|
169 |
-
throw new Exception( $validation_result->get_error_message() );
|
170 |
}
|
171 |
|
172 |
-
|
173 |
-
|
174 |
-
$save_post_status = 'pending';
|
175 |
-
}
|
176 |
-
$original_post_status = get_post_status( $this->job_id );
|
177 |
-
|
178 |
-
// Update the job.
|
179 |
-
$this->save_job( $values['job']['job_title'], $values['job']['job_description'], $save_post_status, $values, false );
|
180 |
$this->update_job_data( $values );
|
181 |
|
182 |
-
// Successful
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
} elseif ( 'publish' === $original_post_status && 'pending' === $post_status ) {
|
191 |
-
$save_message = __( 'Your changes have been submitted and your listing will be visible again once approved.', 'wp-job-manager' );
|
192 |
-
|
193 |
-
/**
|
194 |
-
* Resets the job expiration date when a user submits their job listing edit for approval.
|
195 |
-
* Defaults to `false`.
|
196 |
-
*
|
197 |
-
* @since 1.29.0
|
198 |
-
*
|
199 |
-
* @param bool $reset_expiration If true, reset expiration date.
|
200 |
-
*/
|
201 |
-
if ( apply_filters( 'job_manager_reset_listing_expiration_on_user_edit', false ) ) {
|
202 |
-
delete_post_meta( $this->job_id, '_job_expires' );
|
203 |
-
}
|
204 |
}
|
205 |
|
206 |
-
/**
|
207 |
-
* Fire action after the user edits a job listing.
|
208 |
-
*
|
209 |
-
* @since 1.30.0
|
210 |
-
*
|
211 |
-
* @param int $job_id Job ID.
|
212 |
-
* @param string $save_message Save message to filter.
|
213 |
-
* @param array $values Submitted values for job listing.
|
214 |
-
*/
|
215 |
-
do_action( 'job_manager_user_edit_job_listing', $this->job_id, $save_message, $values );
|
216 |
-
|
217 |
-
/**
|
218 |
-
* Change the message that appears when a user edits a job listing.
|
219 |
-
*
|
220 |
-
* @since 1.29.0
|
221 |
-
*
|
222 |
-
* @param string $save_message Save message to filter.
|
223 |
-
* @param int $job_id Job ID.
|
224 |
-
* @param array $values Submitted values for job listing.
|
225 |
-
*/
|
226 |
-
$this->save_message = apply_filters( 'job_manager_update_job_listings_message', $save_message, $this->job_id, $values );
|
227 |
-
|
228 |
} catch ( Exception $e ) {
|
229 |
-
|
|
|
230 |
}
|
231 |
}
|
232 |
}
|
1 |
<?php
|
2 |
|
3 |
+
include_once( 'class-wp-job-manager-form-submit-job.php' );
|
4 |
|
5 |
/**
|
6 |
* Handles the editing of Job Listings from the public facing frontend (from within `[job_dashboard]` shortcode).
|
18 |
*/
|
19 |
public $form_name = 'edit-job';
|
20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
/**
|
22 |
* Instance
|
23 |
*
|
40 |
* Constructor
|
41 |
*/
|
42 |
public function __construct() {
|
43 |
+
$this->job_id = ! empty( $_REQUEST['job_id'] ) ? absint( $_REQUEST[ 'job_id' ] ) : 0;
|
|
|
44 |
|
45 |
+
if ( ! job_manager_user_can_edit_job( $this->job_id ) ) {
|
46 |
$this->job_id = 0;
|
47 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
}
|
49 |
|
50 |
/**
|
51 |
+
* output function.
|
52 |
*
|
53 |
* @param array $atts
|
54 |
*/
|
55 |
public function output( $atts = array() ) {
|
56 |
+
$this->submit_handler();
|
|
|
|
|
|
|
|
|
|
|
57 |
$this->submit();
|
58 |
}
|
59 |
|
63 |
public function submit() {
|
64 |
$job = get_post( $this->job_id );
|
65 |
|
66 |
+
if ( empty( $this->job_id ) || ( $job->post_status !== 'publish' && ! job_manager_user_can_edit_pending_submissions() ) ) {
|
67 |
+
echo wpautop( __( 'Invalid listing', 'wp-job-manager' ) );
|
68 |
return;
|
69 |
}
|
70 |
|
94 |
|
95 |
$this->fields = apply_filters( 'submit_job_form_fields_get_job_data', $this->fields, $job );
|
96 |
|
97 |
+
wp_enqueue_script( 'wp-job-manager-job-submission' );
|
98 |
+
|
99 |
+
get_job_manager_template( 'job-submit.php', array(
|
100 |
+
'form' => $this->form_name,
|
101 |
+
'job_id' => $this->get_job_id(),
|
102 |
+
'action' => $this->get_action(),
|
103 |
+
'job_fields' => $this->get_fields( 'job' ),
|
104 |
+
'company_fields' => $this->get_fields( 'company' ),
|
105 |
+
'step' => $this->get_step(),
|
106 |
+
'submit_button_text' => __( 'Save changes', 'wp-job-manager' )
|
107 |
+
) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
}
|
109 |
|
110 |
/**
|
111 |
+
* Submit Step is posted
|
|
|
|
|
112 |
*/
|
113 |
public function submit_handler() {
|
114 |
if ( empty( $_POST['submit_job'] ) ) {
|
117 |
|
118 |
try {
|
119 |
|
120 |
+
// Get posted values
|
121 |
$values = $this->get_posted_fields();
|
122 |
|
123 |
+
// Validate required
|
124 |
+
if ( is_wp_error( ( $return = $this->validate_fields( $values ) ) ) ) {
|
125 |
+
throw new Exception( $return->get_error_message() );
|
|
|
126 |
}
|
127 |
|
128 |
+
// Update the job
|
129 |
+
$this->save_job( $values['job']['job_title'], $values['job']['job_description'], '', $values, false );
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
$this->update_job_data( $values );
|
131 |
|
132 |
+
// Successful
|
133 |
+
switch ( get_post_status( $this->job_id ) ) {
|
134 |
+
case 'publish' :
|
135 |
+
echo '<div class="job-manager-message">' . __( 'Your changes have been saved.', 'wp-job-manager' ) . ' <a href="' . get_permalink( $this->job_id ) . '">' . __( 'View →', 'wp-job-manager' ) . '</a>' . '</div>';
|
136 |
+
break;
|
137 |
+
default :
|
138 |
+
echo '<div class="job-manager-message">' . __( 'Your changes have been saved.', 'wp-job-manager' ) . '</div>';
|
139 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
}
|
141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
} catch ( Exception $e ) {
|
143 |
+
echo '<div class="job-manager-error">' . $e->getMessage() . '</div>';
|
144 |
+
return;
|
145 |
}
|
146 |
}
|
147 |
}
|
includes/forms/class-wp-job-manager-form-submit-job.php
CHANGED
@@ -57,44 +57,37 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
57 |
*/
|
58 |
public function __construct() {
|
59 |
add_action( 'wp', array( $this, 'process' ) );
|
60 |
-
if ( $this->use_recaptcha_field() ) {
|
61 |
-
add_action( 'submit_job_form_end', array( $this, 'display_recaptcha_field' ) );
|
62 |
-
add_action( 'submit_job_form_validate_fields', array( $this, 'validate_recaptcha_field' ) );
|
63 |
-
}
|
64 |
|
65 |
-
$this->steps
|
66 |
-
'
|
67 |
-
|
68 |
-
'
|
69 |
-
|
70 |
-
|
71 |
-
'handler' => array( $this, 'submit_handler' ),
|
72 |
-
'priority' => 10,
|
73 |
-
),
|
74 |
-
'preview' => array(
|
75 |
-
'name' => __( 'Preview', 'wp-job-manager' ),
|
76 |
-
'view' => array( $this, 'preview' ),
|
77 |
-
'handler' => array( $this, 'preview_handler' ),
|
78 |
-
'priority' => 20,
|
79 |
-
),
|
80 |
-
'done' => array(
|
81 |
-
'name' => __( 'Done', 'wp-job-manager' ),
|
82 |
-
'view' => array( $this, 'done' ),
|
83 |
-
'priority' => 30,
|
84 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
)
|
86 |
-
);
|
87 |
|
88 |
uasort( $this->steps, array( $this, 'sort_by_priority' ) );
|
89 |
|
90 |
-
// Get step/job
|
91 |
if ( isset( $_POST['step'] ) ) {
|
92 |
-
$this->step = is_numeric( $_POST['step'] ) ? max( absint( $_POST['step'] ), 0 ) : array_search(
|
93 |
} elseif ( ! empty( $_GET['step'] ) ) {
|
94 |
-
$this->step = is_numeric( $_GET['step'] ) ? max( absint( $_GET['step'] ), 0 ) : array_search(
|
95 |
}
|
96 |
|
97 |
-
$this->job_id = ! empty( $_REQUEST['job_id'] ) ? absint( $_REQUEST['job_id'] ) : 0;
|
98 |
|
99 |
if ( ! job_manager_user_can_edit_job( $this->job_id ) ) {
|
100 |
$this->job_id = 0;
|
@@ -102,17 +95,17 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
102 |
|
103 |
// Allow resuming from cookie.
|
104 |
$this->resume_edit = false;
|
105 |
-
if ( ! isset( $_GET['new'] ) && ( 'before' === get_option( 'job_manager_paid_listings_flow' ) || ! $this->job_id ) && ! empty( $_COOKIE['wp-job-manager-submitting-job-id'] ) && ! empty( $_COOKIE['wp-job-manager-submitting-job-key'] ) ) {
|
106 |
$job_id = absint( $_COOKIE['wp-job-manager-submitting-job-id'] );
|
107 |
$job_status = get_post_status( $job_id );
|
108 |
|
109 |
if ( ( 'preview' === $job_status || 'pending_payment' === $job_status ) && get_post_meta( $job_id, '_submitting_key', true ) === $_COOKIE['wp-job-manager-submitting-job-key'] ) {
|
110 |
-
$this->job_id
|
111 |
$this->resume_edit = get_post_meta( $job_id, '_submitting_key', true );
|
112 |
}
|
113 |
}
|
114 |
|
115 |
-
// Load job details
|
116 |
if ( $this->job_id ) {
|
117 |
$job_status = get_post_status( $this->job_id );
|
118 |
if ( 'expired' === $job_status ) {
|
@@ -120,7 +113,7 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
120 |
$this->job_id = 0;
|
121 |
$this->step = 0;
|
122 |
}
|
123 |
-
} elseif ( ! in_array( $job_status, apply_filters( 'job_manager_valid_submit_job_statuses', array( 'preview' ) )
|
124 |
$this->job_id = 0;
|
125 |
$this->step = 0;
|
126 |
}
|
@@ -146,21 +139,18 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
146 |
|
147 |
$allowed_application_method = get_option( 'job_manager_allowed_application_method', '' );
|
148 |
switch ( $allowed_application_method ) {
|
149 |
-
case 'email':
|
150 |
$application_method_label = __( 'Application email', 'wp-job-manager' );
|
151 |
$application_method_placeholder = __( 'you@yourdomain.com', 'wp-job-manager' );
|
152 |
-
|
153 |
-
|
154 |
-
case 'url':
|
155 |
$application_method_label = __( 'Application URL', 'wp-job-manager' );
|
156 |
$application_method_placeholder = __( 'http://', 'wp-job-manager' );
|
157 |
-
|
158 |
-
|
159 |
-
default:
|
160 |
$application_method_label = __( 'Application email/URL', 'wp-job-manager' );
|
161 |
$application_method_placeholder = __( 'Enter an email address or website URL', 'wp-job-manager' );
|
162 |
-
|
163 |
-
break;
|
164 |
}
|
165 |
|
166 |
if ( job_manager_multi_job_type() ) {
|
@@ -168,151 +158,133 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
168 |
} else {
|
169 |
$job_type = 'term-select';
|
170 |
}
|
171 |
-
$this->fields = apply_filters(
|
172 |
-
'
|
173 |
-
|
174 |
-
|
175 |
-
'
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
),
|
182 |
-
'
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
),
|
190 |
-
'
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
),
|
199 |
-
'
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
'default' => '',
|
206 |
-
'taxonomy' => 'job_listing_category',
|
207 |
-
),
|
208 |
-
'job_description' => array(
|
209 |
-
'label' => __( 'Description', 'wp-job-manager' ),
|
210 |
-
'type' => 'wp-editor',
|
211 |
-
'required' => true,
|
212 |
-
'priority' => 5,
|
213 |
-
),
|
214 |
-
'application' => array(
|
215 |
-
'label' => $application_method_label,
|
216 |
-
'type' => 'text',
|
217 |
-
'sanitizer' => $application_method_sanitizer,
|
218 |
-
'required' => true,
|
219 |
-
'placeholder' => $application_method_placeholder,
|
220 |
-
'priority' => 6,
|
221 |
-
),
|
222 |
),
|
223 |
-
'
|
224 |
-
'
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
'priority' => 1,
|
230 |
-
),
|
231 |
-
'company_website' => array(
|
232 |
-
'label' => __( 'Website', 'wp-job-manager' ),
|
233 |
-
'type' => 'text',
|
234 |
-
'sanitizer' => 'url',
|
235 |
-
'required' => false,
|
236 |
-
'placeholder' => __( 'http://', 'wp-job-manager' ),
|
237 |
-
'priority' => 2,
|
238 |
-
),
|
239 |
-
'company_tagline' => array(
|
240 |
-
'label' => __( 'Tagline', 'wp-job-manager' ),
|
241 |
-
'type' => 'text',
|
242 |
-
'required' => false,
|
243 |
-
'placeholder' => __( 'Briefly describe your company', 'wp-job-manager' ),
|
244 |
-
'maxlength' => 64,
|
245 |
-
'priority' => 3,
|
246 |
-
),
|
247 |
-
'company_video' => array(
|
248 |
-
'label' => __( 'Video', 'wp-job-manager' ),
|
249 |
-
'type' => 'text',
|
250 |
-
'sanitizer' => 'url',
|
251 |
-
'required' => false,
|
252 |
-
'placeholder' => __( 'A link to a video about your company', 'wp-job-manager' ),
|
253 |
-
'priority' => 4,
|
254 |
-
),
|
255 |
-
'company_twitter' => array(
|
256 |
-
'label' => __( 'Twitter username', 'wp-job-manager' ),
|
257 |
-
'type' => 'text',
|
258 |
-
'required' => false,
|
259 |
-
'placeholder' => __( '@yourcompany', 'wp-job-manager' ),
|
260 |
-
'priority' => 5,
|
261 |
-
),
|
262 |
-
'company_logo' => array(
|
263 |
-
'label' => __( 'Logo', 'wp-job-manager' ),
|
264 |
-
'type' => 'file',
|
265 |
-
'required' => false,
|
266 |
-
'placeholder' => '',
|
267 |
-
'priority' => 6,
|
268 |
-
'ajax' => true,
|
269 |
-
'multiple' => false,
|
270 |
-
'allowed_mime_types' => array(
|
271 |
-
'jpg' => 'image/jpeg',
|
272 |
-
'jpeg' => 'image/jpeg',
|
273 |
-
'gif' => 'image/gif',
|
274 |
-
'png' => 'image/png',
|
275 |
-
),
|
276 |
-
),
|
277 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
)
|
279 |
-
);
|
280 |
|
281 |
-
if ( ! get_option( 'job_manager_enable_categories' ) ||
|
282 |
unset( $this->fields['job']['job_category'] );
|
283 |
}
|
284 |
-
if ( ! get_option( 'job_manager_enable_types' ) ||
|
285 |
unset( $this->fields['job']['job_type'] );
|
286 |
}
|
287 |
}
|
288 |
|
289 |
-
/**
|
290 |
-
* Use reCAPTCHA field on the form?
|
291 |
-
*
|
292 |
-
* @return bool
|
293 |
-
*/
|
294 |
-
public function use_recaptcha_field() {
|
295 |
-
if ( ! $this->is_recaptcha_available() ) {
|
296 |
-
return false;
|
297 |
-
}
|
298 |
-
return 1 === absint( get_option( 'job_manager_enable_recaptcha_job_submission' ) );
|
299 |
-
}
|
300 |
-
|
301 |
/**
|
302 |
* Validates the posted fields.
|
303 |
*
|
304 |
* @param array $values
|
305 |
-
* @
|
306 |
-
* @
|
307 |
*/
|
308 |
protected function validate_fields( $values ) {
|
309 |
foreach ( $this->fields as $group_key => $group_fields ) {
|
310 |
foreach ( $group_fields as $key => $field ) {
|
311 |
if ( $field['required'] && empty( $values[ $group_key ][ $key ] ) ) {
|
312 |
-
// translators: Placeholder %s is the label for the required field.
|
313 |
return new WP_Error( 'validation-error', sprintf( __( '%s is a required field', 'wp-job-manager' ), $field['label'] ) );
|
314 |
}
|
315 |
-
if ( ! empty( $field['taxonomy'] ) && in_array( $field['type'], array( 'term-checklist', 'term-select', 'term-multiselect' )
|
316 |
if ( is_array( $values[ $group_key ][ $key ] ) ) {
|
317 |
$check_value = $values[ $group_key ][ $key ];
|
318 |
} else {
|
@@ -320,11 +292,28 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
320 |
}
|
321 |
foreach ( $check_value as $term ) {
|
322 |
if ( ! term_exists( $term, $field['taxonomy'] ) ) {
|
323 |
-
// translators: Placeholder %s is the field label that is did not validate.
|
324 |
return new WP_Error( 'validation-error', sprintf( __( '%s is invalid', 'wp-job-manager' ), $field['label'] ) );
|
325 |
}
|
326 |
}
|
327 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
328 |
if ( 'file' === $field['type'] && ! empty( $field['allowed_mime_types'] ) ) {
|
329 |
if ( is_array( $values[ $group_key ][ $key ] ) ) {
|
330 |
$check_value = array_filter( $values[ $group_key ][ $key ] );
|
@@ -336,9 +325,8 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
336 |
$file_url = current( explode( '?', $file_url ) );
|
337 |
$file_info = wp_check_filetype( $file_url );
|
338 |
|
339 |
-
if ( ! is_numeric( $file_url ) && $file_info && ! in_array( $file_info['type'], $field['allowed_mime_types']
|
340 |
-
|
341 |
-
throw new Exception( sprintf( __( '"%1$s" (filetype %2$s) needs to be one of the following file types: %3$s', 'wp-job-manager' ), $field['label'], $file_info['ext'], implode( ', ', array_keys( $field['allowed_mime_types'] ) ) ) );
|
342 |
}
|
343 |
}
|
344 |
}
|
@@ -346,28 +334,28 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
346 |
}
|
347 |
}
|
348 |
|
349 |
-
// Application method
|
350 |
if ( isset( $values['job']['application'] ) && ! empty( $values['job']['application'] ) ) {
|
351 |
-
$allowed_application_method
|
352 |
$values['job']['application'] = str_replace( ' ', '+', $values['job']['application'] );
|
353 |
switch ( $allowed_application_method ) {
|
354 |
-
case 'email':
|
355 |
if ( ! is_email( $values['job']['application'] ) ) {
|
356 |
throw new Exception( __( 'Please enter a valid application email address', 'wp-job-manager' ) );
|
357 |
}
|
358 |
-
|
359 |
-
case 'url':
|
360 |
-
// Prefix http if needed
|
361 |
if ( ! strstr( $values['job']['application'], 'http:' ) && ! strstr( $values['job']['application'], 'https:' ) ) {
|
362 |
$values['job']['application'] = 'http://' . $values['job']['application'];
|
363 |
}
|
364 |
if ( ! filter_var( $values['job']['application'], FILTER_VALIDATE_URL ) ) {
|
365 |
throw new Exception( __( 'Please enter a valid application URL', 'wp-job-manager' ) );
|
366 |
}
|
367 |
-
|
368 |
-
default:
|
369 |
if ( ! is_email( $values['job']['application'] ) ) {
|
370 |
-
// Prefix http if needed
|
371 |
if ( ! strstr( $values['job']['application'], 'http:' ) && ! strstr( $values['job']['application'], 'https:' ) ) {
|
372 |
$values['job']['application'] = 'http://' . $values['job']['application'];
|
373 |
}
|
@@ -375,47 +363,13 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
375 |
throw new Exception( __( 'Please enter a valid application email address or URL', 'wp-job-manager' ) );
|
376 |
}
|
377 |
}
|
378 |
-
|
379 |
}
|
380 |
}
|
381 |
|
382 |
return apply_filters( 'submit_job_form_validate_fields', true, $this->fields, $values );
|
383 |
}
|
384 |
|
385 |
-
/**
|
386 |
-
* Enqueues scripts and styles for editing and posting a job listing.
|
387 |
-
*/
|
388 |
-
protected function enqueue_job_form_assets() {
|
389 |
-
wp_enqueue_script( 'wp-job-manager-job-submission' );
|
390 |
-
wp_enqueue_style( 'wp-job-manager-job-submission', JOB_MANAGER_PLUGIN_URL . '/assets/css/job-submission.css', array(), JOB_MANAGER_VERSION );
|
391 |
-
|
392 |
-
// Register datepicker JS. It will be enqueued if needed when a date.
|
393 |
-
// field is rendered.
|
394 |
-
wp_register_script( 'wp-job-manager-datepicker', JOB_MANAGER_PLUGIN_URL . '/assets/js/datepicker.min.js', array( 'jquery', 'jquery-ui-datepicker' ), JOB_MANAGER_VERSION, true );
|
395 |
-
|
396 |
-
// Localize scripts after the fields are rendered.
|
397 |
-
add_action( 'submit_job_form_end', array( $this, 'localize_job_form_scripts' ) );
|
398 |
-
}
|
399 |
-
|
400 |
-
/**
|
401 |
-
* Localize frontend scripts that have been enqueued. This should be called
|
402 |
-
* after the fields are rendered, in case some of them enqueue new scripts.
|
403 |
-
*/
|
404 |
-
public function localize_job_form_scripts() {
|
405 |
-
if ( function_exists( 'wp_localize_jquery_ui_datepicker' ) ) {
|
406 |
-
wp_localize_jquery_ui_datepicker();
|
407 |
-
} else {
|
408 |
-
wp_localize_script(
|
409 |
-
'wp-job-manager-datepicker',
|
410 |
-
'job_manager_datepicker',
|
411 |
-
array(
|
412 |
-
/* translators: jQuery date format, see http://api.jqueryui.com/datepicker/#utility-formatDate */
|
413 |
-
'date_format' => _x( 'yy-mm-dd', 'Date format for jQuery datepicker.', 'wp-job-manager' ),
|
414 |
-
)
|
415 |
-
);
|
416 |
-
}
|
417 |
-
}
|
418 |
-
|
419 |
/**
|
420 |
* Returns an array of the job types indexed by slug. (Unused)
|
421 |
*
|
@@ -436,40 +390,37 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
436 |
public function submit() {
|
437 |
$this->init_fields();
|
438 |
|
439 |
-
// Load data if neccessary
|
440 |
if ( $this->job_id ) {
|
441 |
$job = get_post( $this->job_id );
|
442 |
foreach ( $this->fields as $group_key => $group_fields ) {
|
443 |
foreach ( $group_fields as $key => $field ) {
|
444 |
switch ( $key ) {
|
445 |
-
case 'job_title':
|
446 |
$this->fields[ $group_key ][ $key ]['value'] = $job->post_title;
|
447 |
-
|
448 |
-
case 'job_description':
|
449 |
$this->fields[ $group_key ][ $key ]['value'] = $job->post_content;
|
450 |
-
|
451 |
-
case 'job_type':
|
452 |
-
$this->fields[ $group_key ][ $key ]['value'] = wp_get_object_terms( $job->ID, 'job_listing_type', array( 'fields' => 'ids' ) );
|
453 |
-
|
454 |
-
|
455 |
-
}
|
456 |
-
break;
|
457 |
-
case 'job_category':
|
458 |
$this->fields[ $group_key ][ $key ]['value'] = wp_get_object_terms( $job->ID, 'job_listing_category', array( 'fields' => 'ids' ) );
|
459 |
-
|
460 |
-
case 'company_logo':
|
461 |
$this->fields[ $group_key ][ $key ]['value'] = has_post_thumbnail( $job->ID ) ? get_post_thumbnail_id( $job->ID ) : get_post_meta( $job->ID, '_' . $key, true );
|
462 |
-
|
463 |
default:
|
464 |
$this->fields[ $group_key ][ $key ]['value'] = get_post_meta( $job->ID, '_' . $key, true );
|
465 |
-
|
466 |
}
|
467 |
}
|
468 |
}
|
469 |
|
470 |
$this->fields = apply_filters( 'submit_job_form_fields_get_job_data', $this->fields, $job );
|
471 |
|
472 |
-
|
473 |
} elseif ( is_user_logged_in() && empty( $_POST['submit_job'] ) ) {
|
474 |
if ( ! empty( $this->fields['company'] ) ) {
|
475 |
foreach ( $this->fields['company'] as $key => $field ) {
|
@@ -478,54 +429,49 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
478 |
}
|
479 |
if ( ! empty( $this->fields['job']['application'] ) ) {
|
480 |
$allowed_application_method = get_option( 'job_manager_allowed_application_method', '' );
|
481 |
-
if ( 'url'
|
482 |
-
$current_user
|
483 |
$this->fields['job']['application']['value'] = $current_user->user_email;
|
484 |
}
|
485 |
}
|
486 |
$this->fields = apply_filters( 'submit_job_form_fields_get_user_data', $this->fields, get_current_user_id() );
|
487 |
}
|
488 |
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
)
|
502 |
-
);
|
503 |
}
|
504 |
|
505 |
/**
|
506 |
* Handles the submission of form data.
|
507 |
-
*
|
508 |
-
* @throws Exception On validation error.
|
509 |
*/
|
510 |
public function submit_handler() {
|
511 |
try {
|
512 |
-
// Init fields
|
513 |
$this->init_fields();
|
514 |
|
515 |
-
// Get posted values
|
516 |
$values = $this->get_posted_fields();
|
517 |
|
518 |
if ( empty( $_POST['submit_job'] ) ) {
|
519 |
return;
|
520 |
}
|
521 |
|
522 |
-
// Validate required
|
523 |
-
$
|
524 |
-
|
525 |
-
throw new Exception( $validation_status->get_error_message() );
|
526 |
}
|
527 |
|
528 |
-
// Account creation
|
529 |
if ( ! is_user_logged_in() ) {
|
530 |
$create_account = false;
|
531 |
|
@@ -534,40 +480,16 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
534 |
if ( ! job_manager_generate_username_from_email() && empty( $_POST['create_account_username'] ) ) {
|
535 |
throw new Exception( __( 'Please enter a username.', 'wp-job-manager' ) );
|
536 |
}
|
537 |
-
if ( ! wpjm_use_standard_password_setup_email() ) {
|
538 |
-
if ( empty( $_POST['create_account_password'] ) ) {
|
539 |
-
throw new Exception( __( 'Please enter a password.', 'wp-job-manager' ) );
|
540 |
-
}
|
541 |
-
}
|
542 |
if ( empty( $_POST['create_account_email'] ) ) {
|
543 |
throw new Exception( __( 'Please enter your email address.', 'wp-job-manager' ) );
|
544 |
}
|
545 |
}
|
546 |
-
|
547 |
-
if ( ! wpjm_use_standard_password_setup_email() && ! empty( $_POST['create_account_password'] ) ) {
|
548 |
-
if ( empty( $_POST['create_account_password_verify'] ) || $_POST['create_account_password_verify'] !== $_POST['create_account_password'] ) {
|
549 |
-
throw new Exception( __( 'Passwords must match.', 'wp-job-manager' ) );
|
550 |
-
}
|
551 |
-
if ( ! wpjm_validate_new_password( $_POST['create_account_password'] ) ) {
|
552 |
-
$password_hint = wpjm_get_password_rules_hint();
|
553 |
-
if ( $password_hint ) {
|
554 |
-
// translators: Placeholder %s is the password hint.
|
555 |
-
throw new Exception( sprintf( __( 'Invalid Password: %s', 'wp-job-manager' ), $password_hint ) );
|
556 |
-
} else {
|
557 |
-
throw new Exception( __( 'Password is not valid.', 'wp-job-manager' ) );
|
558 |
-
}
|
559 |
-
}
|
560 |
-
}
|
561 |
-
|
562 |
if ( ! empty( $_POST['create_account_email'] ) ) {
|
563 |
-
$create_account = wp_job_manager_create_account(
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
'role' => get_option( 'job_manager_registration_role' ),
|
569 |
-
)
|
570 |
-
);
|
571 |
}
|
572 |
}
|
573 |
|
@@ -580,11 +502,11 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
580 |
throw new Exception( __( 'You must be signed in to post a new listing.', 'wp-job-manager' ) );
|
581 |
}
|
582 |
|
583 |
-
// Update the job
|
584 |
$this->save_job( $values['job']['job_title'], $values['job']['job_description'], $this->job_id ? '' : 'preview', $values );
|
585 |
$this->update_job_data( $values );
|
586 |
|
587 |
-
// Successful, show next step
|
588 |
$this->step ++;
|
589 |
|
590 |
} catch ( Exception $e ) {
|
@@ -607,37 +529,25 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
607 |
'post_title' => $post_title,
|
608 |
'post_content' => $post_content,
|
609 |
'post_type' => 'job_listing',
|
610 |
-
'comment_status' => 'closed'
|
611 |
);
|
612 |
|
613 |
if ( $update_slug ) {
|
614 |
-
$job_slug
|
615 |
|
616 |
-
// Prepend with company name
|
617 |
if ( apply_filters( 'submit_job_form_prefix_post_name_with_company', true ) && ! empty( $values['company']['company_name'] ) ) {
|
618 |
$job_slug[] = $values['company']['company_name'];
|
619 |
}
|
620 |
|
621 |
-
// Prepend location
|
622 |
if ( apply_filters( 'submit_job_form_prefix_post_name_with_location', true ) && ! empty( $values['job']['job_location'] ) ) {
|
623 |
$job_slug[] = $values['job']['job_location'];
|
624 |
}
|
625 |
|
626 |
-
// Prepend with job type
|
627 |
if ( apply_filters( 'submit_job_form_prefix_post_name_with_job_type', true ) && ! empty( $values['job']['job_type'] ) ) {
|
628 |
-
|
629 |
-
$job_slug[] = $values['job']['job_type'];
|
630 |
-
} else {
|
631 |
-
$terms = $values['job']['job_type'];
|
632 |
-
|
633 |
-
foreach ( $terms as $term ) {
|
634 |
-
$term = get_term_by( 'id', intval( $term ), 'job_listing_type' );
|
635 |
-
|
636 |
-
if ( $term ) {
|
637 |
-
$job_slug[] = $term->slug;
|
638 |
-
}
|
639 |
-
}
|
640 |
-
}
|
641 |
}
|
642 |
|
643 |
$job_slug[] = $post_title;
|
@@ -671,11 +581,16 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
671 |
* Creates a file attachment.
|
672 |
*
|
673 |
* @param string $attachment_url
|
674 |
-
* @return int attachment id
|
675 |
*/
|
676 |
protected function create_attachment( $attachment_url ) {
|
677 |
-
include_once ABSPATH . 'wp-admin/includes/image.php';
|
678 |
-
include_once ABSPATH . 'wp-admin/includes/media.php';
|
|
|
|
|
|
|
|
|
|
|
679 |
|
680 |
$upload_dir = wp_upload_dir();
|
681 |
$attachment_url = str_replace( array( $upload_dir['baseurl'], WP_CONTENT_URL, site_url( '/' ) ), array( $upload_dir['basedir'], WP_CONTENT_DIR, ABSPATH ), $attachment_url );
|
@@ -684,16 +599,15 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
684 |
return 0;
|
685 |
}
|
686 |
|
687 |
-
$attachment
|
688 |
-
'post_title' =>
|
689 |
'post_content' => '',
|
690 |
'post_status' => 'inherit',
|
691 |
'post_parent' => $this->job_id,
|
692 |
-
'guid' => $attachment_url
|
693 |
);
|
694 |
|
695 |
-
$info = wp_check_filetype( $attachment_url )
|
696 |
-
if ( $info ) {
|
697 |
$attachment['post_mime_type'] = $info['type'];
|
698 |
}
|
699 |
|
@@ -713,16 +627,16 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
713 |
* @param array $values
|
714 |
*/
|
715 |
protected function update_job_data( $values ) {
|
716 |
-
// Set defaults
|
717 |
add_post_meta( $this->job_id, '_filled', 0, true );
|
718 |
add_post_meta( $this->job_id, '_featured', 0, true );
|
719 |
|
720 |
$maybe_attach = array();
|
721 |
|
722 |
-
// Loop fields and save meta and term data
|
723 |
foreach ( $this->fields as $group_key => $group_fields ) {
|
724 |
foreach ( $group_fields as $key => $field ) {
|
725 |
-
// Save taxonomies
|
726 |
if ( ! empty( $field['taxonomy'] ) ) {
|
727 |
if ( is_array( $values[ $group_key ][ $key ] ) ) {
|
728 |
wp_set_object_terms( $this->job_id, $values[ $group_key ][ $key ], $field['taxonomy'], false );
|
@@ -730,21 +644,17 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
730 |
wp_set_object_terms( $this->job_id, array( $values[ $group_key ][ $key ] ), $field['taxonomy'], false );
|
731 |
}
|
732 |
|
733 |
-
|
734 |
} elseif ( 'company_logo' === $key ) {
|
735 |
$attachment_id = is_numeric( $values[ $group_key ][ $key ] ) ? absint( $values[ $group_key ][ $key ] ) : $this->create_attachment( $values[ $group_key ][ $key ] );
|
736 |
-
|
737 |
-
delete_post_thumbnail( $this->job_id );
|
738 |
-
} else {
|
739 |
-
set_post_thumbnail( $this->job_id, $attachment_id );
|
740 |
-
}
|
741 |
update_user_meta( get_current_user_id(), '_company_logo', $attachment_id );
|
742 |
|
743 |
-
|
744 |
} else {
|
745 |
update_post_meta( $this->job_id, '_' . $key, $values[ $group_key ][ $key ] );
|
746 |
|
747 |
-
// Handle attachments
|
748 |
if ( 'file' === $field['type'] ) {
|
749 |
if ( is_array( $values[ $group_key ][ $key ] ) ) {
|
750 |
foreach ( $values[ $group_key ][ $key ] as $file_url ) {
|
@@ -760,25 +670,25 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
760 |
|
761 |
$maybe_attach = array_filter( $maybe_attach );
|
762 |
|
763 |
-
// Handle attachments
|
764 |
-
if (
|
765 |
-
// Get attachments
|
766 |
-
$attachments = get_posts( 'post_parent=' . $this->job_id . '&post_type=attachment&fields=ids&numberposts=-1' );
|
767 |
$attachment_urls = array();
|
768 |
|
769 |
-
// Loop attachments already attached to the job
|
770 |
foreach ( $attachments as $attachment_id ) {
|
771 |
$attachment_urls[] = wp_get_attachment_url( $attachment_id );
|
772 |
}
|
773 |
|
774 |
foreach ( $maybe_attach as $attachment_url ) {
|
775 |
-
if ( ! in_array( $attachment_url, $attachment_urls
|
776 |
$this->create_attachment( $attachment_url );
|
777 |
}
|
778 |
}
|
779 |
}
|
780 |
|
781 |
-
// And user meta to save time in future
|
782 |
if ( is_user_logged_in() ) {
|
783 |
update_user_meta( get_current_user_id(), '_company_name', isset( $values['company']['company_name'] ) ? $values['company']['company_name'] : '' );
|
784 |
update_user_meta( get_current_user_id(), '_company_website', isset( $values['company']['company_website'] ) ? $values['company']['company_website'] : '' );
|
@@ -798,17 +708,14 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
798 |
|
799 |
if ( $this->job_id ) {
|
800 |
$job_preview = true;
|
801 |
-
$post = get_post( $this->job_id );
|
802 |
$post->post_status = 'preview';
|
803 |
|
804 |
setup_postdata( $post );
|
805 |
|
806 |
-
get_job_manager_template(
|
807 |
-
'
|
808 |
-
|
809 |
-
'form' => $this,
|
810 |
-
)
|
811 |
-
);
|
812 |
|
813 |
wp_reset_postdata();
|
814 |
}
|
@@ -822,20 +729,20 @@ class WP_Job_Manager_Form_Submit_Job extends WP_Job_Manager_Form {
|
|
822 |
return;
|
823 |
}
|
824 |
|
825 |
-
// Edit = show submit form again
|
826 |
if ( ! empty( $_POST['edit_job'] ) ) {
|
827 |
$this->step --;
|
828 |
}
|
829 |
|
830 |
-
// Continue = change job status then show next screen
|
831 |
if ( ! empty( $_POST['continue'] ) ) {
|
832 |
$job = get_post( $this->job_id );
|
833 |
|
834 |
-
if ( in_array( $job->post_status, array( 'preview', 'expired' )
|
835 |
-
// Reset expiry
|
836 |
delete_post_meta( $job->ID, '_job_expires' );
|
837 |
|
838 |
-
// Update job listing
|
839 |
$update_job = array();
|
840 |
$update_job['ID'] = $job->ID;
|
841 |
$update_job['post_status'] = apply_filters( 'submit_job_post_status', get_option( 'job_manager_submission_requires_approval' ) ? 'pending' : 'publish', $job );
|
57 |
*/
|
58 |
public function __construct() {
|
59 |
add_action( 'wp', array( $this, 'process' ) );
|
|
|
|
|
|
|
|
|
60 |
|
61 |
+
$this->steps = (array) apply_filters( 'submit_job_steps', array(
|
62 |
+
'submit' => array(
|
63 |
+
'name' => __( 'Submit Details', 'wp-job-manager' ),
|
64 |
+
'view' => array( $this, 'submit' ),
|
65 |
+
'handler' => array( $this, 'submit_handler' ),
|
66 |
+
'priority' => 10
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
),
|
68 |
+
'preview' => array(
|
69 |
+
'name' => __( 'Preview', 'wp-job-manager' ),
|
70 |
+
'view' => array( $this, 'preview' ),
|
71 |
+
'handler' => array( $this, 'preview_handler' ),
|
72 |
+
'priority' => 20
|
73 |
+
),
|
74 |
+
'done' => array(
|
75 |
+
'name' => __( 'Done', 'wp-job-manager' ),
|
76 |
+
'view' => array( $this, 'done' ),
|
77 |
+
'priority' => 30
|
78 |
)
|
79 |
+
) );
|
80 |
|
81 |
uasort( $this->steps, array( $this, 'sort_by_priority' ) );
|
82 |
|
83 |
+
// Get step/job
|
84 |
if ( isset( $_POST['step'] ) ) {
|
85 |
+
$this->step = is_numeric( $_POST['step'] ) ? max( absint( $_POST['step'] ), 0 ) : array_search( $_POST['step'], array_keys( $this->steps ) );
|
86 |
} elseif ( ! empty( $_GET['step'] ) ) {
|
87 |
+
$this->step = is_numeric( $_GET['step'] ) ? max( absint( $_GET['step'] ), 0 ) : array_search( $_GET['step'], array_keys( $this->steps ) );
|
88 |
}
|
89 |
|
90 |
+
$this->job_id = ! empty( $_REQUEST[ 'job_id' ] ) ? absint( $_REQUEST[ 'job_id' ] ) : 0;
|
91 |
|
92 |
if ( ! job_manager_user_can_edit_job( $this->job_id ) ) {
|
93 |
$this->job_id = 0;
|
95 |
|
96 |
// Allow resuming from cookie.
|
97 |
$this->resume_edit = false;
|
98 |
+
if ( ! isset( $_GET[ 'new' ] ) && ( 'before' === get_option( 'job_manager_paid_listings_flow' ) || ! $this->job_id ) && ! empty( $_COOKIE['wp-job-manager-submitting-job-id'] ) && ! empty( $_COOKIE['wp-job-manager-submitting-job-key'] ) ) {
|
99 |
$job_id = absint( $_COOKIE['wp-job-manager-submitting-job-id'] );
|
100 |
$job_status = get_post_status( $job_id );
|
101 |
|
102 |
if ( ( 'preview' === $job_status || 'pending_payment' === $job_status ) && get_post_meta( $job_id, '_submitting_key', true ) === $_COOKIE['wp-job-manager-submitting-job-key'] ) {
|
103 |
+
$this->job_id = $job_id;
|
104 |
$this->resume_edit = get_post_meta( $job_id, '_submitting_key', true );
|
105 |
}
|
106 |
}
|
107 |
|
108 |
+
// Load job details
|
109 |
if ( $this->job_id ) {
|
110 |
$job_status = get_post_status( $this->job_id );
|
111 |
if ( 'expired' === $job_status ) {
|
113 |
$this->job_id = 0;
|
114 |
$this->step = 0;
|
115 |
}
|
116 |
+
} elseif ( ! in_array( $job_status, apply_filters( 'job_manager_valid_submit_job_statuses', array( 'preview' ) ) ) ) {
|
117 |
$this->job_id = 0;
|
118 |
$this->step = 0;
|
119 |
}
|
139 |
|
140 |
$allowed_application_method = get_option( 'job_manager_allowed_application_method', '' );
|
141 |
switch ( $allowed_application_method ) {
|
142 |
+
case 'email' :
|
143 |
$application_method_label = __( 'Application email', 'wp-job-manager' );
|
144 |
$application_method_placeholder = __( 'you@yourdomain.com', 'wp-job-manager' );
|
145 |
+
break;
|
146 |
+
case 'url' :
|
|
|
147 |
$application_method_label = __( 'Application URL', 'wp-job-manager' );
|
148 |
$application_method_placeholder = __( 'http://', 'wp-job-manager' );
|
149 |
+
break;
|
150 |
+
default :
|
|
|
151 |
$application_method_label = __( 'Application email/URL', 'wp-job-manager' );
|
152 |
$application_method_placeholder = __( 'Enter an email address or website URL', 'wp-job-manager' );
|
153 |
+
break;
|
|
|
154 |
}
|
155 |
|
156 |
if ( job_manager_multi_job_type() ) {
|
158 |
} else {
|
159 |
$job_type = 'term-select';
|
160 |
}
|
161 |
+
$this->fields = apply_filters( 'submit_job_form_fields', array(
|
162 |
+
'job' => array(
|
163 |
+
'job_title' => array(
|
164 |
+
'label' => __( 'Job Title', 'wp-job-manager' ),
|
165 |
+
'type' => 'text',
|
166 |
+
'required' => true,
|
167 |
+
'placeholder' => '',
|
168 |
+
'priority' => 1
|
169 |
+
),
|
170 |
+
'job_location' => array(
|
171 |
+
'label' => __( 'Location', 'wp-job-manager' ),
|
172 |
+
'description' => __( 'Leave this blank if the location is not important', 'wp-job-manager' ),
|
173 |
+
'type' => 'text',
|
174 |
+
'required' => false,
|
175 |
+
'placeholder' => __( 'e.g. "London"', 'wp-job-manager' ),
|
176 |
+
'priority' => 2
|
177 |
+
),
|
178 |
+
'job_type' => array(
|
179 |
+
'label' => __( 'Job type', 'wp-job-manager' ),
|
180 |
+
'type' => $job_type,
|
181 |
+
'required' => true,
|
182 |
+
'placeholder' => __( 'Choose job type…', 'wp-job-manager' ),
|
183 |
+
'priority' => 3,
|
184 |
+
'default' => 'full-time',
|
185 |
+
'taxonomy' => 'job_listing_type'
|
186 |
+
),
|
187 |
+
'job_category' => array(
|
188 |
+
'label' => __( 'Job category', 'wp-job-manager' ),
|
189 |
+
'type' => 'term-multiselect',
|
190 |
+
'required' => true,
|
191 |
+
'placeholder' => '',
|
192 |
+
'priority' => 4,
|
193 |
+
'default' => '',
|
194 |
+
'taxonomy' => 'job_listing_category'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
),
|
196 |
+
'job_description' => array(
|
197 |
+
'label' => __( 'Description', 'wp-job-manager' ),
|
198 |
+
'type' => 'wp-editor',
|
199 |
+
'required' => true,
|
200 |
+
'placeholder' => '',
|
201 |
+
'priority' => 5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
),
|
203 |
+
'application' => array(
|
204 |
+
'label' => $application_method_label,
|
205 |
+
'type' => 'text',
|
206 |
+
'required' => true,
|
207 |
+
'placeholder' => $application_method_placeholder,
|
208 |
+
'priority' => 6
|
209 |
+
)
|
210 |
+
),
|
211 |
+
'company' => array(
|
212 |
+
'company_name' => array(
|
213 |
+
'label' => __( 'Company name', 'wp-job-manager' ),
|
214 |
+
'type' => 'text',
|
215 |
+
'required' => true,
|
216 |
+
'placeholder' => __( 'Enter the name of the company', 'wp-job-manager' ),
|
217 |
+
'priority' => 1
|
218 |
+
),
|
219 |
+
'company_website' => array(
|
220 |
+
'label' => __( 'Website', 'wp-job-manager' ),
|
221 |
+
'type' => 'text',
|
222 |
+
'required' => false,
|
223 |
+
'placeholder' => __( 'http://', 'wp-job-manager' ),
|
224 |
+
'priority' => 2
|
225 |
+
),
|
226 |
+
'company_tagline' => array(
|
227 |
+
'label' => __( 'Tagline', 'wp-job-manager' ),
|
228 |
+
'type' => 'text',
|
229 |
+
'required' => false,
|
230 |
+
'placeholder' => __( 'Briefly describe your company', 'wp-job-manager' ),
|
231 |
+
'maxlength' => 64,
|
232 |
+
'priority' => 3
|
233 |
+
),
|
234 |
+
'company_video' => array(
|
235 |
+
'label' => __( 'Video', 'wp-job-manager' ),
|
236 |
+
'type' => 'text',
|
237 |
+
'required' => false,
|
238 |
+
'placeholder' => __( 'A link to a video about your company', 'wp-job-manager' ),
|
239 |
+
'priority' => 4
|
240 |
+
),
|
241 |
+
'company_twitter' => array(
|
242 |
+
'label' => __( 'Twitter username', 'wp-job-manager' ),
|
243 |
+
'type' => 'text',
|
244 |
+
'required' => false,
|
245 |
+
'placeholder' => __( '@yourcompany', 'wp-job-manager' ),
|
246 |
+
'priority' => 5
|
247 |
+
),
|
248 |
+
'company_logo' => array(
|
249 |
+
'label' => __( 'Logo', 'wp-job-manager' ),
|
250 |
+
'type' => 'file',
|
251 |
+
'required' => false,
|
252 |
+
'placeholder' => '',
|
253 |
+
'priority' => 6,
|
254 |
+
'ajax' => true,
|
255 |
+
'multiple' => false,
|
256 |
+
'allowed_mime_types' => array(
|
257 |
+
'jpg' => 'image/jpeg',
|
258 |
+
'jpeg' => 'image/jpeg',
|
259 |
+
'gif' => 'image/gif',
|
260 |
+
'png' => 'image/png'
|
261 |
+
)
|
262 |
+
)
|
263 |
)
|
264 |
+
) );
|
265 |
|
266 |
+
if ( ! get_option( 'job_manager_enable_categories' ) || wp_count_terms( 'job_listing_category' ) == 0 ) {
|
267 |
unset( $this->fields['job']['job_category'] );
|
268 |
}
|
269 |
+
if ( ! get_option( 'job_manager_enable_types' ) || wp_count_terms( 'job_listing_type' ) == 0 ) {
|
270 |
unset( $this->fields['job']['job_type'] );
|
271 |
}
|
272 |
}
|
273 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
/**
|
275 |
* Validates the posted fields.
|
276 |
*
|
277 |
* @param array $values
|
278 |
+
* @throws Exception Uploaded file is not a valid mime-type or other validation error
|
279 |
+
* @return bool|WP_Error True on success, WP_Error on failure
|
280 |
*/
|
281 |
protected function validate_fields( $values ) {
|
282 |
foreach ( $this->fields as $group_key => $group_fields ) {
|
283 |
foreach ( $group_fields as $key => $field ) {
|
284 |
if ( $field['required'] && empty( $values[ $group_key ][ $key ] ) ) {
|
|
|
285 |
return new WP_Error( 'validation-error', sprintf( __( '%s is a required field', 'wp-job-manager' ), $field['label'] ) );
|
286 |
}
|
287 |
+
if ( ! empty( $field['taxonomy'] ) && in_array( $field['type'], array( 'term-checklist', 'term-select', 'term-multiselect' ) ) ) {
|
288 |
if ( is_array( $values[ $group_key ][ $key ] ) ) {
|
289 |
$check_value = $values[ $group_key ][ $key ];
|
290 |
} else {
|
292 |
}
|
293 |
foreach ( $check_value as $term ) {
|
294 |
if ( ! term_exists( $term, $field['taxonomy'] ) ) {
|
|
|
295 |
return new WP_Error( 'validation-error', sprintf( __( '%s is invalid', 'wp-job-manager' ), $field['label'] ) );
|
296 |
}
|
297 |
}
|
298 |
}
|
299 |
+
if ( 'file' === $field['type'] ) {
|
300 |
+
if ( is_array( $values[ $group_key ][ $key ] ) ) {
|
301 |
+
$check_value = array_filter( $values[ $group_key ][ $key ] );
|
302 |
+
} else {
|
303 |
+
$check_value = array_filter( array( $values[ $group_key ][ $key ] ) );
|
304 |
+
}
|
305 |
+
if ( ! empty( $check_value ) ) {
|
306 |
+
foreach ( $check_value as $file_url ) {
|
307 |
+
if ( is_numeric( $file_url ) ) {
|
308 |
+
continue;
|
309 |
+
}
|
310 |
+
$file_url = esc_url( $file_url, array( 'http', 'https' ) );
|
311 |
+
if ( empty( $file_url ) ) {
|
312 |
+
throw new Exception( __( 'Invalid attachment provided.', 'wp-job-manager' ) );
|
313 |
+
}
|
314 |
+
}
|
315 |
+
}
|
316 |
+
}
|
317 |
if ( 'file' === $field['type'] && ! empty( $field['allowed_mime_types'] ) ) {
|
318 |
if ( is_array( $values[ $group_key ][ $key ] ) ) {
|
319 |
$check_value = array_filter( $values[ $group_key ][ $key ] );
|
325 |
$file_url = current( explode( '?', $file_url ) );
|
326 |
$file_info = wp_check_filetype( $file_url );
|
327 |
|
328 |
+
if ( ! is_numeric( $file_url ) && $file_info && ! in_array( $file_info['type'], $field['allowed_mime_types'] ) ) {
|
329 |
+
throw new Exception( sprintf( __( '"%s" (filetype %s) needs to be one of the following file types: %s', 'wp-job-manager' ), $field['label'], $file_info['ext'], implode( ', ', array_keys( $field['allowed_mime_types'] ) ) ) );
|
|
|
330 |
}
|
331 |
}
|
332 |
}
|
334 |
}
|
335 |
}
|
336 |
|
337 |
+
// Application method
|
338 |
if ( isset( $values['job']['application'] ) && ! empty( $values['job']['application'] ) ) {
|
339 |
+
$allowed_application_method = get_option( 'job_manager_allowed_application_method', '' );
|
340 |
$values['job']['application'] = str_replace( ' ', '+', $values['job']['application'] );
|
341 |
switch ( $allowed_application_method ) {
|
342 |
+
case 'email' :
|
343 |
if ( ! is_email( $values['job']['application'] ) ) {
|
344 |
throw new Exception( __( 'Please enter a valid application email address', 'wp-job-manager' ) );
|
345 |
}
|
346 |
+
break;
|
347 |
+
case 'url' :
|
348 |
+
// Prefix http if needed
|
349 |
if ( ! strstr( $values['job']['application'], 'http:' ) && ! strstr( $values['job']['application'], 'https:' ) ) {
|
350 |
$values['job']['application'] = 'http://' . $values['job']['application'];
|
351 |
}
|
352 |
if ( ! filter_var( $values['job']['application'], FILTER_VALIDATE_URL ) ) {
|
353 |
throw new Exception( __( 'Please enter a valid application URL', 'wp-job-manager' ) );
|
354 |
}
|
355 |
+
break;
|
356 |
+
default :
|
357 |
if ( ! is_email( $values['job']['application'] ) ) {
|
358 |
+
// Prefix http if needed
|
359 |
if ( ! strstr( $values['job']['application'], 'http:' ) && ! strstr( $values['job']['application'], 'https:' ) ) {
|
360 |
$values['job']['application'] = 'http://' . $values['job']['application'];
|
361 |
}
|
363 |
throw new Exception( __( 'Please enter a valid application email address or URL', 'wp-job-manager' ) );
|
364 |
}
|
365 |
}
|
366 |
+
break;
|
367 |
}
|
368 |
}
|
369 |
|
370 |
return apply_filters( 'submit_job_form_validate_fields', true, $this->fields, $values );
|
371 |
}
|
372 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
373 |
/**
|
374 |
* Returns an array of the job types indexed by slug. (Unused)
|
375 |
*
|
390 |
public function submit() {
|
391 |
$this->init_fields();
|
392 |
|
393 |
+
// Load data if neccessary
|
394 |
if ( $this->job_id ) {
|
395 |
$job = get_post( $this->job_id );
|
396 |
foreach ( $this->fields as $group_key => $group_fields ) {
|
397 |
foreach ( $group_fields as $key => $field ) {
|
398 |
switch ( $key ) {
|
399 |
+
case 'job_title' :
|
400 |
$this->fields[ $group_key ][ $key ]['value'] = $job->post_title;
|
401 |
+
break;
|
402 |
+
case 'job_description' :
|
403 |
$this->fields[ $group_key ][ $key ]['value'] = $job->post_content;
|
404 |
+
break;
|
405 |
+
case 'job_type' :
|
406 |
+
$this->fields[ $group_key ][ $key ]['value'] = current( wp_get_object_terms( $job->ID, 'job_listing_type', array( 'fields' => 'ids' ) ) );
|
407 |
+
break;
|
408 |
+
case 'job_category' :
|
|
|
|
|
|
|
409 |
$this->fields[ $group_key ][ $key ]['value'] = wp_get_object_terms( $job->ID, 'job_listing_category', array( 'fields' => 'ids' ) );
|
410 |
+
break;
|
411 |
+
case 'company_logo' :
|
412 |
$this->fields[ $group_key ][ $key ]['value'] = has_post_thumbnail( $job->ID ) ? get_post_thumbnail_id( $job->ID ) : get_post_meta( $job->ID, '_' . $key, true );
|
413 |
+
break;
|
414 |
default:
|
415 |
$this->fields[ $group_key ][ $key ]['value'] = get_post_meta( $job->ID, '_' . $key, true );
|
416 |
+
break;
|
417 |
}
|
418 |
}
|
419 |
}
|
420 |
|
421 |
$this->fields = apply_filters( 'submit_job_form_fields_get_job_data', $this->fields, $job );
|
422 |
|
423 |
+
// Get user meta
|
424 |
} elseif ( is_user_logged_in() && empty( $_POST['submit_job'] ) ) {
|
425 |
if ( ! empty( $this->fields['company'] ) ) {
|
426 |
foreach ( $this->fields['company'] as $key => $field ) {
|
429 |
}
|
430 |
if ( ! empty( $this->fields['job']['application'] ) ) {
|
431 |
$allowed_application_method = get_option( 'job_manager_allowed_application_method', '' );
|
432 |
+
if ( $allowed_application_method !== 'url' ) {
|
433 |
+
$current_user = wp_get_current_user();
|
434 |
$this->fields['job']['application']['value'] = $current_user->user_email;
|
435 |
}
|
436 |
}
|
437 |
$this->fields = apply_filters( 'submit_job_form_fields_get_user_data', $this->fields, get_current_user_id() );
|
438 |
}
|
439 |
|
440 |
+
wp_enqueue_script( 'wp-job-manager-job-submission' );
|
441 |
+
|
442 |
+
get_job_manager_template( 'job-submit.php', array(
|
443 |
+
'form' => $this->form_name,
|
444 |
+
'job_id' => $this->get_job_id(),
|
445 |
+
'resume_edit' => $this->resume_edit,
|
446 |
+
'action' => $this->get_action(),
|
447 |
+
'job_fields' => $this->get_fields( 'job' ),
|
448 |
+
'company_fields' => $this->get_fields( 'company' ),
|
449 |
+
'step' => $this->get_step(),
|
450 |
+
'submit_button_text' => apply_filters( 'submit_job_form_submit_button_text', __( 'Preview', 'wp-job-manager' ) )
|
451 |
+
) );
|
|
|
|
|
452 |
}
|
453 |
|
454 |
/**
|
455 |
* Handles the submission of form data.
|
|
|
|
|
456 |
*/
|
457 |
public function submit_handler() {
|
458 |
try {
|
459 |
+
// Init fields
|
460 |
$this->init_fields();
|
461 |
|
462 |
+
// Get posted values
|
463 |
$values = $this->get_posted_fields();
|
464 |
|
465 |
if ( empty( $_POST['submit_job'] ) ) {
|
466 |
return;
|
467 |
}
|
468 |
|
469 |
+
// Validate required
|
470 |
+
if ( is_wp_error( ( $return = $this->validate_fields( $values ) ) ) ) {
|
471 |
+
throw new Exception( $return->get_error_message() );
|
|
|
472 |
}
|
473 |
|
474 |
+
// Account creation
|
475 |
if ( ! is_user_logged_in() ) {
|
476 |
$create_account = false;
|
477 |
|
480 |
if ( ! job_manager_generate_username_from_email() && empty( $_POST['create_account_username'] ) ) {
|
481 |
throw new Exception( __( 'Please enter a username.', 'wp-job-manager' ) );
|
482 |
}
|
|
|
|
|
|
|
|
|
|
|
483 |
if ( empty( $_POST['create_account_email'] ) ) {
|
484 |
throw new Exception( __( 'Please enter your email address.', 'wp-job-manager' ) );
|
485 |
}
|
486 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
487 |
if ( ! empty( $_POST['create_account_email'] ) ) {
|
488 |
+
$create_account = wp_job_manager_create_account( array(
|
489 |
+
'username' => empty( $_POST['create_account_username'] ) ? '' : $_POST['create_account_username'],
|
490 |
+
'email' => $_POST['create_account_email'],
|
491 |
+
'role' => get_option( 'job_manager_registration_role' )
|
492 |
+
) );
|
|
|
|
|
|
|
493 |
}
|
494 |
}
|
495 |
|
502 |
throw new Exception( __( 'You must be signed in to post a new listing.', 'wp-job-manager' ) );
|
503 |
}
|
504 |
|
505 |
+
// Update the job
|
506 |
$this->save_job( $values['job']['job_title'], $values['job']['job_description'], $this->job_id ? '' : 'preview', $values );
|
507 |
$this->update_job_data( $values );
|
508 |
|
509 |
+
// Successful, show next step
|
510 |
$this->step ++;
|
511 |
|
512 |
} catch ( Exception $e ) {
|
529 |
'post_title' => $post_title,
|
530 |
'post_content' => $post_content,
|
531 |
'post_type' => 'job_listing',
|
532 |
+
'comment_status' => 'closed'
|
533 |
);
|
534 |
|
535 |
if ( $update_slug ) {
|
536 |
+
$job_slug = array();
|
537 |
|
538 |
+
// Prepend with company name
|
539 |
if ( apply_filters( 'submit_job_form_prefix_post_name_with_company', true ) && ! empty( $values['company']['company_name'] ) ) {
|
540 |
$job_slug[] = $values['company']['company_name'];
|
541 |
}
|
542 |
|
543 |
+
// Prepend location
|
544 |
if ( apply_filters( 'submit_job_form_prefix_post_name_with_location', true ) && ! empty( $values['job']['job_location'] ) ) {
|
545 |
$job_slug[] = $values['job']['job_location'];
|
546 |
}
|
547 |
|
548 |
+
// Prepend with job type
|
549 |
if ( apply_filters( 'submit_job_form_prefix_post_name_with_job_type', true ) && ! empty( $values['job']['job_type'] ) ) {
|
550 |
+
$job_slug[] = $values['job']['job_type'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
551 |
}
|
552 |
|
553 |
$job_slug[] = $post_title;
|
581 |
* Creates a file attachment.
|
582 |
*
|
583 |
* @param string $attachment_url
|
584 |
+
* @return int attachment id
|
585 |
*/
|
586 |
protected function create_attachment( $attachment_url ) {
|
587 |
+
include_once( ABSPATH . 'wp-admin/includes/image.php' );
|
588 |
+
include_once( ABSPATH . 'wp-admin/includes/media.php' );
|
589 |
+
|
590 |
+
$attachment_url = esc_url( $attachment_url, array( 'http', 'https' ) );
|
591 |
+
if ( empty( $attachment_url ) ) {
|
592 |
+
return 0;
|
593 |
+
}
|
594 |
|
595 |
$upload_dir = wp_upload_dir();
|
596 |
$attachment_url = str_replace( array( $upload_dir['baseurl'], WP_CONTENT_URL, site_url( '/' ) ), array( $upload_dir['basedir'], WP_CONTENT_DIR, ABSPATH ), $attachment_url );
|
599 |
return 0;
|
600 |
}
|
601 |
|
602 |
+
$attachment = array(
|
603 |
+
'post_title' => get_the_title( $this->job_id ),
|
604 |
'post_content' => '',
|
605 |
'post_status' => 'inherit',
|
606 |
'post_parent' => $this->job_id,
|
607 |
+
'guid' => $attachment_url
|
608 |
);
|
609 |
|
610 |
+
if ( $info = wp_check_filetype( $attachment_url ) ) {
|
|
|
611 |
$attachment['post_mime_type'] = $info['type'];
|
612 |
}
|
613 |
|
627 |
* @param array $values
|
628 |
*/
|
629 |
protected function update_job_data( $values ) {
|
630 |
+
// Set defaults
|
631 |
add_post_meta( $this->job_id, '_filled', 0, true );
|
632 |
add_post_meta( $this->job_id, '_featured', 0, true );
|
633 |
|
634 |
$maybe_attach = array();
|
635 |
|
636 |
+
// Loop fields and save meta and term data
|
637 |
foreach ( $this->fields as $group_key => $group_fields ) {
|
638 |
foreach ( $group_fields as $key => $field ) {
|
639 |
+
// Save taxonomies
|
640 |
if ( ! empty( $field['taxonomy'] ) ) {
|
641 |
if ( is_array( $values[ $group_key ][ $key ] ) ) {
|
642 |
wp_set_object_terms( $this->job_id, $values[ $group_key ][ $key ], $field['taxonomy'], false );
|
644 |
wp_set_object_terms( $this->job_id, array( $values[ $group_key ][ $key ] ), $field['taxonomy'], false );
|
645 |
}
|
646 |
|
647 |
+
// Company logo is a featured image
|
648 |
} elseif ( 'company_logo' === $key ) {
|
649 |
$attachment_id = is_numeric( $values[ $group_key ][ $key ] ) ? absint( $values[ $group_key ][ $key ] ) : $this->create_attachment( $values[ $group_key ][ $key ] );
|
650 |
+
set_post_thumbnail( $this->job_id, $attachment_id );
|
|
|
|
|
|
|
|
|
651 |
update_user_meta( get_current_user_id(), '_company_logo', $attachment_id );
|
652 |
|
653 |
+
// Save meta data
|
654 |
} else {
|
655 |
update_post_meta( $this->job_id, '_' . $key, $values[ $group_key ][ $key ] );
|
656 |
|
657 |
+
// Handle attachments
|
658 |
if ( 'file' === $field['type'] ) {
|
659 |
if ( is_array( $values[ $group_key ][ $key ] ) ) {
|
660 |
foreach ( $values[ $group_key ][ $key ] as $file_url ) {
|
670 |
|
671 |
$maybe_attach = array_filter( $maybe_attach );
|
672 |
|
673 |
+
// Handle attachments
|
674 |
+
if ( sizeof( $maybe_attach ) && apply_filters( 'job_manager_attach_uploaded_files', true ) ) {
|
675 |
+
// Get attachments
|
676 |
+
$attachments = get_posts( 'post_parent=' . $this->job_id . '&post_type=attachment&fields=ids&post_mime_type=image&numberposts=-1' );
|
677 |
$attachment_urls = array();
|
678 |
|
679 |
+
// Loop attachments already attached to the job
|
680 |
foreach ( $attachments as $attachment_id ) {
|
681 |
$attachment_urls[] = wp_get_attachment_url( $attachment_id );
|
682 |
}
|
683 |
|
684 |
foreach ( $maybe_attach as $attachment_url ) {
|
685 |
+
if ( ! in_array( $attachment_url, $attachment_urls ) ) {
|
686 |
$this->create_attachment( $attachment_url );
|
687 |
}
|
688 |
}
|
689 |
}
|
690 |
|
691 |
+
// And user meta to save time in future
|
692 |
if ( is_user_logged_in() ) {
|
693 |
update_user_meta( get_current_user_id(), '_company_name', isset( $values['company']['company_name'] ) ? $values['company']['company_name'] : '' );
|
694 |
update_user_meta( get_current_user_id(), '_company_website', isset( $values['company']['company_website'] ) ? $values['company']['company_website'] : '' );
|
708 |
|
709 |
if ( $this->job_id ) {
|
710 |
$job_preview = true;
|
711 |
+
$post = get_post( $this->job_id );
|
712 |
$post->post_status = 'preview';
|
713 |
|
714 |
setup_postdata( $post );
|
715 |
|
716 |
+
get_job_manager_template( 'job-preview.php', array(
|
717 |
+
'form' => $this
|
718 |
+
) );
|
|
|
|
|
|
|
719 |
|
720 |
wp_reset_postdata();
|
721 |
}
|
729 |
return;
|
730 |
}
|
731 |
|
732 |
+
// Edit = show submit form again
|
733 |
if ( ! empty( $_POST['edit_job'] ) ) {
|
734 |
$this->step --;
|
735 |
}
|
736 |
|
737 |
+
// Continue = change job status then show next screen
|
738 |
if ( ! empty( $_POST['continue'] ) ) {
|
739 |
$job = get_post( $this->job_id );
|
740 |
|
741 |
+
if ( in_array( $job->post_status, array( 'preview', 'expired' ) ) ) {
|
742 |
+
// Reset expiry
|
743 |
delete_post_meta( $job->ID, '_job_expires' );
|
744 |
|
745 |
+
// Update job listing
|
746 |
$update_job = array();
|
747 |
$update_job['ID'] = $job->ID;
|
748 |
$update_job['post_status'] = apply_filters( 'submit_job_post_status', get_option( 'job_manager_submission_requires_approval' ) ? 'pending' : 'publish', $job );
|
includes/helper/class-wp-job-manager-helper-api.php
DELETED
@@ -1,176 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit;
|
5 |
-
}
|
6 |
-
|
7 |
-
/**
|
8 |
-
* WP_Job_Manager_Helper_API
|
9 |
-
*/
|
10 |
-
class WP_Job_Manager_Helper_API {
|
11 |
-
|
12 |
-
const API_BASE_URL = 'https://wpjobmanager.com/';
|
13 |
-
|
14 |
-
/**
|
15 |
-
* The single instance of the class.
|
16 |
-
*
|
17 |
-
* @var self
|
18 |
-
* @since 1.29.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.29.0
|
26 |
-
* @static
|
27 |
-
* @return self Main instance.
|
28 |
-
*/
|
29 |
-
public static function instance() {
|
30 |
-
if ( is_null( self::$_instance ) ) {
|
31 |
-
self::$_instance = new self();
|
32 |
-
}
|
33 |
-
return self::$_instance;
|
34 |
-
}
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Sends and receives data to and from the server API
|
38 |
-
*
|
39 |
-
* @param array|string $args
|
40 |
-
* @return object|bool $response.
|
41 |
-
*/
|
42 |
-
public function plugin_update_check( $args ) {
|
43 |
-
$args = wp_parse_args( $args );
|
44 |
-
$args['wc-api'] = 'wp_plugin_licencing_update_api';
|
45 |
-
$args['request'] = 'pluginupdatecheck';
|
46 |
-
return $this->request( $args );
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Sends and receives data to and from the server API
|
51 |
-
*
|
52 |
-
* @param array|string $args
|
53 |
-
* @return object $response.
|
54 |
-
*/
|
55 |
-
public function plugin_information( $args ) {
|
56 |
-
$args = wp_parse_args( $args );
|
57 |
-
$args['wc-api'] = 'wp_plugin_licencing_update_api';
|
58 |
-
$args['request'] = 'plugininformation';
|
59 |
-
return $this->request( $args );
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Attempt to activate a plugin licence.
|
64 |
-
*
|
65 |
-
* @param array|string $args
|
66 |
-
* @return boolean|string JSON response or false if failed.
|
67 |
-
*/
|
68 |
-
public function activate( $args ) {
|
69 |
-
$args = wp_parse_args( $args );
|
70 |
-
$args['wc-api'] = 'wp_plugin_licencing_activation_api';
|
71 |
-
$args['request'] = 'activate';
|
72 |
-
$response = $this->request( $args, true );
|
73 |
-
if ( false === $response ) {
|
74 |
-
return false;
|
75 |
-
}
|
76 |
-
return $response;
|
77 |
-
}
|
78 |
-
|
79 |
-
/**
|
80 |
-
* Attempt to deactivate a plugin licence.
|
81 |
-
*
|
82 |
-
* @param array|string $args
|
83 |
-
* @return boolean|string JSON response or false if failed.
|
84 |
-
*/
|
85 |
-
public function deactivate( $args ) {
|
86 |
-
$args = wp_parse_args( $args );
|
87 |
-
$args['wc-api'] = 'wp_plugin_licencing_activation_api';
|
88 |
-
$args['request'] = 'deactivate';
|
89 |
-
$response = $this->request( $args, false );
|
90 |
-
if ( false === $response ) {
|
91 |
-
return false;
|
92 |
-
}
|
93 |
-
return $response;
|
94 |
-
}
|
95 |
-
|
96 |
-
/**
|
97 |
-
* Make a licence helper API request.
|
98 |
-
*
|
99 |
-
* @param array $args
|
100 |
-
* @param bool $return_error
|
101 |
-
*
|
102 |
-
* @return array|bool|mixed|object
|
103 |
-
*/
|
104 |
-
protected function request( $args, $return_error = false ) {
|
105 |
-
$defaults = array(
|
106 |
-
'instance' => $this->get_site_url(),
|
107 |
-
'plugin_name' => '',
|
108 |
-
'version' => '',
|
109 |
-
'api_product_id' => '',
|
110 |
-
'licence_key' => '',
|
111 |
-
'email' => '',
|
112 |
-
);
|
113 |
-
|
114 |
-
$args = wp_parse_args( $args, $defaults );
|
115 |
-
$request = wp_safe_remote_get(
|
116 |
-
$this->get_api_base_url() . '?' . http_build_query( $args, '', '&' ),
|
117 |
-
array(
|
118 |
-
'timeout' => 10,
|
119 |
-
'headers' => array(
|
120 |
-
'Accept' => 'application/json',
|
121 |
-
),
|
122 |
-
)
|
123 |
-
);
|
124 |
-
|
125 |
-
if ( is_wp_error( $request ) || 200 !== wp_remote_retrieve_response_code( $request ) ) {
|
126 |
-
if ( $return_error ) {
|
127 |
-
if ( is_wp_error( $request ) ) {
|
128 |
-
return array(
|
129 |
-
'error_code' => $request->get_error_code(),
|
130 |
-
'error' => $request->get_error_message(),
|
131 |
-
);
|
132 |
-
}
|
133 |
-
return array(
|
134 |
-
'error_code' => wp_remote_retrieve_response_code( $request ),
|
135 |
-
'error' => 'Error code: ' . wp_remote_retrieve_response_code( $request ),
|
136 |
-
);
|
137 |
-
}
|
138 |
-
return false;
|
139 |
-
}
|
140 |
-
|
141 |
-
$response = json_decode( wp_remote_retrieve_body( $request ), true );
|
142 |
-
|
143 |
-
if ( is_array( $response ) ) {
|
144 |
-
return $response;
|
145 |
-
}
|
146 |
-
|
147 |
-
return false;
|
148 |
-
}
|
149 |
-
|
150 |
-
/**
|
151 |
-
* Returns the site URL that is MU safe.
|
152 |
-
*
|
153 |
-
* @return string
|
154 |
-
*/
|
155 |
-
private function get_site_url() {
|
156 |
-
if ( is_multisite() || is_network_admin() ) {
|
157 |
-
return network_site_url();
|
158 |
-
}
|
159 |
-
return site_url();
|
160 |
-
}
|
161 |
-
|
162 |
-
/**
|
163 |
-
* Returns the API base URL.
|
164 |
-
*
|
165 |
-
* @return string
|
166 |
-
*/
|
167 |
-
private function get_api_base_url() {
|
168 |
-
if ( defined( 'JOB_MANAGER_VERSION' )
|
169 |
-
&& defined( 'JOB_MANAGER_DEV_API_BASE_URL' )
|
170 |
-
&& '-dev' === substr( JOB_MANAGER_VERSION, -4 )
|
171 |
-
) {
|
172 |
-
return JOB_MANAGER_DEV_API_BASE_URL;
|
173 |
-
}
|
174 |
-
return self::API_BASE_URL;
|
175 |
-
}
|
176 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/helper/class-wp-job-manager-helper-options.php
DELETED
@@ -1,115 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit;
|
5 |
-
}
|
6 |
-
|
7 |
-
/**
|
8 |
-
* WP_Job_Manager_Helper_Options
|
9 |
-
*/
|
10 |
-
class WP_Job_Manager_Helper_Options {
|
11 |
-
const OPTION_NAME = 'job_manager_helper';
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Update a WPJM plugin's licence data.
|
15 |
-
*
|
16 |
-
* @param string $product_slug
|
17 |
-
* @param string $key
|
18 |
-
* @param mixed $value
|
19 |
-
*
|
20 |
-
* @return bool
|
21 |
-
*/
|
22 |
-
public static function update( $product_slug, $key, $value ) {
|
23 |
-
$options = self::get_master_option();
|
24 |
-
if ( ! isset( $options[ $product_slug ] ) ) {
|
25 |
-
$options[ $product_slug ] = array();
|
26 |
-
}
|
27 |
-
$options[ $product_slug ][ $key ] = $value;
|
28 |
-
return self::update_master_option( $options );
|
29 |
-
}
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Retrieve a WPJM plugin's licence data.
|
33 |
-
*
|
34 |
-
* @param string $product_slug
|
35 |
-
* @param string $key
|
36 |
-
* @param mixed $default
|
37 |
-
*
|
38 |
-
* @return mixed
|
39 |
-
*/
|
40 |
-
public static function get( $product_slug, $key, $default = false ) {
|
41 |
-
$options = self::get_master_option();
|
42 |
-
if ( ! isset( $options[ $product_slug ] ) ) {
|
43 |
-
$options[ $product_slug ] = self::attempt_legacy_restore( $product_slug );
|
44 |
-
}
|
45 |
-
if ( isset( $options[ $product_slug ][ $key ] ) ) {
|
46 |
-
return $options[ $product_slug ][ $key ];
|
47 |
-
}
|
48 |
-
return $default;
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Delete a WPJM plugin's licence data.
|
53 |
-
*
|
54 |
-
* @param string $product_slug
|
55 |
-
* @param string $key
|
56 |
-
*
|
57 |
-
* @return bool
|
58 |
-
*/
|
59 |
-
public static function delete( $product_slug, $key ) {
|
60 |
-
$options = self::get_master_option();
|
61 |
-
if ( ! isset( $options[ $product_slug ] ) ) {
|
62 |
-
$options[ $product_slug ] = array();
|
63 |
-
}
|
64 |
-
unset( $options[ $product_slug ][ $key ] );
|
65 |
-
return self::update_master_option( $options );
|
66 |
-
}
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Attempt to retrieve licence data from legacy storage.
|
70 |
-
*
|
71 |
-
* @param string $product_slug
|
72 |
-
*
|
73 |
-
* @return array
|
74 |
-
*/
|
75 |
-
private static function attempt_legacy_restore( $product_slug ) {
|
76 |
-
$options = self::get_master_option();
|
77 |
-
if ( ! isset( $options[ $product_slug ] ) ) {
|
78 |
-
$options[ $product_slug ] = array();
|
79 |
-
}
|
80 |
-
foreach ( array( 'licence_key', 'email', 'errors', 'hide_key_notice' ) as $key ) {
|
81 |
-
$option_value = get_option( $product_slug . '_' . $key, false );
|
82 |
-
if ( ! empty( $option_value ) ) {
|
83 |
-
$options[ $product_slug ][ $key ] = $option_value;
|
84 |
-
delete_option( $product_slug . '_' . $key );
|
85 |
-
}
|
86 |
-
}
|
87 |
-
self::update_master_option( $options );
|
88 |
-
return $options[ $product_slug ];
|
89 |
-
}
|
90 |
-
|
91 |
-
/**
|
92 |
-
* Retrieve the master option.
|
93 |
-
*
|
94 |
-
* @return array
|
95 |
-
*/
|
96 |
-
private static function get_master_option() {
|
97 |
-
if ( is_multisite() || is_network_admin() ) {
|
98 |
-
return get_site_option( self::OPTION_NAME, array() );
|
99 |
-
}
|
100 |
-
return get_option( self::OPTION_NAME, array() );
|
101 |
-
}
|
102 |
-
|
103 |
-
/**
|
104 |
-
* Update the master option.
|
105 |
-
*
|
106 |
-
* @param array $value Master license container array.
|
107 |
-
* @return bool
|
108 |
-
*/
|
109 |
-
private static function update_master_option( $value ) {
|
110 |
-
if ( is_multisite() || is_network_admin() ) {
|
111 |
-
return update_site_option( self::OPTION_NAME, $value );
|
112 |
-
}
|
113 |
-
return update_option( self::OPTION_NAME, $value );
|
114 |
-
}
|
115 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/helper/class-wp-job-manager-helper.php
DELETED
@@ -1,609 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly.
|
5 |
-
}
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Handles Job Manager's Ajax endpoints.
|
9 |
-
*
|
10 |
-
* @package wp-job-manager
|
11 |
-
* @since 1.29.0
|
12 |
-
*/
|
13 |
-
class WP_Job_Manager_Helper {
|
14 |
-
/**
|
15 |
-
* License messages to display to the user.
|
16 |
-
*
|
17 |
-
* @var array Messages when updating licences.
|
18 |
-
*/
|
19 |
-
protected $licence_messages = array();
|
20 |
-
|
21 |
-
/**
|
22 |
-
* API object.
|
23 |
-
*
|
24 |
-
* @var WP_Job_Manager_Helper_API
|
25 |
-
*/
|
26 |
-
protected $api;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* The single instance of the class.
|
30 |
-
*
|
31 |
-
* @var self
|
32 |
-
* @since 1.29.0
|
33 |
-
*/
|
34 |
-
private static $_instance = null;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* True if the plugin cache has already been cleared.
|
38 |
-
*
|
39 |
-
* @var bool
|
40 |
-
* @since 1.29.1
|
41 |
-
*/
|
42 |
-
private static $cleared_plugin_cache = false;
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Allows for accessing single instance of class. Class should only be constructed once per call.
|
46 |
-
*
|
47 |
-
* @since 1.29.0
|
48 |
-
* @static
|
49 |
-
* @return self Main instance.
|
50 |
-
*/
|
51 |
-
public static function instance() {
|
52 |
-
if ( is_null( self::$_instance ) ) {
|
53 |
-
self::$_instance = new self();
|
54 |
-
}
|
55 |
-
return self::$_instance;
|
56 |
-
}
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Loads the class, runs on init.
|
60 |
-
*/
|
61 |
-
public function init() {
|
62 |
-
include_once dirname( __FILE__ ) . '/class-wp-job-manager-helper-options.php';
|
63 |
-
include_once dirname( __FILE__ ) . '/class-wp-job-manager-helper-api.php';
|
64 |
-
|
65 |
-
$this->api = WP_Job_Manager_Helper_API::instance();
|
66 |
-
|
67 |
-
add_action( 'job_manager_helper_output', array( $this, 'licence_output' ) );
|
68 |
-
|
69 |
-
add_filter( 'job_manager_addon_core_version_check', array( $this, 'addon_core_version_check' ), 10, 2 );
|
70 |
-
add_filter( 'extra_plugin_headers', array( $this, 'extra_headers' ) );
|
71 |
-
add_filter( 'plugins_api', array( $this, 'plugins_api' ), 20, 3 );
|
72 |
-
add_action( 'pre_set_site_transient_update_plugins', array( $this, 'check_for_updates' ) );
|
73 |
-
|
74 |
-
add_action( 'activated_plugin', array( $this, 'plugin_activated' ) );
|
75 |
-
add_action( 'deactivated_plugin', array( $this, 'plugin_deactivated' ) );
|
76 |
-
add_action( 'admin_init', array( $this, 'admin_init' ) );
|
77 |
-
}
|
78 |
-
|
79 |
-
/**
|
80 |
-
* Initializes admin-only actions.
|
81 |
-
*/
|
82 |
-
public function admin_init() {
|
83 |
-
add_action( 'plugin_action_links', array( $this, 'plugin_links' ), 10, 2 );
|
84 |
-
add_action( 'admin_notices', array( $this, 'licence_error_notices' ) );
|
85 |
-
$this->handle_admin_request();
|
86 |
-
}
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Handles special tasks on admin requests.
|
90 |
-
*/
|
91 |
-
private function handle_admin_request() {
|
92 |
-
if ( ! empty( $_GET['dismiss-wpjm-licence-notice'] ) ) {
|
93 |
-
$product_plugins = $this->get_installed_plugins();
|
94 |
-
$product_slug = sanitize_text_field( $_GET['dismiss-wpjm-licence-notice'] );
|
95 |
-
if ( isset( $product_plugins[ $product_slug ] ) ) {
|
96 |
-
WP_Job_Manager_Helper_Options::update( $product_slug, 'hide_key_notice', true );
|
97 |
-
}
|
98 |
-
}
|
99 |
-
}
|
100 |
-
|
101 |
-
/**
|
102 |
-
* Tell the add-on when to check for and display and core WPJM version notices.
|
103 |
-
*
|
104 |
-
* @param bool $do_check True if the add-on should do a core version check.
|
105 |
-
* @param string $minimum_required_core_version Minimum version the plugin is reporting it requires.
|
106 |
-
* @return bool
|
107 |
-
*/
|
108 |
-
public function addon_core_version_check( $do_check, $minimum_required_core_version = null ) {
|
109 |
-
if ( ! is_admin() || ! did_action( 'admin_init' ) ) {
|
110 |
-
return false;
|
111 |
-
}
|
112 |
-
|
113 |
-
// We only want to show the notices on the plugins page and main job listing admin page.
|
114 |
-
$screen = get_current_screen();
|
115 |
-
if ( null === $screen || ! in_array( $screen->id, array( 'plugins', 'edit-job_listing' ), true ) ) {
|
116 |
-
return false;
|
117 |
-
}
|
118 |
-
|
119 |
-
$dev_version_loc = strpos( JOB_MANAGER_VERSION, '-dev' );
|
120 |
-
if (
|
121 |
-
false !== $dev_version_loc
|
122 |
-
&& substr( JOB_MANAGER_VERSION, 0, $dev_version_loc ) === $minimum_required_core_version
|
123 |
-
) {
|
124 |
-
return false;
|
125 |
-
}
|
126 |
-
|
127 |
-
return $do_check;
|
128 |
-
}
|
129 |
-
|
130 |
-
/**
|
131 |
-
* Check for licence managed WPJM addon plugin updates.
|
132 |
-
*
|
133 |
-
* @param array $check_for_updates_data
|
134 |
-
*
|
135 |
-
* @return array
|
136 |
-
*/
|
137 |
-
public function check_for_updates( $check_for_updates_data ) {
|
138 |
-
// Set version variables.
|
139 |
-
foreach ( $this->get_installed_plugins() as $product_slug => $plugin_data ) {
|
140 |
-
$response = $this->get_plugin_version( $plugin_data['_filename'] );
|
141 |
-
// If there is a new version, modify the transient to reflect an update is available.
|
142 |
-
if ( $response
|
143 |
-
&& isset( $response['new_version'] )
|
144 |
-
&& version_compare( $response['new_version'], $plugin_data['Version'], '>' )
|
145 |
-
) {
|
146 |
-
$check_for_updates_data->response[ $plugin_data['_filename'] ] = (object) $response;
|
147 |
-
}
|
148 |
-
}
|
149 |
-
return $check_for_updates_data;
|
150 |
-
}
|
151 |
-
|
152 |
-
/**
|
153 |
-
* Get plugin version info from API.
|
154 |
-
*
|
155 |
-
* @param string $plugin_filename
|
156 |
-
*
|
157 |
-
* @return array|bool
|
158 |
-
*/
|
159 |
-
private function get_plugin_version( $plugin_filename ) {
|
160 |
-
$plugin_data = $this->get_licence_managed_plugin( $plugin_filename );
|
161 |
-
if ( ! $plugin_data ) {
|
162 |
-
return false;
|
163 |
-
}
|
164 |
-
$product_slug = $plugin_data['_product_slug'];
|
165 |
-
$licence = $this->get_plugin_licence( $product_slug );
|
166 |
-
if ( ! $licence || empty( $licence['licence_key'] ) ) {
|
167 |
-
return false;
|
168 |
-
}
|
169 |
-
|
170 |
-
$response = $this->api->plugin_update_check(
|
171 |
-
array(
|
172 |
-
'plugin_name' => $plugin_data['Name'],
|
173 |
-
'version' => $plugin_data['Version'],
|
174 |
-
'api_product_id' => $product_slug,
|
175 |
-
'licence_key' => $licence['licence_key'],
|
176 |
-
'email' => $licence['email'],
|
177 |
-
)
|
178 |
-
);
|
179 |
-
|
180 |
-
$this->handle_api_errors( $product_slug, $response );
|
181 |
-
|
182 |
-
// Set version variables.
|
183 |
-
if ( ! empty( $response ) ) {
|
184 |
-
return $response;
|
185 |
-
}
|
186 |
-
|
187 |
-
return false;
|
188 |
-
}
|
189 |
-
|
190 |
-
/**
|
191 |
-
* Cleanup old things when WPJM licence managed plugin is activated.
|
192 |
-
*
|
193 |
-
* @param string $plugin_filename
|
194 |
-
*/
|
195 |
-
public function plugin_activated( $plugin_filename ) {
|
196 |
-
$plugins = $this->get_installed_plugins( false );
|
197 |
-
foreach ( $plugins as $product_slug => $plugin_data ) {
|
198 |
-
if ( $plugin_filename !== $plugin_data['_filename'] ) {
|
199 |
-
continue;
|
200 |
-
}
|
201 |
-
WP_Job_Manager_Helper_Options::delete( $product_slug, 'hide_key_notice' );
|
202 |
-
break;
|
203 |
-
}
|
204 |
-
}
|
205 |
-
|
206 |
-
/**
|
207 |
-
* Deactivate licence when WPJM licence managed plugin is deactivated.
|
208 |
-
*
|
209 |
-
* @param string $plugin_filename
|
210 |
-
*/
|
211 |
-
public function plugin_deactivated( $plugin_filename ) {
|
212 |
-
$plugins = $this->get_installed_plugins( false );
|
213 |
-
foreach ( $plugins as $product_slug => $plugin_data ) {
|
214 |
-
if ( $plugin_filename !== $plugin_data['_filename'] ) {
|
215 |
-
continue;
|
216 |
-
}
|
217 |
-
$this->deactivate_licence( $product_slug );
|
218 |
-
break;
|
219 |
-
}
|
220 |
-
}
|
221 |
-
|
222 |
-
/**
|
223 |
-
* Fetches the plugin information for WPJM plugins.
|
224 |
-
*
|
225 |
-
* @param false|object|array $response The result object or array. Default false.
|
226 |
-
* @param string $action The type of information being requested from the Plugin Install API.
|
227 |
-
* @param object $args Plugin API arguments.
|
228 |
-
*
|
229 |
-
* @return false|object|array
|
230 |
-
*/
|
231 |
-
public function plugins_api( $response, $action, $args ) {
|
232 |
-
if ( 'plugin_information' !== $action ) {
|
233 |
-
return $response;
|
234 |
-
}
|
235 |
-
|
236 |
-
if ( empty( $args->slug ) ) {
|
237 |
-
return $response;
|
238 |
-
}
|
239 |
-
|
240 |
-
$plugin_info = $this->get_plugin_info( $args->slug );
|
241 |
-
if ( $plugin_info ) {
|
242 |
-
$response = (object) $plugin_info;
|
243 |
-
}
|
244 |
-
|
245 |
-
return $response;
|
246 |
-
}
|
247 |
-
|
248 |
-
/**
|
249 |
-
* Appends links to manage plugin licence when managed.
|
250 |
-
*
|
251 |
-
* @param array $actions
|
252 |
-
* @param string $plugin_filename
|
253 |
-
* @return array
|
254 |
-
*/
|
255 |
-
public function plugin_links( $actions, $plugin_filename ) {
|
256 |
-
$plugin = $this->get_licence_managed_plugin( $plugin_filename );
|
257 |
-
if ( ! $plugin || ! current_user_can( 'update_plugins' ) ) {
|
258 |
-
return $actions;
|
259 |
-
}
|
260 |
-
$product_slug = $plugin['_product_slug'];
|
261 |
-
$licence = $this->get_plugin_licence( $product_slug );
|
262 |
-
$css_class = '';
|
263 |
-
if ( $licence && ! empty( $licence['licence_key'] ) ) {
|
264 |
-
if ( ! empty( $licence['errors'] ) ) {
|
265 |
-
$manage_licence_label = __( 'Manage License (Requires Attention)', 'wp-job-manager' );
|
266 |
-
$css_class = 'wpjm-activate-licence-link';
|
267 |
-
} else {
|
268 |
-
$manage_licence_label = __( 'Manage License', 'wp-job-manager' );
|
269 |
-
}
|
270 |
-
} else {
|
271 |
-
$manage_licence_label = __( 'Activate License', 'wp-job-manager' );
|
272 |
-
$css_class = 'wpjm-activate-licence-link';
|
273 |
-
}
|
274 |
-
$actions[] = '<a class="' . esc_attr( $css_class ) . '" href="' . esc_url( admin_url( 'edit.php?post_type=job_listing&page=job-manager-addons§ion=helper' ) ) . '">' . esc_html( $manage_licence_label ) . '</a>';
|
275 |
-
return $actions;
|
276 |
-
}
|
277 |
-
|
278 |
-
/**
|
279 |
-
* Returns the plugin info for a licensed WPJM plugin.
|
280 |
-
*
|
281 |
-
* @param string $product_slug
|
282 |
-
*
|
283 |
-
* @return bool|object
|
284 |
-
*/
|
285 |
-
protected function get_plugin_info( $product_slug ) {
|
286 |
-
if ( ! $this->is_product_installed( $product_slug ) ) {
|
287 |
-
return false;
|
288 |
-
}
|
289 |
-
$args = $this->get_plugin_licence( $product_slug );
|
290 |
-
if ( empty( $args['licence_key'] ) || empty( $args['email'] ) ) {
|
291 |
-
return false;
|
292 |
-
}
|
293 |
-
$args['api_product_id'] = $product_slug;
|
294 |
-
|
295 |
-
$response = $this->api->plugin_information( $args );
|
296 |
-
$this->handle_api_errors( $product_slug, $response );
|
297 |
-
|
298 |
-
return $response;
|
299 |
-
}
|
300 |
-
|
301 |
-
/**
|
302 |
-
* Checks if a WPJM plugin is installed.
|
303 |
-
*
|
304 |
-
* @param string $product_slug
|
305 |
-
*
|
306 |
-
* @return bool
|
307 |
-
*/
|
308 |
-
public function is_product_installed( $product_slug ) {
|
309 |
-
$product_plugins = $this->get_installed_plugins();
|
310 |
-
return isset( $product_plugins[ $product_slug ] );
|
311 |
-
}
|
312 |
-
|
313 |
-
/**
|
314 |
-
* Returns true if there are licensed products being managed.
|
315 |
-
*
|
316 |
-
* @return bool
|
317 |
-
*/
|
318 |
-
public function has_licenced_products() {
|
319 |
-
$product_plugins = $this->get_installed_plugins();
|
320 |
-
return ! empty( $product_plugins );
|
321 |
-
}
|
322 |
-
|
323 |
-
/**
|
324 |
-
* Returns the plugin data for plugin with a `WPJM-Product` tag by plugin filename.
|
325 |
-
*
|
326 |
-
* @param string $plugin_filename
|
327 |
-
* @return bool|array
|
328 |
-
*/
|
329 |
-
private function get_licence_managed_plugin( $plugin_filename ) {
|
330 |
-
foreach ( $this->get_installed_plugins() as $plugin ) {
|
331 |
-
if ( $plugin_filename === $plugin['_filename'] ) {
|
332 |
-
return $plugin;
|
333 |
-
}
|
334 |
-
}
|
335 |
-
return false;
|
336 |
-
}
|
337 |
-
|
338 |
-
/**
|
339 |
-
* Gets the license key and email for a WPJM managed plugin.
|
340 |
-
*
|
341 |
-
* @param string $product_slug
|
342 |
-
* @return array|bool
|
343 |
-
*/
|
344 |
-
public function get_plugin_licence( $product_slug ) {
|
345 |
-
$licence_key = WP_Job_Manager_Helper_Options::get( $product_slug, 'licence_key' );
|
346 |
-
$activation_email = WP_Job_Manager_Helper_Options::get( $product_slug, 'email' );
|
347 |
-
$errors = WP_Job_Manager_Helper_Options::get( $product_slug, 'errors' );
|
348 |
-
|
349 |
-
return array(
|
350 |
-
'licence_key' => $licence_key,
|
351 |
-
'email' => $activation_email,
|
352 |
-
'errors' => $errors,
|
353 |
-
);
|
354 |
-
}
|
355 |
-
|
356 |
-
/**
|
357 |
-
* Adds newly recognized data header in WordPress plugin files.
|
358 |
-
*
|
359 |
-
* @param array $headers
|
360 |
-
* @return array
|
361 |
-
*/
|
362 |
-
public function extra_headers( $headers ) {
|
363 |
-
$headers[] = 'WPJM-Product';
|
364 |
-
return $headers;
|
365 |
-
}
|
366 |
-
|
367 |
-
/**
|
368 |
-
* Returns list of installed WPJM plugins with managed licenses indexed by product ID.
|
369 |
-
*
|
370 |
-
* @param bool $active_only Only return active plugins.
|
371 |
-
* @return array
|
372 |
-
*/
|
373 |
-
protected function get_installed_plugins( $active_only = true ) {
|
374 |
-
if ( ! function_exists( 'get_plugins' ) ) {
|
375 |
-
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
376 |
-
}
|
377 |
-
|
378 |
-
/**
|
379 |
-
* Clear the plugin cache on first request for installed WPJM add-on plugins.
|
380 |
-
*
|
381 |
-
* @since 1.29.1
|
382 |
-
*
|
383 |
-
* @param bool $clear_plugin_cache True if we should clear the plugin cache.
|
384 |
-
*/
|
385 |
-
if ( ! self::$cleared_plugin_cache && apply_filters( 'job_manager_clear_plugin_cache', true ) ) {
|
386 |
-
// Reset the plugin cache on the first call. Some plugins prematurely hydrate the cache.
|
387 |
-
wp_clean_plugins_cache( false );
|
388 |
-
self::$cleared_plugin_cache = true;
|
389 |
-
}
|
390 |
-
|
391 |
-
$wpjm_plugins = array();
|
392 |
-
$plugins = get_plugins();
|
393 |
-
|
394 |
-
foreach ( $plugins as $filename => $data ) {
|
395 |
-
if ( empty( $data['WPJM-Product'] ) || ( true === $active_only && ! is_plugin_active( $filename ) ) ) {
|
396 |
-
continue;
|
397 |
-
}
|
398 |
-
|
399 |
-
$data['_filename'] = $filename;
|
400 |
-
$data['_product_slug'] = $data['WPJM-Product'];
|
401 |
-
$data['_type'] = 'plugin';
|
402 |
-
$wpjm_plugins[ $data['WPJM-Product'] ] = $data;
|
403 |
-
}
|
404 |
-
|
405 |
-
return $wpjm_plugins;
|
406 |
-
}
|
407 |
-
|
408 |
-
/**
|
409 |
-
* Outputs the license management.
|
410 |
-
*/
|
411 |
-
public function licence_output() {
|
412 |
-
if ( ! current_user_can( 'update_plugins' ) ) {
|
413 |
-
return;
|
414 |
-
}
|
415 |
-
if ( ! empty( $_POST ) ) {
|
416 |
-
$this->handle_request();
|
417 |
-
}
|
418 |
-
$licenced_plugins = $this->get_installed_plugins();
|
419 |
-
include_once dirname( __FILE__ ) . '/views/html-licences.php';
|
420 |
-
}
|
421 |
-
|
422 |
-
/**
|
423 |
-
* Outputs unset license key notices.
|
424 |
-
*/
|
425 |
-
public function licence_error_notices() {
|
426 |
-
$screen = get_current_screen();
|
427 |
-
if ( null === $screen || in_array( $screen->id, array( 'job_listing_page_job-manager-addons' ), true ) ) {
|
428 |
-
return;
|
429 |
-
}
|
430 |
-
foreach ( $this->get_installed_plugins() as $product_slug => $plugin_data ) {
|
431 |
-
$licence = $this->get_plugin_licence( $product_slug );
|
432 |
-
if ( ! WP_Job_Manager_Helper_Options::get( $product_slug, 'hide_key_notice' ) ) {
|
433 |
-
if ( empty( $licence['licence_key'] ) ) {
|
434 |
-
include 'views/html-licence-key-notice.php';
|
435 |
-
} elseif ( ! empty( $licence['errors'] ) ) {
|
436 |
-
include 'views/html-licence-key-error.php';
|
437 |
-
}
|
438 |
-
}
|
439 |
-
}
|
440 |
-
}
|
441 |
-
|
442 |
-
/**
|
443 |
-
* Handles a request on the manage license key screen.
|
444 |
-
*/
|
445 |
-
private function handle_request() {
|
446 |
-
$licenced_plugins = $this->get_installed_plugins();
|
447 |
-
if ( empty( $_POST )
|
448 |
-
|| empty( $_POST['_wpnonce'] )
|
449 |
-
|| empty( $_POST['action'] )
|
450 |
-
|| empty( $_POST['product_slug'] )
|
451 |
-
|| ! isset( $licenced_plugins[ $_POST['product_slug'] ] )
|
452 |
-
|| ! wp_verify_nonce( $_POST['_wpnonce'], 'wpjm-manage-licence' )
|
453 |
-
) {
|
454 |
-
return false;
|
455 |
-
}
|
456 |
-
$product_slug = sanitize_text_field( $_POST['product_slug'] );
|
457 |
-
switch ( $_POST['action'] ) {
|
458 |
-
case 'activate':
|
459 |
-
if ( empty( $_POST['email'] ) || empty( $_POST['licence_key'] ) ) {
|
460 |
-
$this->add_error( $product_slug, __( 'Please enter a valid license key and email address in order to activate this plugin\'s license.', 'wp-job-manager' ) );
|
461 |
-
break;
|
462 |
-
}
|
463 |
-
$email = sanitize_email( $_POST['email'] );
|
464 |
-
$licence_key = sanitize_text_field( $_POST['licence_key'] );
|
465 |
-
$this->activate_licence( $product_slug, $licence_key, $email );
|
466 |
-
break;
|
467 |
-
case 'deactivate':
|
468 |
-
$this->deactivate_licence( $product_slug );
|
469 |
-
break;
|
470 |
-
}
|
471 |
-
}
|
472 |
-
|
473 |
-
/**
|
474 |
-
* Activate a licence key for a WPJM add-on plugin.
|
475 |
-
*
|
476 |
-
* @param string $product_slug
|
477 |
-
* @param string $licence_key
|
478 |
-
* @param string $email
|
479 |
-
*/
|
480 |
-
private function activate_licence( $product_slug, $licence_key, $email ) {
|
481 |
-
$response = $this->api->activate(
|
482 |
-
array(
|
483 |
-
'api_product_id' => $product_slug,
|
484 |
-
'licence_key' => $licence_key,
|
485 |
-
'email' => $email,
|
486 |
-
)
|
487 |
-
);
|
488 |
-
|
489 |
-
if ( false === $response ) {
|
490 |
-
$this->add_error( $product_slug, __( 'Connection failed to the License Key API server - possible server issue.', 'wp-job-manager' ) );
|
491 |
-
} elseif ( isset( $response['error_code'] ) && isset( $response['error'] ) ) {
|
492 |
-
$this->add_error( $product_slug, $response['error'] );
|
493 |
-
} elseif ( ! empty( $response['activated'] ) ) {
|
494 |
-
WP_Job_Manager_Helper_Options::update( $product_slug, 'licence_key', $licence_key );
|
495 |
-
WP_Job_Manager_Helper_Options::update( $product_slug, 'email', $email );
|
496 |
-
WP_Job_Manager_Helper_Options::delete( $product_slug, 'errors' );
|
497 |
-
WP_Job_Manager_Helper_Options::delete( $product_slug, 'hide_key_notice' );
|
498 |
-
$this->add_success( $product_slug, __( 'Plugin license has been activated.', 'wp-job-manager' ) );
|
499 |
-
} else {
|
500 |
-
$this->add_error( $product_slug, __( 'An unknown error occurred while attempting to activate the license', 'wp-job-manager' ) );
|
501 |
-
}
|
502 |
-
}
|
503 |
-
|
504 |
-
/**
|
505 |
-
* Deactivate a licence key for a WPJM add-on plugin.
|
506 |
-
*
|
507 |
-
* @param string $product_slug
|
508 |
-
*/
|
509 |
-
private function deactivate_licence( $product_slug ) {
|
510 |
-
$licence = $this->get_plugin_licence( $product_slug );
|
511 |
-
if ( empty( $licence['licence_key'] ) || empty( $licence['email'] ) ) {
|
512 |
-
$this->add_error( $product_slug, __( 'license is not active.', 'wp-job-manager' ) );
|
513 |
-
return;
|
514 |
-
}
|
515 |
-
$this->api->deactivate(
|
516 |
-
array(
|
517 |
-
'api_product_id' => $product_slug,
|
518 |
-
'licence_key' => $licence['licence_key'],
|
519 |
-
'email' => $licence['email'],
|
520 |
-
)
|
521 |
-
);
|
522 |
-
|
523 |
-
WP_Job_Manager_Helper_Options::delete( $product_slug, 'licence_key' );
|
524 |
-
WP_Job_Manager_Helper_Options::delete( $product_slug, 'email' );
|
525 |
-
WP_Job_Manager_Helper_Options::delete( $product_slug, 'errors' );
|
526 |
-
WP_Job_Manager_Helper_Options::delete( $product_slug, 'hide_key_notice' );
|
527 |
-
delete_site_transient( 'update_plugins' );
|
528 |
-
$this->add_success( $product_slug, __( 'Plugin license has been deactivated.', 'wp-job-manager' ) );
|
529 |
-
}
|
530 |
-
|
531 |
-
/**
|
532 |
-
* Handle errors from the API.
|
533 |
-
*
|
534 |
-
* @param string $product_slug
|
535 |
-
* @param array $response
|
536 |
-
*/
|
537 |
-
private function handle_api_errors( $product_slug, $response ) {
|
538 |
-
$plugin_products = $this->get_installed_plugins();
|
539 |
-
if ( ! isset( $plugin_products[ $product_slug ] ) ) {
|
540 |
-
return;
|
541 |
-
}
|
542 |
-
|
543 |
-
$errors = ! empty( $response['errors'] ) ? $response['errors'] : array();
|
544 |
-
$allowed_errors = array( 'no_activation', 'expired_key', 'expiring_soon' );
|
545 |
-
$ignored_errors = array_diff( array_keys( $errors ), $allowed_errors );
|
546 |
-
|
547 |
-
foreach ( $ignored_errors as $key ) {
|
548 |
-
unset( $errors[ $key ] );
|
549 |
-
}
|
550 |
-
|
551 |
-
if ( ! empty( $errors['no_activation'] ) ) {
|
552 |
-
$this->deactivate_licence( $product_slug );
|
553 |
-
}
|
554 |
-
|
555 |
-
WP_Job_Manager_Helper_Options::update( $product_slug, 'errors', $errors );
|
556 |
-
}
|
557 |
-
|
558 |
-
/**
|
559 |
-
* Add an error message.
|
560 |
-
*
|
561 |
-
* @param string $product_slug The plugin slug.
|
562 |
-
* @param string $message Your error message.
|
563 |
-
*/
|
564 |
-
private function add_error( $product_slug, $message ) {
|
565 |
-
$this->add_message( 'error', $product_slug, $message );
|
566 |
-
}
|
567 |
-
|
568 |
-
/**
|
569 |
-
* Add a success message.
|
570 |
-
*
|
571 |
-
* @param string $product_slug The plugin slug.
|
572 |
-
* @param string $message Your error message.
|
573 |
-
*/
|
574 |
-
private function add_success( $product_slug, $message ) {
|
575 |
-
$this->add_message( 'success', $product_slug, $message );
|
576 |
-
}
|
577 |
-
|
578 |
-
/**
|
579 |
-
* Add a message.
|
580 |
-
*
|
581 |
-
* @param string $type Message type.
|
582 |
-
* @param string $product_slug The plugin slug.
|
583 |
-
* @param string $message Your error message.
|
584 |
-
*/
|
585 |
-
private function add_message( $type, $product_slug, $message ) {
|
586 |
-
if ( ! isset( $this->licence_messages[ $product_slug ] ) ) {
|
587 |
-
$this->licence_messages[ $product_slug ] = array();
|
588 |
-
}
|
589 |
-
$this->licence_messages[ $product_slug ][] = array(
|
590 |
-
'type' => $type,
|
591 |
-
'message' => $message,
|
592 |
-
);
|
593 |
-
}
|
594 |
-
|
595 |
-
/**
|
596 |
-
* Get a plugin's licence messages.
|
597 |
-
*
|
598 |
-
* @param string $product_slug The plugin slug.
|
599 |
-
* @return array
|
600 |
-
*/
|
601 |
-
public function get_messages( $product_slug ) {
|
602 |
-
if ( ! isset( $this->licence_messages[ $product_slug ] ) ) {
|
603 |
-
$this->licence_messages[ $product_slug ] = array();
|
604 |
-
}
|
605 |
-
return $this->licence_messages[ $product_slug ];
|
606 |
-
}
|
607 |
-
}
|
608 |
-
|
609 |
-
WP_Job_Manager_Helper::instance()->init();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/helper/views/html-licence-key-error.php
DELETED
@@ -1,9 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
-
exit; // Exit if accessed directly.
|
4 |
-
}
|
5 |
-
?>
|
6 |
-
<div class="error">
|
7 |
-
<p class="wpjm-updater-dismiss" style="float:right;"><a href="<?php echo esc_url( add_query_arg( 'dismiss-wpjm-licence-notice', $product_slug ) ); ?>"><?php esc_html_e( 'Hide notice', 'wp-job-manager' ); ?></a></p>
|
8 |
-
<p><?php printf( 'There is a problem with the license for "%s". Please <a href="%s">manage the license</a> to check for a solution and continue receiving updates.', esc_html( $plugin_data['Name'] ), esc_url( admin_url( 'edit.php?post_type=job_listing&page=job-manager-addons§ion=helper#' . sanitize_title( $product_slug . '_row' ) ) ) ); ?></p>
|
9 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/helper/views/html-licence-key-notice.php
DELETED
@@ -1,9 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
-
exit; // Exit if accessed directly.
|
4 |
-
}
|
5 |
-
?>
|
6 |
-
<div class="updated">
|
7 |
-
<p class="wpjm-updater-dismiss" style="float:right;"><a href="<?php echo esc_url( add_query_arg( 'dismiss-wpjm-licence-notice', $product_slug ) ); ?>"><?php esc_html_e( 'Hide notice', 'wp-job-manager' ); ?></a></p>
|
8 |
-
<p><?php printf( '<a href="%s">Please enter your license key</a> to get updates for "%s".', esc_url( admin_url( 'edit.php?post_type=job_listing&page=job-manager-addons§ion=helper#' . sanitize_title( $product_slug . '_row' ) ) ), esc_html( $plugin_data['Name'] ) ); ?></p>
|
9 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/helper/views/html-licences.php
DELETED
@@ -1,81 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
-
exit; // Exit if accessed directly.
|
4 |
-
}
|
5 |
-
?>
|
6 |
-
<h1 class="screen-reader-text"><?php esc_html_e( 'Licenses', 'wp-job-manager' ); ?></h1>
|
7 |
-
<div class="wpjm-licences">
|
8 |
-
<?php if ( ! empty( $licenced_plugins ) ) : ?>
|
9 |
-
<?php foreach ( $licenced_plugins as $product_slug => $plugin_data ) : ?>
|
10 |
-
<?php
|
11 |
-
$licence = WP_Job_Manager_Helper::get_plugin_licence( $product_slug );
|
12 |
-
?>
|
13 |
-
<div class="licence-row">
|
14 |
-
<div class="plugin-info">
|
15 |
-
<?php echo esc_html( $plugin_data['Name'] ); ?>
|
16 |
-
<div class="plugin-author">
|
17 |
-
<?php
|
18 |
-
$author = $plugin_data['Author'];
|
19 |
-
if ( ! empty( $plugin_data['AuthorURI'] ) ) {
|
20 |
-
$author = '<a href="' . esc_url( $plugin_data['AuthorURI'] ) . '">' . wp_kses_post( $plugin_data['Author'] ) . '</a>';
|
21 |
-
}
|
22 |
-
echo wp_kses_post( $author );
|
23 |
-
?>
|
24 |
-
</div>
|
25 |
-
</div>
|
26 |
-
<div class="plugin-licence">
|
27 |
-
<?php
|
28 |
-
$notices = WP_Job_Manager_Helper::get_messages( $product_slug );
|
29 |
-
if ( empty( $notices ) && ! empty( $licence['errors'] ) ) {
|
30 |
-
$notices = array();
|
31 |
-
foreach ( $licence['errors'] as $key => $error ) {
|
32 |
-
$notices[] = array(
|
33 |
-
'type' => 'error',
|
34 |
-
'message' => $error,
|
35 |
-
);
|
36 |
-
}
|
37 |
-
}
|
38 |
-
foreach ( $notices as $message ) {
|
39 |
-
echo '<div class="notice inline notice-' . esc_attr( $message['type'] ) . '"><p>' . wp_kses_post( $message['message'] ) . '</p></div>';
|
40 |
-
}
|
41 |
-
?>
|
42 |
-
<form method="post">
|
43 |
-
<?php wp_nonce_field( 'wpjm-manage-licence' ); ?>
|
44 |
-
<?php
|
45 |
-
if ( ! empty( $licence['licence_key'] ) && ! empty( $licence['email'] ) ) {
|
46 |
-
?>
|
47 |
-
<input type="hidden" id="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_action" name="action" value="deactivate"/>
|
48 |
-
<input type="hidden" id="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_plugin" name="product_slug" value="<?php echo esc_attr( $product_slug ); ?>"/>
|
49 |
-
|
50 |
-
<label for="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_licence_key"><?php esc_html_e( 'License', 'wp-job-manager' ); ?>:
|
51 |
-
<input type="text" disabled="disabled" id="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_licence_key" name="licence_key" placeholder="XXXX-XXXX-XXXX-XXXX" value="<?php echo esc_attr( $licence['licence_key'] ); ?>"/>
|
52 |
-
</label>
|
53 |
-
<label for="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_email"><?php esc_html_e( 'Email', 'wp-job-manager' ); ?>:
|
54 |
-
<input type="email" disabled="disabled" id="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_email" name="email" placeholder="Email address" value="<?php echo esc_attr( $licence['email'] ); ?>"/>
|
55 |
-
</label>
|
56 |
-
|
57 |
-
<input type="submit" class="button" name="submit" value="<?php esc_attr_e( 'Deactivate License', 'wp-job-manager' ); ?>" />
|
58 |
-
<?php
|
59 |
-
} else { // licence is not active.
|
60 |
-
?>
|
61 |
-
<input type="hidden" id="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_action" name="action" value="activate"/>
|
62 |
-
<input type="hidden" id="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_plugin" name="product_slug" value="<?php echo esc_attr( $product_slug ); ?>"/>
|
63 |
-
<label for="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_licence_key"><?php esc_html_e( 'License', 'wp-job-manager' ); ?>:
|
64 |
-
<input type="text" id="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_licence_key" name="licence_key" placeholder="XXXX-XXXX-XXXX-XXXX"/>
|
65 |
-
</label>
|
66 |
-
<label for="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_email"><?php esc_html_e( 'Email', 'wp-job-manager' ); ?>:
|
67 |
-
<input type="email" id="<?php echo esc_attr( sanitize_title( $product_slug ) ); ?>_email" name="email" placeholder="Email address" value="<?php echo esc_attr( get_option( 'admin_email' ) ); ?>"/>
|
68 |
-
</label>
|
69 |
-
<input type="submit" class="button" name="submit" value="<?php esc_attr_e( 'Activate License', 'wp-job-manager' ); ?>" />
|
70 |
-
<?php
|
71 |
-
} // end if : else licence is not active.
|
72 |
-
?>
|
73 |
-
</form>
|
74 |
-
</div>
|
75 |
-
</div>
|
76 |
-
<?php endforeach; ?>
|
77 |
-
<div class="notice notice-info inline"><p><?php printf( 'Lost your license key? <a href="%s">Retrieve it here</a>.', 'https://wpjobmanager.com/lost-licence-key/' ); ?></p></div>
|
78 |
-
<?php else : ?>
|
79 |
-
<div class="notice notice-warning inline"><p><?php esc_html_e( 'No plugins are activated that have licenses managed by WP Job Manager.', 'wp-job-manager' ); ?></p></div>
|
80 |
-
<?php endif; ?>
|
81 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-controllers-status.php
DELETED
@@ -1,132 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Declaration of our Status Model
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_Controllers_Status
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_Controllers_Status extends WP_Job_Manager_REST_Controller_Model
|
16 |
-
implements WP_Job_Manager_REST_Interfaces_Controller {
|
17 |
-
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Setup
|
21 |
-
*/
|
22 |
-
public function setup() {
|
23 |
-
$this->add_route( '/' )
|
24 |
-
->add_action( $this->action( 'index', 'index' ) );
|
25 |
-
|
26 |
-
$this->add_route( '/(?P<key>[a-zA-Z_]+)' )
|
27 |
-
->add_action( $this->action( 'show', 'show' ) )
|
28 |
-
->add_action( $this->action( 'update', 'update' ) );
|
29 |
-
}
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Index handler
|
33 |
-
*
|
34 |
-
* @param WP_REST_Request $request The request.
|
35 |
-
*
|
36 |
-
* @return WP_REST_Response
|
37 |
-
* @throws WP_Job_Manager_REST_Exception Thrown during error while processing of request.
|
38 |
-
*/
|
39 |
-
public function index( $request ) {
|
40 |
-
$params = $request->get_params();
|
41 |
-
$filter = $this->environment()
|
42 |
-
->model( 'WP_Job_Manager_Filters_Status' )
|
43 |
-
->new_from_array( $params );
|
44 |
-
|
45 |
-
if ( is_wp_error( $filter ) ) {
|
46 |
-
return $this->bad_request( $filter );
|
47 |
-
}
|
48 |
-
|
49 |
-
$configuration = $this->get_model_prototype()
|
50 |
-
->get_data_store()
|
51 |
-
->get_entity( null );
|
52 |
-
|
53 |
-
if ( empty( $configuration ) ) {
|
54 |
-
return $this->not_found( __( 'Not Found', 'wp-job-manager' ) );
|
55 |
-
}
|
56 |
-
|
57 |
-
$dto = $this->prepare_dto( $configuration );
|
58 |
-
$keys = $filter->get( 'keys' );
|
59 |
-
if ( empty( $keys ) ) {
|
60 |
-
return $this->ok( $dto );
|
61 |
-
}
|
62 |
-
|
63 |
-
$filtered_params = array();
|
64 |
-
foreach ( $keys as $key ) {
|
65 |
-
if ( isset( $params[ $key ] ) ) {
|
66 |
-
$filtered_params[ $key ] = $params[ $key ];
|
67 |
-
}
|
68 |
-
}
|
69 |
-
return $this->ok( $filtered_params );
|
70 |
-
}
|
71 |
-
|
72 |
-
/**
|
73 |
-
* Show handler
|
74 |
-
*
|
75 |
-
* @param WP_REST_Request $request The request.
|
76 |
-
* @return WP_REST_Response
|
77 |
-
*/
|
78 |
-
public function show( $request ) {
|
79 |
-
$key = $request->get_param( 'key' );
|
80 |
-
$configuration = $this->get_model_prototype()
|
81 |
-
->get_data_store()
|
82 |
-
->get_entity( null );
|
83 |
-
|
84 |
-
if ( ! $configuration->has( $key ) ) {
|
85 |
-
return $this->not_found( 'Invalid key: ' . $key );
|
86 |
-
}
|
87 |
-
|
88 |
-
return $configuration->get( $key );
|
89 |
-
}
|
90 |
-
|
91 |
-
/**
|
92 |
-
* Update handler
|
93 |
-
*
|
94 |
-
* @param WP_REST_Request $request The request.
|
95 |
-
* @return WP_REST_Response
|
96 |
-
*/
|
97 |
-
public function update( $request ) {
|
98 |
-
$key = $request->get_param( 'key' );
|
99 |
-
$value = $request->get_param( 'value' );
|
100 |
-
if ( ! isset( $value ) ) {
|
101 |
-
if ( ! function_exists( 'json_decode' ) ) {
|
102 |
-
include_once ABSPATH . WPINC . 'compat.php';
|
103 |
-
}
|
104 |
-
$body = $request->get_body();
|
105 |
-
$value = json_decode( $body, true );
|
106 |
-
}
|
107 |
-
$thing_to_update = array(
|
108 |
-
$key => $value,
|
109 |
-
);
|
110 |
-
|
111 |
-
$configuration = $this->get_model_prototype()
|
112 |
-
->get_data_store()
|
113 |
-
->get_entity( '' );
|
114 |
-
$configuration->update_from_array( $thing_to_update );
|
115 |
-
$result = $this->get_model_prototype()
|
116 |
-
->get_data_store()
|
117 |
-
->upsert( $configuration );
|
118 |
-
|
119 |
-
if ( is_wp_error( $result ) ) {
|
120 |
-
return $this->respond( $result, 500 );
|
121 |
-
}
|
122 |
-
|
123 |
-
$dto = $this->prepare_dto( $configuration );
|
124 |
-
|
125 |
-
if ( WP_REST_Server::CREATABLE === $request->get_method() ) {
|
126 |
-
return $this->created( $dto );
|
127 |
-
}
|
128 |
-
|
129 |
-
return $this->ok( $dto );
|
130 |
-
}
|
131 |
-
}
|
132 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-data-stores-status.php
DELETED
@@ -1,72 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Declaration of our Status Data Store
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_Data_Stores_Status
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_Data_Stores_Status extends WP_Job_Manager_REST_Data_Store_Abstract
|
16 |
-
implements WP_Job_Manager_REST_Interfaces_Data_Store {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Get all the models (taking into account any filtering)
|
20 |
-
*
|
21 |
-
* @param WP_Job_Manager_REST_Interfaces_Model|null $filter A filter.
|
22 |
-
* @return WP_Job_Manager_REST_Model_Collection
|
23 |
-
* @throws WP_Job_Manager_REST_Exception Thrown during error while processing of request.
|
24 |
-
*/
|
25 |
-
public function get_entities( $filter = null ) {
|
26 |
-
return new WP_Job_Manager_REST_Model_Collection( array( $this->get_entity( null ) ) );
|
27 |
-
}
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Get a Model Using it's unique identifier
|
31 |
-
*
|
32 |
-
* @param mixed $id The id of the entity.
|
33 |
-
*
|
34 |
-
* @return WP_Job_Manager_REST_Interfaces_Model
|
35 |
-
* @throws WP_Job_Manager_REST_Exception Thrown during error while processing of request.
|
36 |
-
*/
|
37 |
-
public function get_entity( $id ) {
|
38 |
-
$should_run_page_setup = (bool) get_transient( '_job_manager_activation_redirect' );
|
39 |
-
$params = array(
|
40 |
-
'run_page_setup' => $should_run_page_setup,
|
41 |
-
);
|
42 |
-
return $this->get_model_prototype()->create( $params );
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Delete a Model
|
47 |
-
*
|
48 |
-
* @param WP_Job_Manager_REST_Interfaces_Model $model The model to delete.
|
49 |
-
* @param array $args Args.
|
50 |
-
* @return mixed
|
51 |
-
*/
|
52 |
-
public function delete( $model, $args = array() ) {
|
53 |
-
return true;
|
54 |
-
}
|
55 |
-
|
56 |
-
/**
|
57 |
-
* Update/Insert Model
|
58 |
-
*
|
59 |
-
* @param WP_Job_Manager_REST_Interfaces_Model $model The model.
|
60 |
-
* @return mixed
|
61 |
-
*/
|
62 |
-
public function upsert( $model ) {
|
63 |
-
$run_page_setup_val = $model->get( 'run_page_setup' );
|
64 |
-
if ( $run_page_setup_val ) {
|
65 |
-
set_transient( '_job_manager_activation_redirect', 1, HOUR_IN_SECONDS );
|
66 |
-
} else {
|
67 |
-
delete_transient( '_job_manager_activation_redirect' );
|
68 |
-
}
|
69 |
-
return true;
|
70 |
-
}
|
71 |
-
}
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-filters-status.php
DELETED
@@ -1,46 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Declaration of our Status Filters (will be used in GET requests)
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_Filters_Status
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_Filters_Status extends WP_Job_Manager_REST_Model {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Declare our fields
|
19 |
-
*
|
20 |
-
* @return array
|
21 |
-
* @throws WP_Job_Manager_REST_Exception Exc.
|
22 |
-
*/
|
23 |
-
public function declare_fields() {
|
24 |
-
$env = $this->get_environment();
|
25 |
-
return array(
|
26 |
-
$env->field( 'keys', 'The status keys to return' )
|
27 |
-
->with_type( $env->type( 'array:string' ) )
|
28 |
-
->with_before_set( 'explode_keys' )
|
29 |
-
->with_default( array() ),
|
30 |
-
);
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Explode keys
|
35 |
-
*
|
36 |
-
* @param mixed $keys The keys.
|
37 |
-
* @return array
|
38 |
-
*/
|
39 |
-
public function explode_keys( $keys ) {
|
40 |
-
if ( is_string( $keys ) ) {
|
41 |
-
return explode( ',', $keys );
|
42 |
-
}
|
43 |
-
return $keys;
|
44 |
-
}
|
45 |
-
}
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-models-job-categories-custom-fields.php
DELETED
@@ -1,26 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Declaration of Job Categories Custom Fields Model
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_Models_Job_Categories_Custom_Fields
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_Models_Job_Categories_Custom_Fields extends WP_Job_Manager_REST_Model
|
16 |
-
implements WP_Job_Manager_REST_Interfaces_Model {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Declare Fields.
|
20 |
-
*
|
21 |
-
* @return array
|
22 |
-
*/
|
23 |
-
public function declare_fields() {
|
24 |
-
return array();
|
25 |
-
}
|
26 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php
DELETED
@@ -1,104 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Declaration of our Job Listings Custom Fields Model
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_Models_Job_Listings_Custom_Fields
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_Models_Job_Listings_Custom_Fields extends WP_Job_Manager_REST_Model {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Declare Fields
|
19 |
-
*
|
20 |
-
* @return array
|
21 |
-
* @throws WP_Job_Manager_REST_Exception Exc.
|
22 |
-
*/
|
23 |
-
public function declare_fields() {
|
24 |
-
$env = $this->get_environment();
|
25 |
-
$current_user = wp_get_current_user();
|
26 |
-
|
27 |
-
$declarations = array(
|
28 |
-
$env->field( '_job_location', __( 'Leave this blank if the location is not important.', 'wp-job-manager' ) )
|
29 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
|
30 |
-
->with_type( $env->type( 'string' ) ),
|
31 |
-
|
32 |
-
$env->field( '_application', __( 'Application Email or URL', 'wp-job-manager' ) )
|
33 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
|
34 |
-
->with_default( $current_user->user_email )
|
35 |
-
->with_type( $env->type( 'string' ) ),
|
36 |
-
|
37 |
-
$env->field( '_company_name', __( 'Company Name', 'wp-job-manager' ) )
|
38 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
|
39 |
-
->with_type( $env->type( 'string' ) ),
|
40 |
-
|
41 |
-
$env->field( '_company_website', __( 'Company Website', 'wp-job-manager' ) )
|
42 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
|
43 |
-
->with_type( $env->type( 'string' ) ),
|
44 |
-
|
45 |
-
$env->field( '_company_tagline', __( 'Company Tagline', 'wp-job-manager' ) )
|
46 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
|
47 |
-
->with_type( $env->type( 'string' ) ),
|
48 |
-
|
49 |
-
$env->field( '_company_twitter', __( 'Company Twitter', 'wp-job-manager' ) )
|
50 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
|
51 |
-
->with_type( $env->type( 'string' ) ),
|
52 |
-
|
53 |
-
$env->field( '_company_video', __( 'Company Video', 'wp-job-manager' ) )
|
54 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
|
55 |
-
->with_type( $env->type( 'string' ) ),
|
56 |
-
|
57 |
-
$env->field( '_filled', __( 'Position Filled', 'wp-job-manager' ) )
|
58 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
|
59 |
-
->with_type( $env->type( 'boolean' ) ),
|
60 |
-
);
|
61 |
-
|
62 |
-
// These caps are more related to updating.
|
63 |
-
if ( $current_user->has_cap( 'manage_job_listings' ) ) {
|
64 |
-
$declarations[] = $env->field( '_featured', __( 'Featured Listing', 'wp-job-manager' ) )
|
65 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
|
66 |
-
->with_type( $env->type( 'boolean' ) );
|
67 |
-
|
68 |
-
$declarations[] = $env->field( '_job_expires', __( 'Listing Expiry Date', 'wp-job-manager' ) )
|
69 |
-
->with_type( $env->type( 'string' ) )
|
70 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
|
71 |
-
->with_before_get( 'format_job_expires' );
|
72 |
-
}
|
73 |
-
|
74 |
-
if ( $current_user->has_cap( 'edit_others_job_listings' ) ) {
|
75 |
-
$declarations[] = $env->field( '_job_author', __( 'Posted by', 'wp-job-manager' ) )
|
76 |
-
->with_type( $env->type( 'string' ) )
|
77 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META );
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
* Exposed so extension developers can add their custom fields.
|
82 |
-
*
|
83 |
-
* If the fields map to meta, you can follow the
|
84 |
-
* Example of the above declarations to shape s your own (remember to add any validation or formatting callbacks).
|
85 |
-
* For more constom things, you might want to check out Derived fields.
|
86 |
-
*
|
87 |
-
* @param array $declarations The Declarations so far.
|
88 |
-
* @param WP_Job_Manager_REST_Environment $env Environment.
|
89 |
-
*
|
90 |
-
* @return array
|
91 |
-
*/
|
92 |
-
return (array) apply_filters( 'wpjm_rest_api_job_listings_declare_fields', $declarations, $env );
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* Format the date of Job_Expires
|
97 |
-
*
|
98 |
-
* @param mixed $value Value.
|
99 |
-
* @return bool|string
|
100 |
-
*/
|
101 |
-
public function format_job_expires( $value ) {
|
102 |
-
return ! empty( $value ) ? date( 'Y-m-d H:i:s', strtotime( $value ) ) : '';
|
103 |
-
}
|
104 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-models-job-types-custom-fields.php
DELETED
@@ -1,64 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Declaration of Job Types Custom Fields Model
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_Models_Job_Types_Custom_Fields
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_Models_Job_Types_Custom_Fields extends WP_Job_Manager_REST_Model
|
16 |
-
implements WP_Job_Manager_REST_Interfaces_Model {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Accepted employment types
|
20 |
-
*
|
21 |
-
* @var array
|
22 |
-
*/
|
23 |
-
private static $accepted_employment_types = array();
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Declare Fields
|
27 |
-
*
|
28 |
-
* @return array
|
29 |
-
* @throws WP_Job_Manager_REST_Exception Thrown during error while processing of request.
|
30 |
-
*/
|
31 |
-
public function declare_fields() {
|
32 |
-
$env = $this->get_environment();
|
33 |
-
$employment_types = wpjm_job_listing_employment_type_options();
|
34 |
-
self::$accepted_employment_types = array_keys( $employment_types );
|
35 |
-
return array(
|
36 |
-
$env->field( 'employment_type', esc_html__( 'Employment Type', 'wp-job-manager' ) )
|
37 |
-
->with_kind( WP_Job_Manager_REST_Field_Declaration::META )
|
38 |
-
->with_type( $env->type( 'string' ) )
|
39 |
-
->with_choices( self::$accepted_employment_types ),
|
40 |
-
);
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Validate this
|
45 |
-
*
|
46 |
-
* @return bool|WP_Error
|
47 |
-
* @throws WP_Job_Manager_REST_Exception Thrown during error while processing of request.
|
48 |
-
*/
|
49 |
-
public function validate() {
|
50 |
-
$employment_type = $this->get( 'employment_type' );
|
51 |
-
if ( ! empty( $employment_type ) && ! in_array( $employment_type, self::$accepted_employment_types, true ) ) {
|
52 |
-
return new WP_Error(
|
53 |
-
'invalid_employment_type',
|
54 |
-
esc_html__( 'Invalid Employment Type', 'wp-job-manager' ),
|
55 |
-
array(
|
56 |
-
'input' => $employment_type,
|
57 |
-
'acceptable_values' => self::$accepted_employment_types,
|
58 |
-
'status' => 400,
|
59 |
-
)
|
60 |
-
);
|
61 |
-
}
|
62 |
-
return parent::validate();
|
63 |
-
}
|
64 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-models-settings.php
DELETED
@@ -1,109 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Declaration of our Settings Model
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_Models_Settings
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_Models_Settings extends WP_Job_Manager_REST_Model_Settings
|
16 |
-
implements WP_Job_Manager_REST_Interfaces_Permissions_Provider {
|
17 |
-
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Fields that have to be valid page ids.
|
21 |
-
*
|
22 |
-
* @var array|null
|
23 |
-
*/
|
24 |
-
private static $fields_requiring_page_id_validation = null;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Get Job Manager Settings
|
28 |
-
*
|
29 |
-
* @return array
|
30 |
-
*/
|
31 |
-
public function get_settings() {
|
32 |
-
if ( ! class_exists( 'WP_Job_Manager_Settings' ) ) {
|
33 |
-
$parent = dirname( dirname( __FILE__ ) );
|
34 |
-
if ( ! function_exists( 'get_editable_roles' ) ) {
|
35 |
-
// WP_Job_Manager_Settings needs this for user roles.
|
36 |
-
include_once ABSPATH . 'wp-admin/includes/user.php';
|
37 |
-
}
|
38 |
-
include_once $parent . '/admin/class-wp-job-manager-settings.php';
|
39 |
-
}
|
40 |
-
|
41 |
-
return WP_Job_Manager_Settings::instance()->get_settings();
|
42 |
-
}
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Adds validations to fields requiring page ids.
|
46 |
-
*
|
47 |
-
* @param string $field_name The fields name.
|
48 |
-
* @param WP_Job_Manager_REST_Field_Declaration_Builder $field_builder The field builder.
|
49 |
-
* @param array $field_data The field data.
|
50 |
-
* @param WP_Job_Manager_REST_Environment $env The definition.
|
51 |
-
*
|
52 |
-
* @throws WP_Job_Manager_REST_Exception Thrown during error while processing of request.
|
53 |
-
*/
|
54 |
-
protected function on_field_setup( $field_name, $field_builder, $field_data, $env ) {
|
55 |
-
if ( in_array( $field_name, self::get_fields_requiring_page_id_validation(), true ) ) {
|
56 |
-
$field_builder->with_type( $env->type( 'integer' ) )
|
57 |
-
->with_validations( 'validate_page_id_belongs_to_valid_page' );
|
58 |
-
}
|
59 |
-
}
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Validates that a page_id points to a valid page.
|
63 |
-
*
|
64 |
-
* @param int $id The id.
|
65 |
-
* @return bool|WP_Error
|
66 |
-
*/
|
67 |
-
public function validate_page_id_belongs_to_valid_page( $id ) {
|
68 |
-
$content = get_post( $id );
|
69 |
-
|
70 |
-
if ( ! empty( $content ) && 'page' === $content->post_type ) {
|
71 |
-
return true;
|
72 |
-
}
|
73 |
-
|
74 |
-
return new WP_Error( 'invalid-page-id', __( 'Invalid page ID provided', 'wp-job-manager' ) );
|
75 |
-
}
|
76 |
-
|
77 |
-
/**
|
78 |
-
* Permissions for accessing Settings.
|
79 |
-
*
|
80 |
-
* @param WP_REST_Request $request The request.
|
81 |
-
* @param string $action The action.
|
82 |
-
*
|
83 |
-
* @return bool
|
84 |
-
*/
|
85 |
-
public function permissions_check( $request, $action ) {
|
86 |
-
return current_user_can( 'manage_options' );
|
87 |
-
}
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Lazy-load field names requiring Page ID Validation.
|
91 |
-
*
|
92 |
-
* @return array
|
93 |
-
*/
|
94 |
-
private function get_fields_requiring_page_id_validation() {
|
95 |
-
if ( null === self::$fields_requiring_page_id_validation ) {
|
96 |
-
self::$fields_requiring_page_id_validation = (array) apply_filters(
|
97 |
-
'wpjm_rest_api_settings_fields_requiring_page_id_validation',
|
98 |
-
array(
|
99 |
-
'job_manager_submit_job_form_page_id',
|
100 |
-
'job_manager_job_dashboard_page_id',
|
101 |
-
'job_manager_jobs_page_id',
|
102 |
-
)
|
103 |
-
);
|
104 |
-
}
|
105 |
-
|
106 |
-
return self::$fields_requiring_page_id_validation;
|
107 |
-
}
|
108 |
-
}
|
109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-models-status.php
DELETED
@@ -1,50 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Declaration of our Status Model
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_Models_Status
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_Models_Status extends WP_Job_Manager_REST_Model
|
16 |
-
implements WP_Job_Manager_REST_Interfaces_Permissions_Provider {
|
17 |
-
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Declare our fields
|
21 |
-
*
|
22 |
-
* @return array
|
23 |
-
* @throws WP_Job_Manager_REST_Exception Exc.
|
24 |
-
*/
|
25 |
-
public function declare_fields() {
|
26 |
-
$env = $this->get_environment();
|
27 |
-
return array(
|
28 |
-
$env->field( 'run_page_setup', 'Should we run page setup' )
|
29 |
-
->with_type( $env->type( 'boolean' ) ),
|
30 |
-
);
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Handle Permissions for a REST Controller Action
|
35 |
-
*
|
36 |
-
* @param WP_REST_Request $request The request.
|
37 |
-
* @param string $action The action (e.g. index, create update etc).
|
38 |
-
* @return bool
|
39 |
-
*/
|
40 |
-
public function permissions_check( $request, $action ) {
|
41 |
-
if ( ! is_user_logged_in() ) {
|
42 |
-
return false;
|
43 |
-
}
|
44 |
-
if ( in_array( $action, array( 'index', 'show' ), true ) ) {
|
45 |
-
return current_user_can( 'manage_job_listings' );
|
46 |
-
}
|
47 |
-
return current_user_can( 'manage_options' );
|
48 |
-
}
|
49 |
-
}
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-registrable-job-categories.php
DELETED
@@ -1,42 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Exposes Job Categories Taxonomy REST Api
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_Registrable_Job_Categories
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_Registrable_Job_Categories extends WP_Job_Manager_Registrable_Taxonomy_Type {
|
16 |
-
/**
|
17 |
-
* Gets the taxonomy type to register.
|
18 |
-
*
|
19 |
-
* @return string Taxonomy type to expose.
|
20 |
-
*/
|
21 |
-
public function get_taxonomy_type() {
|
22 |
-
return 'job_listing_category';
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Gets the REST API base slug.
|
27 |
-
*
|
28 |
-
* @return string Slug for REST API base.
|
29 |
-
*/
|
30 |
-
public function get_rest_base() {
|
31 |
-
return 'job-categories';
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Gets the REST API model class name.
|
36 |
-
*
|
37 |
-
* @return string Class name for the taxonomy type's model.
|
38 |
-
*/
|
39 |
-
public function get_model_class_name() {
|
40 |
-
return 'WP_Job_Manager_Models_Job_Categories_Custom_Fields';
|
41 |
-
}
|
42 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-registrable-job-listings.php
DELETED
@@ -1,238 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Used for RESTifying the job_listing post type
|
4 |
-
*
|
5 |
-
* Adds custom fields. Needs a model definition that will provide the extra fields.
|
6 |
-
*
|
7 |
-
* @package WPJM/REST
|
8 |
-
*/
|
9 |
-
|
10 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
-
exit;
|
12 |
-
}
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Class MT_Controller_Extension
|
16 |
-
*/
|
17 |
-
class WP_Job_Manager_Registrable_Job_Listings implements WP_Job_Manager_REST_Interfaces_Registrable {
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Environment
|
21 |
-
*
|
22 |
-
* @var WP_Job_Manager_REST_Environment
|
23 |
-
*/
|
24 |
-
private $environment;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Object to extend
|
28 |
-
*
|
29 |
-
* @var string
|
30 |
-
*/
|
31 |
-
private $object_to_extend;
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Model def.
|
35 |
-
*
|
36 |
-
* @var WP_Job_Manager_REST_Model_Factory
|
37 |
-
*/
|
38 |
-
private $model_factory;
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Model Definition name, This should be a valid Model definition at registration time, otherwise register throws
|
42 |
-
*
|
43 |
-
* @var string
|
44 |
-
*/
|
45 |
-
private $model_class;
|
46 |
-
|
47 |
-
/**
|
48 |
-
* REST Field name, the field name we will nest under
|
49 |
-
*
|
50 |
-
* @var string
|
51 |
-
*/
|
52 |
-
private $rest_field_name;
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Constructor.
|
56 |
-
*
|
57 |
-
* @param string $object_to_extend Post type.
|
58 |
-
* @param string $model_class Model Class name.
|
59 |
-
* @param string $rest_field_name The REST field name.
|
60 |
-
*/
|
61 |
-
public function __construct( $object_to_extend, $model_class, $rest_field_name ) {
|
62 |
-
$this->model_class = $model_class;
|
63 |
-
$this->object_to_extend = $object_to_extend;
|
64 |
-
$this->rest_field_name = $rest_field_name;
|
65 |
-
}
|
66 |
-
|
67 |
-
/**
|
68 |
-
* Register This Controller
|
69 |
-
*
|
70 |
-
* @param WP_Job_Manager_REST_Environment $environment The Environment to use.
|
71 |
-
* @throws WP_Job_Manager_REST_Exception Throws.
|
72 |
-
*
|
73 |
-
* @return bool|WP_Error true if valid otherwise error.
|
74 |
-
*/
|
75 |
-
public function register( $environment ) {
|
76 |
-
global $wp_post_types;
|
77 |
-
$post_type_name = $this->object_to_extend;
|
78 |
-
if ( ! isset( $wp_post_types[ $post_type_name ] ) ) {
|
79 |
-
return false;
|
80 |
-
}
|
81 |
-
|
82 |
-
if ( $wp_post_types[ $post_type_name ]->show_in_rest ) {
|
83 |
-
return true;
|
84 |
-
}
|
85 |
-
|
86 |
-
// Optionally customize the rest_base or controller class.
|
87 |
-
$wp_post_types[ $post_type_name ]->show_in_rest = true;
|
88 |
-
$wp_post_types[ $post_type_name ]->rest_base = 'job-listings';
|
89 |
-
$wp_post_types[ $post_type_name ]->rest_controller_class = 'WP_REST_Posts_Controller';
|
90 |
-
|
91 |
-
$this->environment = $environment;
|
92 |
-
$this->model_factory = $this->environment->model( $this->model_class );
|
93 |
-
if ( ! $this->model_factory ) {
|
94 |
-
return new WP_Error( 'model-not-found' );
|
95 |
-
}
|
96 |
-
register_rest_field(
|
97 |
-
$this->object_to_extend,
|
98 |
-
$this->rest_field_name,
|
99 |
-
array(
|
100 |
-
'get_callback' => array( $this, 'get_fields' ),
|
101 |
-
'update_callback' => array( $this, 'update_fields' ),
|
102 |
-
'schema' => $this->get_item_schema(),
|
103 |
-
)
|
104 |
-
);
|
105 |
-
|
106 |
-
return true;
|
107 |
-
}
|
108 |
-
|
109 |
-
/**
|
110 |
-
* Get Item Schema
|
111 |
-
*
|
112 |
-
* @return array
|
113 |
-
*/
|
114 |
-
public function get_item_schema() {
|
115 |
-
$fields = $this->model_factory->get_fields();
|
116 |
-
$properties = array();
|
117 |
-
$required = array();
|
118 |
-
foreach ( $fields as $field_declaration ) {
|
119 |
-
/**
|
120 |
-
* Our declaration
|
121 |
-
*
|
122 |
-
* @var WP_Job_Manager_REST_Field_Declaration $field_declaration
|
123 |
-
*/
|
124 |
-
$properties[ $field_declaration->get_data_transfer_name() ] = $field_declaration->as_item_schema_property();
|
125 |
-
if ( $field_declaration->is_required() ) {
|
126 |
-
$required[] = $field_declaration->get_data_transfer_name();
|
127 |
-
}
|
128 |
-
}
|
129 |
-
$schema = array(
|
130 |
-
'$schema' => 'http://json-schema.org/schema#',
|
131 |
-
'title' => $this->model_factory->get_name(),
|
132 |
-
'type' => 'object',
|
133 |
-
'properties' => (array) apply_filters( 'mixtape_rest_api_schema_properties', $properties, $this->model_factory ),
|
134 |
-
);
|
135 |
-
|
136 |
-
if ( ! empty( $required ) ) {
|
137 |
-
$schema['required'] = $required;
|
138 |
-
}
|
139 |
-
|
140 |
-
return $schema;
|
141 |
-
}
|
142 |
-
|
143 |
-
/**
|
144 |
-
* Our Get Fields.
|
145 |
-
*
|
146 |
-
* @param array $object Object.
|
147 |
-
* @param string $field_name Field Name.
|
148 |
-
* @param WP_REST_Request $request Request.
|
149 |
-
* @param string $object_type Object Type.
|
150 |
-
*
|
151 |
-
* @return mixed|string
|
152 |
-
* @throws WP_Job_Manager_REST_Exception If type not there.
|
153 |
-
*/
|
154 |
-
public function get_fields( $object, $field_name, $request, $object_type ) {
|
155 |
-
if ( 'job_listing' !== $object_type ) {
|
156 |
-
return null;
|
157 |
-
}
|
158 |
-
|
159 |
-
if ( $this->rest_field_name !== $field_name ) {
|
160 |
-
return null;
|
161 |
-
}
|
162 |
-
|
163 |
-
$object_id = absint( $object['id'] );
|
164 |
-
$model = $this->get_model( $object_id );
|
165 |
-
return $model->to_dto();
|
166 |
-
}
|
167 |
-
|
168 |
-
/**
|
169 |
-
* Get a model if exists
|
170 |
-
*
|
171 |
-
* @param int $object_id Object ID.
|
172 |
-
* @return WP_Job_Manager_REST_Interfaces_Model
|
173 |
-
*/
|
174 |
-
private function get_model( $object_id ) {
|
175 |
-
$data = array();
|
176 |
-
foreach ( $this->model_factory->get_fields() as $field_declaration ) {
|
177 |
-
$field_name = $field_declaration->get_name();
|
178 |
-
if ( metadata_exists( 'post', $object_id, $field_name ) ) {
|
179 |
-
$meta = get_post_meta( $object_id, $field_name, true );
|
180 |
-
$data[ $field_name ] = $meta;
|
181 |
-
}
|
182 |
-
}
|
183 |
-
|
184 |
-
return $this->model_factory->create(
|
185 |
-
$data,
|
186 |
-
array(
|
187 |
-
'deserialize' => true,
|
188 |
-
)
|
189 |
-
);
|
190 |
-
}
|
191 |
-
|
192 |
-
/**
|
193 |
-
* Our Reader.
|
194 |
-
*
|
195 |
-
* @param mixed $data Data.
|
196 |
-
* @param array|object $object Object.
|
197 |
-
* @param string $field_name Field Name.
|
198 |
-
* @param WP_REST_Request $request Request.
|
199 |
-
* @param string $object_type Object Type.
|
200 |
-
*
|
201 |
-
* @return mixed|string
|
202 |
-
* @throws WP_Job_Manager_REST_Exception If type not there.
|
203 |
-
*/
|
204 |
-
public function update_fields( $data, $object, $field_name, $request, $object_type ) {
|
205 |
-
if ( 'job_listing' !== $object_type ) {
|
206 |
-
return null;
|
207 |
-
}
|
208 |
-
|
209 |
-
if ( $this->rest_field_name !== $field_name ) {
|
210 |
-
return null;
|
211 |
-
}
|
212 |
-
|
213 |
-
$object_id = absint( $object->ID );
|
214 |
-
$existing_model = $this->get_model( $object_id );
|
215 |
-
|
216 |
-
$updated = $existing_model->update_from_array( $data );
|
217 |
-
if ( is_wp_error( $updated ) ) {
|
218 |
-
return $updated;
|
219 |
-
}
|
220 |
-
|
221 |
-
$maybe_validation_error = $updated->validate();
|
222 |
-
if ( is_wp_error( $maybe_validation_error ) ) {
|
223 |
-
return $maybe_validation_error;
|
224 |
-
}
|
225 |
-
|
226 |
-
$serialized_data = $updated->serialize( WP_Job_Manager_REST_Field_Declaration::META );
|
227 |
-
|
228 |
-
foreach ( $serialized_data as $field_name => $val ) {
|
229 |
-
if ( metadata_exists( 'post', $object_id, $field_name ) ) {
|
230 |
-
update_post_meta( $object_id, $field_name, $val );
|
231 |
-
} else {
|
232 |
-
add_post_meta( $object_id, $field_name, $val );
|
233 |
-
}
|
234 |
-
}
|
235 |
-
|
236 |
-
return true;
|
237 |
-
}
|
238 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-registrable-job-types.php
DELETED
@@ -1,42 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Exposes Job Types Taxonomy REST Api
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_Registrable_Job_Types
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_Registrable_Job_Types extends WP_Job_Manager_Registrable_Taxonomy_Type {
|
16 |
-
/**
|
17 |
-
* Gets the taxonomy type to register.
|
18 |
-
*
|
19 |
-
* @return string Taxonomy type to expose.
|
20 |
-
*/
|
21 |
-
public function get_taxonomy_type() {
|
22 |
-
return 'job_listing_type';
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Gets the REST API base slug.
|
27 |
-
*
|
28 |
-
* @return string Slug for REST API base.
|
29 |
-
*/
|
30 |
-
public function get_rest_base() {
|
31 |
-
return 'job-types';
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Gets the REST API model class name.
|
36 |
-
*
|
37 |
-
* @return string Class name for the taxonomy type's model.
|
38 |
-
*/
|
39 |
-
public function get_model_class_name() {
|
40 |
-
return 'WP_Job_Manager_Models_Job_Types_Custom_Fields';
|
41 |
-
}
|
42 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-registrable-taxonomy-type.php
DELETED
@@ -1,239 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Exposes Taxonomy REST Api
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_Registrable_Taxonomy_Type
|
14 |
-
*/
|
15 |
-
abstract class WP_Job_Manager_Registrable_Taxonomy_Type implements WP_Job_Manager_REST_Interfaces_Registrable {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* The Model Prototype
|
19 |
-
*
|
20 |
-
* @var WP_Job_Manager_REST_Model
|
21 |
-
*/
|
22 |
-
private $model_prototype;
|
23 |
-
|
24 |
-
/**
|
25 |
-
* REST Field Name
|
26 |
-
*
|
27 |
-
* @var string
|
28 |
-
*/
|
29 |
-
private $rest_field_name;
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Gets the taxonomy type to register.
|
33 |
-
*
|
34 |
-
* @return string Taxonomy type to expose.
|
35 |
-
*/
|
36 |
-
abstract public function get_taxonomy_type();
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Gets the REST API base slug.
|
40 |
-
*
|
41 |
-
* @return string Slug for REST API base.
|
42 |
-
*/
|
43 |
-
abstract public function get_rest_base();
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Gets the REST API model class name.
|
47 |
-
*
|
48 |
-
* @return string Class name for the taxonomy type's model.
|
49 |
-
*/
|
50 |
-
abstract public function get_model_class_name();
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Register Job Categories
|
54 |
-
*
|
55 |
-
* @param WP_Job_Manager_REST_Environment $environment The Environment to use.
|
56 |
-
* @throws WP_Job_Manager_REST_Exception Throws.
|
57 |
-
*
|
58 |
-
* @return bool|WP_Error true if valid otherwise error.
|
59 |
-
*/
|
60 |
-
public function register( $environment ) {
|
61 |
-
global $wp_taxonomies;
|
62 |
-
|
63 |
-
$taxonomy_type = $this->get_taxonomy_type();
|
64 |
-
$this->rest_field_name = 'fields';
|
65 |
-
|
66 |
-
if ( ! isset( $wp_taxonomies[ $taxonomy_type ] ) ) {
|
67 |
-
return false;
|
68 |
-
}
|
69 |
-
|
70 |
-
if ( $wp_taxonomies[ $taxonomy_type ]->show_in_rest ) {
|
71 |
-
return true;
|
72 |
-
}
|
73 |
-
|
74 |
-
$wp_taxonomies[ $taxonomy_type ]->show_in_rest = true;
|
75 |
-
$wp_taxonomies[ $taxonomy_type ]->rest_base = $this->get_rest_base();
|
76 |
-
|
77 |
-
$this->model_prototype = $environment->model( $this->get_model_class_name() );
|
78 |
-
|
79 |
-
if ( ! $this->model_prototype ) {
|
80 |
-
return new WP_Error( 'model-not-found' );
|
81 |
-
}
|
82 |
-
register_rest_field(
|
83 |
-
$taxonomy_type,
|
84 |
-
$this->rest_field_name,
|
85 |
-
array(
|
86 |
-
'get_callback' => array( $this, 'get_taxonomy_term' ),
|
87 |
-
'update_callback' => array( $this, 'update_taxonomy_term' ),
|
88 |
-
'schema' => $this->get_item_schema(),
|
89 |
-
)
|
90 |
-
);
|
91 |
-
|
92 |
-
return true;
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* Get Item Schema
|
97 |
-
*
|
98 |
-
* @return array
|
99 |
-
*/
|
100 |
-
public function get_item_schema() {
|
101 |
-
$fields = $this->model_prototype->get_fields();
|
102 |
-
$properties = array();
|
103 |
-
$required = array();
|
104 |
-
foreach ( $fields as $field_declaration ) {
|
105 |
-
/**
|
106 |
-
* Our declaration
|
107 |
-
*
|
108 |
-
* @var WP_Job_Manager_REST_Field_Declaration $field_declaration
|
109 |
-
*/
|
110 |
-
$properties[ $field_declaration->get_data_transfer_name() ] = $field_declaration->as_item_schema_property();
|
111 |
-
if ( $field_declaration->is_required() ) {
|
112 |
-
$required[] = $field_declaration->get_data_transfer_name();
|
113 |
-
}
|
114 |
-
}
|
115 |
-
$schema = array(
|
116 |
-
'$schema' => 'http://json-schema.org/schema#',
|
117 |
-
'title' => $this->model_prototype->get_name(),
|
118 |
-
'type' => 'object',
|
119 |
-
'properties' => (array) apply_filters( 'mixtape_rest_api_schema_properties', $properties, $this->model_prototype ),
|
120 |
-
);
|
121 |
-
|
122 |
-
if ( ! empty( $required ) ) {
|
123 |
-
$schema['required'] = $required;
|
124 |
-
}
|
125 |
-
|
126 |
-
return $schema;
|
127 |
-
}
|
128 |
-
|
129 |
-
/**
|
130 |
-
* Our Get Fields.
|
131 |
-
*
|
132 |
-
* @param array $object Object.
|
133 |
-
* @param string $field_name Field Name.
|
134 |
-
* @param WP_REST_Request $request Request.
|
135 |
-
* @param string $object_type Object Type.
|
136 |
-
*
|
137 |
-
* @return mixed|string
|
138 |
-
* @throws WP_Job_Manager_REST_Exception If type not there.
|
139 |
-
*/
|
140 |
-
public function get_taxonomy_term( $object, $field_name, $request, $object_type ) {
|
141 |
-
if ( $this->get_taxonomy_type() !== $object_type ) {
|
142 |
-
return null;
|
143 |
-
}
|
144 |
-
|
145 |
-
if ( $this->rest_field_name !== $field_name ) {
|
146 |
-
return null;
|
147 |
-
}
|
148 |
-
|
149 |
-
$object_id = absint( $object['id'] );
|
150 |
-
$model = $this->get_model( $object_id );
|
151 |
-
return $model->to_dto();
|
152 |
-
}
|
153 |
-
|
154 |
-
/**
|
155 |
-
* Get a model if exists
|
156 |
-
*
|
157 |
-
* @param int $object_id Object ID.
|
158 |
-
* @return WP_Job_Manager_REST_Interfaces_Model
|
159 |
-
* @throws WP_Job_Manager_REST_Exception On Error.
|
160 |
-
*/
|
161 |
-
private function get_model( $object_id ) {
|
162 |
-
$data = array();
|
163 |
-
foreach ( $this->model_prototype->get_fields( WP_Job_Manager_REST_Field_Declaration::META ) as $field_declaration ) {
|
164 |
-
$field_name = $field_declaration->get_name();
|
165 |
-
if ( metadata_exists( 'term', $object_id, $field_name ) ) {
|
166 |
-
$meta = get_term_meta( $object_id, $field_name, true );
|
167 |
-
$data[ $field_name ] = $meta;
|
168 |
-
}
|
169 |
-
}
|
170 |
-
|
171 |
-
return $this->model_prototype->create(
|
172 |
-
$data,
|
173 |
-
array(
|
174 |
-
'deserialize' => true,
|
175 |
-
)
|
176 |
-
);
|
177 |
-
}
|
178 |
-
|
179 |
-
/**
|
180 |
-
* Our Reader.
|
181 |
-
*
|
182 |
-
* @param mixed $data Data.
|
183 |
-
* @param object $object Object.
|
184 |
-
* @param string $field_name Field Name.
|
185 |
-
* @param WP_REST_Request $request Request.
|
186 |
-
* @param string $object_type Object Type.
|
187 |
-
*
|
188 |
-
* @return mixed|string
|
189 |
-
* @throws WP_Job_Manager_REST_Exception If type not there.
|
190 |
-
*/
|
191 |
-
public function update_taxonomy_term( $data, $object, $field_name, $request, $object_type ) {
|
192 |
-
if ( $this->get_taxonomy_type() !== $object_type ) {
|
193 |
-
return null;
|
194 |
-
}
|
195 |
-
|
196 |
-
if ( $this->rest_field_name !== $field_name ) {
|
197 |
-
return null;
|
198 |
-
}
|
199 |
-
|
200 |
-
if ( ! is_a( $object, 'WP_Term' ) ) {
|
201 |
-
return null;
|
202 |
-
}
|
203 |
-
|
204 |
-
$rest_base = $this->get_rest_base();
|
205 |
-
$term_id = absint( $object->term_id );
|
206 |
-
if ( ! $term_id ) {
|
207 |
-
// No way to update this. Bail.
|
208 |
-
return new WP_Error(
|
209 |
-
$rest_base . '-error-invalid-id', $rest_base . '-error-invalid-id',
|
210 |
-
array(
|
211 |
-
'status' => 400,
|
212 |
-
)
|
213 |
-
);
|
214 |
-
}
|
215 |
-
$existing_model = $this->get_model( $term_id );
|
216 |
-
|
217 |
-
$updated = $existing_model->update_from_array( $data );
|
218 |
-
if ( is_wp_error( $updated ) ) {
|
219 |
-
return $updated;
|
220 |
-
}
|
221 |
-
|
222 |
-
$maybe_validation_error = $updated->sanitize()->validate();
|
223 |
-
if ( is_wp_error( $maybe_validation_error ) ) {
|
224 |
-
return $maybe_validation_error;
|
225 |
-
}
|
226 |
-
|
227 |
-
$serialized_data = $updated->serialize( WP_Job_Manager_REST_Field_Declaration::META );
|
228 |
-
|
229 |
-
foreach ( $serialized_data as $field_name => $val ) {
|
230 |
-
if ( metadata_exists( 'term', $term_id, $field_name ) ) {
|
231 |
-
update_term_meta( $term_id, $field_name, $val );
|
232 |
-
} else {
|
233 |
-
add_term_meta( $term_id, $field_name, $val );
|
234 |
-
}
|
235 |
-
}
|
236 |
-
|
237 |
-
return true;
|
238 |
-
}
|
239 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/rest-api/class-wp-job-manager-rest-api.php
DELETED
@@ -1,128 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* The REST API Initializer
|
4 |
-
*
|
5 |
-
* @package WPJM/REST
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_API
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_REST_API {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Is the api enabled?
|
19 |
-
*
|
20 |
-
* @var bool
|
21 |
-
*/
|
22 |
-
private $is_rest_api_enabled;
|
23 |
-
/**
|
24 |
-
* Our bootstrap
|
25 |
-
*
|
26 |
-
* @var WP_Job_Manager_REST_Bootstrap
|
27 |
-
*/
|
28 |
-
private $wpjm_rest_api;
|
29 |
-
/**
|
30 |
-
* The plugin base dir
|
31 |
-
*
|
32 |
-
* @var string
|
33 |
-
*/
|
34 |
-
private $base_dir;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* WP_Job_Manager_REST_API constructor.
|
38 |
-
*
|
39 |
-
* @param string $base_dir The base dir.
|
40 |
-
*/
|
41 |
-
public function __construct( $base_dir ) {
|
42 |
-
$this->base_dir = trailingslashit( $base_dir );
|
43 |
-
$this->is_rest_api_enabled = defined( 'WPJM_REST_API_ENABLED' ) && ( true === constant( 'WPJM_REST_API_ENABLED' ) );
|
44 |
-
$file = $this->base_dir . 'lib/wpjm_rest/class-wp-job-manager-rest-bootstrap.php';
|
45 |
-
if ( file_exists( $file ) && $this->is_rest_api_enabled ) {
|
46 |
-
include_once $file;
|
47 |
-
$this->wpjm_rest_api = WP_Job_Manager_REST_Bootstrap::create();
|
48 |
-
$this->wpjm_rest_api
|
49 |
-
->environment()
|
50 |
-
->get_event_dispatcher()
|
51 |
-
->add_action( 'environment_before_start', array( $this, 'define_api' ) );
|
52 |
-
$this->wpjm_rest_api->run();
|
53 |
-
}
|
54 |
-
}
|
55 |
-
|
56 |
-
/**
|
57 |
-
* Get WP_Job_Manager_REST_Bootstrap
|
58 |
-
*
|
59 |
-
* @return WP_Job_Manager_REST_Bootstrap
|
60 |
-
*/
|
61 |
-
public function get_bootstrap() {
|
62 |
-
return $this->wpjm_rest_api;
|
63 |
-
}
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Initialize the REST API
|
67 |
-
*
|
68 |
-
* @return WP_Job_Manager_REST_API $this
|
69 |
-
*/
|
70 |
-
public function init() {
|
71 |
-
if ( ! $this->is_rest_api_enabled ) {
|
72 |
-
return $this;
|
73 |
-
}
|
74 |
-
$this->define_api( $this->wpjm_rest_api->environment() );
|
75 |
-
return $this;
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Define our REST API Models and Controllers
|
80 |
-
*
|
81 |
-
* @param WP_Job_Manager_REST_Environment $env The Environment.
|
82 |
-
*
|
83 |
-
* @throws WP_Job_Manager_REST_Exception Thrown during error while processing of request.
|
84 |
-
*/
|
85 |
-
public function define_api( $env ) {
|
86 |
-
if ( ! is_a( $env, 'WP_Job_Manager_REST_Environment' ) ) {
|
87 |
-
return;
|
88 |
-
}
|
89 |
-
|
90 |
-
include_once 'class-wp-job-manager-models-settings.php';
|
91 |
-
include_once 'class-wp-job-manager-models-status.php';
|
92 |
-
include_once 'class-wp-job-manager-filters-status.php';
|
93 |
-
include_once 'class-wp-job-manager-data-stores-status.php';
|
94 |
-
include_once 'class-wp-job-manager-controllers-status.php';
|
95 |
-
include_once 'class-wp-job-manager-models-job-listings-custom-fields.php';
|
96 |
-
include_once 'class-wp-job-manager-models-job-types-custom-fields.php';
|
97 |
-
include_once 'class-wp-job-manager-models-job-categories-custom-fields.php';
|
98 |
-
include_once 'class-wp-job-manager-registrable-job-listings.php';
|
99 |
-
include_once 'class-wp-job-manager-registrable-taxonomy-type.php';
|
100 |
-
include_once 'class-wp-job-manager-registrable-job-types.php';
|
101 |
-
include_once 'class-wp-job-manager-registrable-job-categories.php';
|
102 |
-
|
103 |
-
// Models.
|
104 |
-
$env->define_model( 'WP_Job_Manager_Models_Settings' )
|
105 |
-
->with_data_store( new WP_Job_Manager_REST_Data_Store_Option( $env->model( 'WP_Job_Manager_Models_Settings' ) ) );
|
106 |
-
$env->define_model( 'WP_Job_Manager_Models_Status' )
|
107 |
-
->with_data_store( new WP_Job_Manager_Data_Stores_Status( $env->model( 'WP_Job_Manager_Models_Status' ) ) );
|
108 |
-
$env->define_model( 'WP_Job_Manager_Filters_Status' );
|
109 |
-
$env->define_model( 'WP_Job_Manager_Models_Job_Listings_Custom_Fields' );
|
110 |
-
$env->define_model( 'WP_Job_Manager_Models_Job_Types_Custom_Fields' );
|
111 |
-
$env->define_model( 'WP_Job_Manager_Models_Job_Categories_Custom_Fields' );
|
112 |
-
|
113 |
-
// Endpoints.
|
114 |
-
$env->rest_api( 'wpjm/v1' )
|
115 |
-
->add_endpoint( new WP_Job_Manager_REST_Controller_Settings( '/settings', 'WP_Job_Manager_Models_Settings' ) )
|
116 |
-
->add_endpoint( new WP_Job_Manager_Controllers_Status( '/status', 'WP_Job_Manager_Models_Status' ) );
|
117 |
-
$env->add_registrable(
|
118 |
-
new WP_Job_Manager_Registrable_Job_Listings(
|
119 |
-
'job_listing',
|
120 |
-
'WP_Job_Manager_Models_Job_Listings_Custom_Fields',
|
121 |
-
'fields'
|
122 |
-
)
|
123 |
-
);
|
124 |
-
$env->add_registrable( new WP_Job_Manager_Registrable_Job_Types() );
|
125 |
-
$env->add_registrable( new WP_Job_Manager_Registrable_Job_Categories() );
|
126 |
-
}
|
127 |
-
}
|
128 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/widgets/class-wp-job-manager-widget-featured-jobs.php
CHANGED
@@ -17,19 +17,17 @@ class WP_Job_Manager_Widget_Featured_Jobs extends WP_Job_Manager_Widget {
|
|
17 |
public function __construct() {
|
18 |
global $wp_post_types;
|
19 |
|
20 |
-
// translators: Placeholder %s is the plural label for the job listing post type.
|
21 |
-
$this->widget_name = sprintf( __( 'Featured %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name );
|
22 |
$this->widget_cssclass = 'job_manager widget_featured_jobs';
|
23 |
$this->widget_description = __( 'Display a list of featured listings on your site.', 'wp-job-manager' );
|
24 |
$this->widget_id = 'widget_featured_jobs';
|
|
|
25 |
$this->settings = array(
|
26 |
-
'title'
|
27 |
'type' => 'text',
|
28 |
-
// translators: Placeholder %s is the plural label for the job listing post type.
|
29 |
'std' => sprintf( __( 'Featured %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name ),
|
30 |
'label' => __( 'Title', 'wp-job-manager' ),
|
31 |
),
|
32 |
-
'number'
|
33 |
'type' => 'number',
|
34 |
'step' => 1,
|
35 |
'min' => 1,
|
@@ -37,28 +35,8 @@ class WP_Job_Manager_Widget_Featured_Jobs extends WP_Job_Manager_Widget {
|
|
37 |
'std' => 10,
|
38 |
'label' => __( 'Number of listings to show', 'wp-job-manager' ),
|
39 |
),
|
40 |
-
'orderby' => array(
|
41 |
-
'type' => 'select',
|
42 |
-
'std' => 'date',
|
43 |
-
'label' => __( 'Sort By', 'wp-job-manager' ),
|
44 |
-
'options' => array(
|
45 |
-
'date' => __( 'Date', 'wp-job-manager' ),
|
46 |
-
'title' => __( 'Title', 'wp-job-manager' ),
|
47 |
-
'author' => __( 'Author', 'wp-job-manager' ),
|
48 |
-
'rand_featured' => __( 'Random', 'wp-job-manager' ),
|
49 |
-
),
|
50 |
-
),
|
51 |
-
'order' => array(
|
52 |
-
'type' => 'select',
|
53 |
-
'std' => 'DESC',
|
54 |
-
'label' => __( 'Sort Direction', 'wp-job-manager' ),
|
55 |
-
'options' => array(
|
56 |
-
'ASC' => __( 'Ascending', 'wp-job-manager' ),
|
57 |
-
'DESC' => __( 'Descending', 'wp-job-manager' ),
|
58 |
-
),
|
59 |
-
),
|
60 |
);
|
61 |
-
|
62 |
}
|
63 |
|
64 |
/**
|
@@ -69,46 +47,32 @@ class WP_Job_Manager_Widget_Featured_Jobs extends WP_Job_Manager_Widget {
|
|
69 |
* @param array $instance
|
70 |
*/
|
71 |
public function widget( $args, $instance ) {
|
72 |
-
wp_enqueue_style( 'wp-job-manager-job-listings' );
|
73 |
-
|
74 |
if ( $this->get_cached_widget( $args ) ) {
|
75 |
return;
|
76 |
}
|
77 |
|
78 |
-
$instance = array_merge( $this->get_default_instance(), $instance );
|
79 |
-
|
80 |
ob_start();
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
$
|
85 |
-
$
|
86 |
-
$
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
'featured' => true,
|
93 |
-
)
|
94 |
-
);
|
95 |
|
96 |
if ( $jobs->have_posts() ) : ?>
|
97 |
|
98 |
-
<?php echo $
|
99 |
|
100 |
-
<?php
|
101 |
-
if ( $title ) {
|
102 |
-
echo $args['before_title'] . esc_html( $title ) . $args['after_title']; // WPCS: XSS ok.
|
103 |
-
}
|
104 |
-
?>
|
105 |
|
106 |
<ul class="job_listings">
|
107 |
|
108 |
-
<?php
|
109 |
-
while ( $jobs->have_posts() ) :
|
110 |
-
$jobs->the_post();
|
111 |
-
?>
|
112 |
|
113 |
<?php get_job_manager_template_part( 'content-widget', 'job_listing' ); ?>
|
114 |
|
@@ -116,20 +80,19 @@ class WP_Job_Manager_Widget_Featured_Jobs extends WP_Job_Manager_Widget {
|
|
116 |
|
117 |
</ul>
|
118 |
|
119 |
-
<?php echo $
|
120 |
|
121 |
<?php else : ?>
|
122 |
|
123 |
<?php get_job_manager_template_part( 'content-widget', 'no-jobs-found' ); ?>
|
124 |
|
125 |
-
<?php
|
126 |
-
endif;
|
127 |
|
128 |
wp_reset_postdata();
|
129 |
|
130 |
$content = ob_get_clean();
|
131 |
|
132 |
-
echo $content;
|
133 |
|
134 |
$this->cache_widget( $args, $content );
|
135 |
}
|
17 |
public function __construct() {
|
18 |
global $wp_post_types;
|
19 |
|
|
|
|
|
20 |
$this->widget_cssclass = 'job_manager widget_featured_jobs';
|
21 |
$this->widget_description = __( 'Display a list of featured listings on your site.', 'wp-job-manager' );
|
22 |
$this->widget_id = 'widget_featured_jobs';
|
23 |
+
$this->widget_name = sprintf( __( 'Featured %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name );
|
24 |
$this->settings = array(
|
25 |
+
'title' => array(
|
26 |
'type' => 'text',
|
|
|
27 |
'std' => sprintf( __( 'Featured %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name ),
|
28 |
'label' => __( 'Title', 'wp-job-manager' ),
|
29 |
),
|
30 |
+
'number' => array(
|
31 |
'type' => 'number',
|
32 |
'step' => 1,
|
33 |
'min' => 1,
|
35 |
'std' => 10,
|
36 |
'label' => __( 'Number of listings to show', 'wp-job-manager' ),
|
37 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
);
|
39 |
+
$this->register();
|
40 |
}
|
41 |
|
42 |
/**
|
47 |
* @param array $instance
|
48 |
*/
|
49 |
public function widget( $args, $instance ) {
|
|
|
|
|
50 |
if ( $this->get_cached_widget( $args ) ) {
|
51 |
return;
|
52 |
}
|
53 |
|
|
|
|
|
54 |
ob_start();
|
55 |
|
56 |
+
extract( $args );
|
57 |
+
|
58 |
+
$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
|
59 |
+
$number = absint( $instance['number'] );
|
60 |
+
$jobs = get_job_listings( array(
|
61 |
+
'posts_per_page' => $number,
|
62 |
+
'orderby' => 'date',
|
63 |
+
'order' => 'DESC',
|
64 |
+
'featured' => true,
|
65 |
+
) );
|
|
|
|
|
|
|
66 |
|
67 |
if ( $jobs->have_posts() ) : ?>
|
68 |
|
69 |
+
<?php echo $before_widget; ?>
|
70 |
|
71 |
+
<?php if ( $title ) { echo $before_title . $title . $after_title;} ?>
|
|
|
|
|
|
|
|
|
72 |
|
73 |
<ul class="job_listings">
|
74 |
|
75 |
+
<?php while ( $jobs->have_posts() ) : $jobs->the_post(); ?>
|
|
|
|
|
|
|
76 |
|
77 |
<?php get_job_manager_template_part( 'content-widget', 'job_listing' ); ?>
|
78 |
|
80 |
|
81 |
</ul>
|
82 |
|
83 |
+
<?php echo $after_widget; ?>
|
84 |
|
85 |
<?php else : ?>
|
86 |
|
87 |
<?php get_job_manager_template_part( 'content-widget', 'no-jobs-found' ); ?>
|
88 |
|
89 |
+
<?php endif;
|
|
|
90 |
|
91 |
wp_reset_postdata();
|
92 |
|
93 |
$content = ob_get_clean();
|
94 |
|
95 |
+
echo $content;
|
96 |
|
97 |
$this->cache_widget( $args, $content );
|
98 |
}
|
includes/widgets/class-wp-job-manager-widget-recent-jobs.php
CHANGED
@@ -17,29 +17,27 @@ class WP_Job_Manager_Widget_Recent_Jobs extends WP_Job_Manager_Widget {
|
|
17 |
public function __construct() {
|
18 |
global $wp_post_types;
|
19 |
|
20 |
-
// translators: Placeholder %s is the plural label for the job listing post type.
|
21 |
-
$this->widget_name = sprintf( __( 'Recent %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name );
|
22 |
$this->widget_cssclass = 'job_manager widget_recent_jobs';
|
23 |
$this->widget_description = __( 'Display a list of recent listings on your site, optionally matching a keyword and location.', 'wp-job-manager' );
|
24 |
$this->widget_id = 'widget_recent_jobs';
|
|
|
25 |
$this->settings = array(
|
26 |
-
'title'
|
27 |
'type' => 'text',
|
28 |
-
// translators: Placeholder %s is the plural label for the job listing post type.
|
29 |
'std' => sprintf( __( 'Recent %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name ),
|
30 |
'label' => __( 'Title', 'wp-job-manager' ),
|
31 |
),
|
32 |
-
'keyword'
|
33 |
'type' => 'text',
|
34 |
'std' => '',
|
35 |
'label' => __( 'Keyword', 'wp-job-manager' ),
|
36 |
),
|
37 |
-
'location'
|
38 |
'type' => 'text',
|
39 |
'std' => '',
|
40 |
'label' => __( 'Location', 'wp-job-manager' ),
|
41 |
),
|
42 |
-
'number'
|
43 |
'type' => 'number',
|
44 |
'step' => 1,
|
45 |
'min' => 1,
|
@@ -47,14 +45,8 @@ class WP_Job_Manager_Widget_Recent_Jobs extends WP_Job_Manager_Widget {
|
|
47 |
'std' => 10,
|
48 |
'label' => __( 'Number of listings to show', 'wp-job-manager' ),
|
49 |
),
|
50 |
-
'show_logo' => array(
|
51 |
-
'type' => 'checkbox',
|
52 |
-
'std' => 0,
|
53 |
-
'label' => esc_html__( 'Show Company Logo', 'wp-job-manager' ),
|
54 |
-
),
|
55 |
);
|
56 |
-
|
57 |
-
parent::__construct();
|
58 |
}
|
59 |
|
60 |
/**
|
@@ -65,88 +57,53 @@ class WP_Job_Manager_Widget_Recent_Jobs extends WP_Job_Manager_Widget {
|
|
65 |
* @param array $instance
|
66 |
*/
|
67 |
public function widget( $args, $instance ) {
|
68 |
-
wp_enqueue_style( 'wp-job-manager-job-listings' );
|
69 |
-
|
70 |
if ( $this->get_cached_widget( $args ) ) {
|
71 |
return;
|
72 |
}
|
73 |
|
74 |
-
$instance = array_merge( $this->get_default_instance(), $instance );
|
75 |
-
|
76 |
ob_start();
|
77 |
|
78 |
-
|
79 |
-
|
80 |
-
$
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
);
|
89 |
-
$show_logo = absint( $instance['show_logo'] );
|
90 |
-
|
91 |
-
/**
|
92 |
-
* Runs before Recent Jobs widget content.
|
93 |
-
*
|
94 |
-
* @since 1.29.1
|
95 |
-
*
|
96 |
-
* @param array $args
|
97 |
-
* @param array $instance
|
98 |
-
* @param WP_Query $jobs
|
99 |
-
*/
|
100 |
-
do_action( 'job_manager_recent_jobs_widget_before', $args, $instance, $jobs );
|
101 |
|
102 |
if ( $jobs->have_posts() ) : ?>
|
103 |
|
104 |
-
<?php echo $
|
105 |
|
106 |
-
<?php
|
107 |
-
if ( $title ) {
|
108 |
-
echo $args['before_title'] . esc_html( $title ) . $args['after_title']; // WPCS: XSS ok.
|
109 |
-
}
|
110 |
-
?>
|
111 |
|
112 |
<ul class="job_listings">
|
113 |
|
114 |
-
<?php
|
115 |
-
while ( $jobs->have_posts() ) :
|
116 |
-
$jobs->the_post();
|
117 |
-
?>
|
118 |
|
119 |
-
<?php
|
120 |
|
121 |
<?php endwhile; ?>
|
122 |
|
123 |
</ul>
|
124 |
|
125 |
-
<?php echo $
|
126 |
|
127 |
<?php else : ?>
|
128 |
|
129 |
<?php get_job_manager_template_part( 'content-widget', 'no-jobs-found' ); ?>
|
130 |
|
131 |
-
<?php
|
132 |
-
endif;
|
133 |
-
|
134 |
-
/**
|
135 |
-
* Runs after Recent Jobs widget content.
|
136 |
-
*
|
137 |
-
* @since 1.29.1
|
138 |
-
*
|
139 |
-
* @param array $args
|
140 |
-
* @param array $instance
|
141 |
-
* @param WP_Query $jobs
|
142 |
-
*/
|
143 |
-
do_action( 'job_manager_recent_jobs_widget_after', $args, $instance, $jobs );
|
144 |
|
145 |
wp_reset_postdata();
|
146 |
|
147 |
$content = ob_get_clean();
|
148 |
|
149 |
-
echo $content;
|
150 |
|
151 |
$this->cache_widget( $args, $content );
|
152 |
}
|
17 |
public function __construct() {
|
18 |
global $wp_post_types;
|
19 |
|
|
|
|
|
20 |
$this->widget_cssclass = 'job_manager widget_recent_jobs';
|
21 |
$this->widget_description = __( 'Display a list of recent listings on your site, optionally matching a keyword and location.', 'wp-job-manager' );
|
22 |
$this->widget_id = 'widget_recent_jobs';
|
23 |
+
$this->widget_name = sprintf( __( 'Recent %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name );
|
24 |
$this->settings = array(
|
25 |
+
'title' => array(
|
26 |
'type' => 'text',
|
|
|
27 |
'std' => sprintf( __( 'Recent %s', 'wp-job-manager' ), $wp_post_types['job_listing']->labels->name ),
|
28 |
'label' => __( 'Title', 'wp-job-manager' ),
|
29 |
),
|
30 |
+
'keyword' => array(
|
31 |
'type' => 'text',
|
32 |
'std' => '',
|
33 |
'label' => __( 'Keyword', 'wp-job-manager' ),
|
34 |
),
|
35 |
+
'location' => array(
|
36 |
'type' => 'text',
|
37 |
'std' => '',
|
38 |
'label' => __( 'Location', 'wp-job-manager' ),
|
39 |
),
|
40 |
+
'number' => array(
|
41 |
'type' => 'number',
|
42 |
'step' => 1,
|
43 |
'min' => 1,
|
45 |
'std' => 10,
|
46 |
'label' => __( 'Number of listings to show', 'wp-job-manager' ),
|
47 |
),
|
|
|
|
|
|
|
|
|
|
|
48 |
);
|
49 |
+
$this->register();
|
|
|
50 |
}
|
51 |
|
52 |
/**
|
57 |
* @param array $instance
|
58 |
*/
|
59 |
public function widget( $args, $instance ) {
|
|
|
|
|
60 |
if ( $this->get_cached_widget( $args ) ) {
|
61 |
return;
|
62 |
}
|
63 |
|
|
|
|
|
64 |
ob_start();
|
65 |
|
66 |
+
extract( $args );
|
67 |
+
|
68 |
+
$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
|
69 |
+
$number = absint( $instance['number'] );
|
70 |
+
$jobs = get_job_listings( array(
|
71 |
+
'search_location' => isset( $instance['location'] ) ? $instance['location'] : '',
|
72 |
+
'search_keywords' => isset( $instance['keyword'] ) ? $instance['keyword'] : '',
|
73 |
+
'posts_per_page' => $number,
|
74 |
+
'orderby' => 'date',
|
75 |
+
'order' => 'DESC',
|
76 |
+
) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
if ( $jobs->have_posts() ) : ?>
|
79 |
|
80 |
+
<?php echo $before_widget; ?>
|
81 |
|
82 |
+
<?php if ( $title ) { echo $before_title . $title . $after_title;} ?>
|
|
|
|
|
|
|
|
|
83 |
|
84 |
<ul class="job_listings">
|
85 |
|
86 |
+
<?php while ( $jobs->have_posts() ) : $jobs->the_post(); ?>
|
|
|
|
|
|
|
87 |
|
88 |
+
<?php get_job_manager_template_part( 'content-widget', 'job_listing' ); ?>
|
89 |
|
90 |
<?php endwhile; ?>
|
91 |
|
92 |
</ul>
|
93 |
|
94 |
+
<?php echo $after_widget; ?>
|
95 |
|
96 |
<?php else : ?>
|
97 |
|
98 |
<?php get_job_manager_template_part( 'content-widget', 'no-jobs-found' ); ?>
|
99 |
|
100 |
+
<?php endif;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
|
102 |
wp_reset_postdata();
|
103 |
|
104 |
$content = ob_get_clean();
|
105 |
|
106 |
+
echo $content;
|
107 |
|
108 |
$this->cache_widget( $args, $content );
|
109 |
}
|
languages/wp-job-manager.pot
CHANGED
@@ -1,2198 +1,1424 @@
|
|
1 |
-
# Copyright (C)
|
2 |
# This file is distributed under the GPL2+.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
-
"Project-Id-Version: WP Job Manager 1.
|
6 |
-
"Report-Msgid-Bugs-To: https://
|
7 |
-
"POT-Creation-Date:
|
8 |
"MIME-Version: 1.0\n"
|
9 |
"Content-Type: text/plain; charset=utf-8\n"
|
10 |
"Content-Transfer-Encoding: 8bit\n"
|
11 |
-
"PO-Revision-Date:
|
12 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
-
"Language-Team: LANGUAGE <
|
14 |
-
"X-Generator: grunt-wp-
|
15 |
|
16 |
-
#: includes/
|
17 |
-
|
18 |
-
msgstr ""
|
19 |
-
|
20 |
-
#: includes/3rd-party/wpml.php:98
|
21 |
-
#. translators: Placeholder (%s) is the URL to edit the primary language in
|
22 |
-
#. WPML.
|
23 |
-
msgid "<a href=\"%s\">Switch to primary language</a> to edit this setting."
|
24 |
-
msgstr ""
|
25 |
-
|
26 |
-
#: includes/abstracts/abstract-wp-job-manager-form.php:319
|
27 |
-
#: includes/abstracts/abstract-wp-job-manager-form.php:334
|
28 |
-
#. translators: Placeholder is for the label of the reCAPTCHA field.
|
29 |
-
#. translators: %s is the name of the form validation that failed.
|
30 |
-
msgid "\"%s\" check failed. Please try again."
|
31 |
-
msgstr ""
|
32 |
-
|
33 |
-
#: includes/admin/class-wp-job-manager-addons.php:124
|
34 |
-
#: includes/admin/class-wp-job-manager-admin.php:155
|
35 |
-
#: includes/admin/views/html-admin-page-addons.php:2
|
36 |
msgid "WP Job Manager Add-ons"
|
37 |
msgstr ""
|
38 |
|
39 |
-
#: includes/admin/class-wp-job-manager-addons.php:
|
40 |
-
|
41 |
-
msgid "Licenses"
|
42 |
-
msgstr ""
|
43 |
-
|
44 |
-
#: includes/admin/class-wp-job-manager-admin.php:89
|
45 |
-
#. translators: %s is the URL for the page where users can go to update
|
46 |
-
#. WordPress.
|
47 |
-
msgid ""
|
48 |
-
"<strong>WP Job Manager</strong> requires a more recent version of "
|
49 |
-
"WordPress. <a href=\"%s\">Please update WordPresse</a> to avoid issues."
|
50 |
msgstr ""
|
51 |
|
52 |
-
#: includes/admin/class-wp-job-manager-
|
53 |
-
|
54 |
-
#. WordPress.
|
55 |
-
msgid "<a href=\"%s\" style=\"color: red\">WordPress Update Required</a>"
|
56 |
msgstr ""
|
57 |
|
58 |
-
#: includes/admin/class-wp-job-manager-admin.php:
|
59 |
msgid "Settings"
|
60 |
msgstr ""
|
61 |
|
62 |
-
#: includes/admin/class-wp-job-manager-admin.php:
|
63 |
msgid "Add-ons"
|
64 |
msgstr ""
|
65 |
|
66 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
67 |
-
|
68 |
-
#. type.
|
69 |
msgid "Approve %s"
|
70 |
msgstr ""
|
71 |
|
72 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
73 |
-
|
74 |
-
#. type.
|
75 |
-
msgid "%s approved"
|
76 |
-
msgstr ""
|
77 |
-
|
78 |
-
#: includes/admin/class-wp-job-manager-cpt.php:84
|
79 |
-
#. translators: Placeholder (%s) is the plural name of the job listings post
|
80 |
-
#. type.
|
81 |
msgid "Expire %s"
|
82 |
msgstr ""
|
83 |
|
84 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
85 |
-
|
86 |
-
|
87 |
-
msgid "%s expired"
|
88 |
-
msgstr ""
|
89 |
-
|
90 |
-
#: includes/admin/class-wp-job-manager-cpt.php:91
|
91 |
-
#. translators: Placeholder (%s) is the plural name of the job listings post
|
92 |
-
#. type.
|
93 |
-
msgid "Mark %s Filled"
|
94 |
-
msgstr ""
|
95 |
-
|
96 |
-
#: includes/admin/class-wp-job-manager-cpt.php:93
|
97 |
-
#. translators: Placeholder (%s) is the plural name of the job listings post
|
98 |
-
#. type.
|
99 |
-
msgid "%s marked as filled"
|
100 |
-
msgstr ""
|
101 |
-
|
102 |
-
#: includes/admin/class-wp-job-manager-cpt.php:98
|
103 |
-
#. translators: Placeholder (%s) is the plural name of the job listings post
|
104 |
-
#. type.
|
105 |
-
msgid "Mark %s Not Filled"
|
106 |
msgstr ""
|
107 |
|
108 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
109 |
-
|
110 |
-
|
111 |
-
msgid "%s marked as not filled"
|
112 |
msgstr ""
|
113 |
|
114 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
115 |
msgid "Select category"
|
116 |
msgstr ""
|
117 |
|
118 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
119 |
-
|
120 |
-
msgstr ""
|
121 |
-
|
122 |
-
#: includes/admin/class-wp-job-manager-cpt.php:339
|
123 |
-
msgid "Filled"
|
124 |
-
msgstr ""
|
125 |
-
|
126 |
-
#: includes/admin/class-wp-job-manager-cpt.php:343
|
127 |
-
msgid "Not Filled"
|
128 |
-
msgstr ""
|
129 |
-
|
130 |
-
#: includes/admin/class-wp-job-manager-cpt.php:354
|
131 |
-
msgid "Select Featured"
|
132 |
-
msgstr ""
|
133 |
-
|
134 |
-
#: includes/admin/class-wp-job-manager-cpt.php:358
|
135 |
-
msgid "Featured"
|
136 |
-
msgstr ""
|
137 |
-
|
138 |
-
#: includes/admin/class-wp-job-manager-cpt.php:362
|
139 |
-
msgid "Not Featured"
|
140 |
-
msgstr ""
|
141 |
-
|
142 |
-
#: includes/admin/class-wp-job-manager-cpt.php:407
|
143 |
-
#: includes/admin/class-wp-job-manager-cpt.php:464
|
144 |
msgid "Position"
|
145 |
msgstr ""
|
146 |
|
147 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
148 |
-
|
149 |
-
#. the URL to view the listing.
|
150 |
-
msgid "%1$s updated. <a href=\"%2$s\">View</a>"
|
151 |
msgstr ""
|
152 |
|
153 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
154 |
msgid "Custom field updated."
|
155 |
msgstr ""
|
156 |
|
157 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
158 |
msgid "Custom field deleted."
|
159 |
msgstr ""
|
160 |
|
161 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
162 |
-
#. translators: %s is the singular name of the job listing post type.
|
163 |
msgid "%s updated."
|
164 |
msgstr ""
|
165 |
|
166 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
167 |
-
|
168 |
-
#. the revision number.
|
169 |
-
msgid "%1$s restored to revision from %2$s"
|
170 |
msgstr ""
|
171 |
|
172 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
173 |
-
|
174 |
-
#. the URL to view the listing.
|
175 |
-
msgid "%1$s published. <a href=\"%2$s\">View</a>"
|
176 |
msgstr ""
|
177 |
|
178 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
179 |
-
#. translators: %1$s is the singular name of the job listing post type; %2$s is
|
180 |
-
#. the URL to view the listing.
|
181 |
msgid "%s saved."
|
182 |
msgstr ""
|
183 |
|
184 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
185 |
-
|
186 |
-
#. the URL to preview the listing.
|
187 |
-
msgid "%1$s submitted. <a target=\"_blank\" href=\"%2$s\">Preview</a>"
|
188 |
msgstr ""
|
189 |
|
190 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
191 |
-
#. translators: %1$s is the singular name of the post type; %2$s is the date
|
192 |
-
#. the post will be published; %3$s is the URL to preview the listing.
|
193 |
msgid ""
|
194 |
-
"%
|
195 |
-
"href=\"%
|
|
|
|
|
|
|
|
|
196 |
msgstr ""
|
197 |
|
198 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
199 |
-
|
200 |
-
#. the URL to view the listing.
|
201 |
-
msgid "%1$s draft updated. <a target=\"_blank\" href=\"%2$s\">Preview</a>"
|
202 |
msgstr ""
|
203 |
|
204 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
205 |
msgid "Type"
|
206 |
msgstr ""
|
207 |
|
208 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
209 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
210 |
-
#: includes/class-wp-job-manager-
|
211 |
-
#: includes/
|
212 |
-
#:
|
213 |
-
#: templates/job-filters.php:35 templates/job-filters.php:36
|
214 |
msgid "Location"
|
215 |
msgstr ""
|
216 |
|
217 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
218 |
msgid "Status"
|
219 |
msgstr ""
|
220 |
|
221 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
222 |
msgid "Posted"
|
223 |
msgstr ""
|
224 |
|
225 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
226 |
msgid "Expires"
|
227 |
msgstr ""
|
228 |
|
229 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
230 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
231 |
msgid "Categories"
|
232 |
msgstr ""
|
233 |
|
234 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
235 |
msgid "Featured?"
|
236 |
msgstr ""
|
237 |
|
238 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
239 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
240 |
msgid "Filled?"
|
241 |
msgstr ""
|
242 |
|
243 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
244 |
msgid "Actions"
|
245 |
msgstr ""
|
246 |
|
247 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
248 |
-
#. translators: %d is the post ID for the job listing.
|
249 |
msgid "ID: %d"
|
250 |
msgstr ""
|
251 |
|
252 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
253 |
-
|
|
|
|
|
|
|
|
|
254 |
msgid "by a guest"
|
255 |
msgstr ""
|
256 |
|
257 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
258 |
msgid "by %s"
|
259 |
msgstr ""
|
260 |
|
261 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
262 |
msgid "Approve"
|
263 |
msgstr ""
|
264 |
|
265 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
266 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
267 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
268 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
269 |
msgid "View"
|
270 |
msgstr ""
|
271 |
|
272 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
273 |
-
#: includes/class-wp-job-manager-post-types.php:
|
274 |
-
#: templates/job-dashboard.php:
|
275 |
msgid "Edit"
|
276 |
msgstr ""
|
277 |
|
278 |
-
#: includes/admin/class-wp-job-manager-cpt.php:
|
279 |
-
#: templates/job-dashboard.php:
|
280 |
msgid "Delete"
|
281 |
msgstr ""
|
282 |
|
283 |
-
#: includes/admin/class-wp-job-manager-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
#: includes/admin/class-wp-job-manager-permalink-settings.php:67
|
288 |
-
msgid "Job category base"
|
289 |
-
msgstr ""
|
290 |
-
|
291 |
-
#: includes/admin/class-wp-job-manager-permalink-settings.php:74
|
292 |
-
msgid "Job type base"
|
293 |
-
msgstr ""
|
294 |
-
|
295 |
-
#: includes/admin/class-wp-job-manager-settings.php:84
|
296 |
-
msgid "General"
|
297 |
-
msgstr ""
|
298 |
-
|
299 |
-
#: includes/admin/class-wp-job-manager-settings.php:89
|
300 |
-
msgid "Date Format"
|
301 |
-
msgstr ""
|
302 |
-
|
303 |
-
#: includes/admin/class-wp-job-manager-settings.php:90
|
304 |
-
msgid ""
|
305 |
-
"Choose how you want the published date for jobs to be displayed on the "
|
306 |
-
"front-end."
|
307 |
-
msgstr ""
|
308 |
-
|
309 |
-
#: includes/admin/class-wp-job-manager-settings.php:93
|
310 |
-
msgid "Relative to the current date (e.g., 1 day, 1 week, 1 month ago)"
|
311 |
-
msgstr ""
|
312 |
-
|
313 |
-
#: includes/admin/class-wp-job-manager-settings.php:94
|
314 |
-
msgid "Default date format as defined in Settings"
|
315 |
-
msgstr ""
|
316 |
-
|
317 |
-
#: includes/admin/class-wp-job-manager-settings.php:100
|
318 |
-
msgid "Google Maps API Key"
|
319 |
-
msgstr ""
|
320 |
-
|
321 |
-
#: includes/admin/class-wp-job-manager-settings.php:102
|
322 |
-
#. translators: Placeholder %s is URL to set up a Google Maps API key.
|
323 |
-
msgid ""
|
324 |
-
"Google requires an API key to retrieve location information for job "
|
325 |
-
"listings. Acquire an API key from the <a href=\"%s\">Google Maps API "
|
326 |
-
"developer site</a>."
|
327 |
-
msgstr ""
|
328 |
-
|
329 |
-
#: includes/admin/class-wp-job-manager-settings.php:108
|
330 |
-
msgid "Delete Data On Uninstall"
|
331 |
-
msgstr ""
|
332 |
-
|
333 |
-
#: includes/admin/class-wp-job-manager-settings.php:109
|
334 |
-
msgid ""
|
335 |
-
"Delete WP Job Manager data when the plugin is deleted. Once removed, this "
|
336 |
-
"data cannot be restored."
|
337 |
-
msgstr ""
|
338 |
-
|
339 |
-
#: includes/admin/class-wp-job-manager-settings.php:117
|
340 |
-
#: includes/class-wp-job-manager-post-types.php:245
|
341 |
-
#: includes/class-wp-job-manager-post-types.php:342
|
342 |
msgid "Job Listings"
|
343 |
msgstr ""
|
344 |
|
345 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
346 |
msgid "Listings Per Page"
|
347 |
msgstr ""
|
348 |
|
349 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
350 |
-
msgid "
|
351 |
msgstr ""
|
352 |
|
353 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
354 |
msgid "Filled Positions"
|
355 |
msgstr ""
|
356 |
|
357 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
358 |
msgid "Hide filled positions"
|
359 |
msgstr ""
|
360 |
|
361 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
362 |
-
msgid "
|
363 |
msgstr ""
|
364 |
|
365 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
366 |
msgid "Hide Expired Listings"
|
367 |
msgstr ""
|
368 |
|
369 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
370 |
-
msgid "Hide expired listings in job
|
371 |
msgstr ""
|
372 |
|
373 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
374 |
-
msgid "
|
375 |
msgstr ""
|
376 |
|
377 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
378 |
msgid "Hide Expired Listings Content"
|
379 |
msgstr ""
|
380 |
|
381 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
382 |
-
msgid "Hide content in
|
383 |
msgstr ""
|
384 |
|
385 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
386 |
msgid ""
|
387 |
-
"
|
388 |
-
"
|
389 |
-
"minus the application area."
|
390 |
msgstr ""
|
391 |
|
392 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
393 |
-
msgid "Enable
|
394 |
msgstr ""
|
395 |
|
396 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
397 |
msgid ""
|
398 |
-
"
|
399 |
-
"
|
400 |
msgstr ""
|
401 |
|
402 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
403 |
msgid "Multi-select Categories"
|
404 |
msgstr ""
|
405 |
|
406 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
407 |
-
msgid "
|
408 |
msgstr ""
|
409 |
|
410 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
411 |
msgid ""
|
412 |
-
"
|
413 |
-
"
|
414 |
-
"single category when submitting jobs."
|
415 |
msgstr ""
|
416 |
|
417 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
418 |
msgid "Category Filter Type"
|
419 |
msgstr ""
|
420 |
|
421 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
422 |
msgid ""
|
423 |
"Determines the logic used to display jobs when selecting multiple "
|
424 |
"categories."
|
425 |
msgstr ""
|
426 |
|
427 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
428 |
msgid "Jobs will be shown if within ANY selected category"
|
429 |
msgstr ""
|
430 |
|
431 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
432 |
msgid "Jobs will be shown if within ALL selected categories"
|
433 |
msgstr ""
|
434 |
|
435 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
436 |
-
msgid "
|
437 |
-
msgstr ""
|
438 |
-
|
439 |
-
#: includes/admin/class-wp-job-manager-settings.php:187
|
440 |
-
msgid "Enable listing types"
|
441 |
msgstr ""
|
442 |
|
443 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
444 |
msgid ""
|
445 |
-
"
|
446 |
-
"
|
447 |
msgstr ""
|
448 |
|
449 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
450 |
-
msgid "
|
451 |
msgstr ""
|
452 |
|
453 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
454 |
-
msgid "
|
455 |
msgstr ""
|
456 |
|
457 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
458 |
-
msgid ""
|
459 |
-
"This allows users to select more than one type when submitting a job. The "
|
460 |
-
"metabox on the post editor and the selection box on the front-end job "
|
461 |
-
"submission form will both reflect this."
|
462 |
msgstr ""
|
463 |
|
464 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
465 |
-
msgid "
|
466 |
msgstr ""
|
467 |
|
468 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
469 |
-
msgid "
|
|
|
|
|
470 |
msgstr ""
|
471 |
|
472 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
473 |
-
msgid "
|
474 |
msgstr ""
|
475 |
|
476 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
477 |
-
msgid "
|
478 |
msgstr ""
|
479 |
|
480 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
481 |
-
msgid "
|
|
|
|
|
|
|
482 |
msgstr ""
|
483 |
|
484 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
485 |
-
msgid "
|
486 |
msgstr ""
|
487 |
|
488 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
489 |
msgid ""
|
490 |
-
"
|
491 |
-
"
|
492 |
-
"
|
493 |
-
msgstr ""
|
494 |
-
|
495 |
-
#: includes/admin/class-wp-job-manager-settings.php:227
|
496 |
-
msgid "Account Username"
|
497 |
msgstr ""
|
498 |
|
499 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
500 |
-
msgid "
|
501 |
msgstr ""
|
502 |
|
503 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
504 |
-
msgid ""
|
505 |
-
"Automatically generates usernames for new accounts from the registrant's "
|
506 |
-
"email address. If this is not enabled, a \"username\" field will display "
|
507 |
-
"instead."
|
508 |
msgstr ""
|
509 |
|
510 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
511 |
-
msgid "
|
512 |
msgstr ""
|
513 |
|
514 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
515 |
-
msgid "
|
|
|
|
|
516 |
msgstr ""
|
517 |
|
518 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
519 |
-
msgid ""
|
520 |
-
"Sends an email to the user with their username and a link to set their "
|
521 |
-
"password. If this is not enabled, a \"password\" field will display "
|
522 |
-
"instead, and their email address won't be verified."
|
523 |
msgstr ""
|
524 |
|
525 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
526 |
-
msgid "
|
527 |
msgstr ""
|
528 |
|
529 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
530 |
msgid ""
|
531 |
-
"
|
532 |
-
"
|
533 |
-
"your own method of assigning roles will apply."
|
534 |
msgstr ""
|
535 |
|
536 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
537 |
-
msgid "
|
538 |
msgstr ""
|
539 |
|
540 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
541 |
-
msgid "
|
542 |
msgstr ""
|
543 |
|
544 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
545 |
msgid ""
|
546 |
-
"
|
547 |
-
"
|
548 |
-
msgstr ""
|
549 |
-
|
550 |
-
#: includes/admin/class-wp-job-manager-settings.php:262
|
551 |
-
msgid "Allow Pending Edits"
|
552 |
msgstr ""
|
553 |
|
554 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
555 |
-
msgid "
|
556 |
msgstr ""
|
557 |
|
558 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
559 |
msgid ""
|
560 |
-
"
|
561 |
-
"
|
562 |
msgstr ""
|
563 |
|
564 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
565 |
-
msgid "
|
566 |
msgstr ""
|
567 |
|
568 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
569 |
-
msgid "
|
570 |
msgstr ""
|
571 |
|
572 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
573 |
-
msgid ""
|
574 |
-
"Choose whether published job listings can be edited and if edits require "
|
575 |
-
"admin approval. When moderation is required, the original job listings will "
|
576 |
-
"be unpublished while edits await admin approval."
|
577 |
msgstr ""
|
578 |
|
579 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
580 |
-
msgid "
|
581 |
msgstr ""
|
582 |
|
583 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
584 |
-
msgid "
|
585 |
msgstr ""
|
586 |
|
587 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
588 |
-
msgid "
|
589 |
msgstr ""
|
590 |
|
591 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
592 |
msgid "Listing Duration"
|
593 |
msgstr ""
|
594 |
|
595 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
596 |
msgid ""
|
597 |
-
"
|
598 |
-
"
|
599 |
msgstr ""
|
600 |
|
601 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
602 |
msgid "Application Method"
|
603 |
msgstr ""
|
604 |
|
605 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
606 |
-
msgid ""
|
607 |
-
"Choose the application method job listers will need to provide. Specify URL "
|
608 |
-
"or email address only, or allow listers to choose which they prefer."
|
609 |
msgstr ""
|
610 |
|
611 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
612 |
msgid "Email address or website URL"
|
613 |
msgstr ""
|
614 |
|
615 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
616 |
msgid "Email addresses only"
|
617 |
msgstr ""
|
618 |
|
619 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
620 |
msgid "Website URLs only"
|
621 |
msgstr ""
|
622 |
|
623 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
624 |
-
msgid "reCAPTCHA"
|
625 |
-
msgstr ""
|
626 |
-
|
627 |
-
#: includes/admin/class-wp-job-manager-settings.php:308
|
628 |
-
msgid "Are you human?"
|
629 |
-
msgstr ""
|
630 |
-
|
631 |
-
#: includes/admin/class-wp-job-manager-settings.php:310
|
632 |
-
msgid "Field Label"
|
633 |
-
msgstr ""
|
634 |
-
|
635 |
-
#: includes/admin/class-wp-job-manager-settings.php:311
|
636 |
-
msgid "The label used for the reCAPTCHA field on forms."
|
637 |
-
msgstr ""
|
638 |
-
|
639 |
-
#: includes/admin/class-wp-job-manager-settings.php:318
|
640 |
-
msgid "Site Key"
|
641 |
-
msgstr ""
|
642 |
-
|
643 |
-
#: includes/admin/class-wp-job-manager-settings.php:320
|
644 |
-
#. translators: Placeholder %s is URL to set up Google reCAPTCHA API key.
|
645 |
-
msgid ""
|
646 |
-
"You can retrieve your site key from <a href=\"%s\">Google's reCAPTCHA admin "
|
647 |
-
"dashboard</a>."
|
648 |
-
msgstr ""
|
649 |
-
|
650 |
-
#: includes/admin/class-wp-job-manager-settings.php:327
|
651 |
-
msgid "Secret Key"
|
652 |
-
msgstr ""
|
653 |
-
|
654 |
-
#: includes/admin/class-wp-job-manager-settings.php:329
|
655 |
-
#. translators: Placeholder %s is URL to set up Google reCAPTCHA API key.
|
656 |
-
msgid ""
|
657 |
-
"You can retrieve your secret key from <a href=\"%s\">Google's reCAPTCHA "
|
658 |
-
"admin dashboard</a>."
|
659 |
-
msgstr ""
|
660 |
-
|
661 |
-
#: includes/admin/class-wp-job-manager-settings.php:335
|
662 |
-
msgid "Job Submission Form"
|
663 |
-
msgstr ""
|
664 |
-
|
665 |
-
#: includes/admin/class-wp-job-manager-settings.php:336
|
666 |
-
msgid "Display a reCAPTCHA field on job submission form."
|
667 |
-
msgstr ""
|
668 |
-
|
669 |
-
#: includes/admin/class-wp-job-manager-settings.php:337
|
670 |
-
msgid ""
|
671 |
-
"This will help prevent bots from submitting job listings. You must have "
|
672 |
-
"entered a valid site key and secret key above."
|
673 |
-
msgstr ""
|
674 |
-
|
675 |
-
#: includes/admin/class-wp-job-manager-settings.php:344
|
676 |
msgid "Pages"
|
677 |
msgstr ""
|
678 |
|
679 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
680 |
msgid "Submit Job Form Page"
|
681 |
msgstr ""
|
682 |
|
683 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
684 |
msgid ""
|
685 |
-
"Select the page where you
|
686 |
-
"lets the plugin know the
|
687 |
msgstr ""
|
688 |
|
689 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
690 |
msgid "Job Dashboard Page"
|
691 |
msgstr ""
|
692 |
|
693 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
694 |
msgid ""
|
695 |
-
"Select the page where you
|
696 |
-
"the plugin know the
|
697 |
msgstr ""
|
698 |
|
699 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
700 |
msgid "Job Listings Page"
|
701 |
msgstr ""
|
702 |
|
703 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
704 |
msgid ""
|
705 |
-
"Select the page where you
|
706 |
-
"plugin know
|
707 |
msgstr ""
|
708 |
|
709 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
710 |
msgid "Settings successfully saved"
|
711 |
msgstr ""
|
712 |
|
713 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
714 |
-
msgid "Save Changes"
|
715 |
-
msgstr ""
|
716 |
-
|
717 |
-
#: includes/admin/class-wp-job-manager-settings.php:644
|
718 |
msgid "--no page--"
|
719 |
msgstr ""
|
720 |
|
721 |
-
#: includes/admin/class-wp-job-manager-settings.php:
|
722 |
msgid "Select a page…"
|
723 |
msgstr ""
|
724 |
|
725 |
-
#: includes/admin/class-wp-job-manager-
|
|
|
|
|
|
|
|
|
726 |
msgid "Setup"
|
727 |
msgstr ""
|
728 |
|
729 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
730 |
msgid "WP Job Manager Setup"
|
731 |
msgstr ""
|
732 |
|
733 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
734 |
msgid "1. Introduction"
|
735 |
msgstr ""
|
736 |
|
737 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
738 |
msgid "2. Page Setup"
|
739 |
msgstr ""
|
740 |
|
741 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
742 |
msgid "3. Done"
|
743 |
msgstr ""
|
744 |
|
745 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
746 |
-
msgid "
|
747 |
msgstr ""
|
748 |
|
749 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
750 |
-
msgid ""
|
751 |
-
"Thanks for installing <em>WP Job Manager</em>! Let's get your site ready to "
|
752 |
-
"accept job listings."
|
753 |
msgstr ""
|
754 |
|
755 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
756 |
msgid ""
|
757 |
-
"This setup wizard will
|
758 |
-
"job
|
759 |
msgstr ""
|
760 |
|
761 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
762 |
-
#. translators: Placeholder %s is the path to WPJM documentation site.
|
763 |
msgid ""
|
764 |
-
"If you
|
765 |
-
"
|
|
|
766 |
msgstr ""
|
767 |
|
768 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
769 |
-
msgid "
|
770 |
msgstr ""
|
771 |
|
772 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
773 |
-
msgid "Skip setup. I will
|
774 |
msgstr ""
|
775 |
|
776 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
777 |
msgid "Page Setup"
|
778 |
msgstr ""
|
779 |
|
780 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
781 |
-
msgid ""
|
782 |
-
"With WP Job Manager, employers and applicants can post, manage, and browse "
|
783 |
-
"job listings right on your website. Tell us which of these common pages "
|
784 |
-
"you'd like your site to have and we'll create and configure them for you."
|
785 |
-
msgstr ""
|
786 |
-
|
787 |
-
#: includes/admin/class-wp-job-manager-setup.php:251
|
788 |
-
#. translators: %1$s is URL to WordPress core shortcode documentation. %2$s is
|
789 |
-
#. URL to WPJM specific shortcode reference.
|
790 |
msgid ""
|
791 |
-
"
|
792 |
-
"
|
793 |
-
"
|
794 |
-
"
|
795 |
-
"\t\t\t\t\t\t\t\tpage on your site, you can skip this step and take a look "
|
796 |
-
"at <a href=\"%2$s\" target=\"_blank\" class=\"help-page-link\">shortcode "
|
797 |
-
"documentation</a> for detailed instructions.)"
|
798 |
msgstr ""
|
799 |
|
800 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
801 |
msgid "Page Title"
|
802 |
msgstr ""
|
803 |
|
804 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
805 |
msgid "Page Description"
|
806 |
msgstr ""
|
807 |
|
808 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
809 |
msgid "Content Shortcode"
|
810 |
msgstr ""
|
811 |
|
812 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
813 |
msgid ""
|
814 |
-
"
|
815 |
-
"
|
816 |
-
"you'd rather not allow this -- for example, if you want employers to use "
|
817 |
-
"the admin dashboard only -- you can uncheck this setting."
|
818 |
msgstr ""
|
819 |
|
820 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
821 |
msgid ""
|
822 |
-
"
|
823 |
-
"
|
824 |
-
"admin area. If you want to manage all job listings from the admin dashboard "
|
825 |
-
"only, you can uncheck this setting."
|
826 |
msgstr ""
|
827 |
|
828 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
829 |
-
msgid "
|
|
|
|
|
830 |
msgstr ""
|
831 |
|
832 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
833 |
msgid "Skip this step"
|
834 |
msgstr ""
|
835 |
|
836 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
837 |
-
msgid "
|
838 |
msgstr ""
|
839 |
|
840 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
841 |
-
msgid "
|
|
|
|
|
842 |
msgstr ""
|
843 |
|
844 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
845 |
-
msgid "Tweak
|
846 |
msgstr ""
|
847 |
|
848 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
849 |
-
msgid "Add a job
|
850 |
msgstr ""
|
851 |
|
852 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
853 |
-
msgid "
|
854 |
msgstr ""
|
855 |
|
856 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
857 |
-
msgid "
|
858 |
msgstr ""
|
859 |
|
860 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
861 |
-
msgid "
|
862 |
msgstr ""
|
863 |
|
864 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
865 |
-
msgid "
|
866 |
msgstr ""
|
867 |
|
868 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
869 |
msgid "View the job dashboard"
|
870 |
msgstr ""
|
871 |
|
872 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
873 |
-
msgid "
|
874 |
msgstr ""
|
875 |
|
876 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
877 |
-
#. translators: %1$s is the URL to WPJM support documentation; %2$s is the URL
|
878 |
-
#. to WPJM support forums.
|
879 |
msgid ""
|
880 |
-
"
|
881 |
-
"
|
882 |
-
"question on the\n"
|
883 |
-
"\t\t\t\t\t\t\t<a href=\"%2$s\">WP Job Manager support forums</a>. Happy "
|
884 |
-
"hiring!"
|
885 |
msgstr ""
|
886 |
|
887 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
888 |
-
msgid "Support
|
889 |
msgstr ""
|
890 |
|
891 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
892 |
msgid ""
|
893 |
-
"There are
|
894 |
-
"
|
895 |
-
"
|
896 |
-
"
|
897 |
msgstr ""
|
898 |
|
899 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
900 |
msgid "Leave a positive review"
|
901 |
msgstr ""
|
902 |
|
903 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
904 |
msgid "Contribute a localization"
|
905 |
msgstr ""
|
906 |
|
907 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
908 |
msgid "Contribute code or report a bug"
|
909 |
msgstr ""
|
910 |
|
911 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
912 |
msgid "Help other users on the forums"
|
913 |
msgstr ""
|
914 |
|
915 |
-
#: includes/admin/class-wp-job-manager-
|
916 |
-
#: includes/
|
917 |
-
#: includes/admin/class-wp-job-manager-taxonomy-meta.php:120
|
918 |
-
#: includes/rest-api/class-wp-job-manager-models-job-types-custom-fields.php:36
|
919 |
-
msgid "Employment Type"
|
920 |
-
msgstr ""
|
921 |
-
|
922 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:58
|
923 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:187
|
924 |
msgid "e.g. \"London\""
|
925 |
msgstr ""
|
926 |
|
927 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
928 |
-
#: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:28
|
929 |
msgid "Leave this blank if the location is not important."
|
930 |
msgstr ""
|
931 |
|
932 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
933 |
-
#: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:32
|
934 |
msgid "Application Email or URL"
|
935 |
msgstr ""
|
936 |
|
937 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
938 |
msgid "URL or email which applicants use to apply"
|
939 |
msgstr ""
|
940 |
|
941 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
942 |
msgid ""
|
943 |
"This field is required for the \"application\" area to appear beneath the "
|
944 |
"listing."
|
945 |
msgstr ""
|
946 |
|
947 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
948 |
-
#: includes/class-wp-job-manager-data-exporter.php:50
|
949 |
-
#: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:37
|
950 |
msgid "Company Name"
|
951 |
msgstr ""
|
952 |
|
953 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
954 |
-
#: includes/class-wp-job-manager-data-exporter.php:51
|
955 |
-
#: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:41
|
956 |
msgid "Company Website"
|
957 |
msgstr ""
|
958 |
|
959 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
960 |
-
#: includes/class-wp-job-manager-data-exporter.php:52
|
961 |
-
#: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:45
|
962 |
msgid "Company Tagline"
|
963 |
msgstr ""
|
964 |
|
965 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
966 |
msgid "Brief description about the company"
|
967 |
msgstr ""
|
968 |
|
969 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
970 |
-
#: includes/class-wp-job-manager-data-exporter.php:53
|
971 |
-
#: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:49
|
972 |
msgid "Company Twitter"
|
973 |
msgstr ""
|
974 |
|
975 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
976 |
-
#: includes/class-wp-job-manager-data-exporter.php:54
|
977 |
-
#: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:53
|
978 |
msgid "Company Video"
|
979 |
msgstr ""
|
980 |
|
981 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
982 |
msgid "URL to the company video"
|
983 |
msgstr ""
|
984 |
|
985 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
986 |
-
#: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:57
|
987 |
msgid "Position Filled"
|
988 |
msgstr ""
|
989 |
|
990 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
991 |
msgid "Filled listings will no longer accept applications."
|
992 |
msgstr ""
|
993 |
|
994 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
995 |
-
#: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:64
|
996 |
msgid "Featured Listing"
|
997 |
msgstr ""
|
998 |
|
999 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1000 |
msgid ""
|
1001 |
"Featured listings will be sticky during searches, and can be styled "
|
1002 |
"differently."
|
1003 |
msgstr ""
|
1004 |
|
1005 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1006 |
-
#: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:68
|
1007 |
msgid "Listing Expiry Date"
|
1008 |
msgstr ""
|
1009 |
|
1010 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1011 |
-
#: includes/class-wp-job-manager-email-notifications.php:288
|
1012 |
-
#: includes/rest-api/class-wp-job-manager-models-job-listings-custom-fields.php:75
|
1013 |
msgid "Posted by"
|
1014 |
msgstr ""
|
1015 |
|
1016 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1017 |
-
#. translators: Placeholder %s is the singular name for a job listing post
|
1018 |
-
#. type.
|
1019 |
msgid "%s Data"
|
1020 |
msgstr ""
|
1021 |
|
1022 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1023 |
msgid "Most Used"
|
1024 |
msgstr ""
|
1025 |
|
1026 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1027 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1028 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1029 |
msgid "Use file"
|
1030 |
msgstr ""
|
1031 |
|
1032 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1033 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1034 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1035 |
msgid "Upload"
|
1036 |
msgstr ""
|
1037 |
|
1038 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1039 |
msgid "Add file"
|
1040 |
msgstr ""
|
1041 |
|
1042 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1043 |
msgid "Guest User"
|
1044 |
msgstr ""
|
1045 |
|
1046 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1047 |
msgid "Change"
|
1048 |
msgstr ""
|
1049 |
|
1050 |
-
#: includes/admin/class-wp-job-manager-writepanels.php:
|
1051 |
msgid "Enter the ID of the user, or leave blank if submitted by a guest."
|
1052 |
msgstr ""
|
1053 |
|
1054 |
-
#: includes/
|
1055 |
-
#. translators: %1$s is placeholder for singular name of the job listing post
|
1056 |
-
#. type; %2$s is the intl formatted date the listing was last modified.
|
1057 |
-
msgid "%1$s was last modified by the user on %2$s."
|
1058 |
-
msgstr ""
|
1059 |
-
|
1060 |
-
#: includes/admin/views/html-admin-page-addons.php:13
|
1061 |
-
msgid "More Information →"
|
1062 |
-
msgstr ""
|
1063 |
-
|
1064 |
-
#: includes/admin/views/html-admin-page-addons.php:43
|
1065 |
-
msgid "No add-ons were found."
|
1066 |
-
msgstr ""
|
1067 |
-
|
1068 |
-
#: includes/class-wp-job-manager-ajax.php:172
|
1069 |
-
#. translators: Placeholder %d is the number of found search results.
|
1070 |
msgid "Search completed. Found %d matching record."
|
1071 |
msgid_plural "Search completed. Found %d matching records."
|
1072 |
msgstr[0] ""
|
1073 |
msgstr[1] ""
|
1074 |
|
1075 |
-
#: includes/class-wp-job-manager-ajax.php:
|
1076 |
msgid "You must be logged in to upload files using this method."
|
1077 |
msgstr ""
|
1078 |
|
1079 |
-
|
1080 |
-
msgid "
|
1081 |
-
msgstr ""
|
1082 |
-
|
1083 |
-
#: includes/class-wp-job-manager-data-exporter.php:49
|
1084 |
-
#: includes/class-wp-job-manager-post-types.php:268
|
1085 |
-
msgid "Company Logo"
|
1086 |
msgstr ""
|
1087 |
|
1088 |
-
#: includes/class-wp-job-manager-
|
1089 |
-
msgid "
|
1090 |
msgstr ""
|
1091 |
|
1092 |
-
#: includes/class-wp-job-manager-
|
1093 |
-
|
|
|
|
|
1094 |
msgstr ""
|
1095 |
|
1096 |
-
#: includes/class-wp-job-manager-
|
1097 |
-
|
1098 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:191
|
1099 |
-
msgid "Job type"
|
1100 |
msgstr ""
|
1101 |
|
1102 |
-
#: includes/class-wp-job-manager-
|
1103 |
-
#: includes/class-wp-job-manager-
|
1104 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:200
|
1105 |
msgid "Job category"
|
1106 |
msgstr ""
|
1107 |
|
1108 |
-
#: includes/class-wp-job-manager-
|
1109 |
-
|
1110 |
-
msgid "Company name"
|
1111 |
msgstr ""
|
1112 |
|
1113 |
-
#: includes/class-wp-job-manager-
|
1114 |
-
|
|
|
|
|
1115 |
msgstr ""
|
1116 |
|
1117 |
-
#: includes/class-wp-job-manager-
|
1118 |
-
|
|
|
|
|
1119 |
msgstr ""
|
1120 |
|
1121 |
-
#: includes/class-wp-job-manager-
|
1122 |
-
|
|
|
|
|
1123 |
msgstr ""
|
1124 |
|
1125 |
-
#: includes/class-wp-job-manager-
|
1126 |
-
|
|
|
1127 |
msgstr ""
|
1128 |
|
1129 |
-
#: includes/class-wp-job-manager-
|
1130 |
-
|
|
|
|
|
1131 |
msgstr ""
|
1132 |
|
1133 |
-
#: includes/class-wp-job-manager-
|
1134 |
-
|
|
|
1135 |
msgstr ""
|
1136 |
|
1137 |
-
#: includes/class-wp-job-manager-
|
1138 |
-
|
|
|
1139 |
msgstr ""
|
1140 |
|
1141 |
-
#: includes/class-wp-job-manager-
|
1142 |
-
|
|
|
1143 |
msgstr ""
|
1144 |
|
1145 |
-
#: includes/class-wp-job-manager-
|
1146 |
-
|
|
|
1147 |
msgstr ""
|
1148 |
|
1149 |
-
#: includes/class-wp-job-manager-
|
1150 |
-
|
1151 |
-
msgid "Geocoding error"
|
1152 |
msgstr ""
|
1153 |
|
1154 |
-
#: includes/class-wp-job-manager-
|
1155 |
-
msgid "
|
1156 |
msgstr ""
|
1157 |
|
1158 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1159 |
-
msgid "
|
1160 |
msgstr ""
|
1161 |
|
1162 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1163 |
-
|
1164 |
-
#: includes/class-wp-job-manager-post-types.php:261
|
1165 |
-
#. translators: Placeholder %s is the plural label of the job listing category
|
1166 |
-
#. taxonomy type.
|
1167 |
-
#. translators: Placeholder %s is the plural label of the job listing job type
|
1168 |
-
#. taxonomy type.
|
1169 |
-
#. translators: Placeholder %s is the singular label of the job listing post
|
1170 |
-
#. type.
|
1171 |
-
msgid "Search %s"
|
1172 |
msgstr ""
|
1173 |
|
1174 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1175 |
-
|
1176 |
-
#: includes/class-wp-job-manager-post-types.php:247
|
1177 |
-
#. translators: Placeholder %s is the plural label of the job listing category
|
1178 |
-
#. taxonomy type.
|
1179 |
-
#. translators: Placeholder %s is the plural label of the job listing job type
|
1180 |
-
#. taxonomy type.
|
1181 |
-
#. translators: Placeholder %s is the plural label of the job listing post
|
1182 |
-
#. type.
|
1183 |
-
msgid "All %s"
|
1184 |
msgstr ""
|
1185 |
|
1186 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1187 |
-
|
1188 |
-
#: includes/class-wp-job-manager-post-types.php:267
|
1189 |
-
#. translators: Placeholder %s is the singular label of the job listing
|
1190 |
-
#. category taxonomy type.
|
1191 |
-
#. translators: Placeholder %s is the singular label of the job listing job
|
1192 |
-
#. type taxonomy type.
|
1193 |
-
#. translators: Placeholder %s is the singular label of the job listing post
|
1194 |
-
#. type.
|
1195 |
-
msgid "Parent %s"
|
1196 |
msgstr ""
|
1197 |
|
1198 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1199 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1200 |
-
|
1201 |
-
#. category taxonomy type.
|
1202 |
-
#. translators: Placeholder %s is the singular label of the job listing job
|
1203 |
-
#. type taxonomy type.
|
1204 |
-
msgid "Parent %s:"
|
1205 |
msgstr ""
|
1206 |
|
1207 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1208 |
-
#: includes/class-wp-job-manager-post-types.php:188
|
1209 |
-
#: includes/class-wp-job-manager-post-types.php:253
|
1210 |
-
#. translators: Placeholder %s is the singular label of the job listing
|
1211 |
-
#. category taxonomy type.
|
1212 |
-
#. translators: Placeholder %s is the singular label of the job listing job
|
1213 |
-
#. type taxonomy type.
|
1214 |
-
#. translators: Placeholder %s is the singular label of the job listing post
|
1215 |
-
#. type.
|
1216 |
-
msgid "Edit %s"
|
1217 |
-
msgstr ""
|
1218 |
-
|
1219 |
-
#: includes/class-wp-job-manager-post-types.php:130
|
1220 |
-
#: includes/class-wp-job-manager-post-types.php:190
|
1221 |
-
#. translators: Placeholder %s is the singular label of the job listing
|
1222 |
-
#. category taxonomy type.
|
1223 |
-
#. translators: Placeholder %s is the singular label of the job listing job
|
1224 |
-
#. type taxonomy type.
|
1225 |
-
msgid "Update %s"
|
1226 |
-
msgstr ""
|
1227 |
-
|
1228 |
-
#: includes/class-wp-job-manager-post-types.php:132
|
1229 |
-
#: includes/class-wp-job-manager-post-types.php:192
|
1230 |
-
#. translators: Placeholder %s is the singular label of the job listing
|
1231 |
-
#. category taxonomy type.
|
1232 |
-
#. translators: Placeholder %s is the singular label of the job listing job
|
1233 |
-
#. type taxonomy type.
|
1234 |
-
msgid "Add New %s"
|
1235 |
-
msgstr ""
|
1236 |
-
|
1237 |
-
#: includes/class-wp-job-manager-post-types.php:134
|
1238 |
-
#: includes/class-wp-job-manager-post-types.php:194
|
1239 |
-
#. translators: Placeholder %s is the singular label of the job listing
|
1240 |
-
#. category taxonomy type.
|
1241 |
-
#. translators: Placeholder %s is the singular label of the job listing job
|
1242 |
-
#. type taxonomy type.
|
1243 |
-
msgid "New %s Name"
|
1244 |
-
msgstr ""
|
1245 |
-
|
1246 |
-
#: includes/class-wp-job-manager-post-types.php:153
|
1247 |
-
msgid "Job types"
|
1248 |
-
msgstr ""
|
1249 |
-
|
1250 |
-
#: includes/class-wp-job-manager-post-types.php:214
|
1251 |
-
msgid "Job"
|
1252 |
-
msgstr ""
|
1253 |
-
|
1254 |
-
#: includes/class-wp-job-manager-post-types.php:215
|
1255 |
-
msgid "Jobs"
|
1256 |
-
msgstr ""
|
1257 |
-
|
1258 |
-
#: includes/class-wp-job-manager-post-types.php:248
|
1259 |
-
msgid "Add New"
|
1260 |
-
msgstr ""
|
1261 |
-
|
1262 |
-
#: includes/class-wp-job-manager-post-types.php:250
|
1263 |
-
#. translators: Placeholder %s is the singular label of the job listing post
|
1264 |
-
#. type.
|
1265 |
-
msgid "Add %s"
|
1266 |
-
msgstr ""
|
1267 |
-
|
1268 |
-
#: includes/class-wp-job-manager-post-types.php:255
|
1269 |
-
#. translators: Placeholder %s is the singular label of the job listing post
|
1270 |
-
#. type.
|
1271 |
-
msgid "New %s"
|
1272 |
-
msgstr ""
|
1273 |
-
|
1274 |
-
#: includes/class-wp-job-manager-post-types.php:257
|
1275 |
-
#: includes/class-wp-job-manager-post-types.php:259
|
1276 |
-
#. translators: Placeholder %s is the singular label of the job listing post
|
1277 |
-
#. type.
|
1278 |
-
msgid "View %s"
|
1279 |
-
msgstr ""
|
1280 |
-
|
1281 |
-
#: includes/class-wp-job-manager-post-types.php:263
|
1282 |
-
#. translators: Placeholder %s is the singular label of the job listing post
|
1283 |
-
#. type.
|
1284 |
msgid "No %s found"
|
1285 |
msgstr ""
|
1286 |
|
1287 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1288 |
-
#. translators: Placeholder %s is the plural label of the job listing post
|
1289 |
-
#. type.
|
1290 |
msgid "No %s found in trash"
|
1291 |
msgstr ""
|
1292 |
|
1293 |
-
#: includes/class-wp-job-manager-post-types.php:
|
|
|
|
|
|
|
|
|
1294 |
msgid "Set company logo"
|
1295 |
msgstr ""
|
1296 |
|
1297 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1298 |
msgid "Remove company logo"
|
1299 |
msgstr ""
|
1300 |
|
1301 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1302 |
msgid "Use as company logo"
|
1303 |
msgstr ""
|
1304 |
|
1305 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1306 |
-
#. translators: Placeholder %s is the plural label of the job listing post
|
1307 |
-
#. type.
|
1308 |
msgid "This is where you can create and manage %s."
|
1309 |
msgstr ""
|
1310 |
|
1311 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1312 |
-
#. translators: Placeholder %s is the number of expired posts of this type.
|
1313 |
msgid "Expired <span class=\"count\">(%s)</span>"
|
1314 |
msgid_plural "Expired <span class=\"count\">(%s)</span>"
|
1315 |
msgstr[0] ""
|
1316 |
msgstr[1] ""
|
1317 |
|
1318 |
-
#: includes/class-wp-job-manager-post-types.php:
|
1319 |
-
#. translators: Placeholder %s is the number of posts in a preview state.
|
1320 |
msgid "Preview <span class=\"count\">(%s)</span>"
|
1321 |
msgid_plural "Preview <span class=\"count\">(%s)</span>"
|
1322 |
msgstr[0] ""
|
1323 |
msgstr[1] ""
|
1324 |
|
1325 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1326 |
msgid "Invalid ID"
|
1327 |
msgstr ""
|
1328 |
|
1329 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1330 |
msgid "This position has already been filled"
|
1331 |
msgstr ""
|
1332 |
|
1333 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1334 |
-
#. translators: Placeholder %s is the job listing title.
|
1335 |
msgid "%s has been filled"
|
1336 |
msgstr ""
|
1337 |
|
1338 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1339 |
msgid "This position is not filled"
|
1340 |
msgstr ""
|
1341 |
|
1342 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1343 |
-
#. translators: Placeholder %s is the job listing title.
|
1344 |
msgid "%s has been marked as not filled"
|
1345 |
msgstr ""
|
1346 |
|
1347 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1348 |
-
#. translators: Placeholder %s is the job listing title.
|
1349 |
msgid "%s has been deleted"
|
1350 |
msgstr ""
|
1351 |
|
1352 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1353 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1354 |
msgid "Missing submission page."
|
1355 |
msgstr ""
|
1356 |
|
1357 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1358 |
-
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:
|
1359 |
-
#: includes/widgets/class-wp-job-manager-widget-
|
1360 |
-
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:30
|
1361 |
msgid "Title"
|
1362 |
msgstr ""
|
1363 |
|
1364 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1365 |
msgid "Date Posted"
|
1366 |
msgstr ""
|
1367 |
|
1368 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1369 |
msgid "Listing Expires"
|
1370 |
msgstr ""
|
1371 |
|
1372 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1373 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1374 |
msgid "Load more listings"
|
1375 |
msgstr ""
|
1376 |
|
1377 |
-
#: includes/class-wp-job-manager-
|
1378 |
-
#. translators: Placeholder %s is a URL to the document on wpjobmanager.com
|
1379 |
-
#. with info on usage tracking.
|
1380 |
-
msgid ""
|
1381 |
-
"We'd love if you helped us make WP Job Manager better by allowing us to "
|
1382 |
-
"collect\n"
|
1383 |
-
"\t\t\t\t<a href=\"%s\" target=\"_blank\">usage tracking data</a>. No "
|
1384 |
-
"sensitive information is \n"
|
1385 |
-
"\t\t\t\tcollected, and you can opt out at any time."
|
1386 |
-
msgstr ""
|
1387 |
-
|
1388 |
-
#: includes/class-wp-job-manager-usage-tracking.php:175
|
1389 |
-
#. translators: the href tag contains the URL for the page telling users what
|
1390 |
-
#. data WPJM tracks.
|
1391 |
-
msgid ""
|
1392 |
-
"Help us make WP Job Manager better by allowing us to collect\n"
|
1393 |
-
"\t\t\t\t<a href=\"%s\" target=\"_blank\">usage tracking data</a>.\n"
|
1394 |
-
"\t\t\t\tNo sensitive information is collected."
|
1395 |
-
msgstr ""
|
1396 |
-
|
1397 |
-
#: includes/class-wp-job-manager-usage-tracking.php:200
|
1398 |
-
#: lib/usage-tracking/class-usage-tracking-base.php:475
|
1399 |
-
msgid "Enable Usage Tracking"
|
1400 |
-
msgstr ""
|
1401 |
-
|
1402 |
-
#: includes/emails/class-wp-job-manager-email-admin-expiring-job.php:30
|
1403 |
-
msgid "Admin Notice of Expiring Job Listings"
|
1404 |
-
msgstr ""
|
1405 |
-
|
1406 |
-
#: includes/emails/class-wp-job-manager-email-admin-expiring-job.php:40
|
1407 |
-
msgid "Send notices to the site administrator before a job listing expires."
|
1408 |
-
msgstr ""
|
1409 |
-
|
1410 |
-
#: includes/emails/class-wp-job-manager-email-admin-new-job.php:30
|
1411 |
-
msgid "Admin Notice of New Listing"
|
1412 |
-
msgstr ""
|
1413 |
-
|
1414 |
-
#: includes/emails/class-wp-job-manager-email-admin-new-job.php:40
|
1415 |
-
msgid ""
|
1416 |
-
"Send a notice to the site administrator when a new job is submitted on the "
|
1417 |
-
"frontend."
|
1418 |
-
msgstr ""
|
1419 |
-
|
1420 |
-
#: includes/emails/class-wp-job-manager-email-admin-new-job.php:59
|
1421 |
-
#. translators: Placeholder %s is the job listing post title.
|
1422 |
-
msgid "New Job Listing Submitted: %s"
|
1423 |
-
msgstr ""
|
1424 |
-
|
1425 |
-
#: includes/emails/class-wp-job-manager-email-admin-updated-job.php:30
|
1426 |
-
msgid "Admin Notice of Updated Listing"
|
1427 |
-
msgstr ""
|
1428 |
-
|
1429 |
-
#: includes/emails/class-wp-job-manager-email-admin-updated-job.php:40
|
1430 |
-
msgid ""
|
1431 |
-
"Send a notice to the site administrator when a job is updated on the "
|
1432 |
-
"frontend."
|
1433 |
-
msgstr ""
|
1434 |
-
|
1435 |
-
#: includes/emails/class-wp-job-manager-email-admin-updated-job.php:59
|
1436 |
-
#. translators: Placeholder %s is the job listing post title.
|
1437 |
-
msgid "Job Listing Updated: %s"
|
1438 |
-
msgstr ""
|
1439 |
-
|
1440 |
-
#: includes/emails/class-wp-job-manager-email-employer-expiring-job.php:33
|
1441 |
-
msgid "Employer Notice of Expiring Job Listings"
|
1442 |
-
msgstr ""
|
1443 |
-
|
1444 |
-
#: includes/emails/class-wp-job-manager-email-employer-expiring-job.php:43
|
1445 |
-
msgid "Send notices to employers before a job listing expires."
|
1446 |
-
msgstr ""
|
1447 |
-
|
1448 |
-
#: includes/emails/class-wp-job-manager-email-employer-expiring-job.php:75
|
1449 |
-
#. translators: Placeholder %s is the job listing post title.
|
1450 |
-
msgid "Job Listing Expiring: %s"
|
1451 |
-
msgstr ""
|
1452 |
-
|
1453 |
-
#: includes/emails/class-wp-job-manager-email-employer-expiring-job.php:128
|
1454 |
-
msgid "Notice Period"
|
1455 |
-
msgstr ""
|
1456 |
-
|
1457 |
-
#: includes/emails/class-wp-job-manager-email-employer-expiring-job.php:130
|
1458 |
-
msgid "days"
|
1459 |
-
msgstr ""
|
1460 |
-
|
1461 |
-
#: includes/forms/class-wp-job-manager-form-edit-job.php:97
|
1462 |
msgid "Invalid listing"
|
1463 |
msgstr ""
|
1464 |
|
1465 |
-
#: includes/forms/class-wp-job-manager-form-edit-job.php:
|
1466 |
msgid "Save changes"
|
1467 |
msgstr ""
|
1468 |
|
1469 |
-
#: includes/forms/class-wp-job-manager-form-edit-job.php:
|
1470 |
-
|
1471 |
-
msgstr ""
|
1472 |
-
|
1473 |
-
#: includes/forms/class-wp-job-manager-form-edit-job.php:183
|
1474 |
msgid "Your changes have been saved."
|
1475 |
msgstr ""
|
1476 |
|
1477 |
-
#: includes/forms/class-wp-job-manager-form-edit-job.php:
|
1478 |
msgid "View →"
|
1479 |
msgstr ""
|
1480 |
|
1481 |
-
#: includes/forms/class-wp-job-manager-form-
|
1482 |
-
msgid ""
|
1483 |
-
"Your changes have been submitted and your listing will be visible again "
|
1484 |
-
"once approved."
|
1485 |
-
msgstr ""
|
1486 |
-
|
1487 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:69
|
1488 |
msgid "Submit Details"
|
1489 |
msgstr ""
|
1490 |
|
1491 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1492 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1493 |
-
#: templates/job-preview.php:
|
1494 |
msgid "Preview"
|
1495 |
msgstr ""
|
1496 |
|
1497 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1498 |
msgid "Done"
|
1499 |
msgstr ""
|
1500 |
|
1501 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1502 |
msgid "Application email"
|
1503 |
msgstr ""
|
1504 |
|
1505 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1506 |
-
#:
|
1507 |
msgid "you@yourdomain.com"
|
1508 |
msgstr ""
|
1509 |
|
1510 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1511 |
msgid "Application URL"
|
1512 |
msgstr ""
|
1513 |
|
1514 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1515 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1516 |
msgid "http://"
|
1517 |
msgstr ""
|
1518 |
|
1519 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1520 |
msgid "Application email/URL"
|
1521 |
msgstr ""
|
1522 |
|
1523 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1524 |
msgid "Enter an email address or website URL"
|
1525 |
msgstr ""
|
1526 |
|
1527 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1528 |
msgid "Job Title"
|
1529 |
msgstr ""
|
1530 |
|
1531 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1532 |
msgid "Leave this blank if the location is not important"
|
1533 |
msgstr ""
|
1534 |
|
1535 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1536 |
msgid "Choose job type…"
|
1537 |
msgstr ""
|
1538 |
|
1539 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1540 |
msgid "Description"
|
1541 |
msgstr ""
|
1542 |
|
1543 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
|
|
|
|
|
|
|
|
1544 |
msgid "Enter the name of the company"
|
1545 |
msgstr ""
|
1546 |
|
1547 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1548 |
-
#: templates/content-single-job_listing-company.php:
|
1549 |
msgid "Website"
|
1550 |
msgstr ""
|
1551 |
|
1552 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1553 |
msgid "Tagline"
|
1554 |
msgstr ""
|
1555 |
|
1556 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1557 |
msgid "Briefly describe your company"
|
1558 |
msgstr ""
|
1559 |
|
1560 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1561 |
msgid "Video"
|
1562 |
msgstr ""
|
1563 |
|
1564 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1565 |
msgid "A link to a video about your company"
|
1566 |
msgstr ""
|
1567 |
|
1568 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1569 |
msgid "Twitter username"
|
1570 |
msgstr ""
|
1571 |
|
1572 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1573 |
msgid "@yourcompany"
|
1574 |
msgstr ""
|
1575 |
|
1576 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1577 |
msgid "Logo"
|
1578 |
msgstr ""
|
1579 |
|
1580 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1581 |
-
#. translators: Placeholder %s is the label for the required field.
|
1582 |
msgid "%s is a required field"
|
1583 |
msgstr ""
|
1584 |
|
1585 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1586 |
-
#. translators: Placeholder %s is the field label that is did not validate.
|
1587 |
msgid "%s is invalid"
|
1588 |
msgstr ""
|
1589 |
|
1590 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1591 |
-
#: wp-job-manager-functions.php:
|
1592 |
-
|
1593 |
-
#. %3$s is the allowed mime-types.
|
1594 |
-
#. translators: %1$s is the file field label; %2$s is the file type; %3$s is
|
1595 |
-
#. the list of allowed file types.
|
1596 |
-
msgid "\"%1$s\" (filetype %2$s) needs to be one of the following file types: %3$s"
|
1597 |
msgstr ""
|
1598 |
|
1599 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1600 |
msgid "Please enter a valid application email address"
|
1601 |
msgstr ""
|
1602 |
|
1603 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1604 |
msgid "Please enter a valid application URL"
|
1605 |
msgstr ""
|
1606 |
|
1607 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1608 |
msgid "Please enter a valid application email address or URL"
|
1609 |
msgstr ""
|
1610 |
|
1611 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1612 |
msgid "Please enter a username."
|
1613 |
msgstr ""
|
1614 |
|
1615 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1616 |
-
msgid "Please enter a password."
|
1617 |
-
msgstr ""
|
1618 |
-
|
1619 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:543
|
1620 |
msgid "Please enter your email address."
|
1621 |
msgstr ""
|
1622 |
|
1623 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:
|
1624 |
-
msgid "Passwords must match."
|
1625 |
-
msgstr ""
|
1626 |
-
|
1627 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:555
|
1628 |
-
#. translators: Placeholder %s is the password hint.
|
1629 |
-
msgid "Invalid Password: %s"
|
1630 |
-
msgstr ""
|
1631 |
-
|
1632 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:557
|
1633 |
-
msgid "Password is not valid."
|
1634 |
-
msgstr ""
|
1635 |
-
|
1636 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:580
|
1637 |
msgid "You must be signed in to post a new listing."
|
1638 |
msgstr ""
|
1639 |
|
1640 |
-
#: includes/helper/class-wp-job-manager-helper.php:265
|
1641 |
-
msgid "Manage License (Requires Attention)"
|
1642 |
-
msgstr ""
|
1643 |
-
|
1644 |
-
#: includes/helper/class-wp-job-manager-helper.php:268
|
1645 |
-
msgid "Manage License"
|
1646 |
-
msgstr ""
|
1647 |
-
|
1648 |
-
#: includes/helper/class-wp-job-manager-helper.php:271
|
1649 |
-
#: includes/helper/views/html-licences.php:69
|
1650 |
-
msgid "Activate License"
|
1651 |
-
msgstr ""
|
1652 |
-
|
1653 |
-
#: includes/helper/class-wp-job-manager-helper.php:460
|
1654 |
-
msgid ""
|
1655 |
-
"Please enter a valid license key and email address in order to activate "
|
1656 |
-
"this plugin's license."
|
1657 |
-
msgstr ""
|
1658 |
-
|
1659 |
-
#: includes/helper/class-wp-job-manager-helper.php:490
|
1660 |
-
msgid "Connection failed to the License Key API server - possible server issue."
|
1661 |
-
msgstr ""
|
1662 |
-
|
1663 |
-
#: includes/helper/class-wp-job-manager-helper.php:498
|
1664 |
-
msgid "Plugin license has been activated."
|
1665 |
-
msgstr ""
|
1666 |
-
|
1667 |
-
#: includes/helper/class-wp-job-manager-helper.php:500
|
1668 |
-
msgid "An unknown error occurred while attempting to activate the license"
|
1669 |
-
msgstr ""
|
1670 |
-
|
1671 |
-
#: includes/helper/class-wp-job-manager-helper.php:512
|
1672 |
-
msgid "license is not active."
|
1673 |
-
msgstr ""
|
1674 |
-
|
1675 |
-
#: includes/helper/class-wp-job-manager-helper.php:528
|
1676 |
-
msgid "Plugin license has been deactivated."
|
1677 |
-
msgstr ""
|
1678 |
-
|
1679 |
-
#: includes/helper/views/html-licence-key-error.php:7
|
1680 |
-
#: includes/helper/views/html-licence-key-notice.php:7
|
1681 |
-
msgid "Hide notice"
|
1682 |
-
msgstr ""
|
1683 |
-
|
1684 |
-
#: includes/helper/views/html-licences.php:50
|
1685 |
-
#: includes/helper/views/html-licences.php:63
|
1686 |
-
msgid "License"
|
1687 |
-
msgstr ""
|
1688 |
-
|
1689 |
-
#: includes/helper/views/html-licences.php:53
|
1690 |
-
#: includes/helper/views/html-licences.php:66
|
1691 |
-
msgid "Email"
|
1692 |
-
msgstr ""
|
1693 |
-
|
1694 |
-
#: includes/helper/views/html-licences.php:57
|
1695 |
-
msgid "Deactivate License"
|
1696 |
-
msgstr ""
|
1697 |
-
|
1698 |
-
#: includes/helper/views/html-licences.php:79
|
1699 |
-
msgid "No plugins are activated that have licenses managed by WP Job Manager."
|
1700 |
-
msgstr ""
|
1701 |
-
|
1702 |
-
#: includes/rest-api/class-wp-job-manager-controllers-status.php:54
|
1703 |
-
msgid "Not Found"
|
1704 |
-
msgstr ""
|
1705 |
-
|
1706 |
-
#: includes/rest-api/class-wp-job-manager-models-job-types-custom-fields.php:54
|
1707 |
-
msgid "Invalid Employment Type"
|
1708 |
-
msgstr ""
|
1709 |
-
|
1710 |
-
#: includes/rest-api/class-wp-job-manager-models-settings.php:74
|
1711 |
-
msgid "Invalid page ID provided"
|
1712 |
-
msgstr ""
|
1713 |
-
|
1714 |
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:21
|
1715 |
-
|
1716 |
-
#. translators: Placeholder %s is the plural label for the job listing post
|
1717 |
-
#. type.
|
1718 |
-
msgid "Featured %s"
|
1719 |
msgstr ""
|
1720 |
|
1721 |
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:23
|
1722 |
-
|
|
|
1723 |
msgstr ""
|
1724 |
|
1725 |
-
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:
|
1726 |
-
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:
|
1727 |
msgid "Number of listings to show"
|
1728 |
msgstr ""
|
1729 |
|
1730 |
-
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:43
|
1731 |
-
msgid "Sort By"
|
1732 |
-
msgstr ""
|
1733 |
-
|
1734 |
-
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:45
|
1735 |
-
msgid "Date"
|
1736 |
-
msgstr ""
|
1737 |
-
|
1738 |
-
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:47
|
1739 |
-
msgid "Author"
|
1740 |
-
msgstr ""
|
1741 |
-
|
1742 |
-
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:48
|
1743 |
-
msgid "Random"
|
1744 |
-
msgstr ""
|
1745 |
-
|
1746 |
-
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:54
|
1747 |
-
msgid "Sort Direction"
|
1748 |
-
msgstr ""
|
1749 |
-
|
1750 |
-
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:56
|
1751 |
-
msgid "Ascending"
|
1752 |
-
msgstr ""
|
1753 |
-
|
1754 |
-
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:57
|
1755 |
-
msgid "Descending"
|
1756 |
-
msgstr ""
|
1757 |
-
|
1758 |
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:21
|
1759 |
-
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:29
|
1760 |
-
#. translators: Placeholder %s is the plural label for the job listing post
|
1761 |
-
#. type.
|
1762 |
-
msgid "Recent %s"
|
1763 |
-
msgstr ""
|
1764 |
-
|
1765 |
-
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:23
|
1766 |
msgid ""
|
1767 |
"Display a list of recent listings on your site, optionally matching a "
|
1768 |
"keyword and location."
|
1769 |
msgstr ""
|
1770 |
|
1771 |
-
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:
|
1772 |
-
|
1773 |
-
|
1774 |
-
|
1775 |
-
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:53
|
1776 |
-
msgid "Show Company Logo"
|
1777 |
-
msgstr ""
|
1778 |
-
|
1779 |
-
#: lib/usage-tracking/class-usage-tracking-base.php:336
|
1780 |
-
msgid "Every Two Weeks"
|
1781 |
-
msgstr ""
|
1782 |
-
|
1783 |
-
#: lib/usage-tracking/class-usage-tracking-base.php:478
|
1784 |
-
msgid "Disable Usage Tracking"
|
1785 |
-
msgstr ""
|
1786 |
-
|
1787 |
-
#: lib/usage-tracking/class-usage-tracking-base.php:484
|
1788 |
-
msgid "Usage data enabled. Thank you!"
|
1789 |
-
msgstr ""
|
1790 |
-
|
1791 |
-
#: lib/usage-tracking/class-usage-tracking-base.php:487
|
1792 |
-
msgid "Disabled usage tracking."
|
1793 |
-
msgstr ""
|
1794 |
-
|
1795 |
-
#: lib/usage-tracking/class-usage-tracking-base.php:490
|
1796 |
-
msgid "Something went wrong. Please try again later."
|
1797 |
-
msgstr ""
|
1798 |
-
|
1799 |
-
#: lib/wpjm_rest/class-wp-job-manager-rest-model.php:214
|
1800 |
-
#. translators: %s is usually a field name.
|
1801 |
-
msgid "%s cannot be empty"
|
1802 |
-
msgstr ""
|
1803 |
-
|
1804 |
-
#: lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-crud.php:48
|
1805 |
-
msgid "Model not found"
|
1806 |
msgstr ""
|
1807 |
|
1808 |
-
#:
|
1809 |
-
msgid "
|
1810 |
msgstr ""
|
1811 |
|
1812 |
-
#: templates/account-signin.php:
|
1813 |
msgid "Your account"
|
1814 |
msgstr ""
|
1815 |
|
1816 |
-
#: templates/account-signin.php:
|
1817 |
msgid "You are currently signed in as <strong>%s</strong>."
|
1818 |
msgstr ""
|
1819 |
|
1820 |
-
#: templates/account-signin.php:
|
1821 |
msgid "Sign out"
|
1822 |
msgstr ""
|
1823 |
|
1824 |
-
#: templates/account-signin.php:
|
1825 |
msgid "Have an account?"
|
1826 |
msgstr ""
|
1827 |
|
1828 |
-
#: templates/account-signin.php:
|
1829 |
msgid "Sign in"
|
1830 |
msgstr ""
|
1831 |
|
1832 |
-
#: templates/account-signin.php:
|
1833 |
msgid ""
|
1834 |
-
"If you don
|
1835 |
-
"email address/username."
|
|
|
1836 |
msgstr ""
|
1837 |
|
1838 |
-
#: templates/account-signin.php:
|
1839 |
msgid "optionally"
|
1840 |
msgstr ""
|
1841 |
|
1842 |
-
#: templates/account-signin.php:
|
1843 |
-
msgid "
|
1844 |
msgstr ""
|
1845 |
|
1846 |
-
#: templates/account-signin.php:
|
1847 |
-
msgid "
|
1848 |
msgstr ""
|
1849 |
|
1850 |
-
#: templates/account-signin.php:
|
1851 |
-
#: templates/job-submit.php:
|
1852 |
msgid "(optional)"
|
1853 |
msgstr ""
|
1854 |
|
1855 |
-
#: templates/
|
|
|
|
|
|
|
|
|
1856 |
msgid "There are no listings matching your search."
|
1857 |
msgstr ""
|
1858 |
|
1859 |
-
#: templates/content-no-jobs-found.php:
|
1860 |
msgid "There are currently no vacancies."
|
1861 |
msgstr ""
|
1862 |
|
1863 |
-
#: templates/content-single-job_listing-meta.php:
|
1864 |
msgid "This position has been filled"
|
1865 |
msgstr ""
|
1866 |
|
1867 |
-
#: templates/content-single-job_listing-meta.php:
|
1868 |
msgid "Applications have closed"
|
1869 |
msgstr ""
|
1870 |
|
1871 |
-
#: templates/content-single-job_listing.php:
|
1872 |
msgid "This listing has expired."
|
1873 |
msgstr ""
|
1874 |
|
1875 |
-
#: templates/
|
1876 |
-
#: templates/emails/employer-expiring-job.php:32
|
1877 |
-
msgid "The following job listing is expiring today from <a href=\"%s\">%s</a>."
|
1878 |
-
msgstr ""
|
1879 |
-
|
1880 |
-
#: templates/emails/admin-expiring-job.php:32
|
1881 |
-
#: templates/emails/employer-expiring-job.php:40
|
1882 |
-
msgid "The following job listing is expiring soon from <a href=\"%s\">%s</a>."
|
1883 |
-
msgstr ""
|
1884 |
-
|
1885 |
-
#: templates/emails/admin-expiring-job.php:35
|
1886 |
-
msgid "Visit <a href=\"%s\">WordPress admin</a> to manage the listing."
|
1887 |
-
msgstr ""
|
1888 |
-
|
1889 |
-
#: templates/emails/admin-new-job.php:26
|
1890 |
-
msgid "A new job listing has been submitted to <a href=\"%s\">%s</a>."
|
1891 |
-
msgstr ""
|
1892 |
-
|
1893 |
-
#: templates/emails/admin-new-job.php:33
|
1894 |
-
#: templates/emails/plain/admin-new-job.php:26
|
1895 |
-
msgid "It has been published and is now available to the public."
|
1896 |
-
msgstr ""
|
1897 |
-
|
1898 |
-
#: templates/emails/admin-new-job.php:38
|
1899 |
-
msgid ""
|
1900 |
-
"It is awaiting approval by an administrator in <a href=\"%s\">WordPress "
|
1901 |
-
"admin</a>."
|
1902 |
-
msgstr ""
|
1903 |
-
|
1904 |
-
#: templates/emails/admin-updated-job.php:25
|
1905 |
-
msgid "A job listing has been updated on <a href=\"%s\">%s</a>."
|
1906 |
-
msgstr ""
|
1907 |
-
|
1908 |
-
#: templates/emails/admin-updated-job.php:28
|
1909 |
-
#: templates/emails/plain/admin-updated-job.php:26
|
1910 |
-
msgid "The changes have been published and are now available to the public."
|
1911 |
-
msgstr ""
|
1912 |
-
|
1913 |
-
#: templates/emails/admin-updated-job.php:32
|
1914 |
-
msgid ""
|
1915 |
-
"The job listing is not publicly available until the changes are approved by "
|
1916 |
-
"an administrator in the site's <a href=\"%s\">WordPress admin</a>."
|
1917 |
-
msgstr ""
|
1918 |
-
|
1919 |
-
#: templates/emails/employer-expiring-job.php:48
|
1920 |
-
msgid "Visit the <a href=\"%s\">job listing dashboard</a> to manage the listing."
|
1921 |
-
msgstr ""
|
1922 |
-
|
1923 |
-
#: templates/emails/plain/admin-expiring-job.php:30
|
1924 |
-
#: templates/emails/plain/employer-expiring-job.php:29
|
1925 |
-
msgid "The following job listing is expiring today from %s (%s)."
|
1926 |
-
msgstr ""
|
1927 |
-
|
1928 |
-
#: templates/emails/plain/admin-expiring-job.php:36
|
1929 |
-
#: templates/emails/plain/employer-expiring-job.php:31
|
1930 |
-
msgid "The following job listing is expiring soon from %s (%s)."
|
1931 |
-
msgstr ""
|
1932 |
-
|
1933 |
-
#: templates/emails/plain/admin-expiring-job.php:43
|
1934 |
-
msgid "Visit WordPress admin (%s) to manage the listing."
|
1935 |
-
msgstr ""
|
1936 |
-
|
1937 |
-
#: templates/emails/plain/admin-new-job.php:23
|
1938 |
-
msgid "A new job listing has been submitted to %s (%s)."
|
1939 |
-
msgstr ""
|
1940 |
-
|
1941 |
-
#: templates/emails/plain/admin-new-job.php:29
|
1942 |
-
msgid "It is awaiting approval by an administrator in WordPress admin (%s)."
|
1943 |
-
msgstr ""
|
1944 |
-
|
1945 |
-
#: templates/emails/plain/admin-updated-job.php:23
|
1946 |
-
msgid "A job listing has been updated on %s (%s)."
|
1947 |
-
msgstr ""
|
1948 |
-
|
1949 |
-
#: templates/emails/plain/admin-updated-job.php:29
|
1950 |
-
msgid ""
|
1951 |
-
"The job listing is not publicly available until the changes are approved by "
|
1952 |
-
"an administrator in the site's WordPress admin (%s)."
|
1953 |
-
msgstr ""
|
1954 |
-
|
1955 |
-
#: templates/emails/plain/employer-expiring-job.php:33
|
1956 |
-
msgid "Visit the job listing dashboard (%s) to manage the listing."
|
1957 |
-
msgstr ""
|
1958 |
-
|
1959 |
-
#: templates/form-fields/file-field.php:45
|
1960 |
msgid "Maximum file size: %s."
|
1961 |
msgstr ""
|
1962 |
|
1963 |
-
#: templates/form-fields/multiselect-field.php:
|
1964 |
-
#: wp-job-manager-functions.php:
|
1965 |
msgid "No results match"
|
1966 |
msgstr ""
|
1967 |
|
1968 |
-
#: templates/form-fields/multiselect-field.php:
|
1969 |
-
#: wp-job-manager-functions.php:
|
1970 |
msgid "Select Some Options"
|
1971 |
msgstr ""
|
1972 |
|
1973 |
-
#: templates/form-fields/uploaded-file-html.php:
|
1974 |
-
#: templates/form-fields/uploaded-file-html.php:
|
1975 |
msgid "remove"
|
1976 |
msgstr ""
|
1977 |
|
1978 |
-
#: templates/job-application-email.php:
|
1979 |
msgid ""
|
1980 |
"To apply for this job <strong>email your details to</strong> <a "
|
1981 |
"class=\"job_application_email\" href=\"mailto:%1$s%2$s\">%1$s</a>"
|
1982 |
msgstr ""
|
1983 |
|
1984 |
-
#: templates/job-application-url.php:
|
1985 |
-
msgid "To apply for this job please visit"
|
1986 |
msgstr ""
|
1987 |
|
1988 |
-
#: templates/job-application.php:
|
1989 |
msgid "Apply for job"
|
1990 |
msgstr ""
|
1991 |
|
1992 |
-
#: templates/job-dashboard-login.php:
|
1993 |
msgid "You need to be signed in to manage your listings."
|
1994 |
msgstr ""
|
1995 |
|
1996 |
-
#: templates/job-dashboard.php:
|
1997 |
msgid "Your listings are shown in the table below."
|
1998 |
msgstr ""
|
1999 |
|
2000 |
-
#: templates/job-dashboard.php:
|
2001 |
msgid "You do not have any active listings."
|
2002 |
msgstr ""
|
2003 |
|
2004 |
-
#: templates/job-dashboard.php:
|
2005 |
-
msgid "Featured Job"
|
2006 |
-
msgstr ""
|
2007 |
-
|
2008 |
-
#: templates/job-dashboard.php:55
|
2009 |
msgid "Mark not filled"
|
2010 |
msgstr ""
|
2011 |
|
2012 |
-
#: templates/job-dashboard.php:
|
2013 |
msgid "Mark filled"
|
2014 |
msgstr ""
|
2015 |
|
2016 |
-
#: templates/job-dashboard.php:
|
2017 |
msgid "Duplicate"
|
2018 |
msgstr ""
|
2019 |
|
2020 |
-
#: templates/job-dashboard.php:
|
2021 |
msgid "Relist"
|
2022 |
msgstr ""
|
2023 |
|
2024 |
-
#: templates/job-filters.php:
|
2025 |
msgid "Keywords"
|
2026 |
msgstr ""
|
2027 |
|
2028 |
-
#: templates/job-filters.php:
|
2029 |
msgid "Category"
|
2030 |
msgstr ""
|
2031 |
|
2032 |
-
#: templates/job-filters.php:
|
2033 |
msgid "Any category"
|
2034 |
msgstr ""
|
2035 |
|
2036 |
-
#: templates/job-filters.php:
|
2037 |
msgid ""
|
2038 |
"Your browser does not support JavaScript, or it is disabled. JavaScript "
|
2039 |
"must be enabled in order to view listings."
|
2040 |
msgstr ""
|
2041 |
|
2042 |
-
#: templates/job-preview.php:
|
2043 |
msgid "Submit Listing"
|
2044 |
msgstr ""
|
2045 |
|
2046 |
-
#: templates/job-preview.php:
|
2047 |
msgid "Edit listing"
|
2048 |
msgstr ""
|
2049 |
|
2050 |
-
#: templates/job-submit.php:
|
2051 |
msgid "You are editing an existing job. %s"
|
2052 |
msgstr ""
|
2053 |
|
2054 |
-
#: templates/job-submit.php:
|
2055 |
msgid "Create A New Job"
|
2056 |
msgstr ""
|
2057 |
|
2058 |
-
#: templates/job-submit.php:
|
2059 |
msgid "Company Details"
|
2060 |
msgstr ""
|
2061 |
|
2062 |
-
#: templates/job-submitted.php:
|
2063 |
msgid "%s listed successfully. To view your listing <a href=\"%s\">click here</a>."
|
2064 |
msgstr ""
|
2065 |
|
2066 |
-
#: templates/job-submitted.php:
|
2067 |
msgid "%s submitted successfully. Your listing will be visible once approved."
|
2068 |
msgstr ""
|
2069 |
|
2070 |
-
#: wp-job-manager-functions.php:
|
2071 |
msgid "Reset"
|
2072 |
msgstr ""
|
2073 |
|
2074 |
-
#: wp-job-manager-functions.php:
|
2075 |
msgid "RSS"
|
2076 |
msgstr ""
|
2077 |
|
2078 |
-
#: wp-job-manager-functions.php:
|
2079 |
msgid "Invalid email address."
|
2080 |
msgstr ""
|
2081 |
|
2082 |
-
#: wp-job-manager-functions.php:
|
2083 |
msgid "Your email address isn’t correct."
|
2084 |
msgstr ""
|
2085 |
|
2086 |
-
#: wp-job-manager-functions.php:
|
2087 |
msgid "This email is already registered, please choose another one."
|
2088 |
msgstr ""
|
2089 |
|
2090 |
-
#: wp-job-manager-functions.php:
|
2091 |
-
msgid "Full Time"
|
2092 |
-
msgstr ""
|
2093 |
-
|
2094 |
-
#: wp-job-manager-functions.php:867
|
2095 |
-
msgid "Part Time"
|
2096 |
-
msgstr ""
|
2097 |
-
|
2098 |
-
#: wp-job-manager-functions.php:868
|
2099 |
-
msgid "Contractor"
|
2100 |
-
msgstr ""
|
2101 |
-
|
2102 |
-
#: wp-job-manager-functions.php:869
|
2103 |
-
msgid "Temporary"
|
2104 |
-
msgstr ""
|
2105 |
-
|
2106 |
-
#: wp-job-manager-functions.php:870
|
2107 |
-
msgid "Intern"
|
2108 |
-
msgstr ""
|
2109 |
-
|
2110 |
-
#: wp-job-manager-functions.php:871
|
2111 |
-
msgid "Volunteer"
|
2112 |
-
msgstr ""
|
2113 |
-
|
2114 |
-
#: wp-job-manager-functions.php:872
|
2115 |
-
msgid "Per Diem"
|
2116 |
-
msgstr ""
|
2117 |
-
|
2118 |
-
#: wp-job-manager-functions.php:873
|
2119 |
-
msgid "Other"
|
2120 |
-
msgstr ""
|
2121 |
-
|
2122 |
-
#: wp-job-manager-functions.php:940
|
2123 |
-
msgid "Passwords must be at least 8 characters long."
|
2124 |
-
msgstr ""
|
2125 |
-
|
2126 |
-
#: wp-job-manager-functions.php:1059
|
2127 |
msgid "Choose a category…"
|
2128 |
msgstr ""
|
2129 |
|
2130 |
-
#: wp-job-manager-functions.php:
|
2131 |
-
#. translators: %s is the list of allowed file types.
|
2132 |
msgid "Uploaded files need to be one of the following file types: %s"
|
2133 |
msgstr ""
|
2134 |
|
2135 |
-
#: wp-job-manager-template.php:
|
2136 |
msgid "Inactive"
|
2137 |
msgstr ""
|
2138 |
|
2139 |
-
#: wp-job-manager-template.php:
|
2140 |
-
|
2141 |
-
#. WordPress instance.
|
2142 |
-
msgid "Application via \"%1$s\" listing on %2$s"
|
2143 |
msgstr ""
|
2144 |
|
2145 |
-
#: wp-job-manager-template.php:
|
2146 |
-
msgid "Username"
|
2147 |
-
msgstr ""
|
2148 |
-
|
2149 |
-
#: wp-job-manager-template.php:699
|
2150 |
-
msgid "Password"
|
2151 |
-
msgstr ""
|
2152 |
-
|
2153 |
-
#: wp-job-manager-template.php:709
|
2154 |
-
msgid "Verify Password"
|
2155 |
-
msgstr ""
|
2156 |
-
|
2157 |
-
#: wp-job-manager-template.php:716
|
2158 |
-
msgid "Your email"
|
2159 |
-
msgstr ""
|
2160 |
-
|
2161 |
-
#: wp-job-manager-template.php:743
|
2162 |
msgid "Posted on "
|
2163 |
msgstr ""
|
2164 |
|
2165 |
-
#: wp-job-manager-template.php:
|
2166 |
-
#. translators: Placeholder %s is the relative, human readable time since the
|
2167 |
-
#. job listing was posted.
|
2168 |
msgid "Posted %s ago"
|
2169 |
msgstr ""
|
2170 |
|
2171 |
-
#: wp-job-manager-template.php:
|
2172 |
msgid "Anywhere"
|
2173 |
msgstr ""
|
2174 |
|
2175 |
-
#: wp-job-manager.php:
|
2176 |
-
#. translators: Placeholders %1$s and %2$s are the names of the two cookies
|
2177 |
-
#. used in WP Job Manager.
|
2178 |
-
msgid ""
|
2179 |
-
"This site adds the following cookies to help users resume job submissions "
|
2180 |
-
"that they \n"
|
2181 |
-
"\t\t\t\thave started but have not completed: %1$s and %2$s"
|
2182 |
-
msgstr ""
|
2183 |
-
|
2184 |
-
#: wp-job-manager.php:332
|
2185 |
msgid "Load previous listings"
|
2186 |
msgstr ""
|
2187 |
|
2188 |
-
#: wp-job-manager.php:
|
2189 |
msgid "Invalid file type. Accepted types:"
|
2190 |
msgstr ""
|
2191 |
|
2192 |
-
#: wp-job-manager.php:
|
2193 |
msgid "Are you sure you want to delete this listing?"
|
2194 |
msgstr ""
|
2195 |
|
|
|
|
|
|
|
|
|
2196 |
#. Author URI of the plugin/theme
|
2197 |
msgid "https://wpjobmanager.com/"
|
2198 |
msgstr ""
|
@@ -2207,80 +1433,82 @@ msgstr ""
|
|
2207 |
msgid "Automattic"
|
2208 |
msgstr ""
|
2209 |
|
2210 |
-
#: includes/admin/class-wp-job-manager-admin.php:
|
2211 |
-
#: includes/forms/class-wp-job-manager-form-submit-job.php:413
|
2212 |
#. translators: jQuery date format, see
|
2213 |
#. http:api.jqueryui.com/datepicker/#utility-formatDate
|
2214 |
msgctxt "Date format for jQuery datepicker."
|
2215 |
msgid "yy-mm-dd"
|
2216 |
msgstr ""
|
2217 |
|
2218 |
-
#: includes/admin/class-wp-job-manager-
|
2219 |
-
#: includes/class-wp-job-manager-post-types.php:701
|
2220 |
-
msgctxt "Job permalink - resave permalinks after changing this"
|
2221 |
-
msgid "job"
|
2222 |
-
msgstr ""
|
2223 |
-
|
2224 |
-
#: includes/admin/class-wp-job-manager-permalink-settings.php:95
|
2225 |
-
#: includes/class-wp-job-manager-post-types.php:702
|
2226 |
-
msgctxt "Job category slug - resave permalinks after changing this"
|
2227 |
-
msgid "job-category"
|
2228 |
-
msgstr ""
|
2229 |
-
|
2230 |
-
#: includes/admin/class-wp-job-manager-permalink-settings.php:104
|
2231 |
-
#: includes/class-wp-job-manager-post-types.php:703
|
2232 |
-
msgctxt "Job type slug - resave permalinks after changing this"
|
2233 |
-
msgid "job-type"
|
2234 |
-
msgstr ""
|
2235 |
-
|
2236 |
-
#: includes/admin/class-wp-job-manager-setup.php:274
|
2237 |
msgctxt "Default page title (wizard)"
|
2238 |
msgid "Post a Job"
|
2239 |
msgstr ""
|
2240 |
|
2241 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
2242 |
msgctxt "Default page title (wizard)"
|
2243 |
msgid "Job Dashboard"
|
2244 |
msgstr ""
|
2245 |
|
2246 |
-
#: includes/admin/class-wp-job-manager-setup.php:
|
2247 |
msgctxt "Default page title (wizard)"
|
2248 |
msgid "Jobs"
|
2249 |
msgstr ""
|
2250 |
|
2251 |
-
#: includes/class-wp-job-manager-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2252 |
msgctxt "Post type archive slug - resave permalinks after changing this"
|
2253 |
msgid "jobs"
|
2254 |
msgstr ""
|
2255 |
|
2256 |
-
#: includes/class-wp-job-manager-post-types.php:
|
2257 |
-
|
|
|
|
|
|
|
|
|
|
|
2258 |
msgctxt "post status"
|
2259 |
msgid "Expired"
|
2260 |
msgstr ""
|
2261 |
|
2262 |
-
#: includes/class-wp-job-manager-post-types.php:
|
2263 |
-
#: wp-job-manager-functions.php:
|
2264 |
msgctxt "post status"
|
2265 |
msgid "Preview"
|
2266 |
msgstr ""
|
2267 |
|
2268 |
-
#: wp-job-manager-functions.php:
|
2269 |
msgctxt "post status"
|
2270 |
msgid "Draft"
|
2271 |
msgstr ""
|
2272 |
|
2273 |
-
#: wp-job-manager-functions.php:
|
2274 |
msgctxt "post status"
|
2275 |
msgid "Pending approval"
|
2276 |
msgstr ""
|
2277 |
|
2278 |
-
#: wp-job-manager-functions.php:
|
2279 |
msgctxt "post status"
|
2280 |
msgid "Pending payment"
|
2281 |
msgstr ""
|
2282 |
|
2283 |
-
#: wp-job-manager-functions.php:
|
2284 |
msgctxt "post status"
|
2285 |
msgid "Active"
|
2286 |
msgstr ""
|
1 |
+
# Copyright (C) 2017 Automattic
|
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"
|
11 |
+
"PO-Revision-Date: 2017-MO-DA HO:MI+ZONE\n"
|
12 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
+
"X-Generator: grunt-wp-i18n 0.5.4\n"
|
15 |
|
16 |
+
#: includes/admin/class-wp-job-manager-addons.php:82
|
17 |
+
#: includes/admin/class-wp-job-manager-admin.php:82
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
msgid "WP Job Manager Add-ons"
|
19 |
msgstr ""
|
20 |
|
21 |
+
#: includes/admin/class-wp-job-manager-addons.php:84
|
22 |
+
msgid "Do you need multiple add-ons?"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
msgstr ""
|
24 |
|
25 |
+
#: includes/admin/class-wp-job-manager-addons.php:84
|
26 |
+
msgid "Check out the core add-on bundle →"
|
|
|
|
|
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
|
120 |
+
#: templates/job-filters.php:17 templates/job-filters.php:18
|
|
|
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 |
|
199 |
+
#: includes/admin/class-wp-job-manager-settings.php:69
|
200 |
msgid "Listings Per Page"
|
201 |
msgstr ""
|
202 |
|
203 |
+
#: includes/admin/class-wp-job-manager-settings.php:70
|
204 |
+
msgid "How many listings should be shown per page by default?"
|
205 |
msgstr ""
|
206 |
|
207 |
+
#: includes/admin/class-wp-job-manager-settings.php:76
|
208 |
msgid "Filled Positions"
|
209 |
msgstr ""
|
210 |
|
211 |
+
#: includes/admin/class-wp-job-manager-settings.php:77
|
212 |
msgid "Hide filled positions"
|
213 |
msgstr ""
|
214 |
|
215 |
+
#: includes/admin/class-wp-job-manager-settings.php:78
|
216 |
+
msgid "If enabled, filled positions will be hidden from archives."
|
217 |
msgstr ""
|
218 |
|
219 |
+
#: includes/admin/class-wp-job-manager-settings.php:85
|
220 |
msgid "Hide Expired Listings"
|
221 |
msgstr ""
|
222 |
|
223 |
+
#: includes/admin/class-wp-job-manager-settings.php:86
|
224 |
+
msgid "Hide expired listings in job archive/search"
|
225 |
msgstr ""
|
226 |
|
227 |
+
#: includes/admin/class-wp-job-manager-settings.php:87
|
228 |
+
msgid "If enabled, expired job listing is not searchable."
|
229 |
msgstr ""
|
230 |
|
231 |
+
#: includes/admin/class-wp-job-manager-settings.php:94
|
232 |
msgid "Hide Expired Listings Content"
|
233 |
msgstr ""
|
234 |
|
235 |
+
#: includes/admin/class-wp-job-manager-settings.php:95
|
236 |
+
msgid "Hide expired listing content in single job listing (singular)"
|
237 |
msgstr ""
|
238 |
|
239 |
+
#: includes/admin/class-wp-job-manager-settings.php:96
|
240 |
msgid ""
|
241 |
+
"If enabled, the content within expired listings will be hidden. Otherwise, "
|
242 |
+
"expired listings will be displayed as normal (without the application area)."
|
|
|
243 |
msgstr ""
|
244 |
|
245 |
+
#: includes/admin/class-wp-job-manager-settings.php:104
|
246 |
+
msgid "Enable categories for listings"
|
247 |
msgstr ""
|
248 |
|
249 |
+
#: includes/admin/class-wp-job-manager-settings.php:105
|
250 |
msgid ""
|
251 |
+
"Choose whether to enable categories. Categories must be setup by an admin "
|
252 |
+
"to allow users to choose them during submission."
|
253 |
msgstr ""
|
254 |
|
255 |
+
#: includes/admin/class-wp-job-manager-settings.php:112
|
256 |
msgid "Multi-select Categories"
|
257 |
msgstr ""
|
258 |
|
259 |
+
#: includes/admin/class-wp-job-manager-settings.php:113
|
260 |
+
msgid "Enable category multiselect by default"
|
261 |
msgstr ""
|
262 |
|
263 |
+
#: includes/admin/class-wp-job-manager-settings.php:114
|
264 |
msgid ""
|
265 |
+
"If enabled, the category select box will default to a multiselect on the "
|
266 |
+
"[jobs] shortcode."
|
|
|
267 |
msgstr ""
|
268 |
|
269 |
+
#: includes/admin/class-wp-job-manager-settings.php:121
|
270 |
msgid "Category Filter Type"
|
271 |
msgstr ""
|
272 |
|
273 |
+
#: includes/admin/class-wp-job-manager-settings.php:122
|
274 |
msgid ""
|
275 |
"Determines the logic used to display jobs when selecting multiple "
|
276 |
"categories."
|
277 |
msgstr ""
|
278 |
|
279 |
+
#: includes/admin/class-wp-job-manager-settings.php:125
|
280 |
msgid "Jobs will be shown if within ANY selected category"
|
281 |
msgstr ""
|
282 |
|
283 |
+
#: includes/admin/class-wp-job-manager-settings.php:126
|
284 |
msgid "Jobs will be shown if within ALL selected categories"
|
285 |
msgstr ""
|
286 |
|
287 |
+
#: includes/admin/class-wp-job-manager-settings.php:132
|
288 |
+
msgid "Date Format"
|
|
|
|
|
|
|
|
|
289 |
msgstr ""
|
290 |
|
291 |
+
#: includes/admin/class-wp-job-manager-settings.php:133
|
292 |
msgid ""
|
293 |
+
"Choose how you want the published date for jobs to be displayed on the "
|
294 |
+
"front-end."
|
295 |
msgstr ""
|
296 |
|
297 |
+
#: includes/admin/class-wp-job-manager-settings.php:136
|
298 |
+
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
|
306 |
+
msgid "Types"
|
|
|
|
|
|
|
307 |
msgstr ""
|
308 |
|
309 |
+
#: includes/admin/class-wp-job-manager-settings.php:144
|
310 |
+
msgid "Enable types for listings"
|
311 |
msgstr ""
|
312 |
|
313 |
+
#: includes/admin/class-wp-job-manager-settings.php:145
|
314 |
+
msgid ""
|
315 |
+
"Choose whether to enable types. Types must be setup by an admin to allow "
|
316 |
+
"users to choose them during submission."
|
317 |
msgstr ""
|
318 |
|
319 |
+
#: includes/admin/class-wp-job-manager-settings.php:152
|
320 |
+
msgid "Multi-select Listing Types"
|
321 |
msgstr ""
|
322 |
|
323 |
+
#: includes/admin/class-wp-job-manager-settings.php:153
|
324 |
+
msgid "Enable multiple types for listings"
|
325 |
msgstr ""
|
326 |
|
327 |
+
#: includes/admin/class-wp-job-manager-settings.php:154
|
328 |
+
msgid ""
|
329 |
+
"If enabled each job can have more than one type. The metabox on the post "
|
330 |
+
"editor and the select box on the frontend job submission form are changed "
|
331 |
+
"by this."
|
332 |
msgstr ""
|
333 |
|
334 |
+
#: includes/admin/class-wp-job-manager-settings.php:161
|
335 |
+
msgid "Google Maps API Key"
|
336 |
msgstr ""
|
337 |
|
338 |
+
#: includes/admin/class-wp-job-manager-settings.php:162
|
339 |
msgid ""
|
340 |
+
"Google requires an API key to retrieve location information for job "
|
341 |
+
"listings. Acquire an API key from the <a href=\"%s\">Google Maps API "
|
342 |
+
"developer site</a>."
|
|
|
|
|
|
|
|
|
343 |
msgstr ""
|
344 |
|
345 |
+
#: includes/admin/class-wp-job-manager-settings.php:168
|
346 |
+
msgid "Job Submission"
|
347 |
msgstr ""
|
348 |
|
349 |
+
#: includes/admin/class-wp-job-manager-settings.php:173
|
350 |
+
msgid "Account Required"
|
|
|
|
|
|
|
351 |
msgstr ""
|
352 |
|
353 |
+
#: includes/admin/class-wp-job-manager-settings.php:174
|
354 |
+
msgid "Submitting listings requires an account"
|
355 |
msgstr ""
|
356 |
|
357 |
+
#: includes/admin/class-wp-job-manager-settings.php:175
|
358 |
+
msgid ""
|
359 |
+
"If disabled, non-logged in users will be able to submit listings without "
|
360 |
+
"creating an account."
|
361 |
msgstr ""
|
362 |
|
363 |
+
#: includes/admin/class-wp-job-manager-settings.php:182
|
364 |
+
msgid "Account Creation"
|
|
|
|
|
|
|
365 |
msgstr ""
|
366 |
|
367 |
+
#: includes/admin/class-wp-job-manager-settings.php:183
|
368 |
+
msgid "Allow account creation"
|
369 |
msgstr ""
|
370 |
|
371 |
+
#: includes/admin/class-wp-job-manager-settings.php:184
|
372 |
msgid ""
|
373 |
+
"If enabled, non-logged in users will be able to create an account by "
|
374 |
+
"entering their email address on the submission form."
|
|
|
375 |
msgstr ""
|
376 |
|
377 |
+
#: includes/admin/class-wp-job-manager-settings.php:191
|
378 |
+
msgid "Account Username"
|
379 |
msgstr ""
|
380 |
|
381 |
+
#: includes/admin/class-wp-job-manager-settings.php:192
|
382 |
+
msgid "Automatically Generate Username from Email Address"
|
383 |
msgstr ""
|
384 |
|
385 |
+
#: includes/admin/class-wp-job-manager-settings.php:193
|
386 |
msgid ""
|
387 |
+
"If enabled, a username will be generated from the first part of the user "
|
388 |
+
"email address. Otherwise, a username field will be shown."
|
|
|
|
|
|
|
|
|
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…"
|
499 |
msgstr ""
|
500 |
|
501 |
+
#: includes/admin/class-wp-job-manager-settings.php:422
|
502 |
+
msgid "Save Changes"
|
503 |
+
msgstr ""
|
504 |
+
|
505 |
+
#: includes/admin/class-wp-job-manager-setup.php:51
|
506 |
msgid "Setup"
|
507 |
msgstr ""
|
508 |
|
509 |
+
#: includes/admin/class-wp-job-manager-setup.php:148
|
510 |
msgid "WP Job Manager Setup"
|
511 |
msgstr ""
|
512 |
|
513 |
+
#: includes/admin/class-wp-job-manager-setup.php:151
|
514 |
msgid "1. Introduction"
|
515 |
msgstr ""
|
516 |
|
517 |
+
#: includes/admin/class-wp-job-manager-setup.php:152
|
518 |
msgid "2. Page Setup"
|
519 |
msgstr ""
|
520 |
|
521 |
+
#: includes/admin/class-wp-job-manager-setup.php:153
|
522 |
msgid "3. Done"
|
523 |
msgstr ""
|
524 |
|
525 |
+
#: includes/admin/class-wp-job-manager-setup.php:158
|
526 |
+
msgid "Setup Wizard Introduction"
|
527 |
msgstr ""
|
528 |
|
529 |
+
#: includes/admin/class-wp-job-manager-setup.php:160
|
530 |
+
msgid "Thanks for installing <em>WP Job Manager</em>!"
|
|
|
|
|
531 |
msgstr ""
|
532 |
|
533 |
+
#: includes/admin/class-wp-job-manager-setup.php:161
|
534 |
msgid ""
|
535 |
+
"This setup wizard will help you get started by creating the pages for job "
|
536 |
+
"submission, job management, and listing your jobs."
|
537 |
msgstr ""
|
538 |
|
539 |
+
#: includes/admin/class-wp-job-manager-setup.php:162
|
|
|
540 |
msgid ""
|
541 |
+
"If you want to skip the wizard and setup the pages and shortcodes yourself "
|
542 |
+
"manually, the process is still relatively simple. Refer to the "
|
543 |
+
"%sdocumentation%s for help."
|
544 |
msgstr ""
|
545 |
|
546 |
+
#: includes/admin/class-wp-job-manager-setup.php:165
|
547 |
+
msgid "Continue to page setup"
|
548 |
msgstr ""
|
549 |
|
550 |
+
#: includes/admin/class-wp-job-manager-setup.php:166
|
551 |
+
msgid "Skip setup. I will setup the plugin manually"
|
552 |
msgstr ""
|
553 |
|
554 |
+
#: includes/admin/class-wp-job-manager-setup.php:172
|
555 |
msgid "Page Setup"
|
556 |
msgstr ""
|
557 |
|
558 |
+
#: includes/admin/class-wp-job-manager-setup.php:174
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
559 |
msgid ""
|
560 |
+
"<em>WP Job Manager</em> includes %1$sshortcodes%2$s which can be used "
|
561 |
+
"within your %3$spages%2$s to output content. These can be created for you "
|
562 |
+
"below. For more information on the job shortcodes view the %4$sshortcode "
|
563 |
+
"documentation%2$s."
|
|
|
|
|
|
|
564 |
msgstr ""
|
565 |
|
566 |
+
#: includes/admin/class-wp-job-manager-setup.php:182
|
567 |
msgid "Page Title"
|
568 |
msgstr ""
|
569 |
|
570 |
+
#: includes/admin/class-wp-job-manager-setup.php:183
|
571 |
msgid "Page Description"
|
572 |
msgstr ""
|
573 |
|
574 |
+
#: includes/admin/class-wp-job-manager-setup.php:184
|
575 |
msgid "Content Shortcode"
|
576 |
msgstr ""
|
577 |
|
578 |
+
#: includes/admin/class-wp-job-manager-setup.php:192
|
579 |
+
msgid "This page allows employers to post jobs to your website from the front-end."
|
580 |
+
msgstr ""
|
581 |
+
|
582 |
+
#: includes/admin/class-wp-job-manager-setup.php:194
|
583 |
+
msgid ""
|
584 |
+
"If you do not want to accept submissions from users in this way (for "
|
585 |
+
"example you just want to post jobs from the admin dashboard) you can skip "
|
586 |
+
"creating this page."
|
587 |
+
msgstr ""
|
588 |
+
|
589 |
+
#: includes/admin/class-wp-job-manager-setup.php:202
|
590 |
msgid ""
|
591 |
+
"This page allows employers to manage and edit their own jobs from the "
|
592 |
+
"front-end."
|
|
|
|
|
593 |
msgstr ""
|
594 |
|
595 |
+
#: includes/admin/class-wp-job-manager-setup.php:204
|
596 |
msgid ""
|
597 |
+
"If you plan on managing all listings from the admin dashboard you can skip "
|
598 |
+
"creating this page."
|
|
|
|
|
599 |
msgstr ""
|
600 |
|
601 |
+
#: includes/admin/class-wp-job-manager-setup.php:211
|
602 |
+
msgid ""
|
603 |
+
"This page allows users to browse, search, and filter job listings on the "
|
604 |
+
"front-end of your site."
|
605 |
msgstr ""
|
606 |
|
607 |
+
#: includes/admin/class-wp-job-manager-setup.php:219
|
608 |
msgid "Skip this step"
|
609 |
msgstr ""
|
610 |
|
611 |
+
#: includes/admin/class-wp-job-manager-setup.php:229
|
612 |
+
msgid "All Done!"
|
613 |
msgstr ""
|
614 |
|
615 |
+
#: includes/admin/class-wp-job-manager-setup.php:231
|
616 |
+
msgid ""
|
617 |
+
"Looks like you're all set to start using the plugin. In case you're "
|
618 |
+
"wondering where to go next:"
|
619 |
msgstr ""
|
620 |
|
621 |
+
#: includes/admin/class-wp-job-manager-setup.php:234
|
622 |
+
msgid "Tweak the plugin settings"
|
623 |
msgstr ""
|
624 |
|
625 |
+
#: includes/admin/class-wp-job-manager-setup.php:235
|
626 |
+
msgid "Add a job via the back-end"
|
627 |
msgstr ""
|
628 |
|
629 |
+
#: includes/admin/class-wp-job-manager-setup.php:238
|
630 |
+
msgid "Add a job via the front-end"
|
631 |
msgstr ""
|
632 |
|
633 |
+
#: includes/admin/class-wp-job-manager-setup.php:240
|
634 |
+
msgid "Find out more about the front-end job submission form"
|
635 |
msgstr ""
|
636 |
|
637 |
+
#: includes/admin/class-wp-job-manager-setup.php:244
|
638 |
+
msgid "View submitted job listings"
|
639 |
msgstr ""
|
640 |
|
641 |
+
#: includes/admin/class-wp-job-manager-setup.php:246
|
642 |
+
msgid "Add the [jobs] shortcode to a page to list jobs"
|
643 |
msgstr ""
|
644 |
|
645 |
+
#: includes/admin/class-wp-job-manager-setup.php:250
|
646 |
msgid "View the job dashboard"
|
647 |
msgstr ""
|
648 |
|
649 |
+
#: includes/admin/class-wp-job-manager-setup.php:252
|
650 |
+
msgid "Find out more about the front-end job dashboard"
|
651 |
msgstr ""
|
652 |
|
653 |
+
#: includes/admin/class-wp-job-manager-setup.php:256
|
|
|
|
|
654 |
msgid ""
|
655 |
+
"And don't forget, if you need any more help using <em>WP Job Manager</em> "
|
656 |
+
"you can consult the %1$sdocumentation%2$s or %3$spost on the forums%2$s!"
|
|
|
|
|
|
|
657 |
msgstr ""
|
658 |
|
659 |
+
#: includes/admin/class-wp-job-manager-setup.php:259
|
660 |
+
msgid "Support the Ongoing Development of this Plugin"
|
661 |
msgstr ""
|
662 |
|
663 |
+
#: includes/admin/class-wp-job-manager-setup.php:260
|
664 |
msgid ""
|
665 |
+
"There are many ways to support open-source projects such as WP Job Manager, "
|
666 |
+
"for example code contribution, translation, or even telling your friends "
|
667 |
+
"how awesome the plugin (hopefully) is. Thanks in advance for your support - "
|
668 |
+
"it is much appreciated!"
|
669 |
msgstr ""
|
670 |
|
671 |
+
#: includes/admin/class-wp-job-manager-setup.php:262
|
672 |
msgid "Leave a positive review"
|
673 |
msgstr ""
|
674 |
|
675 |
+
#: includes/admin/class-wp-job-manager-setup.php:263
|
676 |
msgid "Contribute a localization"
|
677 |
msgstr ""
|
678 |
|
679 |
+
#: includes/admin/class-wp-job-manager-setup.php:264
|
680 |
msgid "Contribute code or report a bug"
|
681 |
msgstr ""
|
682 |
|
683 |
+
#: includes/admin/class-wp-job-manager-setup.php:265
|
684 |
msgid "Help other users on the forums"
|
685 |
msgstr ""
|
686 |
|
687 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:56
|
688 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:175
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
689 |
msgid "e.g. \"London\""
|
690 |
msgstr ""
|
691 |
|
692 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:57
|
|
|
693 |
msgid "Leave this blank if the location is not important."
|
694 |
msgstr ""
|
695 |
|
696 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:61
|
|
|
697 |
msgid "Application Email or URL"
|
698 |
msgstr ""
|
699 |
|
700 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:62
|
701 |
msgid "URL or email which applicants use to apply"
|
702 |
msgstr ""
|
703 |
|
704 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:63
|
705 |
msgid ""
|
706 |
"This field is required for the \"application\" area to appear beneath the "
|
707 |
"listing."
|
708 |
msgstr ""
|
709 |
|
710 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:68
|
|
|
|
|
711 |
msgid "Company Name"
|
712 |
msgstr ""
|
713 |
|
714 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:73
|
|
|
|
|
715 |
msgid "Company Website"
|
716 |
msgstr ""
|
717 |
|
718 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:78
|
|
|
|
|
719 |
msgid "Company Tagline"
|
720 |
msgstr ""
|
721 |
|
722 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:79
|
723 |
msgid "Brief description about the company"
|
724 |
msgstr ""
|
725 |
|
726 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:83
|
|
|
|
|
727 |
msgid "Company Twitter"
|
728 |
msgstr ""
|
729 |
|
730 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:88
|
|
|
|
|
731 |
msgid "Company Video"
|
732 |
msgstr ""
|
733 |
|
734 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:89
|
735 |
msgid "URL to the company video"
|
736 |
msgstr ""
|
737 |
|
738 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:94
|
|
|
739 |
msgid "Position Filled"
|
740 |
msgstr ""
|
741 |
|
742 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:97
|
743 |
msgid "Filled listings will no longer accept applications."
|
744 |
msgstr ""
|
745 |
|
746 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:102
|
|
|
747 |
msgid "Featured Listing"
|
748 |
msgstr ""
|
749 |
|
750 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:104
|
751 |
msgid ""
|
752 |
"Featured listings will be sticky during searches, and can be styled "
|
753 |
"differently."
|
754 |
msgstr ""
|
755 |
|
756 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:109
|
|
|
757 |
msgid "Listing Expiry Date"
|
758 |
msgstr ""
|
759 |
|
760 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:119
|
|
|
|
|
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 |
|
810 |
+
#: includes/class-wp-job-manager-geocode.php:221
|
811 |
+
msgid "No results found"
|
|
|
|
|
|
|
|
|
|
|
812 |
msgstr ""
|
813 |
|
814 |
+
#: includes/class-wp-job-manager-geocode.php:225
|
815 |
+
msgid "Query limit reached"
|
816 |
msgstr ""
|
817 |
|
818 |
+
#: includes/class-wp-job-manager-geocode.php:231
|
819 |
+
#: includes/class-wp-job-manager-geocode.php:235
|
820 |
+
#: includes/class-wp-job-manager-geocode.php:239
|
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] ""
|
953 |
msgstr[1] ""
|
954 |
|
955 |
+
#: includes/class-wp-job-manager-shortcodes.php:96
|
956 |
msgid "Invalid ID"
|
957 |
msgstr ""
|
958 |
|
959 |
+
#: includes/class-wp-job-manager-shortcodes.php:103
|
960 |
msgid "This position has already been filled"
|
961 |
msgstr ""
|
962 |
|
963 |
+
#: includes/class-wp-job-manager-shortcodes.php:109
|
|
|
964 |
msgid "%s has been filled"
|
965 |
msgstr ""
|
966 |
|
967 |
+
#: includes/class-wp-job-manager-shortcodes.php:114
|
968 |
msgid "This position is not filled"
|
969 |
msgstr ""
|
970 |
|
971 |
+
#: includes/class-wp-job-manager-shortcodes.php:121
|
|
|
972 |
msgid "%s has been marked as not filled"
|
973 |
msgstr ""
|
974 |
|
975 |
+
#: includes/class-wp-job-manager-shortcodes.php:128
|
|
|
976 |
msgid "%s has been deleted"
|
977 |
msgstr ""
|
978 |
|
979 |
+
#: includes/class-wp-job-manager-shortcodes.php:133
|
980 |
+
#: includes/class-wp-job-manager-shortcodes.php:146
|
981 |
msgid "Missing submission page."
|
982 |
msgstr ""
|
983 |
|
984 |
+
#: includes/class-wp-job-manager-shortcodes.php:217
|
985 |
+
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:28
|
986 |
+
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:28
|
|
|
987 |
msgid "Title"
|
988 |
msgstr ""
|
989 |
|
990 |
+
#: includes/class-wp-job-manager-shortcodes.php:219
|
991 |
msgid "Date Posted"
|
992 |
msgstr ""
|
993 |
|
994 |
+
#: includes/class-wp-job-manager-shortcodes.php:220
|
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 |
|
1003 |
+
#: includes/forms/class-wp-job-manager-form-edit-job.php:67
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1004 |
msgid "Invalid listing"
|
1005 |
msgstr ""
|
1006 |
|
1007 |
+
#: includes/forms/class-wp-job-manager-form-edit-job.php:106
|
1008 |
msgid "Save changes"
|
1009 |
msgstr ""
|
1010 |
|
1011 |
+
#: includes/forms/class-wp-job-manager-form-edit-job.php:135
|
1012 |
+
#: includes/forms/class-wp-job-manager-form-edit-job.php:138
|
|
|
|
|
|
|
1013 |
msgid "Your changes have been saved."
|
1014 |
msgstr ""
|
1015 |
|
1016 |
+
#: includes/forms/class-wp-job-manager-form-edit-job.php:135
|
1017 |
msgid "View →"
|
1018 |
msgstr ""
|
1019 |
|
1020 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:63
|
|
|
|
|
|
|
|
|
|
|
|
|
1021 |
msgid "Submit Details"
|
1022 |
msgstr ""
|
1023 |
|
1024 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:69
|
1025 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:432
|
1026 |
+
#: templates/job-preview.php:5
|
1027 |
msgid "Preview"
|
1028 |
msgstr ""
|
1029 |
|
1030 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:75
|
1031 |
msgid "Done"
|
1032 |
msgstr ""
|
1033 |
|
1034 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:143
|
1035 |
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 |
|
1043 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:147
|
1044 |
msgid "Application URL"
|
1045 |
msgstr ""
|
1046 |
|
1047 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:148
|
1048 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:223
|
1049 |
msgid "http://"
|
1050 |
msgstr ""
|
1051 |
|
1052 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:151
|
1053 |
msgid "Application email/URL"
|
1054 |
msgstr ""
|
1055 |
|
1056 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:152
|
1057 |
msgid "Enter an email address or website URL"
|
1058 |
msgstr ""
|
1059 |
|
1060 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:164
|
1061 |
msgid "Job Title"
|
1062 |
msgstr ""
|
1063 |
|
1064 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:172
|
1065 |
msgid "Leave this blank if the location is not important"
|
1066 |
msgstr ""
|
1067 |
|
1068 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:182
|
1069 |
msgid "Choose job type…"
|
1070 |
msgstr ""
|
1071 |
|
1072 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:197
|
1073 |
msgid "Description"
|
1074 |
msgstr ""
|
1075 |
|
1076 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:213
|
1077 |
+
msgid "Company name"
|
1078 |
+
msgstr ""
|
1079 |
+
|
1080 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:216
|
1081 |
msgid "Enter the name of the company"
|
1082 |
msgstr ""
|
1083 |
|
1084 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:220
|
1085 |
+
#: templates/content-single-job_listing-company.php:19
|
1086 |
msgid "Website"
|
1087 |
msgstr ""
|
1088 |
|
1089 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:227
|
1090 |
msgid "Tagline"
|
1091 |
msgstr ""
|
1092 |
|
1093 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:230
|
1094 |
msgid "Briefly describe your company"
|
1095 |
msgstr ""
|
1096 |
|
1097 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:235
|
1098 |
msgid "Video"
|
1099 |
msgstr ""
|
1100 |
|
1101 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:238
|
1102 |
msgid "A link to a video about your company"
|
1103 |
msgstr ""
|
1104 |
|
1105 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:242
|
1106 |
msgid "Twitter username"
|
1107 |
msgstr ""
|
1108 |
|
1109 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:245
|
1110 |
msgid "@yourcompany"
|
1111 |
msgstr ""
|
1112 |
|
1113 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:249
|
1114 |
msgid "Logo"
|
1115 |
msgstr ""
|
1116 |
|
1117 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:285
|
|
|
1118 |
msgid "%s is a required field"
|
1119 |
msgstr ""
|
1120 |
|
1121 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:295
|
|
|
1122 |
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 |
|
1130 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:326
|
1131 |
msgid "Please enter a valid application email address"
|
1132 |
msgstr ""
|
1133 |
|
1134 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:335
|
1135 |
msgid "Please enter a valid application URL"
|
1136 |
msgstr ""
|
1137 |
|
1138 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:345
|
1139 |
msgid "Please enter a valid application email address or URL"
|
1140 |
msgstr ""
|
1141 |
|
1142 |
+
#: includes/forms/class-wp-job-manager-form-submit-job.php:463
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1154 |
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:21
|
1155 |
+
msgid "Display a list of featured listings on your site."
|
|
|
|
|
|
|
1156 |
msgstr ""
|
1157 |
|
1158 |
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:23
|
1159 |
+
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:27
|
1160 |
+
msgid "Featured %s"
|
1161 |
msgstr ""
|
1162 |
|
1163 |
+
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:36
|
1164 |
+
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:46
|
1165 |
msgid "Number of listings to show"
|
1166 |
msgstr ""
|
1167 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1168 |
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:21
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1169 |
msgid ""
|
1170 |
"Display a list of recent listings on your site, optionally matching a "
|
1171 |
"keyword and location."
|
1172 |
msgstr ""
|
1173 |
|
1174 |
+
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:23
|
1175 |
+
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:27
|
1176 |
+
msgid "Recent %s"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1177 |
msgstr ""
|
1178 |
|
1179 |
+
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:33
|
1180 |
+
msgid "Keyword"
|
1181 |
msgstr ""
|
1182 |
|
1183 |
+
#: templates/account-signin.php:4
|
1184 |
msgid "Your account"
|
1185 |
msgstr ""
|
1186 |
|
1187 |
+
#: templates/account-signin.php:8
|
1188 |
msgid "You are currently signed in as <strong>%s</strong>."
|
1189 |
msgstr ""
|
1190 |
|
1191 |
+
#: templates/account-signin.php:11
|
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’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 ""
|
1234 |
|
1235 |
+
#: templates/content-no-jobs-found.php:4
|
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 |
|
1247 |
+
#: templates/content-single-job_listing.php:6
|
1248 |
msgid "This listing has expired."
|
1249 |
msgstr ""
|
1250 |
|
1251 |
+
#: templates/form-fields/file-field.php:29
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1252 |
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 |
|
1265 |
+
#: templates/form-fields/uploaded-file-html.php:12
|
1266 |
+
#: templates/form-fields/uploaded-file-html.php:14
|
1267 |
msgid "remove"
|
1268 |
msgstr ""
|
1269 |
|
1270 |
+
#: templates/job-application-email.php:1
|
1271 |
msgid ""
|
1272 |
"To apply for this job <strong>email your details to</strong> <a "
|
1273 |
"class=\"job_application_email\" href=\"mailto:%1$s%2$s\">%1$s</a>"
|
1274 |
msgstr ""
|
1275 |
|
1276 |
+
#: templates/job-application-url.php:1
|
1277 |
+
msgid "To apply for this job please visit the following URL:"
|
1278 |
msgstr ""
|
1279 |
|
1280 |
+
#: templates/job-application.php:7
|
1281 |
msgid "Apply for job"
|
1282 |
msgstr ""
|
1283 |
|
1284 |
+
#: templates/job-dashboard-login.php:3
|
1285 |
msgid "You need to be signed in to manage your listings."
|
1286 |
msgstr ""
|
1287 |
|
1288 |
+
#: templates/job-dashboard.php:2
|
1289 |
msgid "Your listings are shown in the table below."
|
1290 |
msgstr ""
|
1291 |
|
1292 |
+
#: templates/job-dashboard.php:14
|
1293 |
msgid "You do not have any active listings."
|
1294 |
msgstr ""
|
1295 |
|
1296 |
+
#: templates/job-dashboard.php:36
|
|
|
|
|
|
|
|
|
1297 |
msgid "Mark not filled"
|
1298 |
msgstr ""
|
1299 |
|
1300 |
+
#: templates/job-dashboard.php:38
|
1301 |
msgid "Mark filled"
|
1302 |
msgstr ""
|
1303 |
|
1304 |
+
#: templates/job-dashboard.php:41
|
1305 |
msgid "Duplicate"
|
1306 |
msgstr ""
|
1307 |
|
1308 |
+
#: templates/job-dashboard.php:45
|
1309 |
msgid "Relist"
|
1310 |
msgstr ""
|
1311 |
|
1312 |
+
#: templates/job-filters.php:12 templates/job-filters.php:13
|
1313 |
msgid "Keywords"
|
1314 |
msgstr ""
|
1315 |
|
1316 |
+
#: templates/job-filters.php:27
|
1317 |
msgid "Category"
|
1318 |
msgstr ""
|
1319 |
|
1320 |
+
#: templates/job-filters.php:31
|
1321 |
msgid "Any category"
|
1322 |
msgstr ""
|
1323 |
|
1324 |
+
#: templates/job-filters.php:44
|
1325 |
msgid ""
|
1326 |
"Your browser does not support JavaScript, or it is disabled. JavaScript "
|
1327 |
"must be enabled in order to view listings."
|
1328 |
msgstr ""
|
1329 |
|
1330 |
+
#: templates/job-preview.php:3
|
1331 |
msgid "Submit Listing"
|
1332 |
msgstr ""
|
1333 |
|
1334 |
+
#: templates/job-preview.php:4
|
1335 |
msgid "Edit listing"
|
1336 |
msgstr ""
|
1337 |
|
1338 |
+
#: templates/job-submit.php:13
|
1339 |
msgid "You are editing an existing job. %s"
|
1340 |
msgstr ""
|
1341 |
|
1342 |
+
#: templates/job-submit.php:13
|
1343 |
msgid "Create A New Job"
|
1344 |
msgstr ""
|
1345 |
|
1346 |
+
#: templates/job-submit.php:43
|
1347 |
msgid "Company Details"
|
1348 |
msgstr ""
|
1349 |
|
1350 |
+
#: templates/job-submitted.php:6
|
1351 |
msgid "%s listed successfully. To view your listing <a href=\"%s\">click here</a>."
|
1352 |
msgstr ""
|
1353 |
|
1354 |
+
#: templates/job-submitted.php:9
|
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’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…"
|
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 |
|
1386 |
+
#: wp-job-manager-template.php:146
|
1387 |
msgid "Inactive"
|
1388 |
msgstr ""
|
1389 |
|
1390 |
+
#: wp-job-manager-template.php:237
|
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 |
|
1418 |
+
#. Plugin Name of the plugin/theme
|
1419 |
+
msgid "WP Job Manager"
|
1420 |
+
msgstr ""
|
1421 |
+
|
1422 |
#. Author URI of the plugin/theme
|
1423 |
msgid "https://wpjobmanager.com/"
|
1424 |
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"
|
1446 |
msgstr ""
|
1447 |
|
1448 |
+
#: includes/admin/class-wp-job-manager-setup.php:200
|
1449 |
msgctxt "Default page title (wizard)"
|
1450 |
msgid "Job Dashboard"
|
1451 |
msgstr ""
|
1452 |
|
1453 |
+
#: includes/admin/class-wp-job-manager-setup.php:210
|
1454 |
msgctxt "Default page title (wizard)"
|
1455 |
msgid "Jobs"
|
1456 |
msgstr ""
|
1457 |
|
1458 |
+
#: includes/admin/class-wp-job-manager-writepanels.php:113
|
1459 |
+
#. translators: date format placeholder, see https:secure.php.net/date
|
1460 |
+
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 ""
|
lib/emogrifier/class-emogrifier.php
DELETED
@@ -1,1557 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* This class provides functions for converting CSS styles into inline style attributes in your HTML code.
|
4 |
-
*
|
5 |
-
* For more information, please see the README.md file.
|
6 |
-
*
|
7 |
-
* @version 1.2.0
|
8 |
-
*
|
9 |
-
* @author Cameron Brooks
|
10 |
-
* @author Jaime Prado
|
11 |
-
* @author Oliver Klee <typo3-coding@oliverklee.de>
|
12 |
-
* @author Roman Ožana <ozana@omdesign.cz>
|
13 |
-
* @author Sander Kruger <s.kruger@invessel.com>
|
14 |
-
*
|
15 |
-
* @see https://raw.githubusercontent.com/MyIntervals/emogrifier/V1.2.0/Classes/Emogrifier.php
|
16 |
-
*/
|
17 |
-
// @codingStandardsIgnoreFile
|
18 |
-
class Emogrifier
|
19 |
-
{
|
20 |
-
/**
|
21 |
-
* @var int
|
22 |
-
*/
|
23 |
-
const CACHE_KEY_CSS = 0;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @var int
|
27 |
-
*/
|
28 |
-
const CACHE_KEY_SELECTOR = 1;
|
29 |
-
|
30 |
-
/**
|
31 |
-
* @var int
|
32 |
-
*/
|
33 |
-
const CACHE_KEY_XPATH = 2;
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @var int
|
37 |
-
*/
|
38 |
-
const CACHE_KEY_CSS_DECLARATIONS_BLOCK = 3;
|
39 |
-
|
40 |
-
/**
|
41 |
-
* @var int
|
42 |
-
*/
|
43 |
-
const CACHE_KEY_COMBINED_STYLES = 4;
|
44 |
-
|
45 |
-
/**
|
46 |
-
* for calculating nth-of-type and nth-child selectors
|
47 |
-
*
|
48 |
-
* @var int
|
49 |
-
*/
|
50 |
-
const INDEX = 0;
|
51 |
-
|
52 |
-
/**
|
53 |
-
* for calculating nth-of-type and nth-child selectors
|
54 |
-
*
|
55 |
-
* @var int
|
56 |
-
*/
|
57 |
-
const MULTIPLIER = 1;
|
58 |
-
|
59 |
-
/**
|
60 |
-
* @var string
|
61 |
-
*/
|
62 |
-
const ID_ATTRIBUTE_MATCHER = '/(\\w+)?\\#([\\w\\-]+)/';
|
63 |
-
|
64 |
-
/**
|
65 |
-
* @var string
|
66 |
-
*/
|
67 |
-
const CLASS_ATTRIBUTE_MATCHER = '/(\\w+|[\\*\\]])?((\\.[\\w\\-]+)+)/';
|
68 |
-
|
69 |
-
/**
|
70 |
-
* @var string
|
71 |
-
*/
|
72 |
-
const CONTENT_TYPE_META_TAG = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
|
73 |
-
|
74 |
-
/**
|
75 |
-
* @var string
|
76 |
-
*/
|
77 |
-
const DEFAULT_DOCUMENT_TYPE = '<!DOCTYPE html>';
|
78 |
-
|
79 |
-
/**
|
80 |
-
* @var string
|
81 |
-
*/
|
82 |
-
private $html = '';
|
83 |
-
|
84 |
-
/**
|
85 |
-
* @var string
|
86 |
-
*/
|
87 |
-
private $css = '';
|
88 |
-
|
89 |
-
/**
|
90 |
-
* @var bool[]
|
91 |
-
*/
|
92 |
-
private $excludedSelectors = array();
|
93 |
-
|
94 |
-
/**
|
95 |
-
* @var string[]
|
96 |
-
*/
|
97 |
-
private $unprocessableHtmlTags = array( 'wbr' );
|
98 |
-
|
99 |
-
/**
|
100 |
-
* @var bool[]
|
101 |
-
*/
|
102 |
-
private $allowedMediaTypes = array( 'all' => true, 'screen' => true, 'print' => true );
|
103 |
-
|
104 |
-
/**
|
105 |
-
* @var mixed[]
|
106 |
-
*/
|
107 |
-
private $caches = array(
|
108 |
-
self::CACHE_KEY_CSS => array(),
|
109 |
-
self::CACHE_KEY_SELECTOR => array(),
|
110 |
-
self::CACHE_KEY_XPATH => array(),
|
111 |
-
self::CACHE_KEY_CSS_DECLARATIONS_BLOCK => array(),
|
112 |
-
self::CACHE_KEY_COMBINED_STYLES => array(),
|
113 |
-
);
|
114 |
-
|
115 |
-
/**
|
116 |
-
* the visited nodes with the XPath paths as array keys
|
117 |
-
*
|
118 |
-
* @var \DOMElement[]
|
119 |
-
*/
|
120 |
-
private $visitedNodes = array();
|
121 |
-
|
122 |
-
/**
|
123 |
-
* the styles to apply to the nodes with the XPath paths as array keys for the outer array
|
124 |
-
* and the attribute names/values as key/value pairs for the inner array
|
125 |
-
*
|
126 |
-
* @var string[][]
|
127 |
-
*/
|
128 |
-
private $styleAttributesForNodes = array();
|
129 |
-
|
130 |
-
/**
|
131 |
-
* Determines whether the "style" attributes of tags in the the HTML passed to this class should be preserved.
|
132 |
-
* If set to false, the value of the style attributes will be discarded.
|
133 |
-
*
|
134 |
-
* @var bool
|
135 |
-
*/
|
136 |
-
private $isInlineStyleAttributesParsingEnabled = true;
|
137 |
-
|
138 |
-
/**
|
139 |
-
* Determines whether the <style> blocks in the HTML passed to this class should be parsed.
|
140 |
-
*
|
141 |
-
* If set to true, the <style> blocks will be removed from the HTML and their contents will be applied to the HTML
|
142 |
-
* via inline styles.
|
143 |
-
*
|
144 |
-
* If set to false, the <style> blocks will be left as they are in the HTML.
|
145 |
-
*
|
146 |
-
* @var bool
|
147 |
-
*/
|
148 |
-
private $isStyleBlocksParsingEnabled = true;
|
149 |
-
|
150 |
-
/**
|
151 |
-
* Determines whether elements with the `display: none` property are
|
152 |
-
* removed from the DOM.
|
153 |
-
*
|
154 |
-
* @var bool
|
155 |
-
*/
|
156 |
-
private $shouldKeepInvisibleNodes = true;
|
157 |
-
|
158 |
-
/**
|
159 |
-
* @var string[]
|
160 |
-
*/
|
161 |
-
private $xPathRules = array(
|
162 |
-
// child
|
163 |
-
'/\\s*>\\s*/' => '/',
|
164 |
-
// adjacent sibling
|
165 |
-
'/\\s+\\+\\s+/' => '/following-sibling::*[1]/self::',
|
166 |
-
// descendant
|
167 |
-
'/\\s+(?=.*[^\\]]{1}$)/' => '//',
|
168 |
-
// :first-child
|
169 |
-
'/([^\\/]+):first-child/i' => '*[1]/self::\\1',
|
170 |
-
// :last-child
|
171 |
-
'/([^\\/]+):last-child/i' => '*[last()]/self::\\1',
|
172 |
-
// attribute only
|
173 |
-
'/^\\[(\\w+|\\w+\\=[\'"]?\\w+[\'"]?)\\]/' => '*[@\\1]',
|
174 |
-
// attribute
|
175 |
-
'/(\\w)\\[(\\w+)\\]/' => '\\1[@\\2]',
|
176 |
-
// exact attribute
|
177 |
-
'/(\\w)\\[(\\w+)\\=[\'"]?([\\w\\s]+)[\'"]?\\]/' => '\\1[@\\2="\\3"]',
|
178 |
-
// element attribute~=
|
179 |
-
'/([\\w\\*]+)\\[(\\w+)[\\s]*\\~\\=[\\s]*[\'"]?([\\w-_\\/]+)[\'"]?\\]/'
|
180 |
-
=> '\\1[contains(concat(" ", @\\2, " "), concat(" ", "\\3", " "))]',
|
181 |
-
// element attribute^=
|
182 |
-
'/([\\w\\*]+)\\[(\\w+)[\\s]*\\^\\=[\\s]*[\'"]?([\\w-_\\/]+)[\'"]?\\]/' => '\\1[starts-with(@\\2, "\\3")]',
|
183 |
-
// element attribute*=
|
184 |
-
'/([\\w\\*]+)\\[(\\w+)[\\s]*\\*\\=[\\s]*[\'"]?([\\w-_\\s\\/:;]+)[\'"]?\\]/' => '\\1[contains(@\\2, "\\3")]',
|
185 |
-
// element attribute$=
|
186 |
-
'/([\\w\\*]+)\\[(\\w+)[\\s]*\\$\\=[\\s]*[\'"]?([\\w-_\\s\\/]+)[\'"]?\\]/'
|
187 |
-
=> '\\1[substring(@\\2, string-length(@\\2) - string-length("\\3") + 1) = "\\3"]',
|
188 |
-
// element attribute|=
|
189 |
-
'/([\\w\\*]+)\\[(\\w+)[\\s]*\\|\\=[\\s]*[\'"]?([\\w-_\\s\\/]+)[\'"]?\\]/'
|
190 |
-
=> '\\1[@\\2="\\3" or starts-with(@\\2, concat("\\3", "-"))]',
|
191 |
-
);
|
192 |
-
|
193 |
-
/**
|
194 |
-
* Determines whether CSS styles that have an equivalent HTML attribute
|
195 |
-
* should be mapped and attached to those elements.
|
196 |
-
*
|
197 |
-
* @var bool
|
198 |
-
*/
|
199 |
-
private $shouldMapCssToHtml = false;
|
200 |
-
|
201 |
-
/**
|
202 |
-
* This multi-level array contains simple mappings of CSS properties to
|
203 |
-
* HTML attributes. If a mapping only applies to certain HTML nodes or
|
204 |
-
* only for certain values, the mapping is an object with a whitelist
|
205 |
-
* of nodes and values.
|
206 |
-
*
|
207 |
-
* @var mixed[][]
|
208 |
-
*/
|
209 |
-
private $cssToHtmlMap = array(
|
210 |
-
'background-color' => array(
|
211 |
-
'attribute' => 'bgcolor',
|
212 |
-
),
|
213 |
-
'text-align' => array(
|
214 |
-
'attribute' => 'align',
|
215 |
-
'nodes' => array('p', 'div', 'td'),
|
216 |
-
'values' => array('left', 'right', 'center', 'justify'),
|
217 |
-
),
|
218 |
-
'float' => array(
|
219 |
-
'attribute' => 'align',
|
220 |
-
'nodes' => array('table', 'img'),
|
221 |
-
'values' => array('left', 'right'),
|
222 |
-
),
|
223 |
-
'border-spacing' => array(
|
224 |
-
'attribute' => 'cellspacing',
|
225 |
-
'nodes' => array('table'),
|
226 |
-
),
|
227 |
-
);
|
228 |
-
|
229 |
-
public static $_media = '';
|
230 |
-
|
231 |
-
/**
|
232 |
-
* The constructor.
|
233 |
-
*
|
234 |
-
* @param string $html the HTML to emogrify, must be UTF-8-encoded
|
235 |
-
* @param string $css the CSS to merge, must be UTF-8-encoded
|
236 |
-
*/
|
237 |
-
public function __construct($html = '', $css = '')
|
238 |
-
{
|
239 |
-
$this->setHtml($html);
|
240 |
-
$this->setCss($css);
|
241 |
-
}
|
242 |
-
|
243 |
-
/**
|
244 |
-
* The destructor.
|
245 |
-
*/
|
246 |
-
public function __destruct()
|
247 |
-
{
|
248 |
-
$this->purgeVisitedNodes();
|
249 |
-
}
|
250 |
-
|
251 |
-
/**
|
252 |
-
* Sets the HTML to emogrify.
|
253 |
-
*
|
254 |
-
* @param string $html the HTML to emogrify, must be UTF-8-encoded
|
255 |
-
*
|
256 |
-
* @return void
|
257 |
-
*/
|
258 |
-
public function setHtml($html)
|
259 |
-
{
|
260 |
-
$this->html = $html;
|
261 |
-
}
|
262 |
-
|
263 |
-
/**
|
264 |
-
* Sets the CSS to merge with the HTML.
|
265 |
-
*
|
266 |
-
* @param string $css the CSS to merge, must be UTF-8-encoded
|
267 |
-
*
|
268 |
-
* @return void
|
269 |
-
*/
|
270 |
-
public function setCss($css)
|
271 |
-
{
|
272 |
-
$this->css = $css;
|
273 |
-
}
|
274 |
-
|
275 |
-
/**
|
276 |
-
* Applies $this->css to $this->html and returns the HTML with the CSS
|
277 |
-
* applied.
|
278 |
-
*
|
279 |
-
* This method places the CSS inline.
|
280 |
-
*
|
281 |
-
* @return string
|
282 |
-
*
|
283 |
-
* @throws \BadMethodCallException
|
284 |
-
*/
|
285 |
-
public function emogrify()
|
286 |
-
{
|
287 |
-
if ($this->html === '') {
|
288 |
-
throw new BadMethodCallException('Please set some HTML first before calling emogrify.', 1390393096);
|
289 |
-
}
|
290 |
-
|
291 |
-
self::$_media = ''; // reset.
|
292 |
-
|
293 |
-
$xmlDocument = $this->createXmlDocument();
|
294 |
-
$this->process($xmlDocument);
|
295 |
-
|
296 |
-
return $xmlDocument->saveHTML();
|
297 |
-
}
|
298 |
-
|
299 |
-
/**
|
300 |
-
* Applies $this->css to $this->html and returns only the HTML content
|
301 |
-
* within the <body> tag.
|
302 |
-
*
|
303 |
-
* This method places the CSS inline.
|
304 |
-
*
|
305 |
-
* @return string
|
306 |
-
*
|
307 |
-
* @throws \BadMethodCallException
|
308 |
-
*/
|
309 |
-
public function emogrifyBodyContent()
|
310 |
-
{
|
311 |
-
if ($this->html === '') {
|
312 |
-
throw new BadMethodCallException('Please set some HTML first before calling emogrify.', 1390393096);
|
313 |
-
}
|
314 |
-
|
315 |
-
$xmlDocument = $this->createXmlDocument();
|
316 |
-
$this->process($xmlDocument);
|
317 |
-
|
318 |
-
$innerDocument = new DOMDocument();
|
319 |
-
foreach ($xmlDocument->documentElement->getElementsByTagName('body')->item(0)->childNodes as $childNode) {
|
320 |
-
$innerDocument->appendChild($innerDocument->importNode($childNode, true));
|
321 |
-
}
|
322 |
-
|
323 |
-
return html_entity_decode($innerDocument->saveHTML());
|
324 |
-
}
|
325 |
-
|
326 |
-
/**
|
327 |
-
* Applies $this->css to $xmlDocument.
|
328 |
-
*
|
329 |
-
* This method places the CSS inline.
|
330 |
-
*
|
331 |
-
* @param \DOMDocument $xmlDocument
|
332 |
-
*
|
333 |
-
* @return void
|
334 |
-
*
|
335 |
-
* @throws \InvalidArgumentException
|
336 |
-
*/
|
337 |
-
protected function process(DOMDocument $xmlDocument)
|
338 |
-
{
|
339 |
-
$xPath = new DOMXPath($xmlDocument);
|
340 |
-
$this->clearAllCaches();
|
341 |
-
|
342 |
-
// Before be begin processing the CSS file, parse the document and normalize all existing CSS attributes.
|
343 |
-
// This changes 'DISPLAY: none' to 'display: none'.
|
344 |
-
// We wouldn't have to do this if DOMXPath supported XPath 2.0.
|
345 |
-
// Also store a reference of nodes with existing inline styles so we don't overwrite them.
|
346 |
-
$this->purgeVisitedNodes();
|
347 |
-
|
348 |
-
set_error_handler(array($this, 'handleXpathError'), E_WARNING);
|
349 |
-
|
350 |
-
$nodesWithStyleAttributes = $xPath->query('//*[@style]');
|
351 |
-
if ($nodesWithStyleAttributes !== false) {
|
352 |
-
/** @var \DOMElement $node */
|
353 |
-
foreach ($nodesWithStyleAttributes as $node) {
|
354 |
-
if ($this->isInlineStyleAttributesParsingEnabled) {
|
355 |
-
$this->normalizeStyleAttributes($node);
|
356 |
-
} else {
|
357 |
-
$node->removeAttribute('style');
|
358 |
-
}
|
359 |
-
}
|
360 |
-
}
|
361 |
-
|
362 |
-
// grab any existing style blocks from the html and append them to the existing CSS
|
363 |
-
// (these blocks should be appended so as to have precedence over conflicting styles in the existing CSS)
|
364 |
-
$allCss = $this->css;
|
365 |
-
|
366 |
-
if ($this->isStyleBlocksParsingEnabled) {
|
367 |
-
$allCss .= $this->getCssFromAllStyleNodes($xPath);
|
368 |
-
}
|
369 |
-
|
370 |
-
$cssParts = $this->splitCssAndMediaQuery($allCss);
|
371 |
-
$excludedNodes = $this->getNodesToExclude($xPath);
|
372 |
-
$cssRules = $this->parseCssRules($cssParts['css']);
|
373 |
-
foreach ($cssRules as $cssRule) {
|
374 |
-
// query the body for the xpath selector
|
375 |
-
$nodesMatchingCssSelectors = $xPath->query($this->translateCssToXpath($cssRule['selector']));
|
376 |
-
// ignore invalid selectors
|
377 |
-
if ($nodesMatchingCssSelectors === false) {
|
378 |
-
continue;
|
379 |
-
}
|
380 |
-
|
381 |
-
/** @var \DOMElement $node */
|
382 |
-
foreach ($nodesMatchingCssSelectors as $node) {
|
383 |
-
if (in_array($node, $excludedNodes, true)) {
|
384 |
-
continue;
|
385 |
-
}
|
386 |
-
|
387 |
-
// if it has a style attribute, get it, process it, and append (overwrite) new stuff
|
388 |
-
if ($node->hasAttribute('style')) {
|
389 |
-
// break it up into an associative array
|
390 |
-
$oldStyleDeclarations = $this->parseCssDeclarationsBlock($node->getAttribute('style'));
|
391 |
-
} else {
|
392 |
-
$oldStyleDeclarations = array();
|
393 |
-
}
|
394 |
-
$newStyleDeclarations = $this->parseCssDeclarationsBlock($cssRule['declarationsBlock']);
|
395 |
-
if ($this->shouldMapCssToHtml) {
|
396 |
-
$this->mapCssToHtmlAttributes($newStyleDeclarations, $node);
|
397 |
-
}
|
398 |
-
$node->setAttribute(
|
399 |
-
'style',
|
400 |
-
$this->generateStyleStringFromDeclarationsArrays($oldStyleDeclarations, $newStyleDeclarations)
|
401 |
-
);
|
402 |
-
}
|
403 |
-
}
|
404 |
-
|
405 |
-
restore_error_handler();
|
406 |
-
|
407 |
-
if ($this->isInlineStyleAttributesParsingEnabled) {
|
408 |
-
$this->fillStyleAttributesWithMergedStyles();
|
409 |
-
}
|
410 |
-
|
411 |
-
if ($this->shouldKeepInvisibleNodes) {
|
412 |
-
$this->removeInvisibleNodes($xPath);
|
413 |
-
}
|
414 |
-
|
415 |
-
$this->copyCssWithMediaToStyleNode($xmlDocument, $xPath, $cssParts['media']);
|
416 |
-
}
|
417 |
-
|
418 |
-
/**
|
419 |
-
* Applies $styles to $node.
|
420 |
-
*
|
421 |
-
* This method maps CSS styles to HTML attributes and adds those to the
|
422 |
-
* node.
|
423 |
-
*
|
424 |
-
* @param string[] $styles the new CSS styles taken from the global styles to be applied to this node
|
425 |
-
* @param \DOMNode $node node to apply styles to
|
426 |
-
*
|
427 |
-
* @return void
|
428 |
-
*/
|
429 |
-
private function mapCssToHtmlAttributes(array $styles, DOMNode $node)
|
430 |
-
{
|
431 |
-
foreach ($styles as $property => $value) {
|
432 |
-
// Strip !important indicator
|
433 |
-
$value = trim(str_replace('!important', '', $value));
|
434 |
-
$this->mapCssToHtmlAttribute($property, $value, $node);
|
435 |
-
}
|
436 |
-
}
|
437 |
-
|
438 |
-
/**
|
439 |
-
* Tries to apply the CSS style to $node as an attribute.
|
440 |
-
*
|
441 |
-
* This method maps a CSS rule to HTML attributes and adds those to the node.
|
442 |
-
*
|
443 |
-
* @param string $property the name of the CSS property to map
|
444 |
-
* @param string $value the value of the style rule to map
|
445 |
-
* @param \DOMNode $node node to apply styles to
|
446 |
-
*
|
447 |
-
* @return void
|
448 |
-
*/
|
449 |
-
private function mapCssToHtmlAttribute($property, $value, DOMNode $node)
|
450 |
-
{
|
451 |
-
if (!$this->mapSimpleCssProperty($property, $value, $node)) {
|
452 |
-
$this->mapComplexCssProperty($property, $value, $node);
|
453 |
-
}
|
454 |
-
}
|
455 |
-
|
456 |
-
/**
|
457 |
-
* Looks up the CSS property in the mapping table and maps it if it matches the conditions.
|
458 |
-
*
|
459 |
-
* @param string $property the name of the CSS property to map
|
460 |
-
* @param string $value the value of the style rule to map
|
461 |
-
* @param \DOMNode $node node to apply styles to
|
462 |
-
*
|
463 |
-
* @return bool true if the property cab be mapped using the simple mapping table
|
464 |
-
*/
|
465 |
-
private function mapSimpleCssProperty($property, $value, DOMNode $node)
|
466 |
-
{
|
467 |
-
if (!isset($this->cssToHtmlMap[$property])) {
|
468 |
-
return false;
|
469 |
-
}
|
470 |
-
|
471 |
-
$mapping = $this->cssToHtmlMap[$property];
|
472 |
-
$nodesMatch = !isset($mapping['nodes']) || in_array($node->nodeName, $mapping['nodes'], true);
|
473 |
-
$valuesMatch = !isset($mapping['values']) || in_array($value, $mapping['values'], true);
|
474 |
-
if (!$nodesMatch || !$valuesMatch) {
|
475 |
-
return false;
|
476 |
-
}
|
477 |
-
|
478 |
-
$node->setAttribute($mapping['attribute'], $value);
|
479 |
-
|
480 |
-
return true;
|
481 |
-
}
|
482 |
-
|
483 |
-
/**
|
484 |
-
* Maps CSS properties that need special transformation to an HTML attribute.
|
485 |
-
*
|
486 |
-
* @param string $property the name of the CSS property to map
|
487 |
-
* @param string $value the value of the style rule to map
|
488 |
-
* @param \DOMNode $node node to apply styles to
|
489 |
-
*
|
490 |
-
* @return void
|
491 |
-
*/
|
492 |
-
private function mapComplexCssProperty($property, $value, DOMNode $node)
|
493 |
-
{
|
494 |
-
$nodeName = $node->nodeName;
|
495 |
-
$isTable = $nodeName === 'table';
|
496 |
-
$isImage = $nodeName === 'img';
|
497 |
-
$isTableOrImage = $isTable || $isImage;
|
498 |
-
|
499 |
-
switch ($property) {
|
500 |
-
case 'background':
|
501 |
-
// Parse out the color, if any
|
502 |
-
$styles = explode(' ', $value);
|
503 |
-
$first = $styles[0];
|
504 |
-
if (!is_numeric(substr($first, 0, 1)) && substr($first, 0, 3) !== 'url') {
|
505 |
-
// This is not a position or image, assume it's a color
|
506 |
-
$node->setAttribute('bgcolor', $first);
|
507 |
-
}
|
508 |
-
break;
|
509 |
-
case 'width':
|
510 |
-
// intentional fall-through
|
511 |
-
case 'height':
|
512 |
-
// Only parse values in px and %, but not values like "auto".
|
513 |
-
if (preg_match('/^\d+(px|%)$/', $value)) {
|
514 |
-
// Remove 'px'. This regex only conserves numbers and %
|
515 |
-
$number = preg_replace('/[^0-9.%]/', '', $value);
|
516 |
-
$node->setAttribute($property, $number);
|
517 |
-
}
|
518 |
-
break;
|
519 |
-
case 'margin':
|
520 |
-
if ($isTableOrImage) {
|
521 |
-
$margins = $this->parseCssShorthandValue($value);
|
522 |
-
if ($margins['left'] === 'auto' && $margins['right'] === 'auto') {
|
523 |
-
$node->setAttribute('align', 'center');
|
524 |
-
}
|
525 |
-
}
|
526 |
-
break;
|
527 |
-
case 'border':
|
528 |
-
if ($isTableOrImage) {
|
529 |
-
if ($value === 'none' || $value === '0') {
|
530 |
-
$node->setAttribute('border', '0');
|
531 |
-
}
|
532 |
-
}
|
533 |
-
break;
|
534 |
-
default:
|
535 |
-
}
|
536 |
-
}
|
537 |
-
|
538 |
-
/**
|
539 |
-
* Parses a shorthand CSS value and splits it into individual values
|
540 |
-
*
|
541 |
-
* @param string $value a string of CSS value with 1, 2, 3 or 4 sizes
|
542 |
-
* For example: padding: 0 auto;
|
543 |
-
* '0 auto' is split into top: 0, left: auto, bottom: 0,
|
544 |
-
* right: auto.
|
545 |
-
*
|
546 |
-
* @return string[] an array of values for top, right, bottom and left (using these as associative array keys)
|
547 |
-
*/
|
548 |
-
private function parseCssShorthandValue($value)
|
549 |
-
{
|
550 |
-
$values = preg_split('/\\s+/', $value);
|
551 |
-
|
552 |
-
$css = array();
|
553 |
-
$css['top'] = $values[0];
|
554 |
-
$css['right'] = (count($values) > 1) ? $values[1] : $css['top'];
|
555 |
-
$css['bottom'] = (count($values) > 2) ? $values[2] : $css['top'];
|
556 |
-
$css['left'] = (count($values) > 3) ? $values[3] : $css['right'];
|
557 |
-
|
558 |
-
return $css;
|
559 |
-
}
|
560 |
-
|
561 |
-
/**
|
562 |
-
* Extracts and parses the individual rules from a CSS string.
|
563 |
-
*
|
564 |
-
* @param string $css a string of raw CSS code
|
565 |
-
*
|
566 |
-
* @return string[][] an array of string sub-arrays with the keys
|
567 |
-
* "selector" (the CSS selector(s), e.g., "*" or "h1"),
|
568 |
-
* "declarationsBLock" (the semicolon-separated CSS declarations for that selector(s),
|
569 |
-
* e.g., "color: red; height: 4px;"),
|
570 |
-
* and "line" (the line number e.g. 42)
|
571 |
-
*/
|
572 |
-
private function parseCssRules($css)
|
573 |
-
{
|
574 |
-
$cssKey = md5($css);
|
575 |
-
if (!isset($this->caches[self::CACHE_KEY_CSS][$cssKey])) {
|
576 |
-
// process the CSS file for selectors and definitions
|
577 |
-
preg_match_all('/(?:^|[\\s^{}]*)([^{]+){([^}]*)}/mis', $css, $matches, PREG_SET_ORDER);
|
578 |
-
|
579 |
-
$cssRules = array();
|
580 |
-
/** @var string[] $cssRule */
|
581 |
-
foreach ($matches as $key => $cssRule) {
|
582 |
-
$cssDeclaration = trim($cssRule[2]);
|
583 |
-
if ($cssDeclaration === '') {
|
584 |
-
continue;
|
585 |
-
}
|
586 |
-
|
587 |
-
$selectors = explode(',', $cssRule[1]);
|
588 |
-
foreach ($selectors as $selector) {
|
589 |
-
// don't process pseudo-elements and behavioral (dynamic) pseudo-classes;
|
590 |
-
// only allow structural pseudo-classes
|
591 |
-
$hasPseudoElement = strpos($selector, '::') !== false;
|
592 |
-
$hasAnyPseudoClass = (bool) preg_match('/:[a-zA-Z]/', $selector);
|
593 |
-
$hasSupportedPseudoClass = (bool) preg_match('/:\\S+\\-(child|type\\()/i', $selector);
|
594 |
-
if ($hasPseudoElement || ($hasAnyPseudoClass && !$hasSupportedPseudoClass)) {
|
595 |
-
continue;
|
596 |
-
}
|
597 |
-
|
598 |
-
$cssRules[] = array(
|
599 |
-
'selector' => trim($selector),
|
600 |
-
'declarationsBlock' => $cssDeclaration,
|
601 |
-
// keep track of where it appears in the file, since order is important
|
602 |
-
'line' => $key,
|
603 |
-
);
|
604 |
-
}
|
605 |
-
}
|
606 |
-
|
607 |
-
usort($cssRules, array($this, 'sortBySelectorPrecedence'));
|
608 |
-
|
609 |
-
$this->caches[self::CACHE_KEY_CSS][$cssKey] = $cssRules;
|
610 |
-
}
|
611 |
-
|
612 |
-
return $this->caches[self::CACHE_KEY_CSS][$cssKey];
|
613 |
-
}
|
614 |
-
|
615 |
-
/**
|
616 |
-
* Disables the parsing of inline styles.
|
617 |
-
*
|
618 |
-
* @return void
|
619 |
-
*/
|
620 |
-
public function disableInlineStyleAttributesParsing()
|
621 |
-
{
|
622 |
-
$this->isInlineStyleAttributesParsingEnabled = false;
|
623 |
-
}
|
624 |
-
|
625 |
-
/**
|
626 |
-
* Disables the parsing of <style> blocks.
|
627 |
-
*
|
628 |
-
* @return void
|
629 |
-
*/
|
630 |
-
public function disableStyleBlocksParsing()
|
631 |
-
{
|
632 |
-
$this->isStyleBlocksParsingEnabled = false;
|
633 |
-
}
|
634 |
-
|
635 |
-
/**
|
636 |
-
* Disables the removal of elements with `display: none` properties.
|
637 |
-
*
|
638 |
-
* @return void
|
639 |
-
*/
|
640 |
-
public function disableInvisibleNodeRemoval()
|
641 |
-
{
|
642 |
-
$this->shouldKeepInvisibleNodes = false;
|
643 |
-
}
|
644 |
-
|
645 |
-
/**
|
646 |
-
* Enables the attachment/override of HTML attributes for which a
|
647 |
-
* corresponding CSS property has been set.
|
648 |
-
*
|
649 |
-
* @return void
|
650 |
-
*/
|
651 |
-
public function enableCssToHtmlMapping()
|
652 |
-
{
|
653 |
-
$this->shouldMapCssToHtml = true;
|
654 |
-
}
|
655 |
-
|
656 |
-
/**
|
657 |
-
* Clears all caches.
|
658 |
-
*
|
659 |
-
* @return void
|
660 |
-
*/
|
661 |
-
private function clearAllCaches()
|
662 |
-
{
|
663 |
-
$this->clearCache(self::CACHE_KEY_CSS);
|
664 |
-
$this->clearCache(self::CACHE_KEY_SELECTOR);
|
665 |
-
$this->clearCache(self::CACHE_KEY_XPATH);
|
666 |
-
$this->clearCache(self::CACHE_KEY_CSS_DECLARATIONS_BLOCK);
|
667 |
-
$this->clearCache(self::CACHE_KEY_COMBINED_STYLES);
|
668 |
-
}
|
669 |
-
|
670 |
-
/**
|
671 |
-
* Clears a single cache by key.
|
672 |
-
*
|
673 |
-
* @param int $key the cache key, must be CACHE_KEY_CSS, CACHE_KEY_SELECTOR, CACHE_KEY_XPATH
|
674 |
-
* or CACHE_KEY_CSS_DECLARATION_BLOCK
|
675 |
-
*
|
676 |
-
* @return void
|
677 |
-
*
|
678 |
-
* @throws \InvalidArgumentException
|
679 |
-
*/
|
680 |
-
private function clearCache($key)
|
681 |
-
{
|
682 |
-
$allowedCacheKeys = array(
|
683 |
-
self::CACHE_KEY_CSS,
|
684 |
-
self::CACHE_KEY_SELECTOR,
|
685 |
-
self::CACHE_KEY_XPATH,
|
686 |
-
self::CACHE_KEY_CSS_DECLARATIONS_BLOCK,
|
687 |
-
self::CACHE_KEY_COMBINED_STYLES,
|
688 |
-
);
|
689 |
-
if (!in_array($key, $allowedCacheKeys, true)) {
|
690 |
-
throw new InvalidArgumentException('Invalid cache key: ' . $key, 1391822035);
|
691 |
-
}
|
692 |
-
|
693 |
-
$this->caches[$key] = array();
|
694 |
-
}
|
695 |
-
|
696 |
-
/**
|
697 |
-
* Purges the visited nodes.
|
698 |
-
*
|
699 |
-
* @return void
|
700 |
-
*/
|
701 |
-
private function purgeVisitedNodes()
|
702 |
-
{
|
703 |
-
$this->visitedNodes = array();
|
704 |
-
$this->styleAttributesForNodes = array();
|
705 |
-
}
|
706 |
-
|
707 |
-
/**
|
708 |
-
* Marks a tag for removal.
|
709 |
-
*
|
710 |
-
* There are some HTML tags that DOMDocument cannot process, and it will throw an error if it encounters them.
|
711 |
-
* In particular, DOMDocument will complain if you try to use HTML5 tags in an XHTML document.
|
712 |
-
*
|
713 |
-
* Note: The tags will not be removed if they have any content.
|
714 |
-
*
|
715 |
-
* @param string $tagName the tag name, e.g., "p"
|
716 |
-
*
|
717 |
-
* @return void
|
718 |
-
*/
|
719 |
-
public function addUnprocessableHtmlTag($tagName)
|
720 |
-
{
|
721 |
-
$this->unprocessableHtmlTags[] = $tagName;
|
722 |
-
}
|
723 |
-
|
724 |
-
/**
|
725 |
-
* Drops a tag from the removal list.
|
726 |
-
*
|
727 |
-
* @param string $tagName the tag name, e.g., "p"
|
728 |
-
*
|
729 |
-
* @return void
|
730 |
-
*/
|
731 |
-
public function removeUnprocessableHtmlTag($tagName)
|
732 |
-
{
|
733 |
-
$key = array_search($tagName, $this->unprocessableHtmlTags, true);
|
734 |
-
if ($key !== false) {
|
735 |
-
unset($this->unprocessableHtmlTags[$key]);
|
736 |
-
}
|
737 |
-
}
|
738 |
-
|
739 |
-
/**
|
740 |
-
* Marks a media query type to keep.
|
741 |
-
*
|
742 |
-
* @param string $mediaName the media type name, e.g., "braille"
|
743 |
-
*
|
744 |
-
* @return void
|
745 |
-
*/
|
746 |
-
public function addAllowedMediaType($mediaName)
|
747 |
-
{
|
748 |
-
$this->allowedMediaTypes[$mediaName] = true;
|
749 |
-
}
|
750 |
-
|
751 |
-
/**
|
752 |
-
* Drops a media query type from the allowed list.
|
753 |
-
*
|
754 |
-
* @param string $mediaName the tag name, e.g., "braille"
|
755 |
-
*
|
756 |
-
* @return void
|
757 |
-
*/
|
758 |
-
public function removeAllowedMediaType($mediaName)
|
759 |
-
{
|
760 |
-
if (isset($this->allowedMediaTypes[$mediaName])) {
|
761 |
-
unset($this->allowedMediaTypes[$mediaName]);
|
762 |
-
}
|
763 |
-
}
|
764 |
-
|
765 |
-
/**
|
766 |
-
* Adds a selector to exclude nodes from emogrification.
|
767 |
-
*
|
768 |
-
* Any nodes that match the selector will not have their style altered.
|
769 |
-
*
|
770 |
-
* @param string $selector the selector to exclude, e.g., ".editor"
|
771 |
-
*
|
772 |
-
* @return void
|
773 |
-
*/
|
774 |
-
public function addExcludedSelector($selector)
|
775 |
-
{
|
776 |
-
$this->excludedSelectors[$selector] = true;
|
777 |
-
}
|
778 |
-
|
779 |
-
/**
|
780 |
-
* No longer excludes the nodes matching this selector from emogrification.
|
781 |
-
*
|
782 |
-
* @param string $selector the selector to no longer exclude, e.g., ".editor"
|
783 |
-
*
|
784 |
-
* @return void
|
785 |
-
*/
|
786 |
-
public function removeExcludedSelector($selector)
|
787 |
-
{
|
788 |
-
if (isset($this->excludedSelectors[$selector])) {
|
789 |
-
unset($this->excludedSelectors[$selector]);
|
790 |
-
}
|
791 |
-
}
|
792 |
-
|
793 |
-
/**
|
794 |
-
* This removes styles from your email that contain display:none.
|
795 |
-
* We need to look for display:none, but we need to do a case-insensitive search. Since DOMDocument only
|
796 |
-
* supports XPath 1.0, lower-case() isn't available to us. We've thus far only set attributes to lowercase,
|
797 |
-
* not attribute values. Consequently, we need to translate() the letters that would be in 'NONE' ("NOE")
|
798 |
-
* to lowercase.
|
799 |
-
*
|
800 |
-
* @param \DOMXPath $xPath
|
801 |
-
*
|
802 |
-
* @return void
|
803 |
-
*/
|
804 |
-
private function removeInvisibleNodes(DOMXPath $xPath)
|
805 |
-
{
|
806 |
-
$nodesWithStyleDisplayNone = $xPath->query(
|
807 |
-
'//*[contains(translate(translate(@style," ",""),"NOE","noe"),"display:none")]'
|
808 |
-
);
|
809 |
-
if ($nodesWithStyleDisplayNone->length === 0) {
|
810 |
-
return;
|
811 |
-
}
|
812 |
-
|
813 |
-
// The checks on parentNode and is_callable below ensure that if we've deleted the parent node,
|
814 |
-
// we don't try to call removeChild on a nonexistent child node
|
815 |
-
/** @var \DOMNode $node */
|
816 |
-
foreach ($nodesWithStyleDisplayNone as $node) {
|
817 |
-
if ($node->parentNode && is_callable(array($node->parentNode, 'removeChild'))) {
|
818 |
-
$node->parentNode->removeChild($node);
|
819 |
-
}
|
820 |
-
}
|
821 |
-
}
|
822 |
-
|
823 |
-
private function normalizeStyleAttributes_callback( $m ) {
|
824 |
-
return strtolower( $m[0] );
|
825 |
-
}
|
826 |
-
|
827 |
-
/**
|
828 |
-
* Normalizes the value of the "style" attribute and saves it.
|
829 |
-
*
|
830 |
-
* @param \DOMElement $node
|
831 |
-
*
|
832 |
-
* @return void
|
833 |
-
*/
|
834 |
-
private function normalizeStyleAttributes(DOMElement $node)
|
835 |
-
{
|
836 |
-
$normalizedOriginalStyle = preg_replace_callback(
|
837 |
-
'/[A-z\\-]+(?=\\:)/S',
|
838 |
-
array( $this, 'normalizeStyleAttributes_callback' ),
|
839 |
-
$node->getAttribute('style')
|
840 |
-
);
|
841 |
-
|
842 |
-
// in order to not overwrite existing style attributes in the HTML, we
|
843 |
-
// have to save the original HTML styles
|
844 |
-
$nodePath = $node->getNodePath();
|
845 |
-
if (!isset($this->styleAttributesForNodes[$nodePath])) {
|
846 |
-
$this->styleAttributesForNodes[$nodePath] = $this->parseCssDeclarationsBlock($normalizedOriginalStyle);
|
847 |
-
$this->visitedNodes[$nodePath] = $node;
|
848 |
-
}
|
849 |
-
|
850 |
-
$node->setAttribute('style', $normalizedOriginalStyle);
|
851 |
-
}
|
852 |
-
|
853 |
-
/**
|
854 |
-
* Merges styles from styles attributes and style nodes and applies them to the attribute nodes
|
855 |
-
*
|
856 |
-
* @return void
|
857 |
-
*/
|
858 |
-
private function fillStyleAttributesWithMergedStyles()
|
859 |
-
{
|
860 |
-
foreach ($this->styleAttributesForNodes as $nodePath => $styleAttributesForNode) {
|
861 |
-
$node = $this->visitedNodes[$nodePath];
|
862 |
-
$currentStyleAttributes = $this->parseCssDeclarationsBlock($node->getAttribute('style'));
|
863 |
-
$node->setAttribute(
|
864 |
-
'style',
|
865 |
-
$this->generateStyleStringFromDeclarationsArrays(
|
866 |
-
$currentStyleAttributes,
|
867 |
-
$styleAttributesForNode
|
868 |
-
)
|
869 |
-
);
|
870 |
-
}
|
871 |
-
}
|
872 |
-
|
873 |
-
/**
|
874 |
-
* This method merges old or existing name/value array with new name/value array
|
875 |
-
* and then generates a string of the combined style suitable for placing inline.
|
876 |
-
* This becomes the single point for CSS string generation allowing for consistent
|
877 |
-
* CSS output no matter where the CSS originally came from.
|
878 |
-
*
|
879 |
-
* @param string[] $oldStyles
|
880 |
-
* @param string[] $newStyles
|
881 |
-
*
|
882 |
-
* @return string
|
883 |
-
*/
|
884 |
-
private function generateStyleStringFromDeclarationsArrays(array $oldStyles, array $newStyles)
|
885 |
-
{
|
886 |
-
$combinedStyles = array_merge($oldStyles, $newStyles);
|
887 |
-
$cacheKey = serialize($combinedStyles);
|
888 |
-
if (isset($this->caches[self::CACHE_KEY_COMBINED_STYLES][$cacheKey])) {
|
889 |
-
return $this->caches[self::CACHE_KEY_COMBINED_STYLES][$cacheKey];
|
890 |
-
}
|
891 |
-
|
892 |
-
foreach ($oldStyles as $attributeName => $attributeValue) {
|
893 |
-
if (!isset($newStyles[$attributeName])) {
|
894 |
-
continue;
|
895 |
-
}
|
896 |
-
|
897 |
-
$newAttributeValue = $newStyles[$attributeName];
|
898 |
-
if ($this->attributeValueIsImportant($attributeValue)
|
899 |
-
&& !$this->attributeValueIsImportant($newAttributeValue)
|
900 |
-
) {
|
901 |
-
$combinedStyles[$attributeName] = $attributeValue;
|
902 |
-
}
|
903 |
-
}
|
904 |
-
|
905 |
-
$style = '';
|
906 |
-
foreach ($combinedStyles as $attributeName => $attributeValue) {
|
907 |
-
$style .= strtolower(trim($attributeName)) . ': ' . trim($attributeValue) . '; ';
|
908 |
-
}
|
909 |
-
$trimmedStyle = rtrim($style);
|
910 |
-
|
911 |
-
$this->caches[self::CACHE_KEY_COMBINED_STYLES][$cacheKey] = $trimmedStyle;
|
912 |
-
|
913 |
-
return $trimmedStyle;
|
914 |
-
}
|
915 |
-
|
916 |
-
/**
|
917 |
-
* Checks whether $attributeValue is marked as !important.
|
918 |
-
*
|
919 |
-
* @param string $attributeValue
|
920 |
-
*
|
921 |
-
* @return bool
|
922 |
-
*/
|
923 |
-
private function attributeValueIsImportant($attributeValue)
|
924 |
-
{
|
925 |
-
return strtolower(substr(trim($attributeValue), -10)) === '!important';
|
926 |
-
}
|
927 |
-
|
928 |
-
/**
|
929 |
-
* Applies $css to $xmlDocument, limited to the media queries that actually apply to the document.
|
930 |
-
*
|
931 |
-
* @param \DOMDocument $xmlDocument the document to match against
|
932 |
-
* @param \DOMXPath $xPath
|
933 |
-
* @param string $css a string of CSS
|
934 |
-
*
|
935 |
-
* @return void
|
936 |
-
*/
|
937 |
-
private function copyCssWithMediaToStyleNode(DOMDocument $xmlDocument, DOMXPath $xPath, $css)
|
938 |
-
{
|
939 |
-
if ($css === '') {
|
940 |
-
return;
|
941 |
-
}
|
942 |
-
|
943 |
-
$mediaQueriesRelevantForDocument = array();
|
944 |
-
|
945 |
-
foreach ($this->extractMediaQueriesFromCss($css) as $mediaQuery) {
|
946 |
-
foreach ($this->parseCssRules($mediaQuery['css']) as $selector) {
|
947 |
-
if ($this->existsMatchForCssSelector($xPath, $selector['selector'])) {
|
948 |
-
$mediaQueriesRelevantForDocument[] = $mediaQuery['query'];
|
949 |
-
break;
|
950 |
-
}
|
951 |
-
}
|
952 |
-
}
|
953 |
-
|
954 |
-
$this->addStyleElementToDocument($xmlDocument, implode($mediaQueriesRelevantForDocument));
|
955 |
-
}
|
956 |
-
|
957 |
-
/**
|
958 |
-
* Extracts the media queries from $css while skipping empty media queries.
|
959 |
-
*
|
960 |
-
* @param string $css
|
961 |
-
*
|
962 |
-
* @return string[][] numeric array with string sub-arrays with the keys "css" and "query"
|
963 |
-
*/
|
964 |
-
private function extractMediaQueriesFromCss($css)
|
965 |
-
{
|
966 |
-
preg_match_all('/@media\\b[^{]*({((?:[^{}]+|(?1))*)})/', $css, $rawMediaQueries, PREG_SET_ORDER);
|
967 |
-
$parsedQueries = array();
|
968 |
-
|
969 |
-
foreach ($rawMediaQueries as $mediaQuery) {
|
970 |
-
if ($mediaQuery[2] !== '') {
|
971 |
-
$parsedQueries[] = array(
|
972 |
-
'css' => $mediaQuery[2],
|
973 |
-
'query' => $mediaQuery[0],
|
974 |
-
);
|
975 |
-
}
|
976 |
-
}
|
977 |
-
|
978 |
-
return $parsedQueries;
|
979 |
-
}
|
980 |
-
|
981 |
-
/**
|
982 |
-
* Checks whether there is at least one matching element for $cssSelector.
|
983 |
-
*
|
984 |
-
* @param \DOMXPath $xPath
|
985 |
-
* @param string $cssSelector
|
986 |
-
*
|
987 |
-
* @return bool
|
988 |
-
*/
|
989 |
-
private function existsMatchForCssSelector(DOMXPath $xPath, $cssSelector)
|
990 |
-
{
|
991 |
-
$nodesMatchingSelector = $xPath->query($this->translateCssToXpath($cssSelector));
|
992 |
-
|
993 |
-
return $nodesMatchingSelector !== false && $nodesMatchingSelector->length !== 0;
|
994 |
-
}
|
995 |
-
|
996 |
-
/**
|
997 |
-
* Returns CSS content.
|
998 |
-
*
|
999 |
-
* @param \DOMXPath $xPath
|
1000 |
-
*
|
1001 |
-
* @return string
|
1002 |
-
*/
|
1003 |
-
private function getCssFromAllStyleNodes(DOMXPath $xPath)
|
1004 |
-
{
|
1005 |
-
$styleNodes = $xPath->query('//style');
|
1006 |
-
|
1007 |
-
if ($styleNodes === false) {
|
1008 |
-
return '';
|
1009 |
-
}
|
1010 |
-
|
1011 |
-
$css = '';
|
1012 |
-
/** @var \DOMNode $styleNode */
|
1013 |
-
foreach ($styleNodes as $styleNode) {
|
1014 |
-
$css .= "\n\n" . $styleNode->nodeValue;
|
1015 |
-
$styleNode->parentNode->removeChild($styleNode);
|
1016 |
-
}
|
1017 |
-
|
1018 |
-
return $css;
|
1019 |
-
}
|
1020 |
-
|
1021 |
-
/**
|
1022 |
-
* Adds a style element with $css to $document.
|
1023 |
-
*
|
1024 |
-
* This method is protected to allow overriding.
|
1025 |
-
*
|
1026 |
-
* @see https://github.com/jjriv/emogrifier/issues/103
|
1027 |
-
*
|
1028 |
-
* @param \DOMDocument $document
|
1029 |
-
* @param string $css
|
1030 |
-
*
|
1031 |
-
* @return void
|
1032 |
-
*/
|
1033 |
-
protected function addStyleElementToDocument(DOMDocument $document, $css)
|
1034 |
-
{
|
1035 |
-
$styleElement = $document->createElement('style', $css);
|
1036 |
-
$styleAttribute = $document->createAttribute('type');
|
1037 |
-
$styleAttribute->value = 'text/css';
|
1038 |
-
$styleElement->appendChild($styleAttribute);
|
1039 |
-
|
1040 |
-
$head = $this->getOrCreateHeadElement($document);
|
1041 |
-
$head->appendChild($styleElement);
|
1042 |
-
}
|
1043 |
-
|
1044 |
-
/**
|
1045 |
-
* Returns the existing or creates a new head element in $document.
|
1046 |
-
*
|
1047 |
-
* @param \DOMDocument $document
|
1048 |
-
*
|
1049 |
-
* @return \DOMNode the head element
|
1050 |
-
*/
|
1051 |
-
private function getOrCreateHeadElement(DOMDocument $document)
|
1052 |
-
{
|
1053 |
-
$head = $document->getElementsByTagName('head')->item(0);
|
1054 |
-
|
1055 |
-
if ($head === null) {
|
1056 |
-
$head = $document->createElement('head');
|
1057 |
-
$html = $document->getElementsByTagName('html')->item(0);
|
1058 |
-
$html->insertBefore($head, $document->getElementsByTagName('body')->item(0));
|
1059 |
-
}
|
1060 |
-
|
1061 |
-
return $head;
|
1062 |
-
}
|
1063 |
-
|
1064 |
-
/**
|
1065 |
-
* Splits input CSS code to an array where:
|
1066 |
-
*
|
1067 |
-
* - key "css" will be contains clean CSS code
|
1068 |
-
* - key "media" will be contains all valuable media queries
|
1069 |
-
*
|
1070 |
-
* Example:
|
1071 |
-
*
|
1072 |
-
* The CSS code
|
1073 |
-
*
|
1074 |
-
* "@import "file.css"; h1 { color:red; } @media { h1 {}} @media tv { h1 {}}"
|
1075 |
-
*
|
1076 |
-
* will be parsed into the following array:
|
1077 |
-
*
|
1078 |
-
* "css" => "h1 { color:red; }"
|
1079 |
-
* "media" => "@media { h1 {}}"
|
1080 |
-
*
|
1081 |
-
* @param string $css
|
1082 |
-
*
|
1083 |
-
* @return string[]
|
1084 |
-
*/
|
1085 |
-
private function splitCssAndMediaQuery($css)
|
1086 |
-
{
|
1087 |
-
$cssWithoutComments = preg_replace('/\\/\\*.*\\*\\//sU', '', $css);
|
1088 |
-
|
1089 |
-
$mediaTypesExpression = '';
|
1090 |
-
if (!empty($this->allowedMediaTypes)) {
|
1091 |
-
$mediaTypesExpression = '|' . implode('|', array_keys($this->allowedMediaTypes));
|
1092 |
-
}
|
1093 |
-
|
1094 |
-
$cssForAllowedMediaTypes = preg_replace_callback(
|
1095 |
-
'#@media\\s+(?:only\\s)?(?:[\\s{\\(]' . $mediaTypesExpression . ')\\s?[^{]+{.*}\\s*}\\s*#misU',
|
1096 |
-
array( $this, '_media_concat' ),
|
1097 |
-
$cssWithoutComments
|
1098 |
-
);
|
1099 |
-
|
1100 |
-
// filter the CSS
|
1101 |
-
$search = array(
|
1102 |
-
'import directives' => '/^\\s*@import\\s[^;]+;/misU',
|
1103 |
-
'remaining media enclosures' => '/^\\s*@media\\s[^{]+{(.*)}\\s*}\\s/misU',
|
1104 |
-
);
|
1105 |
-
|
1106 |
-
$cleanedCss = preg_replace($search, '', $cssForAllowedMediaTypes);
|
1107 |
-
|
1108 |
-
return array('css' => $cleanedCss, 'media' => self::$_media);
|
1109 |
-
}
|
1110 |
-
|
1111 |
-
private function _media_concat( $matches ) {
|
1112 |
-
self::$_media .= $matches[0];
|
1113 |
-
}
|
1114 |
-
|
1115 |
-
/**
|
1116 |
-
* Creates a DOMDocument instance with the current HTML.
|
1117 |
-
*
|
1118 |
-
* @return \DOMDocument
|
1119 |
-
*/
|
1120 |
-
private function createXmlDocument()
|
1121 |
-
{
|
1122 |
-
$xmlDocument = new DOMDocument;
|
1123 |
-
$xmlDocument->encoding = 'UTF-8';
|
1124 |
-
$xmlDocument->strictErrorChecking = false;
|
1125 |
-
$xmlDocument->formatOutput = true;
|
1126 |
-
$libXmlState = libxml_use_internal_errors(true);
|
1127 |
-
$xmlDocument->loadHTML($this->getUnifiedHtml());
|
1128 |
-
libxml_clear_errors();
|
1129 |
-
libxml_use_internal_errors($libXmlState);
|
1130 |
-
$xmlDocument->normalizeDocument();
|
1131 |
-
|
1132 |
-
return $xmlDocument;
|
1133 |
-
}
|
1134 |
-
|
1135 |
-
/**
|
1136 |
-
* Returns the HTML with the unprocessable HTML tags removed and
|
1137 |
-
* with added document type and Content-Type meta tag if needed.
|
1138 |
-
*
|
1139 |
-
* @return string the unified HTML
|
1140 |
-
*
|
1141 |
-
* @throws \BadMethodCallException
|
1142 |
-
*/
|
1143 |
-
private function getUnifiedHtml()
|
1144 |
-
{
|
1145 |
-
$htmlWithoutUnprocessableTags = $this->removeUnprocessableTags($this->html);
|
1146 |
-
$htmlWithDocumentType = $this->ensureDocumentType($htmlWithoutUnprocessableTags);
|
1147 |
-
|
1148 |
-
return $this->addContentTypeMetaTag($htmlWithDocumentType);
|
1149 |
-
}
|
1150 |
-
|
1151 |
-
/**
|
1152 |
-
* Removes the unprocessable tags from $html (if this feature is enabled).
|
1153 |
-
*
|
1154 |
-
* @param string $html
|
1155 |
-
*
|
1156 |
-
* @return string the reworked HTML with the unprocessable tags removed
|
1157 |
-
*/
|
1158 |
-
private function removeUnprocessableTags($html)
|
1159 |
-
{
|
1160 |
-
if (empty($this->unprocessableHtmlTags)) {
|
1161 |
-
return $html;
|
1162 |
-
}
|
1163 |
-
|
1164 |
-
$unprocessableHtmlTags = implode('|', $this->unprocessableHtmlTags);
|
1165 |
-
|
1166 |
-
return preg_replace(
|
1167 |
-
'/<\\/?(' . $unprocessableHtmlTags . ')[^>]*>/i',
|
1168 |
-
'',
|
1169 |
-
$html
|
1170 |
-
);
|
1171 |
-
}
|
1172 |
-
|
1173 |
-
/**
|
1174 |
-
* Makes sure that the passed HTML has a document type.
|
1175 |
-
*
|
1176 |
-
* @param string $html
|
1177 |
-
*
|
1178 |
-
* @return string HTML with document type
|
1179 |
-
*/
|
1180 |
-
private function ensureDocumentType($html)
|
1181 |
-
{
|
1182 |
-
$hasDocumentType = stripos($html, '<!DOCTYPE') !== false;
|
1183 |
-
if ($hasDocumentType) {
|
1184 |
-
return $html;
|
1185 |
-
}
|
1186 |
-
|
1187 |
-
return self::DEFAULT_DOCUMENT_TYPE . $html;
|
1188 |
-
}
|
1189 |
-
|
1190 |
-
/**
|
1191 |
-
* Adds a Content-Type meta tag for the charset.
|
1192 |
-
*
|
1193 |
-
* @param string $html
|
1194 |
-
*
|
1195 |
-
* @return string the HTML with the meta tag added
|
1196 |
-
*/
|
1197 |
-
private function addContentTypeMetaTag($html)
|
1198 |
-
{
|
1199 |
-
$hasContentTypeMetaTag = stristr($html, 'Content-Type') !== false;
|
1200 |
-
if ($hasContentTypeMetaTag) {
|
1201 |
-
return $html;
|
1202 |
-
}
|
1203 |
-
|
1204 |
-
// We are trying to insert the meta tag to the right spot in the DOM.
|
1205 |
-
// If we just prepended it to the HTML, we would lose attributes set to the HTML tag.
|
1206 |
-
$hasHeadTag = stripos($html, '<head') !== false;
|
1207 |
-
$hasHtmlTag = stripos($html, '<html') !== false;
|
1208 |
-
|
1209 |
-
if ($hasHeadTag) {
|
1210 |
-
$reworkedHtml = preg_replace('/<head(.*?)>/i', '<head$1>' . self::CONTENT_TYPE_META_TAG, $html);
|
1211 |
-
} elseif ($hasHtmlTag) {
|
1212 |
-
$reworkedHtml = preg_replace(
|
1213 |
-
'/<html(.*?)>/i',
|
1214 |
-
'<html$1><head>' . self::CONTENT_TYPE_META_TAG . '</head>',
|
1215 |
-
$html
|
1216 |
-
);
|
1217 |
-
} else {
|
1218 |
-
$reworkedHtml = self::CONTENT_TYPE_META_TAG . $html;
|
1219 |
-
}
|
1220 |
-
|
1221 |
-
return $reworkedHtml;
|
1222 |
-
}
|
1223 |
-
|
1224 |
-
/**
|
1225 |
-
* @param string[] $a
|
1226 |
-
* @param string[] $b
|
1227 |
-
*
|
1228 |
-
* @return int
|
1229 |
-
*/
|
1230 |
-
private function sortBySelectorPrecedence(array $a, array $b)
|
1231 |
-
{
|
1232 |
-
$precedenceA = $this->getCssSelectorPrecedence($a['selector']);
|
1233 |
-
$precedenceB = $this->getCssSelectorPrecedence($b['selector']);
|
1234 |
-
|
1235 |
-
// We want these sorted in ascending order so selectors with lesser precedence get processed first and
|
1236 |
-
// selectors with greater precedence get sorted last.
|
1237 |
-
$precedenceForEquals = ($a['line'] < $b['line'] ? -1 : 1);
|
1238 |
-
$precedenceForNotEquals = ($precedenceA < $precedenceB ? -1 : 1);
|
1239 |
-
return ($precedenceA === $precedenceB) ? $precedenceForEquals : $precedenceForNotEquals;
|
1240 |
-
}
|
1241 |
-
|
1242 |
-
/**
|
1243 |
-
* @param string $selector
|
1244 |
-
*
|
1245 |
-
* @return int
|
1246 |
-
*/
|
1247 |
-
private function getCssSelectorPrecedence($selector)
|
1248 |
-
{
|
1249 |
-
$selectorKey = md5($selector);
|
1250 |
-
if (!isset($this->caches[self::CACHE_KEY_SELECTOR][$selectorKey])) {
|
1251 |
-
$precedence = 0;
|
1252 |
-
$value = 100;
|
1253 |
-
// ids: worth 100, classes: worth 10, elements: worth 1
|
1254 |
-
$search = array('\\#','\\.','');
|
1255 |
-
|
1256 |
-
foreach ($search as $s) {
|
1257 |
-
if (trim($selector) === '') {
|
1258 |
-
break;
|
1259 |
-
}
|
1260 |
-
$number = 0;
|
1261 |
-
$selector = preg_replace('/' . $s . '\\w+/', '', $selector, -1, $number);
|
1262 |
-
$precedence += ($value * $number);
|
1263 |
-
$value /= 10;
|
1264 |
-
}
|
1265 |
-
$this->caches[self::CACHE_KEY_SELECTOR][$selectorKey] = $precedence;
|
1266 |
-
}
|
1267 |
-
|
1268 |
-
return $this->caches[self::CACHE_KEY_SELECTOR][$selectorKey];
|
1269 |
-
}
|
1270 |
-
|
1271 |
-
private function translateCssToXpath_callback( $matches ) {
|
1272 |
-
return strtolower($matches[0]);
|
1273 |
-
}
|
1274 |
-
|
1275 |
-
/**
|
1276 |
-
* Maps a CSS selector to an XPath query string.
|
1277 |
-
*
|
1278 |
-
* @see http://plasmasturm.org/log/444/
|
1279 |
-
*
|
1280 |
-
* @param string $cssSelector a CSS selector
|
1281 |
-
*
|
1282 |
-
* @return string the corresponding XPath selector
|
1283 |
-
*/
|
1284 |
-
private function translateCssToXpath($cssSelector)
|
1285 |
-
{
|
1286 |
-
$paddedSelector = ' ' . $cssSelector . ' ';
|
1287 |
-
$lowercasePaddedSelector = preg_replace_callback(
|
1288 |
-
'/\\s+\\w+\\s+/',
|
1289 |
-
array( $this, 'translateCssToXpath_callback' ),
|
1290 |
-
$paddedSelector
|
1291 |
-
);
|
1292 |
-
|
1293 |
-
$trimmedLowercaseSelector = trim($lowercasePaddedSelector);
|
1294 |
-
$xPathKey = md5($trimmedLowercaseSelector);
|
1295 |
-
if (!isset($this->caches[self::CACHE_KEY_XPATH][$xPathKey])) {
|
1296 |
-
$roughXpath = '//' . preg_replace(
|
1297 |
-
array_keys($this->xPathRules),
|
1298 |
-
$this->xPathRules,
|
1299 |
-
$trimmedLowercaseSelector
|
1300 |
-
);
|
1301 |
-
$xPathWithIdAttributeMatchers = preg_replace_callback(
|
1302 |
-
self::ID_ATTRIBUTE_MATCHER,
|
1303 |
-
array($this, 'matchIdAttributes'),
|
1304 |
-
$roughXpath
|
1305 |
-
);
|
1306 |
-
$xPathWithIdAttributeAndClassMatchers = preg_replace_callback(
|
1307 |
-
self::CLASS_ATTRIBUTE_MATCHER,
|
1308 |
-
array($this, 'matchClassAttributes'),
|
1309 |
-
$xPathWithIdAttributeMatchers
|
1310 |
-
);
|
1311 |
-
|
1312 |
-
// Advanced selectors are going to require a bit more advanced emogrification.
|
1313 |
-
// When we required PHP 5.3, we could do this with closures.
|
1314 |
-
$xPathWithIdAttributeAndClassMatchers = preg_replace_callback(
|
1315 |
-
'/([^\\/]+):nth-child\\(\\s*(odd|even|[+\\-]?\\d|[+\\-]?\\d?n(\\s*[+\\-]\\s*\\d)?)\\s*\\)/i',
|
1316 |
-
array($this, 'translateNthChild'),
|
1317 |
-
$xPathWithIdAttributeAndClassMatchers
|
1318 |
-
);
|
1319 |
-
$finalXpath = preg_replace_callback(
|
1320 |
-
'/([^\\/]+):nth-of-type\\(\s*(odd|even|[+\\-]?\\d|[+\\-]?\\d?n(\\s*[+\\-]\\s*\\d)?)\\s*\\)/i',
|
1321 |
-
array($this, 'translateNthOfType'),
|
1322 |
-
$xPathWithIdAttributeAndClassMatchers
|
1323 |
-
);
|
1324 |
-
|
1325 |
-
$this->caches[self::CACHE_KEY_SELECTOR][$xPathKey] = $finalXpath;
|
1326 |
-
}
|
1327 |
-
return $this->caches[self::CACHE_KEY_SELECTOR][$xPathKey];
|
1328 |
-
}
|
1329 |
-
|
1330 |
-
/**
|
1331 |
-
* @param string[] $match
|
1332 |
-
*
|
1333 |
-
* @return string
|
1334 |
-
*/
|
1335 |
-
private function matchIdAttributes(array $match)
|
1336 |
-
{
|
1337 |
-
return ($match[1] !== '' ? $match[1] : '*') . '[@id="' . $match[2] . '"]';
|
1338 |
-
}
|
1339 |
-
|
1340 |
-
/**
|
1341 |
-
* @param string[] $match
|
1342 |
-
*
|
1343 |
-
* @return string
|
1344 |
-
*/
|
1345 |
-
private function matchClassAttributes(array $match)
|
1346 |
-
{
|
1347 |
-
return ($match[1] !== '' ? $match[1] : '*') . '[contains(concat(" ",@class," "),concat(" ","' .
|
1348 |
-
implode(
|
1349 |
-
'"," "))][contains(concat(" ",@class," "),concat(" ","',
|
1350 |
-
explode('.', substr($match[2], 1))
|
1351 |
-
) . '"," "))]';
|
1352 |
-
}
|
1353 |
-
|
1354 |
-
/**
|
1355 |
-
* @param string[] $match
|
1356 |
-
*
|
1357 |
-
* @return string
|
1358 |
-
*/
|
1359 |
-
private function translateNthChild(array $match)
|
1360 |
-
{
|
1361 |
-
$parseResult = $this->parseNth($match);
|
1362 |
-
|
1363 |
-
if (isset($parseResult[self::MULTIPLIER])) {
|
1364 |
-
if ($parseResult[self::MULTIPLIER] < 0) {
|
1365 |
-
$parseResult[self::MULTIPLIER] = abs($parseResult[self::MULTIPLIER]);
|
1366 |
-
$xPathExpression = sprintf(
|
1367 |
-
'*[(last() - position()) mod %u = %u]/self::%s',
|
1368 |
-
$parseResult[self::MULTIPLIER],
|
1369 |
-
$parseResult[self::INDEX],
|
1370 |
-
$match[1]
|
1371 |
-
);
|
1372 |
-
} else {
|
1373 |
-
$xPathExpression = sprintf(
|
1374 |
-
'*[position() mod %u = %u]/self::%s',
|
1375 |
-
$parseResult[self::MULTIPLIER],
|
1376 |
-
$parseResult[self::INDEX],
|
1377 |
-
$match[1]
|
1378 |
-
);
|
1379 |
-
}
|
1380 |
-
} else {
|
1381 |
-
$xPathExpression = sprintf('*[%u]/self::%s', $parseResult[self::INDEX], $match[1]);
|
1382 |
-
}
|
1383 |
-
|
1384 |
-
return $xPathExpression;
|
1385 |
-
}
|
1386 |
-
|
1387 |
-
/**
|
1388 |
-
* @param string[] $match
|
1389 |
-
*
|
1390 |
-
* @return string
|
1391 |
-
*/
|
1392 |
-
private function translateNthOfType(array $match)
|
1393 |
-
{
|
1394 |
-
$parseResult = $this->parseNth($match);
|
1395 |
-
|
1396 |
-
if (isset($parseResult[self::MULTIPLIER])) {
|
1397 |
-
if ($parseResult[self::MULTIPLIER] < 0) {
|
1398 |
-
$parseResult[self::MULTIPLIER] = abs($parseResult[self::MULTIPLIER]);
|
1399 |
-
$xPathExpression = sprintf(
|
1400 |
-
'%s[(last() - position()) mod %u = %u]',
|
1401 |
-
$match[1],
|
1402 |
-
$parseResult[self::MULTIPLIER],
|
1403 |
-
$parseResult[self::INDEX]
|
1404 |
-
);
|
1405 |
-
} else {
|
1406 |
-
$xPathExpression = sprintf(
|
1407 |
-
'%s[position() mod %u = %u]',
|
1408 |
-
$match[1],
|
1409 |
-
$parseResult[self::MULTIPLIER],
|
1410 |
-
$parseResult[self::INDEX]
|
1411 |
-
);
|
1412 |
-
}
|
1413 |
-
} else {
|
1414 |
-
$xPathExpression = sprintf('%s[%u]', $match[1], $parseResult[self::INDEX]);
|
1415 |
-
}
|
1416 |
-
|
1417 |
-
return $xPathExpression;
|
1418 |
-
}
|
1419 |
-
|
1420 |
-
/**
|
1421 |
-
* @param string[] $match
|
1422 |
-
*
|
1423 |
-
* @return int[]
|
1424 |
-
*/
|
1425 |
-
private function parseNth(array $match)
|
1426 |
-
{
|
1427 |
-
if (in_array(strtolower($match[2]), array('even', 'odd'), true)) {
|
1428 |
-
// we have "even" or "odd"
|
1429 |
-
$index = strtolower($match[2]) === 'even' ? 0 : 1;
|
1430 |
-
return array(self::MULTIPLIER => 2, self::INDEX => $index);
|
1431 |
-
}
|
1432 |
-
if (stripos($match[2], 'n') === false) {
|
1433 |
-
// if there is a multiplier
|
1434 |
-
$index = (int) str_replace(' ', '', $match[2]);
|
1435 |
-
return array(self::INDEX => $index);
|
1436 |
-
}
|
1437 |
-
|
1438 |
-
if (isset($match[3])) {
|
1439 |
-
$multipleTerm = str_replace($match[3], '', $match[2]);
|
1440 |
-
$index = (int) str_replace(' ', '', $match[3]);
|
1441 |
-
} else {
|
1442 |
-
$multipleTerm = $match[2];
|
1443 |
-
$index = 0;
|
1444 |
-
}
|
1445 |
-
|
1446 |
-
$multiplier = str_ireplace('n', '', $multipleTerm);
|
1447 |
-
|
1448 |
-
if ($multiplier === '') {
|
1449 |
-
$multiplier = 1;
|
1450 |
-
} elseif ($multiplier === '0') {
|
1451 |
-
return array(self::INDEX => $index);
|
1452 |
-
} else {
|
1453 |
-
$multiplier = (int) $multiplier;
|
1454 |
-
}
|
1455 |
-
|
1456 |
-
while ($index < 0) {
|
1457 |
-
$index += abs($multiplier);
|
1458 |
-
}
|
1459 |
-
|
1460 |
-
return array(self::MULTIPLIER => $multiplier, self::INDEX => $index);
|
1461 |
-
}
|
1462 |
-
|
1463 |
-
/**
|
1464 |
-
* Parses a CSS declaration block into property name/value pairs.
|
1465 |
-
*
|
1466 |
-
* Example:
|
1467 |
-
*
|
1468 |
-
* The declaration block
|
1469 |
-
*
|
1470 |
-
* "color: #000; font-weight: bold;"
|
1471 |
-
*
|
1472 |
-
* will be parsed into the following array:
|
1473 |
-
*
|
1474 |
-
* "color" => "#000"
|
1475 |
-
* "font-weight" => "bold"
|
1476 |
-
*
|
1477 |
-
* @param string $cssDeclarationsBlock the CSS declarations block without the curly braces, may be empty
|
1478 |
-
*
|
1479 |
-
* @return string[]
|
1480 |
-
* the CSS declarations with the property names as array keys and the property values as array values
|
1481 |
-
*/
|
1482 |
-
private function parseCssDeclarationsBlock($cssDeclarationsBlock)
|
1483 |
-
{
|
1484 |
-
if (isset($this->caches[self::CACHE_KEY_CSS_DECLARATIONS_BLOCK][$cssDeclarationsBlock])) {
|
1485 |
-
return $this->caches[self::CACHE_KEY_CSS_DECLARATIONS_BLOCK][$cssDeclarationsBlock];
|
1486 |
-
}
|
1487 |
-
|
1488 |
-
$properties = array();
|
1489 |
-
$declarations = preg_split('/;(?!base64|charset)/', $cssDeclarationsBlock);
|
1490 |
-
|
1491 |
-
foreach ($declarations as $declaration) {
|
1492 |
-
$matches = array();
|
1493 |
-
if (!preg_match('/^([A-Za-z\\-]+)\\s*:\\s*(.+)$/', trim($declaration), $matches)) {
|
1494 |
-
continue;
|
1495 |
-
}
|
1496 |
-
|
1497 |
-
$propertyName = strtolower($matches[1]);
|
1498 |
-
$propertyValue = $matches[2];
|
1499 |
-
$properties[$propertyName] = $propertyValue;
|
1500 |
-
}
|
1501 |
-
$this->caches[self::CACHE_KEY_CSS_DECLARATIONS_BLOCK][$cssDeclarationsBlock] = $properties;
|
1502 |
-
|
1503 |
-
return $properties;
|
1504 |
-
}
|
1505 |
-
|
1506 |
-
/**
|
1507 |
-
* Find the nodes that are not to be emogrified.
|
1508 |
-
*
|
1509 |
-
* @param \DOMXPath $xPath
|
1510 |
-
*
|
1511 |
-
* @return \DOMElement[]
|
1512 |
-
*/
|
1513 |
-
private function getNodesToExclude(DOMXPath $xPath)
|
1514 |
-
{
|
1515 |
-
$excludedNodes = array();
|
1516 |
-
foreach (array_keys($this->excludedSelectors) as $selectorToExclude) {
|
1517 |
-
foreach ($xPath->query($this->translateCssToXpath($selectorToExclude)) as $node) {
|
1518 |
-
$excludedNodes[] = $node;
|
1519 |
-
}
|
1520 |
-
}
|
1521 |
-
|
1522 |
-
return $excludedNodes;
|
1523 |
-
}
|
1524 |
-
|
1525 |
-
/**
|
1526 |
-
* Handles invalid xPath expression warnings, generated by process() method,
|
1527 |
-
* during querying \DOMDocument and trigger \InvalidArgumentException
|
1528 |
-
* with invalid selector.
|
1529 |
-
*
|
1530 |
-
* @param int $type
|
1531 |
-
* @param string $message
|
1532 |
-
* @param string $file
|
1533 |
-
* @param int $line
|
1534 |
-
* @param array $context
|
1535 |
-
*
|
1536 |
-
* @return bool always false
|
1537 |
-
*
|
1538 |
-
* @throws \InvalidArgumentException
|
1539 |
-
*/
|
1540 |
-
public function handleXpathError($type, $message, $file, $line, array $context)
|
1541 |
-
{
|
1542 |
-
if ($type === E_WARNING && isset($context['cssRule']['selector'])) {
|
1543 |
-
throw new InvalidArgumentException(
|
1544 |
-
sprintf(
|
1545 |
-
'%s in selector >> %s << in %s on line %s',
|
1546 |
-
$message,
|
1547 |
-
$context['cssRule']['selector'],
|
1548 |
-
$file,
|
1549 |
-
$line
|
1550 |
-
)
|
1551 |
-
);
|
1552 |
-
}
|
1553 |
-
|
1554 |
-
// the normal error handling continues when handler return false
|
1555 |
-
return false;
|
1556 |
-
}
|
1557 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/usage-tracking/class-usage-tracking-base.php
DELETED
@@ -1,581 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Reusable Usage Tracking library. For sending plugin usage data and events to
|
4 |
-
* Tracks.
|
5 |
-
**/
|
6 |
-
|
7 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
8 |
-
exit;
|
9 |
-
}
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Usage Tracking class. Please update the prefix to something unique to your
|
13 |
-
* plugin.
|
14 |
-
*/
|
15 |
-
abstract class WP_Job_Manager_Usage_Tracking_Base {
|
16 |
-
const PLUGIN_PREFIX = 'plugin_';
|
17 |
-
|
18 |
-
/*
|
19 |
-
* Instance variables.
|
20 |
-
*/
|
21 |
-
|
22 |
-
/**
|
23 |
-
* The name of the option for hiding the Usage Tracking opt-in dialog.
|
24 |
-
*
|
25 |
-
* @var string
|
26 |
-
**/
|
27 |
-
protected $hide_tracking_opt_in_option_name;
|
28 |
-
|
29 |
-
/**
|
30 |
-
* The name of the cron job action for regularly logging usage data.
|
31 |
-
*
|
32 |
-
* @var string
|
33 |
-
**/
|
34 |
-
private $job_name;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Callback function for the usage tracking job.
|
38 |
-
*
|
39 |
-
* @var array
|
40 |
-
**/
|
41 |
-
private $callback;
|
42 |
-
|
43 |
-
|
44 |
-
/*
|
45 |
-
* Class variables.
|
46 |
-
*/
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Subclass instances.
|
50 |
-
*
|
51 |
-
* @var array
|
52 |
-
**/
|
53 |
-
private static $instances = array();
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Gets the singleton instance of this class. Subclasses should implement
|
57 |
-
* this as follows:
|
58 |
-
*
|
59 |
-
* ```
|
60 |
-
* public static function get_instance() {
|
61 |
-
* return self::get_instance_for_subclass( get_class() );
|
62 |
-
* }
|
63 |
-
* ```
|
64 |
-
*
|
65 |
-
* This function cannot be abstract (because it is static) but it *must* be
|
66 |
-
* implemented by subclasses.
|
67 |
-
*/
|
68 |
-
public static function get_instance() {
|
69 |
-
throw new Exception( 'Usage Tracking subclasses must implement get_instance. See class-usage-tracking-base.php' );
|
70 |
-
}
|
71 |
-
|
72 |
-
|
73 |
-
/*
|
74 |
-
* Abstract methods.
|
75 |
-
*/
|
76 |
-
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Get prefix for actions and strings. Should be unique to this plugin.
|
80 |
-
*
|
81 |
-
* @return string The prefix string.
|
82 |
-
**/
|
83 |
-
abstract protected function get_prefix();
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Get the text domain used by this plugin. This class will add some
|
87 |
-
* strings to be translated.
|
88 |
-
*
|
89 |
-
* @return string The text domain string.
|
90 |
-
**/
|
91 |
-
abstract protected function get_text_domain();
|
92 |
-
|
93 |
-
/**
|
94 |
-
* Determine whether usage tracking is enabled.
|
95 |
-
*
|
96 |
-
* @return bool true if usage tracking is enabled, false otherwise.
|
97 |
-
**/
|
98 |
-
abstract protected function get_tracking_enabled();
|
99 |
-
|
100 |
-
/**
|
101 |
-
* Set whether usage tracking is enabled.
|
102 |
-
*
|
103 |
-
* @param bool $enable true if usage tracking should be enabled, false if
|
104 |
-
* it should be disabled.
|
105 |
-
**/
|
106 |
-
abstract protected function set_tracking_enabled( $enable );
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Determine whether current user can manage the tracking options.
|
110 |
-
*
|
111 |
-
* @return bool true if the current user is allowed to manage the tracking.
|
112 |
-
* options, false otherwise.
|
113 |
-
**/
|
114 |
-
abstract protected function current_user_can_manage_tracking();
|
115 |
-
|
116 |
-
/**
|
117 |
-
* Get the text to display in the opt-in dialog for users to enable
|
118 |
-
* tracking. This text should include a link to a page indicating what data
|
119 |
-
* is being tracked.
|
120 |
-
*
|
121 |
-
* @return string the text to display in the opt-in dialog.
|
122 |
-
**/
|
123 |
-
abstract protected function opt_in_dialog_text();
|
124 |
-
|
125 |
-
/**
|
126 |
-
* Checks if we should send an activated plugin's installed version in the
|
127 |
-
* `system_log` event.
|
128 |
-
*
|
129 |
-
* @param string $plugin_slug the plugin slug to check.
|
130 |
-
*
|
131 |
-
* @return bool true if we send the version, false if not.
|
132 |
-
*/
|
133 |
-
abstract protected function do_track_plugin( $plugin_slug );
|
134 |
-
|
135 |
-
|
136 |
-
/*
|
137 |
-
* Initialization.
|
138 |
-
*/
|
139 |
-
|
140 |
-
/**
|
141 |
-
* Subclasses may override this to add plugin-specific initialization code.
|
142 |
-
* However, this constructor must be called by the subclass in order to
|
143 |
-
* properly initialize the Usage Tracking system.
|
144 |
-
*
|
145 |
-
* This class is meant to be a singleton, and assumes that the subclass is
|
146 |
-
* implemented as such. If multiple instances are instantiated, the results
|
147 |
-
* are undefined.
|
148 |
-
**/
|
149 |
-
protected function __construct() {
|
150 |
-
// Init instance vars.
|
151 |
-
$this->hide_tracking_opt_in_option_name = $this->get_prefix() . '_usage_tracking_opt_in_hide';
|
152 |
-
$this->job_name = $this->get_prefix() . '_usage_tracking_send_usage_data';
|
153 |
-
|
154 |
-
// Set up the opt-in dialog.
|
155 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_script_deps' ) );
|
156 |
-
add_action( 'admin_footer', array( $this, 'output_opt_in_js' ) );
|
157 |
-
add_action( 'admin_notices', array( $this, 'maybe_display_tracking_opt_in' ) );
|
158 |
-
add_action( 'wp_ajax_' . $this->get_prefix() . '_handle_tracking_opt_in', array( $this, 'handle_tracking_opt_in' ) );
|
159 |
-
|
160 |
-
// Set up schedule and action needed for cron job.
|
161 |
-
add_filter( 'cron_schedules', array( $this, 'add_usage_tracking_two_week_schedule' ) );
|
162 |
-
add_action( $this->job_name, array( $this, 'send_usage_data' ) );
|
163 |
-
}
|
164 |
-
|
165 |
-
/**
|
166 |
-
* Create (if necessary) and return the singleton instance for the given
|
167 |
-
* subclass.
|
168 |
-
*
|
169 |
-
* @param string $subclass the name of the subclass.
|
170 |
-
* @return object Instance of $subclass.
|
171 |
-
*/
|
172 |
-
protected static function get_instance_for_subclass( $subclass ) {
|
173 |
-
if ( ! isset( self::$instances[ $subclass ] ) ) {
|
174 |
-
self::$instances[ $subclass ] = new $subclass();
|
175 |
-
}
|
176 |
-
return self::$instances[ $subclass ];
|
177 |
-
}
|
178 |
-
|
179 |
-
|
180 |
-
/*
|
181 |
-
* Public methods.
|
182 |
-
*/
|
183 |
-
|
184 |
-
/**
|
185 |
-
* Set the Usage Data Callback. This callback should return an array of
|
186 |
-
* data to be logged periodically to Tracks.
|
187 |
-
*
|
188 |
-
* @param callable $callback the callback returning the usage data to be logged.
|
189 |
-
**/
|
190 |
-
public function set_callback( $callback ) {
|
191 |
-
$this->callback = $callback;
|
192 |
-
}
|
193 |
-
|
194 |
-
/**
|
195 |
-
* Send an event to Tracks if tracking is enabled.
|
196 |
-
*
|
197 |
-
* @param string $event The event name. The prefix string will be
|
198 |
-
* automatically prepended to this, so please supply this string without a
|
199 |
-
* prefix.
|
200 |
-
* @param array $properties Event Properties.
|
201 |
-
* @param null|int $event_timestamp When the event occurred.
|
202 |
-
*
|
203 |
-
* @return null|WP_Error
|
204 |
-
**/
|
205 |
-
public function send_event( $event, $properties = array(), $event_timestamp = null ) {
|
206 |
-
|
207 |
-
// Only continue if tracking is enabled.
|
208 |
-
if ( ! $this->is_tracking_enabled() ) {
|
209 |
-
return false;
|
210 |
-
}
|
211 |
-
|
212 |
-
$pixel = 'http://pixel.wp.com/t.gif';
|
213 |
-
$event_name = $this->get_event_prefix() . '_' . $event;
|
214 |
-
$user = wp_get_current_user();
|
215 |
-
|
216 |
-
if ( null === $event_timestamp ) {
|
217 |
-
$event_timestamp = time();
|
218 |
-
}
|
219 |
-
|
220 |
-
$properties['admin_email'] = get_option( 'admin_email' );
|
221 |
-
$properties['_ut'] = $this->get_event_prefix() . ':site_url';
|
222 |
-
// Use site URL as the userid to enable usage tracking at the site level.
|
223 |
-
// Note that we would likely want to use site URL + user ID for userid if we were.
|
224 |
-
// to ever add event tracking at the user level.
|
225 |
-
$properties['_ui'] = site_url();
|
226 |
-
$properties['_ul'] = $user->user_login;
|
227 |
-
$properties['_en'] = $event_name;
|
228 |
-
$properties['_ts'] = $event_timestamp . '000';
|
229 |
-
$properties['_rt'] = round( microtime( true ) * 1000 ); // log time.
|
230 |
-
$p = array();
|
231 |
-
|
232 |
-
foreach ( $properties as $key => $value ) {
|
233 |
-
$p[] = rawurlencode( $key ) . '=' . rawurlencode( $value );
|
234 |
-
}
|
235 |
-
|
236 |
-
$pixel .= '?' . implode( '&', $p ) . '&_=_'; // EOF marker.
|
237 |
-
$response = wp_remote_get(
|
238 |
-
$pixel,
|
239 |
-
array(
|
240 |
-
'blocking' => true,
|
241 |
-
'timeout' => 1,
|
242 |
-
'redirection' => 2,
|
243 |
-
'httpversion' => '1.1',
|
244 |
-
'user-agent' => $this->get_event_prefix() . '_usage_tracking',
|
245 |
-
)
|
246 |
-
);
|
247 |
-
|
248 |
-
if ( is_wp_error( $response ) ) {
|
249 |
-
return $response;
|
250 |
-
}
|
251 |
-
|
252 |
-
$code = isset( $response['response']['code'] ) ? $response['response']['code'] : 0;
|
253 |
-
|
254 |
-
if ( 200 !== $code ) {
|
255 |
-
return new WP_Error( 'request_failed', 'HTTP Request failed', $code );
|
256 |
-
}
|
257 |
-
|
258 |
-
return true;
|
259 |
-
}
|
260 |
-
|
261 |
-
/**
|
262 |
-
* Set up a regular cron job to send usage data. The job will only send
|
263 |
-
* the data if tracking is enabled, so it is safe to call this function,
|
264 |
-
* and schedule the job, before the user opts into tracking.
|
265 |
-
**/
|
266 |
-
public function schedule_tracking_task() {
|
267 |
-
if ( ! wp_next_scheduled( $this->job_name ) ) {
|
268 |
-
wp_schedule_event( time(), $this->get_prefix() . '_usage_tracking_two_weeks', $this->job_name );
|
269 |
-
}
|
270 |
-
}
|
271 |
-
|
272 |
-
/**
|
273 |
-
* Unschedule the job scheduled by schedule_tracking_task if any is
|
274 |
-
* scheduled. This should be called on plugin deactivation.
|
275 |
-
**/
|
276 |
-
public function unschedule_tracking_task() {
|
277 |
-
if ( wp_next_scheduled( $this->job_name ) ) {
|
278 |
-
wp_clear_scheduled_hook( $this->job_name );
|
279 |
-
}
|
280 |
-
}
|
281 |
-
|
282 |
-
/**
|
283 |
-
* Check if tracking is enabled.
|
284 |
-
*
|
285 |
-
* @return bool true if tracking is enabled, false otherwise.
|
286 |
-
**/
|
287 |
-
public function is_tracking_enabled() {
|
288 |
-
// Defer to the plugin-specific function.
|
289 |
-
return $this->get_tracking_enabled();
|
290 |
-
}
|
291 |
-
|
292 |
-
/**
|
293 |
-
* Call the usage data callback and send the usage data to Tracks. Only
|
294 |
-
* sends data if tracking is enabled.
|
295 |
-
**/
|
296 |
-
public function send_usage_data() {
|
297 |
-
if ( ! self::is_tracking_enabled() || ! is_callable( $this->callback ) ) {
|
298 |
-
return;
|
299 |
-
}
|
300 |
-
|
301 |
-
$usage_data = call_user_func( $this->callback );
|
302 |
-
|
303 |
-
if ( ! is_array( $usage_data ) ) {
|
304 |
-
return;
|
305 |
-
}
|
306 |
-
|
307 |
-
self::send_event( 'system_log', $this->get_system_data() );
|
308 |
-
self::send_event( 'stats_log', $usage_data );
|
309 |
-
}
|
310 |
-
|
311 |
-
|
312 |
-
/**
|
313 |
-
* Internal methods.
|
314 |
-
*/
|
315 |
-
|
316 |
-
/**
|
317 |
-
* Get the prefix for the event-related values. By default, this is the
|
318 |
-
* same prefix used everywhere else, but plugins may override this if
|
319 |
-
* needed.
|
320 |
-
*/
|
321 |
-
protected function get_event_prefix() {
|
322 |
-
return $this->get_prefix();
|
323 |
-
}
|
324 |
-
|
325 |
-
/**
|
326 |
-
* Add two week schedule to use for cron job. Should not be called
|
327 |
-
* externally.
|
328 |
-
*
|
329 |
-
* @param array $schedules the existing cron schedules.
|
330 |
-
* @return array of $schedules.
|
331 |
-
**/
|
332 |
-
public function add_usage_tracking_two_week_schedule( $schedules ) {
|
333 |
-
$day_in_seconds = 86400;
|
334 |
-
$schedules[ $this->get_prefix() . '_usage_tracking_two_weeks' ] = array(
|
335 |
-
'interval' => 15 * $day_in_seconds,
|
336 |
-
'display' => esc_html__( 'Every Two Weeks', $this->get_text_domain() ),
|
337 |
-
);
|
338 |
-
|
339 |
-
return $schedules;
|
340 |
-
}
|
341 |
-
|
342 |
-
/**
|
343 |
-
* Collect system data to track.
|
344 |
-
*
|
345 |
-
* @return array
|
346 |
-
*/
|
347 |
-
public function get_system_data() {
|
348 |
-
global $wp_version;
|
349 |
-
|
350 |
-
/**
|
351 |
-
* Current active theme.
|
352 |
-
*
|
353 |
-
* @var WP_Theme $theme
|
354 |
-
*/
|
355 |
-
$theme = wp_get_theme();
|
356 |
-
|
357 |
-
$system_data = array();
|
358 |
-
$system_data['wp_version'] = $wp_version;
|
359 |
-
$system_data['php_version'] = PHP_VERSION;
|
360 |
-
$system_data['locale'] = get_locale();
|
361 |
-
$system_data['multisite'] = is_multisite() ? 1 : 0;
|
362 |
-
$system_data['active_theme'] = $theme['Name'];
|
363 |
-
$system_data['active_theme_version'] = $theme['Version'];
|
364 |
-
|
365 |
-
$plugin_data = $this->get_plugin_data();
|
366 |
-
foreach ( $plugin_data as $plugin_name => $plugin_version ) {
|
367 |
-
if ( $this->do_track_plugin( $plugin_name ) ) {
|
368 |
-
$plugin_friendly_name = preg_replace( '/[^a-z0-9]/', '_', $plugin_name );
|
369 |
-
$plugin_key = self::PLUGIN_PREFIX . $plugin_friendly_name;
|
370 |
-
$system_data[ $plugin_key ] = $plugin_version;
|
371 |
-
}
|
372 |
-
}
|
373 |
-
|
374 |
-
return $system_data;
|
375 |
-
}
|
376 |
-
|
377 |
-
/**
|
378 |
-
* Gets a list of activated plugins.
|
379 |
-
*
|
380 |
-
* @return array List of plugins. Index is friendly name, value is version.
|
381 |
-
*/
|
382 |
-
protected function get_plugin_data() {
|
383 |
-
$plugins = array();
|
384 |
-
foreach ( $this->get_plugins() as $plugin_basename => $plugin ) {
|
385 |
-
$plugin_name = $this->get_plugin_name( $plugin_basename );
|
386 |
-
$plugins[ $plugin_name ] = $plugin['Version'];
|
387 |
-
}
|
388 |
-
return $plugins;
|
389 |
-
}
|
390 |
-
|
391 |
-
/**
|
392 |
-
* Partial wrapper for for `get_plugins()` function. Filters out non-active plugins.
|
393 |
-
*
|
394 |
-
* @return array Key is the plugin file path and the value is an array of the plugin data.
|
395 |
-
*/
|
396 |
-
protected function get_plugins() {
|
397 |
-
if ( ! function_exists( 'get_plugins' ) ) {
|
398 |
-
include_once ABSPATH . 'wp-admin/includes/plugin.php';
|
399 |
-
}
|
400 |
-
$plugins = get_plugins();
|
401 |
-
foreach ( $plugins as $plugin_basename => $plugin_data ) {
|
402 |
-
if ( ! is_plugin_active( $plugin_basename ) ) {
|
403 |
-
unset( $plugins[ $plugin_basename ] );
|
404 |
-
}
|
405 |
-
}
|
406 |
-
return $plugins;
|
407 |
-
}
|
408 |
-
|
409 |
-
/**
|
410 |
-
* Returns a friendly slug for a plugin.
|
411 |
-
*
|
412 |
-
* @param string $basename Plugin basename.
|
413 |
-
*
|
414 |
-
* @return string
|
415 |
-
*/
|
416 |
-
private function get_plugin_name( $basename ) {
|
417 |
-
$basename = strtolower( $basename );
|
418 |
-
if ( false === strpos( $basename, '/' ) ) {
|
419 |
-
return basename( $basename, '.php' );
|
420 |
-
}
|
421 |
-
return dirname( $basename );
|
422 |
-
}
|
423 |
-
|
424 |
-
/**
|
425 |
-
* Hide the opt-in for enabling usage tracking.
|
426 |
-
**/
|
427 |
-
protected function hide_tracking_opt_in() {
|
428 |
-
update_option( $this->hide_tracking_opt_in_option_name, true );
|
429 |
-
}
|
430 |
-
|
431 |
-
/**
|
432 |
-
* Determine whether the opt-in for enabling usage tracking is hidden.
|
433 |
-
*
|
434 |
-
* @return bool true if the opt-in is hidden, false otherwise.
|
435 |
-
**/
|
436 |
-
protected function is_opt_in_hidden() {
|
437 |
-
return (bool) get_option( $this->hide_tracking_opt_in_option_name );
|
438 |
-
}
|
439 |
-
|
440 |
-
/**
|
441 |
-
* Allowed html tags, used by wp_kses, for the translated opt-in dialog
|
442 |
-
* text.
|
443 |
-
*
|
444 |
-
* @return array the html tags.
|
445 |
-
**/
|
446 |
-
protected function opt_in_dialog_text_allowed_html() {
|
447 |
-
return array(
|
448 |
-
'a' => array(
|
449 |
-
'href' => array(),
|
450 |
-
'title' => array(),
|
451 |
-
'target' => array(),
|
452 |
-
),
|
453 |
-
'em' => array(),
|
454 |
-
'strong' => array(),
|
455 |
-
);
|
456 |
-
}
|
457 |
-
|
458 |
-
/**
|
459 |
-
* If needed, display opt-in dialog to enable tracking. Should not be
|
460 |
-
* called externally.
|
461 |
-
**/
|
462 |
-
public function maybe_display_tracking_opt_in() {
|
463 |
-
$opt_in_hidden = $this->is_opt_in_hidden();
|
464 |
-
$user_tracking_enabled = $this->is_tracking_enabled();
|
465 |
-
$can_manage_tracking = $this->current_user_can_manage_tracking();
|
466 |
-
|
467 |
-
if ( ! $user_tracking_enabled && ! $opt_in_hidden && $can_manage_tracking ) { ?>
|
468 |
-
<div id="<?php echo esc_attr( $this->get_prefix() ); ?>-usage-tracking-notice" class="notice notice-info"
|
469 |
-
data-nonce="<?php echo esc_attr( wp_create_nonce( 'tracking-opt-in' ) ); ?>">
|
470 |
-
<p>
|
471 |
-
<?php echo wp_kses( $this->opt_in_dialog_text(), $this->opt_in_dialog_text_allowed_html() ); ?>
|
472 |
-
</p>
|
473 |
-
<p>
|
474 |
-
<button class="button button-primary" data-enable-tracking="yes">
|
475 |
-
<?php esc_html_e( 'Enable Usage Tracking', $this->get_text_domain() ); ?>
|
476 |
-
</button>
|
477 |
-
<button class="button" data-enable-tracking="no">
|
478 |
-
<?php esc_html_e( 'Disable Usage Tracking', $this->get_text_domain() ); ?>
|
479 |
-
</button>
|
480 |
-
<span id="progress" class="spinner alignleft"></span>
|
481 |
-
</p>
|
482 |
-
</div>
|
483 |
-
<div id="<?php echo esc_attr( $this->get_prefix() ); ?>-usage-tracking-enable-success" class="notice notice-success hidden">
|
484 |
-
<p><?php esc_html_e( 'Usage data enabled. Thank you!', $this->get_text_domain() ); ?></p>
|
485 |
-
</div>
|
486 |
-
<div id="<?php echo esc_attr( $this->get_prefix() ); ?>-usage-tracking-disable-success" class="notice notice-success hidden">
|
487 |
-
<p><?php esc_html_e( 'Disabled usage tracking.', $this->get_text_domain() ); ?></p>
|
488 |
-
</div>
|
489 |
-
<div id="<?php echo esc_attr( $this->get_prefix() ); ?>-usage-tracking-failure" class="notice notice-error hidden">
|
490 |
-
<p><?php esc_html_e( 'Something went wrong. Please try again later.', $this->get_text_domain() ); ?></p>
|
491 |
-
</div>
|
492 |
-
<?php
|
493 |
-
}
|
494 |
-
}
|
495 |
-
|
496 |
-
/**
|
497 |
-
* Handle ajax request from the opt-in dialog. Should not be called
|
498 |
-
* externally.
|
499 |
-
**/
|
500 |
-
public function handle_tracking_opt_in() {
|
501 |
-
check_ajax_referer( 'tracking-opt-in', 'nonce' );
|
502 |
-
|
503 |
-
if ( ! $this->current_user_can_manage_tracking() ) {
|
504 |
-
wp_die( '', '', 403 );
|
505 |
-
}
|
506 |
-
|
507 |
-
$enable_tracking = isset( $_POST['enable_tracking'] ) && '1' === $_POST['enable_tracking'];
|
508 |
-
$this->set_tracking_enabled( $enable_tracking );
|
509 |
-
$this->hide_tracking_opt_in();
|
510 |
-
$this->send_usage_data();
|
511 |
-
wp_die();
|
512 |
-
}
|
513 |
-
|
514 |
-
/**
|
515 |
-
* Ensure that jQuery has been enqueued since the opt-in dialog JS depends
|
516 |
-
* on it. Should not be called externally.
|
517 |
-
**/
|
518 |
-
public function enqueue_script_deps() {
|
519 |
-
// Ensure jQuery is loaded.
|
520 |
-
wp_enqueue_script(
|
521 |
-
$this->get_prefix() . '_usage-tracking-notice', '',
|
522 |
-
array( 'jquery' ), null, true
|
523 |
-
);
|
524 |
-
}
|
525 |
-
|
526 |
-
/**
|
527 |
-
* Output the JS code to handle the opt-in dialog. Should not be called
|
528 |
-
* externally.
|
529 |
-
**/
|
530 |
-
public function output_opt_in_js() {
|
531 |
-
?>
|
532 |
-
<script type="text/javascript">
|
533 |
-
(function( prefix ) {
|
534 |
-
jQuery( document ).ready( function() {
|
535 |
-
function displayProgressIndicator() {
|
536 |
-
jQuery( '#' + prefix + '-usage-tracking-notice #progress' ).addClass( 'is-active' );
|
537 |
-
}
|
538 |
-
|
539 |
-
function displaySuccess( enabledTracking ) {
|
540 |
-
if ( enabledTracking ) {
|
541 |
-
jQuery( '#' + prefix + '-usage-tracking-enable-success' ).show();
|
542 |
-
} else {
|
543 |
-
jQuery( '#' + prefix + '-usage-tracking-disable-success' ).show();
|
544 |
-
}
|
545 |
-
jQuery( '#' + prefix + '-usage-tracking-notice' ).hide();
|
546 |
-
}
|
547 |
-
|
548 |
-
function displayError() {
|
549 |
-
jQuery( '#' + prefix + '-usage-tracking-failure' ).show();
|
550 |
-
jQuery( '#' + prefix + '-usage-tracking-notice' ).hide();
|
551 |
-
}
|
552 |
-
|
553 |
-
// Handle button clicks.
|
554 |
-
jQuery( '#' + prefix + '-usage-tracking-notice button' ).click( function( event ) {
|
555 |
-
event.preventDefault();
|
556 |
-
|
557 |
-
var enableTracking = jQuery( this ).data( 'enable-tracking' ) == 'yes';
|
558 |
-
var nonce = jQuery( '#' + prefix + '-usage-tracking-notice' ).data( 'nonce' );
|
559 |
-
|
560 |
-
displayProgressIndicator();
|
561 |
-
|
562 |
-
jQuery.ajax( {
|
563 |
-
type: 'POST',
|
564 |
-
url: ajaxurl,
|
565 |
-
data: {
|
566 |
-
action: prefix + '_handle_tracking_opt_in',
|
567 |
-
enable_tracking: enableTracking ? 1 : 0,
|
568 |
-
nonce: nonce,
|
569 |
-
},
|
570 |
-
success: function() {
|
571 |
-
displaySuccess( enableTracking );
|
572 |
-
},
|
573 |
-
error: displayError,
|
574 |
-
} );
|
575 |
-
});
|
576 |
-
});
|
577 |
-
})( "<?php echo esc_js( $this->get_prefix() ); ?>" );
|
578 |
-
</script>
|
579 |
-
<?php
|
580 |
-
}
|
581 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/usage-tracking/tests/support/class-usage-tracking-test-subclass.php
DELETED
@@ -1,67 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
require_once dirname( __FILE__ ) . '/../../class-usage-tracking-base.php';
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Usage Tracking subclass for testing. Please update the superclass name to
|
7 |
-
* match the one used by your plugin (usage-tracking/class-usage-tracking-base.php).
|
8 |
-
*/
|
9 |
-
class Usage_Tracking_Test_Subclass extends WP_Job_Manager_Usage_Tracking_Base {
|
10 |
-
|
11 |
-
const TRACKING_ENABLED_OPTION_NAME = 'testing-usage-tracking-enabled';
|
12 |
-
|
13 |
-
public static function get_instance() {
|
14 |
-
return self::get_instance_for_subclass( get_class() );
|
15 |
-
}
|
16 |
-
|
17 |
-
public function get_prefix() {
|
18 |
-
return 'testing';
|
19 |
-
}
|
20 |
-
|
21 |
-
public function get_text_domain() {
|
22 |
-
return 'text-domain';
|
23 |
-
}
|
24 |
-
|
25 |
-
public function get_tracking_enabled() {
|
26 |
-
return get_option( self::TRACKING_ENABLED_OPTION_NAME ) || false;
|
27 |
-
}
|
28 |
-
|
29 |
-
public function set_tracking_enabled( $enable ) {
|
30 |
-
update_option( self::TRACKING_ENABLED_OPTION_NAME, $enable );
|
31 |
-
}
|
32 |
-
|
33 |
-
public function current_user_can_manage_tracking() {
|
34 |
-
return current_user_can( 'manage_usage_tracking' );
|
35 |
-
}
|
36 |
-
|
37 |
-
public function opt_in_dialog_text() {
|
38 |
-
return 'Please enable Usage Tracking!';
|
39 |
-
}
|
40 |
-
|
41 |
-
public function do_track_plugin( $plugin_slug ) {
|
42 |
-
if ( in_array( $plugin_slug, array( 'hello', 'test', 'my-favorite-plugin' ), true ) ) {
|
43 |
-
return true;
|
44 |
-
}
|
45 |
-
return false;
|
46 |
-
}
|
47 |
-
|
48 |
-
protected function get_plugins() {
|
49 |
-
return array(
|
50 |
-
'Hello.php' => array(
|
51 |
-
'Version' => '1.0.0',
|
52 |
-
),
|
53 |
-
'jetpack/jetpack.php' => array(
|
54 |
-
'Version' => '1.1.1',
|
55 |
-
),
|
56 |
-
'test-dev/test.php' => array(
|
57 |
-
'Version' => '1.1.1',
|
58 |
-
),
|
59 |
-
'test/test.php' => array(
|
60 |
-
'Version' => '1.0.0',
|
61 |
-
),
|
62 |
-
'my-favorite-plugin/my-favorite-plugin.php' => array(
|
63 |
-
'Version' => '1.0.0',
|
64 |
-
),
|
65 |
-
);
|
66 |
-
}
|
67 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/usage-tracking/tests/support/wp-die-exception.php
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class WP_Die_Exception extends Exception {
|
4 |
-
private $wp_die_args = null;
|
5 |
-
|
6 |
-
public function set_wp_die_args( $message, $title, $args ) {
|
7 |
-
$this->wp_die_args = array(
|
8 |
-
'message' => $message,
|
9 |
-
'title' => $title,
|
10 |
-
'args' => $args,
|
11 |
-
);
|
12 |
-
}
|
13 |
-
|
14 |
-
public function get_wp_die_args() {
|
15 |
-
return $this->wp_die_args;
|
16 |
-
}
|
17 |
-
}
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/usage-tracking/tests/test-class-usage-tracking.php
DELETED
@@ -1,527 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
include dirname( __FILE__ ) . '/support/class-usage-tracking-test-subclass.php';
|
4 |
-
include dirname( __FILE__ ) . '/support/wp-die-exception.php';
|
5 |
-
|
6 |
-
// Ensure instance is set up before PHPUnit starts removing hooks.
|
7 |
-
Usage_Tracking_Test_Subclass::get_instance();
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Usage Tracking tests. Please update the prefix to something unique to your
|
11 |
-
* plugin.
|
12 |
-
*
|
13 |
-
* @group usage-tracking
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_Usage_Tracking_Test extends WP_UnitTestCase {
|
16 |
-
private $event_counts = array();
|
17 |
-
private $track_http_request = array();
|
18 |
-
|
19 |
-
public function setUp() {
|
20 |
-
parent::setUp();
|
21 |
-
// Update the class name here to match the Usage Tracking class.
|
22 |
-
$this->usage_tracking = Usage_Tracking_Test_Subclass::get_instance();
|
23 |
-
$this->usage_tracking->set_callback( array( $this, 'basicDataCallback' ) );
|
24 |
-
}
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Ensure cron job action is set up.
|
28 |
-
*
|
29 |
-
* @covers {Prefix}_Usage_Tracking::hook
|
30 |
-
*/
|
31 |
-
public function testCronJobActionAdded() {
|
32 |
-
$this->assertTrue( !! has_action( $this->usage_tracking->get_prefix() . '_usage_tracking_send_usage_data', array( $this->usage_tracking, 'send_usage_data' ) ) );
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* Ensure scheduling function works properly.
|
37 |
-
*
|
38 |
-
* @covers {Prefix}_Usage_Tracking::schedule_tracking_task
|
39 |
-
*/
|
40 |
-
public function testScheduleTrackingTask() {
|
41 |
-
// Make sure it's cleared initially.
|
42 |
-
wp_clear_scheduled_hook( $this->usage_tracking->get_prefix() . '_usage_tracking_send_usage_data' );
|
43 |
-
|
44 |
-
// Record how many times the event is scheduled.
|
45 |
-
$this->event_counts['schedule_event'] = 0;
|
46 |
-
add_filter( 'schedule_event', array( $this, 'countScheduleEvent' ) );
|
47 |
-
|
48 |
-
// Should successfully schedule the task.
|
49 |
-
$this->assertFalse( wp_get_schedule( $this->usage_tracking->get_prefix() . '_usage_tracking_send_usage_data' ), 'Not scheduled initial' );
|
50 |
-
$this->usage_tracking->schedule_tracking_task();
|
51 |
-
$this->assertNotFalse( wp_get_schedule( $this->usage_tracking->get_prefix() . '_usage_tracking_send_usage_data' ), 'Schedules a job' );
|
52 |
-
$this->assertEquals( 1, $this->event_counts['schedule_event'], 'Schedules only one job' );
|
53 |
-
|
54 |
-
// Should not duplicate when called again.
|
55 |
-
$this->usage_tracking->schedule_tracking_task();
|
56 |
-
$this->assertEquals( 1, $this->event_counts['schedule_event'], 'Does not schedule an additional job' );
|
57 |
-
}
|
58 |
-
|
59 |
-
/* Test ajax request cases */
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Ensure ajax hook is set up properly.
|
63 |
-
*
|
64 |
-
* @covers {Prefix}_Usage_Tracking::hook
|
65 |
-
*/
|
66 |
-
public function testAjaxRequestSetup() {
|
67 |
-
$this->assertTrue( !! has_action( 'wp_ajax_' . $this->usage_tracking->get_prefix() . '_handle_tracking_opt_in', array( $this->usage_tracking, 'handle_tracking_opt_in' ) ) );
|
68 |
-
}
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Ensure tracking is enabled through ajax request.
|
72 |
-
*
|
73 |
-
* @covers {Prefix}_Usage_Tracking::_handle_tracking_opt_in
|
74 |
-
*/
|
75 |
-
public function testAjaxRequestEnableTracking() {
|
76 |
-
$this->setupAjaxRequest();
|
77 |
-
$_POST['enable_tracking'] = '1';
|
78 |
-
|
79 |
-
$this->assertFalse( !! $this->usage_tracking->is_tracking_enabled(), 'Usage tracking initially disabled' );
|
80 |
-
$this->assertFalse( !! get_option( $this->usage_tracking->get_prefix() . '_usage_tracking_opt_in_hide' ), 'Dialog initially shown' );
|
81 |
-
|
82 |
-
try {
|
83 |
-
$this->usage_tracking->handle_tracking_opt_in();
|
84 |
-
} catch ( WP_Die_Exception $e ) {
|
85 |
-
$wp_die_args = $e->get_wp_die_args();
|
86 |
-
$this->assertEquals( array(), $wp_die_args['args'], 'wp_die call has no non-success status' );
|
87 |
-
}
|
88 |
-
|
89 |
-
$this->assertTrue( $this->usage_tracking->is_tracking_enabled(), 'Usage tracking enabled' );
|
90 |
-
$this->assertTrue( get_option( $this->usage_tracking->get_prefix() . '_usage_tracking_opt_in_hide' ), 'Dialog hidden' );
|
91 |
-
}
|
92 |
-
|
93 |
-
/**
|
94 |
-
* Ensure usage data is sent when tracking is enabled.
|
95 |
-
*
|
96 |
-
* @covers {Prefix}_Usage_Tracking::_handle_tracking_opt_in
|
97 |
-
*/
|
98 |
-
public function testAjaxRequestEnableTrackingSendsData() {
|
99 |
-
$this->setupAjaxRequest();
|
100 |
-
$_POST['enable_tracking'] = '1';
|
101 |
-
|
102 |
-
// Count the number of network requests.
|
103 |
-
$this->event_counts['http_request'] = 0;
|
104 |
-
add_filter( 'pre_http_request', array( $this, 'countHttpRequest' ) );
|
105 |
-
|
106 |
-
try {
|
107 |
-
$this->usage_tracking->handle_tracking_opt_in();
|
108 |
-
} catch ( WP_Die_Exception $e ) {
|
109 |
-
$wp_die_args = $e->get_wp_die_args();
|
110 |
-
$this->assertEquals( array(), $wp_die_args['args'], 'wp_die call has no non-success status' );
|
111 |
-
}
|
112 |
-
|
113 |
-
$this->assertEquals( 2, $this->event_counts['http_request'], 'Data was sent on usage tracking enable' );
|
114 |
-
}
|
115 |
-
|
116 |
-
/**
|
117 |
-
* Ensure tracking is disabled through ajax request.
|
118 |
-
*
|
119 |
-
* @covers {Prefix}_Usage_Tracking::_handle_tracking_opt_in
|
120 |
-
*/
|
121 |
-
public function testAjaxRequestDisableTracking() {
|
122 |
-
$this->setupAjaxRequest();
|
123 |
-
$_POST['enable_tracking'] = '0';
|
124 |
-
|
125 |
-
$this->assertFalse( !! $this->usage_tracking->is_tracking_enabled(), 'Usage tracking initially disabled' );
|
126 |
-
$this->assertFalse( !! get_option( $this->usage_tracking->get_prefix() . '_usage_tracking_opt_in_hide' ), 'Dialog initially shown' );
|
127 |
-
|
128 |
-
try {
|
129 |
-
$this->usage_tracking->handle_tracking_opt_in();
|
130 |
-
} catch ( WP_Die_Exception $e ) {
|
131 |
-
$wp_die_args = $e->get_wp_die_args();
|
132 |
-
$this->assertEquals( array(), $wp_die_args['args'], 'wp_die call has no non-success status' );
|
133 |
-
}
|
134 |
-
|
135 |
-
$this->assertFalse( !! $this->usage_tracking->is_tracking_enabled(), 'Usage tracking disabled' );
|
136 |
-
$this->assertTrue( get_option( $this->usage_tracking->get_prefix() . '_usage_tracking_opt_in_hide' ), 'Dialog hidden' );
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* Ensure ajax request fails on nonce failure and does not update option.
|
141 |
-
*
|
142 |
-
* @covers {Prefix}_Usage_Tracking::_handle_tracking_opt_in
|
143 |
-
*/
|
144 |
-
public function testAjaxRequestFailedNonce() {
|
145 |
-
$this->setupAjaxRequest();
|
146 |
-
$_REQUEST['nonce'] = 'invalid_nonce_1234';
|
147 |
-
|
148 |
-
$this->assertFalse( !! $this->usage_tracking->is_tracking_enabled(), 'Usage tracking initially disabled' );
|
149 |
-
$this->assertFalse( !! get_option( $this->usage_tracking->get_prefix() . '_usage_tracking_opt_in_hide' ), 'Dialog initially shown' );
|
150 |
-
|
151 |
-
try {
|
152 |
-
$this->usage_tracking->handle_tracking_opt_in();
|
153 |
-
} catch ( WP_Die_Exception $e ) {
|
154 |
-
$wp_die_args = $e->get_wp_die_args();
|
155 |
-
$this->assertEquals( 403, $wp_die_args['args']['response'], 'wp_die called has "Forbidden" status' );
|
156 |
-
}
|
157 |
-
|
158 |
-
$this->assertFalse( !! $this->usage_tracking->is_tracking_enabled(), 'Usage tracking disabled' );
|
159 |
-
$this->assertFalse( !! get_option( $this->usage_tracking->get_prefix() . '_usage_tracking_opt_in_hide' ), 'Dialog not hidden' );
|
160 |
-
}
|
161 |
-
|
162 |
-
/**
|
163 |
-
* Ensure ajax request fails on authorization failure and does not update option.
|
164 |
-
*
|
165 |
-
* @covers {Prefix}_Usage_Tracking::_handle_tracking_opt_in
|
166 |
-
*/
|
167 |
-
public function testAjaxRequestFailedAuth() {
|
168 |
-
$this->setupAjaxRequest();
|
169 |
-
|
170 |
-
// Current user cannot enable tracking.
|
171 |
-
$this->allowCurrentUserToEnableTracking( false );
|
172 |
-
|
173 |
-
$this->assertFalse( !! $this->usage_tracking->is_tracking_enabled(), 'Usage tracking initially disabled' );
|
174 |
-
$this->assertFalse( !! get_option( $this->usage_tracking->get_prefix() . '_usage_tracking_opt_in_hide' ), 'Dialog initially shown' );
|
175 |
-
|
176 |
-
try {
|
177 |
-
$this->usage_tracking->handle_tracking_opt_in();
|
178 |
-
} catch ( WP_Die_Exception $e ) {
|
179 |
-
$wp_die_args = $e->get_wp_die_args();
|
180 |
-
$this->assertEquals( 403, $wp_die_args['args']['response'], 'wp_die called has "Forbidden" status' );
|
181 |
-
}
|
182 |
-
|
183 |
-
$this->assertFalse( !! $this->usage_tracking->is_tracking_enabled(), 'Usage tracking disabled' );
|
184 |
-
$this->assertFalse( !! get_option( $this->usage_tracking->get_prefix() . '_usage_tracking_opt_in_hide' ), 'Dialog not hidden' );
|
185 |
-
}
|
186 |
-
|
187 |
-
/* END test ajax request cases */
|
188 |
-
|
189 |
-
/**
|
190 |
-
* Ensure that a request is made to the correct URL with the given
|
191 |
-
* properties and the default properties.
|
192 |
-
*
|
193 |
-
* @covers {Prefix}_Usage_Tracking::send_event
|
194 |
-
*/
|
195 |
-
public function testSendEvent() {
|
196 |
-
$event = 'my_event';
|
197 |
-
$properties = array(
|
198 |
-
'button_clicked' => 'my_button',
|
199 |
-
);
|
200 |
-
$timestamp = '1234';
|
201 |
-
|
202 |
-
// Enable tracking.
|
203 |
-
$this->usage_tracking->set_tracking_enabled( true );
|
204 |
-
|
205 |
-
// Capture the network request, save the request URL and arguments, and simulate a WP_Error.
|
206 |
-
$this->track_http_request['request_params'] = null;
|
207 |
-
$this->track_http_request['request_url'] = null;
|
208 |
-
add_filter( 'pre_http_request', array( $this, 'trackHttpRequest' ), 10, 3 );
|
209 |
-
|
210 |
-
$this->usage_tracking->send_event( 'my_event', $properties, $timestamp );
|
211 |
-
|
212 |
-
$parsed_url = parse_url( $this->track_http_request['request_url'] );
|
213 |
-
|
214 |
-
$this->assertEquals( 'pixel.wp.com', $parsed_url['host'], 'Host' );
|
215 |
-
$this->assertEquals( '/t.gif', $parsed_url['path'], 'Path' );
|
216 |
-
|
217 |
-
$query = array();
|
218 |
-
parse_str( $parsed_url['query'], $query );
|
219 |
-
|
220 |
-
// Older versions (for PHP 5.2) of PHPUnit do not have this method.
|
221 |
-
if ( method_exists( $this, 'assertArraySubset' ) ) {
|
222 |
-
$this->assertArraySubset(
|
223 |
-
array(
|
224 |
-
'button_clicked' => 'my_button',
|
225 |
-
'admin_email' => 'admin@example.org',
|
226 |
-
'_ut' => $this->usage_tracking->get_prefix() . ':site_url',
|
227 |
-
'_ui' => 'http://example.org',
|
228 |
-
'_ul' => '',
|
229 |
-
'_en' => $this->usage_tracking->get_prefix() . '_my_event',
|
230 |
-
'_ts' => '1234000',
|
231 |
-
'_' => '_',
|
232 |
-
), $query, 'Query parameters'
|
233 |
-
);
|
234 |
-
}
|
235 |
-
}
|
236 |
-
|
237 |
-
/**
|
238 |
-
* Ensure that the request is not made if tracking is not enabled, unless
|
239 |
-
* $force is true.
|
240 |
-
*
|
241 |
-
* @covers {Prefix}_Usage_Tracking::send_event
|
242 |
-
*/
|
243 |
-
public function testSendEventWithTrackingDisabled() {
|
244 |
-
$event = 'my_event';
|
245 |
-
$properties = array(
|
246 |
-
'button_clicked' => 'my_button',
|
247 |
-
);
|
248 |
-
$timestamp = '1234';
|
249 |
-
|
250 |
-
// Disable tracking.
|
251 |
-
$this->usage_tracking->set_tracking_enabled( false );
|
252 |
-
|
253 |
-
// Count network requests.
|
254 |
-
$this->event_counts['http_request'] = 0;
|
255 |
-
add_filter( 'pre_http_request', array( $this, 'countHttpRequest' ) );
|
256 |
-
|
257 |
-
$this->usage_tracking->send_event( 'my_event', $properties, $timestamp );
|
258 |
-
$this->assertEquals( 0, $this->event_counts['http_request'], 'No request when disabled' );
|
259 |
-
}
|
260 |
-
|
261 |
-
/**
|
262 |
-
* Ensure that the request is only sent when the setting is enabled.
|
263 |
-
*
|
264 |
-
* @covers {Prefix}_Usage_Tracking::maybe_send_usage_data
|
265 |
-
*/
|
266 |
-
public function testSendUsageData() {
|
267 |
-
// Count the number of network requests.
|
268 |
-
$this->event_counts['http_request'] = 0;
|
269 |
-
add_filter( 'pre_http_request', array( $this, 'countHttpRequest' ) );
|
270 |
-
|
271 |
-
// Setting is not set, ensure the request is not sent.
|
272 |
-
$this->usage_tracking->send_usage_data();
|
273 |
-
$this->assertEquals( 0, $this->event_counts['http_request'], 'Request not sent when Usage Tracking disabled' );
|
274 |
-
|
275 |
-
// Set the setting and ensure request is sent.
|
276 |
-
$this->usage_tracking->set_tracking_enabled( true );
|
277 |
-
|
278 |
-
$this->usage_tracking->send_usage_data();
|
279 |
-
$this->assertEquals( 2, $this->event_counts['http_request'], 'Request sent when Usage Tracking enabled' );
|
280 |
-
}
|
281 |
-
|
282 |
-
/* Tests for tracking opt in dialog */
|
283 |
-
|
284 |
-
/**
|
285 |
-
* When setting is not set, dialog is not hidden, and user has capability,
|
286 |
-
* we should see the dialog and Enable Usage Tracking button.
|
287 |
-
*
|
288 |
-
* @covers {Prefix}_Usage_Tracking::_maybe_display_tracking_opt_in
|
289 |
-
*/
|
290 |
-
public function testDisplayTrackingOptIn() {
|
291 |
-
$this->setupOptInDialog();
|
292 |
-
|
293 |
-
$this->expectOutputRegex( '/Enable Usage Tracking/' );
|
294 |
-
$this->usage_tracking->maybe_display_tracking_opt_in();
|
295 |
-
}
|
296 |
-
|
297 |
-
/**
|
298 |
-
* When setting is already set, dialog should not appear.
|
299 |
-
*
|
300 |
-
* @covers {Prefix}_Usage_Tracking::_maybe_display_tracking_opt_in
|
301 |
-
*/
|
302 |
-
public function testDoNotDisplayTrackingOptInWhenSettingEnabled() {
|
303 |
-
$this->setupOptInDialog();
|
304 |
-
$this->usage_tracking->set_tracking_enabled( true );
|
305 |
-
|
306 |
-
$this->expectOutputString( '' );
|
307 |
-
$this->usage_tracking->maybe_display_tracking_opt_in();
|
308 |
-
}
|
309 |
-
|
310 |
-
/**
|
311 |
-
* When option is set to hide the dialog, it should not appear.
|
312 |
-
*
|
313 |
-
* @covers {Prefix}_Usage_Tracking::_maybe_display_tracking_opt_in
|
314 |
-
*/
|
315 |
-
public function testDoNotDisplayTrackingOptInWhenDialogHidden() {
|
316 |
-
$this->setupOptInDialog();
|
317 |
-
update_option( $this->usage_tracking->get_prefix() . '_usage_tracking_opt_in_hide', true );
|
318 |
-
|
319 |
-
$this->expectOutputString( '' );
|
320 |
-
$this->usage_tracking->maybe_display_tracking_opt_in();
|
321 |
-
}
|
322 |
-
|
323 |
-
/**
|
324 |
-
* When user does not have permission to manage usage tracking, dialog
|
325 |
-
* should not appear.
|
326 |
-
*
|
327 |
-
* @covers {Prefix}_Usage_Tracking::_maybe_display_tracking_opt_in
|
328 |
-
*/
|
329 |
-
public function testDoNotDisplayTrackingOptInWhenUserNotAuthorized() {
|
330 |
-
$this->setupOptInDialog();
|
331 |
-
$this->allowCurrentUserToEnableTracking( false );
|
332 |
-
|
333 |
-
$this->expectOutputString( '' );
|
334 |
-
$this->usage_tracking->maybe_display_tracking_opt_in();
|
335 |
-
}
|
336 |
-
|
337 |
-
/* END tests for tracking opt in dialog */
|
338 |
-
|
339 |
-
/* Tests for system data */
|
340 |
-
|
341 |
-
/**
|
342 |
-
* Tests the basic structure for collected system data.
|
343 |
-
*
|
344 |
-
* @covers {Prefix}_Usage_Tracking::get_system_data
|
345 |
-
* @group track-system-data
|
346 |
-
*/
|
347 |
-
public function testSystemDataStructure() {
|
348 |
-
global $wp_version;
|
349 |
-
|
350 |
-
$system_data = $this->usage_tracking->get_system_data();
|
351 |
-
|
352 |
-
$this->assertInternalType( 'array', $system_data, 'System data must be returned as an array' );
|
353 |
-
|
354 |
-
$this->assertArrayHasKey( 'wp_version', $system_data, '`wp_version` key must exist in system data' );
|
355 |
-
$this->assertEquals( $wp_version, $system_data['wp_version'], '`wp_version` does not match expected value' );
|
356 |
-
|
357 |
-
$this->assertArrayHasKey( 'php_version', $system_data, '`php_version` key must exist in system data' );
|
358 |
-
$this->assertEquals( PHP_VERSION, $system_data['php_version'], '`php_version` does not match expected value' );
|
359 |
-
|
360 |
-
$this->assertArrayHasKey( 'locale', $system_data, '`locale` key must exist in system data' );
|
361 |
-
$this->assertEquals( get_locale(), $system_data['locale'], '`locale` does not match expected value' );
|
362 |
-
|
363 |
-
$this->assertArrayHasKey( 'multisite', $system_data, '`multisite` key must exist in system data' );
|
364 |
-
$this->assertEquals( is_multisite(), $system_data['multisite'], '`multisite` does not match expected value' );
|
365 |
-
|
366 |
-
/**
|
367 |
-
* Current active theme.
|
368 |
-
*
|
369 |
-
* @var WP_Theme $theme
|
370 |
-
*/
|
371 |
-
$theme = wp_get_theme();
|
372 |
-
|
373 |
-
$this->assertArrayHasKey( 'active_theme', $system_data, '`active_theme` key must exist in system data' );
|
374 |
-
$this->assertEquals( $theme['Name'], $system_data['active_theme'], '`active_theme` does not match expected value' );
|
375 |
-
|
376 |
-
$this->assertArrayHasKey( 'active_theme_version', $system_data, '`active_theme_version` key must exist in system data' );
|
377 |
-
$this->assertEquals( $theme['Version'], $system_data['active_theme_version'], '`active_theme_version` does not match expected value' );
|
378 |
-
|
379 |
-
$this->assertArrayHasKey( 'plugin_my_favorite_plugin', $system_data, '`plugin_my_favorite_plugin` key must exist in system data' );
|
380 |
-
$this->assertEquals( '1.0.0', $system_data['plugin_my_favorite_plugin'], '`plugin_my_favorite_plugin` does not match expected value' );
|
381 |
-
|
382 |
-
$this->assertArrayHasKey( 'plugin_hello', $system_data, '`plugin_hello` key must exist in system data' );
|
383 |
-
$this->assertEquals( '1.0.0', $system_data['plugin_my_favorite_plugin'], '`plugin_hello` does not match expected value' );
|
384 |
-
|
385 |
-
$this->assertArrayHasKey( 'plugin_test', $system_data, '`plugin_test` key must exist in system data' );
|
386 |
-
$this->assertEquals( '1.0.0', $system_data['plugin_test'], '`plugin_test` does not match expected value' );
|
387 |
-
|
388 |
-
$this->assertArrayNotHasKey( 'plugin_jetpack', $system_data, '`plugin_jetpack` key must NOT exist in system data' );
|
389 |
-
$this->assertArrayNotHasKey( 'plugin_test_dev', $system_data, '`plugin_test_dev` key must NOT exist in system data' );
|
390 |
-
|
391 |
-
$plugin_prefix_count = 0;
|
392 |
-
foreach ( $system_data as $key => $value ) {
|
393 |
-
if ( 1 === preg_match( '/^plugin_/', $key ) ) {
|
394 |
-
$plugin_prefix_count++;
|
395 |
-
}
|
396 |
-
}
|
397 |
-
|
398 |
-
$this->assertEquals( 3, $plugin_prefix_count );
|
399 |
-
}
|
400 |
-
|
401 |
-
/* END tests for system data */
|
402 |
-
|
403 |
-
/****** Helper methods ******/
|
404 |
-
|
405 |
-
/**
|
406 |
-
* Helper method for ajax request.
|
407 |
-
*/
|
408 |
-
private function setupAjaxRequest() {
|
409 |
-
// Simulate an ajax request.
|
410 |
-
add_filter( 'wp_doing_ajax', '__return_true' );
|
411 |
-
|
412 |
-
// Set up nonce.
|
413 |
-
$_REQUEST['nonce'] = wp_create_nonce( 'tracking-opt-in' );
|
414 |
-
|
415 |
-
// Ensure current user can enable tracking.
|
416 |
-
$this->allowCurrentUserToEnableTracking();
|
417 |
-
|
418 |
-
// When wp_die is called, save the args and throw an exception to stop.
|
419 |
-
// execution.
|
420 |
-
add_filter( 'wp_die_ajax_handler', array( $this, 'ajaxDieHandler' ) );
|
421 |
-
}
|
422 |
-
|
423 |
-
/**
|
424 |
-
* Helper method to set up tracking opt-in dialog.
|
425 |
-
*/
|
426 |
-
private function setupOptInDialog() {
|
427 |
-
// Ensure current user can enable tracking.
|
428 |
-
$this->allowCurrentUserToEnableTracking();
|
429 |
-
|
430 |
-
// Ensure setting is not set.
|
431 |
-
$this->usage_tracking->set_tracking_enabled( false );
|
432 |
-
}
|
433 |
-
|
434 |
-
/**
|
435 |
-
* Update the capaility for the current user to be able to enable or
|
436 |
-
* disable tracking.
|
437 |
-
*
|
438 |
-
* @param bool $allow true if the current user should be allowed to update.
|
439 |
-
* the tracking setting, false otherwise. Default: true
|
440 |
-
**/
|
441 |
-
private function allowCurrentUserToEnableTracking( $allow = true ) {
|
442 |
-
$user = wp_get_current_user();
|
443 |
-
|
444 |
-
if ( $allow ) {
|
445 |
-
$user->add_cap( 'manage_usage_tracking' );
|
446 |
-
} else {
|
447 |
-
$user->remove_cap( 'manage_usage_tracking' );
|
448 |
-
}
|
449 |
-
}
|
450 |
-
|
451 |
-
/**
|
452 |
-
* Callback helpers.
|
453 |
-
*/
|
454 |
-
|
455 |
-
/**
|
456 |
-
* Basic callback for usage data.
|
457 |
-
*
|
458 |
-
* @return array
|
459 |
-
*/
|
460 |
-
public function basicDataCallback() {
|
461 |
-
return array( 'testing' => true );
|
462 |
-
}
|
463 |
-
|
464 |
-
/**
|
465 |
-
* Sets the die handler for ajax request.
|
466 |
-
*
|
467 |
-
* @return array
|
468 |
-
*/
|
469 |
-
public function ajaxDieHandler() {
|
470 |
-
return array( $this, 'ajaxDieHandlerCallback' );
|
471 |
-
}
|
472 |
-
|
473 |
-
/**
|
474 |
-
* Error handler for ajax requests.
|
475 |
-
*
|
476 |
-
* @param string $message
|
477 |
-
* @param string $title
|
478 |
-
* @param array $args
|
479 |
-
*
|
480 |
-
* @throws WP_Die_Exception
|
481 |
-
*/
|
482 |
-
public function ajaxDieHandlerCallback( $message, $title, $args ) {
|
483 |
-
$e = new WP_Die_Exception( 'wp_die called' );
|
484 |
-
$e->set_wp_die_args( $message, $title, $args );
|
485 |
-
throw $e;
|
486 |
-
}
|
487 |
-
|
488 |
-
/**
|
489 |
-
* Count the number of times an event is scheduled.
|
490 |
-
*
|
491 |
-
* @param object $event
|
492 |
-
*
|
493 |
-
* @return object
|
494 |
-
*/
|
495 |
-
public function countScheduleEvent( $event ) {
|
496 |
-
$prefix = $this->usage_tracking->get_prefix();
|
497 |
-
if ( $event->hook === $prefix . '_usage_tracking_send_usage_data' ) {
|
498 |
-
$this->event_counts['schedule_event']++;
|
499 |
-
}
|
500 |
-
return $event;
|
501 |
-
}
|
502 |
-
|
503 |
-
/**
|
504 |
-
* Count the number of HTTP requests.
|
505 |
-
*
|
506 |
-
* @return WP_Error
|
507 |
-
*/
|
508 |
-
public function countHttpRequest() {
|
509 |
-
$this->event_counts['http_request']++;
|
510 |
-
return new WP_Error();
|
511 |
-
}
|
512 |
-
|
513 |
-
/**
|
514 |
-
* Track HTTP request params and URL.
|
515 |
-
*
|
516 |
-
* @param string $preempt
|
517 |
-
* @param array $r
|
518 |
-
* @param string $url
|
519 |
-
*
|
520 |
-
* @return WP_Error
|
521 |
-
*/
|
522 |
-
public function trackHttpRequest( $preempt, $r, $url ) {
|
523 |
-
$this->track_http_request['request_params'] = $r;
|
524 |
-
$this->track_http_request['request_url'] = $url;
|
525 |
-
return new WP_Error();
|
526 |
-
}
|
527 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/class-wp-job-manager-rest-bootstrap.php
DELETED
@@ -1,196 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Bootstrap
|
4 |
-
*
|
5 |
-
* Loads classes and creates an Environment subclass instance from
|
6 |
-
* the specified lib location, with the specified prefix
|
7 |
-
*
|
8 |
-
* @package Mixtape
|
9 |
-
*/
|
10 |
-
|
11 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
-
exit;
|
13 |
-
}
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Class WP_Job_Manager_REST_Bootstrap
|
17 |
-
*
|
18 |
-
* This is the entry point for.
|
19 |
-
*/
|
20 |
-
class WP_Job_Manager_REST_Bootstrap {
|
21 |
-
const MINIMUM_PHP_VERSION = '5.2.0';
|
22 |
-
|
23 |
-
/**
|
24 |
-
* The Environment we will use
|
25 |
-
*
|
26 |
-
* @var null|object the Environment implementation.
|
27 |
-
*/
|
28 |
-
private $environment = null;
|
29 |
-
|
30 |
-
/**
|
31 |
-
* The class loader we will use
|
32 |
-
*
|
33 |
-
* @var null|WP_Job_Manager_REST_Classloader
|
34 |
-
*/
|
35 |
-
private $class_loader = null;
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Construct a new Bootstrap
|
39 |
-
*
|
40 |
-
* @param null|WP_Job_Manager_REST_Interfaces_Classloader $class_loader The class loader to use.
|
41 |
-
*/
|
42 |
-
private function __construct( $class_loader = null ) {
|
43 |
-
$this->class_loader = $class_loader;
|
44 |
-
}
|
45 |
-
|
46 |
-
/**
|
47 |
-
* Check compatibility of PHP Version.
|
48 |
-
*
|
49 |
-
* @return bool
|
50 |
-
*/
|
51 |
-
public static function is_compatible() {
|
52 |
-
return version_compare( phpversion(), self::MINIMUM_PHP_VERSION, '>=' );
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Get Base Dir
|
57 |
-
*
|
58 |
-
* @return string
|
59 |
-
*/
|
60 |
-
public static function get_base_dir() {
|
61 |
-
return untrailingslashit( dirname( __FILE__ ) );
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Create a Bootstrap, unless we are using a really early php version (< 5.3.0)
|
66 |
-
*
|
67 |
-
* @param WP_Job_Manager_REST_Interfaces_Classloader|null $class_loader The class loader to use.
|
68 |
-
* @return WP_Job_Manager_REST_Bootstrap|null
|
69 |
-
*/
|
70 |
-
public static function create( $class_loader = null ) {
|
71 |
-
if ( empty( $class_loader ) ) {
|
72 |
-
include_once( 'interfaces/class-wp-job-manager-rest-interfaces-classloader.php' );
|
73 |
-
include_once( 'class-wp-job-manager-rest-classloader.php' );
|
74 |
-
$prefix = str_replace( '_Bootstrap', '', __CLASS__ );
|
75 |
-
$base_dir = self::get_base_dir();
|
76 |
-
$class_loader = new WP_Job_Manager_REST_Classloader( $prefix, $base_dir );
|
77 |
-
}
|
78 |
-
return new self( $class_loader );
|
79 |
-
}
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Run the app
|
83 |
-
*
|
84 |
-
* @return bool
|
85 |
-
*/
|
86 |
-
public function run() {
|
87 |
-
if ( ! self::is_compatible() ) {
|
88 |
-
return false;
|
89 |
-
}
|
90 |
-
$this->load()
|
91 |
-
->environment()->start();
|
92 |
-
return true;
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* Optional: Instead of calling load() you can
|
97 |
-
* register as an auto-loader
|
98 |
-
*
|
99 |
-
* @return WP_Job_Manager_REST_Bootstrap $this
|
100 |
-
*/
|
101 |
-
function register_autoload() {
|
102 |
-
if ( function_exists( 'spl_autoload_register' ) ) {
|
103 |
-
spl_autoload_register( array( $this->class_loader(), 'load_class' ), true );
|
104 |
-
}
|
105 |
-
return $this;
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Loads all classes
|
110 |
-
*
|
111 |
-
* @return WP_Job_Manager_REST_Bootstrap $this
|
112 |
-
* @throws Exception In case a class/file is not found.
|
113 |
-
*/
|
114 |
-
function load() {
|
115 |
-
$this->class_loader()
|
116 |
-
->load_class( 'Interfaces_Data_Store' )
|
117 |
-
->load_class( 'Interfaces_Registrable' )
|
118 |
-
->load_class( 'Interfaces_Type' )
|
119 |
-
->load_class( 'Interfaces_Model' )
|
120 |
-
->load_class( 'Interfaces_Builder' )
|
121 |
-
->load_class( 'Interfaces_Model_Collection' )
|
122 |
-
->load_class( 'Interfaces_Controller' )
|
123 |
-
->load_class( 'Interfaces_Controller_Bundle' )
|
124 |
-
->load_class( 'Interfaces_Permissions_Provider' )
|
125 |
-
->load_class( 'Exception' )
|
126 |
-
->load_class( 'Expect' )
|
127 |
-
->load_class( 'Events' )
|
128 |
-
->load_class( 'Environment' )
|
129 |
-
->load_class( 'Type' )
|
130 |
-
->load_class( 'Type_String' )
|
131 |
-
->load_class( 'Type_Integer' )
|
132 |
-
->load_class( 'Type_Number' )
|
133 |
-
->load_class( 'Type_Boolean' )
|
134 |
-
->load_class( 'Type_Array' )
|
135 |
-
->load_class( 'Type_TypedArray' )
|
136 |
-
->load_class( 'Type_Nullable' )
|
137 |
-
->load_class( 'Type_Model' )
|
138 |
-
->load_class( 'Type_Registry' )
|
139 |
-
->load_class( 'Data_Store_Nil' )
|
140 |
-
->load_class( 'Data_Store_Abstract' )
|
141 |
-
->load_class( 'Data_Store_CustomPostType' )
|
142 |
-
->load_class( 'Data_Store_Option' )
|
143 |
-
->load_class( 'Permissions_Any' )
|
144 |
-
->load_class( 'Field_Declaration' )
|
145 |
-
->load_class( 'Field_Declaration_Builder' )
|
146 |
-
->load_class( 'Model' )
|
147 |
-
->load_class( 'Model_Settings' )
|
148 |
-
->load_class( 'Model_Collection' )
|
149 |
-
->load_class( 'Controller' )
|
150 |
-
->load_class( 'Controller_Action' )
|
151 |
-
->load_class( 'Controller_Model' )
|
152 |
-
->load_class( 'Controller_Settings' )
|
153 |
-
->load_class( 'Controller_Route' )
|
154 |
-
->load_class( 'Controller_CRUD' )
|
155 |
-
->load_class( 'Controller_Bundle' )
|
156 |
-
->load_class( 'Controller_Extension' )
|
157 |
-
->load_class( 'Controller_Bundle_Builder' );
|
158 |
-
|
159 |
-
return $this;
|
160 |
-
}
|
161 |
-
|
162 |
-
/**
|
163 |
-
* Load Unit Testing Base Classes
|
164 |
-
*
|
165 |
-
* @return WP_Job_Manager_REST_Bootstrap $this
|
166 |
-
*/
|
167 |
-
function load_testing_classes() {
|
168 |
-
$this->class_loader()
|
169 |
-
->load_class( 'Testing_TestCase' )
|
170 |
-
->load_class( 'Testing_Model_TestCase' )
|
171 |
-
->load_class( 'Testing_Controller_TestCase' );
|
172 |
-
return $this;
|
173 |
-
}
|
174 |
-
|
175 |
-
/**
|
176 |
-
* Get the class loader
|
177 |
-
*
|
178 |
-
* @return WP_Job_Manager_REST_Classloader
|
179 |
-
*/
|
180 |
-
function class_loader() {
|
181 |
-
return $this->class_loader;
|
182 |
-
}
|
183 |
-
|
184 |
-
/**
|
185 |
-
* Lazy-load the environment
|
186 |
-
*
|
187 |
-
* @return WP_Job_Manager_REST_Environment
|
188 |
-
*/
|
189 |
-
public function environment() {
|
190 |
-
if ( null === $this->environment ) {
|
191 |
-
$this->load();
|
192 |
-
$this->environment = new WP_Job_Manager_REST_Environment( $this );
|
193 |
-
}
|
194 |
-
return $this->environment;
|
195 |
-
}
|
196 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/class-wp-job-manager-rest-classloader.php
DELETED
@@ -1,145 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Default Mixtape_Interfaces_Class_Loader Implementation
|
4 |
-
*
|
5 |
-
* Loads classes in nested folders.
|
6 |
-
*
|
7 |
-
* @package Mixtape
|
8 |
-
*/
|
9 |
-
|
10 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
-
exit;
|
12 |
-
}
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Class WP_Job_Manager_REST_Class_Loader
|
16 |
-
*/
|
17 |
-
class WP_Job_Manager_REST_Classloader implements WP_Job_Manager_REST_Interfaces_Classloader {
|
18 |
-
/**
|
19 |
-
* Keep a record of classes loaded
|
20 |
-
*
|
21 |
-
* @var array The loaded class map.
|
22 |
-
*/
|
23 |
-
private $loaded_classes;
|
24 |
-
/**
|
25 |
-
* The prefix to use (e.g. Mixtape)
|
26 |
-
*
|
27 |
-
* @var string
|
28 |
-
*/
|
29 |
-
private $prefix;
|
30 |
-
/**
|
31 |
-
* The directory the loader looks for classes.
|
32 |
-
*
|
33 |
-
* @var string
|
34 |
-
*/
|
35 |
-
private $base_dir;
|
36 |
-
|
37 |
-
/**
|
38 |
-
* WP_Job_Manager_REST_Class_Loader constructor.
|
39 |
-
*
|
40 |
-
* @param string $prefix The prefix to use (e.g. Mixtape).
|
41 |
-
* @param string $base_dir The directory the loader looks for classes.
|
42 |
-
*
|
43 |
-
* @throws Exception Throws if an invalid directory is provided.
|
44 |
-
*/
|
45 |
-
public function __construct( $prefix, $base_dir ) {
|
46 |
-
$this->loaded_classes = array();
|
47 |
-
$this->prefix = $prefix;
|
48 |
-
$this->base_dir = $base_dir;
|
49 |
-
if ( ! is_dir( $this->base_dir ) ) {
|
50 |
-
throw new Exception( 'base_dir does not exist: ' . $this->base_dir );
|
51 |
-
}
|
52 |
-
}
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Loads a class
|
56 |
-
*
|
57 |
-
* @param string $class_name The class to load.
|
58 |
-
*
|
59 |
-
* @return WP_Job_Manager_REST_Interfaces_Classloader
|
60 |
-
* @throws Exception Throws in case include_class_file fails.
|
61 |
-
*/
|
62 |
-
public function load_class( $class_name ) {
|
63 |
-
$path = $this->get_path_to_class_file( $class_name );
|
64 |
-
return $this->include_class_file( $path );
|
65 |
-
}
|
66 |
-
|
67 |
-
/**
|
68 |
-
* Get path_to_class_file
|
69 |
-
*
|
70 |
-
* @param string $class_name The class.
|
71 |
-
*
|
72 |
-
* @return string The full path to the file.
|
73 |
-
*/
|
74 |
-
public function get_path_to_class_file( $class_name ) {
|
75 |
-
return path_join( $this->base_dir, $this->class_name_to_relative_path( $class_name ) );
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Class_name_to_relative_path
|
80 |
-
*
|
81 |
-
* @param string $class_name The class name.
|
82 |
-
* @param null|string $prefix The prefix.
|
83 |
-
*
|
84 |
-
* @return string
|
85 |
-
*/
|
86 |
-
public function class_name_to_relative_path( $class_name, $prefix = null ) {
|
87 |
-
$lowercase = strtolower( $this->prefixed_class_name( $class_name, $prefix ) );
|
88 |
-
$file_name = 'class-' . str_replace( '_', '-', $lowercase ) . '.php';
|
89 |
-
$parts = explode( '_', strtolower( $this->strip_prefix( $class_name, $prefix ) ) );
|
90 |
-
array_pop( $parts );
|
91 |
-
$parts[] = $file_name;
|
92 |
-
return implode( DIRECTORY_SEPARATOR, $parts );
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* Prefixed_class_name
|
97 |
-
*
|
98 |
-
* @param string $class_name The class name.
|
99 |
-
* @param null|string $prefix The prefix.
|
100 |
-
*
|
101 |
-
* @return string
|
102 |
-
*/
|
103 |
-
public function prefixed_class_name( $class_name, $prefix = null ) {
|
104 |
-
if ( empty( $prefix ) ) {
|
105 |
-
$prefix = $this->prefix;
|
106 |
-
}
|
107 |
-
return $prefix . '_' . $this->strip_prefix( $class_name, $prefix );
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* Strip_prefix
|
112 |
-
*
|
113 |
-
* @param string $class_name The class name.
|
114 |
-
* @param null|string $prefix The prefix.
|
115 |
-
*
|
116 |
-
* @return string
|
117 |
-
*/
|
118 |
-
private function strip_prefix( $class_name, $prefix = null ) {
|
119 |
-
if ( empty( $prefix ) ) {
|
120 |
-
$prefix = $this->prefix;
|
121 |
-
}
|
122 |
-
return str_replace( $prefix, '', $class_name );
|
123 |
-
}
|
124 |
-
|
125 |
-
/**
|
126 |
-
* Include_class_file
|
127 |
-
*
|
128 |
-
* @param string $path_to_the_class The file path.
|
129 |
-
*
|
130 |
-
* @return string
|
131 |
-
* @throws Exception Throws when the file does not exist.
|
132 |
-
*/
|
133 |
-
private function include_class_file( $path_to_the_class ) {
|
134 |
-
if ( isset( $this->loaded_classes[ $path_to_the_class ] ) ) {
|
135 |
-
return $this;
|
136 |
-
}
|
137 |
-
if ( ! file_exists( $path_to_the_class ) ) {
|
138 |
-
throw new Exception( $path_to_the_class . ' not found' );
|
139 |
-
}
|
140 |
-
$included = include_once( $path_to_the_class );
|
141 |
-
$this->loaded_classes[ $path_to_the_class ] = $included;
|
142 |
-
|
143 |
-
return $this;
|
144 |
-
}
|
145 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/class-wp-job-manager-rest-controller.php
DELETED
@@ -1,285 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Controller
|
4 |
-
*
|
5 |
-
* @package Mixtape/Controller
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_Controller
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_REST_Controller extends WP_REST_Controller implements WP_Job_Manager_REST_Interfaces_Controller {
|
16 |
-
const HTTP_CREATED = 201;
|
17 |
-
const HTTP_OK = 200;
|
18 |
-
const HTTP_BAD_REQUEST = 400;
|
19 |
-
const HTTP_NOT_FOUND = 404;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* The bundle this belongs to.
|
23 |
-
*
|
24 |
-
* @var WP_Job_Manager_REST_Controller_Bundle
|
25 |
-
*/
|
26 |
-
protected $controller_bundle;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* The endpoint base (e.g. /users). Override in subclasses.
|
30 |
-
*
|
31 |
-
* @var string
|
32 |
-
*/
|
33 |
-
protected $base = null;
|
34 |
-
/**
|
35 |
-
* Our Handlers
|
36 |
-
*
|
37 |
-
* @var array
|
38 |
-
*/
|
39 |
-
private $routes = array();
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Optional, an enviromnent.
|
43 |
-
*
|
44 |
-
* @var null|WP_Job_Manager_REST_Environment
|
45 |
-
*/
|
46 |
-
protected $environment = null;
|
47 |
-
|
48 |
-
/**
|
49 |
-
* WP_Job_Manager_REST_Rest_Api_Controller constructor.
|
50 |
-
*/
|
51 |
-
public function __construct() {
|
52 |
-
}
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Set Controller Bundle
|
56 |
-
*
|
57 |
-
* @param WP_Job_Manager_REST_Controller_Bundle $controller_bundle Controller Bundle this belongs to.
|
58 |
-
*
|
59 |
-
* @return WP_Job_Manager_REST_Controller $this
|
60 |
-
*/
|
61 |
-
public function set_controller_bundle( $controller_bundle ) {
|
62 |
-
$this->controller_bundle = $controller_bundle;
|
63 |
-
return $this;
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Set the Environment for this Controller.
|
68 |
-
*
|
69 |
-
* @param WP_Job_Manager_REST_Environment|null $environment The Environment.
|
70 |
-
* @return WP_Job_Manager_REST_Controller
|
71 |
-
*/
|
72 |
-
public function set_environment( $environment ) {
|
73 |
-
$this->environment = $environment;
|
74 |
-
return $this;
|
75 |
-
}
|
76 |
-
|
77 |
-
/**
|
78 |
-
* Register This Controller
|
79 |
-
*
|
80 |
-
* @param WP_Job_Manager_REST_Controller_Bundle $bundle The bundle to register with.
|
81 |
-
* @param WP_Job_Manager_REST_Environment $environment The Environment to use.
|
82 |
-
* @throws WP_Job_Manager_REST_Exception Throws.
|
83 |
-
*
|
84 |
-
* @return bool|WP_Error true if valid otherwise error.
|
85 |
-
*/
|
86 |
-
public function register( $bundle, $environment ) {
|
87 |
-
$this->set_controller_bundle( $bundle );
|
88 |
-
$this->set_environment( $environment );
|
89 |
-
$this->setup();
|
90 |
-
WP_Job_Manager_REST_Expect::that( ! empty( $this->base ), 'Need to put a string with a backslash in $base' );
|
91 |
-
$prefix = $this->controller_bundle->get_prefix();
|
92 |
-
foreach ( $this->routes as $pattern => $route ) {
|
93 |
-
/**
|
94 |
-
* The route we want to register.
|
95 |
-
*
|
96 |
-
* @var WP_Job_Manager_REST_Controller_Route $route
|
97 |
-
*/
|
98 |
-
$params = $route->as_array();
|
99 |
-
$result = register_rest_route( $prefix, $this->base . $params['pattern'], $params['actions'] );
|
100 |
-
if ( false === $result ) {
|
101 |
-
// For now we throw on error, maybe we just need to warn though.
|
102 |
-
throw new WP_Job_Manager_REST_Exception( 'Registration failed' );
|
103 |
-
}
|
104 |
-
}
|
105 |
-
|
106 |
-
return true;
|
107 |
-
}
|
108 |
-
|
109 |
-
/**
|
110 |
-
* Create Action
|
111 |
-
*
|
112 |
-
* @param string $action_name Action Name.
|
113 |
-
* @param null|string|array|callable $callback Callback.
|
114 |
-
* @return WP_Job_Manager_REST_Controller_Action
|
115 |
-
*/
|
116 |
-
public function action( $action_name, $callback = null ) {
|
117 |
-
$route_action = new WP_Job_Manager_REST_Controller_Action( $this, $action_name );
|
118 |
-
if ( null !== $callback ) {
|
119 |
-
$route_action->callback( $callback );
|
120 |
-
}
|
121 |
-
|
122 |
-
return $route_action;
|
123 |
-
}
|
124 |
-
|
125 |
-
/**
|
126 |
-
* Do any additional Configuration. Runs inside register before any register_rest_route
|
127 |
-
*
|
128 |
-
* This is a good place for overriding classes to define routes and handlers
|
129 |
-
*/
|
130 |
-
protected function setup() {
|
131 |
-
}
|
132 |
-
|
133 |
-
/**
|
134 |
-
* Succeed
|
135 |
-
*
|
136 |
-
* @param array $data The dto.
|
137 |
-
*
|
138 |
-
* @return WP_REST_Response
|
139 |
-
*/
|
140 |
-
public function ok( $data ) {
|
141 |
-
return $this->respond( $data, self::HTTP_OK );
|
142 |
-
}
|
143 |
-
|
144 |
-
/**
|
145 |
-
* Created
|
146 |
-
*
|
147 |
-
* @param array $data The dto.
|
148 |
-
*
|
149 |
-
* @return WP_REST_Response
|
150 |
-
*/
|
151 |
-
public function created( $data ) {
|
152 |
-
return $this->respond( $data, self::HTTP_CREATED );
|
153 |
-
}
|
154 |
-
|
155 |
-
/**
|
156 |
-
* Bad request
|
157 |
-
*
|
158 |
-
* @param array|WP_Error $data The dto.
|
159 |
-
*
|
160 |
-
* @return WP_REST_Response
|
161 |
-
*/
|
162 |
-
public function bad_request( $data ) {
|
163 |
-
return $this->respond( $data, self::HTTP_BAD_REQUEST );
|
164 |
-
}
|
165 |
-
|
166 |
-
/**
|
167 |
-
* Not Found (404)
|
168 |
-
*
|
169 |
-
* @param string $message The message.
|
170 |
-
*
|
171 |
-
* @return WP_REST_Response
|
172 |
-
*/
|
173 |
-
public function not_found( $message ) {
|
174 |
-
return $this->respond( array(
|
175 |
-
'message' => $message,
|
176 |
-
), self::HTTP_NOT_FOUND );
|
177 |
-
}
|
178 |
-
|
179 |
-
/**
|
180 |
-
* Respond
|
181 |
-
*
|
182 |
-
* @param array|WP_REST_Response|WP_Error|mixed $data The thing.
|
183 |
-
* @param int $status The Status.
|
184 |
-
*
|
185 |
-
* @return mixed|WP_REST_Response
|
186 |
-
*/
|
187 |
-
public function respond( $data, $status ) {
|
188 |
-
if ( is_a( $data, 'WP_REST_Response' ) ) {
|
189 |
-
return $data;
|
190 |
-
}
|
191 |
-
|
192 |
-
return new WP_REST_Response( $data, $status );
|
193 |
-
}
|
194 |
-
|
195 |
-
/**
|
196 |
-
* Permissions for get_items
|
197 |
-
*
|
198 |
-
* @param WP_REST_Request $request Request.
|
199 |
-
* @return bool
|
200 |
-
*/
|
201 |
-
public function index_permissions_check( $request ) {
|
202 |
-
return $this->permissions_check( $request, 'index' );
|
203 |
-
}
|
204 |
-
|
205 |
-
/**
|
206 |
-
* Permissions for get_item
|
207 |
-
*
|
208 |
-
* @param WP_REST_Request $request The request.
|
209 |
-
* @return bool
|
210 |
-
*/
|
211 |
-
public function show_permissions_check( $request ) {
|
212 |
-
return $this->permissions_check( $request, 'show' );
|
213 |
-
}
|
214 |
-
|
215 |
-
/**
|
216 |
-
* Permissions for create_item
|
217 |
-
*
|
218 |
-
* @param WP_REST_Request $request Request.
|
219 |
-
* @return bool
|
220 |
-
*/
|
221 |
-
public function create_permissions_check( $request ) {
|
222 |
-
return $this->permissions_check( $request, 'create' );
|
223 |
-
}
|
224 |
-
|
225 |
-
/**
|
226 |
-
* Permissions for update_item
|
227 |
-
*
|
228 |
-
* @param WP_REST_Request $request Request.
|
229 |
-
* @return bool
|
230 |
-
*/
|
231 |
-
public function update_permissions_check( $request ) {
|
232 |
-
return $this->permissions_check( $request, 'update' );
|
233 |
-
}
|
234 |
-
|
235 |
-
/**
|
236 |
-
* Permissions for delete
|
237 |
-
*
|
238 |
-
* @param WP_REST_Request $request Request.
|
239 |
-
* @return bool
|
240 |
-
*/
|
241 |
-
public function delete_permissions_check( $request ) {
|
242 |
-
return $this->permissions_check( $request, 'delete' );
|
243 |
-
}
|
244 |
-
|
245 |
-
/**
|
246 |
-
* Generic Permissions Check.
|
247 |
-
*
|
248 |
-
* @param WP_REST_Request $request Request.
|
249 |
-
* @param string $action One of (index, show, create, update, delete, any).
|
250 |
-
* @return bool
|
251 |
-
*/
|
252 |
-
function permissions_check( $request, $action = 'any' ) {
|
253 |
-
return true;
|
254 |
-
}
|
255 |
-
|
256 |
-
/**
|
257 |
-
* Add a route
|
258 |
-
*
|
259 |
-
* @param string $pattern The route pattern (e.g. '/').
|
260 |
-
* @return WP_Job_Manager_REST_Controller_Route
|
261 |
-
*/
|
262 |
-
function add_route( $pattern = '' ) {
|
263 |
-
$route = new WP_Job_Manager_REST_Controller_Route( $this, $pattern );
|
264 |
-
$this->routes[ $pattern ] = $route;
|
265 |
-
return $this->routes[ $pattern ];
|
266 |
-
}
|
267 |
-
|
268 |
-
/**
|
269 |
-
* Get Environment
|
270 |
-
*
|
271 |
-
* @return WP_Job_Manager_REST_Environment
|
272 |
-
*/
|
273 |
-
protected function environment() {
|
274 |
-
return $this->environment;
|
275 |
-
}
|
276 |
-
|
277 |
-
/**
|
278 |
-
* Get base url
|
279 |
-
*
|
280 |
-
* @return string
|
281 |
-
*/
|
282 |
-
function get_base() {
|
283 |
-
return rest_url( $this->controller_bundle->get_prefix() . $this->base );
|
284 |
-
}
|
285 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/class-wp-job-manager-rest-environment.php
DELETED
@@ -1,426 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Environment
|
4 |
-
*
|
5 |
-
* Contains variables, rest api, type and model definitions
|
6 |
-
*
|
7 |
-
* @package Mixtape
|
8 |
-
*/
|
9 |
-
|
10 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
-
exit;
|
12 |
-
}
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Class WP_Job_Manager_REST_Environment
|
16 |
-
*
|
17 |
-
* Our global Environment
|
18 |
-
*
|
19 |
-
* @package Mixtape
|
20 |
-
*/
|
21 |
-
class WP_Job_Manager_REST_Environment {
|
22 |
-
const REGISTRABLE = 'IRegistrable';
|
23 |
-
const BUNDLES = 'Bundles';
|
24 |
-
const MODELS = 'Models';
|
25 |
-
|
26 |
-
/**
|
27 |
-
* This environment's registered REST bundles
|
28 |
-
*
|
29 |
-
* (used for versioned APIs, or logical grouping of related api parts)
|
30 |
-
*
|
31 |
-
* @var array
|
32 |
-
*/
|
33 |
-
protected $rest_apis;
|
34 |
-
|
35 |
-
/**
|
36 |
-
* This environment's model definitions
|
37 |
-
*
|
38 |
-
* @var array
|
39 |
-
*/
|
40 |
-
protected $model_definitions;
|
41 |
-
|
42 |
-
/**
|
43 |
-
* The Environment Variables
|
44 |
-
*
|
45 |
-
* A key-value array of things.
|
46 |
-
*
|
47 |
-
* @var array
|
48 |
-
*/
|
49 |
-
protected $variables;
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Did this Environment start?
|
53 |
-
*
|
54 |
-
* @var bool
|
55 |
-
*/
|
56 |
-
private $has_started;
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Our Bootstrap
|
60 |
-
*
|
61 |
-
* @var WP_Job_Manager_REST_Bootstrap
|
62 |
-
*/
|
63 |
-
private $bootstrap;
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Our Type Registry
|
67 |
-
*
|
68 |
-
* @var WP_Job_Manager_REST_Type_Registry
|
69 |
-
*/
|
70 |
-
private $type_registry;
|
71 |
-
|
72 |
-
/**
|
73 |
-
* Events
|
74 |
-
*
|
75 |
-
* @var WP_Job_Manager_REST_Events
|
76 |
-
*/
|
77 |
-
private $event_dispatcher;
|
78 |
-
|
79 |
-
/**
|
80 |
-
* Mixtape_Environment constructor.
|
81 |
-
*
|
82 |
-
* @param WP_Job_Manager_REST_Bootstrap $bootstrap The bootstrap.
|
83 |
-
*/
|
84 |
-
public function __construct( $bootstrap ) {
|
85 |
-
$this->event_dispatcher = new WP_Job_Manager_REST_Events();
|
86 |
-
$this->bootstrap = $bootstrap;
|
87 |
-
$this->has_started = false;
|
88 |
-
$this->rest_apis = array();
|
89 |
-
$this->variables = array();
|
90 |
-
$this->model_definitions = array();
|
91 |
-
$this->type_registry = new WP_Job_Manager_REST_Type_Registry();
|
92 |
-
$this->type_registry->initialize( $this );
|
93 |
-
// initialize our array vars.
|
94 |
-
$this->array_var( self::MODELS )
|
95 |
-
->array_var( self::REGISTRABLE )
|
96 |
-
->array_var( self::BUNDLES );
|
97 |
-
}
|
98 |
-
|
99 |
-
/**
|
100 |
-
* Get Event Dispacher
|
101 |
-
*
|
102 |
-
* @return WP_Job_Manager_REST_Events
|
103 |
-
*/
|
104 |
-
public function get_event_dispatcher() {
|
105 |
-
return $this->event_dispatcher;
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Push a Builder to the Environment.
|
110 |
-
*
|
111 |
-
* All builders are evaluated lazily when needed
|
112 |
-
*
|
113 |
-
* @param string $where The queue to push the builder to.
|
114 |
-
* @param WP_Job_Manager_REST_Interfaces_Builder $builder The builder to push.
|
115 |
-
*
|
116 |
-
* @return WP_Job_Manager_REST_Environment $this
|
117 |
-
* @throws WP_Job_Manager_REST_Exception In case the $builder is not a Mixtape_Interfaces_Builder.
|
118 |
-
*/
|
119 |
-
public function push_builder( $where, $builder ) {
|
120 |
-
WP_Job_Manager_REST_Expect::that( is_string( $where ), '$where should be a string' );
|
121 |
-
WP_Job_Manager_REST_Expect::is_a( $builder, 'WP_Job_Manager_REST_Interfaces_Builder' );
|
122 |
-
return $this->array_var( $where, $builder );
|
123 |
-
}
|
124 |
-
|
125 |
-
/**
|
126 |
-
* Retrieve a previously defined WP_Job_Manager_REST_Model
|
127 |
-
*
|
128 |
-
* @param string $class the class name.
|
129 |
-
* @return WP_Job_Manager_REST_Model the definition.
|
130 |
-
* @throws WP_Job_Manager_REST_Exception Throws in case the model is not registered.
|
131 |
-
*/
|
132 |
-
public function model( $class ) {
|
133 |
-
if ( ! class_exists( $class ) ) {
|
134 |
-
throw new WP_Job_Manager_REST_Exception( $class . ' does not exist' );
|
135 |
-
}
|
136 |
-
WP_Job_Manager_REST_Expect::that( isset( $this->model_definitions[ $class ] ), $class . ' definition does not exist' );
|
137 |
-
return $this->model_definitions[ $class ];
|
138 |
-
}
|
139 |
-
|
140 |
-
/**
|
141 |
-
* Time to build pending models and bundles
|
142 |
-
*
|
143 |
-
* @param string $type One of (models, bundles).
|
144 |
-
* @return WP_Job_Manager_REST_Environment
|
145 |
-
*/
|
146 |
-
private function load_pending_builders( $type ) {
|
147 |
-
$things = $this->get( $type );
|
148 |
-
if ( ! empty( $things ) && is_array( $things ) ) {
|
149 |
-
foreach ( $things as $pending ) {
|
150 |
-
/**
|
151 |
-
* Our pending builder.
|
152 |
-
*
|
153 |
-
* @var WP_Job_Manager_REST_Interfaces_Builder $pending Our builder.
|
154 |
-
*/
|
155 |
-
if ( self::BUNDLES === $type ) {
|
156 |
-
$this->add_rest_bundle( $pending->build() );
|
157 |
-
}
|
158 |
-
}
|
159 |
-
}
|
160 |
-
|
161 |
-
return $this;
|
162 |
-
}
|
163 |
-
|
164 |
-
/**
|
165 |
-
* Start things up
|
166 |
-
*
|
167 |
-
* This should be called once our Environment is set up to our liking.
|
168 |
-
* Evaluates all Builders, creating missing REST Api and Model Definitions.
|
169 |
-
*
|
170 |
-
*
|
171 |
-
* It is recommended we hook this into 'rest_api_init'.
|
172 |
-
*
|
173 |
-
* @return WP_Job_Manager_REST_Environment $this
|
174 |
-
*/
|
175 |
-
public function start() {
|
176 |
-
if ( ! $this->bootstrap->is_compatible() ) {
|
177 |
-
// Do not even start on an incompatible system.
|
178 |
-
return $this;
|
179 |
-
}
|
180 |
-
|
181 |
-
if ( false === $this->has_started ) {
|
182 |
-
$this->get_event_dispatcher()->do_action( 'environment_before_start', $this, get_class( $this ) );
|
183 |
-
$this->load_pending_builders( self::MODELS );
|
184 |
-
$this->load_pending_builders( self::BUNDLES );
|
185 |
-
$registrables = $this->get( self::REGISTRABLE ) ? $this->get( self::REGISTRABLE ) : array();
|
186 |
-
foreach ( $registrables as $registrable ) {
|
187 |
-
/**
|
188 |
-
* A Registrable
|
189 |
-
*
|
190 |
-
* @var WP_Job_Manager_REST_Interfaces_Registrable $registrable
|
191 |
-
*/
|
192 |
-
$registrable->register( $this );
|
193 |
-
}
|
194 |
-
|
195 |
-
/**
|
196 |
-
* Use this hook to add/remove rest api bundles
|
197 |
-
*
|
198 |
-
* @param array $rest_apis The existing rest apis.
|
199 |
-
* @param WP_Job_Manager_REST_Environment $this The Environment.
|
200 |
-
*/
|
201 |
-
$rest_apis = (array) $this->get_event_dispatcher()->apply_filters( 'environment_get_rest_apis', $this->rest_apis, $this );
|
202 |
-
|
203 |
-
foreach ( $rest_apis as $k => $bundle ) {
|
204 |
-
/**
|
205 |
-
* Register this bundle
|
206 |
-
*
|
207 |
-
* @var WP_Job_Manager_REST_Interfaces_Controller_Bundle
|
208 |
-
*/
|
209 |
-
$bundle->register( $this );
|
210 |
-
}
|
211 |
-
$this->has_started = true;
|
212 |
-
$this->get_event_dispatcher()->do_action( 'environment_after_start', $this );
|
213 |
-
}
|
214 |
-
|
215 |
-
return $this;
|
216 |
-
}
|
217 |
-
|
218 |
-
/**
|
219 |
-
* Add Registrable
|
220 |
-
*
|
221 |
-
* @param WP_Job_Manager_REST_Interfaces_Registrable $registrable_thing Registrable.
|
222 |
-
* @return WP_Job_Manager_REST_Environment
|
223 |
-
* @throws WP_Job_Manager_REST_Exception When not a WP_Job_Manager_REST_Interfaces_Registrable.
|
224 |
-
*/
|
225 |
-
public function add_registrable( $registrable_thing ) {
|
226 |
-
WP_Job_Manager_REST_Expect::is_a( $registrable_thing, 'WP_Job_Manager_REST_Interfaces_Registrable' );
|
227 |
-
$this->array_var( self::REGISTRABLE, $registrable_thing );
|
228 |
-
return $this->define_var( get_class( $registrable_thing ), $registrable_thing );
|
229 |
-
}
|
230 |
-
|
231 |
-
/**
|
232 |
-
* Has Variable
|
233 |
-
*
|
234 |
-
* @param string $name Is this variable Set.
|
235 |
-
* @return bool
|
236 |
-
*/
|
237 |
-
public function has_variable( $name ) {
|
238 |
-
return isset( $this->variables[ $name ] );
|
239 |
-
}
|
240 |
-
|
241 |
-
/**
|
242 |
-
* Append to an array
|
243 |
-
*
|
244 |
-
* @param string $name The VarArray Name.
|
245 |
-
* @param mixed $thing The thing.
|
246 |
-
* @return WP_Job_Manager_REST_Environment
|
247 |
-
*/
|
248 |
-
public function array_var( $name, $thing = null ) {
|
249 |
-
return $this->define_var( $name, $thing, true );
|
250 |
-
}
|
251 |
-
|
252 |
-
/**
|
253 |
-
* Get A Variable
|
254 |
-
*
|
255 |
-
* @param string $name The Variable Name.
|
256 |
-
* @return mixed|null The variable or null
|
257 |
-
*
|
258 |
-
* @throws WP_Job_Manager_REST_Exception Name should be a string.
|
259 |
-
*/
|
260 |
-
public function get( $name ) {
|
261 |
-
WP_Job_Manager_REST_Expect::that( is_string( $name ), '$name should be a string' );
|
262 |
-
$value = $this->has_variable( $name ) ? $this->variables[ $name ] : null;
|
263 |
-
/**
|
264 |
-
* Filter the variable value
|
265 |
-
*
|
266 |
-
* @param mixed $value The value.
|
267 |
-
* @param WP_Job_Manager_REST_Environment $this The Environemnt.
|
268 |
-
* @param string $name The var name.
|
269 |
-
*
|
270 |
-
* @return mixed
|
271 |
-
*/
|
272 |
-
return $this->get_event_dispatcher()->apply_filters( 'variable_get', $value, $this, $name );
|
273 |
-
}
|
274 |
-
|
275 |
-
/**
|
276 |
-
* Def.
|
277 |
-
*
|
278 |
-
* @param string $name The Variable To Add.
|
279 |
-
* @param mixed $thing The thing that is associated with the var.
|
280 |
-
* @param bool $append If true, this var is a list.
|
281 |
-
*
|
282 |
-
* @return $this
|
283 |
-
*
|
284 |
-
* @throws WP_Job_Manager_REST_Exception When name is not a string.
|
285 |
-
*/
|
286 |
-
public function define_var( $name, $thing = null, $append = false ) {
|
287 |
-
WP_Job_Manager_REST_Expect::that( is_string( $name ), '$name should be a string' );
|
288 |
-
if ( $append && ! $this->has_variable( $name ) ) {
|
289 |
-
$this->variables[ $name ] = array();
|
290 |
-
}
|
291 |
-
if ( null !== $thing ) {
|
292 |
-
if ( $append ) {
|
293 |
-
$this->variables[ $name ][] = $thing;
|
294 |
-
} else {
|
295 |
-
$this->variables[ $name ] = $thing;
|
296 |
-
}
|
297 |
-
}
|
298 |
-
return $this;
|
299 |
-
}
|
300 |
-
|
301 |
-
/**
|
302 |
-
* Auto start on rest_api_init. For more control, use ::start();
|
303 |
-
*/
|
304 |
-
public function auto_start() {
|
305 |
-
add_action( 'rest_api_init', array( $this, 'start' ) );
|
306 |
-
}
|
307 |
-
|
308 |
-
/**
|
309 |
-
* Get this Environment's bootstrap instance
|
310 |
-
*
|
311 |
-
* @return WP_Job_Manager_REST_Bootstrap our bootstrap.
|
312 |
-
*/
|
313 |
-
public function get_bootstrap() {
|
314 |
-
return $this->bootstrap;
|
315 |
-
}
|
316 |
-
|
317 |
-
/**
|
318 |
-
* Create a new Field Declaration Builder
|
319 |
-
*
|
320 |
-
* @param null|string $name Optional, the field name.
|
321 |
-
* @param null|string $description Optional, the description.
|
322 |
-
* @param null|string $field_kind The field kind (default 'field').
|
323 |
-
*
|
324 |
-
* @return WP_Job_Manager_REST_Field_Declaration_Builder
|
325 |
-
*/
|
326 |
-
public function field( $name = null, $description = null, $field_kind = null ) {
|
327 |
-
$builder = new WP_Job_Manager_REST_Field_Declaration_Builder();
|
328 |
-
|
329 |
-
if ( ! empty( $name ) ) {
|
330 |
-
$builder->with_name( $name );
|
331 |
-
}
|
332 |
-
|
333 |
-
if ( ! empty( $description ) ) {
|
334 |
-
$builder->with_description( $description );
|
335 |
-
}
|
336 |
-
|
337 |
-
if ( empty( $field_kind ) ) {
|
338 |
-
$field_kind = WP_Job_Manager_REST_Field_Declaration::FIELD;
|
339 |
-
}
|
340 |
-
|
341 |
-
$builder->with_kind( $field_kind );
|
342 |
-
|
343 |
-
return $builder;
|
344 |
-
}
|
345 |
-
|
346 |
-
/**
|
347 |
-
* Get our registered types
|
348 |
-
*
|
349 |
-
* @return WP_Job_Manager_REST_Type_Registry
|
350 |
-
*/
|
351 |
-
public function get_type_registry() {
|
352 |
-
return $this->type_registry;
|
353 |
-
}
|
354 |
-
|
355 |
-
/**
|
356 |
-
* Get a known type definition
|
357 |
-
*
|
358 |
-
* @param string $type_name The type name.
|
359 |
-
* @return WP_Job_Manager_REST_Interfaces_Type
|
360 |
-
*
|
361 |
-
* @throws WP_Job_Manager_REST_Exception When provided with an unknown/invalid type.
|
362 |
-
*/
|
363 |
-
public function type( $type_name ) {
|
364 |
-
return $this->get_type_registry()->definition( $type_name );
|
365 |
-
}
|
366 |
-
|
367 |
-
/**
|
368 |
-
* Define a new REST API Bundle.
|
369 |
-
*
|
370 |
-
* @param null|string|WP_Job_Manager_REST_Interfaces_Controller_Bundle $maybe_bundle_or_prefix The bundle name.
|
371 |
-
* @return WP_Job_Manager_REST_Controller_Bundle_Builder
|
372 |
-
*/
|
373 |
-
public function rest_api( $maybe_bundle_or_prefix = null ) {
|
374 |
-
if ( is_a( $maybe_bundle_or_prefix, 'WP_Job_Manager_REST_Interfaces_Controller_Bundle' ) ) {
|
375 |
-
$builder = new WP_Job_Manager_REST_Controller_Bundle_Builder( $maybe_bundle_or_prefix );
|
376 |
-
} else {
|
377 |
-
$builder = new WP_Job_Manager_REST_Controller_Bundle_Builder();
|
378 |
-
if ( is_string( $maybe_bundle_or_prefix ) ) {
|
379 |
-
$builder->with_prefix( $maybe_bundle_or_prefix );
|
380 |
-
}
|
381 |
-
$builder->with_environment( $this );
|
382 |
-
}
|
383 |
-
|
384 |
-
$this->push_builder( self::BUNDLES, $builder );
|
385 |
-
return $builder;
|
386 |
-
}
|
387 |
-
|
388 |
-
/**
|
389 |
-
* Define a new Model
|
390 |
-
*
|
391 |
-
* @param string $declaration A Model class string.
|
392 |
-
*
|
393 |
-
* @return WP_Job_Manager_REST_Model
|
394 |
-
*/
|
395 |
-
function define_model( $declaration ) {
|
396 |
-
WP_Job_Manager_REST_Expect::that( class_exists( $declaration ), '$declaration string should be an existing class' );
|
397 |
-
WP_Job_Manager_REST_Expect::that( in_array( 'WP_Job_Manager_REST_Interfaces_Model', class_implements( $declaration ), true ), '$declaration does not implement WP_Job_Manager_REST_Interfaces_Model' );
|
398 |
-
|
399 |
-
/**
|
400 |
-
* Create an empty Model to act as our factory (I know this is weird, see php5.2)
|
401 |
-
*
|
402 |
-
* @var WP_Job_Manager_REST_Model $factory
|
403 |
-
*/
|
404 |
-
$factory = new $declaration();
|
405 |
-
$factory->with_environment( $this );
|
406 |
-
$factory->with_data_store( new WP_Job_Manager_REST_Data_Store_Nil() );
|
407 |
-
$factory->with_permissions_provider( new WP_Job_Manager_REST_Permissions_Any() );
|
408 |
-
$this->model_definitions[ $declaration ] = $factory;
|
409 |
-
return $factory;
|
410 |
-
}
|
411 |
-
|
412 |
-
/**
|
413 |
-
* Add a Bundle to our bundles (muse be Mixtape_Interfaces_Rest_Api_Controller_Bundle)
|
414 |
-
*
|
415 |
-
* @param WP_Job_Manager_REST_Interfaces_Controller_Bundle $bundle the bundle.
|
416 |
-
*
|
417 |
-
* @return WP_Job_Manager_REST_Environment $this
|
418 |
-
* @throws WP_Job_Manager_REST_Exception In case it's not a WP_Job_Manager_REST_Interfaces_Controller_Bundle.
|
419 |
-
*/
|
420 |
-
private function add_rest_bundle( $bundle ) {
|
421 |
-
WP_Job_Manager_REST_Expect::is_a( $bundle, 'WP_Job_Manager_REST_Interfaces_Controller_Bundle' );
|
422 |
-
$key = $bundle->get_prefix();
|
423 |
-
$this->rest_apis[ $key ] = $bundle;
|
424 |
-
return $this;
|
425 |
-
}
|
426 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/class-wp-job-manager-rest-events.php
DELETED
@@ -1,144 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* WP_Job_Manager_REST_Events: Simple event bus
|
4 |
-
*
|
5 |
-
* @package Mixtape
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_Events
|
14 |
-
*
|
15 |
-
* Simple event bus
|
16 |
-
*
|
17 |
-
* @package Mixtape
|
18 |
-
*/
|
19 |
-
class WP_Job_Manager_REST_Events {
|
20 |
-
/**
|
21 |
-
* Events
|
22 |
-
*
|
23 |
-
* @var array
|
24 |
-
*/
|
25 |
-
private $events = array();
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Add Filter
|
29 |
-
*
|
30 |
-
* @param string $event Event.
|
31 |
-
* @param callable $func Func.
|
32 |
-
* @param int $priority Priority.
|
33 |
-
* @param int $accepted_args Accepted Args.
|
34 |
-
*
|
35 |
-
* @return $this
|
36 |
-
*/
|
37 |
-
public function add_filter( $event, $func, $priority = 10, $accepted_args = 1 ) {
|
38 |
-
WP_Job_Manager_REST_Expect::that( is_callable( $func ), sprintf( '$func is not callable' ) );
|
39 |
-
if ( ! isset( $this->events[ $event ] ) ) {
|
40 |
-
$this->events[ $event ] = new WP_Hook();
|
41 |
-
}
|
42 |
-
/**
|
43 |
-
* The hook.
|
44 |
-
*
|
45 |
-
* @var WP_Hook $hook
|
46 |
-
*/
|
47 |
-
$hook = $this->events[ $event ];
|
48 |
-
$hook->add_filter( $event, $func, $priority, $accepted_args );
|
49 |
-
return $this;
|
50 |
-
}
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Add Action
|
54 |
-
*
|
55 |
-
* @param string $event Event.
|
56 |
-
* @param callable $func Func.
|
57 |
-
* @param int $priority Priority.
|
58 |
-
* @param int $accepted_args Accepted Args.
|
59 |
-
*
|
60 |
-
* @return $this
|
61 |
-
*/
|
62 |
-
public function add_action( $event, $func, $priority = 10, $accepted_args = 1 ) {
|
63 |
-
return $this->add_filter( $event, $func, $priority, $accepted_args );
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Apply Filters
|
68 |
-
*
|
69 |
-
* @param string $event Event.
|
70 |
-
* @param mixed $value Value.
|
71 |
-
*
|
72 |
-
* @return mixed
|
73 |
-
*/
|
74 |
-
public function apply_filters( $event, $value ) {
|
75 |
-
$func_args = func_get_args();
|
76 |
-
if ( ! isset( $this->events[ $event ] ) ) {
|
77 |
-
return $value;
|
78 |
-
}
|
79 |
-
/**
|
80 |
-
* The hook.
|
81 |
-
*
|
82 |
-
* @var WP_Hook $hook
|
83 |
-
*/
|
84 |
-
$hook = $this->events[ $event ];
|
85 |
-
$func_args = array_slice( $func_args, 1 );
|
86 |
-
return $hook->apply_filters( $value, $func_args );
|
87 |
-
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Do Action
|
92 |
-
*
|
93 |
-
* @param string $event Event.
|
94 |
-
*
|
95 |
-
* @return mixed
|
96 |
-
*/
|
97 |
-
public function do_action( $event ) {
|
98 |
-
$func_args = func_get_args();
|
99 |
-
if ( ! isset( $this->events[ $event ] ) ) {
|
100 |
-
return;
|
101 |
-
}
|
102 |
-
/**
|
103 |
-
* The hook.
|
104 |
-
*
|
105 |
-
* @var WP_Hook $hook
|
106 |
-
*/
|
107 |
-
$hook = $this->events[ $event ];
|
108 |
-
array_shift( $func_args );
|
109 |
-
$hook->do_action( $func_args );
|
110 |
-
}
|
111 |
-
|
112 |
-
/**
|
113 |
-
* Remove
|
114 |
-
*
|
115 |
-
* @param string $event The Event.
|
116 |
-
* @param bool|callable $function_to_remove The callable.
|
117 |
-
* @param int $priority Priority.
|
118 |
-
* @return $this
|
119 |
-
*/
|
120 |
-
public function remove( $event, $function_to_remove = false, $priority = 10 ) {
|
121 |
-
if ( isset( $this->events[ $event ] ) ) {
|
122 |
-
if ( false === $function_to_remove ) {
|
123 |
-
/**
|
124 |
-
* The hook.
|
125 |
-
*
|
126 |
-
* @var WP_Hook $hook
|
127 |
-
*/
|
128 |
-
$hook = $this->events[ $event ];
|
129 |
-
$hook->remove_all_filters();
|
130 |
-
unset( $this->events[ $event ] );
|
131 |
-
}
|
132 |
-
/**
|
133 |
-
* The hook.
|
134 |
-
*
|
135 |
-
* @var WP_Hook $hook
|
136 |
-
*/
|
137 |
-
$hook = $this->events[ $event ];
|
138 |
-
if ( $hook->has_filter( $event, $function_to_remove ) ) {
|
139 |
-
$hook->remove_filter( $event, $function_to_remove, $priority );
|
140 |
-
}
|
141 |
-
}
|
142 |
-
return $this;
|
143 |
-
}
|
144 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/class-wp-job-manager-rest-exception.php
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Mixtape_Exception
|
4 |
-
*
|
5 |
-
* @package Mixtape
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Base Exception class
|
14 |
-
* Class WP_Job_Manager_REST_Exception
|
15 |
-
*/
|
16 |
-
class WP_Job_Manager_REST_Exception extends Exception {
|
17 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/class-wp-job-manager-rest-expect.php
DELETED
@@ -1,77 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Mixtape_Expect
|
4 |
-
*
|
5 |
-
* Asserts about invariants
|
6 |
-
*
|
7 |
-
* @package Mixtape
|
8 |
-
*/
|
9 |
-
|
10 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
-
exit;
|
12 |
-
}
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Class Mixtape_Expect
|
16 |
-
*/
|
17 |
-
class WP_Job_Manager_REST_Expect {
|
18 |
-
/**
|
19 |
-
* Expect a certain class
|
20 |
-
*
|
21 |
-
* @param mixed $thing The thing to test.
|
22 |
-
* @param string $class_name The class.
|
23 |
-
*
|
24 |
-
* @throws WP_Job_Manager_REST_Exception Fail if we got an unexpected class.
|
25 |
-
*/
|
26 |
-
static function is_a( $thing, $class_name ) {
|
27 |
-
self::is_object( $thing );
|
28 |
-
self::that( is_a( $thing, $class_name ), 'Expected ' . $class_name . ', got ' . get_class( $thing ) );
|
29 |
-
}
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Expect that something implements an interface.
|
33 |
-
*
|
34 |
-
* @param object|string|mixed $thing The thing to check.
|
35 |
-
* @param string $interface_name The interface name.
|
36 |
-
*/
|
37 |
-
static function implements_interface( $thing, $interface_name ) {
|
38 |
-
$thing_class = is_object( $thing ) ? get_class( $thing ) : (string) $thing;
|
39 |
-
$interfaces = class_implements( $thing );
|
40 |
-
self::that( in_array( $interface_name, $interfaces, true ), 'Class ' . $thing_class . ' does not implement interface ' . $interface_name );
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Expect that thing is an object
|
45 |
-
*
|
46 |
-
* @param mixed $thing The thing.
|
47 |
-
* @throws WP_Job_Manager_REST_Exception Throw if not an object.
|
48 |
-
*/
|
49 |
-
static function is_object( $thing ) {
|
50 |
-
self::that( is_object( $thing ), 'Variable is is not an Object' );
|
51 |
-
}
|
52 |
-
|
53 |
-
/**
|
54 |
-
* Express an invariant.
|
55 |
-
*
|
56 |
-
* @param bool $cond The boolean condition that needs to hold.
|
57 |
-
* @param string $fail_message In case of failure, the reason this failed.
|
58 |
-
*
|
59 |
-
* @throws WP_Job_Manager_REST_Exception Fail if condition doesn't hold.
|
60 |
-
*/
|
61 |
-
static function that( $cond, $fail_message ) {
|
62 |
-
if ( ! $cond ) {
|
63 |
-
throw new WP_Job_Manager_REST_Exception( $fail_message );
|
64 |
-
}
|
65 |
-
}
|
66 |
-
|
67 |
-
/**
|
68 |
-
* This method should be Overridden
|
69 |
-
*
|
70 |
-
* @param string $method The method name.
|
71 |
-
*
|
72 |
-
* @throws WP_Job_Manager_REST_Exception To Overrride this.
|
73 |
-
*/
|
74 |
-
static function should_override( $method ) {
|
75 |
-
throw new WP_Job_Manager_REST_Exception( $method . ' should be overriden' );
|
76 |
-
}
|
77 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/class-wp-job-manager-rest-model.php
DELETED
@@ -1,686 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* The Abstract Mixtape_Interfaces_Model Base Class
|
4 |
-
*
|
5 |
-
* @package Mixtape/Model
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_Model
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_REST_Model implements
|
16 |
-
WP_Job_Manager_REST_Interfaces_Model,
|
17 |
-
WP_Job_Manager_REST_Interfaces_Permissions_Provider {
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Fields By Class Name
|
21 |
-
*
|
22 |
-
* @var array
|
23 |
-
*/
|
24 |
-
private static $fields_by_class_name = array();
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Data Stores By Class Name
|
28 |
-
*
|
29 |
-
* @var array
|
30 |
-
*/
|
31 |
-
private static $data_stores_by_class_name = array();
|
32 |
-
|
33 |
-
/**
|
34 |
-
* The Environment the model exists in
|
35 |
-
*
|
36 |
-
* @var WP_Job_Manager_REST_Environment
|
37 |
-
*/
|
38 |
-
private static $environments_by_class_name = array();
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Permissions Providers by class Name
|
42 |
-
*
|
43 |
-
* @var array
|
44 |
-
*/
|
45 |
-
private static $permissions_providers_by_class_name = array();
|
46 |
-
|
47 |
-
/**
|
48 |
-
* Our data
|
49 |
-
*
|
50 |
-
* @var array
|
51 |
-
*/
|
52 |
-
private $data;
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Our raw data
|
56 |
-
*
|
57 |
-
* @var array
|
58 |
-
*/
|
59 |
-
private $raw_data;
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Mixtape_Model constructor.
|
63 |
-
*
|
64 |
-
* @param array $data The data array.
|
65 |
-
* @param array $args Args.
|
66 |
-
*
|
67 |
-
* @throws WP_Job_Manager_REST_Exception Throws when data is not an array.
|
68 |
-
*/
|
69 |
-
function __construct( $data = array(), $args = array() ) {
|
70 |
-
WP_Job_Manager_REST_Expect::that( is_array( $data ), '$data should be an array' );
|
71 |
-
$this->data = array();
|
72 |
-
|
73 |
-
if ( isset( $args['deserialize'] ) && true === $args['deserialize'] ) {
|
74 |
-
unset( $args['deserialize'] );
|
75 |
-
$data = $this->deserialize( $data );
|
76 |
-
}
|
77 |
-
$this->raw_data = $data;
|
78 |
-
$data_keys = array_keys( $data );
|
79 |
-
|
80 |
-
foreach ( $data_keys as $key ) {
|
81 |
-
$this->set( $key, $this->raw_data[ $key ] );
|
82 |
-
}
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Gets the value of a previously defined field.
|
87 |
-
*
|
88 |
-
* @param string $field_name The field name.
|
89 |
-
* @param array $args Any args.
|
90 |
-
*
|
91 |
-
* @return mixed
|
92 |
-
* @throws WP_Job_Manager_REST_Exception Fails when field is unknown.
|
93 |
-
*/
|
94 |
-
public function get( $field_name, $args = array() ) {
|
95 |
-
WP_Job_Manager_REST_Expect::that( $this->has( $field_name ), 'Field ' . $field_name . 'is not defined' );
|
96 |
-
$fields = $this->get_fields();
|
97 |
-
$field_declaration = $fields[ $field_name ];
|
98 |
-
$this->set_field_if_unset( $field_declaration );
|
99 |
-
|
100 |
-
return $this->prepare_value( $field_declaration );
|
101 |
-
}
|
102 |
-
|
103 |
-
/**
|
104 |
-
* Sets a field value.
|
105 |
-
*
|
106 |
-
* @param string $field The field name.
|
107 |
-
* @param mixed $value The new field value.
|
108 |
-
*
|
109 |
-
* @return $this
|
110 |
-
* @throws WP_Job_Manager_REST_Exception Throws when trying to set an unknown field.
|
111 |
-
*/
|
112 |
-
public function set( $field, $value ) {
|
113 |
-
WP_Job_Manager_REST_Expect::that( $this->has( $field ), 'Field ' . $field . 'is not defined' );
|
114 |
-
$fields = self::get_fields();
|
115 |
-
/**
|
116 |
-
* The declaration.
|
117 |
-
*
|
118 |
-
* @var WP_Job_Manager_REST_Field_Declaration $field_declaration The declaration.
|
119 |
-
*/
|
120 |
-
$field_declaration = $fields[ $field ];
|
121 |
-
if ( isset( $args['deserializing'] ) && $args['deserializing'] ) {
|
122 |
-
$value = $this->deserialize_field( $field_declaration, $value );
|
123 |
-
}
|
124 |
-
if ( null !== $field_declaration->before_set() ) {
|
125 |
-
$val = $this->call( $field_declaration->before_set(), array( $value, $field_declaration->get_name() ) );
|
126 |
-
} else {
|
127 |
-
$val = $field_declaration->cast_value( $value );
|
128 |
-
}
|
129 |
-
$this->data[ $field_declaration->get_name() ] = $val;
|
130 |
-
return $this;
|
131 |
-
}
|
132 |
-
|
133 |
-
/**
|
134 |
-
* Check if this model has a field
|
135 |
-
*
|
136 |
-
* @param string $field The field name to check.
|
137 |
-
* @return bool
|
138 |
-
*/
|
139 |
-
public function has( $field ) {
|
140 |
-
$fields = $this->get_fields();
|
141 |
-
return isset( $fields[ $field ] );
|
142 |
-
}
|
143 |
-
|
144 |
-
/**
|
145 |
-
* Validate this Model's current state.
|
146 |
-
*
|
147 |
-
* @return bool|WP_Error Either true or WP_Error on failure.
|
148 |
-
*/
|
149 |
-
public function validate() {
|
150 |
-
$validation_errors = array();
|
151 |
-
$fields = self::get_fields();
|
152 |
-
foreach ( $fields as $key => $field_declaration ) {
|
153 |
-
$is_valid = $this->run_field_validations( $field_declaration );
|
154 |
-
if ( is_wp_error( $is_valid ) ) {
|
155 |
-
$validation_errors[] = $is_valid->get_error_data();
|
156 |
-
}
|
157 |
-
}
|
158 |
-
if ( count( $validation_errors ) > 0 ) {
|
159 |
-
return $this->validation_error( $validation_errors );
|
160 |
-
}
|
161 |
-
return true;
|
162 |
-
}
|
163 |
-
|
164 |
-
/**
|
165 |
-
* Sanitize this Model's current data.
|
166 |
-
*
|
167 |
-
* @return WP_Job_Manager_REST_Interfaces_Model $this
|
168 |
-
*/
|
169 |
-
public function sanitize() {
|
170 |
-
$fields = self::get_fields();
|
171 |
-
foreach ( $fields as $key => $field_declaration ) {
|
172 |
-
/**
|
173 |
-
* Field Declaration.
|
174 |
-
*
|
175 |
-
* @var WP_Job_Manager_REST_Field_Declaration $field_declaration
|
176 |
-
*/
|
177 |
-
$field_name = $field_declaration->get_name();
|
178 |
-
$value = $this->get( $field_name );
|
179 |
-
$custom_sanitization = $field_declaration->get_sanitizer();
|
180 |
-
if ( ! empty( $custom_sanitization ) ) {
|
181 |
-
$value = $this->call( $custom_sanitization, array( $this, $value ) );
|
182 |
-
} else {
|
183 |
-
$value = $field_declaration->get_type()->sanitize( $value );
|
184 |
-
}
|
185 |
-
$this->set( $field_name, $value );
|
186 |
-
}
|
187 |
-
return $this;
|
188 |
-
}
|
189 |
-
|
190 |
-
/**
|
191 |
-
* We got a Validation Error
|
192 |
-
*
|
193 |
-
* @param array $error_data The details.
|
194 |
-
* @return WP_Error
|
195 |
-
*/
|
196 |
-
protected function validation_error( $error_data ) {
|
197 |
-
return new WP_Error( 'validation-error', 'validation-error', $error_data );
|
198 |
-
}
|
199 |
-
|
200 |
-
/**
|
201 |
-
* Run Validations for this field.
|
202 |
-
*
|
203 |
-
* @param WP_Job_Manager_REST_Field_Declaration $field_declaration The field.
|
204 |
-
*
|
205 |
-
* @return bool|WP_Error
|
206 |
-
*/
|
207 |
-
protected function run_field_validations( $field_declaration ) {
|
208 |
-
if ( $field_declaration->is_kind( WP_Job_Manager_REST_Field_Declaration::DERIVED ) ) {
|
209 |
-
return true;
|
210 |
-
}
|
211 |
-
$value = $this->get( $field_declaration->get_name() );
|
212 |
-
if ( $field_declaration->is_required() && empty( $value ) ) {
|
213 |
-
// translators: %s is usually a field name.
|
214 |
-
$message = sprintf( __( '%s cannot be empty', 'mixtape' ), $field_declaration->get_name() );
|
215 |
-
return new WP_Error( 'required-field-empty', $message );
|
216 |
-
} elseif ( ! $field_declaration->is_required() && ! empty( $value ) ) {
|
217 |
-
foreach ( $field_declaration->get_validations() as $validation ) {
|
218 |
-
$result = $this->call( $validation, array( $value ) );
|
219 |
-
if ( is_wp_error( $result ) ) {
|
220 |
-
$result->add_data(array(
|
221 |
-
'reason' => $result->get_error_messages(),
|
222 |
-
'field' => $field_declaration->get_data_transfer_name(),
|
223 |
-
'value' => $value,
|
224 |
-
) );
|
225 |
-
return $result;
|
226 |
-
}
|
227 |
-
}
|
228 |
-
}
|
229 |
-
return true;
|
230 |
-
}
|
231 |
-
|
232 |
-
/**
|
233 |
-
* Prepare the value associated with this declaraton for output.
|
234 |
-
*
|
235 |
-
* @param WP_Job_Manager_REST_Field_Declaration $field_declaration The declaration to use.
|
236 |
-
* @return mixed
|
237 |
-
*/
|
238 |
-
private function prepare_value( $field_declaration ) {
|
239 |
-
$key = $field_declaration->get_name();
|
240 |
-
$value = $this->data[ $key ];
|
241 |
-
$before_return = $field_declaration->before_get();
|
242 |
-
if ( isset( $before_return ) && ! empty( $before_return ) ) {
|
243 |
-
$value = $this->call( $before_return, array( $value, $key ) );
|
244 |
-
}
|
245 |
-
|
246 |
-
return $value;
|
247 |
-
}
|
248 |
-
|
249 |
-
/**
|
250 |
-
* Sets this field's value. Used for derived fields.
|
251 |
-
*
|
252 |
-
* @param WP_Job_Manager_REST_Field_Declaration $field_declaration The field declaration.
|
253 |
-
*/
|
254 |
-
private function set_field_if_unset( $field_declaration ) {
|
255 |
-
$field_name = $field_declaration->get_name();
|
256 |
-
if ( ! isset( $this->data[ $field_name ] ) ) {
|
257 |
-
if ( $field_declaration->is_kind( WP_Job_Manager_REST_Field_Declaration::DERIVED ) ) {
|
258 |
-
$map_from = $field_declaration->get_map_from();
|
259 |
-
$value = $this->call( $map_from );
|
260 |
-
$this->set( $field_name, $value );
|
261 |
-
} else {
|
262 |
-
$this->set( $field_name, $field_declaration->get_default_value() );
|
263 |
-
}
|
264 |
-
}
|
265 |
-
}
|
266 |
-
|
267 |
-
/**
|
268 |
-
* Get this model class fields
|
269 |
-
*
|
270 |
-
* @param null|string $filter_by_type Filter.
|
271 |
-
* @return array
|
272 |
-
*/
|
273 |
-
public function get_fields( $filter_by_type = null ) {
|
274 |
-
$class_name = get_class( $this );
|
275 |
-
/**
|
276 |
-
* Out model
|
277 |
-
*
|
278 |
-
* @var WP_Job_Manager_REST_Interfaces_Model $instance
|
279 |
-
*/
|
280 |
-
$instance = new $class_name();
|
281 |
-
if ( ! isset( self::$fields_by_class_name[ $class_name ] ) ) {
|
282 |
-
$fields = $instance->declare_fields();
|
283 |
-
self::$fields_by_class_name[ $class_name ] = self::initialize_field_map( $fields );
|
284 |
-
}
|
285 |
-
|
286 |
-
if ( null === $filter_by_type ) {
|
287 |
-
return self::$fields_by_class_name[ $class_name ];
|
288 |
-
}
|
289 |
-
|
290 |
-
$filtered = array();
|
291 |
-
|
292 |
-
foreach ( self::$fields_by_class_name[ $class_name ] as $field_declaration ) {
|
293 |
-
/**
|
294 |
-
* The field declaration.
|
295 |
-
*
|
296 |
-
* @var WP_Job_Manager_REST_Field_Declaration $field_declaration
|
297 |
-
*/
|
298 |
-
if ( $field_declaration->get_kind() === $filter_by_type ) {
|
299 |
-
$filtered[] = $field_declaration;
|
300 |
-
}
|
301 |
-
}
|
302 |
-
return $filtered;
|
303 |
-
}
|
304 |
-
|
305 |
-
/**
|
306 |
-
* Initialize_field_map
|
307 |
-
*
|
308 |
-
* @param array $declared_field_builders Array<Mixtape_Model_Field_Declaration_Builder>.
|
309 |
-
*
|
310 |
-
* @return array
|
311 |
-
*/
|
312 |
-
private static function initialize_field_map( $declared_field_builders ) {
|
313 |
-
$fields = array();
|
314 |
-
foreach ( $declared_field_builders as $field_builder ) {
|
315 |
-
/**
|
316 |
-
* Builder
|
317 |
-
*
|
318 |
-
* @var WP_Job_Manager_REST_Field_Declaration $field Field Builder.
|
319 |
-
*/
|
320 |
-
$field = $field_builder->build();
|
321 |
-
$fields[ $field->get_name() ] = $field;
|
322 |
-
}
|
323 |
-
return $fields;
|
324 |
-
}
|
325 |
-
|
326 |
-
/**
|
327 |
-
* Get this model's data store
|
328 |
-
*
|
329 |
-
* @return WP_Job_Manager_REST_Interfaces_Data_Store
|
330 |
-
*/
|
331 |
-
public function get_data_store() {
|
332 |
-
$class_name = get_class( $this );
|
333 |
-
if ( ! isset( self::$data_stores_by_class_name[ $class_name ] ) ) {
|
334 |
-
self::$data_stores_by_class_name[ $class_name ] = new WP_Job_Manager_REST_Data_Store_Nil();
|
335 |
-
}
|
336 |
-
return self::$data_stores_by_class_name[ $class_name ];
|
337 |
-
}
|
338 |
-
|
339 |
-
/**
|
340 |
-
* Set this model's data store
|
341 |
-
*
|
342 |
-
* @param WP_Job_Manager_REST_Interfaces_Data_Store $data_store A builder or a Data store.
|
343 |
-
* @throws WP_Job_Manager_REST_Exception Throws when Data Store Invalid.
|
344 |
-
*/
|
345 |
-
public function with_data_store( $data_store ) {
|
346 |
-
$class_name = get_class( $this );
|
347 |
-
// at this point we should have a data store.
|
348 |
-
WP_Job_Manager_REST_Expect::is_a( $data_store, 'WP_Job_Manager_REST_Interfaces_Data_Store' );
|
349 |
-
self::$data_stores_by_class_name[ $class_name ] = $data_store;
|
350 |
-
}
|
351 |
-
|
352 |
-
/**
|
353 |
-
* Get this model's environment
|
354 |
-
*
|
355 |
-
* @return WP_Job_Manager_REST_Environment|null
|
356 |
-
*/
|
357 |
-
public function get_environment() {
|
358 |
-
$class_name = get_class( $this );
|
359 |
-
if ( isset( self::$environments_by_class_name[ $class_name ] ) ) {
|
360 |
-
return self::$environments_by_class_name[ $class_name ];
|
361 |
-
}
|
362 |
-
return null;
|
363 |
-
}
|
364 |
-
|
365 |
-
/**
|
366 |
-
* Set the model base class environment (change effective in all subclasses)
|
367 |
-
*
|
368 |
-
* @param WP_Job_Manager_REST_Environment $environment The Environment.
|
369 |
-
*
|
370 |
-
* @return WP_Job_Manager_REST_Interfaces_Model
|
371 |
-
*
|
372 |
-
* @throws WP_Job_Manager_REST_Exception If an WP_Job_Manager_REST_Environment is not provided.
|
373 |
-
*/
|
374 |
-
public function with_environment( $environment ) {
|
375 |
-
WP_Job_Manager_REST_Expect::is_a( $environment, 'WP_Job_Manager_REST_Environment' );
|
376 |
-
$class_name = get_class( $this );
|
377 |
-
self::$environments_by_class_name[ $class_name ] = $environment;
|
378 |
-
return $this;
|
379 |
-
}
|
380 |
-
|
381 |
-
/**
|
382 |
-
* Create a new Model Instance
|
383 |
-
*
|
384 |
-
* @param array $data The data.
|
385 |
-
* @param array $args Args.
|
386 |
-
*
|
387 |
-
* @return WP_Job_Manager_REST_Interfaces_Model
|
388 |
-
* @throws WP_Job_Manager_REST_Exception Throws if data not an array.
|
389 |
-
*/
|
390 |
-
public function create( $data, $args = array() ) {
|
391 |
-
WP_Job_Manager_REST_Expect::that( is_array( $data ), '$data should be an array' );
|
392 |
-
WP_Job_Manager_REST_Expect::that( is_array( $args ), '$args should be an array' );
|
393 |
-
$class_name = get_class( $this );
|
394 |
-
return new $class_name( $data, $args );
|
395 |
-
}
|
396 |
-
|
397 |
-
/**
|
398 |
-
* Merge values from array with current values.
|
399 |
-
* Note: Values change in place.
|
400 |
-
*
|
401 |
-
* @param array $data The data (key-value assumed).
|
402 |
-
* @param bool $updating Is this an update?.
|
403 |
-
*
|
404 |
-
* @return WP_Job_Manager_REST_Interfaces_Model|WP_Error
|
405 |
-
* @throws WP_Job_Manager_REST_Exception Throws.
|
406 |
-
*/
|
407 |
-
function update_from_array( $data, $updating = false ) {
|
408 |
-
$mapped_data = self::map_data( $data, $updating );
|
409 |
-
foreach ( $mapped_data as $name => $value ) {
|
410 |
-
$this->set( $name, $value );
|
411 |
-
}
|
412 |
-
return $this->sanitize();
|
413 |
-
}
|
414 |
-
|
415 |
-
/**
|
416 |
-
* Creates a new Model From a Data Array
|
417 |
-
*
|
418 |
-
* @param array $data The Data.
|
419 |
-
*
|
420 |
-
* @return WP_Job_Manager_REST_Model|WP_Error
|
421 |
-
*/
|
422 |
-
public function new_from_array( $data ) {
|
423 |
-
$field_data = $this->map_data( $data, false );
|
424 |
-
return $this->create( $field_data )->sanitize();
|
425 |
-
}
|
426 |
-
|
427 |
-
/**
|
428 |
-
* Get field DTO Mappings
|
429 |
-
*
|
430 |
-
* @return array
|
431 |
-
*/
|
432 |
-
public function get_dto_field_mappings() {
|
433 |
-
$mappings = array();
|
434 |
-
foreach ( $this->get_fields() as $field_declaration ) {
|
435 |
-
/**
|
436 |
-
* Declaration
|
437 |
-
*
|
438 |
-
* @var WP_Job_Manager_REST_Field_Declaration $field_declaration
|
439 |
-
*/
|
440 |
-
if ( ! $field_declaration->supports_output_type( 'json' ) ) {
|
441 |
-
continue;
|
442 |
-
}
|
443 |
-
$mappings[ $field_declaration->get_data_transfer_name() ] = $field_declaration->get_name();
|
444 |
-
}
|
445 |
-
return $mappings;
|
446 |
-
}
|
447 |
-
|
448 |
-
/**
|
449 |
-
* Prepare the Model for Data Transfer
|
450 |
-
*
|
451 |
-
* @return array
|
452 |
-
*/
|
453 |
-
function to_dto() {
|
454 |
-
$result = array();
|
455 |
-
foreach ( $this->get_dto_field_mappings() as $mapping_name => $field_name ) {
|
456 |
-
$value = $this->get( $field_name );
|
457 |
-
$result[ $mapping_name ] = $value;
|
458 |
-
}
|
459 |
-
|
460 |
-
return $result;
|
461 |
-
}
|
462 |
-
|
463 |
-
/**
|
464 |
-
* Map data names
|
465 |
-
*
|
466 |
-
* @param array $data The data to map.
|
467 |
-
* @param bool $updating Are we Updating.
|
468 |
-
* @return array
|
469 |
-
*/
|
470 |
-
private function map_data( $data, $updating = false ) {
|
471 |
-
$request_data = array();
|
472 |
-
$fields = $this->get_fields();
|
473 |
-
foreach ( $fields as $field ) {
|
474 |
-
/**
|
475 |
-
* Field
|
476 |
-
*
|
477 |
-
* @var WP_Job_Manager_REST_Field_Declaration $field Field.
|
478 |
-
*/
|
479 |
-
if ( $field->is_kind( WP_Job_Manager_REST_Field_Declaration::DERIVED ) ) {
|
480 |
-
continue;
|
481 |
-
}
|
482 |
-
$dto_name = $field->get_data_transfer_name();
|
483 |
-
$field_name = $field->get_name();
|
484 |
-
if ( isset( $data[ $dto_name ] ) && ! ( $updating && $field->is_primary() ) ) {
|
485 |
-
$value = $data[ $dto_name ];
|
486 |
-
$request_data[ $field_name ] = $value;
|
487 |
-
}
|
488 |
-
}
|
489 |
-
return $request_data;
|
490 |
-
}
|
491 |
-
|
492 |
-
/**
|
493 |
-
* Call a method.
|
494 |
-
*
|
495 |
-
* @param string $method The method.
|
496 |
-
* @param array $args The args.
|
497 |
-
*
|
498 |
-
* @return mixed
|
499 |
-
* @throws WP_Job_Manager_REST_Exception Throw if method nonexistent.
|
500 |
-
*/
|
501 |
-
private function call( $method, $args = array() ) {
|
502 |
-
if ( is_callable( $method ) ) {
|
503 |
-
return call_user_func_array( $method, $args );
|
504 |
-
}
|
505 |
-
WP_Job_Manager_REST_Expect::that( method_exists( $this, $method ), $method . ' does not exist' );
|
506 |
-
return call_user_func_array( array( $this, $method ), $args );
|
507 |
-
}
|
508 |
-
|
509 |
-
/**
|
510 |
-
* Get name
|
511 |
-
*
|
512 |
-
* @return string
|
513 |
-
*/
|
514 |
-
public function get_name() {
|
515 |
-
return strtolower( get_class( $this ) );
|
516 |
-
}
|
517 |
-
|
518 |
-
/**
|
519 |
-
* Declare fields.
|
520 |
-
*
|
521 |
-
* @return array
|
522 |
-
*/
|
523 |
-
public function declare_fields() {
|
524 |
-
WP_Job_Manager_REST_Expect::should_override( __METHOD__ );
|
525 |
-
return array();
|
526 |
-
}
|
527 |
-
|
528 |
-
/**
|
529 |
-
* Get the id
|
530 |
-
*
|
531 |
-
* @return mixed|null
|
532 |
-
*/
|
533 |
-
function get_id() {
|
534 |
-
return $this->get( 'id' );
|
535 |
-
}
|
536 |
-
|
537 |
-
/**
|
538 |
-
* Set the id
|
539 |
-
*
|
540 |
-
* @param mixed $new_id The new id.
|
541 |
-
*
|
542 |
-
* @return mixed|null
|
543 |
-
*/
|
544 |
-
function set_id( $new_id ) {
|
545 |
-
return $this->set( 'id', $new_id );
|
546 |
-
}
|
547 |
-
|
548 |
-
/**
|
549 |
-
* Create from Post.
|
550 |
-
*
|
551 |
-
* @param WP_Post $post Post.
|
552 |
-
* @return WP_Job_Manager_REST_Model
|
553 |
-
* @throws WP_Job_Manager_REST_Exception If something goes wrong.
|
554 |
-
*/
|
555 |
-
public static function from_raw_data( $post ) {
|
556 |
-
$raw_post_data = $post->to_array();
|
557 |
-
$raw_meta_data = get_post_meta( $post->ID ); // assumes we are only ever adding one postmeta per key.
|
558 |
-
|
559 |
-
$flattened_meta = array();
|
560 |
-
foreach ( $raw_meta_data as $key => $value_arr ) {
|
561 |
-
$flattened_meta[ $key ] = $value_arr[0];
|
562 |
-
}
|
563 |
-
$merged_data = array_merge( $raw_post_data, $flattened_meta );
|
564 |
-
|
565 |
-
return self::create( $merged_data, array(
|
566 |
-
'deserialize' => true,
|
567 |
-
) );
|
568 |
-
}
|
569 |
-
|
570 |
-
/**
|
571 |
-
* Transform raw data to model data
|
572 |
-
*
|
573 |
-
* @param array $data Data.
|
574 |
-
* @return array
|
575 |
-
*/
|
576 |
-
public function deserialize( $data ) {
|
577 |
-
$field_declarations = $this->get_fields();
|
578 |
-
$raw_data = array();
|
579 |
-
$post_array_keys = array_keys( $data );
|
580 |
-
foreach ( $field_declarations as $declaration ) {
|
581 |
-
/**
|
582 |
-
* Declaration
|
583 |
-
*
|
584 |
-
* @var WP_Job_Manager_REST_Field_Declaration $declaration
|
585 |
-
*/
|
586 |
-
$key = $declaration->get_name();
|
587 |
-
$mapping = $declaration->get_map_from();
|
588 |
-
$value = null;
|
589 |
-
if ( in_array( $key, $post_array_keys, true ) ) {
|
590 |
-
// simplest case: we got a $key for this, so just map it.
|
591 |
-
$value = $this->deserialize_field( $declaration, $data[ $key ] );
|
592 |
-
} elseif ( in_array( $mapping, $post_array_keys, true ) ) {
|
593 |
-
// other case: we got a mapping.
|
594 |
-
$value = $this->deserialize_field( $declaration, $data[ $mapping ] );
|
595 |
-
} else {
|
596 |
-
// just provide a default.
|
597 |
-
$value = $declaration->get_default_value();
|
598 |
-
}
|
599 |
-
$raw_data[ $key ] = $declaration->cast_value( $value );
|
600 |
-
}
|
601 |
-
return $raw_data;
|
602 |
-
}
|
603 |
-
|
604 |
-
/**
|
605 |
-
* Transform Model to raw data array
|
606 |
-
*
|
607 |
-
* @param null|string $field_type Type.
|
608 |
-
*
|
609 |
-
* @return array
|
610 |
-
*/
|
611 |
-
function serialize( $field_type = null ) {
|
612 |
-
$field_values_to_insert = array();
|
613 |
-
foreach ( $this->get_fields( $field_type ) as $field_declaration ) {
|
614 |
-
/**
|
615 |
-
* Declaration
|
616 |
-
*
|
617 |
-
* @var WP_Job_Manager_REST_Field_Declaration $field_declaration
|
618 |
-
*/
|
619 |
-
$what_to_map_to = $field_declaration->get_map_from();
|
620 |
-
$value = $this->get( $field_declaration->get_name() );
|
621 |
-
$field_values_to_insert[ $what_to_map_to ] = $this->serialize_field( $field_declaration, $value );
|
622 |
-
}
|
623 |
-
|
624 |
-
return $field_values_to_insert;
|
625 |
-
}
|
626 |
-
|
627 |
-
/**
|
628 |
-
* Deserialize
|
629 |
-
*
|
630 |
-
* @param WP_Job_Manager_REST_Field_Declaration $field_declaration Declaration.
|
631 |
-
* @param mixed $value Value.
|
632 |
-
* @return mixed the deserialized value
|
633 |
-
*/
|
634 |
-
private function deserialize_field( $field_declaration, $value ) {
|
635 |
-
$deserializer = $field_declaration->get_deserializer();
|
636 |
-
if ( isset( $deserializer ) && ! empty( $deserializer ) ) {
|
637 |
-
return $this->call( $deserializer, array( $value ) );
|
638 |
-
}
|
639 |
-
return $value;
|
640 |
-
}
|
641 |
-
|
642 |
-
/**
|
643 |
-
* Serialize
|
644 |
-
*
|
645 |
-
* @param WP_Job_Manager_REST_Field_Declaration $field_declaration Declaration.
|
646 |
-
* @param mixed $value Value.
|
647 |
-
* @return mixed
|
648 |
-
* @throws WP_Job_Manager_REST_Exception If call fails.
|
649 |
-
*/
|
650 |
-
private function serialize_field( $field_declaration, $value ) {
|
651 |
-
$serializer = $field_declaration->get_serializer();
|
652 |
-
if ( isset( $serializer ) && ! empty( $serializer ) ) {
|
653 |
-
return $this->call( $serializer, array( $value ) );
|
654 |
-
}
|
655 |
-
return $value;
|
656 |
-
}
|
657 |
-
|
658 |
-
/**
|
659 |
-
* Handle Permissions for a REST Controller Action
|
660 |
-
*
|
661 |
-
* @param WP_REST_Request $request The request.
|
662 |
-
* @param string $action The action (e.g. index, create update etc).
|
663 |
-
* @return bool
|
664 |
-
*/
|
665 |
-
public function permissions_check( $request, $action ) {
|
666 |
-
$class_name = get_class( $this );
|
667 |
-
if ( isset( self::$permissions_providers_by_class_name[ $class_name ] ) ) {
|
668 |
-
$permissions_provider = self::$permissions_providers_by_class_name[ $class_name ];
|
669 |
-
return call_user_func_array( array( $permissions_provider, 'permissions_check' ), array( $request, $action ) );
|
670 |
-
}
|
671 |
-
return true;
|
672 |
-
}
|
673 |
-
|
674 |
-
/**
|
675 |
-
* Set a Proxy Permission Provider for this class
|
676 |
-
*
|
677 |
-
* @param WP_Job_Manager_REST_Interfaces_Permissions_Provider $permissions_provider PP.
|
678 |
-
* @return WP_Job_Manager_REST_Model $this
|
679 |
-
*/
|
680 |
-
public function with_permissions_provider( $permissions_provider ) {
|
681 |
-
WP_Job_Manager_REST_Expect::is_a( $permissions_provider, 'WP_Job_Manager_REST_Interfaces_Permissions_Provider' );
|
682 |
-
$class_name = get_class( $this );
|
683 |
-
self::$permissions_providers_by_class_name[ $class_name ] = $permissions_provider;
|
684 |
-
return $this;
|
685 |
-
}
|
686 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/class-wp-job-manager-rest-type.php
DELETED
@@ -1,90 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* The default Mixtape_Interfaces_Type Implementation
|
4 |
-
*
|
5 |
-
* @package Mixtape/Type
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class Mixtape_Type
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_REST_Type implements WP_Job_Manager_REST_Interfaces_Type {
|
16 |
-
/**
|
17 |
-
* The unique identifier of this type.
|
18 |
-
*
|
19 |
-
* @var string
|
20 |
-
*/
|
21 |
-
protected $identifier;
|
22 |
-
/**
|
23 |
-
* Mixtape_Type constructor.
|
24 |
-
*
|
25 |
-
* @param string $identifier The identifier.
|
26 |
-
*/
|
27 |
-
function __construct( $identifier ) {
|
28 |
-
$this->identifier = $identifier;
|
29 |
-
}
|
30 |
-
|
31 |
-
/**
|
32 |
-
* The name
|
33 |
-
*
|
34 |
-
* @return string
|
35 |
-
*/
|
36 |
-
function name() {
|
37 |
-
return $this->identifier;
|
38 |
-
}
|
39 |
-
|
40 |
-
/**
|
41 |
-
* The default value
|
42 |
-
*
|
43 |
-
* @return null
|
44 |
-
*/
|
45 |
-
function default_value() {
|
46 |
-
return null;
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Cast value to be Type
|
51 |
-
*
|
52 |
-
* @param mixed $value The value that needs casting.
|
53 |
-
*
|
54 |
-
* @return mixed
|
55 |
-
*/
|
56 |
-
function cast( $value ) {
|
57 |
-
return $value;
|
58 |
-
}
|
59 |
-
|
60 |
-
/**
|
61 |
-
* Sanitize this value
|
62 |
-
*
|
63 |
-
* @param mixed $value The value to sanitize.
|
64 |
-
*
|
65 |
-
* @return mixed
|
66 |
-
*/
|
67 |
-
function sanitize( $value ) {
|
68 |
-
return $value;
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* Get this type's JSON Schema.
|
73 |
-
*
|
74 |
-
* @return array
|
75 |
-
*/
|
76 |
-
function schema() {
|
77 |
-
return array(
|
78 |
-
'type' => $this->name(),
|
79 |
-
);
|
80 |
-
}
|
81 |
-
|
82 |
-
/**
|
83 |
-
* Get our "Any" type
|
84 |
-
*
|
85 |
-
* @return WP_Job_Manager_REST_Type
|
86 |
-
*/
|
87 |
-
static function any() {
|
88 |
-
return new self( 'any' );
|
89 |
-
}
|
90 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/controller/bundle/class-wp-job-manager-rest-controller-bundle-builder.php
DELETED
@@ -1,98 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Build a Bundle
|
4 |
-
*
|
5 |
-
* @package WP_Job_Manager_REST/Controller
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_Controller_Bundle_Builder
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_REST_Controller_Bundle_Builder implements WP_Job_Manager_REST_Interfaces_Builder {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Prefix.
|
19 |
-
*
|
20 |
-
* @var string
|
21 |
-
*/
|
22 |
-
private $bundle_prefix;
|
23 |
-
/**
|
24 |
-
* Env.
|
25 |
-
*
|
26 |
-
* @var WP_Job_Manager_REST_Environment
|
27 |
-
*/
|
28 |
-
private $environment;
|
29 |
-
/**
|
30 |
-
* Endpoint Builders.
|
31 |
-
*
|
32 |
-
* @var array
|
33 |
-
*/
|
34 |
-
private $endpoint_builders = array();
|
35 |
-
/**
|
36 |
-
* Bundle.
|
37 |
-
*
|
38 |
-
* @var WP_Job_Manager_REST_Controller_Bundle|null
|
39 |
-
*/
|
40 |
-
private $bundle = null;
|
41 |
-
|
42 |
-
/**
|
43 |
-
* WP_Job_Manager_REST_Controller_Bundle_Builder constructor.
|
44 |
-
*
|
45 |
-
* @param WP_Job_Manager_REST_Interfaces_Controller_Bundle|null $bundle Bundle.
|
46 |
-
*/
|
47 |
-
function __construct( $bundle = null ) {
|
48 |
-
$this->bundle = $bundle;
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Build it
|
53 |
-
*
|
54 |
-
* @return WP_Job_Manager_REST_Interfaces_Controller_Bundle
|
55 |
-
*/
|
56 |
-
public function build() {
|
57 |
-
if ( is_a( $this->bundle, 'WP_Job_Manager_REST_Interfaces_Controller_Bundle' ) ) {
|
58 |
-
return $this->bundle;
|
59 |
-
}
|
60 |
-
return new WP_Job_Manager_REST_Controller_Bundle( $this->bundle_prefix, $this->endpoint_builders );
|
61 |
-
}
|
62 |
-
|
63 |
-
/**
|
64 |
-
* Prefix.
|
65 |
-
*
|
66 |
-
* @param string $bundle_prefix Prefix.
|
67 |
-
* @return WP_Job_Manager_REST_Controller_Bundle_Builder $this
|
68 |
-
*/
|
69 |
-
public function with_prefix( $bundle_prefix ) {
|
70 |
-
$this->bundle_prefix = $bundle_prefix;
|
71 |
-
return $this;
|
72 |
-
}
|
73 |
-
|
74 |
-
/**
|
75 |
-
* Env.
|
76 |
-
*
|
77 |
-
* @param WP_Job_Manager_REST_Environment $env Env.
|
78 |
-
* @return WP_Job_Manager_REST_Controller_Bundle_Builder $this
|
79 |
-
*/
|
80 |
-
public function with_environment( $env ) {
|
81 |
-
$this->environment = $env;
|
82 |
-
return $this;
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Endpoint.
|
87 |
-
*
|
88 |
-
* Adds a new WP_Job_Manager_REST_Controller_Builder to our builders and returns it for further setup.
|
89 |
-
*
|
90 |
-
* @param null|WP_Job_Manager_REST_Interfaces_Controller $controller_object The (optional) controller object.
|
91 |
-
* @return WP_Job_Manager_REST_Controller_Bundle_Builder $this
|
92 |
-
*/
|
93 |
-
public function add_endpoint( $controller_object = null ) {
|
94 |
-
WP_Job_Manager_REST_Expect::is_a( $controller_object, 'WP_Job_Manager_REST_Interfaces_Controller' );
|
95 |
-
$this->endpoint_builders[] = $controller_object;
|
96 |
-
return $this;
|
97 |
-
}
|
98 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-action.php
DELETED
@@ -1,166 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* An Acton that is part of a Route.
|
4 |
-
*
|
5 |
-
* @package WP_Job_Manager_REST/Controller
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_Controller_Action
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_REST_Controller_Action {
|
16 |
-
/**
|
17 |
-
* Permitted actions
|
18 |
-
*
|
19 |
-
* @var array
|
20 |
-
*/
|
21 |
-
private $actions_to_http_methods = array(
|
22 |
-
'index' => WP_REST_Server::READABLE,
|
23 |
-
'show' => WP_REST_Server::READABLE,
|
24 |
-
'create' => WP_REST_Server::CREATABLE,
|
25 |
-
'update' => WP_REST_Server::EDITABLE,
|
26 |
-
'delete' => WP_REST_Server::DELETABLE,
|
27 |
-
'any' => WP_REST_Server::ALLMETHODS,
|
28 |
-
);
|
29 |
-
|
30 |
-
/**
|
31 |
-
* The action name
|
32 |
-
*
|
33 |
-
* @var string
|
34 |
-
*/
|
35 |
-
private $action_name;
|
36 |
-
|
37 |
-
/**
|
38 |
-
* The Handler
|
39 |
-
*
|
40 |
-
* @var null|array|string
|
41 |
-
*/
|
42 |
-
private $handler;
|
43 |
-
|
44 |
-
/**
|
45 |
-
* The Permissions Callback
|
46 |
-
*
|
47 |
-
* @var null|array|string
|
48 |
-
*/
|
49 |
-
private $permission_callback;
|
50 |
-
|
51 |
-
/**
|
52 |
-
* The Args
|
53 |
-
*
|
54 |
-
* @var null|array|string
|
55 |
-
*/
|
56 |
-
private $args;
|
57 |
-
|
58 |
-
/**
|
59 |
-
* WP_Job_Manager_REST_Controller_Action constructor.
|
60 |
-
*
|
61 |
-
* @param WP_Job_Manager_REST_Controller $controller Controller.
|
62 |
-
* @param string $action_name The action Name.
|
63 |
-
*/
|
64 |
-
public function __construct( $controller, $action_name ) {
|
65 |
-
$is_known_action = in_array( $action_name, array_keys( $this->actions_to_http_methods ), true );
|
66 |
-
WP_Job_Manager_REST_Expect::that( $is_known_action, 'Unknown method: ' . $action_name );
|
67 |
-
|
68 |
-
$this->controller = $controller;
|
69 |
-
$this->action_name = $action_name;
|
70 |
-
$this->handler = null;
|
71 |
-
$this->args = null;
|
72 |
-
$this->permission_callback = null;
|
73 |
-
}
|
74 |
-
|
75 |
-
/**
|
76 |
-
* Get Name
|
77 |
-
*
|
78 |
-
* @return string
|
79 |
-
*/
|
80 |
-
public function name() {
|
81 |
-
return $this->action_name;
|
82 |
-
}
|
83 |
-
|
84 |
-
/**
|
85 |
-
* Set Permissions
|
86 |
-
*
|
87 |
-
* @param mixed $callable A Callable.
|
88 |
-
*
|
89 |
-
* @return WP_Job_Manager_REST_Controller_Action
|
90 |
-
*/
|
91 |
-
public function permissions( $callable ) {
|
92 |
-
$this->permission_callback = $callable;
|
93 |
-
return $this;
|
94 |
-
}
|
95 |
-
|
96 |
-
/**
|
97 |
-
* Set Handler
|
98 |
-
*
|
99 |
-
* @param mixed $callable A Callable.
|
100 |
-
*
|
101 |
-
* @return WP_Job_Manager_REST_Controller_Action
|
102 |
-
*/
|
103 |
-
public function callback( $callable ) {
|
104 |
-
$this->handler = $callable;
|
105 |
-
return $this;
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Set Handler
|
110 |
-
*
|
111 |
-
* @param mixed $callable A Callable.
|
112 |
-
*
|
113 |
-
* @return WP_Job_Manager_REST_Controller_Action
|
114 |
-
*/
|
115 |
-
public function args( $callable ) {
|
116 |
-
$this->args = $callable;
|
117 |
-
return $this;
|
118 |
-
}
|
119 |
-
|
120 |
-
/**
|
121 |
-
* Used in register rest route
|
122 |
-
*
|
123 |
-
* @return array
|
124 |
-
*/
|
125 |
-
public function as_array() {
|
126 |
-
$callable_func = $this->expect_callable( $this->handler );
|
127 |
-
if ( null !== $this->permission_callback ) {
|
128 |
-
$permission_callback = $this->expect_callable( $this->permission_callback );
|
129 |
-
} else {
|
130 |
-
$permission_callback = $this->expect_callable( array( $this->controller, $this->action_name . '_permissions_check' ) );
|
131 |
-
}
|
132 |
-
|
133 |
-
if ( null !== $this->args ) {
|
134 |
-
$args = call_user_func( $this->expect_callable( $this->args ), $this->actions_to_http_methods[ $this->action_name ] );
|
135 |
-
} else {
|
136 |
-
$args = $this->controller->get_endpoint_args_for_item_schema( $this->actions_to_http_methods[ $this->action_name ] );
|
137 |
-
}
|
138 |
-
|
139 |
-
$result = array(
|
140 |
-
'methods' => $this->actions_to_http_methods[ $this->action_name ],
|
141 |
-
'callback' => $callable_func,
|
142 |
-
'permission_callback' => $permission_callback,
|
143 |
-
'args' => $args,
|
144 |
-
);
|
145 |
-
|
146 |
-
return $result;
|
147 |
-
}
|
148 |
-
|
149 |
-
/**
|
150 |
-
* Expect a callable
|
151 |
-
*
|
152 |
-
* @param mixed $callable_func A Callable.
|
153 |
-
* @return array
|
154 |
-
* @throws WP_Job_Manager_REST_Exception If not a callable.
|
155 |
-
*/
|
156 |
-
private function expect_callable( $callable_func ) {
|
157 |
-
if ( ! is_callable( $callable_func ) ) {
|
158 |
-
// Check if controller has a public method called $callable_func.
|
159 |
-
if ( is_string( $callable_func ) && method_exists( $this->controller, $callable_func ) ) {
|
160 |
-
return array( $this->controller, $callable_func );
|
161 |
-
}
|
162 |
-
WP_Job_Manager_REST_Expect::that( is_callable( $callable_func ), 'Callable Expected: $callable_func' );
|
163 |
-
}
|
164 |
-
return $callable_func;
|
165 |
-
}
|
166 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-bundle.php
DELETED
@@ -1,99 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* A Collection of Controllers, under the same prefix
|
4 |
-
*
|
5 |
-
* @package WP_Job_Manager_REST/Controller
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_Controller_Bundle
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_REST_Controller_Bundle implements WP_Job_Manager_REST_Interfaces_Controller_Bundle {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* The prefix of this bundle (required)
|
19 |
-
*
|
20 |
-
* @var string|null
|
21 |
-
*/
|
22 |
-
protected $prefix = null;
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Collection of Mixtape_Rest_Api_Controller subclasses
|
26 |
-
*
|
27 |
-
* @var array
|
28 |
-
*/
|
29 |
-
protected $endpoints = array();
|
30 |
-
/**
|
31 |
-
* Our Endpoint Builders
|
32 |
-
*
|
33 |
-
* @var array
|
34 |
-
*/
|
35 |
-
private $endpoint_builders;
|
36 |
-
/**
|
37 |
-
* Environment.
|
38 |
-
*
|
39 |
-
* @var WP_Job_Manager_REST_Environment
|
40 |
-
*/
|
41 |
-
private $environment;
|
42 |
-
|
43 |
-
/**
|
44 |
-
* WP_Job_Manager_REST_Controller_Bundle_Definition constructor.
|
45 |
-
*
|
46 |
-
* @param string $bundle_prefix Prefix.
|
47 |
-
* @param array $endpoints Builders.
|
48 |
-
*/
|
49 |
-
function __construct( $bundle_prefix, $endpoints ) {
|
50 |
-
$this->prefix = $bundle_prefix;
|
51 |
-
$this->endpoints = $endpoints;
|
52 |
-
}
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Register this bundle with the environment.
|
56 |
-
*
|
57 |
-
* @param WP_Job_Manager_REST_Environment $environment The Environment.
|
58 |
-
* @return WP_Job_Manager_REST_Controller_Bundle $this
|
59 |
-
* @throws WP_Job_Manager_REST_Exception When no prefix is defined.
|
60 |
-
*/
|
61 |
-
function register( $environment ) {
|
62 |
-
WP_Job_Manager_REST_Expect::that( null !== $this->prefix, 'prefix should be defined' );
|
63 |
-
$this->environment = $environment;
|
64 |
-
/**
|
65 |
-
* Add/remove endpoints. Useful for extensions
|
66 |
-
*
|
67 |
-
* @param array $endpoints An array of WP_Job_Manager_REST_Interfaces_Controller
|
68 |
-
* @param $bundle WP_Job_Manager_REST_Controller_Bundle The bundle instance.
|
69 |
-
*
|
70 |
-
* @return array
|
71 |
-
*/
|
72 |
-
$endpoints = (array) $this->environment->get_event_dispatcher()->apply_filters(
|
73 |
-
'rest_api_controller_bundle_get_endpoints',
|
74 |
-
$this->endpoints,
|
75 |
-
$this
|
76 |
-
);
|
77 |
-
|
78 |
-
foreach ( $endpoints as $endpoint ) {
|
79 |
-
/**
|
80 |
-
* Controller
|
81 |
-
*
|
82 |
-
* @var WP_Job_Manager_REST_Interfaces_Controller
|
83 |
-
*/
|
84 |
-
$endpoint->register( $this, $this->environment );
|
85 |
-
}
|
86 |
-
|
87 |
-
return $this;
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Get Prefix.
|
92 |
-
*
|
93 |
-
* @return string
|
94 |
-
*/
|
95 |
-
function get_prefix() {
|
96 |
-
return $this->prefix;
|
97 |
-
}
|
98 |
-
}
|
99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-crud.php
DELETED
@@ -1,199 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Classic Create, Read, Update, Delete Controller
|
4 |
-
*
|
5 |
-
* @package WP_Job_Manager_REST/Controller
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
} // End if().
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_Controller_CRUD
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_REST_Controller_CRUD extends WP_Job_Manager_REST_Controller_Model implements WP_Job_Manager_REST_Interfaces_Controller {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Setup
|
19 |
-
*/
|
20 |
-
public function setup() {
|
21 |
-
$this->add_route( '/' )
|
22 |
-
->add_action( $this->action( 'index', array( $this, 'get_items' ) ) )
|
23 |
-
->add_action( $this->action( 'create', array( $this, 'create_item' ) ) );
|
24 |
-
|
25 |
-
$this->add_route( '/(?P<id>\d+)' )
|
26 |
-
->add_action( $this->action( 'show', array( $this, 'get_item' ) ) )
|
27 |
-
->add_action( $this->action( 'update', array( $this, 'update_item' ) ) )
|
28 |
-
->add_action( $this->action( 'delete', array( $this, 'delete_item' ) ) );
|
29 |
-
}
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Get Items.
|
33 |
-
*
|
34 |
-
* @param WP_REST_Request $request Request.
|
35 |
-
* @return WP_REST_Response
|
36 |
-
*/
|
37 |
-
public function get_items( $request ) {
|
38 |
-
$item_id = isset( $request['id'] ) ? absint( $request['id'] ) : null;
|
39 |
-
|
40 |
-
if ( null === $item_id ) {
|
41 |
-
$models = $this->get_model_data_store()->get_entities();
|
42 |
-
$data = $this->prepare_dto( $models );
|
43 |
-
return $this->ok( $data );
|
44 |
-
}
|
45 |
-
|
46 |
-
$model = $this->model_prototype->get_data_store()->get_entity( $item_id );
|
47 |
-
if ( empty( $model ) ) {
|
48 |
-
return $this->not_found( __( 'Model not found' ) );
|
49 |
-
}
|
50 |
-
|
51 |
-
return $this->ok( $this->prepare_dto( $model ) );
|
52 |
-
}
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Get Item
|
56 |
-
*
|
57 |
-
* @param WP_REST_Request $request Request.
|
58 |
-
* @return WP_REST_Response
|
59 |
-
*/
|
60 |
-
public function get_item( $request ) {
|
61 |
-
return $this->get_items( $request );
|
62 |
-
}
|
63 |
-
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Create Item
|
67 |
-
*
|
68 |
-
* @param WP_REST_Request $request Request.
|
69 |
-
* @return WP_REST_Response
|
70 |
-
*/
|
71 |
-
public function create_item( $request ) {
|
72 |
-
$is_update = false;
|
73 |
-
return $this->create_or_update( $request, $is_update );
|
74 |
-
}
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Update Item
|
78 |
-
*
|
79 |
-
* @param WP_REST_Request $request Request.
|
80 |
-
* @return WP_REST_Response
|
81 |
-
*/
|
82 |
-
public function update_item( $request ) {
|
83 |
-
$is_update = true;
|
84 |
-
return $this->create_or_update( $request, $is_update );
|
85 |
-
}
|
86 |
-
|
87 |
-
/**
|
88 |
-
* Create Or Update Item
|
89 |
-
*
|
90 |
-
* @param WP_REST_Request $request Request.
|
91 |
-
* @param bool $is_update Is Update.
|
92 |
-
*
|
93 |
-
* @return WP_REST_Response
|
94 |
-
*/
|
95 |
-
protected function create_or_update( $request, $is_update = false ) {
|
96 |
-
$model_to_update = null;
|
97 |
-
if ( $is_update ) {
|
98 |
-
$id = isset( $request['id'] ) ? absint( $request['id'] ) : null;
|
99 |
-
if ( ! empty( $id ) ) {
|
100 |
-
$model_to_update = $this->model_prototype->get_data_store()->get_entity( $id );
|
101 |
-
if ( empty( $model_to_update ) ) {
|
102 |
-
return $this->not_found( 'Model does not exist' );
|
103 |
-
}
|
104 |
-
}
|
105 |
-
}
|
106 |
-
|
107 |
-
if ( $is_update && $model_to_update ) {
|
108 |
-
$model = $model_to_update->update_from_array( $request->get_params(), $is_update );
|
109 |
-
} else {
|
110 |
-
$model = $this->get_model_prototype()->new_from_array( $request->get_params() );
|
111 |
-
}
|
112 |
-
|
113 |
-
if ( is_wp_error( $model ) ) {
|
114 |
-
$wp_err = $model;
|
115 |
-
return $this->bad_request( $wp_err );
|
116 |
-
}
|
117 |
-
|
118 |
-
$validation = $model->validate();
|
119 |
-
if ( is_wp_error( $validation ) ) {
|
120 |
-
return $this->bad_request( $validation );
|
121 |
-
}
|
122 |
-
|
123 |
-
$id_or_error = $this->model_data_store->upsert( $model );
|
124 |
-
|
125 |
-
if ( is_wp_error( $id_or_error ) ) {
|
126 |
-
return $this->bad_request( $id_or_error );
|
127 |
-
}
|
128 |
-
|
129 |
-
$dto = $this->prepare_dto( array(
|
130 |
-
'id' => absint( $id_or_error ),
|
131 |
-
) );
|
132 |
-
|
133 |
-
return $is_update ? $this->ok( $dto ) : $this->created( $dto );
|
134 |
-
}
|
135 |
-
|
136 |
-
/**
|
137 |
-
* Delete an Item
|
138 |
-
*
|
139 |
-
* @param WP_REST_Request $request Request.
|
140 |
-
* @return WP_REST_Response
|
141 |
-
*/
|
142 |
-
public function delete_item( $request ) {
|
143 |
-
$id = isset( $request['id'] ) ? absint( $request['id'] ) : null;
|
144 |
-
if ( empty( $id ) ) {
|
145 |
-
return $this->bad_request( 'No Model ID provided' );
|
146 |
-
}
|
147 |
-
$model = $this->model_prototype->get_data_store()->get_entity( $id );
|
148 |
-
if ( null === $model ) {
|
149 |
-
return $this->not_found( 'Model does not exist' );
|
150 |
-
}
|
151 |
-
$result = $this->model_data_store->delete( $model );
|
152 |
-
return $this->ok( $result );
|
153 |
-
}
|
154 |
-
|
155 |
-
/**
|
156 |
-
* Model To Dto
|
157 |
-
*
|
158 |
-
* @param WP_Job_Manager_REST_Interfaces_Model $model The Model.
|
159 |
-
* @return array
|
160 |
-
*/
|
161 |
-
protected function model_to_dto( $model ) {
|
162 |
-
$result = parent::model_to_dto( $model );
|
163 |
-
$result['_links'] = $this->add_links( $model );
|
164 |
-
return $result;
|
165 |
-
}
|
166 |
-
|
167 |
-
/**
|
168 |
-
* Add Links
|
169 |
-
*
|
170 |
-
* @param WP_Job_Manager_REST_Interfaces_Model $model Model.
|
171 |
-
* @return array
|
172 |
-
*/
|
173 |
-
protected function add_links( $model ) {
|
174 |
-
$base_url = rest_url() . $this->controller_bundle->get_prefix() . $this->base . '/';
|
175 |
-
|
176 |
-
$result = array(
|
177 |
-
'collection' => array(
|
178 |
-
array(
|
179 |
-
'href' => esc_url( $base_url ),
|
180 |
-
),
|
181 |
-
),
|
182 |
-
);
|
183 |
-
if ( $model->get_id() ) {
|
184 |
-
$result['self'] = array(
|
185 |
-
array(
|
186 |
-
'href' => esc_url( $base_url . $model->get_id() ),
|
187 |
-
),
|
188 |
-
);
|
189 |
-
}
|
190 |
-
if ( $model->has( 'author' ) ) {
|
191 |
-
$result['author'] = array(
|
192 |
-
array(
|
193 |
-
'href' => esc_url( rest_url() . 'wp/v2/users/' . $model->get( 'author' ) ),
|
194 |
-
),
|
195 |
-
);
|
196 |
-
}
|
197 |
-
return $result;
|
198 |
-
}
|
199 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-extension.php
DELETED
@@ -1,83 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Controller-like class used for extending existing object types (e.g. post)
|
4 |
-
* With custom fields. Needs a model definition that will provide the extra fields.
|
5 |
-
*
|
6 |
-
* @package WP_Job_Manager_REST/Controller
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Class WP_Job_Manager_REST_Controller_Extension
|
11 |
-
*/
|
12 |
-
class WP_Job_Manager_REST_Controller_Extension implements WP_Job_Manager_REST_Interfaces_Registrable {
|
13 |
-
/**
|
14 |
-
* Environment
|
15 |
-
*
|
16 |
-
* @var WP_Job_Manager_REST_Environment
|
17 |
-
*/
|
18 |
-
private $environment;
|
19 |
-
/**
|
20 |
-
* Object to extend
|
21 |
-
*
|
22 |
-
* @var string
|
23 |
-
*/
|
24 |
-
private $object_to_extend;
|
25 |
-
/**
|
26 |
-
* Model def.
|
27 |
-
*
|
28 |
-
* @var WP_Job_Manager_REST_Model_Definition
|
29 |
-
*/
|
30 |
-
private $model_definition;
|
31 |
-
/**
|
32 |
-
* Model Definition name, This should be a valid Model definition at registration time, otherwise register will throw
|
33 |
-
*
|
34 |
-
* @var string
|
35 |
-
*/
|
36 |
-
private $model_definition_name;
|
37 |
-
|
38 |
-
/**
|
39 |
-
* WP_Job_Manager_REST_Controller_Extension constructor.
|
40 |
-
*
|
41 |
-
* @param string $object_to_extend Post type.
|
42 |
-
* @param string $model_definition_name Model Definition name.
|
43 |
-
*/
|
44 |
-
function __construct( $object_to_extend, $model_definition_name ) {
|
45 |
-
$this->model_definition_name = $model_definition_name;
|
46 |
-
$this->object_to_extend = $object_to_extend;
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Register This Controller
|
51 |
-
*
|
52 |
-
* @param WP_Job_Manager_REST_Environment $environment The Environment to use.
|
53 |
-
* @throws WP_Job_Manager_REST_Exception Throws.
|
54 |
-
*
|
55 |
-
* @return bool|WP_Error true if valid otherwise error.
|
56 |
-
*/
|
57 |
-
function register( $environment ) {
|
58 |
-
$this->environment = $environment;
|
59 |
-
$this->model_definition = $this->environment->model( $this->model_definition_name );
|
60 |
-
if ( ! $this->model_definition ) {
|
61 |
-
return new WP_Error( 'model-not-found' );
|
62 |
-
}
|
63 |
-
$fields = $this->model_definition->get_fields();
|
64 |
-
foreach ( $fields as $field ) {
|
65 |
-
$this->register_field( $field );
|
66 |
-
}
|
67 |
-
|
68 |
-
return true;
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* Register Field
|
73 |
-
*
|
74 |
-
* @param WP_Job_Manager_REST_Field_Declaration $field Field.
|
75 |
-
*/
|
76 |
-
private function register_field( $field ) {
|
77 |
-
register_rest_field( $this->object_to_extend, $field->get_data_transfer_name(), array(
|
78 |
-
'get_callback' => $field->get_reader(),
|
79 |
-
'update_callback' => $field->get_updater(),
|
80 |
-
'schema' => $field->as_item_schema_property(),
|
81 |
-
) );
|
82 |
-
}
|
83 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-model.php
DELETED
@@ -1,165 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* A Controller that is related to a Model Declaration.
|
4 |
-
*
|
5 |
-
* @package WP_Job_Manager_REST/Controller
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_Controller_Model
|
14 |
-
* Knows about models
|
15 |
-
*/
|
16 |
-
class WP_Job_Manager_REST_Controller_Model extends WP_Job_Manager_REST_Controller implements WP_Job_Manager_REST_Interfaces_Controller {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* The Factory
|
20 |
-
*
|
21 |
-
* @var WP_Job_Manager_REST_Model
|
22 |
-
*/
|
23 |
-
protected $model_prototype;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* The data Store
|
27 |
-
*
|
28 |
-
* @var WP_Job_Manager_REST_Interfaces_Data_Store
|
29 |
-
*/
|
30 |
-
protected $model_data_store;
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Model Definition Name
|
34 |
-
*
|
35 |
-
* @var string
|
36 |
-
*/
|
37 |
-
private $model_class_name;
|
38 |
-
|
39 |
-
/**
|
40 |
-
* WP_Job_Manager_REST_Controller_Model constructor.
|
41 |
-
*
|
42 |
-
* @param string $base The baser.
|
43 |
-
* @param string $model_class_name A Definition or a definition name.
|
44 |
-
*/
|
45 |
-
public function __construct( $base, $model_class_name ) {
|
46 |
-
$this->base = $base;
|
47 |
-
$this->model_class_name = $model_class_name;
|
48 |
-
}
|
49 |
-
|
50 |
-
/**
|
51 |
-
* Get our model factory
|
52 |
-
*
|
53 |
-
* @return WP_Job_Manager_REST_Model
|
54 |
-
*/
|
55 |
-
protected function get_model_prototype() {
|
56 |
-
return $this->model_prototype;
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Register this controller, initialize model-related object fields.
|
61 |
-
*
|
62 |
-
* @param WP_Job_Manager_REST_Controller_Bundle $bundle The bundle to use.
|
63 |
-
* @param WP_Job_Manager_REST_Environment $environment The Environment.
|
64 |
-
*
|
65 |
-
* @throws WP_Job_Manager_REST_Exception If an invalid model is provided.
|
66 |
-
*
|
67 |
-
* @return bool|WP_Error true if valid otherwise error.
|
68 |
-
*/
|
69 |
-
public function register( $bundle, $environment ) {
|
70 |
-
$this->model_prototype = $environment->model( $this->model_class_name );
|
71 |
-
$this->model_data_store = $this->model_prototype->get_data_store();
|
72 |
-
return parent::register( $bundle, $environment );
|
73 |
-
}
|
74 |
-
|
75 |
-
/**
|
76 |
-
* Retrieves the item's schema, conforming to JSON Schema.
|
77 |
-
*
|
78 |
-
* In our case, it gets fields/types from our definition's declared fields.
|
79 |
-
*
|
80 |
-
* @access public
|
81 |
-
*
|
82 |
-
* @return array Item schema data.
|
83 |
-
*/
|
84 |
-
public function get_item_schema() {
|
85 |
-
$model_definition = $this->get_model_prototype();
|
86 |
-
$fields = $model_definition->get_fields();
|
87 |
-
$properties = array();
|
88 |
-
$required = array();
|
89 |
-
foreach ( $fields as $field_declaration ) {
|
90 |
-
/**
|
91 |
-
* Our declaration
|
92 |
-
*
|
93 |
-
* @var WP_Job_Manager_REST_Field_Declaration $field_declaration
|
94 |
-
*/
|
95 |
-
$properties[ $field_declaration->get_data_transfer_name() ] = $field_declaration->as_item_schema_property();
|
96 |
-
if ( $field_declaration->is_required() ) {
|
97 |
-
$required[] = $field_declaration->get_data_transfer_name();
|
98 |
-
}
|
99 |
-
}
|
100 |
-
$schema = array(
|
101 |
-
'$schema' => 'http://json-schema.org/schema#',
|
102 |
-
'title' => $model_definition->get_name(),
|
103 |
-
'type' => 'object',
|
104 |
-
'properties' => (array) $this->environment()->get_event_dispatcher()->apply_filters( 'rest_api_schema_properties', $properties, $this->get_model_prototype() ),
|
105 |
-
);
|
106 |
-
|
107 |
-
if ( ! empty( $required ) ) {
|
108 |
-
$schema['required'] = $required;
|
109 |
-
}
|
110 |
-
|
111 |
-
return $this->add_additional_fields_schema( $schema );
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* Get Model DataStore
|
116 |
-
*
|
117 |
-
* @return WP_Job_Manager_REST_Interfaces_Data_Store
|
118 |
-
*/
|
119 |
-
protected function get_model_data_store() {
|
120 |
-
return $this->model_data_store;
|
121 |
-
}
|
122 |
-
|
123 |
-
/**
|
124 |
-
* Generic Permissions Check.
|
125 |
-
*
|
126 |
-
* @param WP_REST_Request $request Request.
|
127 |
-
* @param string $action One of (index, show, create, update, delete).
|
128 |
-
* @return bool
|
129 |
-
*/
|
130 |
-
public function permissions_check( $request, $action = 'any' ) {
|
131 |
-
return $this->get_model_prototype()->permissions_check( $request, $action );
|
132 |
-
}
|
133 |
-
|
134 |
-
/**
|
135 |
-
* Prepare Entity to be a DTO
|
136 |
-
*
|
137 |
-
* @param array|WP_Job_Manager_REST_Model_Collection|WP_Job_Manager_REST_Interfaces_Model $entity The Entity.
|
138 |
-
* @return array
|
139 |
-
*/
|
140 |
-
protected function prepare_dto( $entity ) {
|
141 |
-
if ( is_a( $entity, 'WP_Job_Manager_REST_Model_Collection' ) ) {
|
142 |
-
$results = array();
|
143 |
-
foreach ( $entity->get_items() as $model ) {
|
144 |
-
$results[] = $this->model_to_dto( $model );
|
145 |
-
}
|
146 |
-
return $results;
|
147 |
-
}
|
148 |
-
|
149 |
-
if ( is_a( $entity, 'WP_Job_Manager_REST_Interfaces_Model' ) ) {
|
150 |
-
return $this->model_to_dto( $entity );
|
151 |
-
}
|
152 |
-
|
153 |
-
return $entity;
|
154 |
-
}
|
155 |
-
|
156 |
-
/**
|
157 |
-
* Map a model to a Data Transfer Object (plain array)
|
158 |
-
*
|
159 |
-
* @param WP_Job_Manager_REST_Interfaces_Model $model The Model.
|
160 |
-
* @return array
|
161 |
-
*/
|
162 |
-
protected function model_to_dto( $model ) {
|
163 |
-
return $model->to_dto();
|
164 |
-
}
|
165 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-route.php
DELETED
@@ -1,90 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* A Route that is part of a controller.
|
4 |
-
*
|
5 |
-
* @package WP_Job_Manager_REST/Controller
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_Controller_Route
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_REST_Controller_Route {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Our pattern
|
19 |
-
*
|
20 |
-
* @var string
|
21 |
-
*/
|
22 |
-
private $pattern;
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Our Handlers
|
26 |
-
*
|
27 |
-
* @var array
|
28 |
-
*/
|
29 |
-
private $actions;
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Our Controller
|
33 |
-
*
|
34 |
-
* @var WP_Job_Manager_REST_Controller
|
35 |
-
*/
|
36 |
-
private $controller;
|
37 |
-
|
38 |
-
/**
|
39 |
-
* HTTP Methods
|
40 |
-
*
|
41 |
-
* @var array
|
42 |
-
*/
|
43 |
-
private $http_methods;
|
44 |
-
|
45 |
-
/**
|
46 |
-
* WP_Job_Manager_REST_Controller_Route constructor.
|
47 |
-
*
|
48 |
-
* @param WP_Job_Manager_REST_Controller $controller A Controller.
|
49 |
-
* @param string $pattern Pattern.
|
50 |
-
*/
|
51 |
-
public function __construct( $controller, $pattern ) {
|
52 |
-
$this->controller = $controller;
|
53 |
-
$this->pattern = $pattern;
|
54 |
-
$this->actions = array();
|
55 |
-
$this->http_methods = explode( ', ', WP_REST_Server::ALLMETHODS );
|
56 |
-
}
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Add/Get an action
|
60 |
-
*
|
61 |
-
* @param WP_Job_Manager_REST_Controller_Action $action Action.
|
62 |
-
*
|
63 |
-
* @return WP_Job_Manager_REST_Controller_Route
|
64 |
-
*/
|
65 |
-
public function add_action( $action ) {
|
66 |
-
$this->actions[ $action->name() ] = $action;
|
67 |
-
return $this;
|
68 |
-
}
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Gets Route info to use in Register rest route.
|
72 |
-
*
|
73 |
-
* @throws WP_Job_Manager_REST_Exception If invalid callable.
|
74 |
-
* @return array
|
75 |
-
*/
|
76 |
-
public function as_array() {
|
77 |
-
$result = array();
|
78 |
-
$result['pattern'] = $this->pattern;
|
79 |
-
$result['actions'] = array();
|
80 |
-
foreach ( $this->actions as $action => $route_action ) {
|
81 |
-
/**
|
82 |
-
* The route action.
|
83 |
-
*
|
84 |
-
* @var WP_Job_Manager_REST_Controller_Action $route_action
|
85 |
-
*/
|
86 |
-
$result['actions'][] = $route_action->as_array();
|
87 |
-
}
|
88 |
-
return $result;
|
89 |
-
}
|
90 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/controller/class-wp-job-manager-rest-controller-settings.php
DELETED
@@ -1,86 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Controller for handling settings
|
4 |
-
*
|
5 |
-
* @package WP_Job_Manager_REST/Controller
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_Controller_Settings
|
14 |
-
*/
|
15 |
-
class WP_Job_Manager_REST_Controller_Settings extends WP_Job_Manager_REST_Controller_Model {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Setup
|
19 |
-
*/
|
20 |
-
public function setup() {
|
21 |
-
$this->add_route()
|
22 |
-
->add_action( $this->action( 'index', array( $this, 'get_items' ) ) )
|
23 |
-
->add_action( $this->action( 'update', array( $this, 'create_item' ) ) );
|
24 |
-
}
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Get Settings
|
28 |
-
*
|
29 |
-
* @param WP_REST_Request $request The request.
|
30 |
-
* @return WP_REST_Response
|
31 |
-
*/
|
32 |
-
public function get_items( $request ) {
|
33 |
-
$model = $this->model_prototype->get_data_store()->get_entity( null );
|
34 |
-
if ( empty( $model ) ) {
|
35 |
-
return $this->not_found( __( 'Settings not found' ) );
|
36 |
-
}
|
37 |
-
|
38 |
-
return $this->ok( $this->prepare_dto( $model ) );
|
39 |
-
}
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Create or Update settings.
|
43 |
-
*
|
44 |
-
* @param WP_REST_Request $request Request.
|
45 |
-
* @return WP_REST_Response
|
46 |
-
*/
|
47 |
-
public function create_item( $request ) {
|
48 |
-
return $this->create_or_update( $request );
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Create or Update a Model
|
53 |
-
*
|
54 |
-
* @param WP_REST_Request $request Request.
|
55 |
-
* @return WP_REST_Response
|
56 |
-
*/
|
57 |
-
protected function create_or_update( $request ) {
|
58 |
-
$is_update = $request->get_method() !== 'POST';
|
59 |
-
$model_to_update = $this->model_prototype->get_data_store()->get_entity( null );
|
60 |
-
if ( empty( $model_to_update ) ) {
|
61 |
-
return $this->not_found( 'Model does not exist' );
|
62 |
-
}
|
63 |
-
|
64 |
-
$model = $model_to_update->update_from_array( $request->get_params(), true );
|
65 |
-
|
66 |
-
if ( is_wp_error( $model ) ) {
|
67 |
-
return $this->bad_request( $model );
|
68 |
-
}
|
69 |
-
|
70 |
-
$validation = $model->validate();
|
71 |
-
if ( is_wp_error( $validation ) ) {
|
72 |
-
return $this->bad_request( $validation );
|
73 |
-
}
|
74 |
-
|
75 |
-
$id_or_error = $this->model_data_store->upsert( $model );
|
76 |
-
|
77 |
-
if ( is_wp_error( $id_or_error ) ) {
|
78 |
-
return $this->bad_request( $id_or_error );
|
79 |
-
}
|
80 |
-
|
81 |
-
$model = $this->model_prototype->get_data_store()->get_entity( null );
|
82 |
-
$dto = $this->prepare_dto( $model );
|
83 |
-
|
84 |
-
return $is_update ? $this->ok( $dto ) : $this->created( $dto );
|
85 |
-
}
|
86 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-abstract.php
DELETED
@@ -1,72 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Data Store Abstract
|
4 |
-
*
|
5 |
-
* @package WP_Job_Manager_REST/Data
|
6 |
-
*/
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class WP_Job_Manager_REST_Data_Store_Abstract
|
14 |
-
* An abstract Data_Store class that contains a model factory
|
15 |
-
*/
|
16 |
-
abstract class WP_Job_Manager_REST_Data_Store_Abstract implements WP_Job_Manager_REST_Interfaces_Data_Store {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Definition
|
20 |
-
*
|
21 |
-
* @var WP_Job_Manager_REST_Model
|
22 |
-
*/
|
23 |
-
protected $model_prototype;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Type Serializers
|
27 |
-
*
|
28 |
-
* @var array
|
29 |
-
*/
|
30 |
-
private $type_serializers;
|
31 |
-
|
32 |
-
/**
|
33 |
-
* WP_Job_Manager_REST_Data_Store_Abstract constructor.
|
34 |
-
*
|
35 |
-
* @param null|WP_Job_Manager_REST_Model $model_prototype Def.
|
36 |
-
* @param array $args Args.
|
37 |
-
*/
|
38 |
-
public function __construct( $model_prototype = null, $args = array() ) {
|
39 |
-
$this->type_serializers = array();
|
40 |
-
$this->args = $args;
|
41 |
-
WP_Job_Manager_REST_Expect::is_a( $model_prototype, 'WP_Job_Manager_REST_Interfaces_Model' );
|
42 |
-
$this->set_model_factory( $model_prototype );
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Set Definition
|
47 |
-
*
|
48 |
-
* @param WP_Job_Manager_REST_Model $factory Def.
|
49 |
-
*
|
50 |
-
* @return WP_Job_Manager_REST_Interfaces_Data_Store $this
|
51 |
-
*/
|
52 |
-
private function set_model_factory( $factory ) {
|
53 |
-
$this->model_prototype = $factory;
|
54 |
-
$this->configure();
|
55 |
-
return $this;
|
56 |
-
}
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Configure
|
60 |
-
*/
|
61 |
-
protected function configure() {
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Get Definition
|
66 |
-
*
|
67 |
-
* @return WP_Job_Manager_REST_Model
|
68 |
-
*/
|
69 |
-
public function get_model_prototype() {
|
70 |
-
return $this->model_prototype;
|
71 |
-
}
|
72 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/wpjm_rest/data/store/class-wp-job-manager-rest-data-store-customposttype.php
CHANGED
File without changes
|