plugin install
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Telemetry;
|
||||
|
||||
use GFCommon;
|
||||
use GFFormsModel;
|
||||
|
||||
/**
|
||||
* Class GF_Telemetry_Data
|
||||
*
|
||||
* Base class for telemetry data.
|
||||
*
|
||||
* @package Gravity_Forms\Gravity_Forms\Telemetry
|
||||
*/
|
||||
abstract class GF_Telemetry_Data {
|
||||
|
||||
/**
|
||||
* @var array $data Data to be sent.
|
||||
*/
|
||||
public $data = array();
|
||||
|
||||
/**
|
||||
* @var string $key Unique identifier for this data object.
|
||||
*/
|
||||
public $key = '';
|
||||
|
||||
/**
|
||||
* @var bool $data_collection Whether data collection is allowed.
|
||||
*/
|
||||
public $data_collection = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const TELEMETRY_ENDPOINT = 'https://in.gravity.io/';
|
||||
|
||||
public function __construct() {
|
||||
$this->data_collection = $this->is_data_collection_allowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user has allowed data collection.
|
||||
*
|
||||
* @since 2.8.3
|
||||
*
|
||||
* @return false|mixed|null
|
||||
*/
|
||||
public function is_data_collection_allowed() {
|
||||
return get_option( 'rg_gforms_dataCollection', false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current telemetry data.
|
||||
*
|
||||
* @since 2.8
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_data() {
|
||||
$existing_data = get_option( 'gf_telemetry_data', [] );
|
||||
|
||||
return $existing_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save telemetry data.
|
||||
*
|
||||
* @since 2.8
|
||||
*
|
||||
* @param GF_Telemetry_Data $data The data to save.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function save_data( GF_Telemetry_Data $data ) {
|
||||
$existing_data = self::get_data();
|
||||
|
||||
if ( ! $existing_data ) {
|
||||
$existing_data = array(
|
||||
'snapshot' => array(),
|
||||
'events' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
if ( $data->key == 'snapshot' ) {
|
||||
$existing_data[ $data->key ] = $data;
|
||||
} else {
|
||||
$existing_data['events'][] = $data;
|
||||
}
|
||||
|
||||
update_option( 'gf_telemetry_data', $existing_data, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a snapshot of the current site data.
|
||||
*
|
||||
* @since 2.8
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function take_snapshot() {
|
||||
$snapshot = new GF_Telemetry_Snapshot_Data();
|
||||
self::save_data( $snapshot );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to the telemetry endpoint.
|
||||
*
|
||||
* @since 2.8
|
||||
*
|
||||
* @param array $entries The data to send.
|
||||
*
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
public static function send_data( $entries ) {
|
||||
// allow overriding the endpoint to use the local or staging environment for testing purposes.
|
||||
$endpoint = defined( 'GF_TELEMETRY_ENDPOINT' ) ? GF_TELEMETRY_ENDPOINT : self::TELEMETRY_ENDPOINT;
|
||||
$site_url = get_site_url();
|
||||
$data = array(
|
||||
'license_key_md5' => md5( get_option( 'rg_gforms_key', '' ) ),
|
||||
'site_url' => $site_url,
|
||||
'product' => 'gravityforms',
|
||||
'tag' => 'system_report',
|
||||
'data' => $entries,
|
||||
);
|
||||
|
||||
return wp_remote_post(
|
||||
$endpoint . 'api/telemetry_data_bulk',
|
||||
array(
|
||||
'headers' => array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => sha1( $site_url ),
|
||||
),
|
||||
'method' => 'POST',
|
||||
'data_format' => 'body',
|
||||
'body' => json_encode( $data ),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Telemetry;
|
||||
use GFCommon;
|
||||
use function tad\WPBrowser\debug;
|
||||
|
||||
if ( ! class_exists( 'GFForms' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'GF_Background_Process' ) ) {
|
||||
require_once GF_PLUGIN_DIR_PATH . 'includes/libraries/gf-background-process.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* GF_Telemetry_Processor Class.
|
||||
*/
|
||||
class GF_Telemetry_Processor extends \GF_Background_Process {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $action = 'gf_telemetry_processor';
|
||||
|
||||
/**
|
||||
* Task
|
||||
*
|
||||
* Process a single batch of telemetry data.
|
||||
*
|
||||
* @param mixed $batch
|
||||
* @return mixed
|
||||
*/
|
||||
protected function task( $batch ) {
|
||||
|
||||
if ( ! is_array( $batch ) ) {
|
||||
$batch = array( $batch );
|
||||
}
|
||||
|
||||
$raw_response = null;
|
||||
\GFCommon::log_debug( __METHOD__ . sprintf( '(): Processing a batch of %d telemetry data.', count( $batch ) ) );
|
||||
$data = array();
|
||||
foreach ( $batch as $item ) {
|
||||
|
||||
if ( ! is_object( $item ) || ! property_exists( $item, 'data' ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// attach type & tag, required by the telemetry API.
|
||||
$item->data['type'] = $item->key === 'snapshot' ? 'snapshot' : 'event';
|
||||
$item->data['tag'] = $item->key;
|
||||
$data[] = $item->data;
|
||||
}
|
||||
$raw_response = GF_Telemetry_Data::send_data( $data );
|
||||
|
||||
if ( is_wp_error( $raw_response ) ) {
|
||||
\GFCommon::log_debug( __METHOD__ . sprintf( '(): Failed sending telemetry data. Code: %s; Message: %s.', $raw_response->get_error_code(), $raw_response->get_error_message() ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( $batch as $item ) {
|
||||
if ( ! is_object( $item ) ) {
|
||||
\GFCommon::log_debug( __METHOD__ . sprintf( '(): Telemetry data is missing. Aborting running data_sent method on this entry.' ) );
|
||||
continue;
|
||||
}
|
||||
$classname = get_class( $item );
|
||||
if ( method_exists( $classname, 'data_sent' ) ) {
|
||||
$classname::data_sent( $raw_response );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Telemetry;
|
||||
|
||||
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
|
||||
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
|
||||
use GFCommon;
|
||||
use GFFormsModel;
|
||||
|
||||
|
||||
/**
|
||||
* Class GF_Telemetry_Service_Provider
|
||||
*
|
||||
* Service provider for the telemetry Service.
|
||||
*
|
||||
* @package Gravity_Forms\Gravity_Forms\Telemetry;
|
||||
*/
|
||||
class GF_Telemetry_Service_Provider extends GF_Service_Provider {
|
||||
const TELEMETRY_SCHEDULED_TASK = 'gravityforms_telemetry_dispatcher';
|
||||
const BATCH_SIZE = 10;
|
||||
|
||||
/**
|
||||
* Register services to the container.
|
||||
*
|
||||
* @since
|
||||
*
|
||||
* @param GF_Service_Container $container
|
||||
*/
|
||||
public function register( GF_Service_Container $container ) {
|
||||
require_once GF_PLUGIN_DIR_PATH . 'includes/telemetry/class-gf-telemetry-data.php';
|
||||
require_once GF_PLUGIN_DIR_PATH . 'includes/telemetry/class-gf-telemetry-snapshot-data.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the scheduler.
|
||||
*
|
||||
* @since
|
||||
*
|
||||
* @param GF_Service_Container $container
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init( GF_Service_Container $container ) {
|
||||
add_action( self::TELEMETRY_SCHEDULED_TASK, array( $this, 'enqueue_telemetry_batches' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue batches of telemetry events to be processed in the background.
|
||||
*
|
||||
* @since
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_telemetry_batches() {
|
||||
// Only run once a week.
|
||||
$last_run = get_option( 'gf_last_telemetry_run', 0 );
|
||||
$current_time = time();
|
||||
if ( $current_time - $last_run < 60 * 60 * 24 * 7 ) {
|
||||
return;
|
||||
}
|
||||
update_option( 'gf_last_telemetry_run', $current_time );
|
||||
|
||||
\GFCommon::log_debug( __METHOD__ . sprintf( '(): Enqueuing telemetry batches' ) );
|
||||
GF_Telemetry_Data::take_snapshot();
|
||||
|
||||
$processor = $this->container->get( \Gravity_Forms\Gravity_Forms\Async\GF_Background_Process_Service_Provider::TELEMETRY );
|
||||
|
||||
$full_telemetry_data = GF_Telemetry_Data::get_data();
|
||||
|
||||
$snapshot = $full_telemetry_data['snapshot'];
|
||||
|
||||
// Enqueue the snapshot first, alone, to be sent to its own endpoint.
|
||||
$processor->push_to_queue( $snapshot );
|
||||
$processor->save()->dispatch();
|
||||
|
||||
$full_telemetry_data = array_chunk( $full_telemetry_data['events'], self::BATCH_SIZE, true );
|
||||
foreach ( $full_telemetry_data as $batch ) {
|
||||
$processor->push_to_queue( $batch );
|
||||
$processor->save()->dispatch();
|
||||
}
|
||||
|
||||
// Clear saved telemetry data except the snapshot.
|
||||
update_option(
|
||||
'gf_telemetry_data',
|
||||
array(
|
||||
'snapshot' => $snapshot,
|
||||
'events' => array(),
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Telemetry;
|
||||
|
||||
use GFCommon;
|
||||
use GFForms;
|
||||
use GFFormsModel;
|
||||
use \Gravity_Forms\Gravity_Forms\Setup_Wizard\GF_Setup_Wizard_Service_Provider;
|
||||
use \Gravity_Forms\Gravity_Forms\Setup_Wizard\Endpoints\GF_Setup_Wizard_Endpoint_Save_Prefs;
|
||||
|
||||
class GF_Telemetry_Snapshot_Data extends GF_Telemetry_Data {
|
||||
|
||||
/**
|
||||
* @var string $key Identifier for this data object.
|
||||
*/
|
||||
public $key = 'snapshot';
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
/**
|
||||
* Array of callback functions returning an array of data to be included in the telemetry snapshot.
|
||||
*
|
||||
* @since 2.8
|
||||
*/
|
||||
$callbacks = array(
|
||||
array( $this, 'get_site_basic_info' ),
|
||||
array( $this, 'get_gf_settings' ),
|
||||
array( $this, 'get_legacy_forms' ),
|
||||
);
|
||||
|
||||
// Merges the default callbacks with any additional callbacks added via the gform_telemetry_snapshot_data filter. Default callbacks are added last so they can't be overridden.
|
||||
$callbacks = array_merge( $this->get_callbacks(), $callbacks );
|
||||
|
||||
foreach ( $callbacks as $callback ) {
|
||||
if ( is_callable( $callback ) ) {
|
||||
$this->data = array_merge( $this->data, call_user_func( $callback ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get additional callbacks that return data to be included in the telemetry snapshot.
|
||||
*
|
||||
* @since 2.8
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_callbacks() {
|
||||
/**
|
||||
* Filters the non-default data to be included in the telemetry snapshot.
|
||||
*
|
||||
* @since 2.8
|
||||
*
|
||||
* @param array $new_callbacks An array of callbacks returning an array of data to be included in the telemetry snapshot. Default empty array.
|
||||
*/
|
||||
return apply_filters( 'gform_telemetry_snapshot_data', array() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get basic site info for telemetry.
|
||||
*
|
||||
* @since 2.8
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_site_basic_info() {
|
||||
|
||||
if ( ! function_exists( 'get_plugins' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
$plugin_list = get_plugins();
|
||||
$plugins = array();
|
||||
|
||||
$active_plugins = get_option( 'active_plugins' );
|
||||
|
||||
foreach ( $plugin_list as $key => $plugin ) {
|
||||
$is_active = in_array( $key, $active_plugins );
|
||||
|
||||
$slug = substr( $key, 0, strpos( $key, '/' ) );
|
||||
if ( empty( $slug ) ) {
|
||||
$slug = str_replace( '.php', '', $key );
|
||||
}
|
||||
|
||||
$plugins[] = array(
|
||||
'name' => str_replace( 'phpinfo()', 'PHP Info', $plugin['Name'] ),
|
||||
'slug' => $slug,
|
||||
'version' => $plugin['Version'],
|
||||
'is_active' => $is_active,
|
||||
);
|
||||
}
|
||||
|
||||
$theme = wp_get_theme();
|
||||
$theme_name = $theme->get( 'Name' );
|
||||
$theme_uri = $theme->get( 'ThemeURI' );
|
||||
$theme_version = $theme->get( 'Version' );
|
||||
$theme_author = $theme->get( 'Author' );
|
||||
$theme_author_uri = $theme->get( 'AuthorURI' );
|
||||
|
||||
$form_counts = GFFormsModel::get_form_count();
|
||||
$active_count = $form_counts['active'];
|
||||
$inactive_count = $form_counts['inactive'];
|
||||
$fc = abs( $active_count ) + abs( $inactive_count );
|
||||
$entry_count = GFFormsModel::get_entry_count_all_forms( 'active' );
|
||||
$meta_counts = GFFormsModel::get_entry_meta_counts();
|
||||
$im = is_multisite();
|
||||
$lang = get_locale();
|
||||
$db = GFCommon::get_dbms_type();
|
||||
|
||||
$post = array(
|
||||
'key' => GFCommon::get_key(),
|
||||
'wp_version' => get_bloginfo( 'version' ),
|
||||
'php_version' => phpversion(),
|
||||
'mysql_version' => GFCommon::get_db_version(),
|
||||
'plugins' => $plugins,
|
||||
'theme_name' => $theme_name,
|
||||
'theme_uri' => $theme_uri,
|
||||
'theme_version' => $theme_version,
|
||||
'theme_author' => $theme_author,
|
||||
'theme_author_uri' => $theme_author_uri,
|
||||
'is_multisite' => $im,
|
||||
'total_forms' => $fc,
|
||||
'total_entries' => $entry_count,
|
||||
'emails_sent' => GFCommon::get_emails_sent(),
|
||||
'api_calls' => GFCommon::get_api_calls(),
|
||||
'entry_meta_count' => $meta_counts['meta'],
|
||||
'entry_details_count' => $meta_counts['details'],
|
||||
'entry_notes_count' => $meta_counts['notes'],
|
||||
'lang' => $lang,
|
||||
'db' => $db,
|
||||
);
|
||||
|
||||
$installation_telemetry = array(
|
||||
GF_Setup_Wizard_Endpoint_Save_Prefs::PARAM_AUTO_UPDATE,
|
||||
GF_Setup_Wizard_Endpoint_Save_Prefs::PARAM_CURRENCY,
|
||||
GF_Setup_Wizard_Endpoint_Save_Prefs::PARAM_DATA_COLLECTION,
|
||||
GF_Setup_Wizard_Endpoint_Save_Prefs::PARAM_EMAIL,
|
||||
GF_Setup_Wizard_Endpoint_Save_Prefs::PARAM_FORM_TYPES,
|
||||
GF_Setup_Wizard_Endpoint_Save_Prefs::PARAM_FORM_TYPES_OTHER,
|
||||
GF_Setup_Wizard_Endpoint_Save_Prefs::PARAM_HIDE_LICENSE,
|
||||
GF_Setup_Wizard_Endpoint_Save_Prefs::PARAM_ORGANIZATION,
|
||||
GF_Setup_Wizard_Endpoint_Save_Prefs::PARAM_ORGANIZATION_OTHER,
|
||||
GF_Setup_Wizard_Endpoint_Save_Prefs::PARAM_SERVICES,
|
||||
GF_Setup_Wizard_Endpoint_Save_Prefs::PARAM_SERVICES_OTHER,
|
||||
);
|
||||
|
||||
$wizard_endpoint = GFForms::get_service_container()->get( GF_Setup_Wizard_Service_Provider::SAVE_PREFS_ENDPOINT );
|
||||
foreach ( $installation_telemetry as $telem ) {
|
||||
$post[ $telem ] = $wizard_endpoint->get_value( $telem );
|
||||
}
|
||||
|
||||
return $post;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the data from the Gravity Forms settings page
|
||||
*
|
||||
* @since 2.8.3
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_gf_settings() {
|
||||
if ( ! $this->data_collection ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$gform_settings = array();
|
||||
|
||||
$settings_keys = array(
|
||||
'gform_enable_logging',
|
||||
'rg_gforms_default_theme',
|
||||
'gform_enable_toolbar_menu',
|
||||
'gform_enable_noconflict',
|
||||
);
|
||||
|
||||
foreach ( $settings_keys as $key ) {
|
||||
$gform_settings[ $key ] = get_option( $key );
|
||||
}
|
||||
|
||||
return $gform_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of forms with legacy mode enabled.
|
||||
*
|
||||
* @since 2.8.3
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_legacy_forms() {
|
||||
if ( ! $this->data_collection ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$legacy_forms = 0;
|
||||
|
||||
$forms = GFFormsModel::get_forms();
|
||||
foreach ( $forms as $form ) {
|
||||
// if form has legacy mode enabled, add it to the total
|
||||
if ( GFCommon::is_legacy_markup_enabled( $form->id ) ) {
|
||||
$legacy_forms++;
|
||||
}
|
||||
}
|
||||
|
||||
return array( 'legacy_forms' => $legacy_forms );
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the response from the version.php endpoint, to be used by the license service.
|
||||
*
|
||||
* @since 2.8
|
||||
*
|
||||
* @param array $response Raw response from the API endpoint.
|
||||
*/
|
||||
public static function data_sent( $response ) {
|
||||
$version_info = array(
|
||||
'is_valid_key' => '1',
|
||||
'version' => '',
|
||||
'url' => '',
|
||||
'is_error' => '1',
|
||||
);
|
||||
|
||||
if ( is_wp_error( $response ) || rgars( $response, 'response/code' ) != 200 ) {
|
||||
$version_info['timestamp'] = time();
|
||||
|
||||
return $version_info;
|
||||
}
|
||||
|
||||
$decoded = json_decode( $response['body'], true );
|
||||
|
||||
if ( empty( $decoded ) ) {
|
||||
$version_info['timestamp'] = time();
|
||||
|
||||
return $version_info;
|
||||
}
|
||||
|
||||
$decoded['timestamp'] = time();
|
||||
|
||||
update_option( 'gform_version_info', $decoded, false );
|
||||
|
||||
\GFCommon::log_debug( __METHOD__ . sprintf( '(): Version info cached.' ) );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user