AlkantarClanX12
Current Path : /home/thanudqk/thepball.com/wp-content/plugins/google-site-kit/includes/Modules/ |
Current File : /home/thanudqk/thepball.com/wp-content/plugins/google-site-kit/includes/Modules/Analytics_4.php |
<?php /** * Class Google\Site_Kit\Modules\Analytics_4 * * @package Google\Site_Kit * @copyright 2021 Google LLC * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 * @link https://sitekit.withgoogle.com */ namespace Google\Site_Kit\Modules; use Google\Site_Kit\Core\Assets\Asset; use Google\Site_Kit\Core\Assets\Script; use Google\Site_Kit\Core\Authentication\Clients\Google_Site_Kit_Client; use Google\Site_Kit\Core\Modules\Module; use Google\Site_Kit\Core\Modules\Module_Settings; use Google\Site_Kit\Core\Modules\Module_With_Debug_Fields; use Google\Site_Kit\Core\Modules\Module_With_Assets; use Google\Site_Kit\Core\Modules\Module_With_Assets_Trait; use Google\Site_Kit\Core\Modules\Module_With_Scopes; use Google\Site_Kit\Core\Modules\Module_With_Scopes_Trait; use Google\Site_Kit\Core\Modules\Module_With_Settings; use Google\Site_Kit\Core\Modules\Module_With_Settings_Trait; use Google\Site_Kit\Core\Modules\Module_With_Owner; use Google\Site_Kit\Core\Modules\Module_With_Owner_Trait; use Google\Site_Kit\Core\REST_API\Exception\Invalid_Datapoint_Exception; use Google\Site_Kit\Core\REST_API\Data_Request; use Google\Site_Kit\Core\Tags\Guards\Tag_Verify_Guard; use Google\Site_Kit\Core\Util\Debug_Data; use Google\Site_Kit\Core\Util\Method_Proxy_Trait; use Google\Site_Kit\Modules\Analytics\Settings as Analytics_Settings; use Google\Site_Kit\Modules\Analytics_4\Settings; use Google\Site_Kit\Modules\Analytics_4\Tag_Guard; use Google\Site_Kit\Modules\Analytics_4\Web_Tag; use Google\Site_Kit_Dependencies\Google\Model as Google_Model; use Google\Site_Kit_Dependencies\Google_Service_GoogleAnalyticsAdmin; use Google\Site_Kit_Dependencies\Google_Service_GoogleAnalyticsAdmin_GoogleAnalyticsAdminV1alphaProperty; use Google\Site_Kit_Dependencies\Google_Service_GoogleAnalyticsAdmin_GoogleAnalyticsAdminV1alphaWebDataStream; use Google\Site_Kit_Dependencies\Psr\Http\Message\RequestInterface; use WP_Error; /** * Class representing the Analytics 4 module. * * @since 1.30.0 * @access private * @ignore */ final class Analytics_4 extends Module implements Module_With_Scopes, Module_With_Settings, Module_With_Debug_Fields, Module_With_Owner, Module_With_Assets { use Method_Proxy_Trait; use Module_With_Assets_Trait; use Module_With_Owner_Trait; use Module_With_Scopes_Trait; use Module_With_Settings_Trait; /** * Module slug name. */ const MODULE_SLUG = 'analytics-4'; /** * Registers functionality through WordPress hooks. * * @since 1.30.0 */ public function register() { $this->register_scopes_hook(); // Analytics 4 tag placement logic. add_action( 'template_redirect', $this->get_method_proxy( 'register_tag' ) ); } /** * Gets required Google OAuth scopes for the module. * * @since 1.30.0 * * @return array List of Google OAuth scopes. */ public function get_scopes() { return array( 'https://www.googleapis.com/auth/analytics.readonly', ); } /** * Checks whether the module is connected. * * A module being connected means that all steps required as part of its activation are completed. * * @since 1.30.0 * * @return bool True if module is connected, false otherwise. */ public function is_connected() { $required_keys = array( // TODO: These can be uncommented when Analytics and Analytics 4 modules are officially separated. /* 'accountID', */ // phpcs:ignore Squiz.PHP.CommentedOutCode.Found /* 'adsConversionID', */ // phpcs:ignore Squiz.PHP.CommentedOutCode.Found 'propertyID', 'webDataStreamID', 'measurementID', ); $options = $this->get_settings()->get(); foreach ( $required_keys as $required_key ) { if ( empty( $options[ $required_key ] ) ) { return false; } } return parent::is_connected(); } /** * Cleans up when the module is deactivated. * * @since 1.30.0 */ public function on_deactivation() { $this->get_settings()->delete(); } /** * Gets an array of debug field definitions. * * @since 1.30.0 * * @return array */ public function get_debug_fields() { $settings = $this->get_settings()->get(); return array( // phpcs:disable /* TODO: This can be uncommented when Analytics and Analytics 4 modules are officially separated. 'analytics_4_account_id' => array( 'label' => __( 'Analytics 4 account ID', 'google-site-kit' ), 'value' => $settings['accountID'], 'debug' => Debug_Data::redact_debug_value( $settings['accountID'] ), ), 'analytics_4_ads_conversion_id' => array( 'label' => __( 'Analytics 4 ads conversion ID', 'google-site-kit' ), 'value' => $settings['adsConversionID'], 'debug' => Debug_Data::redact_debug_value( $settings['adsConversionID'] ), ), */ // phpcs:enable 'analytics_4_property_id' => array( 'label' => __( 'Analytics 4 property ID', 'google-site-kit' ), 'value' => $settings['propertyID'], 'debug' => Debug_Data::redact_debug_value( $settings['propertyID'], 7 ), ), 'analytics_4_web_data_stream_id' => array( 'label' => __( 'Analytics 4 web data stream ID', 'google-site-kit' ), 'value' => $settings['webDataStreamID'], 'debug' => Debug_Data::redact_debug_value( $settings['webDataStreamID'] ), ), 'analytics_4_measurement_id' => array( 'label' => __( 'Analytics 4 measurement ID', 'google-site-kit' ), 'value' => $settings['measurementID'], 'debug' => Debug_Data::redact_debug_value( $settings['measurementID'] ), ), 'analytics_4_use_snippet' => array( 'label' => __( 'Analytics 4 snippet placed', 'google-site-kit' ), 'value' => $settings['useSnippet'] ? __( 'Yes', 'google-site-kit' ) : __( 'No', 'google-site-kit' ), 'debug' => $settings['useSnippet'] ? 'yes' : 'no', ), ); } /** * Gets map of datapoint to definition data for each. * * @since 1.30.0 * * @return array Map of datapoints to their definitions. */ protected function get_datapoint_definitions() { return array( 'GET:account-summaries' => array( 'service' => 'analyticsadmin' ), 'GET:accounts' => array( 'service' => 'analyticsadmin' ), 'POST:create-property' => array( 'service' => 'analyticsadmin', 'scopes' => array( 'https://www.googleapis.com/auth/analytics.edit' ), 'request_scopes_message' => __( 'You’ll need to grant Site Kit permission to create a new Analytics 4 property on your behalf.', 'google-site-kit' ), ), 'POST:create-webdatastream' => array( 'service' => 'analyticsadmin', 'scopes' => array( 'https://www.googleapis.com/auth/analytics.edit' ), 'request_scopes_message' => __( 'You’ll need to grant Site Kit permission to create a new Analytics 4 web data stream on your behalf.', 'google-site-kit' ), ), 'GET:properties' => array( 'service' => 'analyticsadmin' ), 'GET:property' => array( 'service' => 'analyticsadmin' ), 'GET:webdatastreams' => array( 'service' => 'analyticsadmin' ), 'GET:webdatastreams-batch' => array( 'service' => 'analyticsadmin' ), ); } /** * Creates a request object for the given datapoint. * * @since 1.30.0 * * @param Data_Request $data Data request object. * @return RequestInterface|callable|WP_Error Request object or callable on success, or WP_Error on failure. * * @throws Invalid_Datapoint_Exception Thrown if the datapoint does not exist. */ protected function create_data_request( Data_Request $data ) { switch ( "{$data->method}:{$data->datapoint}" ) { case 'GET:accounts': return $this->get_service( 'analyticsadmin' )->accounts->listAccounts(); case 'GET:account-summaries': return $this->get_service( 'analyticsadmin' )->accountSummaries->listAccountSummaries( array( 'pageSize' => 200 ) ); case 'POST:create-property': if ( ! isset( $data['accountID'] ) ) { return new WP_Error( 'missing_required_param', /* translators: %s: Missing parameter name */ sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'accountID' ), array( 'status' => 400 ) ); } $property = new Google_Service_GoogleAnalyticsAdmin_GoogleAnalyticsAdminV1alphaProperty(); $property->setParent( self::normalize_account_id( $data['accountID'] ) ); $property->setDisplayName( wp_parse_url( $this->context->get_reference_site_url(), PHP_URL_HOST ) ); return $this->get_service( 'analyticsadmin' )->properties->create( $property ); case 'POST:create-webdatastream': if ( ! isset( $data['propertyID'] ) ) { return new WP_Error( 'missing_required_param', /* translators: %s: Missing parameter name */ sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'propertyID' ), array( 'status' => 400 ) ); } $datastream = new Google_Service_GoogleAnalyticsAdmin_GoogleAnalyticsAdminV1alphaWebDataStream(); $datastream->setDisplayName( wp_parse_url( $this->context->get_reference_site_url(), PHP_URL_HOST ) ); $datastream->setDefaultUri( $this->context->get_reference_site_url() ); return $this->get_service( 'analyticsadmin' )->properties_webDataStreams->create( self::normalize_property_id( $data['propertyID'] ), $datastream ); case 'GET:properties': if ( ! isset( $data['accountID'] ) ) { return new WP_Error( 'missing_required_param', /* translators: %s: Missing parameter name */ sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'accountID' ), array( 'status' => 400 ) ); } return $this->get_service( 'analyticsadmin' )->properties->listProperties( array( 'filter' => 'parent:' . self::normalize_account_id( $data['accountID'] ), ) ); case 'GET:property': if ( ! isset( $data['propertyID'] ) ) { return new WP_Error( 'missing_required_param', /* translators: %s: Missing parameter name */ sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'propertyID' ), array( 'status' => 400 ) ); } return $this->get_service( 'analyticsadmin' )->properties->get( self::normalize_property_id( $data['propertyID'] ) ); case 'GET:webdatastreams': if ( ! isset( $data['propertyID'] ) ) { return new WP_Error( 'missing_required_param', /* translators: %s: Missing parameter name */ sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'propertyID' ), array( 'status' => 400 ) ); } return $this->get_service( 'analyticsadmin' )->properties_webDataStreams->listPropertiesWebDataStreams( self::normalize_property_id( $data['propertyID'] ) ); case 'GET:webdatastreams-batch': if ( ! isset( $data['propertyIDs'] ) ) { return new WP_Error( 'missing_required_param', /* translators: %s: Missing parameter name */ sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'propertyIDs' ), array( 'status' => 400 ) ); } if ( ! is_array( $data['propertyIDs'] ) || count( $data['propertyIDs'] ) > 10 ) { return new WP_Error( 'rest_invalid_param', /* translators: %s: List of invalid parameters. */ sprintf( __( 'Invalid parameter(s): %s', 'google-site-kit' ), 'propertyIDs' ), array( 'status' => 400 ) ); } return function() use ( $data ) { $requests = array(); foreach ( $data['propertyIDs'] as $property_id ) { $requests[] = new Data_Request( 'GET', 'modules', self::MODULE_SLUG, 'webdatastreams', array( 'propertyID' => $property_id ), $property_id ); } return $this->get_batch_data( $requests ); }; } return parent::create_data_request( $data ); } /** * Parses a response for the given datapoint. * * @since 1.30.0 * * @param Data_Request $data Data request object. * @param mixed $response Request response. * * @return mixed Parsed response data on success, or WP_Error on failure. */ protected function parse_data_response( Data_Request $data, $response ) { switch ( "{$data->method}:{$data->datapoint}" ) { case 'GET:accounts': return array_map( array( self::class, 'filter_account_with_ids' ), $response->getAccounts() ); case 'GET:account-summaries': return array_map( function( $account ) { $obj = self::filter_account_with_ids( $account, 'account' ); $obj->propertySummaries = array_map( // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase function( $property ) { return self::filter_property_with_ids( $property, 'property' ); }, $account->getPropertySummaries() ); return $obj; }, $response->getAccountSummaries() ); case 'POST:create-property': return self::filter_property_with_ids( $response ); case 'POST:create-webdatastream': return self::filter_webdatastream_with_ids( $response ); case 'GET:properties': return array_map( array( self::class, 'filter_property_with_ids' ), $response->getProperties() ); case 'GET:property': return self::filter_property_with_ids( $response ); case 'GET:webdatastreams': return array_map( array( self::class, 'filter_webdatastream_with_ids' ), $response->getWebDataStreams() ); } return parent::parse_data_response( $data, $response ); } /** * Sets up information about the module. * * @since 1.30.0 * * @return array Associative array of module info. */ protected function setup_info() { return array( 'slug' => self::MODULE_SLUG, 'name' => _x( 'Analytics 4 (Alpha)', 'Service name', 'google-site-kit' ), 'description' => __( 'Get a deeper understanding of your customers. Google Analytics gives you the free tools you need to analyze data for your business in one place.', 'google-site-kit' ), 'cta' => __( 'Get to know your customers.', 'google-site-kit' ), 'order' => 3, 'homepage' => __( 'https://analytics.google.com/analytics/web', 'google-site-kit' ), 'learn_more' => __( 'https://marketingplatform.google.com/about/analytics/', 'google-site-kit' ), 'internal' => true, ); } /** * Sets up the Google services the module should use. * * This method is invoked once by {@see Module::get_service()} to lazily set up the services when one is requested * for the first time. * * @since 1.30.0 * * @param Google_Site_Kit_Client $client Google client instance. * @return array Google services as $identifier => $service_instance pairs. Every $service_instance must be an * instance of Google_Service. */ protected function setup_services( Google_Site_Kit_Client $client ) { return array( 'analyticsadmin' => new Google_Service_GoogleAnalyticsAdmin( $client ), ); } /** * Sets up the module's settings instance. * * @since 1.30.0 * * @return Module_Settings */ protected function setup_settings() { return new Settings( $this->options ); } /** * Sets up the module's assets to register. * * @since 1.31.0 * * @return Asset[] List of Asset objects. */ protected function setup_assets() { $base_url = $this->context->url( 'dist/assets/' ); return array( new Script( 'googlesitekit-modules-analytics-4', array( 'src' => $base_url . 'js/googlesitekit-modules-analytics-4.js', 'dependencies' => array( 'googlesitekit-vendor', 'googlesitekit-api', 'googlesitekit-data', 'googlesitekit-modules', 'googlesitekit-datastore-site', 'googlesitekit-datastore-forms', ), ) ), ); } /** * Registers the Analytics 4 tag. * * @since 1.31.0 */ private function register_tag() { if ( $this->context->is_amp() ) { return; } $settings = $this->get_settings()->get(); $tag = new Web_Tag( $settings['measurementID'], self::MODULE_SLUG ); if ( $tag->is_tag_blocked() ) { return; } $tag->use_guard( new Tag_Verify_Guard( $this->context->input() ) ); $tag->use_guard( new Tag_Guard( $this->get_settings() ) ); if ( $tag->can_register() ) { // Here we need to retrieve the ads conversion ID from the // classic/UA Analytics settings as it does not exist yet for this module. // TODO: Update the value to be sourced from GA4 module settings once decoupled. $ua_settings = ( new Analytics_Settings( $this->options ) )->get(); $tag->set_ads_conversion_id( $ua_settings['adsConversionID'] ); $tag->register(); } } /** * Parses account ID, adds it to the model object and returns updated model. * * @since 1.31.0 * * @param Google_Model $account Account model. * @param string $id_key Attribute name that contains account id. * @return \stdClass Updated model with _id attribute. */ public static function filter_account_with_ids( $account, $id_key = 'name' ) { $obj = $account->toSimpleObject(); $matches = array(); if ( preg_match( '#accounts/([^/]+)#', $account[ $id_key ], $matches ) ) { $obj->_id = $matches[1]; } return $obj; } /** * Parses account and property IDs, adds it to the model object and returns updated model. * * @since 1.31.0 * * @param Google_Model $property Property model. * @param string $id_key Attribute name that contains property id. * @return \stdClass Updated model with _id and _accountID attributes. */ public static function filter_property_with_ids( $property, $id_key = 'name' ) { $obj = $property->toSimpleObject(); $matches = array(); if ( preg_match( '#properties/([^/]+)#', $property[ $id_key ], $matches ) ) { $obj->_id = $matches[1]; } $matches = array(); if ( preg_match( '#accounts/([^/]+)#', $property['parent'], $matches ) ) { $obj->_accountID = $matches[1]; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase } return $obj; } /** * Parses property and web datastream IDs, adds it to the model object and returns updated model. * * @since 1.31.0 * * @param Google_Model $webdatastream Web datastream model. * @return \stdClass Updated model with _id and _propertyID attributes. */ public static function filter_webdatastream_with_ids( $webdatastream ) { $obj = $webdatastream->toSimpleObject(); $matches = array(); if ( preg_match( '#properties/([^/]+)/webDataStreams/([^/]+)#', $webdatastream['name'], $matches ) ) { $obj->_id = $matches[2]; $obj->_propertyID = $matches[1]; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase } return $obj; } /** * Normalizes account ID and returns it. * * @since 1.31.0 * * @param string $account_id Account ID. * @return string Updated account ID with "accounts/" prefix. */ public static function normalize_account_id( $account_id ) { return 'accounts/' . $account_id; } /** * Normalizes property ID and returns it. * * @since 1.31.0 * * @param string $property_id Property ID. * @return string Updated property ID with "properties/" prefix. */ public static function normalize_property_id( $property_id ) { return 'properties/' . $property_id; } }