Opened 9 years ago
Closed 9 years ago
#33281 closed defect (bug) (fixed)
get_term_by() not returning false if ID does not exist
Reported by: | charlestonsw | Owned by: | boonebgorges |
---|---|---|---|
Milestone: | 4.4 | Priority: | normal |
Severity: | normal | Version: | 2.3 |
Component: | Taxonomy | Keywords: | has-patch |
Focuses: | Cc: |
Description
get_term_by() should return false if a specified ID does not exist within a custom taxonomy. Instead an empty array (null) is returned.
Example:
... $category_array = get_term_by( 'id' , $term_id , SLPlus::locationTaxonomy, ARRAY_A ); if ( $category_array === false ) { $this->debugMP('msg', "Tagalong term ID {$term_id} does not exist." ); }
When passing term_id value of 2, which does not exist in the terms tables, this should return false. Instead null is returned.
The issue originates in get_term() which returns null in two cases versus throwing a WP_Error.
From get_term()
... if ( is_object($term) ) $term = $term->term_id; if ( !$term = (int) $term ) return null; if ( ! $_term = wp_cache_get( $term, $taxonomy ) ) { $_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND t.term_id = %d LIMIT 1", $taxonomy, $term) ); if ( ! $_term ) return null; ...
In those two cases, one of which is exactly the "term ID does not exist in the specified taxonomy" get_term_by should return false. However the return logic does not catch the null value:
From get_term_by():
... $term = get_term( (int) $value, $taxonomy, $output, $filter ); if ( is_wp_error( $term ) ) $term = false; return $term; ...
This should be:
... $term = get_term( (int) $value, $taxonomy, $output, $filter ); if ( is_wp_error( $term ) || is_null( $term ) ) $term = false; return $term; ...
WP Version: You are using a development version (4.3-RC2-33572-src).
Attachments (2)
Change History (9)
#1
@
9 years ago
- Keywords close added
- Version changed from trunk to 2.3
I imagine it's done this since the introduction of the function in 2.3. I'm not sure this can reasonably be changed now, given that developers may be doing strict comparisons now that this kind of change would break. The inline docs seem like they could use updating to really lay out which situation returns which value.
#2
@
9 years ago
The docs definitely need to be updated.
As for backward compatibility - developers would be required to check for is_null(), false, and is_wp_error() to ensure proper functionality. By forcing false the function would match the documentation and not cause the null corner case to be missed as any developer relying ONLY on null return values will have several other mainstream cases the would not be functioning properly.
In my admittedly-limited research I found dozens of plugins that incorrectly test for only false or is_wp_error(). It appears in a number of prevalent plugins including several main JetPack modules. Leaving out the is_null() test will cause errant behavior in a variety of taxonomy-related corner cases.
I would bet that far more developers have incorrectly coded for false/is_wp_error() versus developers incorrectly coding for is_null() testing only.
With NULL coming back from several possible logic branches it would be extremely difficult, and I'm guessing a very rare case, that a developer is relying on an is_null() test to branch their logic for one-of-several specific failures with this method.
Yes, updating the docs prevents future developers from making the 2-test logic issue and warns them to look for is_null() as well, but I'm thinking more issues would be fixed by returning the "assumed false if failed" than would be introduced by changing null to false.
My code has been updated to test for all 3 results and will work regardless of null or false. I'm only discussing the point for the betterment of all WordPress installs as there are definitely a number of popular plugins that are missing the null return value.
#4
@
9 years ago
- Keywords needs-unit-tests added; close removed
- Milestone changed from Awaiting Review to 4.4
In the past, we've made a conscious decision that get_term_by()
should return only false
on failure, so that it could be used like this: if ( $term = get_term_by() )
For example, [17526] made it impossible to return a WP_Error
object. See #16464.
It's true that returning null
vs false
is not precisely the same thing as the above, but I think it's in the same spirit. And it's very difficult to come up with a reasonable situation in which null
would be distinguished from false
in the context of get_term_by()
. Let's switch it.
Can we get a unit test that demonstrates the issue, please?
Proposed patch.