Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Admin user data to JetPack connected event #108

Merged
merged 28 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8b17c7c
Add Admin user data to JetPack connected event
mr-vara Nov 11, 2024
5b792ee
Fix lint issues
mr-vara Nov 11, 2024
5a08584
Move the get admin user to Plugin Helper
mr-vara Nov 11, 2024
2401455
Fix lint issues
mr-vara Nov 11, 2024
96afb63
Keep important fields only
mr-vara Nov 13, 2024
80a3960
Add `jetpack` plugin
BrianHenryIE Nov 15, 2024
7143ee3
Change `static` to instance methods
BrianHenryIE Nov 15, 2024
74d5a28
Add types
BrianHenryIE Nov 15, 2024
de93bed
Create PluginWPUnitTest.php
BrianHenryIE Nov 15, 2024
1b79ec0
Add `WP_CONTENT_DIR` to use Composer installed plugins in tests
BrianHenryIE Nov 15, 2024
38d0ee8
Use `isset()`
BrianHenryIE Nov 15, 2024
0d2b3b6
Strict compare the value, otherwise '"false"' would evaluate to 'true'
BrianHenryIE Nov 15, 2024
0363f52
Add tests for `NewfoldLabs\WP\Module\Data\Helpers\Plugin`
BrianHenryIE Nov 15, 2024
dd41adb
Update patchwork.json
BrianHenryIE Nov 15, 2024
db8d438
Update clients to use instance of class rather than static methods
BrianHenryIE Nov 15, 2024
263222f
Update tests after `auto_update_plugin` fix
BrianHenryIE Nov 15, 2024
038b60f
Add default paths so it runs without parameters
BrianHenryIE Nov 15, 2024
67f252a
Phive install `brianhenryie/php-diff-test`
BrianHenryIE Nov 15, 2024
0f89d2e
Revert "Phive install `brianhenryie/php-diff-test`"
BrianHenryIE Nov 15, 2024
1af8eb2
Allow injecting `Helpers/Plugin`
BrianHenryIE Nov 18, 2024
3626318
Use Mockery instead of Patchwork.
BrianHenryIE Nov 18, 2024
d55aea7
Merge remote-tracking branch 'origin' into PRESS11-17-v2
BrianHenryIE Nov 18, 2024
d10b59b
Update deprecated diff filter config
BrianHenryIE Nov 18, 2024
6436c2b
Use diff in `compose cs-changes` script
BrianHenryIE Nov 18, 2024
dda58c8
Show progress and sniff codes in all reports
BrianHenryIE Nov 18, 2024
85c4630
Remove TODO – covered by a broad Jira ticket
BrianHenryIE Nov 18, 2024
0db7084
`phpcs:ignore` the verify token, which is a nonce
BrianHenryIE Nov 18, 2024
5ec6f29
Rename `codecoverage-main` to `unit-tests`
BrianHenryIE Nov 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:

- uses: technote-space/get-diff-action@v6 # repo is archived.
with:
SUFFIX_FILTER: .php
PATTERNS: ./**/*.php

- name: Get Composer cache directory
id: composer-cache
Expand Down Expand Up @@ -68,5 +68,5 @@ jobs:
GITHUB_TOKEN: "${{ github.token }}"

- name: Detecting PHP Code Standards Violations
run: vendor/bin/phpcs --standard=phpcs.xml -s ${{ env.GIT_DIFF }} --report=checkstyle | cs2pr
if: "!! env.GIT_DIFF"
run: vendor/bin/phpcs --standard=phpcs.xml -s ${{ env.GIT_DIFF_FILTERED }} --report=checkstyle | cs2pr
if: "!! env.GIT_DIFF_FILTERED"
2 changes: 1 addition & 1 deletion .github/workflows/unit-tests-and-coverage-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ on:

jobs:

codecoverage-main:
unit-tests:
runs-on: ubuntu-latest

services:
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"vendor/bin/phpcbf . --standard=phpcs.xml"
],
"cs-changes": [
"updated_files=$( git status | grep '\\(new file\\|modified\\):\\s.*.php$' | cut -c14- | awk '{ printf(\"%s \", $0) }' ); echo \"\\nChecking\"$(git status | grep '\\(new file\\|modified\\):\\s.*.php$' | tail -n+2 | wc -l)\" files\"; phpcbf $(echo $updated_files); phpcs $(echo $updated_files);"
"updated_files=$(echo $(git diff --name-only `git merge-base origin/main HEAD` | grep php)); if [ -n \"$updated_files\" ]; then phpcbf $(echo $updated_files); phpcs $(echo $updated_files); else echo \"No modified .php files for PHPCS.\"; fi;"
],
"lint": [
"vendor/bin/phpcs . --standard=phpcs.xml -s"
Expand Down Expand Up @@ -121,6 +121,7 @@
"lucatume/wp-browser": "^3.5.8",
"newfold-labs/wp-php-standards": "^1.2.3",
"phpunit/phpcov": "^5.0",
"wpackagist-plugin/jetpack": "^14.0",
"wpackagist-plugin/woocommerce": ">=9"
},
"extra": {
Expand Down
20 changes: 19 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 46 additions & 17 deletions includes/Helpers/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,32 @@

/**
* Helper class for gathering and formatting plugin data
*
* @phpstan-type plugin-array array{slug:string, version:string, title:string, url:string, active:bool, mu:bool, auto_updates:bool, users?:array<array{id:int, email:string}>}
*/
class Plugin {
/**
* Prepare plugin data for a single plugin
*
* @param string $basename The plugin basename (filename relative to WP_PLUGINS_DIR).
*
* @return array{slug:string, version:string, title:string, url:string, active:bool, mu:bool, auto_updates:bool} Hiive relevant plugin details
* @return plugin-array Hiive relevant plugin details
*/
public static function collect( $basename ) {
public function collect( $basename ): array {

if ( ! function_exists( 'get_plugin_data' ) ) {
require wp_normalize_path( constant( 'ABSPATH' ) . '/wp-admin/includes/plugin.php' );
}

return self::get_data( $basename, get_plugin_data( constant( 'WP_PLUGIN_DIR' ) . '/' . $basename ) );
return $this->get_data( $basename, get_plugin_data( constant( 'WP_PLUGIN_DIR' ) . '/' . $basename ) );
}

/**
* Prepare plugin data for all plugins
*
* @return array of plugins
* @return array<plugin-array> of plugins
*/
public static function collect_installed() {
public function collect_installed(): array {
if ( ! function_exists( 'get_plugins' ) ) {
require wp_normalize_path( constant( 'ABSPATH' ) . '/wp-admin/includes/plugin.php' );
}
Expand All @@ -36,12 +38,12 @@ public static function collect_installed() {

// Collect standard plugins
foreach ( get_plugins() as $slug => $data ) {
array_push( $plugins, self::get_data( $slug, $data ) );
array_push( $plugins, $this->get_data( $slug, $data ) );
}

// Collect mu plugins
foreach ( get_mu_plugins() as $slug => $data ) {
array_push( $plugins, self::get_data( $slug, $data, true ) );
array_push( $plugins, $this->get_data( $slug, $data, true ) );
}

return $plugins;
Expand All @@ -54,17 +56,21 @@ public static function collect_installed() {
* @param array $data The plugin meta-data from its header.
* @param bool $mu Whether the plugin is installed as a must-use plugin.
*
* @return array{slug:string, version:string, title:string, url:string, active:bool, mu:bool, auto_updates:bool} Hiive relevant plugin details
* @return plugin-array Hiive relevant plugin details
*/
public static function get_data( $basename, $data, $mu = false ) {
public function get_data( string $basename, array $data, bool $mu = false ): array {
$plugin = array();
$plugin['slug'] = $basename;
$plugin['version'] = $data['Version'] ? $data['Version'] : '0.0';
$plugin['title'] = $data['Name'] ? $data['Name'] : '';
$plugin['url'] = $data['PluginURI'] ? $data['PluginURI'] : '';
$plugin['version'] = isset( $data['Version'] ) ? $data['Version'] : '0.0';
$plugin['title'] = isset( $data['Name'] ) ? $data['Name'] : '';
$plugin['url'] = isset( $data['PluginURI'] ) ? $data['PluginURI'] : '';
$plugin['active'] = is_plugin_active( $basename );
$plugin['mu'] = $mu;
$plugin['auto_updates'] = ( ! $mu && self::does_it_autoupdate( $basename ) );
$plugin['auto_updates'] = ( ! $mu && $this->does_it_autoupdate( $basename ) );

if ( strpos( $basename, 'jetpack/jetpack.php' ) !== false ) {
$plugin['users'] = $this->get_admin_users();
}

return $plugin;
}
Expand All @@ -73,12 +79,10 @@ public static function get_data( $basename, $data, $mu = false ) {
* Whether the plugin is set to auto update
*
* @param string $slug Name of the plugin
*
* @return bool
*/
public static function does_it_autoupdate( $slug ) {
protected function does_it_autoupdate( string $slug ): bool {
// Check plugin setting for auto updates on all plugins
if ( get_site_option( 'auto_update_plugin', 'true' ) ) {
if ( 'true' === get_site_option( 'auto_update_plugin', 'true' ) ) {
return true;
}

Expand All @@ -87,4 +91,29 @@ public static function does_it_autoupdate( $slug ) {

return in_array( $slug, $wp_auto_updates, true );
}

/**
* Get Admin and SuperAdmin user accounts
*
* @return array<array{id:int, email:string}> $users Array of Admin & Super Admin users
*/
protected function get_admin_users(): array {
// Get all admin users
$admin_users = get_users(
array(
'role' => 'administrator',
)
);
$users = array();

// Add administrators to the $users and check for super admin
foreach ( $admin_users as $user ) {
$users[] = array(
'id' => $user->ID,
'email' => $user->user_email,
);
}

return $users;
}
}
19 changes: 13 additions & 6 deletions includes/HiiveConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,24 +78,32 @@ public function rest_api_init(): void {
*
* Hiive will first attempt to verify using the REST API, and fallback to this AJAX endpoint on error.
*
* Token is generated in {@see self::connect()} using {@see md5()}.
*
* @hooked wp_ajax_nopriv_nfd-hiive-verify
*
* @return never
*/
public function ajax_verify() {
$valid = $this->verify_token( $_REQUEST['token'] );
$status = ( $valid ) ? 200 : 400;
// PHPCS: Ignore the nonce verification here – the token _is_ a nonce.
// @phpcs:ignore WordPress.Security.NonceVerification.Recommended
$token = $_REQUEST['token'];

$is_valid = $this->verify_token( $token );
$status = ( $is_valid ) ? 200 : 400;

$data = array(
'token' => $_REQUEST['token'],
'valid' => $valid,
'token' => $token,
'valid' => $is_valid,
);
\wp_send_json( $data, $status );
}

/**
* Confirm whether verification token is valid
*
* Token is generated in {@see self::connect()} using {@see md5()}.
*
* @param string $token Token to verify
*/
public function verify_token( string $token ): bool {
Expand Down Expand Up @@ -144,7 +152,7 @@ public function connect( string $path = '/sites/v2/connect', ?string $authorizat

$data = $this->get_core_data();
$data['verify_token'] = $token;
$data['plugins'] = PluginHelper::collect_installed();
$data['plugins'] = ( new PluginHelper() )->collect_installed();

$args = array(
'body' => \wp_json_encode( $data ),
Expand Down Expand Up @@ -260,7 +268,6 @@ public function send_event( Event $event ) {
$hiive_response = $this->hiive_request( 'sites/v1/events', $payload );

if ( is_wp_error( $hiive_response ) ) {
// TODO: enqueue failed event for later. Should this function call go via EventManager?
return $hiive_response;
}

Expand Down
2 changes: 1 addition & 1 deletion includes/Listeners/Cron.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function register_hooks(): void {
*/
public function update(): void {
$data = array(
'plugins' => Plugin::collect_installed(),
'plugins' => ( new Plugin() )->collect_installed(),
);

$data = apply_filters( 'newfold_wp_data_module_cron_data_filter', $data );
Expand Down
35 changes: 29 additions & 6 deletions includes/Listeners/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,36 @@

namespace NewfoldLabs\WP\Module\Data\Listeners;

use NewfoldLabs\WP\Module\Data\EventManager;
use NewfoldLabs\WP\Module\Data\Helpers\Transient;
use NewfoldLabs\WP\Module\Data\Helpers\Plugin as PluginHelper;

/**
* Monitors generic plugin events
*/
class Plugin extends Listener {

/**
* Functions for gathering plugin data
*
* @var PluginHelper
*/
protected $plugin_helper;

/**
* Constructor
*
* @param EventManager $manager Event manager instance
* @param ?PluginHelper $plugin_helper Class used to fetch plugin data.
*/
public function __construct(
EventManager $manager,
?PluginHelper $plugin_helper = null
) {
parent::__construct( $manager );
$this->plugin_helper = $plugin_helper ?? new PluginHelper();
}

/**
* Register the hooks for the subscriber
*
Expand Down Expand Up @@ -42,7 +65,7 @@ public function register_hooks() {
*/
public function activated( $plugin, $network_wide ) {
$data = array(
'plugin' => PluginHelper::collect( $plugin ),
'plugin' => $this->plugin_helper->collect( $plugin ),
'network_wide' => $network_wide,
);
$this->push( 'plugin_activated', $data );
Expand All @@ -58,7 +81,7 @@ public function activated( $plugin, $network_wide ) {
*/
public function deactivated( $plugin, $network_wide ) {
$data = array(
'plugin' => PluginHelper::collect( $plugin ),
'plugin' => $this->plugin_helper->collect( $plugin ),
'network_wide' => $network_wide,
);

Expand All @@ -76,7 +99,7 @@ public function deactivated( $plugin, $network_wide ) {
* @return void
*/
public function save_deleted( $plugin ) {
update_option( 'deleted_plugin', PluginHelper::collect( $plugin ) );
update_option( 'deleted_plugin', $this->plugin_helper->collect( $plugin ) );
}

/**
Expand Down Expand Up @@ -137,12 +160,12 @@ protected function updated( array $options ): void {
// Manual updates always return array of plugin slugs
if ( isset( $options['plugins'] ) && is_array( $options['plugins'] ) ) {
foreach ( $options['plugins'] as $slug ) {
array_push( $plugins, PluginHelper::collect( $slug ) );
array_push( $plugins, $this->plugin_helper->collect( $slug ) );
}
}
// Auto updates always return a single plugin slug
if ( isset( $options['plugin'] ) ) {
array_push( $plugins, PluginHelper::collect( $options['plugin'] ) );
array_push( $plugins, $this->plugin_helper->collect( $options['plugin'] ) );
}

$data = array(
Expand All @@ -159,7 +182,7 @@ protected function updated( array $options ): void {
*/
public function installed() {
$data = array(
'plugins' => PluginHelper::collect_installed(),
'plugins' => $this->plugin_helper->collect_installed(),
);
$this->push( 'plugin_installed', $data );
}
Expand Down
1 change: 1 addition & 0 deletions patchwork.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"defined",
"constant",
"file_get_contents",
"function_exists",
"time"
]
}
3 changes: 3 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@

<file>includes</file>
<file>upgrades</file>

<!-- Show progress and sniff codes in all reports -->
<arg value="ps"/>
</ruleset>
Loading
Loading