PayloadBuilder.php
1 month ago
RegisterSite.php
1 month ago
Scheduler.php
1 month ago
Sender.php
1 month ago
PayloadBuilder.php
142 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Builds the full usage report payload (schema_version, site_token, snapshot, dynamic_metrics). |
| 4 | * |
| 5 | * @package TwitterFeed\UsageTracking\Core |
| 6 | * @since 2.6 |
| 7 | */ |
| 8 | |
| 9 | namespace TwitterFeed\UsageTracking\Core; |
| 10 | |
| 11 | use TwitterFeed\UsageTracking\Config; |
| 12 | use TwitterFeed\UsageTracking\ReporterInterface; |
| 13 | |
| 14 | if ( ! defined( 'ABSPATH' ) ) { |
| 15 | exit; |
| 16 | } |
| 17 | |
| 18 | class PayloadBuilder { |
| 19 | |
| 20 | /** |
| 21 | * @var ReporterInterface |
| 22 | */ |
| 23 | private $reporter; |
| 24 | |
| 25 | /** |
| 26 | * @param ReporterInterface $reporter Plugin-specific reporter. |
| 27 | */ |
| 28 | public function __construct( ReporterInterface $reporter ) { |
| 29 | $this->reporter = $reporter; |
| 30 | } |
| 31 | |
| 32 | /** |
| 33 | * Build the full payload for the usage-report endpoint. |
| 34 | * |
| 35 | * @param string $site_token Site token from RegisterSite. |
| 36 | * @param string $period_start Period start (e.g. Y-m-d). |
| 37 | * @param string $period_end Period end (e.g. Y-m-d). |
| 38 | * @return array |
| 39 | */ |
| 40 | public function build( $site_token, $period_start, $period_end ) { |
| 41 | $payload_id = $this->generate_payload_id(); |
| 42 | $slug = $this->reporter->get_plugin_slug(); |
| 43 | $snapshot = $this->reporter->get_configuration_snapshot(); |
| 44 | $license_tier = isset( $snapshot['license_tier'] ) ? $snapshot['license_tier'] : 'free'; |
| 45 | $license_status = isset( $snapshot['license_status'] ) ? $snapshot['license_status'] : null; |
| 46 | $license_expires = isset( $snapshot['license_expires'] ) ? $snapshot['license_expires'] : null; |
| 47 | $license_item_id = isset( $snapshot['license_item_id'] ) ? $snapshot['license_item_id'] : null; |
| 48 | $version = isset( $snapshot['version'] ) ? $snapshot['version'] : (defined( 'CTF_VERSION' ) ? CTF_VERSION : ''); |
| 49 | unset( $snapshot['license_tier'], $snapshot['license_status'], $snapshot['license_expires'], $snapshot['license_item_id'], $snapshot['version'] ); |
| 50 | |
| 51 | $type = defined( 'CTF_STORE_URL' ) ? 'pro' : 'free'; |
| 52 | |
| 53 | $dynamic_metrics = $this->reporter->get_dynamic_metrics( $period_start, $period_end ); |
| 54 | $errors = isset( $dynamic_metrics['errors'] ) ? $dynamic_metrics['errors'] : array(); |
| 55 | unset( $dynamic_metrics['errors'] ); |
| 56 | |
| 57 | return array( |
| 58 | 'schema_version' => $this->reporter->get_schema_version(), |
| 59 | 'plugin' => $slug, |
| 60 | 'type' => $type, |
| 61 | 'site_token' => $site_token, |
| 62 | 'payload_id' => $payload_id, |
| 63 | 'period_start' => $period_start, |
| 64 | 'period_end' => $period_end, |
| 65 | 'plugin_info' => array( |
| 66 | 'slug' => $slug, |
| 67 | 'version' => $version, |
| 68 | 'license_tier' => $license_tier, |
| 69 | 'license_status' => $license_status, |
| 70 | 'license_expires' => $license_expires, |
| 71 | 'license_item_id' => $license_item_id, |
| 72 | ), |
| 73 | 'configuration_snapshot' => $snapshot, |
| 74 | 'errors' => $errors, |
| 75 | 'dynamic_metrics' => $dynamic_metrics, |
| 76 | 'active_plugins' => $this->get_active_plugins(), |
| 77 | 'active_theme' => $this->get_active_theme(), |
| 78 | ); |
| 79 | } |
| 80 | |
| 81 | /** |
| 82 | * Generate a unique payload ID (UUID v4 style). |
| 83 | * |
| 84 | * @return string |
| 85 | */ |
| 86 | private function generate_payload_id() { |
| 87 | if ( function_exists( 'wp_generate_uuid4' ) ) { |
| 88 | return wp_generate_uuid4(); |
| 89 | } |
| 90 | return sprintf( |
| 91 | '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', |
| 92 | wp_rand( 0, 0xffff ), |
| 93 | wp_rand( 0, 0xffff ), |
| 94 | wp_rand( 0, 0xffff ), |
| 95 | wp_rand( 0, 0x0fff ) | 0x4000, |
| 96 | wp_rand( 0, 0x3fff ) | 0x8000, |
| 97 | wp_rand( 0, 0xffff ), |
| 98 | wp_rand( 0, 0xffff ), |
| 99 | wp_rand( 0, 0xffff ) |
| 100 | ); |
| 101 | } |
| 102 | |
| 103 | private function get_active_plugins(): array { |
| 104 | if ( ! function_exists( 'get_plugins' ) ) { |
| 105 | require_once ABSPATH . 'wp-admin/includes/plugin.php'; |
| 106 | } |
| 107 | |
| 108 | $all_plugins = get_plugins(); |
| 109 | $active_basenames = array_merge( |
| 110 | (array) get_option( 'active_plugins', array() ), |
| 111 | array_keys( (array) get_site_option( 'active_sitewide_plugins', array() ) ) |
| 112 | ); |
| 113 | |
| 114 | $result = array(); |
| 115 | foreach ( array_unique( $active_basenames ) as $basename ) { |
| 116 | if ( ! isset( $all_plugins[ $basename ] ) ) { |
| 117 | continue; |
| 118 | } |
| 119 | $data = $all_plugins[ $basename ]; |
| 120 | $result[] = array( |
| 121 | 'slug' => $basename, |
| 122 | 'name' => isset( $data['Name'] ) ? sanitize_text_field( (string) $data['Name'] ) : null, |
| 123 | 'version' => isset( $data['Version'] ) ? sanitize_text_field( (string) $data['Version'] ) : null, |
| 124 | 'author' => isset( $data['Author'] ) ? wp_strip_all_tags( (string) $data['Author'] ) : null, |
| 125 | ); |
| 126 | } |
| 127 | |
| 128 | return $result; |
| 129 | } |
| 130 | |
| 131 | private function get_active_theme(): ?array { |
| 132 | $theme = wp_get_theme(); |
| 133 | if ( ! $theme->exists() ) { |
| 134 | return null; |
| 135 | } |
| 136 | return array( |
| 137 | 'name' => sanitize_text_field( (string) $theme->get( 'Name' ) ), |
| 138 | 'version' => sanitize_text_field( (string) $theme->get( 'Version' ) ), |
| 139 | ); |
| 140 | } |
| 141 | } |
| 142 |