Skip to:
Content

BuddyPress.org

Changeset 6997


Ignore:
Timestamp:
05/05/2013 07:08:19 PM (13 years ago)
Author:
boonebgorges
Message:

Refactor and reorganization of BP_Group_Extension

The shiny new BP_Group_Extension class boasts the following features:

  • The *_screen* methods (edit_screen(), edit_screen_save(), etc) now share identical requirements for markup and logic. You no longer need to provide a Submit button for edit_screen() but not for create_screen(); BuddyPress provides one for you in each context. (For backward compatibility, we verify that your edit_screen() method does not already have a Submit button before auto-adding our own.) Nonces are now created and checked automatically for all form contexts. And it is no longer necessary to check whether you are on the correct group creation or admin step before outputting your markup - BP_Group_Extension does it for you.
  • Introduces support for fallback methods settings_screen() and settings_screen_save(). When you define these methods in your extension, they will provide the markup and form-saving logic for your Create, Edit, and Admin panels. If you provide specific methods for a given context (say, edit_screen() and create_screen_save()), BP_Group_Extension detects it, and uses the more specific ones instead. This should make it much easier to write DRY code in your BP_Group_Extension classes, while maintaining maximum flexibility.
  • Configuration should now be set using a config array, which is then passed to parent::init() at the end of your class constructor. This technique more closely mirrors the way that BuddyPress and WordPress handle configuration elsewhere. BP_Group_Extension parses your config array to arbitrary depth, so that you only need to pass those values that you wish to change from the defaults.
  • Complete backward compatibility for legacy BP_Group_Extension plugins.
  • Improved organization, documentation, and unit tests.

Props johnjamesjacoby for detailed feedback.

See #4955

Location:
trunk
Files:
3 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/bp-groups/bp-groups-classes.php

    r6992 r6997  
    13681368 * the theme.
    13691369 *
    1370  * This class must be extended for each group extension and the following methods overridden:
     1370 * To implement, extend this class. In your constructor, pass an optional array
     1371 * of arguments to parent::init() to configure your widget. The config array
     1372 * supports the following values:
     1373 *   - 'slug' A unique identifier for your extension. This value will be used
     1374 *     to build URLs, so make it URL-safe
     1375 *   - 'name' A translatable name for your extension. This value is used to
     1376       populate the navigation tab, as well as the default titles for admin/
     1377       edit/create tabs.
     1378 *   - 'visibility' Set to 'public' (default) for your extension (the main tab
     1379 *     as well as the widget) to be available to anyone who can access the
     1380 *     group, 'private' otherwise.
     1381 *   - 'nav_item_position' An integer explaining where the nav item should
     1382 *     appear in the tab list
     1383 *   - 'enable_nav_item' Set to true for your extension's main tab to be
     1384 *     available to anyone who can access the group.
     1385 *   - 'nav_item_name' The translatable text you want to appear in the nav tab.
     1386 *     Defaults to the value of 'name'.
     1387 *   - 'display_hook' The WordPress action that the widget_display() method is
     1388 *     hooked to
     1389 *   - 'template_file' The template file that will be used to load the content
     1390 *     of your main extension tab. Defaults to 'groups/single/plugins.php'.
     1391 *   - 'screens' A multi-dimensional array, described below
    13711392 *
    1372  * BP_Group_Extension::widget_display(), BP_Group_Extension::display(),
    1373  * BP_Group_Extension::edit_screen_save(), BP_Group_Extension::edit_screen(),
    1374  * BP_Group_Extension::create_screen_save(), BP_Group_Extension::create_screen()
     1393 * BP_Group_Extension uses the concept of "settings screens". There are three
     1394 * contexts for settings screens:
     1395 *   - 'create', which inserts a new step into the group creation process
     1396 *   - 'edit', which adds a tab for your extension into the Admin section of
     1397 *     a group
     1398 *   - 'admin', which adds a metabox to the Groups administration panel in the
     1399 *     WordPress Dashboard
     1400 * Each of these settings screens is populated by a pair of methods: one that
     1401 * creates the markup for the screen, and one that processes form data
     1402 * submitted from the screen. If your plugin needs screens in all three
     1403 * contexts, and if the markup and form processing logic will be the same in
     1404 * each case, you can define two methods to handle all of the screens:
     1405 *   function settings_screen() {}
     1406 *   function settings_screen_save() {}
     1407 * If one or more of your settings screen needs separate logic, you may define
     1408 * context-specific methods, for example:
     1409 *   function edit_screen() {}
     1410 *   function edit_screen_save() {}
     1411 * BP_Group_Extension will use the more specific methods if they are available.
     1412 *
     1413 * You can further customize the settings screens (tab names, etc) by passing
     1414 * an optional 'screens' parameter to the init array. The format is as follows:
     1415 *   'screens' => array(
     1416 *       'create' => array(
     1417 *           'slug' => 'foo',
     1418 *           'name' => 'Foo',
     1419 *           'position' => 55,
     1420 *           'screen_callback' => 'my_create_screen_callback',
     1421 *           'screen_save_callback' => 'my_create_screen_save_callback',
     1422 *       ),
     1423 *       'edit' => array( // ...
     1424 *   ),
     1425 * Only provide those arguments that you actually want to change from the
     1426 * default configuration. BP_Group_Extension will do the rest.
     1427 *
     1428 * Note that the 'edit' screen accepts an additional parameter: 'submit_text',
     1429 * which defines the text of the Submit button automatically added to the Edit
     1430 * screen of the extension (defaults to 'Save Changes'). Also, the 'admin'
     1431 * screen accepts two additional parameters: 'metabox_priority' and
     1432 * 'metabox_context'. See the docs for add_meta_box() for more details on these
     1433 * arguments.
     1434 *
     1435 * Prior to BuddyPress 1.7, group extension configurations were set slightly
     1436 * differently. The legacy method is still supported, though deprecated.
    13751437 *
    13761438 * @package BuddyPress
     
    13791441 */
    13801442class BP_Group_Extension {
    1381         var $name = false;
    1382         var $slug = false;
    1383 
    1384         // The name/slug of the Group Admin tab for this extension
    1385         var $admin_name = '';
    1386         var $admin_slug = '';
    1387 
    1388         // The name/slug of the Group Creation tab for this extension
    1389         var $create_name = '';
    1390         var $create_slug = '';
    1391 
    1392         // Will this extension be visible to non-members of a group? Options: public/private
    1393         var $visibility = 'public';
    1394 
    1395         var $create_step_position = 81;
    1396         var $nav_item_position = 81;
    1397 
    1398         /**
    1399          * @var string Context for the optional admin metabox
    1400          * @see https://codex.wordpress.org/Function_Reference/add_meta_box for
    1401          *      possible values
    1402          * @since BuddyPress (1.7)
    1403          */
    1404         var $admin_metabox_context = 'normal';
    1405 
    1406         /**
    1407          * @var string Priority for the optional admin menabox
    1408          * @see https://codex.wordpress.org/Function_Reference/add_meta_box for
    1409          *      possible values
    1410          * @since BuddyPress (1.7)
    1411          */
    1412         var $admin_metabox_priority = 'core';
    1413 
    1414         var $enable_create_step = true;
    1415         var $enable_nav_item = true;
    1416         var $enable_edit_item = true;
    1417         var $enable_admin_item = true;
    1418 
    1419         var $nav_item_name = false;
    1420 
    1421         var $display_hook = 'groups_custom_group_boxes';
    1422         var $template_file = 'groups/single/plugins';
    1423 
    1424         // Methods you should override
    1425 
    1426         function display() {}
    1427 
    1428         function widget_display() {}
    1429 
    1430         function edit_screen( $group_id = null ) {}
    1431 
    1432         function edit_screen_save( $group_id = null ) {}
    1433 
    1434         function create_screen( $group_id = null ) {}
    1435 
    1436         function create_screen_save( $group_id = null ) {}
    1437 
    1438         // Private Methods
    1439 
    1440         function _register() {
    1441                 global $bp;
    1442 
    1443                 // If admin/create names and slugs are not provided, they fall back on the main
    1444                 // name and slug for the extension
    1445                 if ( ! $this->admin_name ) {
    1446                         $this->admin_name = $this->name;
    1447                 }
    1448 
    1449                 if ( ! $this->admin_slug ) {
    1450                         $this->admin_slug = $this->slug;
    1451                 }
    1452 
    1453                 if ( ! $this->create_name ) {
    1454                         $this->create_name = $this->name;
    1455                 }
    1456 
    1457                 if ( ! $this->create_slug ) {
    1458                         $this->create_slug = $this->slug;
    1459                 }
    1460 
    1461                 if ( ! empty( $this->enable_create_step ) ) {
    1462                         // Insert the group creation step for the new group extension
    1463                         $bp->groups->group_creation_steps[ $this->create_slug ] = array(
    1464                                 'name'     => $this->create_name,
    1465                                 'slug'     => $this->create_slug,
    1466                                 'position' => $this->create_step_position,
    1467                         );
    1468 
    1469                         // The maybe_ methods check to see whether the create_*
    1470                         // callbacks should be invoked (ie, are we on the
    1471                         // correct group creation step). Hooked in separate
    1472                         // methods because current creation step info not yet
    1473                         // available at this point
    1474                         add_action( 'groups_custom_create_steps', array( $this, 'maybe_create_screen' ) );
    1475                         add_action( 'groups_create_group_step_save_' . $this->create_slug, array( $this, 'maybe_create_screen_save' ) );
    1476                 }
    1477 
    1478                 // When we are viewing a single group, add the group extension nav item
    1479                 if ( bp_is_group() ) {
    1480                         if ( $this->visibility == 'public' || ( $this->visibility != 'public' && $bp->groups->current_group->user_has_access ) ) {
    1481                                 if ( $this->enable_nav_item ) {
    1482                                         bp_core_new_subnav_item( array(
    1483                                                 'name' => !$this->nav_item_name ? $this->name : $this->nav_item_name,
    1484                                                 'slug' => $this->slug,
    1485                                                 'parent_slug' => $bp->groups->current_group->slug,
    1486                                                 'parent_url' => bp_get_group_permalink( $bp->groups->current_group ),
    1487                                                 'position' => $this->nav_item_position,
    1488                                                 'item_css_id' => 'nav-' . $this->slug,
    1489                                                 'screen_function' => array( &$this, '_display_hook' ),
    1490                                                 'user_has_access' => $this->enable_nav_item
    1491                                         ) );
    1492 
    1493                                         // When we are viewing the extension display page, set the title and options title
    1494                                         if ( bp_is_current_action( $this->slug ) ) {
    1495                                                 add_action( 'bp_template_content_header', create_function( '', 'echo "' . esc_attr( $this->name ) . '";' ) );
    1496                                                 add_action( 'bp_template_title', create_function( '', 'echo "' . esc_attr( $this->name ) . '";' ) );
    1497                                         }
    1498                                 }
    1499 
    1500                                 // Hook the group home widget
    1501                                 if ( ! bp_current_action() && bp_is_current_action( 'home' ) ) {
    1502                                         add_action( $this->display_hook, array( &$this, 'widget_display' ) );
    1503                                 }
     1443
     1444        /** Public ****************************************************************/
     1445
     1446        /**
     1447         * @var array Information about this extension's screens
     1448         * @since BuddyPress (1.8)
     1449         */
     1450        public $screens = array();
     1451
     1452        /**
     1453         * @var string The name of the extending class
     1454         * @since BuddyPress (1.8)
     1455         */
     1456        public $class_name = '';
     1457
     1458        /**
     1459         * @var object A ReflectionClass object of the current extension
     1460         * @since BuddyPress (1.8)
     1461         */
     1462        public $class_reflection = null;
     1463
     1464        /**
     1465         * @var array Parsed configuration paramaters for the extension
     1466         * @since BuddyPress (1.8)
     1467         */
     1468        public $params = array();
     1469
     1470        /**
     1471         * @var int The id of the current group
     1472         * @since BuddyPress (1.8)
     1473         */
     1474        public $group_id = 0;
     1475
     1476        /**
     1477         * @var string The slug of the current extension
     1478         */
     1479        public $slug = '';
     1480
     1481        /**
     1482         * @var string The translatable name of the current extension
     1483         */
     1484        public $name = '';
     1485
     1486        /**
     1487         * @var string Whether the extension tab is visible. 'public'
     1488         *   or 'private'
     1489         */
     1490        public $visibility = 'public';
     1491
     1492        /**
     1493         * @var int The numeric position of the main nav item
     1494         */
     1495        public $nav_item_position = 81;
     1496
     1497        /**
     1498         * @var bool Whether to show the nav item
     1499         */
     1500        public $enable_nav_item = false;
     1501
     1502        /**
     1503         * @var string The text of the nav item. Defaults to self::name
     1504         */
     1505        public $nav_item_name = '';
     1506
     1507        /**
     1508         * @var string The WP action that self::widget_display() is attached to.
     1509         *   Defaults to 'groups_custom_group_boxes'
     1510         */
     1511        public $display_hook = 'groups_custom_group_boxes';
     1512
     1513        /**
     1514         * @var string The template file used to load the plugin content.
     1515         *   Defaults to 'groups/single/plugins'
     1516         */
     1517        public $template_file = 'groups/single/plugins';
     1518
     1519        /** Protected *************************************************************/
     1520
     1521        /**
     1522         * @var bool Has the extension been initialized?
     1523         * @since BuddyPress (1.8)
     1524         */
     1525        protected $initialized = false;
     1526
     1527        /**
     1528         * @var array Extension properties as set by legacy extensions
     1529         * @since BuddyPress (1.8)
     1530         */
     1531        protected $legacy_properties = array();
     1532
     1533        /**
     1534         * @var array Extension properties as set by legacy extensions, but
     1535         *   converted to match the new format for params
     1536         * @since BuddyPress (1.8)
     1537         */
     1538        protected $legacy_properties_converted = array();
     1539
     1540        /**
     1541         * @var array Miscellaneous data as set by the __set() magic method
     1542         * @since BuddyPress (1.8)
     1543         */
     1544        protected $data = array();
     1545
     1546        /** Screen Overrides ******************************************************/
     1547
     1548        /**
     1549         * Screen override methods are how your extension will display content
     1550         * and handle form submits. Your extension should only override those
     1551         * methods that it needs for its purposes.
     1552         */
     1553
     1554        // The content of the group tab
     1555        public function display() {}
     1556
     1557        // Content displayed in a widget sidebar, if applicable
     1558        public function widget_display() {}
     1559
     1560        // *_screen() displays the settings form for the given context
     1561        // *_screen_save() processes data submitted via the settings form
     1562        // The settings_* methods are generic fallbacks, which can optionally
     1563        // be overridden by the more specific edit_*, create_*, and admin_*
     1564        // versions.
     1565        public function settings_screen( $group_id = null ) {}
     1566        public function settings_screen_save( $group_id = null ) {}
     1567        public function edit_screen( $group_id = null ) {}
     1568        public function edit_screen_save( $group_id = null ) {}
     1569        public function create_screen( $group_id = null ) {}
     1570        public function create_screen_save( $group_id = null ) {}
     1571        public function admin_screen( $group_id = null ) {}
     1572        public function admin_screen_save( $group_id = null ) {}
     1573
     1574        /** Setup *************************************************************/
     1575
     1576        /**
     1577         * Initialize the extension, using your config settings
     1578         *
     1579         * Your plugin should call this method at the very end of its
     1580         * constructor, like so:
     1581         *
     1582         *   public function __construct() {
     1583         *       $args = array(
     1584         *           'slug' => 'my-group-extension',
     1585         *           'name' => 'My Group Extension',
     1586         *           // ...
     1587         *       );
     1588         *
     1589         *       parent::init( $args );
     1590         *   }
     1591         *
     1592         * @since BuddyPress (1.8)
     1593         * @param array $args See inline definition below for arguments
     1594         */
     1595        public function init( $args = array() ) {
     1596
     1597                // Before this init() method was introduced, plugins were
     1598                // encouraged to set their config directly. For backward
     1599                // compatibility with these plugins, we detect whether this is
     1600                // one of those legacy plugins, and parse any legacy arguments
     1601                // with those passed to init()
     1602                $this->parse_legacy_properties();
     1603                $args = $this->parse_args_r( $args, $this->legacy_properties_converted );
     1604
     1605                // Parse with defaults
     1606                $this->params = $this->parse_args_r( $args, array(
     1607                        'slug'              => $this->slug,
     1608                        'name'              => $this->name,
     1609                        'visibility'        => $this->visibility,
     1610                        'nav_item_position' => $this->nav_item_position,
     1611                        'enable_nav_item'   => (bool) $this->enable_nav_item,
     1612                        'nav_item_name'     => $this->nav_item_name,
     1613                        'display_hook'      => $this->display_hook,
     1614                        'template_file'     => $this->template_file,
     1615                        'screens'           => $this->get_default_screens(),
     1616                ) );
     1617
     1618                $this->initialized = true;
     1619        }
     1620
     1621        /**
     1622         * The main setup routine for the extension
     1623         *
     1624         * This method contains the primary logic for setting up an extension's
     1625         * configuration, setting up backward compatibility for legacy plugins,
     1626         * and hooking the extension's screen functions into WP and BP.
     1627         *
     1628         * Marked 'public' because it must be accessible to add_action().
     1629         * However, you should never need to invoke this method yourself - it
     1630         * is called automatically at the right point in the load order by
     1631         * bp_register_group_extension().
     1632         *
     1633         * @since BuddyPress (1.1)
     1634         */
     1635        public function _register() {
     1636
     1637                // Detect and parse properties set by legacy extensions
     1638                $this->parse_legacy_properties();
     1639
     1640                // Initialize, if necessary. This should only happen for
     1641                // legacy extensions that don't call parent::init() themselves
     1642                if ( true !== $this->initialized ) {
     1643                        $this->init();
     1644                }
     1645
     1646                // Set some config values, based on the parsed params
     1647                $this->group_id          = $this->get_group_id();
     1648                $this->slug              = $this->params['slug'];
     1649                $this->name              = $this->params['name'];
     1650                $this->visibility        = $this->params['visibility'];
     1651                $this->nav_item_position = $this->params['nav_item_position'];
     1652                $this->nav_item_name     = $this->params['nav_item_name'];
     1653                $this->display_hook      = $this->params['display_hook'];
     1654                $this->template_file     = $this->params['template_file'];
     1655
     1656                // Configure 'screens': create, admin, and edit contexts
     1657                $this->setup_screens();
     1658
     1659                // Mirror configuration data so it's accessible to plugins
     1660                // that look for it in its old locations
     1661                $this->setup_legacy_properties();
     1662
     1663                // Hook the extension into BuddyPress
     1664                $this->setup_display_hooks();
     1665                $this->setup_create_hooks();
     1666                $this->setup_edit_hooks();
     1667                $this->setup_admin_hooks();
     1668        }
     1669
     1670        /**
     1671         * Set up some basic info about the Extension
     1672         *
     1673         * Here we collect the name of the extending class, as well as a
     1674         * ReflectionClass that is used in get_screen_callback() to determine
     1675         * whether your extension overrides certain callback methods.
     1676         *
     1677         * @since BuddyPress (1.8)
     1678         */
     1679        protected function setup_class_info() {
     1680                if ( empty( $this->class_name ) ) {
     1681                        $this->class_name = get_class( $this );
     1682                }
     1683
     1684                if ( is_null( $this->class_reflection ) ) {
     1685                        $this->class_reflection = new ReflectionClass( $this->class_name );
     1686                }
     1687        }
     1688
     1689        /**
     1690         * Get the current group id
     1691         *
     1692         * Check for:
     1693         *   - current group
     1694         *   - new group
     1695         *   - group admin
     1696         *
     1697         * @since BuddyPress (1.8)
     1698         */
     1699        public static function get_group_id() {
     1700
     1701                // Usually this will work
     1702                $group_id = bp_get_current_group_id();
     1703
     1704                // On the admin, get the group id out of the $_GET params
     1705                if ( empty( $group_id ) && is_admin() && ( isset( $_GET['page'] ) && ( 'bp-groups' === $_GET['page'] ) ) && ! empty( $_GET['gid'] ) ) {
     1706                        $group_id = (int) $_GET['gid'];
     1707                }
     1708
     1709                // This fallback will only be hit when the create step is very
     1710                // early
     1711                if ( empty( $group_id ) && bp_get_new_group_id() ) {
     1712                        $group_id = bp_get_new_group_id();
     1713                }
     1714
     1715                // On some setups, the group id has to be fetched out of the
     1716                // $_POST array
     1717                // @todo Figure out why this is happening during group creation
     1718                if ( empty( $group_id ) && isset( $_POST['group_id'] ) ) {
     1719                        $group_id = (int) $_POST['group_id'];
     1720                }
     1721
     1722                return $group_id;
     1723        }
     1724
     1725        /**
     1726         * Gather configuration data about your screens
     1727         *
     1728         * @since BuddyPress (1.8)
     1729         */
     1730        protected function get_default_screens() {
     1731                $this->setup_class_info();
     1732
     1733                $screens = array(
     1734                        'create' => array(
     1735                                'position' => 81,
     1736                        ),
     1737                        'edit'   => array(
     1738                                'submit_text' => __( 'Save Changes', 'buddypress' ),
     1739                        ),
     1740                        'admin'  => array(
     1741                                'metabox_context'  => 'normal',
     1742                                'metabox_priority' => 'core',
     1743                        ),
     1744                );
     1745
     1746                foreach ( $screens as $context => &$screen ) {
     1747                        $screen['enabled']     = true;
     1748                        $screen['name']        = $this->name;
     1749                        $screen['slug']        = $this->slug;
     1750
     1751                        $screen['screen_callback']      = $this->get_screen_callback( $context, 'screen'      );
     1752                        $screen['screen_save_callback'] = $this->get_screen_callback( $context, 'screen_save' );
     1753                }
     1754
     1755                return $screens;
     1756        }
     1757
     1758        /**
     1759         * Set up screens array based on params
     1760         *
     1761         * @since BuddyPress (1.8)
     1762         */
     1763        protected function setup_screens() {
     1764                foreach ( (array) $this->params['screens'] as $context => $screen ) {
     1765                        if ( empty( $screen['slug'] ) ) {
     1766                                $screen['slug'] = $this->slug;
    15041767                        }
    1505                 }
    1506 
    1507                 // Construct the admin edit tab for the new group extension
    1508                 if ( ! empty( $this->enable_edit_item ) && bp_is_item_admin() ) {
    1509                         add_action( 'groups_admin_tabs', create_function( '$current, $group_slug',
    1510                                 '$selected = "";
    1511                                 if ( "' . esc_attr( $this->admin_slug ) . '" == $current )
    1512                                         $selected = " class=\"current\"";
    1513                                 echo "<li{$selected}><a href=\"' . trailingslashit( bp_get_root_domain() . '/' . bp_get_groups_root_slug() . '/{$group_slug}/admin/' . esc_attr( $this->admin_slug ) ) . '\">' . esc_attr( $this->admin_name ) . '</a></li>";'
    1514                         ), 10, 2 );
    1515 
    1516                         // Catch the edit screen and forward it to the plugin template
    1517                         if ( bp_is_groups_component() && bp_is_current_action( 'admin' ) && bp_is_action_variable( $this->admin_slug, 0 ) ) {
    1518                                 $this->edit_screen_save( bp_get_current_group_id() );
    1519 
    1520                                 add_action( 'groups_custom_edit_steps', array( &$this, 'call_edit_screen' ) );
    1521 
    1522                                 if ( '' != bp_locate_template( array( 'groups/single/home.php' ), false ) ) {
    1523                                         bp_core_load_template( apply_filters( 'groups_template_group_home', 'groups/single/home' ) );
    1524                                 } else {
    1525                                         add_action( 'bp_template_content_header', create_function( '', 'echo "<ul class=\"content-header-nav\">"; bp_group_admin_tabs(); echo "</ul>";' ) );
    1526                                         add_action( 'bp_template_content', array( &$this, 'call_edit_screen' ) );
    1527                                         bp_core_load_template( apply_filters( 'bp_core_template_plugin', '/groups/single/plugins' ) );
    1528                                 }
     1768
     1769                        if ( empty( $screen['name'] ) ) {
     1770                                $screen['name'] = $this->name;
    15291771                        }
    1530                 }
    1531 
    1532                 // Construct the admin metabox
    1533                 // Plugin authors: Note that $this->enable_admin_item must be
    1534                 // set to true, and self::admin_screen() must be defined
    1535                 if ( ! empty( $this->enable_admin_item ) && is_admin() && method_exists( get_class( $this ), 'admin_screen' ) ) {
    1536                         // Hook the admin screen markup function to the content hook
    1537                         add_action( 'bp_groups_admin_meta_box_content_' . $this->slug, array( $this, 'admin_screen' ) );
    1538 
    1539                         // Initialize the metabox
    1540                         add_action( 'bp_groups_admin_meta_boxes', array( $this, '_meta_box_display_callback' ) );
    1541 
    1542                         // Catch the metabox save
    1543                         if ( method_exists( get_class( $this ), 'admin_screen_save' ) ) {
    1544                                 add_action( 'bp_group_admin_edit_after', array( $this, 'admin_screen_save' ), 10 );
     1772
     1773                        $this->screens[ $context ] = $screen;
     1774                }
     1775        }
     1776
     1777        /** Display ***************************************************************/
     1778
     1779        /**
     1780         * Hook this extension's group tab into BuddyPress, if necessary
     1781         *
     1782         * @since BuddyPress (1.8)
     1783         */
     1784        protected function setup_display_hooks() {
     1785
     1786                // Bail if not a group
     1787                if ( ! bp_is_group() ) {
     1788                        return;
     1789                }
     1790
     1791                // Bail if the current user doesn't have access
     1792                if ( ( 'public' !== $this->visibility ) && ! buddypress()->groups->current_group->user_has_access ) {
     1793                        return;
     1794                }
     1795
     1796                if ( true === $this->enable_nav_item ) {
     1797                        bp_core_new_subnav_item( array(
     1798                                'name'            => ! $this->nav_item_name ? $this->name : $this->nav_item_name,
     1799                                'slug'            => $this->slug,
     1800                                'parent_slug'     => bp_get_current_group_slug(),
     1801                                'parent_url'      => bp_get_group_permalink( groups_get_current_group() ),
     1802                                'position'        => $this->nav_item_position,
     1803                                'item_css_id'     => 'nav-' . $this->slug,
     1804                                'screen_function' => array( &$this, '_display_hook' ),
     1805                                'user_has_access' => $this->enable_nav_item
     1806                        ) );
     1807
     1808                        // When we are viewing the extension display page, set the title and options title
     1809                        if ( bp_is_current_action( $this->slug ) ) {
     1810                                add_action( 'bp_template_content_header', create_function( '', 'echo "' . esc_attr( $this->name ) . '";' ) );
     1811                                add_action( 'bp_template_title',          create_function( '', 'echo "' . esc_attr( $this->name ) . '";' ) );
    15451812                        }
    15461813                }
    1547         }
    1548 
    1549         function _display_hook() {
     1814
     1815                // Hook the group home widget
     1816                if ( ! bp_current_action() && bp_is_current_action( 'home' ) ) {
     1817                        add_action( $this->display_hook, array( &$this, 'widget_display' ) );
     1818                }
     1819        }
     1820
     1821        /**
     1822         * Hooks the main display method, and loads the template file
     1823         */
     1824        public function _display_hook() {
    15501825                add_action( 'bp_template_content', array( &$this, 'display' ) );
    15511826                bp_core_load_template( apply_filters( 'bp_core_template_plugin', $this->template_file ) );
    15521827        }
    15531828
     1829        /** Create ****************************************************************/
     1830
     1831        /**
     1832         * Hook this extension's Create step into BuddyPress, if necessary
     1833         *
     1834         * @since BuddyPress (1.8)
     1835         */
     1836        protected function setup_create_hooks() {
     1837                if ( ! $this->is_screen_enabled( 'create' ) ) {
     1838                        return;
     1839                }
     1840
     1841                $screen = $this->screens['create'];
     1842
     1843                // Insert the group creation step for the new group extension
     1844                buddypress()->groups->group_creation_steps[ $screen['slug'] ] = array(
     1845                        'name'     => $screen['name'],
     1846                        'slug'     => $screen['slug'],
     1847                        'position' => $screen['position'],
     1848                );
     1849
     1850                // The maybe_ methods check to see whether the create_*
     1851                // callbacks should be invoked (ie, are we on the
     1852                // correct group creation step). Hooked in separate
     1853                // methods because current creation step info not yet
     1854                // available at this point
     1855                add_action( 'groups_custom_create_steps', array( $this, 'maybe_create_screen' ) );
     1856                add_action( 'groups_create_group_step_save_' . $screen['slug'], array( $this, 'maybe_create_screen_save' ) );
     1857        }
     1858
     1859        /**
     1860         * Call the create_screen() method, if we're on the right page
     1861         *
     1862         * @since 1.8
     1863         */
     1864        public function maybe_create_screen() {
     1865                if ( ! bp_is_group_creation_step( $this->screens['create']['slug'] ) ) {
     1866                        return;
     1867                }
     1868
     1869                call_user_func( $this->screens['create']['screen_callback'], $this->group_id );
     1870                $this->nonce_field( 'create' );
     1871
     1872                // The create screen requires an additional nonce field
     1873                // due to a quirk in the way the templates are built
     1874                wp_nonce_field( 'groups_create_save_' . bp_get_groups_current_create_step() );
     1875        }
     1876
     1877        /**
     1878         * Call the create_screen_save() method, if we're on the right page
     1879         *
     1880         * @since 1.8
     1881         */
     1882        public function maybe_create_screen_save() {
     1883                if ( ! bp_is_group_creation_step( $this->screens['create']['slug'] ) ) {
     1884                        return;
     1885                }
     1886
     1887                $this->check_nonce( 'create' );
     1888                call_user_func( $this->screens['create']['screen_save_callback'], $this->group_id );
     1889        }
     1890
     1891        /** Edit ******************************************************************/
     1892
     1893        /**
     1894         * Hook this extension's Edit panel into BuddyPress, if necessary
     1895         *
     1896         * @since BuddyPress (1.8)
     1897         */
     1898        protected function setup_edit_hooks() {
     1899
     1900                // Bail if not an edit screen
     1901                if ( ! $this->is_screen_enabled( 'edit' ) || ! bp_is_item_admin() ) {
     1902                        return;
     1903                }
     1904
     1905                $screen = $this->screens['edit'];
     1906
     1907                // Add the tab
     1908                // @todo BP should be using bp_core_new_subnav_item()
     1909                add_action( 'groups_admin_tabs', create_function( '$current, $group_slug',
     1910                        '$selected = "";
     1911                        if ( "' . esc_attr( $screen['slug'] ) . '" == $current )
     1912                                $selected = " class=\"current\"";
     1913                        echo "<li{$selected}><a href=\"' . trailingslashit( bp_get_root_domain() . '/' . bp_get_groups_root_slug() . '/{$group_slug}/admin/' . esc_attr( $screen['slug'] ) ) . '\">' . esc_attr( $screen['name'] ) . '</a></li>";'
     1914                ), 10, 2 );
     1915
     1916                // Catch the edit screen and forward it to the plugin template
     1917                if ( bp_is_groups_component() && bp_is_current_action( 'admin' ) && bp_is_action_variable( $screen['slug'], 0 ) ) {
     1918                        $this->call_edit_screen_save( $this->group_id );
     1919
     1920                        add_action( 'groups_custom_edit_steps', array( &$this, 'call_edit_screen' ) );
     1921
     1922                        if ( '' !== bp_locate_template( array( 'groups/single/home.php' ), false ) ) {
     1923                                bp_core_load_template( apply_filters( 'groups_template_group_home', 'groups/single/home' ) );
     1924                        } else {
     1925                                add_action( 'bp_template_content_header', create_function( '', 'echo "<ul class=\"content-header-nav\">"; bp_group_admin_tabs(); echo "</ul>";' ) );
     1926                                add_action( 'bp_template_content', array( &$this, 'call_edit_screen' ) );
     1927                                bp_core_load_template( apply_filters( 'bp_core_template_plugin', '/groups/single/plugins' ) );
     1928                        }
     1929                }
     1930        }
     1931
     1932        /**
     1933         * Call the edit_screen() method
     1934         *
     1935         * Previous versions of BP_Group_Extension required plugins to provide
     1936         * their own Submit button and nonce fields when building markup. In
     1937         * BP 1.8, this requirement was lifted - BP_Group_Extension now handles
     1938         * all required submit buttons and nonces.
     1939         *
     1940         * We put the edit screen markup into an output buffer before echoing.
     1941         * This is so that we can check for the presence of a hardcoded submit
     1942         * button, as would be present in legacy plugins; if one is found, we
     1943         * do not auto-add our own button.
     1944         *
     1945         * @since BuddyPress (1.8)
     1946         */
     1947        public function call_edit_screen() {
     1948                ob_start();
     1949                call_user_func( $this->screens['edit']['screen_callback'], $this->group_id );
     1950                $screen = ob_get_contents();
     1951                ob_end_clean();
     1952
     1953                echo $this->maybe_add_submit_button( $screen );
     1954
     1955                $this->nonce_field( 'edit' );
     1956        }
     1957
     1958        /**
     1959         * Check the nonce, and call the edit_screen_save() method
     1960         *
     1961         * @since BuddyPress (1.8)
     1962         */
     1963        public function call_edit_screen_save() {
     1964                if ( empty( $_POST ) ) {
     1965                        return;
     1966                }
     1967
     1968                $this->check_nonce( 'edit' );
     1969                call_user_func( $this->screens['edit']['screen_save_callback'], $this->group_id );
     1970        }
     1971
     1972        /**
     1973         * Add a submit button to the edit form, if it needs one
     1974         *
     1975         * There's an inconsistency in the way that the group Edit and Create
     1976         * screens are rendered: the Create screen has a submit button built
     1977         * in, but the Edit screen does not. This function allows plugin
     1978         * authors to write markup that does not contain the submit button for
     1979         * use on both the Create and Edit screens - BP will provide the button
     1980         * if one is not found.
     1981         *
     1982         * @since BuddyPress (1.8)
     1983         * @param string $screen The screen markup, captured in the output buffer
     1984         * @param string $screen The same markup, with a submit button added
     1985         */
     1986        protected function maybe_add_submit_button( $screen = '' ) {
     1987                if ( $this->has_submit_button( $screen ) ) {
     1988                        return $screen;
     1989                }
     1990
     1991                return $screen . sprintf(
     1992                        '<div id="%s"><input type="submit" name="save" value="%s" id="%s"></div>',
     1993                        'bp-group-edit-' . $this->slug . '-submit-wrapper',
     1994                        $this->screens['edit']['submit_text'],
     1995                        'bp-group-edit-' . $this->slug . '-submit'
     1996                );
     1997        }
     1998
     1999        /**
     2000         * Does the given markup have a submit button?
     2001         *
     2002         * @since BuddyPress (1.8)
     2003         * @param $screen The markup to check
     2004         * @return bool
     2005         */
     2006        public static function has_submit_button( $screen = '' ) {
     2007                $pattern = "/<input[^>]+type=[\'\"]submit[\'\"]/";
     2008                preg_match( $pattern, $screen, $matches );
     2009                return ! empty( $matches[0] );
     2010        }
     2011
     2012        /** Admin *****************************************************************/
     2013
     2014        /**
     2015         * Hook this extension's Admin metabox into BuddyPress, if necessary
     2016         *
     2017         * @since BuddyPress (1.8)
     2018         */
     2019        protected function setup_admin_hooks() {
     2020                if ( ! $this->is_screen_enabled( 'admin' ) || ! is_admin() ) {
     2021                        return;
     2022                }
     2023
     2024                // Hook the admin screen markup function to the content hook
     2025                add_action( 'bp_groups_admin_meta_box_content_' . $this->slug, array( $this, 'call_admin_screen' ) );
     2026
     2027                // Initialize the metabox
     2028                add_action( 'bp_groups_admin_meta_boxes', array( $this, '_meta_box_display_callback' ) );
     2029
     2030                // Catch the metabox save
     2031                add_action( 'bp_group_admin_edit_after', array( $this, 'call_admin_screen_save' ), 10 );
     2032        }
     2033
     2034        /**
     2035         * Call the admin_screen() method, and add a nonce field
     2036         *
     2037         * @since BuddyPress (1.8)
     2038         */
     2039        public function call_admin_screen() {
     2040                call_user_func( $this->screens['admin']['screen_callback'], $this->group_id );
     2041                $this->nonce_field( 'admin' );
     2042        }
     2043
     2044        /**
     2045         * Check the nonce, and call the admin_screen_save() method
     2046         *
     2047         * @since BuddyPress (1.8)
     2048         */
     2049        public function call_admin_screen_save() {
     2050                $this->check_nonce( 'admin' );
     2051                call_user_func( $this->screens['admin']['screen_save_callback'], $this->group_id );
     2052        }
     2053
    15542054        /**
    15552055         * Create the Dashboard meta box for this extension
     
    15572057         * @since BuddyPress (1.7)
    15582058         */
    1559         function _meta_box_display_callback() {
     2059        public function _meta_box_display_callback() {
    15602060                $group_id = isset( $_GET['gid'] ) ? (int) $_GET['gid'] : 0;
     2061                $screen   = $this->screens['admin'];
    15612062
    15622063                add_meta_box(
    1563                         $this->slug,
    1564                         $this->name,
     2064                        $screen['slug'],
     2065                        $screen['name'],
    15652066                        create_function( '', 'do_action( "bp_groups_admin_meta_box_content_' . $this->slug . '", ' . $group_id . ' );' ),
    15662067                        get_current_screen()->id,
    1567                         $this->admin_metabox_context,
    1568                         $this->admin_metabox_priority
     2068                        $screen['metabox_context'],
     2069                        $screen['metabox_priority']
    15692070                );
    15702071        }
    15712072
    1572         /**
    1573          * Call the edit_screen() method
    1574          *
    1575          * Broken into a standalone method so we can pass the current group id
    1576          * to edit_screen()
    1577          *
    1578          * @since 1.8
    1579          */
    1580         public function call_edit_screen() {
    1581                 $this->edit_screen( bp_get_current_group_id() );
    1582         }
    1583 
    1584         /**
    1585          * Call the create_screen() method, if we're on the right page
    1586          *
    1587          * @since 1.8
    1588          */
    1589         public function maybe_create_screen() {
    1590                 if ( bp_is_group_creation_step( $this->slug ) ) {
    1591                         $this->create_screen( bp_get_new_group_id() );
    1592                 }
    1593         }
    1594 
    1595         /**
    1596          * Call the create_screen_save() method, if we're on the right page
    1597          *
    1598          * @since 1.8
    1599          */
    1600         public function maybe_create_screen_save() {
    1601                 if ( bp_is_group_creation_step( $this->slug ) ) {
    1602                         $this->create_screen_save( bp_get_new_group_id() );
    1603                 }
    1604         }
    1605 
     2073
     2074        /** Utilities *************************************************************/
     2075
     2076        /**
     2077         * Generate the nonce fields for a settings form
     2078         *
     2079         * The nonce field name (the second param passed to wp_nonce_field)
     2080         * contains this extension's slug and is thus unique to this extension.
     2081         * This is necessary because in some cases (namely, the Dashboard),
     2082         * more than one extension may generate nonces on the same page, and we
     2083         * must avoid name clashes.
     2084         *
     2085         * @since BuddyPress (1.8)
     2086         * @uses wp_nonce_field()
     2087         * @param string $context 'create', 'edit', 'admin'
     2088         */
     2089        public function nonce_field( $context = '' ) {
     2090                wp_nonce_field( 'bp_group_extension_' . $this->slug . '_' . $context, '_bp_group_' . $context . '_nonce_' . $this->slug );
     2091        }
     2092
     2093        /**
     2094         * Check the nonce on a submitted settings form
     2095         *
     2096         * @since BuddyPress (1.8)
     2097         * @uses check_admin_referer()
     2098         * @param string $context 'create', 'edit', 'admin'
     2099         */
     2100        public function check_nonce( $context = '' ) {
     2101                check_admin_referer( 'bp_group_extension_' . $this->slug . '_' . $context, '_bp_group_' . $context . '_nonce_' . $this->slug );
     2102        }
     2103
     2104        /**
     2105         * Is the specified screen enabled?
     2106         *
     2107         * To be enabled, a screen must both have the 'enabled' key set to true
     2108         * (legacy: $this->enable_create_step, etc), and its screen_callback
     2109         * must also exist and be callable.
     2110         *
     2111         * @since BuddyPress (1.8)
     2112         * @param string $context 'create', 'edit', 'admin'
     2113         * @return bool
     2114         */
     2115        public function is_screen_enabled( $context = '' ) {
     2116                $enabled = false;
     2117
     2118                if ( isset( $this->screens[ $context ] ) ) {
     2119                        $enabled = $this->screens[ $context ]['enabled'] && is_callable( $this->screens[ $context ]['screen_callback'] );
     2120                }
     2121
     2122                return (bool) $enabled;
     2123        }
     2124
     2125        /**
     2126         * Get the appropriate screen callback for the specified context/type
     2127         *
     2128         * BP Group Extensions have three special "screen contexts": create,
     2129         * admin, and edit. Each of these contexts has a corresponding
     2130         * _screen() and _screen_save() method, which allow group extension
     2131         * plugins to define different markup and logic for each context.
     2132         *
     2133         * BP also supports fallback settings_screen() and
     2134         * settings_screen_save() methods, which can be used to define markup
     2135         * and logic that is shared between context. For each context, you may
     2136         * either provide context-specific methods, or you can let BP fall back
     2137         * on the shared settings_* callbacks.
     2138         *
     2139         * For example, consider a BP_Group_Extension implementation that looks
     2140         * like this:
     2141         *
     2142         *   // ...
     2143         *   function create_screen( $group_id ) { ... }
     2144         *   function create_screen_save( $group_id ) { ... }
     2145         *   function settings_screen( $group_id ) { ... }
     2146         *   function settings_screen_save( $group_id ) { ... }
     2147         *   // ...
     2148         *
     2149         * BP_Group_Extension will use your create_* methods for the Create
     2150         * steps, and will use your generic settings_* methods for the Edit
     2151         * and Admin contexts. This schema allows plugin authors maximum
     2152         * flexibility without having to repeat themselves.
     2153         *
     2154         * The get_screen_callback() method uses a ReflectionClass object to
     2155         * determine whether your extension has provided a given callback.
     2156         *
     2157         * @since BuddyPress (1.8)
     2158         * @param string $context 'create', 'edit', 'admin'
     2159         * @param string $type 'screen', 'screen_save'
     2160         * @return mixed A callable function handle
     2161         */
     2162        public function get_screen_callback( $context = '', $type = 'screen' ) {
     2163                $callback = '';
     2164
     2165                // Try the context-specific callback first
     2166                $method  = $context . '_' . $type;
     2167                $rmethod = $this->class_reflection->getMethod( $method );
     2168                if ( isset( $rmethod->class ) && $this->class_name === $rmethod->class ) {
     2169                        $callback = array( $this->class_name, $method );
     2170                }
     2171
     2172                if ( empty( $callback ) ) {
     2173                        $fallback_method  = 'settings_' . $type;
     2174                        $rfallback_method = $this->class_reflection->getMethod( $fallback_method );
     2175                        if ( isset( $rfallback_method->class ) && $this->class_name === $rfallback_method->class ) {
     2176                                $callback = array( $this->class_name, $fallback_method );
     2177                        }
     2178                }
     2179
     2180                return $callback;
     2181        }
     2182
     2183        /**
     2184         * Recursive argument parsing
     2185         *
     2186         * This acts like a multi-dimensional version of wp_parse_args() (minus
     2187         * the querystring parsing - you must pass arrays).
     2188         *
     2189         * Values from $a override those from $b; keys in $b that don't exist
     2190         * in $a are passed through.
     2191         *
     2192         * This is different from array_merge_recursive(), both because of the
     2193         * order of preference ($a overrides $b) and because of the fact that
     2194         * array_merge_recursive() combines arrays deep in the tree, rather
     2195         * than overwriting the b array with the a array.
     2196         *
     2197         * The implementation of this function is specific to the needs of
     2198         * BP_Group_Extension, where we know that arrays will always be
     2199         * associative, and that an argument under a given key in one array
     2200         * will be matched by a value of identical depth in the other one. The
     2201         * function is NOT designed for general use, and will probably result
     2202         * in unexpected results when used with data in the wild. See, eg,
     2203         * http://core.trac.wordpress.org/ticket/19888
     2204         *
     2205         * @since BuddyPress (1.8)
     2206         * @arg array $a
     2207         * @arg array $b
     2208         * @return array
     2209         */
     2210        public static function parse_args_r( &$a, $b ) {
     2211                $a = (array) $a;
     2212                $b = (array) $b;
     2213                $r = $b;
     2214
     2215                foreach ( $a as $k => &$v ) {
     2216                        if ( is_array( $v ) && isset( $r[ $k ] ) ) {
     2217                                $r[ $k ] = self::parse_args_r( $v, $r[ $k ] );
     2218                        } else {
     2219                                $r[ $k ] = $v;
     2220                        }
     2221                }
     2222
     2223                return $r;
     2224        }
     2225
     2226        /** Legacy Support ********************************************************/
     2227
     2228        /**
     2229         * In BuddyPress 1.8, the recommended technique for configuring
     2230         * extensions changed from directly setting various object properties
     2231         * in the class constructor, to passing a configuration array to
     2232         * parent::init(). The following methods ensure that extensions created
     2233         * in the old way continue to work, by converting legacy configuration
     2234         * data to the new format.
     2235         */
     2236
     2237        /**
     2238         * Provide access to otherwise unavailable object properties
     2239         *
     2240         * This magic method is here for backward compatibility with plugins
     2241         * that refer to config properties that have moved to a different
     2242         * location (such as enable_create_step, which is now at
     2243         * $this->screens['create']['enabled']
     2244         *
     2245         * The legacy_properties array is set up in
     2246         * self::setup_legacy_properties().
     2247         *
     2248         * @since BuddyPress (1.8)
     2249         * @param string $key
     2250         * @return mixed
     2251         */
     2252        public function __get( $key ) {
     2253                if ( isset( $this->legacy_properties[ $key ] ) ) {
     2254                        return $this->legacy_properties[ $key ];
     2255                } elseif ( isset( $this->data[ $key ] ) ) {
     2256                        return $this->data[ $key ];
     2257                } else {
     2258                        return null;
     2259                }
     2260        }
     2261
     2262        /**
     2263         * Provide a fallback for isset( $this->foo ) when foo is unavailable
     2264         *
     2265         * This magit method is here for backward compatibility with plugins
     2266         * that have set their class config options directly in the class
     2267         * constructor. The parse_legacy_properties() method of the current
     2268         * class needs to check whether any legacy keys have been put into the
     2269         * $this->data array.
     2270         *
     2271         * @since BuddyPress (1.8)
     2272         * @param string $key
     2273         * @return bool
     2274         */
     2275        public function __isset( $key ) {
     2276                if ( isset( $this->legacy_properties[ $key ] ) ) {
     2277                        return true;
     2278                } elseif ( isset( $this->data[ $key ] ) ) {
     2279                        return true;
     2280                } else {
     2281                        return false;
     2282                }
     2283        }
     2284
     2285        /**
     2286         * Allow plugins to set otherwise unavailable object properties
     2287         *
     2288         * This magic method is here for backward compatibility with plugins
     2289         * that may attempt to modify the group extension by manually assigning
     2290         * a value to an object property that no longer exists, such as
     2291         * $this->enable_create_step.
     2292         *
     2293         * @since BuddyPress (1.8)
     2294         * @param string $key
     2295         * @param mixed $value
     2296         */
     2297        public function __set( $key, $value ) {
     2298
     2299                if ( empty( $this->initialized ) ) {
     2300                        $this->data[ $key ] = $value;
     2301                }
     2302
     2303                switch ( $key ) {
     2304                        case 'enable_create_step' :
     2305                                $this->screens['create']['enabled'] = $value;
     2306                                break;
     2307
     2308                        case 'enable_edit_item' :
     2309                                $this->screens['edit']['enabled'] = $value;
     2310                                break;
     2311
     2312                        case 'enable_admin_item' :
     2313                                $this->screens['admin']['enabled'] = $value;
     2314                                break;
     2315
     2316                        case 'create_step_position' :
     2317                                $this->screens['create']['position'] = $value;
     2318                                break;
     2319
     2320                        // Note: 'admin' becomes 'edit' to distinguish from Dashboard 'admin'
     2321                        case 'admin_name' :
     2322                                $this->screens['edit']['name'] = $value;
     2323                                break;
     2324
     2325                        case 'admin_slug' :
     2326                                $this->screens['edit']['slug'] = $value;
     2327                                break;
     2328
     2329                        case 'create_name' :
     2330                                $this->screens['create']['name'] = $value;
     2331                                break;
     2332
     2333                        case 'create_slug' :
     2334                                $this->screens['create']['slug'] = $value;
     2335                                break;
     2336
     2337                        case 'admin_metabox_context' :
     2338                                $this->screens['admin']['metabox_context'] = $value;
     2339                                break;
     2340
     2341                        case 'admin_metabox_priority' :
     2342                                $this->screens['admin']['metabox_priority'] = $value;
     2343                                break;
     2344
     2345                        default :
     2346                                $this->data[ $key ] = $value;
     2347                                break;
     2348                }
     2349        }
     2350
     2351        /**
     2352         * Returns a list of legacy properties
     2353         *
     2354         * The legacy implementation of BP_Group_Extension used all of these
     2355         * object properties for configuration. Some have been moved.
     2356         *
     2357         * @since BuddyPress (1.8)
     2358         * @return array
     2359         */
     2360        protected function get_legacy_property_list() {
     2361                return array(
     2362                        'name',
     2363                        'slug',
     2364                        'admin_name',
     2365                        'admin_slug',
     2366                        'create_name',
     2367                        'create_slug',
     2368                        'visibility',
     2369                        'create_step_position',
     2370                        'nav_item_position',
     2371                        'admin_metabox_context',
     2372                        'admin_metabox_priority',
     2373                        'enable_create_step',
     2374                        'enable_nav_item',
     2375                        'enable_edit_item',
     2376                        'enable_admin_item',
     2377                        'nav_item_name',
     2378                        'display_hook',
     2379                        'template_file',
     2380                );
     2381        }
     2382
     2383        /**
     2384         * Parse legacy properties
     2385         *
     2386         * The old standard for BP_Group_Extension was for plugins to register
     2387         * their settings as properties in their constructor. The new method is
     2388         * to pass a config array to the init() method. In order to support
     2389         * legacy plugins, we slurp up legacy properties, and later on we'll
     2390         * parse them into the new init() array.
     2391         *
     2392         * @since BuddyPress (1.8)
     2393         */
     2394        protected function parse_legacy_properties() {
     2395
     2396                // Only run this one time
     2397                if ( ! empty( $this->legacy_properties_converted ) ) {
     2398                        return;
     2399                }
     2400
     2401                $properties = $this->get_legacy_property_list();
     2402
     2403                // By-reference variable for convenience
     2404                $lpc =& $this->legacy_properties_converted;
     2405
     2406                foreach ( $properties as $property ) {
     2407
     2408                        // No legacy config exists for this key
     2409                        if ( ! isset( $this->{$property} ) ) {
     2410                                continue;
     2411                        }
     2412
     2413                        // Grab the value and record it as appropriate
     2414                        $value = $this->{$property};
     2415
     2416                        switch ( $property ) {
     2417                                case 'enable_create_step' :
     2418                                        $lpc['screens']['create']['enabled'] = (bool) $value;
     2419                                        break;
     2420
     2421                                case 'enable_edit_item' :
     2422                                        $lpc['screens']['edit']['enabled'] = (bool) $value;
     2423                                        break;
     2424
     2425                                case 'enable_admin_item' :
     2426                                        $lpc['screens']['admin']['enabled'] = (bool) $value;
     2427                                        break;
     2428
     2429                                case 'create_step_position' :
     2430                                        $lpc['screens']['create']['position'] = $value;
     2431                                        break;
     2432
     2433                                // Note: 'admin' becomes 'edit' to distinguish from Dashboard 'admin'
     2434                                case 'admin_name' :
     2435                                        $lpc['screens']['edit']['name'] = $value;
     2436                                        break;
     2437
     2438                                case 'admin_slug' :
     2439                                        $lpc['screens']['edit']['slug'] = $value;
     2440                                        break;
     2441
     2442                                case 'create_name' :
     2443                                        $lpc['screens']['create']['name'] = $value;
     2444                                        break;
     2445
     2446                                case 'create_slug' :
     2447                                        $lpc['screens']['create']['slug'] = $value;
     2448                                        break;
     2449
     2450                                case 'admin_metabox_context' :
     2451                                        $lpc['screens']['admin']['metabox_context'] = $value;
     2452                                        break;
     2453
     2454                                case 'admin_metabox_priority' :
     2455                                        $lpc['screens']['admin']['metabox_priority'] = $value;
     2456                                        break;
     2457
     2458                                default :
     2459                                        $lpc[ $property ] = $value;
     2460                                        break;
     2461                        }
     2462                }
     2463        }
     2464
     2465        /**
     2466         * Set up legacy properties
     2467         *
     2468         * This method is responsible for ensuring that all legacy config
     2469         * properties are stored in an array $this->legacy_properties, so that
     2470         * they remain available to plugins that reference the variables at
     2471         * their old locations.
     2472         *
     2473         * @see self::__get()
     2474         *
     2475         * @since BuddyPress (1.8)
     2476         */
     2477        protected function setup_legacy_properties() {
     2478
     2479                // Only run this one time
     2480                if ( ! empty( $this->legacy_properties ) ) {
     2481                        return;
     2482                }
     2483
     2484                $properties = $this->get_legacy_property_list();
     2485                $params     = $this->params;
     2486                $lp         =& $this->legacy_properties;
     2487
     2488                foreach ( $properties as $property ) {
     2489                        switch ( $property ) {
     2490                                case 'enable_create_step' :
     2491                                        $lp['enable_create_step'] = $params['screens']['create']['enabled'];
     2492                                        break;
     2493
     2494                                case 'enable_edit_item' :
     2495                                        $lp['enable_edit_item'] = $params['screens']['edit']['enabled'];
     2496                                        break;
     2497
     2498                                case 'enable_admin_item' :
     2499                                        $lp['enable_admin_item'] = $params['screens']['admin']['enabled'];
     2500                                        break;
     2501
     2502                                case 'create_step_position' :
     2503                                        $lp['create_step_position'] = $params['screens']['create']['position'];
     2504                                        break;
     2505
     2506                                // Note: 'admin' becomes 'edit' to distinguish from Dashboard 'admin'
     2507                                case 'admin_name' :
     2508                                        $lp['admin_name'] = $params['screens']['edit']['name'];
     2509                                        break;
     2510
     2511                                case 'admin_slug' :
     2512                                        $lp['admin_slug'] = $params['screens']['edit']['slug'];
     2513                                        break;
     2514
     2515                                case 'create_name' :
     2516                                        $lp['create_name'] = $params['screens']['create']['name'];
     2517                                        break;
     2518
     2519                                case 'create_slug' :
     2520                                        $lp['create_slug'] = $params['screens']['create']['slug'];
     2521                                        break;
     2522
     2523                                case 'admin_metabox_context' :
     2524                                        $lp['admin_metabox_context'] = $params['screens']['admin']['metabox_context'];
     2525                                        break;
     2526
     2527                                case 'admin_metabox_priority' :
     2528                                        $lp['admin_metabox_priority'] = $params['screens']['admin']['metabox_priority'];
     2529                                        break;
     2530
     2531                                default :
     2532                                        // All other items get moved over
     2533                                        $lp[ $property ] = $params[ $property ];
     2534
     2535                                        // Also reapply to the object, for backpat
     2536                                        $this->{$property} = $params[ $property ];
     2537
     2538                                        break;
     2539                        }
     2540                }
     2541        }
    16062542}
    16072543
    1608 function bp_register_group_extension( $group_extension_class ) {
    1609 
    1610         if ( !class_exists( $group_extension_class ) )
     2544function bp_register_group_extension( $group_extension_class = '' ) {
     2545
     2546        if ( ! class_exists( $group_extension_class ) ) {
    16112547                return false;
     2548        }
    16122549
    16132550        // Register the group extension on the bp_init action so we have access
  • trunk/tests/bootstrap.php

    r6908 r6997  
    33define( 'BP_PLUGIN_DIR', dirname( dirname( __FILE__ ) ) . '/' );
    44
     5if ( ! defined( 'BP_TESTS_DIR' ) ) {
     6        define( 'BP_TESTS_DIR', dirname( __FILE__ ) . '/' );
     7}
     8
    59require_once getenv( 'WP_TESTS_DIR' ) . '/includes/functions.php';
    610
    711function _install_and_load_buddypress() {
    8         require dirname( __FILE__ ) . '/includes/loader.php';
     12        require BP_TESTS_DIR . '/includes/loader.php';
    913}
    1014tests_add_filter( 'muplugins_loaded', '_install_and_load_buddypress' );
     
    1317
    1418// Load the BP-specific testing tools
    15 require dirname( __FILE__ ) . '/includes/testcase.php';
     19require BP_TESTS_DIR . '/includes/testcase.php';
Note: See TracChangeset for help on using the changeset viewer.