diff --git a/composer.json b/composer.json
index b04a148f..da44fd4a 100644
--- a/composer.json
+++ b/composer.json
@@ -23,6 +23,7 @@
"wp-coding-standards/wpcs": "^2.2",
"wp-phpunit/wp-phpunit": "^5.4",
"wpackagist-plugin/advanced-custom-fields": "5.8.12",
+ "wpackagist-plugin/buddypress": "^6.1.0",
"wpackagist-plugin/easy-digital-downloads": "^2.9.23",
"wpackagist-plugin/user-switching": "^1.5.5",
"wpsh/local": "^0.2.3"
diff --git a/composer.lock b/composer.lock
index 03b357a7..f9baef74 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "c025a44ff83e162076363f15803df9da",
+ "content-hash": "085543ec02907c7524270a6df052760b",
"packages": [
{
"name": "composer/installers",
- "version": "v1.9.0",
+ "version": "v1.10.0",
"source": {
"type": "git",
"url": "https://github.com/composer/installers.git",
- "reference": "b93bcf0fa1fccb0b7d176b0967d969691cd74cca"
+ "reference": "1a0357fccad9d1cc1ea0c9a05b8847fbccccb78d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/installers/zipball/b93bcf0fa1fccb0b7d176b0967d969691cd74cca",
- "reference": "b93bcf0fa1fccb0b7d176b0967d969691cd74cca",
+ "url": "https://api.github.com/repos/composer/installers/zipball/1a0357fccad9d1cc1ea0c9a05b8847fbccccb78d",
+ "reference": "1a0357fccad9d1cc1ea0c9a05b8847fbccccb78d",
"shasum": ""
},
"require": {
@@ -28,17 +28,18 @@
"shama/baton": "*"
},
"require-dev": {
- "composer/composer": "1.6.* || 2.0.*@dev",
- "composer/semver": "1.0.* || 2.0.*@dev",
- "phpunit/phpunit": "^4.8.36",
- "sebastian/comparator": "^1.2.4",
+ "composer/composer": "1.6.* || ^2.0",
+ "composer/semver": "^1 || ^3",
+ "phpstan/phpstan": "^0.12.55",
+ "phpstan/phpstan-phpunit": "^0.12.16",
+ "symfony/phpunit-bridge": "^4.2 || ^5",
"symfony/process": "^2.3"
},
"type": "composer-plugin",
"extra": {
"class": "Composer\\Installers\\Plugin",
"branch-alias": {
- "dev-master": "1.0-dev"
+ "dev-main": "1.x-dev"
}
},
"autoload": {
@@ -76,6 +77,7 @@
"Porto",
"RadPHP",
"SMF",
+ "Starbug",
"Thelia",
"Whmcs",
"WolfCMS",
@@ -116,6 +118,7 @@
"phpbb",
"piwik",
"ppi",
+ "processwire",
"puppet",
"pxcms",
"reindex",
@@ -133,19 +136,23 @@
],
"support": {
"issues": "https://github.com/composer/installers/issues",
- "source": "https://github.com/composer/installers/tree/v1.9.0"
+ "source": "https://github.com/composer/installers/tree/v1.10.0"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
- "time": "2020-04-07T06:57:05+00:00"
+ "time": "2021-01-14T11:07:16+00:00"
}
],
"packages-dev": [
@@ -279,16 +286,16 @@
},
{
"name": "composer/composer",
- "version": "1.10.19",
+ "version": "1.10.20",
"source": {
"type": "git",
"url": "https://github.com/composer/composer.git",
- "reference": "196601d50c08c3fae389a417a7689367fcf37cef"
+ "reference": "e55d297525f0ecc805c813a0f63a40114fd670f6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/composer/zipball/196601d50c08c3fae389a417a7689367fcf37cef",
- "reference": "196601d50c08c3fae389a417a7689367fcf37cef",
+ "url": "https://api.github.com/repos/composer/composer/zipball/e55d297525f0ecc805c813a0f63a40114fd670f6",
+ "reference": "e55d297525f0ecc805c813a0f63a40114fd670f6",
"shasum": ""
},
"require": {
@@ -358,7 +365,7 @@
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/composer/issues",
- "source": "https://github.com/composer/composer/tree/1.10.19"
+ "source": "https://github.com/composer/composer/tree/1.10.20"
},
"funding": [
{
@@ -374,7 +381,7 @@
"type": "tidelift"
}
],
- "time": "2020-12-04T08:14:16+00:00"
+ "time": "2021-01-27T14:41:06+00:00"
},
{
"name": "composer/semver",
@@ -1079,20 +1086,20 @@
},
{
"name": "johnpbloch/wordpress",
- "version": "5.6.0",
+ "version": "5.6.1",
"source": {
"type": "git",
"url": "https://github.com/johnpbloch/wordpress.git",
- "reference": "3055975734646c8d0b8caf7b5af168ced6ec4309"
+ "reference": "d7a597988102967cdfc28851b6b897d018613823"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/johnpbloch/wordpress/zipball/3055975734646c8d0b8caf7b5af168ced6ec4309",
- "reference": "3055975734646c8d0b8caf7b5af168ced6ec4309",
+ "url": "https://api.github.com/repos/johnpbloch/wordpress/zipball/d7a597988102967cdfc28851b6b897d018613823",
+ "reference": "d7a597988102967cdfc28851b6b897d018613823",
"shasum": ""
},
"require": {
- "johnpbloch/wordpress-core": "5.6.0",
+ "johnpbloch/wordpress-core": "5.6.1",
"johnpbloch/wordpress-core-installer": "^1.0 || ^2.0",
"php": ">=5.6.20"
},
@@ -1121,20 +1128,20 @@
"source": "http://core.trac.wordpress.org/browser",
"wiki": "http://codex.wordpress.org/"
},
- "time": "2020-12-08T22:34:35+00:00"
+ "time": "2021-02-03T21:27:41+00:00"
},
{
"name": "johnpbloch/wordpress-core",
- "version": "5.6.0",
+ "version": "5.6.1",
"source": {
"type": "git",
"url": "https://github.com/johnpbloch/wordpress-core.git",
- "reference": "f074617dd69f466302836d1ae5de75c0bd7b6dfd"
+ "reference": "82592ec73d42cf784da38adb0028a24dbacab1b4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/johnpbloch/wordpress-core/zipball/f074617dd69f466302836d1ae5de75c0bd7b6dfd",
- "reference": "f074617dd69f466302836d1ae5de75c0bd7b6dfd",
+ "url": "https://api.github.com/repos/johnpbloch/wordpress-core/zipball/82592ec73d42cf784da38adb0028a24dbacab1b4",
+ "reference": "82592ec73d42cf784da38adb0028a24dbacab1b4",
"shasum": ""
},
"require": {
@@ -1142,7 +1149,7 @@
"php": ">=5.6.20"
},
"provide": {
- "wordpress/core-implementation": "5.6.0"
+ "wordpress/core-implementation": "5.6.1"
},
"type": "wordpress-core",
"notification-url": "https://packagist.org/downloads/",
@@ -1169,7 +1176,7 @@
"source": "https://core.trac.wordpress.org/browser",
"wiki": "https://codex.wordpress.org/"
},
- "time": "2020-12-08T22:34:23+00:00"
+ "time": "2021-02-03T21:27:35+00:00"
},
{
"name": "johnpbloch/wordpress-core-installer",
@@ -3145,16 +3152,16 @@
},
{
"name": "sirbrillig/phpcs-variable-analysis",
- "version": "v2.10.1",
+ "version": "v2.10.2",
"source": {
"type": "git",
"url": "https://github.com/sirbrillig/phpcs-variable-analysis.git",
- "reference": "c6716a98fe7bee25d31306e14fb62c3ffa16d70a"
+ "reference": "0775e0c683badad52c03b11c2cd86a9fdecb937a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/c6716a98fe7bee25d31306e14fb62c3ffa16d70a",
- "reference": "c6716a98fe7bee25d31306e14fb62c3ffa16d70a",
+ "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/0775e0c683badad52c03b11c2cd86a9fdecb937a",
+ "reference": "0775e0c683badad52c03b11c2cd86a9fdecb937a",
"shasum": ""
},
"require": {
@@ -3194,7 +3201,7 @@
"source": "https://github.com/sirbrillig/phpcs-variable-analysis",
"wiki": "https://github.com/sirbrillig/phpcs-variable-analysis/wiki"
},
- "time": "2020-12-12T18:28:57+00:00"
+ "time": "2021-01-08T16:31:05+00:00"
},
{
"name": "squizlabs/php_codesniffer",
@@ -4288,12 +4295,12 @@
"version": "1.9.1",
"source": {
"type": "git",
- "url": "https://github.com/webmozart/assert.git",
+ "url": "https://github.com/webmozarts/assert.git",
"reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389",
+ "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389",
"reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389",
"shasum": ""
},
@@ -4331,8 +4338,8 @@
"validate"
],
"support": {
- "issues": "https://github.com/webmozart/assert/issues",
- "source": "https://github.com/webmozart/assert/tree/master"
+ "issues": "https://github.com/webmozarts/assert/issues",
+ "source": "https://github.com/webmozarts/assert/tree/1.9.1"
},
"time": "2020-07-08T17:02:28+00:00"
},
@@ -6476,16 +6483,16 @@
},
{
"name": "wp-phpunit/wp-phpunit",
- "version": "5.6.0",
+ "version": "5.6.1",
"source": {
"type": "git",
"url": "https://github.com/wp-phpunit/wp-phpunit.git",
- "reference": "7130a214573cc8c12a0f8fe8a74b18b453bce1e9"
+ "reference": "f6b3fb65bccc0ff70b3bc7cc241935597dbd5562"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/7130a214573cc8c12a0f8fe8a74b18b453bce1e9",
- "reference": "7130a214573cc8c12a0f8fe8a74b18b453bce1e9",
+ "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/f6b3fb65bccc0ff70b3bc7cc241935597dbd5562",
+ "reference": "f6b3fb65bccc0ff70b3bc7cc241935597dbd5562",
"shasum": ""
},
"type": "library",
@@ -6520,7 +6527,7 @@
"issues": "https://github.com/wp-phpunit/issues",
"source": "https://github.com/wp-phpunit/wp-phpunit"
},
- "time": "2020-12-09T18:06:02+00:00"
+ "time": "2021-02-04T18:24:14+00:00"
},
{
"name": "wpackagist-plugin/advanced-custom-fields",
@@ -6540,6 +6547,24 @@
"type": "wordpress-plugin",
"homepage": "https://wordpress.org/plugins/advanced-custom-fields/"
},
+ {
+ "name": "wpackagist-plugin/buddypress",
+ "version": "6.4.0",
+ "source": {
+ "type": "svn",
+ "url": "https://plugins.svn.wordpress.org/buddypress/",
+ "reference": "tags/6.4.0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://downloads.wordpress.org/plugin/buddypress.6.4.0.zip"
+ },
+ "require": {
+ "composer/installers": "~1.0"
+ },
+ "type": "wordpress-plugin",
+ "homepage": "https://wordpress.org/plugins/buddypress/"
+ },
{
"name": "wpackagist-plugin/easy-digital-downloads",
"version": "2.9.26",
diff --git a/connectors/class-connector-buddypress.php b/connectors/class-connector-buddypress.php
index 3bcecd9c..7c11cb9b 100644
--- a/connectors/class-connector-buddypress.php
+++ b/connectors/class-connector-buddypress.php
@@ -61,9 +61,11 @@ class Connector_BuddyPress extends Connector {
'groups_unban_member',
'groups_remove_member',
+ 'xprofile_field_before_save',
'xprofile_field_after_save',
'xprofile_fields_deleted_field',
+ 'xprofile_group_before_save',
'xprofile_group_after_save',
'xprofile_groups_deleted_group',
);
@@ -427,6 +429,8 @@ public function check( $option, $old_value, $new_value ) {
$replacement = str_replace( '-', '_', $option );
if ( method_exists( $this, 'check_' . $replacement ) ) {
+ $method = "check_{$replacement}";
+ $this->{$method}( $old_value, $new_value );
call_user_func(
array(
$this,
@@ -581,7 +585,7 @@ public function callback_bp_before_activity_delete( $args ) {
* @param array $activities_ids Activity IDs of deleted activities.
*/
public function callback_bp_activity_deleted_activities( $activities_ids ) {
- if ( 1 === count( $activities_ids ) && isset( $this->deleted_activity ) ) { // Single activity deletion.
+ if ( 1 === count( $activities_ids ) && ! empty( $this->deleted_activity ) ) { // Single activity deletion.
$activity = $this->deleted_activity;
$this->log(
sprintf(
@@ -747,11 +751,13 @@ public function group_action( $group, $action, $meta = array(), $message = null
/* translators: %s: a group name (e.g. "Favourites") */
$message = esc_html__( '"%s" group deleted', 'stream' );
} elseif ( 'joined' === $action ) {
- /* translators: %s: a group name (e.g. "Favourites") */
- $message = esc_html__( 'Joined group "%s"', 'stream' );
+ /* translators: %2$s: a user display name, %1$s: a group name (e.g. "Jane Doe", "Favourites") */
+ $message = esc_html__( '"%2$s" joined group "%1$s"', 'stream' );
+ $replacements[] = get_user_by( 'id', $meta['user_id'] )->display_name;
} elseif ( 'left' === $action ) {
- /* translators: %s: a group name (e.g. "Favourites") */
- $message = esc_html__( 'Left group "%s"', 'stream' );
+ /* translators: %2$s: a user display name, %1$s: a group name (e.g. "Jane Doe", "Favourites") */
+ $message = esc_html__( '"%2$s" left group "%1$s"', 'stream' );
+ $replacements[] = get_user_by( 'id', $meta['user_id'] )->display_name;
} elseif ( 'banned' === $action ) {
/* translators: %1$s: a user display name, %2$s: a group name (e.g. "Jane Doe", "Favourites") */
$message = esc_html__( 'Banned "%2$s" from "%1$s"', 'stream' );
@@ -1018,15 +1024,34 @@ public function field_action( $field, $action, $meta = array(), $message = null
);
}
+ /**
+ * Capture field status before create/updating field so it can
+ * be logged in the "after_save" callback.
+ *
+ * @action xprofile_field_before_save
+ *
+ * @param BP_XProfile_Field $field Field object.
+ */
+ public function callback_xprofile_field_before_save( $field ) {
+ $this->incoming_field_action = empty( $field->id ) ? 'created' : 'updated';
+ }
+
/**
* Logs field writes
*
* @action xprofile_field_after_save
*
- * @param object $field Field object.
+ * @param BP_XProfile_Field $field Field object.
*/
public function callback_xprofile_field_after_save( $field ) {
- $action = isset( $field->id ) ? 'updated' : 'created';
+ // Bail if the field's action wasn't captured.
+ if ( is_null( $this->incoming_field_action ) ) {
+ return;
+ }
+
+ $action = $this->incoming_field_action;
+ unset( $this->incomming_field_action );
+
$this->field_action( $field, $action );
}
@@ -1087,6 +1112,19 @@ public function field_group_action( $group, $action, $meta = array(), $message =
);
}
+ /**
+ * Capture field group status before create/updating field so it can
+ * be logged in the "after_save" callback.
+ *
+ * @action xprofile_group_before_save
+ *
+ * @param BP_XProfile_Group $group Field group object.
+ */
+ public function callback_xprofile_group_before_save( $group ) {
+ $this->incoming_field_group_action = empty( $group->id ) ? 'created' : 'updated';
+ }
+
+
/**
* Logs field group writes
*
@@ -1095,12 +1133,14 @@ public function field_group_action( $group, $action, $meta = array(), $message =
* @param object $group Field group.
*/
public function callback_xprofile_group_after_save( $group ) {
- global $wpdb;
- /**
- * A bit hacky, due to inconsistency with BP action scheme,
- * see callback_xprofile_field_after_save for correct behavior.
- */
- $action = ( $group->id === $wpdb->insert_id ) ? 'created' : 'updated';
+ // Bail if the field group's action wasn't captured.
+ if ( is_null( $this->incoming_field_group_action ) ) {
+ return;
+ }
+
+ $action = $this->incoming_field_group_action;
+ unset( $this->incomming_field_group_action );
+
$this->field_group_action( $group, $action );
}
diff --git a/phpunit.xml b/phpunit.xml
index af2b1c44..f217da25 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -10,7 +10,7 @@
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 3c911062..d6fe7c35 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -78,6 +78,29 @@ function( $status = false, $args = array(), $url = '') {
}
);
}
+tests_add_filter(
+ 'bp_core_loaded',
+ function() {
+ $components = array(
+ 'members',
+ 'activity',
+ 'blogs',
+ 'friends',
+ 'groups',
+ 'messages',
+ 'notifications',
+ 'settings',
+ 'xprofile',
+ );
+ $active_components =& buddypress()->active_components;
+ foreach( $components as $component ) {
+ $active_components[ $component ] = 1;
+ }
+
+ \bp_delete_option( 'bp-active-components');
+ \bp_delete_option( 'bp-deactivated-components' );
+ }
+);
// @see https://core.trac.wordpress.org/browser/trunk/tests/phpunit/includes/bootstrap.php
require $_tests_dir . '/includes/bootstrap.php';
diff --git a/tests/tests/connectors/test-class-connector-buddypress.php b/tests/tests/connectors/test-class-connector-buddypress.php
new file mode 100644
index 00000000..2325e65d
--- /dev/null
+++ b/tests/tests/connectors/test-class-connector-buddypress.php
@@ -0,0 +1,699 @@
+delete( (bool) $delete_data ) ) {
+ /* translators: %s: the field type */
+ $message = sprintf( __( 'There was an error deleting the %s. Please try again.', 'buddypress' ), $field_type );
+ $type = 'error';
+
+ return false;
+ } else {
+ /* translators: %s: the field type */
+ $message = sprintf( __( 'The %s was deleted successfully!', 'buddypress' ), $field_type );
+ $type = 'success';
+
+ /**
+ * Fires at the end of the field deletion process, if successful.
+ *
+ * @since 1.0.0
+ *
+ * @param \BP_XProfile_Field $field Current BP_XProfile_Field object.
+ */
+ do_action( 'xprofile_fields_deleted_field', $field );
+
+ return true;
+ }
+}
+
+/**
+ * Handles the deletion of profile data groups.
+ *
+ * @param int $group_id ID of the group to delete.
+ */
+function xprofile_admin_delete_group( $group_id ) {
+ global $message, $type;
+
+ // Handle the deletion of group.
+ $group = new \BP_XProfile_Group( $group_id );
+
+ if ( ! $group->delete() ) {
+ $message = _x( 'There was an error deleting the group. Please try again.', 'Error when deleting profile fields group', 'buddypress' );
+ $type = 'error';
+
+ return false;
+ } else {
+ $message = _x( 'The group was deleted successfully.', 'Profile fields group was deleted successfully', 'buddypress' );
+ $type = 'success';
+
+ /**
+ * Fires at the end of group deletion process, if successful.
+ *
+ * @since 1.0.0
+ *
+ * @param \BP_XProfile_Group $group Current BP_XProfile_Group object.
+ */
+ do_action( 'xprofile_groups_deleted_group', $group );
+
+ return true;
+ }
+}
+
+class Test_WP_Stream_Connector_BuddyPress extends WP_StreamTestCase {
+ /**
+ * Run before each test
+ */
+ public function setUp() {
+ parent::setUp();
+
+ // Make partial of Connector_BuddyPress class, with mocked "log" function.
+ $this->mock = $this->getMockBuilder( Connector_BuddyPress::class )
+ ->setMethods( array( 'log' ) )
+ ->getMock();
+
+ $this->mock->register();
+ update_option( 'users_can_register', true );
+ }
+
+ /**
+ * Run after each test
+ */
+ public function tearDown() {
+ parent::tearDown();
+ }
+
+ public function test_buddypress_installed_and_activated() {
+ $this->assertTrue( is_callable( 'buddypress' ) );
+ }
+
+ public function test_option_callbacks() {
+ // Expected log actions.
+ $this->mock->expects( $this->atLeastOnce() )
+ ->method( 'log' )
+ ->withConsecutive(
+ array(
+ /* translators: %s: setting name (e.g. "Group Creation") */
+ $this->equalTo( _( '"%s" setting updated', 'stream' ) ),
+ $this->equalTo(
+ array(
+ 'option_title' => esc_html_x( 'Group Creation', 'buddypress', 'stream' ),
+ 'option' => 'bp_restrict_group_creation',
+ 'old_value' => null,
+ 'new_value' => false,
+ 'page' => 'bp-settings',
+ )
+ ),
+ $this->equalTo( null ),
+ $this->equalTo( 'settings' ),
+ $this->equalTo( 'updated' )
+ ),
+ array(
+ /* translators: %s: setting name (e.g. "Group Creation") */
+ $this->equalTo( _( '"%s" setting updated', 'stream' ) ),
+ $this->equalTo(
+ array(
+ 'option_title' => esc_html_x( 'Group Creation', 'buddypress', 'stream' ),
+ 'option' => 'bp_restrict_group_creation',
+ 'old_value' => false,
+ 'new_value' => true,
+ 'page' => 'bp-settings',
+ )
+ ),
+ $this->equalTo( null ),
+ $this->equalTo( 'settings' ),
+ $this->equalTo( 'updated' )
+ ),
+ array(
+ /* translators: %s: setting name (e.g. "Group Creation") */
+ $this->equalTo( _( '"%s" setting updated', 'stream' ) ),
+ $this->equalTo(
+ array(
+ 'option_title' => esc_html_x( 'Group Creation', 'buddypress', 'stream' ),
+ 'option' => 'bp_restrict_group_creation',
+ 'old_value' => null,
+ 'new_value' => null,
+ 'page' => 'bp-settings',
+ )
+ ),
+ $this->equalTo( null ),
+ $this->equalTo( 'settings' ),
+ $this->equalTo( 'updated' )
+ ),
+ array(
+ $this->equalTo(
+ sprintf(
+ // translators: Placeholder refers to component title (e.g. "Members")
+ __( '"%1$s" component %2$s', 'stream' ),
+ 'Extended Profiles',
+ 'activated'
+ )
+ ),
+ $this->equalTo(
+ array(
+ 'option' => 'xprofile',
+ 'option_key' => 'bp-active-components',
+ 'old_value' => null,
+ 'value' => array(
+ 'title' => __( 'Extended Profiles', 'buddypress' ),
+ 'description' => __( 'Customize your community with fully editable profile fields that allow your users to describe themselves.', 'buddypress' )
+ ),
+ )
+ ),
+
+ $this->equalTo( null ),
+ $this->equalTo( 'components' ),
+ $this->equalTo( 'activated' ),
+ )
+ );
+
+ // Modify BuddyPress-related options to trigger callbacks.
+ add_option( 'bp_restrict_group_creation', false );
+ update_option( 'bp_restrict_group_creation', true );
+ delete_option( 'bp_restrict_group_creation' );
+
+ bp_update_option( 'bp-active-components', bp_core_get_components( 'all' ) );
+
+ // Check callback test actions.
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_add_option' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_update_option' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_delete_option' ) );
+ }
+
+ public function test_activity_callbacks() {
+ $activity_args = array(
+ 'component' => \buddypress()->activity->id,
+ 'content' => 'Testing testing 123',
+ 'primary_link' => 'http://example.com',
+ 'type' => 'activity_update',
+ 'recorded_time' => \bp_core_current_time(),
+ );
+
+ // Create activity for later use.
+ $activity = new \BP_Activity_Activity( \bp_activity_add( $activity_args ) );
+
+ // Expected log actions.
+ $this->mock->expects( $this->exactly( 3 ) )
+ ->method( 'log' )
+ ->withConsecutive(
+ array(
+ $this->equalTo(
+ sprintf(
+ /* translators: %s an activity title (e.g. "Update") */
+ __( 'Marked activity "%s" as spam', 'stream' ),
+ wp_strip_all_tags( $activity->action )
+ )
+ ),
+ $this->equalTo(
+ array(
+ 'id' => $activity->id,
+ 'item_id' => $activity->item_id,
+ 'type' => $activity->type,
+ 'author' => $activity->user_id,
+ )
+ ),
+ $this->equalTo( $activity->id ),
+ $this->equalTo( $activity->component ),
+ $this->equalTo( 'spammed' ),
+ ),
+ array(
+ $this->equalTo(
+ sprintf(
+ /* translators: %s: an activity title (e.g. "Update") */
+ __( 'Unmarked activity "%s" as spam', 'stream' ),
+ wp_strip_all_tags( $activity->action )
+ )
+ ),
+ $this->equalTo(
+ array(
+ 'id' => $activity->id,
+ 'item_id' => $activity->item_id,
+ 'type' => $activity->type,
+ 'author' => $activity->user_id,
+ )
+ ),
+ $this->equalTo( $activity->id ),
+ $this->equalTo( $activity->component ),
+ $this->equalTo( 'unspammed' ),
+ ),
+ array(
+ $this->equalTo(
+ sprintf(
+ /* translators: %s: an activity title (e.g. "Update") */
+ __( '"%s" activity deleted', 'stream' ),
+ wp_strip_all_tags( $activity->action )
+ )
+ ),
+ $this->equalTo(
+ array(
+ 'id' => $activity->id,
+ 'item_id' => $activity->item_id,
+ 'type' => $activity->type,
+ 'author' => $activity->user_id,
+ )
+ ),
+ $this->equalTo( $activity->id ),
+ $this->equalTo( $activity->component ),
+ $this->equalTo( 'deleted' ),
+ )
+ );
+
+ // Update activity to trigger callbacks.
+ \bp_activity_mark_as_spam( $activity );
+ \bp_activity_mark_as_ham( $activity );
+ \bp_activity_delete_by_activity_id( $activity->id );
+
+ // Check callback test actions.
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_bp_activity_mark_as_spam' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_bp_activity_mark_as_ham' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_bp_before_activity_delete' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_bp_activity_deleted_activities' ) );
+ }
+
+ public function test_group_action_callbacks() {
+ // Authenticate as admin and re-evaluate user access.
+ wp_set_current_user( 1 );
+ bp_update_is_item_admin( bp_user_has_access(), 'core' );
+
+ // Create users for later use.
+ $test_user_id = self::factory()->user->create( array( 'display_name' => 'testuser' ) );
+
+ // Expected log actions.
+ $this->mock->expects( $this->exactly( 13 ) )
+ ->method( 'log' )
+ ->withConsecutive(
+ array(
+ $this->equalTo( esc_html__( '"Test group" group created' ) ),
+ $this->callback(
+ function( $subject ) {
+ $expected = array(
+ 'name' => 'Test group',
+ 'slug' => 'test-group'
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'created'
+ ),
+ array(
+ $this->equalTo( esc_html__( '"Old test group" group updated' ) ),
+ $this->callback(
+ function( $subject ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'test-group'
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'updated'
+ ),
+ array(
+ $this->equalTo( esc_html__( '"Old test group" group updated' ) ),
+ $this->callback(
+ function( $subject ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'old-test-group'
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'updated'
+ ),
+ array(
+ $this->equalTo( esc_html__( '"Old test group" group updated' ) ),
+ $this->callback(
+ function( $subject ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'old-test-group'
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'updated'
+ ),
+ array(
+ $this->equalTo( esc_html__( '"testuser" joined group "Old test group"' ) ),
+ $this->callback(
+ function( $subject ) use ( $test_user_id ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'old-test-group',
+ 'user_id' => $test_user_id,
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'joined'
+ ),
+ array(
+ $this->equalTo( __( 'Promoted "testuser" to "Moderator" in "Old test group"' ) ),
+ $this->callback(
+ function( $subject ) use ( $test_user_id ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'old-test-group',
+ 'user_id' => $test_user_id,
+ 'status' => 'mod',
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'promoted'
+ ),
+ array(
+ $this->equalTo( __( 'Demoted "testuser" to "Member" in "Old test group"' ) ),
+ $this->callback(
+ function( $subject ) use ( $test_user_id ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'old-test-group',
+ 'user_id' => $test_user_id,
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'demoted'
+ ),
+ array(
+ $this->equalTo( esc_html__( 'Banned "testuser" from "Old test group"' ) ),
+ $this->callback(
+ function( $subject ) use ( $test_user_id ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'old-test-group',
+ 'user_id' => $test_user_id,
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'banned'
+ ),
+ array(
+ $this->equalTo( esc_html__( 'Unbanned "testuser" from "Old test group"' ) ),
+ $this->callback(
+ function( $subject ) use ( $test_user_id ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'old-test-group',
+ 'user_id' => $test_user_id,
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'unbanned'
+ ),
+ array(
+ $this->equalTo( esc_html__( '"testuser" left group "Old test group"' ) ),
+ $this->callback(
+ function( $subject ) use ( $test_user_id ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'old-test-group',
+ 'user_id' => $test_user_id,
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'left'
+ ),
+ array(
+ $this->equalTo( esc_html__( '"testuser" joined group "Old test group"' ) ),
+ $this->callback(
+ function( $subject ) use ( $test_user_id ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'old-test-group',
+ 'user_id' => $test_user_id,
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'joined'
+ ),
+ array(
+ $this->equalTo( esc_html__( 'Removed "testuser" from "Old test group"' ) ),
+ $this->callback(
+ function( $subject ) use ( $test_user_id ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'old-test-group',
+ 'user_id' => $test_user_id,
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'removed'
+ ),
+ array(
+ $this->equalTo( esc_html__( '"Old test group" group deleted' ) ),
+ $this->callback(
+ function( $subject ) {
+ $expected = array(
+ 'name' => 'Old test group',
+ 'slug' => 'old-test-group',
+ );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'groups',
+ 'deleted'
+ )
+ );
+
+ // Create and manipulate Groups to trigger callbacks.
+ $group_args = array(
+ 'creator_id' => 1,
+ 'name' => 'Test group',
+ 'description' => 'Lorem ipsum dolor',
+ 'slug' => 'test-group',
+ 'status' => 'public',
+ );
+ $group_id = \groups_create_group( $group_args );
+
+ \groups_create_group(
+ array(
+ 'group_id' => $group_id,
+ 'name' => 'Old test group',
+ )
+ );
+
+ \groups_edit_base_group_details(
+ array(
+ 'group_id' => $group_id,
+ 'slug' => 'old-test-group',
+ 'description' => 'Lorem ipsum dolor two',
+ )
+ );
+
+ // Manually reset duplicate log blocker flag
+ $this->mock->is_update = false;
+
+ \groups_edit_group_settings( $group_id, false, 'public' );
+
+ \groups_join_group( $group_id, $test_user_id );
+ \groups_promote_member( $test_user_id, $group_id, 'mod' );
+ \groups_demote_member( $test_user_id, $group_id );
+
+ // In order to bypass bulk activity deletion logs.
+ $this->mock->ignore_activity_bulk_deletion = true;
+ \groups_ban_member( $test_user_id, $group_id );
+
+ \groups_unban_member( $test_user_id, $group_id );
+ \groups_leave_group( $group_id, $test_user_id );
+ \groups_join_group( $group_id, $test_user_id );
+
+ // In order to bypass bulk activity deletion logs.
+ $this->mock->ignore_activity_bulk_deletion = true;
+ \groups_remove_member( $test_user_id, $group_id );
+
+ \groups_delete_group( $group_id );
+
+ // Check callback test actions.
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_create_group' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_update_group' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_details_updated' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_settings_updated' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_leave_group' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_join_group' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_promote_member' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_demote_member' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_ban_member' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_unban_member' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_remove_member' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_groups_before_delete_group' ) );
+ }
+
+ public function test_profile_action_callbacks() {
+ // Expected log actions.
+ $this->mock->expects( $this->exactly( 6 ) )
+ ->method( 'log' )
+ ->withConsecutive(
+ array(
+ $this->equalTo( esc_html__( 'Created profile field group "Test field group"' ) ),
+ $this->callback(
+ function( $subject ) {
+ $expected = array( 'group_name' => 'Test field group' );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'profile_fields',
+ 'created',
+ ),
+ array(
+ $this->equalTo( esc_html__( 'Created profile field "Test field"' ) ),
+ $this->callback(
+ function( $subject ) {
+ $expected = array( 'field_name' => 'Test field' );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'profile_fields',
+ 'created',
+ ),
+ array(
+ $this->equalTo( esc_html__( 'Updated profile field "Test field"' ) ),
+ $this->callback(
+ function( $subject ) {
+ $expected = array( 'field_name' => 'Test field' );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'profile_fields',
+ 'updated',
+ ),
+ array(
+ $this->equalTo( esc_html__( 'Deleted profile field "Test field"' ) ),
+ $this->callback(
+ function( $subject ) {
+ $expected = array( 'field_name' => 'Test field' );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'profile_fields',
+ 'deleted',
+ ),
+ array(
+ $this->equalTo( esc_html__( 'Updated profile field group "Test field group"' ) ),
+ $this->callback(
+ function( $subject ) {
+ $expected = array( 'group_name' => 'Test field group' );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'profile_fields',
+ 'updated',
+ ),
+ array(
+ $this->equalTo( esc_html__( 'Deleted profile field group "Test field group"' ) ),
+ $this->callback(
+ function( $subject ) {
+ $expected = array( 'group_name' => 'Test field group' );
+ return $expected === array_intersect_key( $expected, $subject );
+ }
+ ),
+ $this->greaterThan( 0 ),
+ 'profile_fields',
+ 'deleted',
+ )
+ );
+
+ // Create/trigger/update fields and field groups to trigger callbacks.
+ // Create new field group.
+ $field_group_args = array(
+ 'name' => 'Test field group',
+ 'description' => 'Lorem ipsum dolor',
+ 'slug' => 'test-field-group',
+ 'can_delete' => 'false',
+ );
+ $group_id = \xprofile_insert_field_group( $field_group_args );
+ $group = new \BP_XProfile_Group( $group_id );
+
+ // Create new field in field group.
+ $field_args = array(
+ 'name' => 'Test field',
+ 'description' => 'Lorem ipsum dolor',
+ 'type' => 'textbox',
+ 'field_group_id' => $group_id
+ );
+ $field_id = \xprofile_insert_field( $field_args );
+ $field = new \BP_XProfile_Field( $field_id );
+
+ // Update field.
+ $field->is_required = true;
+ $field->save();
+
+ // Delete field.
+ $this->assertTrue( xprofile_admin_delete_field( $field_id, 'textbox' ) );
+
+ // Update field group.
+ $group->can_delete = 1;
+ $group->save();
+
+ // Delete field group.
+ $this->assertTrue( xprofile_admin_delete_group( $group->id ) );
+
+ // Check callback test actions.
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_xprofile_group_before_save' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_xprofile_group_after_save' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_xprofile_field_before_save' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_xprofile_field_after_save' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_xprofile_fields_deleted_field' ) );
+ $this->assertFalse( 0 === did_action( $this->action_prefix . 'callback_xprofile_groups_deleted_group' ) );
+ }
+}