<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[BuddyPress][13527] trunk/docs/developer: Document how to use the Group Extension API</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://buddypress.trac.wordpress.org/changeset/13527">13527</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://buddypress.trac.wordpress.org/changeset/13527","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>imath</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2023-07-26 06:16:30 +0000 (Wed, 26 Jul 2023)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Document how to use the Group Extension API

- Update the [https://codex.buddypress.org/developer/group-extension-api/ Codex] resource with new configuration requirement needed by the BP Rewrites API
- Update code examples
- Add screenshots to code examples

Fixes <a href="http://buddypress.trac.wordpress.org/ticket/8941">#8941</a>
Closes https://github.com/buddypress/buddypress/pull/137</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkdocsdeveloperREADMEmd">trunk/docs/developer/README.md</a></li>
<li><a href="#trunkdocsdevelopermanifestjson">trunk/docs/developer/manifest.json</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkdocsdeveloperassetsbpcustombasicgroupextensionpng">trunk/docs/developer/assets/bp-custom-basic-group-extension.png</a></li>
<li><a href="#trunkdocsdeveloperassetsbpcustomgroupextensionadminscreenpng">trunk/docs/developer/assets/bp-custom-group-extension-admin-screen.png</a></li>
<li><a href="#trunkdocsdeveloperassetsbpcustomgroupextensioncreatescreenpng">trunk/docs/developer/assets/bp-custom-group-extension-create-screen.png</a></li>
<li><a href="#trunkdocsdeveloperassetsbpcustomgroupextensioneditscreenpng">trunk/docs/developer/assets/bp-custom-group-extension-edit-screen.png</a></li>
<li>trunk/docs/developer/group-extension/</li>
<li><a href="#trunkdocsdevelopergroupextensionREADMEmd">trunk/docs/developer/group-extension/README.md</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkdocsdeveloperREADMEmd"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/docs/developer/README.md</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/docs/developer/README.md    2023-07-26 05:29:26 UTC (rev 13526)
+++ trunk/docs/developer/README.md      2023-07-26 06:16:30 UTC (rev 13527)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -9,4 +9,5 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ## Table of content
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 1. [BuddyPress Components](./component/README.md)
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-2. [BuddyPress Theme Compatibility](./theme-compat/README.md)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+2. [BuddyPress Group Extension API](./group-extension/README.md)
+3. [BuddyPress Theme Compatibility](./theme-compat/README.md)
</ins></span></pre></div>
<a id="trunkdocsdeveloperassetsbpcustombasicgroupextensionpng"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/docs/developer/assets/bp-custom-basic-group-extension.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx" style="display: block; padding: 0 10px">Index: trunk/docs/developer/assets/bp-custom-basic-group-extension.png
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- trunk/docs/developer/assets/bp-custom-basic-group-extension.png      2023-07-26 05:29:26 UTC (rev 13526)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ trunk/docs/developer/assets/bp-custom-basic-group-extension.png       2023-07-26 06:16:30 UTC (rev 13527)
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/docs/developer/assets/bp-custom-basic-group-extension.png
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:mime-type</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+image/png
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunkdocsdeveloperassetsbpcustomgroupextensionadminscreenpng"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/docs/developer/assets/bp-custom-group-extension-admin-screen.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx" style="display: block; padding: 0 10px">Index: trunk/docs/developer/assets/bp-custom-group-extension-admin-screen.png
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- trunk/docs/developer/assets/bp-custom-group-extension-admin-screen.png       2023-07-26 05:29:26 UTC (rev 13526)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ trunk/docs/developer/assets/bp-custom-group-extension-admin-screen.png        2023-07-26 06:16:30 UTC (rev 13527)
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/docs/developer/assets/bp-custom-group-extension-admin-screen.png
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:mime-type</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+image/png
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunkdocsdeveloperassetsbpcustomgroupextensioncreatescreenpng"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/docs/developer/assets/bp-custom-group-extension-create-screen.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx" style="display: block; padding: 0 10px">Index: trunk/docs/developer/assets/bp-custom-group-extension-create-screen.png
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- trunk/docs/developer/assets/bp-custom-group-extension-create-screen.png      2023-07-26 05:29:26 UTC (rev 13526)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ trunk/docs/developer/assets/bp-custom-group-extension-create-screen.png       2023-07-26 06:16:30 UTC (rev 13527)
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/docs/developer/assets/bp-custom-group-extension-create-screen.png
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:mime-type</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+image/png
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunkdocsdeveloperassetsbpcustomgroupextensioneditscreenpng"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/docs/developer/assets/bp-custom-group-extension-edit-screen.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx" style="display: block; padding: 0 10px">Index: trunk/docs/developer/assets/bp-custom-group-extension-edit-screen.png
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- trunk/docs/developer/assets/bp-custom-group-extension-edit-screen.png        2023-07-26 05:29:26 UTC (rev 13526)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ trunk/docs/developer/assets/bp-custom-group-extension-edit-screen.png 2023-07-26 06:16:30 UTC (rev 13527)
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/docs/developer/assets/bp-custom-group-extension-edit-screen.png
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:mime-type</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+image/png
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunkdocsdevelopergroupextensionREADMEmd"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/docs/developer/group-extension/README.md</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/docs/developer/group-extension/README.md                            (rev 0)
+++ trunk/docs/developer/group-extension/README.md      2023-07-26 06:16:30 UTC (rev 13527)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,302 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+# Group Extension API
+
+The group extension API makes it very easy to add custom creation steps, edit screens, navigation items and pages to a group. It essentially allows you to create fully functional extensions to BuddyPress created groups.
+
+The Group Extension API consists of a base class called `BP_Group_Extension`, which you extend in your own add-on. `BP_Group_Extension` does most of the work necessary to integrate your content into BP group – creating new navigation tabs, registering a step during group creation, etc.
+
+**NB**: the group extension requires the Groups component to be active. Please make sure to wrap your extended class in a `if ( bp_is_active( 'groups' ) ) :` check.
+
+Located inside the `/bp-groups/classes` directory, the `BP_Group_Extension` class will help you to organize your custom group extension. BuddyPress group extensions are registered into the `$group_extensions` property of the `buddypress()->groups` global using the name of your custom class. This registration step needs to be hooked to the `bp_init` action at a priority lower than `11` (you can omit the hook `$priority` argument to use the default one - `10`) and is done passing the name of your class to the `bp_register_group_extension()` function. Below is an example of how you can register your group extension in BuddyPress.
+
+```php
+/**
+ * Registers the custom group extension.
+ */
+function bp_custom_add_on_register_group_extension() {
+       bp_register_group_extension( 'BP_Custom_AddOn_Group_Extension' );
+}
+add_action( 'bp_init', 'bp_custom_add_on_register_group_extension' );
+```
+
+## Building your group extension’s class
+
+It’s a [WordPress good practice](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/#naming-conventions) to put the code of your class into a file having a `class-` prefix followed by your class name where caps are replaced by their corresponding lower case value and underscores by dashes. As our custom group extension's class is named `BP_Custom_Group_Extension`, we are putting its code inside a `class-bp-custom-group-extension.php` file. Let's built it making sure you will inherit from the `BP_Component` parent class using the `extends` keyword.
+
+```php
+class BP_Custom_Group_Extension extends BP_Group_Extension {
+       /*
+        * The properties and methods of for your group extension's class.
+        */ 
+}
+```
+
+### Adding the constructor of your class
+
+This is where you are using the `BP_Group_Extension::init()` method to configure your custom group extension. This method expects an associative array where specific keys will be used to define the name & URL slug for your group extension tab within groups, who can access to it, and init additional screens such as the one BuddyPress can load during the group's creation process, or the one to let group Administrators customize some settings about your group extension. Let's build a very basic tab that will be displayed on each single groups.
+
+![Basic group extension](../assets/bp-custom-basic-group-extension.png)
+
+To get this result, here's how you need to define the arguments of the parameter you will send to the `parent::init()`  method at the end of your constructor.
+
+```php
+if ( bp_is_active( 'groups' ) ) {
+       /**
+        * BP Custom group extension Class.
+        */
+       class BP_Custom_AddOn_Group_Extension extends BP_Group_Extension {
+               /**
+                * Your group extension's constructor.
+                */
+               public function __construct() {
+                       $args = array(
+                               'slug'              => 'custom-group-extension',
+                               'name'              => __( 'Custom group extension', 'custom-text-domain' ),
+                               'nav_item_position' => 105,
+                               'access'            => 'anyone',
+                               'show_tab'          => 'anyone',
+                       );
+
+                       parent::init( $args );
+               }
+
+               /**
+                * Outputs the content of your group extension tab.
+                *
+                * @param int|null $group_id ID of the displayed group.
+                */
+               public function display( $group_id = null ) {
+                       printf( '<p>%1$s %2$s</p>', esc_html__( 'It works! The displayed group ID is', 'custom-text-domain' ), $group_id );
+               }
+       }
+}
+```
+
+The above code early introduced the `display()`  method of your group extension's class so that something is actually displayed into groups! Before looking to it more in details, let's first list all possible keys and values for the `$args` configuration array.
+
+### Possible arguments for your configuration array
+
+As we've just seen, the `__construct()` method of your group extension class should be used to pass a set of arguments to the `parent::init( $args )` method. Below are these `$args` possible keys and values:
+
+#### `slug`
+
+**(required)** A unique string identifier for your group extension. Used, among other places, in the construction of URLs.
+
+#### `name`
+
+**(required)** The translatable name of your extension. Used as the default value for navigation items and page titles.
+
+#### `access`
+
+_(optional)_ Which users can visit the group extension’s tab. Possible values: 'anyone', 'loggedin', 'member', 'mod', 'admin' or 'noone'. ('member', 'mod', 'admin' refer to user’s role in the current group.) Defaults to 'anyone' for public groups and 'member' for private groups. Note that the 'mod' level targets only moderators, so if you want to allow access for group moderators and administrators, specify `array( 'mod', 'admin' )`. **This argument was introduced in BuddyPress 2.1.0.**
+
+#### `show_tab`
+
+_(optional)_ Which users can see the group extension’s navigation tab. Possible values: 'anyone', 'loggedin', 'member', 'mod', 'admin' or 'noone'. ('member', 'mod', 'admin' refer to user’s role in the current group.) Defaults to 'anyone' for public groups and 'member' for private groups. Note that the 'mod' level targets only moderators, so if you want to show the tab to group moderators and administrators, specify `array( 'mod', 'admin' )`. **This argument was introduced in BuddyPress 2.1.0.**
+
+#### `show_tab_callback`
+
+_(optional)_ The name of the function to use to define the `show_tab` argument. If you need to check for a specific setting to define whether or not your group extension tab should be shown to members, the static `show_tab` argument won't reply to your need. Use the `show_tab_callback` argument so that your callback function will be called once BuddyPress has set everything about the displayed group. Your callback function needs to return one of the possible values of the `show_tab` one. **This argument was introduced in BuddyPress 12.0.0.**
+
+#### `nav_item_position`
+
+_(optional)_ An integer describing where your extension’s tab should appear. A number between `1` and `100` is recommended. Defaults to `81`.
+
+#### `nav_item_name`
+
+_(optional)_ The string you want to appear in the navigation tab for your group extension. Defaults to the value of the `name` argument, described above.
+
+#### `template_file`
+
+_(optional)_ The template file that BuddyPress will use as a wrapper to display the content of your group extension. Defaults to  `groups/single/plugins.php`. This template is provided by built-in BP Template Packs (nouveau & legacy). If you are building a BuddyPress standalone theme, please make sure to provide this template.
+
+#### `screens`
+
+_(optional)_ A multi-dimensional array of options related to the three secondary “screens” available to group extensions: `create` (the step dedicated to the extension during the group creation process), `edit` (the subtab dedicated to the extension under the Admin tab of the group), and `admin` (the extension’s metabox that appears on the group page when editing via the Groups Administration Dashboard panels). Each of these screens has a set of configuration options, to be described below. Note that all config values are optional, and you only need to override those values where you want to change the default – BuddyPress will parse your `screens` array, using your provided values when available, otherwise falling back on the defaults.
+
+- `create` – Config options for the `create` screen
+  - `position` – The position of the group extension’s step in the Create a Group process. An integer between `1` and `100` is recommended. Defaults to `81`.
+  - `enabled` – `true` if you want your group extension to have a Create step, otherwise `false`. Defaults to `true`.
+  - `name` – The name of the creation step, as it appears in the step’s navigation tab. Defaults to the general `name` value described above.
+  - `slug` – The string used to create the URL of the creation step. Defaults to the general `slug` value described above.
+  - `screen_callback` – The function BuddyPress will call to display the content of your create screen. BuddyPress attempts to determine this function 
+  automatically; see Methods below. Do not change this value unless you know what you’re doing.
+  - `screen_save_callback` – The function BuddyPress will call after the group extension’s create step has been saved. BuddyPress attempts to determine this 
+  function automatically; see Methods below. Do not change this value unless you know what you’re doing.
+
+- `edit` – Config options for the ‘edit’ screen, a sub item of the Group's Manage item on the front-end.
+  - `submit_text` – The text of the submit button on the edit screen. Defaults to 'Edit'.
+  - `enabled` – `true` if you want your group extension to have a subtab in the Group Adimn area, otherwise `false`. Defaults to `true`.
+  - `name` – The text that appears in the navigation tab for the group extension’s Edit screen. Defaults to the general `name` value described above.
+  - `slug` – The string used to create the URL of the admin tab. Defaults to the general `slug` value described above.
+  - `screen_callback` – The function BuddyPress will call to display the content of your admin tab. BuddyPress attempts to determine this function automatically; 
+  see Methods below. Do not change this value unless you know what you’re doing.
+  - `screen_save_callback` – The function BuddyPress will call after the group extension’s admin tab has been saved. BuddyPress attempts to determine this 
+  function automatically; see Methods below. Do not change this value unless you know what you’re doing.
+
+- `admin` – Config options for the `admin` screen, available from the "Groups" administration menu of your WordPress Dashboard (_Group Admin area_).  
+  - `metabox_context` – The context for your group extension’s metabox. Defaults to `'normal'`. (See [add_meta_box()](https://developer.wordpress.org/reference/functions/add_meta_box/) for more details.)
+  - `metabox_priority` – The priority for your group extension’s metabox. Defaults to `''`. (See [add_meta_box()](https://developer.wordpress.org/reference/functions/add_meta_box/) for more details.)
+  - `enabled` – `true` if you want your group extension to have a subtab in the _Group Admin area_, otherwise `false`. Defaults to `true`.
+  - `name` – The text used as the title for the meta box of your group extension’s Admin screen. Defaults to the general `name` value described above.
+  - `slug` – The string used as the meta box ID (used in the `id` attribute for the meta box). Defaults to the general `slug` value described above.
+  - `screen_callback` – The function BuddyPress will call to display the content for the meta box of your group extension’s Admin screen. BuddyPress attempts to 
+  determine this function automatically; see Methods below. Do not change this value unless you know what you’re doing.
+  - `screen_save_callback` – The function BuddyPress will call to save your group extension’s admin settings during the Group admin settings update. BuddyPress 
+  attempts to determine this function automatically; see Methods below. Do not change this value unless you know what you’re doing.
+
+### Available Methods for your group extension’s class
+
+`BP_Group_Extension` has built-in support for a number of different customization methods, which you can override in your group extension’s class as needed.
+
+#### `display()`
+The most prominent of these methods is `display()`, which BuddyPress uses to generate the output of the add-on’s main tab. It includes the `$group_id` argument so that you can customize your output according to the current displayed group. Your `display()` method should echo markup, which BuddyPress will automatically place into the proper template. As a reminder, below is the code we used in our very basic example of a group extension's class.
+
+```php
+if ( bp_is_active( 'groups' ) ) {
+       class BP_Custom_AddOn_Group_Extension extends BP_Group_Extension {
+               public function __construct() { /* Your group extension's constructor. */ }
+
+               /**
+                * Outputs the content of your group extension tab.
+                *
+                * @param int|null $group_id ID of the displayed group.
+                */
+               public function display( $group_id = null ) {
+                       // You need to echo the markup.
+                       printf( '<p>%1$s %2$s</p>', esc_html__( 'It works! The displayed group ID is', 'custom-text-domain' ), $group_id );
+               }
+       }
+}
+```
+
+#### Other screen methods
+For the three “screen” contexts – `create`, `edit`, and `admin` – a flexible system allows you to customize the way that your group extension’s screens work, without unnecessary reproduction of code. Your group extension should, **at minimum**, provide the following two methods if you defined one or more screen context into your configuration array:
+
+- `settings_screen()`: outputs the fallback markup for your `create` / `edit` / `admin` screens.
+- `settings_screen_save()`: called after changes are submitted from the `create` / `edit` / `admin` screens. This method should contain the logic necessary to catch settings form submits, validate submitted settings, and save them to the database.
+
+**NB**: these 2 methods include the `$group_id` argument so that you can customize your output/handler according to the current group being created, edited or adminstrated.
+
+Let's improve our example of basic group extension including a feature to let the creator/administrator of the group decide whether they want to "activate" the group extension main tab for their group.
+
+|![Create Screen](../assets/bp-custom-group-extension-create-screen.png)|![Edit Screen](../assets/bp-custom-group-extension-edit-screen.png)|![Admin Screen](../assets/bp-custom-group-extension-admin-screen.png)|
+|:-:|:-:|:-:|
+|Create screen|Edit screen|Admin screen|
+
+As shown above, we need to output a form on the group’s `create`, `edit` & `admin` screens. The first step is to edit the configuration array (`$args`) the `__construct()` method is sending to `BP_Group_Extension::init()` so that it includes a `$screens` argument and a `$show_tab_callback` argument. The first will define the screens we need to add, and the second one will set the callback function to use to check whether to display the group’s extension main tab or not. Here's how the configuration array should look like:
+
+```php
+$args = array(
+       'slug'              => 'custom-group-extension',
+       'name'              => __( 'Custom group extension', 'custom-text-domain' ),
+       'nav_item_position' => 105,
+       'access'            => 'anyone',
+
+       // Set the callback function definining the `$show_tab` argument dynamically.
+       'show_tab_callback' => array( $this, 'show_tab' ),
+
+       // Define the screens using default screen settings.
+       'screens'           => array(
+               'edit'   => array(),
+               'create' => array(),
+               'admin'  => array(),
+       ),
+);
+```
+
+**NB**: if you need your group extension to be back compatible with version of BuddyPress < 12.0.0, you'll need to add a conditional statement to use the `$show_tab` argument instead of the `$show_tab_callback` one. Here’s an example of how to add it:
+
+```php
+// BuddyPress < 12.0.0 or BuddyPress >= 12.0.0 with the BP Classic backcompat plugin active.
+if ( ! function_exists( 'bp_core_get_query_parser' ) || 'legacy' === bp_core_get_query_parser() ) {
+       $args['show_tab'] = $this->show_tab();
+       unset( $args['show_tab_callback'] );
+}
+```
+
+**NB**: note that in the above code, we are not setting the callback function but running it. This means as it doesn’t include the `$group_id` in this case, you’ll need to use the `bp_get_current_group_id()` to set it within your `show_tab()` method. For example:
+
+```php
+/**
+ * Checks whether the main group extension’s tab should be displayed.
+ *
+ * @param int|null $group_id ID of the displayed group.
+ * @return string 'anyone' if the group extension’s tab should be displayed. 'noone' otherwise.
+ */
+public function show_tab( $group_id = null ) {
+       if ( ! $group_id ) {
+               $group_id = bp_get_current_group_id();
+       }
+
+       $show_tab = 'noone';
+       if ( $group_id && groups_get_groupmeta( $group_id, 'bp_custom_group_extension_is_active' ) ) {
+               $show_tab = 'anyone';
+       }
+
+       return $show_tab;
+}
+```
+
+The second step is to code the `settings_screen()` & `settings_screen_save()` methods so that each screen will output a form and handle its submission. Here's how these should look like into your group extension’s class:
+
+```php
+if ( bp_is_active( 'groups' ) ) {
+       class BP_Custom_AddOn_Group_Extension extends BP_Group_Extension {
+               public function __construct() { /* Your group extension's constructor. */ }
+               public function display( $group_id = null ) { /* Outputs the content of your group extension tab. */ }
+
+               /**
+                * Outputs a form to activate the extension on 'edit', 'create' & 'admin' screens.
+                *
+                * @param int|null $group_id ID of the displayed group.
+                */
+               public function settings_screen( $group_id = null ) {
+                       $active = (int) groups_get_groupmeta( $group_id, 'bp_custom_group_extension_is_active' );
+                       printf(
+                               '<label><input type="checkbox" name="bp_custom_group_extension_is_active" value="1" %1$s>%2$s</input></label>
+                               <input type="hidden" name="bp_custom_group_extension_was_active" value="%3$s">',
+                               checked( $active, true, false ),
+                               esc_html__( 'I want to activate the custom group extension!', 'custom-text-domain' ),
+                               $active
+                       );
+               }
+
+               /**
+                * Activate or Deactivate the group extension from 'edit', 'create' or 'admin' screens.
+                *
+                * @param int|null $group_id ID of the displayed group.
+                */
+               public function settings_screen_save( $group_id = null ) {
+                       $was_active = 0;
+                       $is_active  = 0;
+
+                       if ( isset( $_REQUEST['bp_custom_group_extension_was_active'] ) ) {
+                               $was_active = intval( wp_unslash( $_REQUEST['bp_custom_group_extension_was_active'] ) );
+
+                               if ( isset( $_REQUEST['bp_custom_group_extension_is_active'] ) ) {
+                                       $is_active = intval( wp_unslash( $_REQUEST['bp_custom_group_extension_is_active'] ) );
+                               }
+
+                               if ( $was_active && ! $is_active ) {
+                                       groups_delete_groupmeta( $group_id, 'bp_custom_group_extension_is_active' );
+                               } elseif ( ! $was_active && $is_active ) {
+                                       groups_update_groupmeta( $group_id, 'bp_custom_group_extension_is_active', $is_active );
+                               }
+                       }
+               }
+       }
+}
+```
+
+Finally, If your extension requires further customization to one or more of the screens, BuddyPress provides the following methods, which are context-specific:
+
+- `create_screen()`: outputs the fallback markup for your `create` screen.
+- `create_screen_save()`: called after changes are submitted from the `create` screen. This method should contain the logic necessary to catch settings form submits, validate submitted settings, and save them to the database.
+- `edit_screen()`: outputs the fallback markup for your `edit` screen.
+- `edit_screen_save()`: called after changes are submitted from the `edit` screen. This method should contain the logic necessary to catch settings form submits, validate submitted settings, and save them to the database.
+- `admin_screen()`: outputs the fallback markup for your `admin` screen.
+- `admin_screen_save()`: called after changes are submitted from the `admin` screen. This method should contain the logic necessary to catch settings form submits, validate submitted settings, and save them to the database.
+
+**NB**: these methods include the `$group_id` argument so that you can customize your output/handler according to the current group being updated.
+
+If your extension contains any of these methods, BuddyPress will use them when appropriate. Otherwise, the generic `settings_screen()` or `settings_screen_save()` will be used.
</ins></span></pre></div>
<a id="trunkdocsdevelopermanifestjson"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/docs/developer/manifest.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/docs/developer/manifest.json        2023-07-26 05:29:26 UTC (rev 13526)
+++ trunk/docs/developer/manifest.json  2023-07-26 06:16:30 UTC (rev 13527)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -24,6 +24,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                "parent": null
</span><span class="cx" style="display: block; padding: 0 10px">        },
</span><span class="cx" style="display: block; padding: 0 10px">        {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                "title": "Group Extension API",
+               "slug": "bp-group-extension",
+               "markdown_source": "../developer/group-extension/README.md",
+               "parent": null
+       },
+       {
</ins><span class="cx" style="display: block; padding: 0 10px">                 "title": "BuddyPress Theme compatibility",
</span><span class="cx" style="display: block; padding: 0 10px">                "slug": "bp-theme-compat",
</span><span class="cx" style="display: block; padding: 0 10px">                "markdown_source": "../developer/theme-compat/README.md",
</span></span></pre>
</div>
</div>

</body>
</html>