WordPress.org

Make WordPress Core

Changeset 36316


Ignore:
Timestamp:
01/15/2016 12:19:15 PM (4 years ago)
Author:
swissspidy
Message:

Post Types: Introduce unregister_post_type().

This new function can be used to completely unregister non built-in post types.

Fixes #14761.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/capabilities.php

    r35747 r36316  
    1616 *
    1717 * @since 2.0.0
     18 *
     19 * @global array $post_type_meta_caps Used to get post type meta capabilities.
    1820 *
    1921 * @param string $cap       Capability name.
     
    378380    default:
    379381        // Handle meta capabilities for custom post types.
    380         $post_type_meta_caps = _post_type_meta_capabilities();
     382        global $post_type_meta_caps;
    381383        if ( isset( $post_type_meta_caps[ $cap ] ) ) {
    382384            $args = array_merge( array( $post_type_meta_caps[ $cap ], $user_id ), $args );
  • trunk/src/wp-includes/post.php

    r36307 r36316  
    11881188
    11891189/**
     1190 * Unregister a post type.
     1191 *
     1192 * Can not be used to unregister built-in post types.
     1193 *
     1194 * @since 4.5.0
     1195 *
     1196 * @global WP_Rewrite $wp_rewrite             WordPress rewrite component.
     1197 * @global WP         $wp                     Current WordPress environment instance.
     1198 * @global array      $_wp_post_type_features Used to remove post type features.
     1199 * @global array      $post_type_meta_caps    Used to remove meta capabilities.
     1200 * @global array      $wp_post_types          List of post types.
     1201 *
     1202 * @param string $post_type Post type key.
     1203 * @return bool|WP_Error True on success, WP_Error on failure.
     1204 */
     1205function unregister_post_type( $post_type ) {
     1206    if ( ! post_type_exists( $post_type ) ) {
     1207        return new WP_Error( 'invalid_post_type', __( 'Invalid post type' ) );
     1208    }
     1209
     1210    $post_type_args = get_post_type_object( $post_type );
     1211
     1212    // Do not allow unregistering internal post types.
     1213    if ( $post_type_args->_builtin ) {
     1214        return new WP_Error( 'invalid_post_type', __( 'Unregistering a built-in post type is not allowed' ) );
     1215    }
     1216
     1217    global $wp, $wp_rewrite, $_wp_post_type_features, $post_type_meta_caps, $wp_post_types;
     1218
     1219    // Remove query var.
     1220    if ( false !== $post_type_args->query_var ) {
     1221        $wp->remove_query_var( $post_type_args->query_var );
     1222    }
     1223
     1224    // Remove any rewrite rules, permastructs, and rules.
     1225    if ( false !== $post_type_args->rewrite ) {
     1226        remove_rewrite_tag( "%$post_type%" );
     1227        remove_permastruct( $post_type );
     1228        foreach ( $wp_rewrite->extra_rules_top as $regex => $query ) {
     1229            if ( false !== strpos( $query, "index.php?post_type=$post_type" ) ) {
     1230                unset( $wp_rewrite->extra_rules_top[ $regex ] );
     1231            }
     1232        }
     1233    }
     1234
     1235    // Remove registered custom meta capabilities.
     1236    foreach ( $post_type_args->cap as $cap ) {
     1237        unset( $post_type_meta_caps[ $cap ] );
     1238    }
     1239
     1240    // Remove all post type support.
     1241    unset( $_wp_post_type_features[ $post_type ] );
     1242
     1243    // Unregister the post type meta box if a custom callback was specified.
     1244    if ( $post_type_args->register_meta_box_cb ) {
     1245        remove_action( 'add_meta_boxes_' . $post_type, $post_type_args->register_meta_box_cb );
     1246    }
     1247
     1248    // Remove the post type from all taxonomies.
     1249    foreach ( get_object_taxonomies( $post_type ) as $taxonomy ) {
     1250        unregister_taxonomy_for_object_type( $taxonomy, $post_type );
     1251    }
     1252
     1253    // Remove the future post hook action.
     1254    remove_action( 'future_' . $post_type, '_future_post_hook', 5 );
     1255
     1256    // Remove the post type.
     1257    unset( $wp_post_types[ $post_type ] );
     1258
     1259    /**
     1260     * Fires after a post type was unregistered.
     1261     *
     1262     * @since 4.5.0
     1263     *
     1264     * @param string $post_type Post type key.
     1265     */
     1266    do_action( 'unregistered_post_type', $post_type );
     1267
     1268    return true;
     1269}
     1270
     1271/**
    11901272 * Build an object with all post type capabilities out of a post type object
    11911273 *
     
    12941376 * @access private
    12951377 *
    1296  * @staticvar array $meta_caps
    1297  *
    1298  * @param array|void $capabilities Post type meta capabilities.
     1378 * @global array $post_type_meta_caps Used to store meta capabilities.
     1379 *
     1380 * @param array $capabilities Post type meta capabilities.
    12991381 */
    13001382function _post_type_meta_capabilities( $capabilities = null ) {
    1301     static $meta_caps = array();
    1302     if ( null === $capabilities )
    1303         return $meta_caps;
     1383    global $post_type_meta_caps;
     1384
    13041385    foreach ( $capabilities as $core => $custom ) {
    1305         if ( in_array( $core, array( 'read_post', 'delete_post', 'edit_post' ) ) )
    1306             $meta_caps[ $custom ] = $core;
     1386        if ( in_array( $core, array( 'read_post', 'delete_post', 'edit_post' ) ) ) {
     1387            $post_type_meta_caps[ $custom ] = $core;
     1388        }
    13071389    }
    13081390}
  • trunk/tests/phpunit/includes/utils.php

    r36272 r36316  
    336336 */
    337337function _unregister_post_type( $cpt_name ) {
    338     unset( $GLOBALS['wp_post_types'][ $cpt_name ] );
    339     unset( $GLOBALS['_wp_post_type_features'][ $cpt_name ] );
    340 
    341     foreach ( $GLOBALS['wp_taxonomies'] as $taxonomy ) {
    342         if ( false !== $key = array_search( $cpt_name, $taxonomy->object_type ) ) {
    343             unset( $taxonomy->object_type[$key] );
    344         }
    345     }
     338    unregister_post_type( $cpt_name );
    346339}
    347340
  • trunk/tests/phpunit/tests/post/types.php

    r34102 r36316  
    160160        _unregister_post_type( 'foo' );
    161161    }
     162
     163    /**
     164     * @ticket 14761
     165     */
     166    public function test_unregister_post_type() {
     167        register_post_type( 'foo' );
     168        $this->assertTrue( unregister_post_type( 'foo' ) );
     169    }
     170
     171    /**
     172     * @ticket 14761
     173     */
     174    public function test_unregister_post_type_unknown_post_type() {
     175        $this->assertWPError( unregister_post_type( 'foo' ) );
     176    }
     177
     178    /**
     179     * @ticket 14761
     180     */
     181    public function test_unregister_post_type_twice() {
     182        register_post_type( 'foo' );
     183        $this->assertTrue( unregister_post_type( 'foo' ) );
     184        $this->assertWPError( unregister_post_type( 'foo' ) );
     185    }
     186
     187    /**
     188     * @ticket 14761
     189     */
     190    public function test_unregister_post_type_disallow_builtin_post_type() {
     191        $this->assertWPError( unregister_post_type( 'post' ) );
     192        $this->assertWPError( unregister_post_type( 'page' ) );
     193        $this->assertWPError( unregister_post_type( 'attachment' ) );
     194        $this->assertWPError( unregister_post_type( 'revision' ) );
     195        $this->assertWPError( unregister_post_type( 'nav_menu_item' ) );
     196    }
     197
     198    /**
     199     * @ticket 14761
     200     */
     201    public function test_unregister_post_type_removes_query_vars() {
     202        global $wp;
     203
     204        register_post_type( 'foo', array(
     205            'public'    => true,
     206            'query_var' => 'bar',
     207        ) );
     208
     209        $this->assertInternalType( 'int', array_search( 'bar', $wp->public_query_vars ) );
     210        $this->assertTrue( unregister_post_type( 'foo' ) );
     211        $this->assertFalse( array_search( 'bar', $wp->public_query_vars ) );
     212    }
     213
     214    /**
     215     * @ticket 14761
     216     */
     217    public function test_unregister_post_type_removes_rewrite_tags() {
     218        $this->set_permalink_structure( '/%postname%' );
     219
     220        global $wp_rewrite;
     221
     222        register_post_type( 'foo', array(
     223            'public'    => true,
     224            'query_var' => 'bar',
     225        ) );
     226
     227        $count_before = count( $wp_rewrite->rewritereplace );
     228
     229        $this->assertContains( '%foo%', $wp_rewrite->rewritecode );
     230        $this->assertContains( 'bar=', $wp_rewrite->queryreplace );
     231        $this->assertTrue( unregister_post_type( 'foo' ) );
     232        $this->assertNotContains( '%foo%', $wp_rewrite->rewritecode );
     233        $this->assertNotContains( 'bar=', $wp_rewrite->queryreplace );
     234        $this->assertSame( -- $count_before, count( $wp_rewrite->rewritereplace ) ); // Array was reduced by one value.
     235    }
     236
     237    /**
     238     * @ticket 14761
     239     */
     240    public function test_unregister_post_type_removes_rewrite_rules() {
     241        $this->set_permalink_structure( '/%postname%' );
     242
     243        global $wp_rewrite;
     244
     245        register_post_type( 'foo', array(
     246            'public'      => true,
     247            'has_archive' => true,
     248        ) );
     249
     250        $this->assertContains( 'index.php?post_type=foo', $wp_rewrite->extra_rules_top );
     251        $this->assertTrue( unregister_post_type( 'foo' ) );
     252        $this->assertNotContains( 'index.php?post_type=foo', $wp_rewrite->extra_rules_top );
     253    }
     254
     255    /**
     256     * @ticket 14761
     257     */
     258    public function test_unregister_post_type_removes_custom_meta_capabilities() {
     259        global $post_type_meta_caps;
     260
     261        register_post_type( 'foo', array(
     262            'public'          => true,
     263            'capability_type' => 'bar',
     264            'map_meta_cap' => true,
     265        ) );
     266
     267        $this->assertSame( 'read_post', $post_type_meta_caps['read_bar'] );
     268        $this->assertSame( 'delete_post', $post_type_meta_caps['delete_bar'] );
     269        $this->assertSame( 'edit_post', $post_type_meta_caps['edit_bar'] );
     270
     271        $this->assertTrue( unregister_post_type( 'foo' ) );
     272
     273        $this->assertFalse( isset( $post_type_meta_caps['read_bar'] ) );
     274        $this->assertFalse( isset( $post_type_meta_caps['delete_bar'] ) );
     275        $this->assertFalse( isset( $post_type_meta_caps['edit_bar'] ) );
     276    }
     277
     278    /**
     279     * @ticket 14761
     280     */
     281    public function test_unregister_post_type_removes_post_type_supports() {
     282        global $_wp_post_type_features;
     283
     284        register_post_type( 'foo', array(
     285            'public'   => true,
     286            'supports' => array( 'editor', 'author', 'title' ),
     287        ) );
     288
     289        $this->assertEqualSetsWithIndex(
     290            array(
     291                'editor' => true,
     292                'author' => true,
     293                'title'  => true,
     294            ),
     295            $_wp_post_type_features['foo']
     296        );
     297        $this->assertTrue( unregister_post_type( 'foo' ) );
     298        $this->assertFalse( isset( $_wp_post_type_features['foo'] ) );
     299    }
     300
     301    /**
     302     * @ticket 14761
     303     */
     304    public function test_unregister_post_type_removes_post_type_from_taxonomies() {
     305        global $wp_taxonomies;
     306
     307        register_post_type( 'foo', array(
     308            'public'     => true,
     309            'taxonomies' => array( 'category', 'post_tag' ),
     310        ) );
     311
     312        $this->assertInternalType( 'int', array_search( 'foo', $wp_taxonomies['category']->object_type, true ) );
     313        $this->assertInternalType( 'int', array_search( 'foo', $wp_taxonomies['post_tag']->object_type, true ) );
     314        $this->assertTrue( unregister_post_type( 'foo' ) );
     315        $this->assertFalse( array_search( 'foo', $wp_taxonomies['category']->object_type, true ) );
     316        $this->assertFalse( array_search( 'foo', $wp_taxonomies['post_tag']->object_type, true ) );
     317        $this->assertEmpty( get_object_taxonomies( 'foo' ) );
     318    }
     319
     320    /**
     321     * @ticket 14761
     322     */
     323    public function test_unregister_post_type_removes_the_future_post_hooks() {
     324        global $wp_filter;
     325
     326        register_post_type( 'foo', array(
     327            'public' => true,
     328        ) );
     329
     330        $this->assertSame( 1, count( $wp_filter['future_foo'] ) );
     331        $this->assertTrue( unregister_post_type( 'foo' ) );
     332        $this->assertSame( array(), $wp_filter['future_foo'] );
     333    }
     334
     335    /**
     336     * @ticket 14761
     337     */
     338    public function test_unregister_post_type_removes_meta_box_callback() {
     339        global $wp_filter;
     340
     341        register_post_type( 'foo', array(
     342            'public'               => true,
     343            'register_meta_box_cb' => '__return_empty_string',
     344        ) );
     345
     346        $this->assertSame( 1, count( $wp_filter['add_meta_boxes_foo'] ) );
     347        $this->assertTrue( unregister_post_type( 'foo' ) );
     348        $this->assertSame( array(), $wp_filter['add_meta_boxes_foo'] );
     349    }
     350
     351    /**
     352     * @ticket 14761
     353     */
     354    public function test_unregister_post_type_removes_post_type_from_global() {
     355        global $wp_post_types;
     356
     357        register_post_type( 'foo', array(
     358            'public' => true,
     359        ) );
     360
     361        $this->assertInternalType( 'object', $wp_post_types['foo'] );
     362        $this->assertInternalType( 'object', get_post_type_object( 'foo' ) );
     363
     364        $this->assertTrue( unregister_post_type( 'foo' ) );
     365
     366        $this->assertFalse( isset( $wp_post_types['foo'] ) );
     367        $this->assertNull( get_post_type_object( 'foo' ) );
     368    }
     369
     370    /**
     371     * @ticket 14761
     372     */
     373    public function test_post_type_does_not_exist_after_unregister_post_type() {
     374        register_post_type( 'foo', array(
     375            'public' => true,
     376        ) );
     377
     378        $this->assertTrue( unregister_post_type( 'foo' ) );
     379
     380        $this->assertFalse( post_type_exists( 'foo' ) );
     381    }
    162382}
Note: See TracChangeset for help on using the changeset viewer.