Skip to:
Content

BuddyPress.org

Ticket #7181: 7181.patch

File 7181.patch, 75.3 KB (added by imath, 3 years ago)
  • new file src/bp-core/admin/bp-core-admin-types.php

    diff --git src/bp-core/admin/bp-core-admin-types.php src/bp-core/admin/bp-core-admin-types.php
    new file mode 100644
    index 000000000..6b8db3f7a
    - +  
     1<?php
     2/**
     3 * BuddyPress Types Admin functions.
     4 *
     5 * @package BuddyPress
     6 * @subpackage Core
     7 * @since 7.0.0
     8 */
     9
     10// Exit if accessed directly.
     11if ( ! defined( 'ABSPATH' ) ) {
     12        exit;
     13}
     14
     15/**
     16 * Get default values for the taxonomy registered metadata.
     17 *
     18 * @since 7.0.0
     19 *
     20 * @param string $type_taxonomy The type's taxonomy name.
     21 * @return array                Default values for the taxonomy registered metadata.
     22 */
     23function bp_core_admin_get_type_default_meta_values( $type_taxonomy ) {
     24        $metadata_schema = bp_get_type_metadata_schema( false, $type_taxonomy );
     25        $metadata        = wp_list_pluck( $metadata_schema, 'type' );
     26
     27        // Set default values according to their schema type.
     28        foreach ( $metadata as $meta_key => $meta_value ) {
     29                if ( in_array( $meta_value, array( 'boolean', 'integer' ), true ) ) {
     30                        $metadata[ $meta_key ] = 0;
     31                } else {
     32                        $metadata[ $meta_key ] = '';
     33                }
     34        }
     35
     36        return $metadata;
     37}
     38
     39/**
     40 * Insert a new type into the database.
     41 *
     42 * @since 7.0.0
     43 *
     44 * @param array  $args {
     45 *     Array of arguments describing the object type.
     46 *
     47 *     @type string $taxonomy   The Type's taxonomy. Required.
     48 *     @type string $bp_type_id Unique string identifier for the member type. Required.
     49 *     @see keys of the array returned by bp_get_type_metadata_schema() for the other arguments.
     50 * }
     51 * @return integer|WP_Error The Type's term ID on success. A WP_Error object otherwise.
     52 */
     53function bp_core_admin_insert_type( $args = array() ) {
     54        $default_args = array(
     55                'taxonomy'   => '',
     56                'bp_type_id' => '',
     57        );
     58
     59        $args = array_map( 'wp_unslash', $args );
     60        $args = bp_parse_args(
     61                $args,
     62                $default_args,
     63                'admin_insert_type'
     64        );
     65
     66        if ( ! $args['bp_type_id'] || ! $args['taxonomy'] ) {
     67                 return new WP_Error(
     68                         'invalid_type_taxonomy',
     69                         __( 'The Type ID value is missing', 'buddypress' ),
     70                         array(
     71                                'message' => 1,
     72                         )
     73                );
     74        }
     75
     76        $type_id       = sanitize_title( $args['bp_type_id'] );
     77        $type_taxonomy = sanitize_key( $args['taxonomy'] );
     78
     79        /**
     80         * Filter here to check for an already existing type.
     81         *
     82         * @since 7.0.0
     83         *
     84         * @param boolean $value   True if the type exists. False otherwise.
     85         * @param string  $type_id The Type's ID.
     86         */
     87        $type_exists = apply_filters( "{$type_taxonomy}_check_existing_type", false, $type_id );
     88
     89        if ( false !== $type_exists ) {
     90                return new WP_Error(
     91                        'type_already_exists',
     92                        __( 'The Type already exists', 'buddypress' ),
     93                        array(
     94                           'message' => 5,
     95                        )
     96           );
     97        }
     98
     99        // Get defaulte values for metadata.
     100        $metadata = bp_core_admin_get_type_default_meta_values( $type_taxonomy );
     101
     102        // Validate metadata
     103        $metas = array_filter( array_intersect_key( $args, $metadata ) );
     104
     105        // Insert the Type into the database.
     106        $type_term_id = bp_insert_term(
     107                $type_id,
     108                $type_taxonomy,
     109                array(
     110                        'slug'  => $type_id,
     111                        'metas' => $metas,
     112                )
     113        );
     114
     115        if ( is_wp_error( $type_term_id ) ) {
     116                $type_term_id->add_data(
     117                        array(
     118                                'message' => 3,
     119                        )
     120                );
     121
     122                return $type_term_id;
     123        }
     124
     125        /**
     126         * Hook here to add code once the type has been inserted.
     127         *
     128         * @since 7.0.0
     129         *
     130         * @param integer $type_term_id  The Type's term_ID.
     131         * @param string  $type_taxonomy The Type's taxonomy name.
     132         * @param string  $type_id       The Type's ID.
     133         */
     134        do_action( 'bp_type_inserted', $type_term_id, $type_taxonomy, $type_id );
     135
     136        // Finally return the inserted Type's term ID.
     137        return $type_term_id;
     138}
     139
     140/**
     141 * Update a type into the database.
     142 *
     143 * @since 7.0.0
     144 *
     145 * @param array  $args {
     146 *     Array of arguments describing the object type.
     147 *
     148 *     @type string  $taxonomy     The Type's taxonomy. Required.
     149 *     @type integer $type_term_id The Type's term ID. Required.
     150 *     @see keys of the array returned by bp_get_type_metadata_schema() for the other arguments.
     151 * }
     152 * @return boolean|WP_Error True on success. A WP_Error object otherwise.
     153 */
     154function bp_core_admin_update_type( $args = array() ) {
     155        $default_args = array(
     156                'taxonomy'     => '',
     157                'type_term_id' => 0,
     158        );
     159
     160        $args = array_map( 'wp_unslash', $args );
     161        $args = bp_parse_args(
     162                $args,
     163                $default_args,
     164                'admin_update_type'
     165        );
     166
     167        if ( ! $args['type_term_id'] || ! $args['taxonomy'] ) {
     168                 return new WP_Error(
     169                         'invalid_type_taxonomy',
     170                         __( 'The Term Type ID value is missing', 'buddypress' ),
     171                         array(
     172                                'message' => 10,
     173                        )
     174                );
     175        }
     176
     177        $type_term_id  = (int) $args['type_term_id'];
     178        $type_taxonomy = sanitize_key( $args['taxonomy'] );
     179
     180        // Get defaulte values for metadata.
     181        $metadata  = bp_core_admin_get_type_default_meta_values( $type_taxonomy );
     182
     183        // Merge customs with defaults.
     184        $metas = wp_parse_args( $args, $metadata );
     185
     186        // Validate metadata
     187        $metas = array_intersect_key( $metas, $metadata );
     188
     189        foreach ( $metas as $meta_key => $meta_value ) {
     190                if ( '' === $meta_value ) {
     191                        delete_term_meta( $type_term_id, $meta_key );
     192                } else {
     193                        update_term_meta( $type_term_id, $meta_key, $meta_value );
     194                }
     195        }
     196
     197        /**
     198         * Hook here to add code once the type has been updated.
     199         *
     200         * @since 7.0.0
     201         *
     202         * @param integer $type_term_id  The Type's term_ID.
     203         * @param string  $type_taxonomy The Type's taxonomy name.
     204         */
     205        do_action( 'bp_type_updated', $type_term_id, $type_taxonomy );
     206
     207        // Finally informs about the successfull update.
     208        return true;
     209}
     210
     211/**
     212 * Delete a type from the database.
     213 *
     214 * @since 7.0.0
     215 *
     216 * @param array  $args {
     217 *     Array of arguments describing the object type.
     218 *
     219 *     @type string  $taxonomy     The Type's taxonomy. Required.
     220 *     @type integer $type_term_id The Type's term ID. Required.
     221 * }
     222 * @return boolean|WP_Error True on success. A WP_Error object otherwise.
     223 */
     224function bp_core_admin_delete_type( $args = array() ) {
     225        $default_args = array(
     226                'taxonomy'     => '',
     227                'type_term_id' => 0,
     228        );
     229
     230        $args = array_map( 'wp_unslash', $args );
     231        $args = bp_parse_args(
     232                $args,
     233                $default_args,
     234                'admin_delete_type'
     235        );
     236
     237        if ( ! $args['type_term_id'] || ! $args['taxonomy'] ) {
     238                 return new WP_Error(
     239                         'invalid_type_taxonomy',
     240                         __( 'The Term Type ID value is missing', 'buddypress' ),
     241                         array(
     242                                'message' => 10,
     243                        )
     244                );
     245        }
     246
     247        $type_term_id  = (int) $args['type_term_id'];
     248        $type_taxonomy = sanitize_key( $args['taxonomy'] );
     249        $type_term     = bp_get_term_by( 'id', $type_term_id, $type_taxonomy );
     250
     251        if ( ! $type_term ) {
     252                return new WP_Error(
     253                        'type_doesnotexist',
     254                        __( 'The type was not deleted: it does not exist.', 'buddypress' ),
     255                        array(
     256                           'message' => 6,
     257                        )
     258                );
     259        }
     260
     261        /** This filter is documented in bp-core/classes/class-bp-admin-types.php */
     262        $registered_by_code_types = apply_filters( "{$type_taxonomy}_registered_by_code", array() );
     263
     264        if ( isset( $registered_by_code_types[ $type_term->name ] ) ) {
     265                return new WP_Error(
     266                        'type_register_by_code',
     267                        __( 'This type is registered using code, deactivate the plugin or remove the custom code before trying to delete it again.', 'buddypress' ),
     268                        array(
     269                           'message' => 7,
     270                        )
     271                );
     272        }
     273
     274        $deleted = bp_delete_term( $type_term_id, $type_taxonomy );
     275
     276        if ( true !== $deleted ) {
     277                return new WP_Error(
     278                        'type_not_deleted',
     279                        __( 'There was an error while trying to delete this type.', 'buddypress' ),
     280                        array(
     281                           'message' => 8,
     282                        )
     283                );
     284        }
     285
     286        /**
     287         * Hook here to add code once the type has been deleted.
     288         *
     289         * @since 7.0.0
     290         *
     291         * @param integer $type_term_id  The Type's term_ID.
     292         * @param string  $type_taxonomy The Type's taxonomy name.
     293         */
     294        do_action( 'bp_type_deleted', $type_term_id, $type_taxonomy );
     295
     296        // Finally informs about the successfull delete.
     297        return true;
     298}
  • new file src/bp-core/admin/js/types-admin.js

    diff --git src/bp-core/admin/js/types-admin.js src/bp-core/admin/js/types-admin.js
    new file mode 100644
    index 000000000..077fdcf3d
    - +  
     1( function() {
     2        var bpTypesCustomizeForm = function() {
     3                if ( document.querySelector( '#addtag input[name="post_type"]' ) ) {
     4                        document.querySelector( '#addtag input[name="post_type"]' ).remove();
     5                }
     6
     7                if ( document.querySelectorAll( '.form-field' ) ) {
     8                        document.querySelectorAll( '.form-field' ).forEach( function( element ) {
     9                                if ( -1 === element.classList.value.indexOf( 'bp-types-form' ) ) {
     10                                        element.remove();
     11                                }
     12                        } );
     13                }
     14
     15                if ( document.querySelector( '#bp_type_has_directory' ) ) {
     16                        if ( true === document.querySelector( '#bp_type_has_directory' ).checked ) {
     17                                document.querySelector( '.term-bp_type_directory_slug-wrap' ).classList.add( 'bp-set-directory-slug' );
     18                        }
     19
     20                        document.querySelector( '#bp_type_has_directory' ).addEventListener( 'change', function( event ) {
     21                                if ( true === event.target.checked ) {
     22                                        document.querySelector( '.term-bp_type_directory_slug-wrap' ).classList.add( 'bp-set-directory-slug' );
     23                                        document.querySelector( '#bp_type_directory_slug' ).removeAttribute( 'disabled' );
     24                                } else {
     25                                        document.querySelector( '.term-bp_type_directory_slug-wrap' ).classList.remove( 'bp-set-directory-slug' );
     26                                        document.querySelector( '#bp_type_directory_slug' ).setAttribute( 'disabled', 'disabled' );
     27                                }
     28                        } );
     29                }
     30
     31                if ( document.querySelector( '#delete-link' ) ) {
     32                        document.querySelector( '#delete-link' ).remove();
     33                }
     34        };
     35
     36        if ( 'loading' === document.readyState ) {
     37                document.addEventListener( 'DOMContentLoaded', bpTypesCustomizeForm );
     38        } else {
     39                bpTypesCustomizeForm;
     40        }
     41} )();
  • src/bp-core/bp-core-actions.php

    diff --git src/bp-core/bp-core-actions.php src/bp-core/bp-core-actions.php
    index 89296dd79..caf628b97 100644
    add_action( 'bp_init', 'bp_add_rewrite_rules', 30 ); 
    8282add_action( 'bp_init', 'bp_add_permastructs',        40 );
    8383
    8484/**
    85  * The bp_register_taxonomies hook - Attached to 'bp_init' @ priority 2 above.
     85 * The bp_register_taxonomies hooks - Attached to 'bp_init' @ priority 2 above.
    8686 */
    8787add_action( 'bp_register_taxonomies', 'bp_register_member_types' );
     88add_action( 'bp_register_taxonomies', 'bp_register_type_metadata', 20 );
    8889
    8990/**
    9091 * Late includes.
  • src/bp-core/bp-core-cache.php

    diff --git src/bp-core/bp-core-cache.php src/bp-core/bp-core-cache.php
    index 2868eb87f..12c674241 100644
    function bp_invitations_reset_cache_incrementor() { 
    390390}
    391391add_action( 'bp_invitation_after_save', 'bp_invitations_reset_cache_incrementor' );
    392392add_action( 'bp_invitation_after_delete', 'bp_invitations_reset_cache_incrementor' );
     393
     394/**
     395 * Add a cache group for Database object types.
     396 *
     397 * @since 7.0.0
     398 */
     399function bp_set_object_type_terms_cache_group() {
     400        wp_cache_add_global_groups( 'bp_object_terms' );
     401}
     402add_action( 'bp_setup_cache_groups', 'bp_set_object_type_terms_cache_group' );
     403
     404/**
     405 * Clear the Database object types cache.
     406 *
     407 * @since 7.0.0
     408 *
     409 * @param int $type_id The Type's term ID.
     410 * @param string $taxonomy The Type's taxonomy name.
     411 */
     412function bp_clear_object_type_terms_cache( $type_id = 0, $taxonomy = '' ) {
     413        wp_cache_delete( $taxonomy, 'bp_object_terms' );
     414}
     415add_action( 'bp_type_inserted', 'bp_clear_object_type_terms_cache' );
     416add_action( 'bp_type_updated', 'bp_clear_object_type_terms_cache' );
     417add_action( 'bp_type_deleted', 'bp_clear_object_type_terms_cache' );
  • src/bp-core/bp-core-dependency.php

    diff --git src/bp-core/bp-core-dependency.php src/bp-core/bp-core-dependency.php
    index cb3a3f4f5..91d2566b3 100644
    function bp_register_taxonomies() { 
    9595        do_action( 'bp_register_taxonomies' );
    9696}
    9797
     98/**
     99 * Fire the 'bp_register_type_metadata' action, where plugins should register metadata for their custom BuddyPress types.
     100 *
     101 * @since 7.0.0
     102 */
     103function bp_register_type_metadata() {
     104
     105        /**
     106         * Fires inside the 'bp_register_type_metadata' function, where plugins should register metadata for their custom BuddyPress types.
     107         *
     108         * @since 7.0.0
     109         */
     110        do_action( 'bp_register_type_metadata' );
     111}
     112
    98113/**
    99114 * Fire the 'bp_register_post_types' action, where plugins should register post types.
    100115 *
  • src/bp-core/bp-core-functions.php

    diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
    index c1481135e..74b6830a3 100644
    function bp_get_email_post_type_supports() { 
    29362936
    29372937/** Taxonomies *****************************************************************/
    29382938
     2939/**
     2940 * Returns the BP Taxonomy common arguments.
     2941 *
     2942 * @since 7.0.0
     2943 *
     2944 * @return array The BP Taxonomy common arguments.
     2945 */
     2946function bp_get_taxonomy_common_args() {
     2947        return array(
     2948                'public'        => false,
     2949                'show_in_rest'  => false,
     2950                'query_var'     => false,
     2951                'rewrite'       => false,
     2952                'show_in_menu'  => false,
     2953                'show_tagcloud' => false,
     2954                'show_ui'       => bp_is_root_blog() && bp_current_user_can( 'bp_moderate' ),
     2955        );
     2956}
     2957
     2958/**
     2959 * Returns the BP Taxonomy common labels.
     2960 *
     2961 * @since 7.0.0
     2962 *
     2963 * @return array The BP Taxonomy common labels.
     2964 */
     2965function bp_get_taxonomy_common_labels() {
     2966        return array(
     2967                'bp_type_name'           => _x( 'Name', 'BP Type name label', 'buddypress' ),
     2968                'bp_type_singular_name'  => _x( 'Singular name', 'BP Type singular name label', 'buddypress' ),
     2969                'bp_type_has_directory'  => _x( 'Add Type-Filtered Directory View', 'BP Type has directory checkbox label', 'buddypress' ),
     2970                'bp_type_directory_slug' => _x( 'Custom type directory slug', 'BP Type slug label', 'buddypress' ),
     2971        );
     2972}
     2973
    29392974/**
    29402975 * Output the name of the email type taxonomy.
    29412976 *
    function bp_get_email_tax_type_labels() { 
    29983033        ) );
    29993034}
    30003035
     3036/**
     3037 * Return arguments used by the email type taxonomy.
     3038 *
     3039 * @since 7.0.0
     3040 *
     3041 * @return array
     3042 */
     3043function bp_get_email_tax_type_args() {
     3044
     3045        /**
     3046         * Filters emails type taxonomy args.
     3047         *
     3048         * @since 7.0.0
     3049         *
     3050         * @param array $value Associative array (key => arg).
     3051         */
     3052        return apply_filters(
     3053                'bp_register_email_tax_type',
     3054                array_merge(
     3055                        array(
     3056                                'description'   => _x( 'BuddyPress email types', 'email type taxonomy description', 'buddypress' ),
     3057                                'labels'        => bp_get_email_tax_type_labels(),
     3058                                'meta_box_cb'   => 'bp_email_tax_type_metabox',
     3059                        ),
     3060                        bp_get_taxonomy_common_args()
     3061                )
     3062        );
     3063}
     3064
     3065/**
     3066 * Returns the default BuddyPress type metadata schema.
     3067 *
     3068 * @since 7.0.0
     3069 *
     3070 * @param  boolean $suppress_filters Whether to suppress filters. Default `false`.
     3071 * @param  string  $type_taxonomy    Optional. the Type's taxonomy name.
     3072 * @return array                     The default BuddyPress type metadata schema.
     3073 */
     3074function bp_get_type_metadata_schema( $suppress_filters = false, $type_taxonomy = '' ) {
     3075        $schema = array(
     3076                'bp_type_name' => array(
     3077                        'description'       => __( 'The name of your type, at the plural form.', 'buddypress' ),
     3078                        'type'              => 'string',
     3079                        'single'            => true,
     3080                        'sanitize_callback' => 'sanitize_text_field',
     3081                ),
     3082                'bp_type_singular_name' => array(
     3083                        'description'       => __( 'The name of your type, at the singular form.', 'buddypress' ),
     3084                        'type'              => 'string',
     3085                        'single'            => true,
     3086                        'sanitize_callback' => 'sanitize_text_field',
     3087                ),
     3088                'bp_type_has_directory' => array(
     3089                        'description'       => __( 'Add a list of members matching the member type available on the Members Directory page (e.g. site.url/members/type/teacher/).', 'buddypress' ),
     3090                        'type'              => 'boolean',
     3091                        'single'            => true,
     3092                        'sanitize_callback' => 'absint',
     3093                ),
     3094                'bp_type_directory_slug' => array(
     3095                        'label'             => __( 'Custom type directory slug', 'buddypress' ),
     3096                        'description'       => __( 'If you want to use a slug that is different from the Member Type ID above, enter it here.', 'buddypress' ),
     3097                        'type'              => 'string',
     3098                        'single'            => true,
     3099                        'sanitize_callback' => 'sanitize_title',
     3100                ),
     3101        );
     3102
     3103        if ( true === $suppress_filters ) {
     3104                return $schema;
     3105        }
     3106
     3107        /**
     3108         * Filter here to add new meta to the BuddyPress type metadata.
     3109         *
     3110         * @since 7.0.0
     3111         *
     3112         * @param array  $schema        Associative array (name => arguments).
     3113         * @param string $type_taxonomy The Type's taxonomy name.
     3114         */
     3115        return apply_filters( 'bp_get_type_metadata_schema', $schema, $type_taxonomy );
     3116}
     3117
     3118/**
     3119 * Registers a meta key for BuddyPress types.
     3120 *
     3121 * @since 7.0.0
     3122 *
     3123 * @param string $type_tax The BuddyPress type taxonomy.
     3124 * @param string $meta_key The meta key to register.
     3125 * @param array  $args     Data used to describe the meta key when registered. See
     3126 *                         {@see register_meta()} for a list of supported arguments.
     3127 * @return bool True if the meta key was successfully registered, false if not.
     3128 */
     3129function bp_register_type_meta( $type_tax, $meta_key, array $args ) {
     3130        $taxonomies = wp_list_pluck( bp_get_default_taxonomies(), 'component' );
     3131
     3132        if ( ! isset( $taxonomies[ $type_tax ] ) ) {
     3133                return false;
     3134        }
     3135
     3136        // register_term_meta() was introduced in WP 4.9.8.
     3137        if ( ! function_exists( 'register_term_meta' ) ) {
     3138                $args['object_subtype'] = $type_tax;
     3139
     3140                return register_meta( 'term', $meta_key, $args );
     3141        }
     3142
     3143        return register_term_meta( $type_tax, $meta_key, $args );
     3144}
     3145
     3146/**
     3147 * Update a list of metadata for a given type ID and a given taxonomy.
     3148 *
     3149 * @since 7.0.0
     3150 *
     3151 * @param  integer $type_id    The database ID of the BP Type.
     3152 * @param  string  $taxonomy   The BP Type taxonomy.
     3153 * @param  array   $type_metas An associative array (meta_key=>meta_value).
     3154 * @return boolean             False on failure. True otherwise.
     3155 */
     3156function bp_update_type_metadata( $type_id = 0, $taxonomy = '', $type_metas = array() ) {
     3157        if ( ! $type_id || ! $taxonomy || ! is_array( $type_metas ) ) {
     3158                return false;
     3159        }
     3160
     3161        foreach ( $type_metas as $meta_key => $meta_value ) {
     3162                if ( ! registered_meta_key_exists( 'term', $meta_key, $taxonomy ) ) {
     3163                        continue;
     3164                }
     3165
     3166                update_term_meta( $type_id, $meta_key, $meta_value );
     3167        }
     3168
     3169        return true;
     3170}
     3171
     3172/**
     3173 * Get types for a given BP Taxonomy.
     3174 *
     3175 * @since 7.0.0
     3176 *
     3177 * @param string $taxonomy The taxonomy to transform terms in types for.
     3178 * @param array  $types    Existing types to merge with the types found into the database.
     3179 *                         For instance this function is used internally to merge Group/Member
     3180 *                         types registered using code with the ones created by the administrator
     3181 *                         from the Group/Member types Administration screen. If not provided, only
     3182 *                         Types created by the administrator will be returned.
     3183 *                         Optional.
     3184 * @return array           The types of the given taxonomy.
     3185 */
     3186function bp_get_taxonomy_types( $taxonomy = '', $types = array() ) {
     3187        if ( ! $taxonomy ) {
     3188                return $types;
     3189        }
     3190
     3191        $db_types = wp_cache_get( $taxonomy, 'bp_object_terms' );
     3192
     3193        if ( ! $db_types ) {
     3194                $terms = bp_get_terms(
     3195                        array(
     3196                                'taxonomy' => $taxonomy,
     3197                        )
     3198                );
     3199
     3200                if ( ! is_array( $terms ) ) {
     3201                        return $types;
     3202                }
     3203
     3204                $type_metadata = array_keys( get_registered_meta_keys( 'term', $taxonomy ) );
     3205
     3206                foreach ( $terms as $term ) {
     3207                        $type_name                      = $term->name;
     3208                        $db_types[ $type_name ]         = new stdClass();
     3209                        $db_types[ $type_name ]->db_id  = $term->term_id;
     3210                        $db_types[ $type_name ]->labels = array();
     3211                        $db_types[ $type_name ]->name   = $type_name;
     3212
     3213                        if ( $type_metadata ) {
     3214                                foreach ( $type_metadata as $meta_key ) {
     3215                                        $type_key = str_replace( 'bp_type_', '', $meta_key );
     3216                                        if ( in_array( $type_key, array( 'name', 'singular_name' ), true ) ) {
     3217                                                $db_types[ $type_name ]->labels[ $type_key ] = get_term_meta( $term->term_id, $meta_key, true );
     3218                                        } else {
     3219                                                $db_types[ $type_name ]->{$type_key} = get_term_meta( $term->term_id, $meta_key, true );
     3220                                        }
     3221                                }
     3222                        }
     3223                }
     3224
     3225                wp_cache_set( $taxonomy, $db_types, 'bp_object_terms' );
     3226        }
     3227
     3228        if ( is_array( $db_types ) ) {
     3229                foreach ( $db_types as $db_type_name => $db_type ) {
     3230                        // Override props of registered by code types if customized by the admun user.
     3231                        if ( isset( $types[ $db_type_name ] ) && isset( $types[ $db_type_name ]->code ) && $types[ $db_type_name ]->code ) {
     3232                                // Merge Labels.
     3233                                if ( $db_type->labels ) {
     3234                                        foreach ( $db_type->labels as $key_label => $value_label ) {
     3235                                                if ( '' !== $value_label ) {
     3236                                                        $types[ $db_type_name ]->labels[ $key_label ] = $value_label;
     3237                                                }
     3238                                        }
     3239                                }
     3240
     3241                                // Merge other properties.
     3242                                foreach ( get_object_vars( $types[ $db_type_name ] ) as $key_prop => $value_prop ) {
     3243                                        if ( 'labels' === $key_prop || 'name' === $key_prop ) {
     3244                                                continue;
     3245                                        }
     3246
     3247                                        if ( isset( $db_type->{$key_prop} ) && '' !== $db_type->{$key_prop} ) {
     3248                                                $types[ $db_type_name  ]->{$key_prop} = $db_type->{$key_prop};
     3249                                        }
     3250                                }
     3251
     3252                                unset( $db_types[ $db_type_name ] );
     3253                        }
     3254                }
     3255        }
     3256
     3257        return array_merge( $types, (array) $db_types );
     3258}
    30013259
    30023260/** Email *****************************************************************/
    30033261
  • src/bp-core/bp-core-taxonomy.php

    diff --git src/bp-core/bp-core-taxonomy.php src/bp-core/bp-core-taxonomy.php
    index 14334e00d..69932c953 100644
     
    1414// Exit if accessed directly.
    1515defined( 'ABSPATH' ) || exit;
    1616
     17/**
     18 * Returns default BuddyPress taxonomies.
     19 *
     20 * @since 7.0.0
     21 *
     22 * @return array The BuddyPress default taxonomies.
     23 */
     24function bp_get_default_taxonomies() {
     25        $taxonomies = array(
     26                // Member Type.
     27                bp_get_member_type_tax_name() => array(
     28                        'object'    => 'user',
     29                        'component' => 'members',
     30                        'args'      => bp_get_member_type_tax_args(),
     31                ),
     32                // Email type.
     33                bp_get_email_tax_type()       => array(
     34                        'object'    => bp_get_email_post_type(),
     35                        'component' => 'core',
     36                        'args'      => bp_get_email_tax_type_args(),
     37                ),
     38        );
     39
     40        /**
     41         * This filter should only be used by built-in BuddyPress Components.
     42         *
     43         * @since 7.0.0
     44         *
     45         * @param array $taxonomies The taxonomy arguments used for WordPress registration.
     46         */
     47        return apply_filters( 'bp_get_default_taxonomies', $taxonomies );
     48}
     49
    1750/**
    1851 * Register our default taxonomies.
    1952 *
    2053 * @since 2.2.0
    2154 */
    2255function bp_register_default_taxonomies() {
    23         // Member Type.
    24         register_taxonomy( bp_get_member_type_tax_name(), 'user', array(
    25                 'public' => false,
    26         ) );
    27 
    28         // Email type.
    29         register_taxonomy(
    30                 bp_get_email_tax_type(),
    31                 bp_get_email_post_type(),
    32                 apply_filters( 'bp_register_email_tax_type', array(
    33                         'description'   => _x( 'BuddyPress email types', 'email type taxonomy description', 'buddypress' ),
    34                         'labels'        => bp_get_email_tax_type_labels(),
    35                         'meta_box_cb'   => 'bp_email_tax_type_metabox',
    36                         'public'        => false,
    37                         'query_var'     => false,
    38                         'rewrite'       => false,
    39                         'show_in_menu'  => false,
    40                         'show_tagcloud' => false,
    41                         'show_ui'       => bp_is_root_blog() && bp_current_user_can( 'bp_moderate' ),
    42                 ) )
    43         );
     56        $taxonomies = bp_get_default_taxonomies();
     57
     58        foreach ( $taxonomies as $taxonomy_name => $taxonomy_params ) {
     59                if ( ! isset( $taxonomy_params['object'] ) || ! isset( $taxonomy_params['args'] ) ) {
     60                        continue;
     61                }
     62
     63                register_taxonomy(
     64                        $taxonomy_name,
     65                        $taxonomy_params['object'],
     66                        $taxonomy_params['args']
     67                );
     68        }
    4469}
    4570add_action( 'bp_register_taxonomies', 'bp_register_default_taxonomies' );
    4671
    function bp_get_term_by( $field, $value, $taxonomy = '', $output = OBJECT, $filt 
    277302
    278303        return $term;
    279304}
     305
     306/**
     307 * Add a new taxonomy term to the database.
     308 *
     309 * @since 7.0.0
     310 *
     311 * @param string $term     The BP term name to add.
     312 * @param string $taxonomy The BP taxonomy to which to add the BP term.
     313 * @param array  $args {
     314 *     Optional. Array of arguments for inserting a BP term.
     315 *     @type string $description The term description. Default empty string.
     316 *     @type string $slug        The term slug to use. Default empty string.
     317 *     @type array  $metas       The term metas to add. Default empty array.
     318 * }
     319 * @return array|WP_Error An array containing the `term_id` and `term_taxonomy_id`,
     320 *                        WP_Error otherwise.
     321 */
     322function bp_insert_term( $term, $taxonomy = '', $args = array() ) {
     323        if ( ! taxonomy_exists( $taxonomy ) ) {
     324                return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.', 'buddypress' ) );
     325        }
     326
     327        $site_id = bp_get_taxonomy_term_site_id( $taxonomy );
     328
     329        $switched = false;
     330        if ( $site_id !== get_current_blog_id() ) {
     331                switch_to_blog( $site_id );
     332                bp_register_taxonomies();
     333                $switched = true;
     334        }
     335
     336        $term_metas = array();
     337        if ( isset( $args['metas'] ) ) {
     338                $term_metas = (array) $args['metas'];
     339                unset( $args['metas'] );
     340        }
     341
     342        /**
     343         * Fires before a BP Term is added to the database.
     344         *
     345         * @since 7.0.0
     346         *
     347         * @param string $term     The BP term name to add.
     348         * @param string $taxonomy The BP taxonomy to which to add the term.
     349         * @param array  $args     Array of arguments for inserting a BP term.
     350         */
     351        do_action( 'bp_before_insert_term', $term, $taxonomy, $args );
     352
     353        $tt_id = wp_insert_term( $term, $taxonomy, $args );
     354
     355        if ( is_wp_error( $tt_id ) ) {
     356                return $tt_id;
     357        }
     358
     359        $term_id = reset( $tt_id );
     360
     361        if ( $term_metas ) {
     362                bp_update_type_metadata( $term_id, $taxonomy, $term_metas );
     363        }
     364
     365        if ( $switched ) {
     366                restore_current_blog();
     367        }
     368
     369        /**
     370         * Fires when taxonomy terms have been set on BuddyPress objects.
     371         *
     372         * @since 7.0.0
     373         *
     374         * @param array  $tt_ids    An array containing the `term_id` and `term_taxonomy_id`.
     375         * @param string $taxonomy  Taxonomy name.
     376         * @param array  $term_metas The term metadata.
     377         */
     378        do_action( 'bp_insert_term', $tt_id, $taxonomy, $term_metas );
     379
     380        return $tt_id;
     381}
     382
     383/**
     384 * Get taxonomy BP Terms from the database.
     385 *
     386 * @since 7.0.0
     387 *
     388 * @param array  $args {
     389 *     Array of arguments to query BP Terms.
     390 *     @see `get_terms()` for full description of arguments in case of a member type.
     391 * }
     392 * @return array The list of terms matching arguments.
     393 */
     394function bp_get_terms( $args = array() ) {
     395        $args = bp_parse_args(
     396                $args,
     397                array(
     398                        'taxonomy'   => '',
     399                        'number'     => '',
     400                        'hide_empty' => false,
     401                ),
     402                'get_terms'
     403        );
     404
     405        if ( ! $args['taxonomy'] ) {
     406                return array();
     407        }
     408
     409        $site_id = bp_get_taxonomy_term_site_id( $args['taxonomy'] );
     410
     411        $switched = false;
     412        if ( $site_id !== get_current_blog_id() ) {
     413                switch_to_blog( $site_id );
     414                bp_register_taxonomies();
     415                $switched = true;
     416        }
     417
     418        $terms = get_terms( $args );
     419
     420        if ( $switched ) {
     421                restore_current_blog();
     422        }
     423
     424        /**
     425         * Filter here to modify the BP Terms found into the database.
     426         *
     427         * @since 7.0.0
     428         *
     429         * @param array $terms The list of terms matching arguments.
     430         * @param array $args  Array of arguments used to query BP Terms.
     431         */
     432        return apply_filters(
     433                'bp_get_terms',
     434                $terms,
     435                $args
     436        );
     437}
     438
     439/**
     440 * Deletes a BP Term.
     441 *
     442 * @since 7.0.0
     443 *
     444 * @param int     $term_id  The BP Term ID. Required.
     445 * @param string  $taxonomy The BP Taxonomy Name. Required.
     446 * @return bool|WP_Error True on success, WP_Error on failure.
     447 */
     448function bp_delete_term( $term_id = 0, $taxonomy = '' ) {
     449        if ( ! $term_id || ! $taxonomy ) {
     450                return new WP_Error( 'missing_arguments', __( 'Sorry, the term ID and the taxonomy are required arguments.', 'buddypress' ) );
     451        }
     452
     453        $site_id = bp_get_taxonomy_term_site_id( $taxonomy );
     454
     455        $switched = false;
     456        if ( $site_id !== get_current_blog_id() ) {
     457                switch_to_blog( $site_id );
     458                bp_register_taxonomies();
     459                $switched = true;
     460        }
     461
     462        /**
     463         * Fires before a BP Term is deleted from the database.
     464         *
     465         * @since 7.0.0
     466         *
     467         * @param int    $term_id  The BP Term ID.
     468         * @param string $taxonomy The BP Taxonomy Name.
     469         */
     470        do_action( 'bp_before_delete_term', $term_id, $taxonomy );
     471
     472        $deleted = wp_delete_term( $term_id, $taxonomy );
     473
     474        if ( $switched ) {
     475                restore_current_blog();
     476        }
     477
     478        if ( is_wp_error( $deleted ) ) {
     479                return $deleted;
     480        }
     481
     482        if ( false === $deleted ) {
     483                return new WP_Error( 'inexistant_term', __( 'Sorry, the term does not exist.', 'buddypress' ) );
     484        }
     485
     486        if ( 0 === $deleted ) {
     487                return new WP_Error( 'default_term', __( 'Sorry, the default term cannot be deleted.', 'buddypress' ) );
     488        }
     489
     490        /**
     491         * Fires once a BP Term has been deleted from the database.
     492         *
     493         * @since 7.0.0
     494         *
     495         * @param boolean $deleted True.
     496         * @param int     $term_id  The deleted BP Term ID.
     497         * @param string  $taxonomy The BP Taxonomy Name of the deleted BP Term ID.
     498         */
     499        do_action( 'bp_delete_term', $deleted, $term_id, $taxonomy );
     500
     501        return $deleted;
     502}
  • new file src/bp-core/classes/class-bp-admin-types.php

    diff --git src/bp-core/classes/class-bp-admin-types.php src/bp-core/classes/class-bp-admin-types.php
    new file mode 100644
    index 000000000..0ef4201ea
    - +  
     1<?php
     2/**
     3 * BuddyPress Types Admin Class.
     4 *
     5 * @package BuddyPress
     6 * @subpackage CoreAdministration
     7 * @since 7.0.0
     8 */
     9
     10// Exit if accessed directly.
     11if ( ! defined( 'ABSPATH' ) ) {
     12        exit;
     13}
     14
     15if ( ! class_exists( 'BP_Admin_Types' ) ) :
     16
     17/**
     18 * Load BuddyPress Types admin area.
     19 *
     20 * @since 7.O.0
     21 */
     22class BP_Admin_Types {
     23        /**
     24         * Current BuddyPress taxonomy.
     25         *
     26         * @since 7.0.0
     27         * @var string
     28         */
     29        public $taxonomy = '';
     30
     31        /**
     32         * All registered BuddyPress taxonomies.
     33         *
     34         * @since 7.0.0
     35         * @var array()
     36         */
     37        public $taxonomies = array();
     38
     39        /**
     40         * Current screen ID.
     41         *
     42         * @since 7.0.0
     43         * @var string
     44         */
     45        public $screen_id = '';
     46
     47        /**
     48         * The main BuddyPress Types admin loader.
     49         *
     50         * @since 7.0.0
     51         */
     52        public function __construct() {
     53                $this->setup_globals();
     54
     55                if ( $this->taxonomy && $this->screen_id ) {
     56                        $this->includes();
     57                        $this->setup_hooks();
     58
     59                        if ( isset( $_POST['action'] ) || isset( $_GET['action'] ) ) {
     60                                if ( isset( $_GET['action'] ) ) {
     61                                        $action = wp_unslash( $_GET['action'] );
     62                                } else {
     63                                        $action = wp_unslash( $_POST['action'] );
     64                                }
     65
     66                                $this->handle_action( $action );
     67                        }
     68                }
     69        }
     70
     71        /**
     72         * Register BP Types Admin.
     73         *
     74         * @since 7.0.0
     75         *
     76         * @return BP_Admin_Types
     77         */
     78        public static function register_types_admin() {
     79                if ( ! is_admin() ) {
     80                        return;
     81                }
     82
     83                $bp = buddypress();
     84
     85                if ( empty( $bp->core->types_admin ) ) {
     86                        $bp->core->types_admin = new self;
     87                }
     88
     89                return $bp->core->types_admin;
     90        }
     91
     92        /**
     93         * Set the globals.
     94         *
     95         * @since 7.0.0
     96         */
     97        private function setup_globals() {
     98                $current_screen = get_current_screen();
     99
     100                if ( isset( $current_screen->taxonomy ) && $current_screen->taxonomy ) {
     101                        $this->taxonomies = bp_get_default_taxonomies();
     102
     103                        if ( isset( $this->taxonomies[ $current_screen->taxonomy ] ) ) {
     104                                $this->taxonomy  = $current_screen->taxonomy;
     105                                $this->screen_id = $current_screen->id;
     106                        }
     107                }
     108        }
     109
     110        /**
     111         * Include Admin functions.
     112         *
     113         * @since 7.0.0
     114         */
     115        private function includes() {
     116                require plugin_dir_path( dirname( __FILE__ ) ) . 'admin/bp-core-admin-types.php';
     117        }
     118
     119        /**
     120         * Set hooks.
     121         *
     122         * @since 7.0.0
     123         */
     124        private function setup_hooks() {
     125                // Actions.
     126                add_action( 'admin_head-edit-tags.php', array( $this, 'screen_head' ) );
     127                add_action( 'admin_head-term.php', array( $this, 'screen_head' ) );
     128                add_action( 'bp_admin_enqueue_scripts', array( $this, 'screen_scripts' ) );
     129                add_action( "{$this->taxonomy}_add_form_fields", array( $this, 'add_form_fields' ), 10, 1 );
     130                add_action( "{$this->taxonomy}_edit_form_fields", array( $this, 'edit_form_fields' ), 10, 2 );
     131
     132                // Filters
     133                add_filter( 'bp_core_admin_register_scripts', array( $this, 'register_scripts' ) );
     134                add_filter( "manage_{$this->screen_id}_columns", array( $this, 'column_headers' ), 10, 1 );
     135                add_filter( "manage_{$this->taxonomy}_custom_column", array( $this, 'column_contents' ), 10, 3 );
     136                add_filter( "{$this->taxonomy}_row_actions", array( $this, 'row_actions' ), 10, 2 );
     137                add_filter( "bulk_actions-{$this->screen_id}", '__return_empty_array', 10, 1 );
     138        }
     139
     140        /**
     141         * Handle BP Type actions.
     142         *
     143         * @since 7.0.0
     144         *
     145         * @param string $action Required. The action to handle ('add-tag', 'editedtag' or 'delete' ).
     146         */
     147        private function handle_action( $action ) {
     148                $referer = wp_get_referer();
     149
     150                // Adding a new type into the database.
     151                if ( 'add-tag' === $action ) {
     152                        check_admin_referer( 'add-tag', '_wpnonce_add-tag' );
     153
     154                        $result = bp_core_admin_insert_type( $_POST );
     155
     156                        if ( is_wp_error( $result ) ) {
     157                                $referer = add_query_arg(
     158                                        array_merge(
     159                                                $result->get_error_data(),
     160                                                array(
     161                                                        'error' => 1,
     162                                                )
     163                                        ),
     164                                        $referer
     165                                );
     166
     167                                wp_safe_redirect( $referer );
     168                                exit;
     169                        }
     170
     171                        wp_safe_redirect( add_query_arg( 'message', 2, $referer ) );
     172                        exit;
     173
     174                        // Updating an existing type intot the Database.
     175                } elseif ( 'editedtag' === $action ) {
     176                        $args                 = $_POST;
     177                        $args['type_term_id'] = 0;
     178                        unset( $args['tag_ID'] );
     179
     180                        if ( isset( $_POST['tag_ID'] ) ) {
     181                                $args['type_term_id'] = $_POST['tag_ID'];
     182                        }
     183
     184                        if ( isset( $_POST['taxonomy'] ) ) {
     185                                $args['taxonomy'] = $_POST['taxonomy'];
     186                        }
     187
     188                        check_admin_referer( 'update-tag_' . $args['type_term_id'] );
     189
     190                        $result = bp_core_admin_update_type( $args );
     191
     192                        if ( is_wp_error( $result ) ) {
     193                                $referer = add_query_arg(
     194                                        array_merge(
     195                                                $result->get_error_data(),
     196                                                array(
     197                                                        'error' => 1,
     198                                                )
     199                                        ),
     200                                        $referer
     201                                );
     202
     203                                wp_safe_redirect( $referer );
     204                                exit;
     205                        }
     206
     207                        wp_safe_redirect( add_query_arg( 'message', 4, $referer ) );
     208                        exit;
     209
     210                        // Deletes a type.
     211                } elseif ( 'delete' === $action ) {
     212                        $args                 = $_GET;
     213                        $args['type_term_id'] = 0;
     214                        unset( $args['tag_ID'] );
     215
     216                        if ( isset( $_GET['tag_ID'] ) ) {
     217                                $args['type_term_id'] = $_GET['tag_ID'];
     218                        }
     219
     220                        if ( isset( $_GET['taxonomy'] ) ) {
     221                                $args['taxonomy'] = $_GET['taxonomy'];
     222                        }
     223
     224                        check_admin_referer( 'delete-tag_' . $args['type_term_id'] );
     225                        $referer = remove_query_arg( array( 'action', 'tag_ID', '_wpnonce' ), $referer );
     226
     227                        // Delete the type.
     228                        $result = bp_core_admin_delete_type( $args );
     229
     230                        if ( is_wp_error( $result ) ) {
     231                                $referer = add_query_arg(
     232                                        array_merge(
     233                                                $result->get_error_data(),
     234                                                array(
     235                                                        'error' => 1,
     236                                                )
     237                                        ),
     238                                        $referer
     239                                );
     240
     241                                wp_safe_redirect( $referer );
     242                                exit;
     243                        }
     244
     245                        wp_safe_redirect( add_query_arg( 'message', 9, $referer ) );
     246                        exit;
     247                }
     248        }
     249
     250        /**
     251         * Override the Admin parent file to highlight the right menu.
     252         *
     253         * @since 7.0.0
     254         */
     255        public function screen_head() {
     256                global $parent_file;
     257
     258                if ( 'members' === $this->taxonomies[ $this->taxonomy ]['component'] ) {
     259                        $parent_file = 'users.php';
     260                } else {
     261                        $parent_file = 'bp-' . $this->taxonomies[ $this->taxonomy ]['component'];
     262                }
     263        }
     264
     265        /**
     266         * Registers script.
     267         *
     268         * @since 7.0.0
     269         */
     270        public function register_scripts( $scripts = array() ) {
     271                // Neutralize WordPress Taxonomy scripts.
     272                wp_dequeue_script( 'admin-tags' );
     273                wp_dequeue_script( 'inline-edit-tax' );
     274
     275                // Adapt some styles.
     276                wp_add_inline_style(
     277                        'common',
     278                        '.form-field:not(.bp-types-form), .term-bp_type_directory_slug-wrap:not(.bp-set-directory-slug), .edit-tag-actions #delete-link { display: none; }'
     279                );
     280
     281                // Register the Types admin script.
     282                return array_merge(
     283                        $scripts,
     284                        array(
     285                                'bp-admin-types' => array(
     286                                        'file'         => sprintf(
     287                                                '%1$sadmin/js/types-admin%2$s.js',
     288                                                plugin_dir_url( dirname( __FILE__ ) ),
     289                                                bp_core_get_minified_asset_suffix()
     290                                        ),
     291                                        'dependencies' => array(),
     292                                        'footer'       => true,
     293                                ),
     294                        )
     295                );
     296        }
     297
     298        /**
     299         * Enqueues script.
     300         *
     301         * @since 7.0.0
     302         */
     303        public function screen_scripts() {
     304                wp_enqueue_script( 'bp-admin-types' );
     305        }
     306
     307        /**
     308         * Outputs the BP type add form.
     309         *
     310         * @since 7.0.0
     311         *
     312         * @param string      $taxonomy The type taxonomy name.
     313         * @param null|object $type     The type object, `null` if not passed to the method.
     314         */
     315        public function add_form_fields( $taxonomy = '', $type = null ) {
     316                $taxonomy_object = get_taxonomy( $taxonomy );
     317                $labels          = get_taxonomy_labels( $taxonomy_object );
     318
     319                // Default values for the Type ID field.
     320                $type_id_label   = __( 'Type ID', 'buddypress' );
     321                $type_id_desc    = __( 'Enter a lower-case string without spaces or special characters (used internally to identify the type).', 'buddypress' );
     322
     323                if ( isset( $labels->bp_type_id_label ) && $labels->bp_type_id_label ) {
     324                        $type_id_label = $labels->bp_type_id_label;
     325                }
     326
     327                if ( isset( $labels->bp_type_id_description ) && $labels->bp_type_id_description ) {
     328                        $type_id_desc = $labels->bp_type_id_description;
     329                }
     330
     331                // Outputs the Type ID field.
     332                if ( isset( $type->name ) ) {
     333                        printf(
     334                                '<tr class="form-field bp-types-form form-required term-bp_type_id-wrap">
     335                                        <th scope="row"><label for="bp_type_id">%1$s</label></th>
     336                                        <td>
     337                                                <input name="bp_type_id" id="bp_type_id" type="text" value="%2$s" size="40" disabled="disabled">
     338                                        </td>
     339                                </tr>',
     340                                esc_html( $type_id_label ),
     341                                esc_attr( $type->name ),
     342                                esc_html( $type_id_desc )
     343                        );
     344                } else {
     345                        printf(
     346                                '<div class="form-field bp-types-form form-required term-bp_type_id-wrap">
     347                                        <label for="bp_type_id">%1$s</label>
     348                                        <input name="bp_type_id" id="bp_type_id" type="text" value="" size="40" aria-required="true">
     349                                        <p>%2$s</p>
     350                                </div>',
     351                                esc_html( $type_id_label ),
     352                                esc_html( $type_id_desc )
     353                        );
     354                }
     355
     356                // Gets the Type's metadata.
     357                $metafields = get_registered_meta_keys( 'term', $taxonomy );
     358
     359                foreach ( $metafields as $meta_key => $meta_schema ) {
     360                        if ( ! isset( $labels->{ $meta_key } ) || ! $labels->{ $meta_key } ) {
     361                                _doing_it_wrong(
     362                                        __METHOD__,
     363                                        __( 'Type metadata labels need to be set into the labels argument when registering your taxonomy using the meta key as the label’s key.', 'buddypress' )
     364                                        . ' ' .
     365                                        sprintf(
     366                                                /* translators: %s is the name of the Type meta key */
     367                                                __( 'As a result, the form elements for the "%s" meta key cannot be displayed', 'buddypress' ), $meta_key ),
     368                                        '7.0.0'
     369                                );
     370                                continue;
     371                        }
     372
     373                        $type_key = str_replace( 'bp_type_', '', $meta_key );
     374
     375                        if ( 'string' === $meta_schema['type'] ) {
     376                                if ( isset( $type->name ) ) {
     377                                        $type_prop_value = null;
     378                                        if ( in_array( $type_key, array( 'name', 'singular_name' ), true ) ) {
     379                                                if ( isset( $type->labels[ $type_key ] ) ) {
     380                                                        $type_prop_value = $type->labels[ $type_key ];
     381                                                }
     382
     383                                        } elseif ( isset( $type->{$type_key} ) ) {
     384                                                $type_prop_value = $type->{$type_key};
     385                                        }
     386
     387                                        printf(
     388                                                '<tr class="form-field bp-types-form form-required term-%1$s-wrap">
     389                                                        <th scope="row"><label for="%1$s">%2$s</label></th>
     390                                                        <td>
     391                                                                <input name="%1$s" id="%1$s" type="text" value="%3$s" size="40" aria-required="true">
     392                                                                <p class="description">%4$s</p>
     393                                                        </td>
     394                                                </tr>',
     395                                                esc_attr( $meta_key ),
     396                                                esc_html( $labels->{ $meta_key } ),
     397                                                esc_attr( $type_prop_value ),
     398                                                esc_html( $meta_schema['description'] )
     399                                        );
     400
     401                                } else {
     402                                        printf(
     403                                                '<div class="form-field bp-types-form form-required term-%1$s-wrap">
     404                                                        <label for="%1$s">%2$s</label>
     405                                                        <input name="%1$s" id="%1$s" type="text" value="" size="40">
     406                                                        <p>%3$s</p>
     407                                                </div>',
     408                                                esc_attr( $meta_key ),
     409                                                esc_html( $labels->{ $meta_key } ),
     410                                                esc_html( $meta_schema['description'] )
     411                                        );
     412                                }
     413                        } else {
     414                                if ( isset( $type->name ) ) {
     415                                        $checked = '';
     416                                        if ( isset( $type->{$type_key} ) && true === (bool) $type->{$type_key} ) {
     417                                                $checked = ' checked="checked"';
     418                                        }
     419
     420                                        printf(
     421                                                '<tr class="form-field bp-types-form term-%1$s-wrap">
     422                                                        <th scope="row"><label for="%1$s">%2$s</label></th>
     423                                                        <td>
     424                                                                <input name="%1$s" id="%1$s" type="checkbox" value="1"%3$s> %4$s
     425                                                                <p class="description">%5$s</p>
     426                                                        </td>
     427                                                </tr>',
     428                                                esc_attr( $meta_key ),
     429                                                esc_html( $labels->{ $meta_key } ),
     430                                                $checked,
     431                                                esc_html__( 'Yes', 'buddypress' ),
     432                                                esc_html( $meta_schema['description'] )
     433                                        );
     434                                } else {
     435                                        printf(
     436                                                '<div class="form-field bp-types-form term-%1$s-wrap">
     437                                                        <label for="%1$s">
     438                                                                <input name="%1$s" id="%1$s" type="checkbox" value="1"> %2$s
     439                                                        </label>
     440                                                        <p>%3$s</p>
     441                                                </div>',
     442                                                esc_attr( $meta_key ),
     443                                                esc_html( $labels->{ $meta_key } ),
     444                                                esc_html( $meta_schema['description'] )
     445                                        );
     446                                }
     447                        }
     448                }
     449        }
     450
     451        /**
     452         * Outputs the BP type edit form.
     453         *
     454         * @since 7.0.0
     455         *
     456         * @param WP_Term $term     The term object for the BP Type.
     457         * @param string  $taxonomy The type taxonomy name.
     458         * @return string           HTML Output.
     459         */
     460        public function edit_form_fields( $term = null, $taxonomy = '' ) {
     461                if ( ! isset( $term->name ) || ! $term->name || ! $taxonomy ) {
     462                        return;
     463                }
     464
     465                $type         = new stdClass();
     466                $type->name   = $term->name;
     467                $type->labels = array();
     468                $metadatas    = get_metadata( 'term', $term->term_id );
     469
     470                foreach ( $metadatas as $meta_key => $meta_values ) {
     471                        $meta_value = reset( $meta_values );
     472                        $type_key   = str_replace( 'bp_type_', '', $meta_key );
     473
     474                        if ( in_array( $type_key, array( 'name', 'singular_name' ), true ) ) {
     475                                $type->labels[ $type_key ] = $meta_value;
     476                        } else {
     477                                $type->{$type_key} = $meta_value;
     478                        }
     479                }
     480
     481                return $this->add_form_fields( $taxonomy, $type );
     482        }
     483
     484        /**
     485         * Filters the terms list table column headers to customize them for BuddyPress Types.
     486         *
     487         * @since 7.0.0
     488         *
     489         * @param array  $column_headers The column header labels keyed by column ID.
     490         * @return array                 The column header labels keyed by column ID.
     491         */
     492        public function column_headers( $column_headers = array() ) {
     493                if ( isset( $column_headers['name'] ) ) {
     494                        $column_headers['name'] = __( 'Type ID', 'buddypress' );
     495                }
     496
     497                unset( $column_headers['cb'], $column_headers['description'], $column_headers['posts'] );
     498
     499                $column_headers['plural_name'] = __( 'Name', 'buddypress' );
     500                $column_headers['counts']      = _x( 'Count', 'Number/count of types', 'buddypress' );
     501
     502                return $column_headers;
     503        }
     504
     505        /**
     506         * Sets the content for the Plural name & Counts columns.
     507         *
     508         * @since 7.0.0
     509         *
     510         * @param string  $string      Blank string.
     511         * @param string  $column_name Name of the column.
     512         * @param int     $type_id     The type's term ID.
     513         * @return string              The Type Plural name.
     514         */
     515        public function column_contents( $column_content = '', $column_name = '', $type_id = 0 ) {
     516                if ( 'plural_name' !== $column_name && 'counts' !== $column_name || ! $type_id ) {
     517                        return $column_content;
     518                }
     519
     520                // Set the Plural name column.
     521                if ( 'plural_name' === $column_name ) {
     522                        $type_plural_name = get_term_meta( $type_id, 'bp_type_name', true );
     523
     524                        // Plural name meta is not set? Let's check register by code types!
     525                        if ( ! $type_plural_name ) {
     526                                $type_name = get_term_field( 'name', $type_id, $this->taxonomy );
     527
     528                                /**
     529                                 * Filter here to set missing term meta for registered by code types.
     530                                 *
     531                                 * @see bp_set_registered_by_code_member_type_metadata() for an example of use.
     532                                 *
     533                                 * @since 7.0.0
     534                                 *
     535                                 * @param string $value Metadata for the BP Type.
     536                                 */
     537                                $metadata = apply_filters( "{$this->taxonomy}_set_registered_by_code_metada", array(), $type_name );
     538
     539                                if ( isset( $metadata['bp_type_name'] ) ) {
     540                                        $type_plural_name = $metadata['bp_type_name'];
     541                                }
     542                        }
     543
     544                        echo esc_html( $type_plural_name );
     545
     546                        // Set the Totals column.
     547                } elseif ( 'counts' === $column_name ) {
     548                        global $parent_file;
     549                        $type  = bp_get_term_by( 'id', $type_id, $this->taxonomy );
     550                        if ( 0 === (int) $type->count ) {
     551                                return 0;
     552                        }
     553
     554                        // Format the count.
     555                        $count = number_format_i18n( $type->count );
     556
     557                        $args = array(
     558                                str_replace( '_', '-', $this->taxonomy ) => $type->slug,
     559                        );
     560
     561                        $base_url = $parent_file;
     562                        if ( false === strpos( $parent_file, '.php' ) ) {
     563                                $base_url = add_query_arg( 'page', $parent_file, 'admin.php' );
     564                        }
     565
     566                        printf(
     567                                '<a href="%1$s">%2$s</a>',
     568                                esc_url( add_query_arg( $args, bp_get_admin_url( $base_url ) ) ),
     569                                esc_html( $count )
     570                        );
     571                }
     572        }
     573
     574        /**
     575         * Customizes the Types Admin list table row actions.
     576         *
     577         * @since 7.0.0
     578         *
     579         * @param array   $actions The table row actions.
     580         * @param WP_Term $type    The current BP Type for the row.
     581         * @return array           The table row actions for the current BP type.
     582         */
     583        public function row_actions( $actions = array(), $type = null ) {
     584                if ( ! isset( $type->taxonomy ) || ! $type->taxonomy ) {
     585                        return $actions;
     586                }
     587
     588                /**
     589                 * Filter here to set the types "registered by code".
     590                 *
     591                 * @see bp_get_member_types_registered_by_code() for an example of use.
     592                 *
     593                 * @since 7.0.0
     594                 */
     595                $registered_by_code_types = apply_filters( "{$type->taxonomy}_registered_by_code", array() );
     596
     597                // Types registered by code cannot be deleted as long as the custom registration code exists.
     598                if ( isset( $registered_by_code_types[ $type->name ] ) ) {
     599                        unset( $actions['delete'] );
     600                }
     601
     602                // Inline edits are disabled for all types.
     603                unset( $actions['inline hide-if-no-js'] );
     604
     605                // Removes the post type query argument for the edit action.
     606                if ( isset( $actions['edit'] ) ) {
     607                        $actions['edit'] = str_replace( '&#038;post_type=post', '', $actions['edit'] );
     608                }
     609
     610                return $actions;
     611        }
     612}
     613
     614endif;
  • src/bp-core/classes/class-bp-admin.php

    diff --git src/bp-core/classes/class-bp-admin.php src/bp-core/classes/class-bp-admin.php
    index 5457a816c..12487789e 100644
    class BP_Admin { 
    175175                // BuddyPress Hello.
    176176                add_action( 'admin_footer', array( $this, 'about_screen' ) );
    177177
     178                // BuddyPress Types administration.
     179                add_action( 'load-edit-tags.php', array( 'BP_Admin_Types', 'register_types_admin' ) );
     180
    178181                /* Filters ***********************************************************/
    179182
    180183                // Add link to settings page.
  • src/bp-groups/bp-groups-admin.php

    diff --git src/bp-groups/bp-groups-admin.php src/bp-groups/bp-groups-admin.php
    index e41abf20a..8ddb55c3f 100644
     
    1414defined( 'ABSPATH' ) || exit;
    1515
    1616// Include WP's list table class.
    17 if ( !class_exists( 'WP_List_Table' ) ) require( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
     17if ( ! class_exists( 'WP_List_Table' ) ) {
     18        require ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
     19}
    1820
    1921// The per_page screen option. Has to be hooked in extremely early.
    20 if ( is_admin() && ! empty( $_REQUEST['page'] ) && 'bp-groups' == $_REQUEST['page'] )
     22if ( is_admin() && ! empty( $_REQUEST['page'] ) && 'bp-groups' == $_REQUEST['page'] ) {
    2123        add_filter( 'set-screen-option', 'bp_groups_admin_screen_options', 10, 3 );
     24}
    2225
    2326/**
    2427 * Register the Groups component admin screen.
    function bp_groups_add_admin_menu() { 
    4245}
    4346add_action( bp_core_admin_hook(), 'bp_groups_add_admin_menu' );
    4447
     48/**
     49 * Redirects the user on the Goups network admin screen when BuddyPress is network activated.
     50 *
     51 * @since 1.1.0
     52 */
     53function bp_group_site_admin_network_admin_redirect() {
     54        wp_safe_redirect( add_query_arg( 'page', 'bp-groups', network_admin_url( 'admin.php' ) ) );
     55        exit();
     56}
     57
     58function bp_groups_admin_types_menu() {
     59        if ( ! bp_is_root_blog() ) {
     60                return;
     61        }
     62
     63        if ( bp_is_network_activated() && is_network_admin() ) {
     64                // Adds a 'bp-groups' submenu to go to the root blog Group types screen.
     65                $group_type_admin_url = add_query_arg( 'taxonomy', 'bp_group_type', get_admin_url( bp_get_root_blog_id(), 'edit-tags.php' ) );
     66                add_submenu_page(
     67                        'bp-groups',
     68                        __( 'Group types', 'buddypress' ),
     69                        __( 'Group types', 'buddypress' ),
     70                        'bp_moderate',
     71                        esc_url( $group_type_admin_url )
     72                );
     73        } elseif ( ! is_network_admin() ) {
     74                if ( is_multisite() ) {
     75                        // Adds a 'bp-groups' menu to the root blog menu.
     76                        $redirect_hook = add_menu_page(
     77                                _x( 'Groups', 'Admin Groups page title', 'buddypress' ),
     78                                _x( 'Groups', 'Admin Groups menu', 'buddypress' ),
     79                                'bp_moderate',
     80                                'bp-groups',
     81                                '__return_empty_string',
     82                                'div'
     83                        );
     84
     85                        add_action( "load-{$redirect_hook}", 'bp_group_site_admin_network_admin_redirect' );
     86                }
     87
     88                // Add the submenu to manage Group Types.
     89                add_submenu_page(
     90                        'bp-groups',
     91                        __( 'Group types', 'buddypress' ),
     92                        __( 'Group types', 'buddypress' ),
     93                        'bp_moderate',
     94                        basename( add_query_arg( 'taxonomy', 'bp_group_type', bp_get_admin_url( 'edit-tags.php' ) ) )
     95                );
     96        }
     97}
     98add_action( 'bp_admin_menu', 'bp_groups_admin_types_menu' );
     99
    45100/**
    46101 * Add groups component to custom menus array.
    47102 *
    function bp_groups_admin_groups_type_change_notice() { 
    14081463        }
    14091464}
    14101465add_action( bp_core_admin_hook(), 'bp_groups_admin_groups_type_change_notice' );
     1466
     1467/**
     1468 * Checks whether a group type already exists.
     1469 *
     1470 * @since 7.0.0
     1471 *
     1472 * @param  boolean $exists  True if the group type already exists. False otherwise.
     1473 * @param  string  $type_id The group type identifier.
     1474 * @return boolean          True if the group type already exists. False otherwise.
     1475 */
     1476function bp_groups_type_admin_type_exists( $exists = false, $type_id = '' ) {
     1477        if ( ! $type_id ) {
     1478                return $exists;
     1479        }
     1480
     1481        return ! is_null( bp_groups_get_group_type_object( $type_id ) );
     1482}
     1483add_filter( bp_get_group_type_tax_name() . '_check_existing_type', 'bp_groups_type_admin_type_exists', 1, 2 );
     1484
     1485/**
     1486 * Set the feedback messages for the Group Types Admin actions.
     1487 *
     1488 * @since 7.0.0
     1489 *
     1490 * @param array  $messages The feedback messages.
     1491 * @return array           The feedback messages including the ones for the Group Types Admin actions.
     1492 */
     1493function bp_groups_type_admin_updated_messages( $messages = array() ) {
     1494        $type_taxonomy = bp_get_group_type_tax_name();
     1495
     1496        $messages[ $type_taxonomy ] = array(
     1497                0  => '',
     1498                1  => __( 'Please define the Group Type ID field.', 'buddypress' ),
     1499                2  => __( 'Group type successfully added.', 'buddypress' ),
     1500                3  => __( 'Sorry, there was an error and the Group type wasn’t added.', 'buddypress' ),
     1501                // The following one needs to be != 5.
     1502                4  => __( 'Group type successfully updated.', 'buddypress' ),
     1503                5  => __( 'Sorry, this Group type already exists.', 'buddypress' ),
     1504                6  => __( 'Sorry, the Group type was not deleted: it does not exist.', 'buddypress' ),
     1505                7  => __( 'Sorry, This Group type is registered using code, deactivate the plugin or remove the custom code before trying to delete it again.', 'buddypress' ),
     1506                8  => __( 'Sorry, there was an error while trying to delete this Group type.', 'buddypress' ),
     1507                9  => __( 'Group type successfully deleted.', 'buddypress' ),
     1508                10 => __( 'Group type could not be updated due to missing required information.', 'buddypress' ),
     1509        );
     1510
     1511        return $messages;
     1512}
     1513add_filter( 'term_updated_messages', 'bp_groups_type_admin_updated_messages' );
  • src/bp-groups/bp-groups-functions.php

    diff --git src/bp-groups/bp-groups-functions.php src/bp-groups/bp-groups-functions.php
    index f1bd15f35..389059f88 100644
    add_action( 'bp_groups_delete_group', 'bp_groups_update_orphaned_groups_on_group 
    24632463
    24642464/** Group Types ***************************************************************/
    24652465
     2466/**
     2467 * Output the slug of the Group type taxonomy.
     2468 *
     2469 * @since 7.0.0
     2470 */
     2471function bp_group_type_tax_name() {
     2472        echo bp_get_group_type_tax_name();
     2473}
     2474
     2475        /**
     2476         * Return the slug of the Group type taxonomy.
     2477         *
     2478         * @since 7.0.0
     2479         *
     2480         * @return string The unique Group taxonomy slug.
     2481         */
     2482        function bp_get_group_type_tax_name() {
     2483                /**
     2484                 * Filters the slug of the Group type taxonomy.
     2485                 *
     2486                 * @since 7.0.0
     2487                 *
     2488                 * @param string $value Group type taxonomy slug.
     2489                 */
     2490                return apply_filters( 'bp_get_group_type_tax_name', 'bp_group_type' );
     2491        }
     2492
     2493/**
     2494 * Returns labels used by the Group type taxonomy.
     2495 *
     2496 * @since 7.0.0
     2497 *
     2498 * @return array
     2499 */
     2500function bp_get_group_type_tax_labels() {
     2501
     2502        /**
     2503         * Filters Group type taxonomy labels.
     2504         *
     2505         * @since 7.0.0
     2506         *
     2507         * @param array $value Associative array (name => label).
     2508         */
     2509        return apply_filters(
     2510                'bp_get_group_type_tax_labels',
     2511                array(
     2512                        'name'                          => _x( 'Group types', 'Group type taxonomy name', 'buddypress' ),
     2513                        'singular_name'                 => _x( 'Group type', 'Group type taxonomy singular name', 'buddypress' ),
     2514                        'search_items'                  => _x( 'Search Group types', 'Group type taxonomy search items label', 'buddypress' ),
     2515                        'popular_items'                 => _x( 'Most used Group types', 'Group type taxonomy popular items label', 'buddypress' ),
     2516                        'all_items'                     => _x( 'All Group types', 'Group type taxonomy all items label', 'buddypress' ),
     2517                        'edit_item'                     => _x( 'Edit Group type', 'Group type taxonomy edit item label', 'buddypress' ),
     2518                        'view_item'                     => _x( 'View Group type', 'Group type taxonomy view item label', 'buddypress' ),
     2519                        'update_item'                   => _x( 'Update Group type', 'Group type taxonomy update item label', 'buddypress' ),
     2520                        'add_new_item'                  => _x( 'Add new Group type', 'Group type taxonomy add new item label', 'buddypress' ),
     2521                        'new_item_name'                 => _x( 'New Group type name', 'Group type taxonomy new item name label', 'buddypress' ),
     2522                        'separate_items_with_commas'    => _x( 'Separate Group types with commas', 'Group type taxonomy separate items with commas label', 'buddypress' ),
     2523                        'add_or_remove_items'           => _x( 'Add or remove Group types', 'Group type taxonomy add or remove items label', 'buddypress' ),
     2524                        'choose_from_most_used'         => _x( 'Choose from the most used Group types', 'Group type taxonomy choose from most used label', 'buddypress' ),
     2525                        'not_found'                     => _x( 'No Group types found', 'Group type taxonomy not found label', 'buddypress' ),
     2526                        'no_terms'                      => _x( 'No Group types', 'Group type taxonomy no terms label', 'buddypress' ),
     2527                        'items_list_navigation'         => _x( 'Group types list navigation', 'Group type taxonomy items list navigation label', 'buddypress' ),
     2528                        'items_list'                    => _x( 'Group types list', 'Group type taxonomy items list label', 'buddypress' ),
     2529                        'back_to_items'                 => _x( 'Back to all Group types', 'Group type taxonomy back to items label', 'buddypress' ),
     2530                        // Specific to BuddyPress.
     2531                        'bp_type_id_label'              => _x( 'Group Type ID', 'BP Member type ID label', 'buddypress' ),
     2532                        'bp_type_id_description'        => _x( 'Enter a lower-case string without spaces or special characters (used internally to identify the group type).', 'BP Group type ID description', 'buddypress' ),
     2533                        'bp_type_show_in_create_screen' => _x( 'Add to Available Types on Create Screen', 'BP Group type show in create screen', 'buddypress' ),
     2534                        'bp_type_show_in_list'          => _x( 'Include when Group Types are Listed for a Group', 'BP Group type show in list', 'buddypress' ),
     2535                )
     2536        );
     2537}
     2538
     2539/**
     2540 * Returns arguments used by the Group type taxonomy.
     2541 *
     2542 * @since 7.0.0
     2543 *
     2544 * @return array
     2545 */
     2546function bp_get_group_type_tax_args() {
     2547
     2548        /**
     2549         * Filters Group type taxonomy args.
     2550         *
     2551         * @since 7.0.0
     2552         *
     2553         * @param array $value Associative array (key => arg).
     2554         */
     2555        return apply_filters(
     2556                'bp_get_group_type_tax_args',
     2557                array_merge(
     2558                        array(
     2559                                'description' => _x( 'BuddyPress Group types', 'Group type taxonomy description', 'buddypress' ),
     2560                                'labels'      => array_merge( bp_get_group_type_tax_labels(), bp_get_taxonomy_common_labels() ),
     2561                        ),
     2562                        bp_get_taxonomy_common_args()
     2563                )
     2564        );
     2565}
     2566
     2567/**
     2568 * Register the Group Types taxonomy.
     2569 *
     2570 * @since 7.0.0
     2571 *
     2572 * @param array $taxonomies BuddyPress default taxonomies.
     2573 * @return array            BuddyPress default taxonomies.
     2574 */
     2575function bp_groups_register_group_type_taxonomy( $taxonomies = array() ) {
     2576        return array_merge(
     2577                $taxonomies,
     2578                array(
     2579                        // Group Type.
     2580                        bp_get_group_type_tax_name() => array(
     2581                                'object'    => 'bp_group',
     2582                                'component' => 'groups',
     2583                                'args'      => bp_get_group_type_tax_args(),
     2584                        ),
     2585                )
     2586        );
     2587}
     2588add_filter( 'bp_get_default_taxonomies', 'bp_groups_register_group_type_taxonomy', 1 );
     2589
    24662590/**
    24672591 * Fire the 'bp_groups_register_group_types' action.
    24682592 *
    function bp_groups_register_group_types() { 
    24782602}
    24792603add_action( 'bp_register_taxonomies', 'bp_groups_register_group_types' );
    24802604
     2605/**
     2606 * Extend generic Type metadata schema to match Group Type needs.
     2607 *
     2608 * @since 7.0.0
     2609 *
     2610 * @param array  $schema   The generic Type metadata schema.
     2611 * @param string $taxonomy The taxonomy name the schema applies to.
     2612 * @return array           The Group Type metadata schema.
     2613 */
     2614function bp_get_group_type_metadata_schema( $schema = array(), $taxonomy = '' ) {
     2615        if ( bp_get_group_type_tax_name() === $taxonomy ) {
     2616                if ( isset( $schema['bp_type_has_directory']['description'] ) ) {
     2617                        $schema['bp_type_has_directory']['description'] = __( 'Add a list of groups matching the member type available on the Groups Directory page (e.g. site.url/groups/type/ninja/).', 'buddypress' );
     2618                }
     2619
     2620                if ( isset( $schema['bp_type_directory_slug']['description'] ) ) {
     2621                        $schema['bp_type_directory_slug']['description'] = __( 'If you want to use a slug that is different from the Group Type ID above, enter it here.', 'buddypress' );
     2622                }
     2623
     2624                $schema = array_merge(
     2625                        $schema,
     2626                        array(
     2627                                'bp_type_show_in_create_screen' => array(
     2628                                        'description'       => __( 'Include this group type during group creation and when a group administrator is on the group&rsquo;s &ldquo;Manage > Settings&rdquo; page.', 'buddypress' ),
     2629                                        'type'              => 'boolean',
     2630                                        'single'            => true,
     2631                                        'sanitize_callback' => 'absint',
     2632                                ),
     2633                                'bp_type_show_in_list'          => array(
     2634                                        'description'       => __( 'Include this group type when group types are listed, like in the group header.', 'buddypress' ),
     2635                                        'type'              => 'boolean',
     2636                                        'single'            => true,
     2637                                        'sanitize_callback' => 'absint',
     2638                                ),
     2639                        )
     2640                );
     2641        }
     2642
     2643        return $schema;
     2644}
     2645add_filter( 'bp_get_type_metadata_schema', 'bp_get_group_type_metadata_schema', 1, 2 );
     2646
     2647/**
     2648 * Registers the Group type metadata.
     2649 *
     2650 * @since 7.0.0
     2651 */
     2652function bp_register_group_type_metadata() {
     2653        $type_taxonomy = bp_get_group_type_tax_name();
     2654
     2655        foreach ( bp_get_type_metadata_schema( false, $type_taxonomy ) as $meta_key => $meta_args ) {
     2656                bp_register_type_meta( $type_taxonomy, $meta_key, $meta_args );
     2657        }
     2658}
     2659add_action( 'bp_register_type_metadata', 'bp_register_group_type_metadata', 11 );
     2660
    24812661/**
    24822662 * Register a group type.
    24832663 *
    function bp_groups_register_group_type( $group_type, $args = array() ) { 
    25252705                'description'           => '',
    25262706                'create_screen_checked' => false,
    25272707                'labels'                => array(),
     2708                'code'                  => true,
     2709                'db_id'                 => 0,
    25282710        ), 'register_group_type' );
    25292711
    25302712        $group_type = sanitize_key( $group_type );
    function bp_groups_get_group_types( $args = array(), $output = 'names', $operato 
    26172799
    26182800        $types = wp_filter_object_list( $types, $args, $operator );
    26192801
     2802        // Merge with types available into the database.
     2803        if ( ! isset( $args['code'] ) || true !== $args['code'] ) {
     2804                $types = bp_get_taxonomy_types( bp_get_group_type_tax_name(), $types );
     2805        }
     2806
    26202807        /**
    26212808         * Filters the array of group type objects.
    26222809         *
    function bp_groups_get_group_type_object( $group_type ) { 
    26562843        return $types[ $group_type ];
    26572844}
    26582845
     2846/**
     2847 * Only gets the group types registered by code.
     2848 *
     2849 * @since 7.0.0
     2850 *
     2851 * @return array The group types registered by code.
     2852 */
     2853function bp_get_group_types_registered_by_code() {
     2854        return bp_groups_get_group_types(
     2855                array(
     2856                        'code' => true,
     2857                ),
     2858                'objects'
     2859        );
     2860}
     2861add_filter( bp_get_group_type_tax_name() . '_registered_by_code', 'bp_get_group_types_registered_by_code' );
     2862
     2863/**
     2864 * Generates missing metadata for a type registered by code.
     2865 *
     2866 * @since 7.0.0
     2867 *
     2868 * @return array The group type metadata.
     2869 */
     2870function bp_set_registered_by_code_group_type_metadata( $metadata = array(), $type = '' ) {
     2871        $group_type = bp_groups_get_group_type_object( $type );
     2872
     2873        foreach ( get_object_vars( $group_type ) as $object_key => $object_value ) {
     2874                if ( 'labels' === $object_key ) {
     2875                        foreach ( $object_value as $label_key => $label_value ) {
     2876                                $metadata[ 'bp_type_' . $label_key ] = $label_value;
     2877                        }
     2878                } elseif ( ! in_array( $object_key, array( 'name', 'code', 'db_id' ), true ) ) {
     2879                        $metadata[ 'bp_type_' . $object_key ] = $object_value;
     2880                }
     2881        }
     2882
     2883        /**
     2884         * Save metadata into database to avoid generating metadata
     2885         * each time a type is listed into the Types Admin screen.
     2886         */
     2887        if ( isset( $group_type->db_id ) && $group_type->db_id ) {
     2888                bp_update_type_metadata( $group_type->db_id, bp_get_group_type_tax_name(), $metadata );
     2889        }
     2890
     2891        return $metadata;
     2892}
     2893add_filter( bp_get_group_type_tax_name() . '_set_registered_by_code_metada', 'bp_set_registered_by_code_group_type_metadata', 10, 2 );
     2894
     2895/**
     2896 * Insert group types registered by code not yet saved into the database as WP Terms.
     2897 *
     2898 * @since 7.0.0
     2899 */
     2900function bp_insert_group_types_registered_by_code() {
     2901        $all_types     = bp_groups_get_group_types( array(), 'objects' );
     2902        $unsaved_types = wp_filter_object_list( $all_types, array( 'db_id' => 0 ), 'and', 'name' );
     2903
     2904        if ( $unsaved_types ) {
     2905                foreach ( $unsaved_types as $type_name ) {
     2906                        bp_insert_term(
     2907                                $type_name,
     2908                                bp_get_group_type_tax_name(),
     2909                                array(
     2910                                        'slug' => $type_name,
     2911                                )
     2912                        );
     2913                }
     2914        }
     2915}
     2916add_action( bp_get_group_type_tax_name() . '_add_form', 'bp_insert_group_types_registered_by_code', 1 );
     2917
    26592918/**
    26602919 * Set type for a group.
    26612920 *
    function bp_groups_set_group_type( $group_id, $group_type, $append = false ) { 
    26852944                }
    26862945        }
    26872946
    2688         $retval = bp_set_object_terms( $group_id, $group_type, 'bp_group_type', $append );
     2947        $retval = bp_set_object_terms( $group_id, $group_type, bp_get_group_type_tax_name(), $append );
    26892948
    26902949        // Bust the cache if the type has been updated.
    26912950        if ( ! is_wp_error( $retval ) ) {
    function bp_groups_get_group_type( $group_id, $single = true ) { 
    27212980        $types = wp_cache_get( $group_id, 'bp_groups_group_type' );
    27222981
    27232982        if ( false === $types ) {
    2724                 $raw_types = bp_get_object_terms( $group_id, 'bp_group_type' );
     2983                $raw_types = bp_get_object_terms( $group_id, bp_get_group_type_tax_name() );
    27252984
    27262985                if ( ! is_wp_error( $raw_types ) ) {
    27272986                        $types = array();
    function bp_groups_remove_group_type( $group_id, $group_type ) { 
    27783037                return false;
    27793038        }
    27803039
    2781         $deleted = bp_remove_object_terms( $group_id, $group_type, 'bp_group_type' );
     3040        $deleted = bp_remove_object_terms( $group_id, $group_type, bp_get_group_type_tax_name() );
    27823041
    27833042        // Bust the case, if the type has been removed.
    27843043        if ( ! is_wp_error( $deleted ) ) {
  • src/bp-groups/classes/class-bp-groups-component.php

    diff --git src/bp-groups/classes/class-bp-groups-component.php src/bp-groups/classes/class-bp-groups-component.php
    index a7c2f5c5c..d78176442 100644
    class BP_Groups_Component extends BP_Component { 
    924924         * Set up taxonomies.
    925925         *
    926926         * @since 2.6.0
     927         * @deprecated 7.0.0
    927928         */
    928929        public function register_taxonomies() {
    929                 // Group Type.
    930                 register_taxonomy( 'bp_group_type', 'bp_group', array(
    931                         'public' => false,
    932                 ) );
     930                /**
     931                 * Since 7.0.0 The Group Type taxonomy is registered using the
     932                 * `bp_groups_register_group_type_taxonomy()` function.
     933                 *
     934                 * @see bp-groups/bp-groups-functions.php.
     935                 */
     936
     937                // Just let BP Component fire 'bp_groups_register_taxonomies'.
     938                return parent::register_taxonomies();
    933939        }
    934940
    935941        /**
  • src/bp-groups/classes/class-bp-groups-group.php

    diff --git src/bp-groups/classes/class-bp-groups-group.php src/bp-groups/classes/class-bp-groups-group.php
    index 0102e41e7..f06ec8055 100644
    class BP_Groups_Group { 
    17461746
    17471747                $tax_query = new WP_Tax_Query( array(
    17481748                        array(
    1749                                 'taxonomy' => 'bp_group_type',
     1749                                'taxonomy' => bp_get_group_type_tax_name(),
    17501750                                'field'    => 'name',
    17511751                                'operator' => $operator,
    17521752                                'terms'    => $types,
    17531753                        ),
    17541754                ) );
    17551755
    1756                 $site_id  = bp_get_taxonomy_term_site_id( 'bp_group_type' );
     1756                $site_id  = bp_get_taxonomy_term_site_id( bp_get_group_type_tax_name() );
    17571757                $switched = false;
    17581758                if ( $site_id !== get_current_blog_id() ) {
    17591759                        switch_to_blog( $site_id );
  • src/bp-members/bp-members-admin.php

    diff --git src/bp-members/bp-members-admin.php src/bp-members/bp-members-admin.php
    index 1d3b875f0..3f852ca31 100644
    defined( 'ABSPATH' ) || exit; 
    1212
    1313// Load the BP Members admin.
    1414add_action( 'bp_init', array( 'BP_Members_Admin', 'register_members_admin' ) );
     15
     16/**
     17 * Create Users submenu to manage BuddyPress types.
     18 *
     19 * @since 7.0.0
     20 */
     21function bp_members_type_admin_menu() {
     22        if ( ! bp_is_root_blog() ) {
     23                return;
     24        }
     25
     26        if ( bp_is_network_activated() && is_network_admin() ) {
     27                // Adds a users.php submenu to go to the root blog Member types screen.
     28                $member_type_admin_url = add_query_arg( 'taxonomy', bp_get_member_type_tax_name(), get_admin_url( bp_get_root_blog_id(), 'edit-tags.php' ) );
     29
     30                add_submenu_page(
     31                        'users.php',
     32                        __( 'Member types', 'buddypress' ),
     33                        __( 'Member types', 'buddypress' ),
     34                        'bp_moderate',
     35                        esc_url( $member_type_admin_url )
     36                );
     37
     38        } elseif ( ! is_network_admin() ) {
     39                add_submenu_page(
     40                        'users.php',
     41                        __( 'Member types', 'buddypress' ),
     42                        __( 'Member types', 'buddypress' ),
     43                        'bp_moderate',
     44                        basename( add_query_arg( 'taxonomy', bp_get_member_type_tax_name(), bp_get_admin_url( 'edit-tags.php' ) ) )
     45                );
     46        }
     47}
     48add_action( 'bp_admin_menu', 'bp_members_type_admin_menu' );
     49
     50/**
     51 * Checks whether a member type already exists.
     52 *
     53 * @since 7.0.0
     54 *
     55 * @param  boolean $exists  True if the member type already exists. False otherwise.
     56 * @param  string  $type_id The member type identifier.
     57 * @return boolean          True if the member type already exists. False otherwise.
     58 */
     59function bp_members_type_admin_type_exists( $exists = false, $type_id = '' ) {
     60        if ( ! $type_id ) {
     61                return $exists;
     62        }
     63
     64        return ! is_null( bp_get_member_type_object( $type_id ) );
     65}
     66add_filter( bp_get_member_type_tax_name() . '_check_existing_type', 'bp_members_type_admin_type_exists', 1, 2 );
     67
     68/**
     69 * Set the feedback messages for the Member Types Admin actions.
     70 *
     71 * @since 7.0.0
     72 *
     73 * @param array  $messages The feedback messages.
     74 * @return array           The feedback messages including the ones for the Member Types Admin actions.
     75 */
     76function bp_members_type_admin_updated_messages( $messages = array() ) {
     77        $type_taxonomy = bp_get_member_type_tax_name();
     78
     79        $messages[ $type_taxonomy ] = array(
     80                0  => '',
     81                1  => __( 'Please define the Member Type ID field.', 'buddypress' ),
     82                2  => __( 'Member type successfully added.', 'buddypress' ),
     83                3  => __( 'Sorry, there was an error and the Member type wasn’t added.', 'buddypress' ),
     84                // The following one needs to be != 5.
     85                4  => __( 'Member type successfully updated.', 'buddypress' ),
     86                5  => __( 'Sorry, this Member type already exists.', 'buddypress' ),
     87                6  => __( 'Sorry, the Member type was not deleted: it does not exist.', 'buddypress' ),
     88                7  => __( 'Sorry, This Member type is registered using code, deactivate the plugin or remove the custom code before trying to delete it again.', 'buddypress' ),
     89                8  => __( 'Sorry, there was an error while trying to delete this Member type.', 'buddypress' ),
     90                9  => __( 'Member type successfully deleted.', 'buddypress' ),
     91                10 => __( 'Member type could not be updated due to missing required information.', 'buddypress' ),
     92        );
     93
     94        return $messages;
     95}
     96add_filter( 'term_updated_messages', 'bp_members_type_admin_updated_messages' );
  • src/bp-members/bp-members-functions.php

    diff --git src/bp-members/bp-members-functions.php src/bp-members/bp-members-functions.php
    index 925759030..411250c59 100644
    function bp_member_type_tax_name() { 
    26452645                return apply_filters( 'bp_get_member_type_tax_name', 'bp_member_type' );
    26462646        }
    26472647
     2648/**
     2649 * Returns labels used by the member type taxonomy.
     2650 *
     2651 * @since 7.0.0
     2652 *
     2653 * @return array
     2654 */
     2655function bp_get_member_type_tax_labels() {
     2656
     2657        /**
     2658         * Filters Member type taxonomy labels.
     2659         *
     2660         * @since 7.0.0
     2661         *
     2662         * @param array $value Associative array (name => label).
     2663         */
     2664        return apply_filters(
     2665                'bp_get_member_type_tax_labels',
     2666                array(
     2667                        'name'                       => _x( 'Member types', 'Member type taxonomy name', 'buddypress' ),
     2668                        'singular_name'              => _x( 'Member type', 'Member type taxonomy singular name', 'buddypress' ),
     2669                        'search_items'               => _x( 'Search Member types', 'Member type taxonomy search items label', 'buddypress' ),
     2670                        'popular_items'              => _x( 'Most used Member types', 'Member type taxonomy popular items label', 'buddypress' ),
     2671                        'all_items'                  => _x( 'All Member types', 'Member type taxonomy all items label', 'buddypress' ),
     2672                        'edit_item'                  => _x( 'Edit Member type', 'Member type taxonomy edit item label', 'buddypress' ),
     2673                        'view_item'                  => _x( 'View Member type', 'Member type taxonomy view item label', 'buddypress' ),
     2674                        'update_item'                => _x( 'Update Member type', 'Member type taxonomy update item label', 'buddypress' ),
     2675                        'add_new_item'               => _x( 'Add new Member type', 'Member type taxonomy add new item label', 'buddypress' ),
     2676                        'new_item_name'              => _x( 'New Member type name', 'Member type taxonomy new item name label', 'buddypress' ),
     2677                        'separate_items_with_commas' => _x( 'Separate Member types with commas', 'Member type taxonomy separate items with commas label', 'buddypress' ),
     2678                        'add_or_remove_items'        => _x( 'Add or remove Member types', 'Member type taxonomy add or remove items label', 'buddypress' ),
     2679                        'choose_from_most_used'      => _x( 'Choose from the most used Member types', 'Member type taxonomy choose from most used label', 'buddypress' ),
     2680                        'not_found'                  => _x( 'No Member types found', 'Member type taxonomy not found label', 'buddypress' ),
     2681                        'no_terms'                   => _x( 'No Member types', 'Member type taxonomy no terms label', 'buddypress' ),
     2682                        'items_list_navigation'      => _x( 'Member types list navigation', 'Member type taxonomy items list navigation label', 'buddypress' ),
     2683                        'items_list'                 => _x( 'Member types list', 'Member type taxonomy items list label', 'buddypress' ),
     2684                        'back_to_items'              => _x( 'Back to all Member types', 'Member type taxonomy back to items label', 'buddypress' ),
     2685                        // Specific to BuddyPress.
     2686                        'bp_type_id_label'           => _x( 'Member Type ID', 'BP Member type ID label', 'buddypress' ),
     2687                        'bp_type_id_description'     => _x( 'Enter a lower-case string without spaces or special characters (used internally to identify the member type).', 'BP Member type ID description', 'buddypress' ),
     2688                )
     2689        );
     2690}
     2691
     2692/**
     2693 * Returns arguments used by the Member type taxonomy.
     2694 *
     2695 * @since 7.0.0
     2696 *
     2697 * @return array
     2698 */
     2699function bp_get_member_type_tax_args() {
     2700
     2701        /**
     2702         * Filters Member type taxonomy args.
     2703         *
     2704         * @since 7.0.0
     2705         *
     2706         * @param array $value Associative array (key => arg).
     2707         */
     2708        return apply_filters(
     2709                'bp_get_member_type_tax_args',
     2710                array_merge(
     2711                        array(
     2712                                'description' => _x( 'BuddyPress Member types', 'Member type taxonomy description', 'buddypress' ),
     2713                                'labels'      => array_merge( bp_get_member_type_tax_labels(), bp_get_taxonomy_common_labels() ),
     2714                        ),
     2715                        bp_get_taxonomy_common_args()
     2716                )
     2717        );
     2718}
     2719
     2720/**
     2721 * Registers the Member type metadata.
     2722 *
     2723 * @since 7.0.0
     2724 */
     2725function bp_register_member_type_metadata() {
     2726        $type_taxonomy = bp_get_member_type_tax_name();
     2727
     2728        foreach ( bp_get_type_metadata_schema( false, $type_taxonomy ) as $meta_key => $meta_args ) {
     2729                bp_register_type_meta( $type_taxonomy, $meta_key, $meta_args );
     2730        }
     2731}
     2732add_action( 'bp_register_type_metadata', 'bp_register_member_type_metadata' );
     2733
    26482734/**
    26492735 * Register a member type.
    26502736 *
    function bp_register_member_type( $member_type, $args = array() ) { 
    26772763        $r = bp_parse_args( $args, array(
    26782764                'labels'        => array(),
    26792765                'has_directory' => true,
     2766                'code'          => true,
     2767                'db_id'         => 0,
    26802768        ), 'register_member_type' );
    26812769
    26822770        $member_type = sanitize_key( $member_type );
    function bp_get_member_type_object( $member_type ) { 
    27762864function bp_get_member_types( $args = array(), $output = 'names', $operator = 'and' ) {
    27772865        $types = buddypress()->members->types;
    27782866
     2867        // Merge with types available into the database.
     2868        if ( ! isset( $args['code'] ) || true !== $args['code'] ) {
     2869                $types = bp_get_taxonomy_types( bp_get_member_type_tax_name(), $types );
     2870        }
     2871
    27792872        $types = wp_filter_object_list( $types, $args, $operator );
    27802873
    27812874        /**
    function bp_get_member_types( $args = array(), $output = 'names', $operator = 'a 
    27992892        return $types;
    28002893}
    28012894
     2895/**
     2896 * Only gets the member types registered by code.
     2897 *
     2898 * @since 7.0.0
     2899 *
     2900 * @return array The member types registered by code.
     2901 */
     2902function bp_get_member_types_registered_by_code() {
     2903        return bp_get_member_types(
     2904                array(
     2905                        'code' => true,
     2906                ),
     2907                'objects'
     2908        );
     2909}
     2910add_filter( bp_get_member_type_tax_name() . '_registered_by_code', 'bp_get_member_types_registered_by_code' );
     2911
     2912/**
     2913 * Generates missing metadata for a type registered by code.
     2914 *
     2915 * @since 7.0.0
     2916 *
     2917 * @return array The member type metadata.
     2918 */
     2919function bp_set_registered_by_code_member_type_metadata( $metadata = array(), $type = '' ) {
     2920        $member_type = bp_get_member_type_object( $type );
     2921
     2922        foreach ( get_object_vars( $member_type ) as $object_key => $object_value ) {
     2923                if ( 'labels' === $object_key ) {
     2924                        foreach ( $object_value as $label_key => $label_value ) {
     2925                                $metadata[ 'bp_type_' . $label_key ] = $label_value;
     2926                        }
     2927                } elseif ( ! in_array( $object_key, array( 'name', 'code', 'db_id' ), true ) ) {
     2928                        $metadata[ 'bp_type_' . $object_key ] = $object_value;
     2929                }
     2930        }
     2931
     2932        /**
     2933         * Save metadata into database to avoid generating metadata
     2934         * each time a type is listed into the Types Admin screen.
     2935         */
     2936        if ( isset( $member_type->db_id ) && $member_type->db_id ) {
     2937                bp_update_type_metadata( $member_type->db_id, bp_get_member_type_tax_name(), $metadata );
     2938        }
     2939
     2940        return $metadata;
     2941}
     2942add_filter( bp_get_member_type_tax_name() . '_set_registered_by_code_metada', 'bp_set_registered_by_code_member_type_metadata', 10, 2 );
     2943
     2944/**
     2945 * Insert member types registered by code not yet saved into the database as WP Terms.
     2946 *
     2947 * @since 7.0.0
     2948 */
     2949function bp_insert_member_types_registered_by_code() {
     2950        $all_types     = bp_get_member_types( array(), 'objects' );
     2951        $unsaved_types = wp_filter_object_list( $all_types, array( 'db_id' => 0 ), 'and', 'name' );
     2952
     2953        if ( $unsaved_types ) {
     2954                foreach ( $unsaved_types as $type_name ) {
     2955                        bp_insert_term(
     2956                                $type_name,
     2957                                bp_get_member_type_tax_name(),
     2958                                array(
     2959                                        'slug' => $type_name,
     2960                                )
     2961                        );
     2962                }
     2963        }
     2964}
     2965add_action( bp_get_member_type_tax_name() . '_add_form', 'bp_insert_member_types_registered_by_code', 1 );
     2966
    28022967/**
    28032968 * Set type for a member.
    28042969 *
  • src/class-buddypress.php

    diff --git src/class-buddypress.php src/class-buddypress.php
    index 5464e5c4a..e3aab8198 100644
    class BuddyPress { 
    592592                        'BP_Invitation'                => 'core',
    593593                        'BP_REST_Components_Endpoint'  => 'core',
    594594                        'BP_REST_Attachments'          => 'core',
     595                        'BP_Admin_Types'               => 'core',
    595596
    596597                        'BP_Core_Friends_Widget'   => 'friends',
    597598                        'BP_REST_Friends_Endpoint' => 'friends',