Open Rayken opened 7 years ago
The reason the ! is_numeric()
check is in place is to allow an associative array to be passed and the array keys to be used (is_numeric()
is false), and also to allow an indexed array to be passed and for the array values to be used instead (is_numeric()
is true).
I can see that if you have an associative array with numeric keys (eg. for post IDs) then this won't behave as expected. I'm not sure how to go about fixing that.
Hi John,
we are running into the same issue - our post types are associated by an arbitrary ID (int value). We need to display a human readable label in the selection list filter, while filtering by the ID. The current implementation doesn't support that.
I looked around and it seems like there are really no good solutions to support the intended behavior. There's no way to determine if current indexes are sequential integers assumed by the system or they are intended by the programmer. There are attempts to solve this issue, but as long as there's an intent to pass sequential integers (even casted as strings) as [0 => "No", 1 => "Yes"]
(or ["0" => "No", "1" => "Yes"]
) where the keys are expected to be used, the solution will always fail. Heres an excellent stackoverflow answer on this exact subject: https://stackoverflow.com/a/13522545
So, either the solution has to have some sort of "exception" to the way certain scenarios implemented... Or it has to be treated as Key to Value array where the array key is the option value and the array value is the option label. It is a straightforward solution that can't brake. The downside is that the keys will have to be duplicated if they are the same as labels and it will brake your backward compatibility.
To keep the backward compatibility, you'd probably want to add either an alternative options
property that would consume keys and values as is, or have extra flag that would indicate that the options
keys need to be used i.e. use_options_key => true
.
Some food for thought...
Thank you!
After thinking a bit more about it, I think everything could be left the way it is, but change how we express key to value options:
In our case the option
tag accepts 2 parameters value
and label
or (title). If we were to represent option
as and object, we would set option.value
and option.label
. If option.value
was not set, then we would default the value to the options.label
or vice versa. So, our options array would simply contain array of objects. In our current PHP scenario we could express it as array of arrays:
$filter = [
'options' => [
['value' => 123, 'label' => 'John Doe'],
['value' => 124, 'label' => 'Jane Doe']
]
];
So, to make it work, all we need to do is to check if our current option item is an array or a string. If string, we use it as option value and label, if array, then we use them as intended.
We also need to filter a custom post type by a related post type, and we came up with 2 possible solutions
apply_filters('ext-cpts/use_key', $use_key, $filter['options']);
'admin_filters' => array(
'linked_post_id' => array(
'title' => __('Select linked post', 'textdomain'),
'meta_key' => 'linked_post_id',
'options' => 'linked_posts',
'use_key' => false
),
),
I assume these solutions wouldn't affect other functionality
Am also experiencing this issue, any chance it can be resolved?
I came up with a workaround (I wouldn't call it a solution) for this. The problem is that $use_key remains false, because the key is an int (numeric), so the value is used, instead of the key.
As a workaround, we can append or prepend the post ID with a string, and later on, remove that string through a filter:
Make sure the key for your filter key & meta_key are the same (event_id) in this case.
'admin_filters' => [
'event_id' => [
'meta_key' => 'event_id',
'title' => __('Event', 'textdomain'),
'options' => function () {
$events = Event::find();
$return = array();
foreach ($events as $key => $event) {
$return['event_' . $event->getId()] = $event->title();
}
return $return;
},
],
],
subscription
is the post type that has the admin filter, event_id
is the metakey, `event` has been added in the previous step.
add_filter('ext-cpts/subscription/filter-query/event_id', function($return, $query, $filter){
$return = [];
$return['meta_query'][] = [
'key' => $filter['meta_key'],
'value' => str_replace('event_', '', wp_unslash($query['event_id'])),
];
return $return;
}, 10, 3);
Line 276 @ https://github.com/johnbillion/extended-cpts/blob/master/src/class-extended-cpt-admin.php#L276
Should probably not have !, because right now, if the key is numeric (like a post_id or so) it reverts to using the 'value' and that is really odd.
My use case is creating a dropdown with post_title and its ID as value, right now I'm getting post_title as value as well. Changing the line to:
Fixes this issue. However, I do believe you could skip the entire foreach @ line 275-280 and changing line 288 to:
Unless I have misunderstood the use of $use_key. However this is causing issues for me atm!
For options I'm returning something like:
And the scripts thinks it should use "Some%20post" as filter instead of 1.