feature: integrate WP job manager#1847
Conversation
WalkthroughThis PR introduces a new WP Job Manager integration for WPUF, adding a form template, metadata mapping handler, and integration bootstrap class. The changes extend the integration loader and taxonomy system to conditionally support job listings when WP Job Manager is active. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
includes/Integrations/WP_Job_Manager/WPUF_WP_Job_Manager_Integration.php (1)
35-73: Redundantclass_exists( 'WP_Job_Manager' )gate.
Integrations::__construct()(includes/Integrations.php:40) already instantiates this class only whenclass_exists( 'WP_Job_Manager' )is true, sois_wpjm_active()/ the early return at line 36–38 is dead code in the normal load path. Safe to keep as a defensive guard, but worth collapsing if you want to reduce duplication — otherwise at least add a comment noting it's only for direct instantiation paths (tests, WP-CLI, etc.).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@includes/Integrations/WP_Job_Manager/WPUF_WP_Job_Manager_Integration.php` around lines 35 - 73, The init_handlers method contains a redundant runtime check using is_wpjm_active()/class_exists('WP_Job_Manager') because Integrations::__construct() already only instantiates WPUF_WP_Job_Manager_Integration when WP_Job_Manager exists; collapse the duplicate guard by removing the early return block in init_handlers (the if (! $this->is_wpjm_active()) return;) or, if you prefer to keep it as defensive code, add a clarifying comment above is_wpjm_active() and the guard referencing Integrations::__construct() and explaining it's only for direct instantiation paths (tests/CLI) so reviewers understand the intent; update code around init_handlers and is_wpjm_active accordingly.includes/Integrations/WP_Job_Manager/Meta_Mapper.php (1)
158-172: Silent drop when fields are submitted but empty.
isset( $_POST[ $field_name ] )returnstruefor submitted-but-empty fields, so empty strings get written (overwriting prior values on edit — acceptable). However, thewpuf_wpjm_meta_mappingfilter allows third-parties to add keys that may not map to any posted field name — those are correctly skipped. Just flagging: if you later changeget_meta_mapping()to$field_name => $meta_keypairs where$field_name !== $meta_key, make sure the free template's fieldnamematches$field_name, not$meta_key. Worth a one-line comment.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@includes/Integrations/WP_Job_Manager/Meta_Mapper.php` around lines 158 - 172, Add a one-line clarifying comment in persist_meta above the foreach that explains the shape of get_meta_mapping() (keys are form input names, values are post meta keys), that isset($_POST[$field_name]) will be true for submitted-but-empty fields (which will overwrite existing meta with empty values), and that third-party filters (wpuf_wpjm_meta_mapping) must supply the form field "name" as the array key ($field_name) not the meta key ($meta_key).includes/Integrations/WP_Job_Manager/Template_Free.php (1)
22-22: Redundantenabledguard.This template is only registered in
Free_Loader::post_form_templates()whenclass_exists( 'WP_Job_Manager' )is already true, so$this->enabledis effectively alwaystruehere. Either drop the check or leave it as a belt-and-braces guard — flagging for awareness, not blocking.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@includes/Integrations/WP_Job_Manager/Template_Free.php` at line 22, The $this->enabled assignment in Template_Free is redundant because Free_Loader::post_form_templates() only registers this template when class_exists('WP_Job_Manager') is true; update Template_Free to set $this->enabled = true unconditionally (or remove the assignment entirely) to remove the needless class_exists check—modify the Template_Free class's constructor/property initialization (the $this->enabled line) accordingly and leave Free_Loader::post_form_templates() untouched.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@includes/Integrations/WP_Job_Manager/Meta_Mapper.php`:
- Around line 216-235: The sanitize_for_meta function currently calls
WP_Job_Manager_Post_Types::sanitize_meta_field_url,
::sanitize_meta_field_application, and ::sanitize_meta_field_based_on_input_type
directly which can cause fatal errors if those static methods are missing;
update sanitize_for_meta to wrap each WP_Job_Manager_Post_Types::method call in
is_callable checks (e.g., is_callable([WP_Job_Manager_Post_Types::class,
'sanitize_meta_field_url'])) and if the method is not callable fall back to safe
defaults: for URL/video use sanitize_text_field (or
wp_sanitize_redirect/esc_url_raw if available), for application use
sanitize_text_field or handle arrays with array_map('sanitize_text_field'), and
for the default case fall back to returning sanitized string/array via
sanitize_text_field/array_map — keep the existing _remote_position cast
unchanged and reference sanitize_for_meta and the three
WP_Job_Manager_Post_Types method names when making the changes.
---
Nitpick comments:
In `@includes/Integrations/WP_Job_Manager/Meta_Mapper.php`:
- Around line 158-172: Add a one-line clarifying comment in persist_meta above
the foreach that explains the shape of get_meta_mapping() (keys are form input
names, values are post meta keys), that isset($_POST[$field_name]) will be true
for submitted-but-empty fields (which will overwrite existing meta with empty
values), and that third-party filters (wpuf_wpjm_meta_mapping) must supply the
form field "name" as the array key ($field_name) not the meta key ($meta_key).
In `@includes/Integrations/WP_Job_Manager/Template_Free.php`:
- Line 22: The $this->enabled assignment in Template_Free is redundant because
Free_Loader::post_form_templates() only registers this template when
class_exists('WP_Job_Manager') is true; update Template_Free to set
$this->enabled = true unconditionally (or remove the assignment entirely) to
remove the needless class_exists check—modify the Template_Free class's
constructor/property initialization (the $this->enabled line) accordingly and
leave Free_Loader::post_form_templates() untouched.
In `@includes/Integrations/WP_Job_Manager/WPUF_WP_Job_Manager_Integration.php`:
- Around line 35-73: The init_handlers method contains a redundant runtime check
using is_wpjm_active()/class_exists('WP_Job_Manager') because
Integrations::__construct() already only instantiates
WPUF_WP_Job_Manager_Integration when WP_Job_Manager exists; collapse the
duplicate guard by removing the early return block in init_handlers (the if (!
$this->is_wpjm_active()) return;) or, if you prefer to keep it as defensive
code, add a clarifying comment above is_wpjm_active() and the guard referencing
Integrations::__construct() and explaining it's only for direct instantiation
paths (tests/CLI) so reviewers understand the intent; update code around
init_handlers and is_wpjm_active accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c0a288e8-5532-4677-8a5f-fc91c5cc2379
📒 Files selected for processing (6)
includes/Free/Free_Loader.phpincludes/Integrations.phpincludes/Integrations/WP_Job_Manager/Meta_Mapper.phpincludes/Integrations/WP_Job_Manager/Template_Free.phpincludes/Integrations/WP_Job_Manager/WPUF_WP_Job_Manager_Integration.phpwpuf-functions.php
| private function sanitize_for_meta( $value, $meta_key ) { | ||
| if ( ! class_exists( WP_Job_Manager_Post_Types::class ) ) { | ||
| return is_array( $value ) ? array_map( 'sanitize_text_field', $value ) : sanitize_text_field( $value ); | ||
| } | ||
|
|
||
| switch ( $meta_key ) { | ||
| case '_company_website': | ||
| case '_company_video': | ||
| return WP_Job_Manager_Post_Types::sanitize_meta_field_url( $value ); | ||
|
|
||
| case '_application': | ||
| return WP_Job_Manager_Post_Types::sanitize_meta_field_application( $value ); | ||
|
|
||
| case '_remote_position': | ||
| return (int) (bool) $value; | ||
|
|
||
| default: | ||
| return WP_Job_Manager_Post_Types::sanitize_meta_field_based_on_input_type( $value, $meta_key ); | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In the current WP Job Manager plugin source, what is the visibility (public/private/protected) of WP_Job_Manager_Post_Types::sanitize_meta_field_url, sanitize_meta_field_application, and sanitize_meta_field_based_on_input_type, and in which version did they become public?
💡 Result:
The methods WP_Job_Manager_Post_Types::sanitize_meta_field_url, ::sanitize_meta_field_application, and ::sanitize_meta_field_based_on_input_type do not appear to exist in the current WP Job Manager plugin source code (version 2.4.1 as of 2026-02-24, trunk branch last updated 2026-04-01). Extensive searches of the GitHub repository (https://github.com/Automattic/WP-Job-Manager), changelogs, and related files (including class-wp-job-manager-writepanels.php, class-wp-job-manager-cpt.php, wp-job-manager-functions.php) show references to WP_Job_Manager_Post_Types::get_job_listing_fields which returns field configurations used for sanitization callbacks, but no explicit methods matching these names or changes to their visibility (public/private/protected). The class WP_Job_Manager_Post_Types is referenced throughout the codebase for post types, taxonomies, capabilities, and expiration handling, but the specific sanitize methods are not found in available source snippets or changelogs. They may be private/internal callbacks not publicly documented, non-existent, or in an unindexed file. No version where they "became public" is mentioned in changelogs.
Citations:
- 1: https://github.com/Automattic/WP-Job-Manager/
- 2: https://github.com/Automattic/WP-Job-Manager/blob/trunk/includes/admin/class-wp-job-manager-writepanels.php
- 3: https://github.com/Automattic/WP-Job-Manager/blob/master/includes/admin/class-wp-job-manager-writepanels.php
- 4: https://github.com/Automattic/WP-Job-Manager/blob/master/changelog.txt
- 5: https://github.com/Automattic/WP-Job-Manager/blob/master/includes/admin/class-wp-job-manager-cpt.php
- 6: https://github.com/Automattic/WP-Job-Manager/blob/master/includes/class-wp-job-manager-install.php
- 7: https://github.com/Automattic/WP-Job-Manager/blob/trunk/wp-job-manager-functions.php
- 8: https://github.com/Automattic/WP-Job-Manager
- 9: https://github.com/Automattic/WP-Job-Manager/tree/trunk
🏁 Script executed:
# Check for WPJM version requirements
fd -e 'composer.json' -e 'composer.lock' -e 'readme.txt' -e 'readme.md' | head -20Repository: weDevsOfficial/wp-user-frontend
Length of output: 57
🏁 Script executed:
# Search for any WPJM version requirements or constants
rg -i "wp.job.manager|wpjm|job.manager" --max-count=20 -t php -t json -t md -t txtRepository: weDevsOfficial/wp-user-frontend
Length of output: 5967
🏁 Script executed:
# Check the target file modification date and context
git log --oneline -n 10 -- 'includes/Integrations/WP_Job_Manager/Meta_Mapper.php' 2>/dev/null || echo "Git history not available"Repository: weDevsOfficial/wp-user-frontend
Length of output: 116
🏁 Script executed:
# Search for any references to the sanitizer methods anywhere in the codebase
rg "sanitize_meta_field_(url|application|based_on_input_type)" --max-count=20Repository: weDevsOfficial/wp-user-frontend
Length of output: 523
🏁 Script executed:
cat -n 'includes/Integrations/WP_Job_Manager/Meta_Mapper.php' | head -100Repository: weDevsOfficial/wp-user-frontend
Length of output: 3733
🏁 Script executed:
# Check the integration bootstrap file for version requirements
cat -n 'includes/Integrations/WP_Job_Manager/WPUF_WP_Job_Manager_Integration.php'Repository: weDevsOfficial/wp-user-frontend
Length of output: 2274
🏁 Script executed:
# Search for any WPJM version constants or requirements in the codebase
rg -i "wp.*job.*manager.*version|WPJM.*version|wpjm.*minimum" -t phpRepository: weDevsOfficial/wp-user-frontend
Length of output: 57
Wrap direct WPJM method calls in is_callable() checks with appropriate fallbacks.
The methods WP_Job_Manager_Post_Types::sanitize_meta_field_url(), sanitize_meta_field_application(), and sanitize_meta_field_based_on_input_type() do not exist in the current WP Job Manager plugin source and will cause fatal errors when form submissions reach the sanitization step.
Implement the defensive fallback pattern to gracefully handle missing WPJM methods:
Suggested fix
private function sanitize_for_meta( $value, $meta_key ) {
- if ( ! class_exists( WP_Job_Manager_Post_Types::class ) ) {
+ if ( ! class_exists( WP_Job_Manager_Post_Types::class ) ) {
return is_array( $value ) ? array_map( 'sanitize_text_field', $value ) : sanitize_text_field( $value );
}
switch ( $meta_key ) {
case '_company_website':
case '_company_video':
- return WP_Job_Manager_Post_Types::sanitize_meta_field_url( $value );
+ return is_callable( [ WP_Job_Manager_Post_Types::class, 'sanitize_meta_field_url' ] )
+ ? WP_Job_Manager_Post_Types::sanitize_meta_field_url( $value )
+ : esc_url_raw( is_array( $value ) ? '' : $value );
case '_application':
- return WP_Job_Manager_Post_Types::sanitize_meta_field_application( $value );
+ return is_callable( [ WP_Job_Manager_Post_Types::class, 'sanitize_meta_field_application' ] )
+ ? WP_Job_Manager_Post_Types::sanitize_meta_field_application( $value )
+ : sanitize_text_field( is_array( $value ) ? '' : $value );
case '_remote_position':
return (int) (bool) $value;
default:
- return WP_Job_Manager_Post_Types::sanitize_meta_field_based_on_input_type( $value, $meta_key );
+ return is_callable( [ WP_Job_Manager_Post_Types::class, 'sanitize_meta_field_based_on_input_type' ] )
+ ? WP_Job_Manager_Post_Types::sanitize_meta_field_based_on_input_type( $value, $meta_key )
+ : ( is_array( $value ) ? array_map( 'sanitize_text_field', $value ) : sanitize_text_field( $value ) );
}
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@includes/Integrations/WP_Job_Manager/Meta_Mapper.php` around lines 216 - 235,
The sanitize_for_meta function currently calls
WP_Job_Manager_Post_Types::sanitize_meta_field_url,
::sanitize_meta_field_application, and ::sanitize_meta_field_based_on_input_type
directly which can cause fatal errors if those static methods are missing;
update sanitize_for_meta to wrap each WP_Job_Manager_Post_Types::method call in
is_callable checks (e.g., is_callable([WP_Job_Manager_Post_Types::class,
'sanitize_meta_field_url'])) and if the method is not callable fall back to safe
defaults: for URL/video use sanitize_text_field (or
wp_sanitize_redirect/esc_url_raw if available), for application use
sanitize_text_field or handle arrays with array_map('sanitize_text_field'), and
for the default case fall back to returning sanitized string/array via
sanitize_text_field/array_map — keep the existing _remote_position cast
unchanged and reference sanitize_for_meta and the three
WP_Job_Manager_Post_Types method names when making the changes.
closes #461
Related PR #1490
Summary
Adds a native WP Job Manager integration to WPUF. When WP Job Manager is active, a new "Post a Job" form template appears in the Post Form Template picker, letting site owners build a branded job submission form in the WPUF drag-and-drop builder instead of editing PHP to customize the WPJM shortcode.
Submissions create real WP Job Manager job listings with all expected meta (location, application email/URL, company info, etc.), respect WPJM's approval setting, and fire the same "new job submitted" notifications employers already expect.
Technical Notes
post_form_template_wp_job_manager. If WPUF Pro ships a richer version, it replaces this one via the same key.wpuf_enable_wpjm_integration— kill-switch.wpuf_wpjm_meta_mapping— customize WPUF-field → WPJM-meta mapping.wpuf_wpjm_should_approve— override the approval decision per submission._job_expires._public_submission = 1so WPJM's own handler firesjob_manager_job_submitted(admin + employer emails) without risk of double-firing.job_listing_categoryandjob_listing_typeadded to the free taxonomy allowlist so WPUF taxonomy fields can target them without Pro.Summary by CodeRabbit