[wp-trac] [WordPress Trac] #35901: WP_Query::is_page() fails in certain cases when post titles include slashes.

WordPress Trac noreply at wordpress.org
Mon Feb 22 16:22:21 UTC 2016


#35901: WP_Query::is_page() fails in certain cases when post titles include
slashes.
--------------------------+-----------------------------
 Reporter:  mikejolley    |      Owner:
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  General       |    Version:  4.4.2
 Severity:  normal        |   Keywords:
  Focuses:                |
--------------------------+-----------------------------
 In WP_Query::is_page(), the following evaluations are made to determine if
 the queried object matches the supplied page property:

 `
 if ( in_array( (string) $page_obj->ID, $page ) ) {
         return true;
 } elseif ( in_array( $page_obj->post_title, $page ) ) {
         return true;
 } elseif ( in_array( $page_obj->post_name, $page ) ) {
         return true;
 } else {
 `

 If you have a page with a slash in the name, for example, `4/6 Sample
 Page`, `WP_Query::is_page(4)` returns true, even if the actual page ID is
 something else.

 I traced this back to the line:

 `
 } elseif ( in_array( $page_obj->post_title, $page ) ) {
 `

 In my test case, $page is:

 `
 array(1) { [0]=> int(4) }
 `

 If you cast `4/6 Sample Page` to int, it becomes `int(4)` causing the
 match.  This comparison should be strict...

 There was some discussion around this in ticket
 https://core.trac.wordpress.org/ticket/24674, however, I don't see a fix
 for the case I posted above. Only IDs were fixed.

 When comparing string based post_titles, ideally the $page should be cast
 to string to prevent the above case returning true.

 To fix this I believe we can do some more intelligent casting.

 The first rule:

 `
 if ( in_array( (string) $page_obj->ID, $page ) ) {
 `

 ID is cast to string and compared against $page with type array, contents
 unknown.

 The second rule we already know title is string:

 `
 } elseif ( in_array( $page_obj->post_title, $page ) ) {
 `

 Same for the postname rule:

 `
 } elseif ( in_array( $page_obj->post_name, $page ) ) {
 `

 Since all comparisons use string, we should be able to safely cast the
 array values to a string too:

 `
 $page = array_map( 'strval', (array) $page );
 `

 This fixes all comparisons and prevents the bug occurring.

 I found this bug when investigating
 https://github.com/woothemes/woocommerce/issues/10404. Page name was `4/6
 Sample Page`, and in my case my shop page was ID #4. Because of this,
 checks for page ID #4 (shop) returned true on `4/6 Sample Page`
 incorrectly.

 Patch to follow...

--
Ticket URL: <https://core.trac.wordpress.org/ticket/35901>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list