[wp-trac] [WordPress Trac] #29030: Screen Options Poor Update/Rendering Causes Many things to Break

WordPress Trac noreply at wordpress.org
Sat Jul 26 01:48:18 UTC 2014


#29030: Screen Options Poor Update/Rendering Causes Many things to Break
----------------------------+---------------------------------------------
 Reporter:  codecandid      |       Owner:
     Type:  defect (bug)    |      Status:  new
 Priority:  normal          |   Milestone:  Awaiting Review
Component:  Administration  |     Version:  3.9.1
 Severity:  normal          |  Resolution:
 Keywords:                  |     Focuses:  ui, javascript, administration
----------------------------+---------------------------------------------
Changes (by SergeyBiryukov):

 * focuses:  ui, javascript, administration, performance => ui, javascript,
     administration


Old description:

> Screen options dont work properly in many different situations. I noticed
> the first issue when trying to create a sticky header plugin for the
> wp_list_table. When scrolling down the page the headers stick to the top
> by cloning the header with javascript and hiding the other original at
> the same time. However, If screen options are updated the tables break
> completly even after the plugin is disabled. Wordpress checks the current
> table headers to determine which ones are hidden and should be added to
> the `manageedit-{$post_type}columnshidden` field in the `user_meta`
> table. So since the cloned table header the plugin created is hidden
> visually while scrolling up, wordpress thinks that all columns
> aredisabled and adds all the columns to
> `manageedit-{$post_type}columnshidden`.
>

> [[Image(http://i.stack.imgur.com/wrYin.png)]]
>
> This is poor practice because it doesn't seperate presentation well
> enough from the logic used to render screen options. Any user who has
> access to `wp-admin/edit.php`can completly break their tables if any
> html/css visually hides the `<thead>` or a column-header perhaps by a
> plugin, or maybe the browser doesn't load a certain script, or perhaps
> they are just messing with the dev-tools. Beginers that don't know how to
> properly [remove columns][5], could run into this issue if they ever try
> to use css instead. `manageedit-{$post_type}column` should not rely on
> the visibility of <thead> and only the actual checked input fields. Also
> `cb` and `title` should not be allowed to be added to the
> `manageedit-{$post_type}column`. They should only be able to be removed
> with `unset`.
>

> ----------
>

> **To recreate this issue:**
>
>  1. open up firebug/chrome dev tools/etc. on http://www.example.com/wp-
> admin/edit.php
>  2. add  `thead {display: none;}` to the style editor
>  3. On the page screen options uncheck at least one column ( this is to
> ensure `manageedit-{$post_type}columnshidden` is a database field for the
> current user and if not it creates it )
>  4. Hit apply to refresh the page
>
> *The tables will now be broken....*
>

> ----------
>

> To chck the columns I used the `get_user_meta();` function to print the
> array of `hiddencolumns` on each post types `edit.php` admin screen
> notices:
>

> {{{
>     <?php
>     function get_current_post_type() {
>             global $post, $typenow, $current_screen;
>             if ($post && $post->post_type)
>                 return $post->post_type;
>              elseif ($typenow)
>                 return $typenow;
>              elseif ($current_screen && $current_screen->post_type)
>                 return $current_screen->post_type;
>              elseif (isset($_REQUEST['post_type']))
>                 return sanitize_key($_REQUEST['post_type']);
>             return null;
>     }
>
>     function get_current_user_manageedit_pagecolumnshidden() {
>         $current_ptype = get_current_post_type();
>         $user_id = get_current_user_id();
>         $key = 'manageedit-'.$current_ptype.'columnshidden';
>         $single = true;
>         if(get_user_meta($user_id, $key, $single))
>                 return get_user_meta($user_id, $key, $single);
>     }
>
>      function echo_current_user_manageedit_pagecolumnshidden() {
>                 global $pagenow;
>                 if ( $pagenow !== 'edit.php' )
>                         return;
>                 $columnshidden=
> get_current_user_manageedit_pagecolumnshidden();
>                 echo '<pre>'; print_r( $columnshidden ); echo '</pre>';
>         }
>         add_action('all_admin_notices',
> 'echo_current_user_manageedit_pagecolumnshidden');
>
> }}}
>

> **Output for the broken tables :**
>

> {{{
>     Array
>     (
>         [0] => cb
>         [1] => title
>         [2] =>
>         [3] =>
>     )
>
> }}}
>

> ----------
>

> After determining that `cb` & `title` were in fact added to the
> `$meta_value`you need to fix the table. This will do the trick:
>

> {{{
>    function delete_current_user_manageedit_pagecolumnshidden() {
>         $user_id = get_current_user_id();
>         $meta_key = 'manageedit-pagecolumnshidden';
>         if( get_user_meta($user_id, $meta_key) )
>                 delete_user_meta( $user_id, $meta_key );
>     }
>     add_action ('admin_init',
> 'delete_current_user_manageedit_pagecolumnshidden');
>
> }}}
>

>

> ''Side-Notes:''
> *`columnshidden` appears [`wp_ajax_hidden_columns()`][1] &
> [`get_hidden_columns()`][2]
> *client-side functionality  appears to be here in [`common.js`][3] which
> checks for the [hidden table headers][4]
>

> ----------
>

> Similar issues with the screen options can be recreated for different
> situations that have nothing to do with the tables.
>
> **Recreate similar issue on nav-menus.php**
>
>  1. Go to http://example.com/wp-admin/nav-menus.php
>  2. Uncheck all the fields in the *"Show advanced menu properties"*
> Screen-Options tab
>  3. Add the screen options filter to hide them from display:
> `add_filter('screen_options_show_screen', 'remove_screen_options_tab');`
>  4. Reload http://example.com/wp-admin/nav-menus.php
>

> All of the hidden advanced menu properties will now be broken and are all
> visible even though they were unchecked. I'm not sure if this is the same
> issue, but it appears that overall screen options have a high change of
> not working properly
>

> ----------
>

> ----------
>

> **Other-Notes**
> These issues of broken tables might also have to do with the same
> functionality problem of how screen options update/render:
>

> http://wordpress.stackexchange.com/questions/31154/wp-list-table-custom-
> quick-edit-box-post-meta-data-missing-and-columns-change
>
> http://wordpress.stackexchange.com/questions/123182/custom-admin-column-
> disappearing-when-using-quick-edit?lq=1
>
> http://wordpress.stackexchange.com/questions/144361/wordpress-admin-wp-
> table-list-show-incorrectly
>
> https://core.trac.wordpress.org/ticket/21016
>

>

>   [1]:
> https://github.com/WordPress/WordPress/blob/448275cce483138f53ccfa586b2d28b7fe8b0785
> /wp-admin/includes/screen.php#L55
>   [2]:
> https://github.com/WordPress/WordPress/blob/270a57075c290736387b6551670fde34fb3f1851
> /wp-admin/includes/ajax-actions.php#L1307
>   [3]:
> https://github.com/WordPress/WordPress/blob/448275cce483138f53ccfa586b2d28b7fe8b0785
> /wp-admin/js/common.js#L29
>   [4]:
> https://github.com/WordPress/WordPress/blob/448275cce483138f53ccfa586b2d28b7fe8b0785
> /wp-admin/includes/screen.php#L17
>   [5]:
> http://codex.wordpress.org/Plugin_API/Filter_Reference/manage_$post_type_posts_columns

New description:

 Screen options dont work properly in many different situations. I noticed
 the first issue when trying to create a sticky header plugin for the
 wp_list_table. When scrolling down the page the headers stick to the top
 by cloning the header with javascript and hiding the other original at the
 same time. However, If screen options are updated the tables break
 completly even after the plugin is disabled. Wordpress checks the current
 table headers to determine which ones are hidden and should be added to
 the `manageedit-{$post_type}columnshidden` field in the `user_meta` table.
 So since the cloned table header the plugin created is hidden visually
 while scrolling up, wordpress thinks that all columns aredisabled and adds
 all the columns to `manageedit-{$post_type}columnshidden`.


 [[Image(http://i.stack.imgur.com/wrYin.png)]]

 This is poor practice because it doesn't seperate presentation well enough
 from the logic used to render screen options. Any user who has access to
 `wp-admin/edit.php`can completly break their tables if any html/css
 visually hides the `<thead>` or a column-header perhaps by a plugin, or
 maybe the browser doesn't load a certain script, or perhaps they are just
 messing with the dev-tools. Beginers that don't know how to properly
 [remove columns][5], could run into this issue if they ever try to use css
 instead. `manageedit-{$post_type}column` should not rely on the visibility
 of <thead> and only the actual checked input fields. Also `cb` and `title`
 should not be allowed to be added to the `manageedit-{$post_type}column`.
 They should only be able to be removed with `unset`.


 ----------


 **To recreate this issue:**

  1. open up firebug/chrome dev tools/etc. on http://www.example.com/wp-
 admin/edit.php
  2. add  `thead {display: none;}` to the style editor
  3. On the page screen options uncheck at least one column ( this is to
 ensure `manageedit-{$post_type}columnshidden` is a database field for the
 current user and if not it creates it )
  4. Hit apply to refresh the page

 *The tables will now be broken....*


 ----------


 To chck the columns I used the `get_user_meta();` function to print the
 array of `hiddencolumns` on each post types `edit.php` admin screen
 notices:


 {{{
     <?php
     function get_current_post_type() {
             global $post, $typenow, $current_screen;
             if ($post && $post->post_type)
                 return $post->post_type;
              elseif ($typenow)
                 return $typenow;
              elseif ($current_screen && $current_screen->post_type)
                 return $current_screen->post_type;
              elseif (isset($_REQUEST['post_type']))
                 return sanitize_key($_REQUEST['post_type']);
             return null;
     }

     function get_current_user_manageedit_pagecolumnshidden() {
         $current_ptype = get_current_post_type();
         $user_id = get_current_user_id();
         $key = 'manageedit-'.$current_ptype.'columnshidden';
         $single = true;
         if(get_user_meta($user_id, $key, $single))
                 return get_user_meta($user_id, $key, $single);
     }

      function echo_current_user_manageedit_pagecolumnshidden() {
                 global $pagenow;
                 if ( $pagenow !== 'edit.php' )
                         return;
                 $columnshidden=
 get_current_user_manageedit_pagecolumnshidden();
                 echo '<pre>'; print_r( $columnshidden ); echo '</pre>';
         }
         add_action('all_admin_notices',
 'echo_current_user_manageedit_pagecolumnshidden');

 }}}


 **Output for the broken tables :**


 {{{
     Array
     (
         [0] => cb
         [1] => title
         [2] =>
         [3] =>
     )

 }}}


 ----------


 After determining that `cb` & `title` were in fact added to the
 `$meta_value`you need to fix the table. This will do the trick:


 {{{
    function delete_current_user_manageedit_pagecolumnshidden() {
         $user_id = get_current_user_id();
         $meta_key = 'manageedit-pagecolumnshidden';
         if( get_user_meta($user_id, $meta_key) )
                 delete_user_meta( $user_id, $meta_key );
     }
     add_action ('admin_init',
 'delete_current_user_manageedit_pagecolumnshidden');

 }}}




 ''Side-Notes:''
 *`columnshidden` appears [`wp_ajax_hidden_columns()`][1] &
 [`get_hidden_columns()`][2]
 *client-side functionality  appears to be here in [`common.js`][3] which
 checks for the [hidden table headers][4]


 ----------


 Similar issues with the screen options can be recreated for different
 situations that have nothing to do with the tables.

 **Recreate similar issue on nav-menus.php**

  1. Go to http://example.com/wp-admin/nav-menus.php
  2. Uncheck all the fields in the *"Show advanced menu properties"*
 Screen-Options tab
  3. Add the screen options filter to hide them from display:
 `add_filter('screen_options_show_screen', 'remove_screen_options_tab');`
  4. Reload http://example.com/wp-admin/nav-menus.php


 All of the hidden advanced menu properties will now be broken and are all
 visible even though they were unchecked. I'm not sure if this is the same
 issue, but it appears that overall screen options have a high change of
 not working properly


 ----------


 ----------


 **Other-Notes**
 These issues of broken tables might also have to do with the same
 functionality problem of how screen options update/render:


 http://wordpress.stackexchange.com/questions/31154/wp-list-table-custom-
 quick-edit-box-post-meta-data-missing-and-columns-change

 http://wordpress.stackexchange.com/questions/123182/custom-admin-column-
 disappearing-when-using-quick-edit?lq=1

 http://wordpress.stackexchange.com/questions/144361/wordpress-admin-wp-
 table-list-show-incorrectly

 #21016




   [1]:
 https://github.com/WordPress/WordPress/blob/448275cce483138f53ccfa586b2d28b7fe8b0785
 /wp-admin/includes/screen.php#L55
   [2]:
 https://github.com/WordPress/WordPress/blob/270a57075c290736387b6551670fde34fb3f1851
 /wp-admin/includes/ajax-actions.php#L1307
   [3]:
 https://github.com/WordPress/WordPress/blob/448275cce483138f53ccfa586b2d28b7fe8b0785
 /wp-admin/js/common.js#L29
   [4]:
 https://github.com/WordPress/WordPress/blob/448275cce483138f53ccfa586b2d28b7fe8b0785
 /wp-admin/includes/screen.php#L17
   [5]:
 http://codex.wordpress.org/Plugin_API/Filter_Reference/manage_$post_type_posts_columns

--

Comment:

 Confirmed.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/29030#comment:2>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list