jobs-data.php
Job data access
One place for the two things the plugin previously did in several: deciding which jobs are visible, and reading a job as data rather than as markup.
Tags
Table of Contents
Functions
- jpkcom_acf_jobs_build_job_query_args() : array<string|int, mixed>
- Build WP_Query arguments for the job visibility rule.
- jpkcom_acf_jobs_normalise_choices() : array<string|int, mixed>
- Normalise an ACF choice-list value to {value,label} pairs.
- jpkcom_acf_jobs_normalise_choice() : array<string|int, mixed>|null
- Normalise a single-choice ACF value (button_group, select) to one pair.
- jpkcom_acf_jobs_normalise_date() : string|null
- Normalise a stored date to Y-m-d.
- jpkcom_acf_jobs_plain_text() : string
- Reduce stored markup to plain text without executing anything.
- jpkcom_acf_jobs_normalise_related() : array<string|int, mixed>
- Project ACF post-object values to {id,title}, dropping anything unpublished.
- jpkcom_acf_jobs_attachment_url() : string|null
- Resolve an ACF image value to a single URL.
- jpkcom_acf_jobs_get_job_data() : array<string|int, mixed>
- Read one job as a JSON-serialisable array.
Functions
jpkcom_acf_jobs_build_job_query_args()
Build WP_Query arguments for the job visibility rule.
jpkcom_acf_jobs_build_job_query_args([array<string|int, mixed> $args = [] ]) : array<string|int, mixed>
This is the single source for "which jobs does this site show". It is called from three places that previously each carried their own copy: the [jpkcom_acf_jobs_list] shortcode, the job archive's pre_get_posts handler, and the Abilities API callbacks.
Keys whose value is null are omitted from the result, because the archive sets its query through WP_Query::set() and must not inherit a page size or a status.
Parameters
- $args : array<string|int, mixed> = []
-
{ Optional. Query parameters.
@type int|null $posts_per_page Page size. Omitted when null. Never defaulted to -1. @type int|null $paged Page number. Omitted when null. @type string $order 'ASC' or 'DESC' for the date component. Default 'DESC'. @type string|null $post_status Post status. Omitted when null. @type string[] $job_type job_type values (not labels). @type int[] $company job_company post IDs. @type int[] $location job_location post IDs. @type int[] $attribute job-attribute term IDs. @type string $search Free-text search. @type bool $exclude_password_protected Whether to drop password-protected jobs.}
Tags
Return values
array<string|int, mixed> —WP_Query arguments.
jpkcom_acf_jobs_normalise_choices()
Normalise an ACF choice-list value to {value,label} pairs.
jpkcom_acf_jobs_normalise_choices(mixed $value) : array<string|int, mixed>
A checkbox with return_format 'array' yields [ ['value'=>…, 'label'=>…], … ]. The same field yields bare strings when ACF falls back to the raw meta, which happens whenever the field group is not registered — a theme replacing acf-field_groups.php through the override system is enough. Both shapes are the contract, not a defensive afterthought.
Parameters
- $value : mixed
-
Raw ACF value.
Tags
Return values
array<string|int, mixed> —List of [ 'value' => string, 'label' => string ].
jpkcom_acf_jobs_normalise_choice()
Normalise a single-choice ACF value (button_group, select) to one pair.
jpkcom_acf_jobs_normalise_choice(mixed $value) : array<string|int, mixed>|null
Parameters
- $value : mixed
-
Raw ACF value.
Tags
Return values
array<string|int, mixed>|null —[ 'value' => string, 'label' => string ], or null when empty.
jpkcom_acf_jobs_normalise_date()
Normalise a stored date to Y-m-d.
jpkcom_acf_jobs_normalise_date(mixed $raw) : string|null
ACF stores date fields as Ymd and formats them on read, so both spellings reach this function depending on whether the field's key reference row exists. Anything else yields null rather than a guess.
Deliberately not written as date( 'Y-m-d', strtotime( $raw ) ), the form used in includes/schema.php:71: under strict_types a false from strtotime() makes date() throw a TypeError, and on the WP 6.9 floor a Throwable out of an ability callback is an uncaught fatal.
is_string() is not enough to make createFromFormat() safe: a PHP string can carry an embedded NUL byte anywhere in it, and as of PHP 8.3 that makes DateTimeImmutable::createFromFormat() throw ValueError instead of returning false — confirmed regardless of the NUL's position or which of the two formats below is tried. MySQL longtext happily stores one; an importer, WP-CLI, a WPML copy or direct SQL against job_expiry_date is enough to plant it. The try/catch below is what closes that door; everything else that can go wrong here (invalid UTF-8, absurdly long input, an overflowing month/day/date) was measured to fail closed already — createFromFormat() returns false rather than throwing, and format() never throws for the two hardcoded, always-valid format strings used here.
Parameters
- $raw : mixed
-
Stored value.
Tags
Return values
string|null —Date as Y-m-d, or null.
jpkcom_acf_jobs_plain_text()
Reduce stored markup to plain text without executing anything.
jpkcom_acf_jobs_plain_text(mixed $value) : string
job_short_description is a textarea with new_lines => 'br', so its stored value is HTML. This turns it back into text. It expands nothing: shortcode expansion is exactly what get_field()'s formatted mode does and what every caller of this function exists to avoid.
Parameters
- $value : mixed
-
Stored value.
Tags
Return values
string —Plain text, empty when the value was not a string.
jpkcom_acf_jobs_normalise_related()
Project ACF post-object values to {id,title}, dropping anything unpublished.
jpkcom_acf_jobs_normalise_related(mixed $value) : array<string|int, mixed>
Never returns a WP_Post. WP_Post implements no JsonSerializable and exposes post_password, post_content and post_status as public properties, so encoding one would publish a related company's plaintext password. ACF resolves post_object fields through acf_get_posts() with post_status 'any', so drafts and private records genuinely arrive here.
Bare integers are accepted and re-resolved: when a translation's ACF key reference row is missing — the case includes/wpml-acf-field-keys-fix.php exists to repair — get_field() returns raw IDs, and every renderer in this repo dereferences ->ID on them.
A bare id is rejected before the lookup when absint() reduces it to less than 1.
absint() maps false, '', null, 'abc' and 0 all to 0, and real get_post( 0 ) treats
0 as empty and falls back to the current global post — the same footgun
jpkcom_acf_jobs_get_job_data()'s own $post_id < 1 guard exists for. ACF genuinely
returns false, not an array, for an unassigned post_object field with
allow_null => 1, which both job_company and job_location are, so an unresolved id
reaching get_post() unguarded would project the current job as its own employer or
location. A password is checked for the same reason the reader's own gate checks
one: nothing about a post_object relation implies the related post is public.
Parameters
- $value : mixed
-
Raw ACF value.
Tags
Return values
array<string|int, mixed> —List of [ 'id' => int, 'title' => string ].
jpkcom_acf_jobs_attachment_url()
Resolve an ACF image value to a single URL.
jpkcom_acf_jobs_attachment_url(mixed $value) : string|null
ACF hands out an image field either as an attachment ID or as an array of roughly thirty keys, depending on the field's return format and on whether the field group is registered at all. Both shapes reduce to one URL here. The full array is deliberately never emitted: it carries the uploader's name, the file path on disk and every registered intermediate size, none of which a job listing needs.
Parameters
- $value : mixed
-
Raw ACF image value.
Tags
Return values
string|null —Image URL, or null when the value resolves to no attachment.
jpkcom_acf_jobs_get_job_data()
Read one job as a JSON-serialisable array.
jpkcom_acf_jobs_get_job_data(int $post_id[, bool $full = false ]) : array<string|int, mixed>
The gate is the first act, because no field reader in this plugin has one: schema.php checks the post type, nothing anywhere checks the status, and the existing readers are safe only because the shortcode hands them posts a post_type/post_status query already filtered. A function taking a bare int inherits none of that, and current_user_can( 'read' ) is every logged-in user.
Returns [] for "does not exist" and for "not readable" alike, so the ability on top of it cannot be used to probe which IDs exist.
Parameters
- $post_id : int
-
Job post ID.
- $full : bool = false
-
Whether to include the detail fields (§5.3 of the spec).
Tags
Return values
array<string|int, mixed> —The record, or [] when the job is not readable.