File: /var/www/shoetique/wp-content/plugins/googleanalytics/class/class-ga-helper.php
<?php
/**
* GoogleAnalytics Helper.
*
* @package GoogleAnalytics
*/
/**
* Helper class.
*/
class Ga_Helper {
const ROLE_ID_PREFIX = 'role-id-';
const GA_DEFAULT_WEB_ID = 'UA-0000000-0';
const GA_STATISTICS_PAGE_URL = 'admin.php?page=googleanalytics';
const GA_SETTINGS_PAGE_URL = 'admin.php?page=googleanalytics/settings';
const DASHBOARD_PAGE_NAME = 'admin.php?page=googleanalytics';
const PHP_VERSION_REQUIRED = '7.4';
const GA_WP_MODERN_VERSION = '4.1';
const GA_TOOLTIP_TERMS_NOT_ACCEPTED = 'Please accept the terms to use this feature.';
const GA_TOOLTIP_FEATURES_DISABLED = 'Click the Enable button at the top to start using this feature.';
const GA_DEBUG_MODE = false;
/**
* Init plugin actions.
*/
public static function init() {
// Displays errors related to required PHP version.
if ( false === self::is_php_version_valid() ) {
add_action( 'admin_notices', 'Ga_Admin::admin_notice_googleanalytics_php_version' );
return false;
}
// Displays errors related to required WP version.
if ( false === self::is_wp_version_valid() ) {
add_action( 'admin_notices', 'Ga_Admin::admin_notice_googleanalytics_wp_version' );
return false;
}
if ( ! is_admin() ) {
Ga_Frontend::add_actions();
}
if ( is_admin() ) {
Ga_Admin::add_filters();
Ga_Admin::add_actions();
Ga_Admin::init_oauth();
$admin_controller = new Ga_Admin_Controller();
$admin_controller->handle_actions();
}
}
/**
* Checks if current page is a WordPress dashboard.
*
* @return integer
*/
public static function is_plugin_page() {
$page = filter_input( INPUT_GET, 'page', FILTER_UNSAFE_RAW );
$page_split = explode( '/', sanitize_text_field( wp_unslash( $page ) ) );
if ( false === empty( $page_split ) && true === isset( $page_split[0] ) ) {
return GA_NAME === $page_split[0];
}
return false;
}
/**
* Checks if current page is a WordPress dashboard.
*
* @return number
*/
public static function is_dashboard_page() {
$site = get_current_screen();
return preg_match( '/' . self::DASHBOARD_PAGE_NAME . '/', $site->base );
}
/**
* Check whether the plugin is configured.
*
* @param string $web_id Web ID string.
*
* @return boolean
*/
public static function is_configured( $web_id ) {
return self::GA_DEFAULT_WEB_ID !== $web_id && false === empty( $web_id );
}
/**
* Prepare an array of current site's user roles
*
* @return array
*/
public static function get_user_roles() {
global $wp_roles;
if ( false === isset( $wp_roles ) ) {
$wp_roles = new WP_Roles(); // phpcs:ignore
}
return $wp_roles->get_names();
}
/**
* Prepare a role ID.
*
* The role ID is derived from the role's name and will be used
* in its setting name in the additional settings.
*
* @param string $role_name Role name.
*
* @return string
*/
public static function prepare_role_id( $role_name ) {
return self::ROLE_ID_PREFIX . strtolower( preg_replace( '/[\W]/', '-', before_last_bar( $role_name ) ) );
}
/**
* Prepares role id.
*
* @param string $v Value string.
* @param string $k Key string.
*/
public static function prepare_role( &$v, $k ) {
$v = self::prepare_role_id( $v );
}
/**
* Checks whether user role is excluded from adding UA code.
*
* @return boolean
*/
public static function can_add_ga_code() {
$current_user = wp_get_current_user();
$user_roles = ! empty( $current_user->roles ) ? $current_user->roles : array();
$exclude_roles = json_decode( get_option( Ga_Admin::GA_EXCLUDE_ROLES_OPTION_NAME ), true );
array_walk( $user_roles, 'Ga_Helper::prepare_role' );
$return = true;
foreach ( $user_roles as $role ) {
if ( ! empty( $exclude_roles[ $role ] ) ) {
$return = false;
break;
}
}
return $return;
}
/**
* Adds ga dashboard widget HTML code for a WordPress Dashboard widget hook.
*/
public static function add_ga_dashboard_widget() {
$widget = self::get_ga_dashboard_widget(
null,
false,
false,
true
);
echo wp_kses(
$widget,
array(
'a' => array(
'href' => array(),
),
'button' => array(
'class' => array(),
'id' => array(),
'style' => array(),
),
'div' => array(
'class' => array(),
'id' => array(),
'style' => array(),
),
'select' => array(
'id' => array(),
'autocomplete' => array(),
),
'script' => array(
'type' => array(),
),
'option' => array(
'value' => array(),
'selected' => array(),
),
)
);
}
/**
* Generates dashboard widget HTML code.
*
* @param string $date_range Google Analytics specific date range string.
* @param boolean $text_mode Text mode.
* @param boolean $ajax Ajax.
* @param boolean $trigger_request Trigger request.
*
* @return null | string HTML dashboard widget code.
*/
public static function get_ga_dashboard_widget(
$date_range = null,
$text_mode = false,
$ajax = false,
$trigger_request = false
) {
if ( empty( $date_range ) ) {
$date_range = '30daysAgo';
}
if ( false === $trigger_request ) {
// Get chart and boxes data.
$data = self::get_dashboard_widget_data( $date_range );
if ( $text_mode ) {
return self::get_chart_page(
'ga-dashboard-widget' . ( $ajax ? '_ajax' : '' ),
array(
'chart' => $data['chart'],
'boxes' => $data['boxes'],
)
);
} else {
return self::get_chart_page(
'ga-dashboard-widget' . ( $ajax ? '_ajax' : '' ),
array(
'chart' => $data['chart'],
'boxes' => $data['boxes'],
'more_details_url' => admin_url( self::GA_STATISTICS_PAGE_URL ),
'ga_nonce' => wp_create_nonce( 'ga_ajax_data_change' ),
'ga_nonce_name' => Ga_Admin_Controller::GA_NONCE_FIELD_NAME,
)
);
}
} else {
return self::get_chart_page(
'ga-dashboard-widget' . ( $ajax ? '_ajax' : '' ),
array(
'chart' => array(),
'boxes' => Ga_Stats::get_empty_boxes_structure(),
'more_details_url' => admin_url( self::GA_STATISTICS_PAGE_URL ),
'show_trigger_button' => true,
'ga_nonce' => wp_create_nonce( 'ga_ajax_data_change' ),
'ga_nonce_name' => Ga_Admin_Controller::GA_NONCE_FIELD_NAME,
)
);
}
return null;
}
/**
* Generates JSON data string for AJAX calls.
*
* @param string $date_range Date range.
* @param string $metric Metric string.
* @param boolean $text_mode Text mode.
* @param boolean $ajax Ajax.
*
* @return string|false Returns JSON data string
*/
public static function get_ga_dashboard_widget_data_json(
$date_range = null, $metric = null, $text_mode = false, $ajax = false
) {
if ( empty( $date_range ) ) {
$date_range = '30daysAgo';
}
if ( empty( $metric ) ) {
$metric = 'pageviews';
}
$data = self::get_dashboard_widget_data( $date_range, $metric );
return wp_json_encode( $data );
}
/**
* Gets dashboard widget data.
*
* @param string $date_range Date range string.
* @param string $metric Metric.
*
* @return array Return chart and boxes data
*/
private static function get_dashboard_widget_data( $date_range, $metric = null ) {
$selected = self::get_selected_account_data( true );
if ( self::is_authorized() && self::is_account_selected() ) {
$query_params = Ga_Stats::get_query( 'main_chart', $selected['view_id'], $date_range, $metric, true );
$stats_data = Ga_Admin::api_client()->call(
'ga_api_data',
array(
$query_params,
)
);
$boxes_query = Ga_Stats::get_query( 'dashboard_boxes', $selected['view_id'], $date_range, null, true );
$boxes_data = Ga_Admin::api_client()->call(
'ga_api_data',
array(
$boxes_query,
)
);
}
$chart = ! empty( $stats_data ) ? Ga_Stats::get_dashboard_chart( $stats_data->get_data() ) : array();
$boxes = ! empty( $boxes_data ) ? Ga_Stats::get_dashboard_boxes_data( $boxes_data->get_data() ) : array();
return array(
'chart' => $chart,
'boxes' => $boxes,
);
}
/**
* Is account selected?
*
* @return bool
*/
public static function is_account_selected() {
return false === empty( self::get_selected_account_data() );
}
/**
* Returns HTML code of the chart page or a notice.
*
* @param string $view View string.
* @param array $params Params array.
*
* @return string Returns HTML code
*/
public static function get_chart_page( $view, $params ) {
$message = sprintf(
/* translators: %s is the settings page URL. */
__( 'Statistics can only be seen after you authenticate with your Google account on the <a href="%s">Settings page</a>.' ),
admin_url( self::GA_SETTINGS_PAGE_URL )
);
$ga4_property = get_option('googleanalytics-ga4-property');
if ( (true === self::is_authorized() && false === self::is_code_manually_enabled() && false === self::is_all_feature_disabled()) || false === empty($ga4_property) ) {
if ( true === self::is_account_selected() || true === isset($ga4_property)) {
if ( false === empty( $params ) ) {
return Ga_View_Core::load( $view, $params, true );
} else {
return self::ga_oauth_notice( sprintf( 'Please configure your <a href="%s">Google Analytics settings</a>.', admin_url( self::GA_SETTINGS_PAGE_URL ) ) );
}
} else {
return self::ga_oauth_notice( $message );
}
} else {
return self::ga_oauth_notice( $message );
}
}
/**
* Checks whether users is authorized with Google.
*
* @return boolean
*/
public static function is_authorized() {
return Ga_Admin::api_client()->get_instance()->is_authorized();
}
/**
* Wrapper for WordPress method get_option
*
* @param string $name Option name.
* @param mixed|null $default Default value if fetched option is null.
*
* @return mixed|null
*/
public static function get_option( $name, $default = null ) {
$opt = get_option( $name, $default );
return false === empty( $opt ) ? $opt : $default;
}
/**
* Wrapper for WordPress method update_option
*
* @param string $name Option name.
* @param mixed $value Option value.
*
* @return null|boolean
*/
public static function update_option( $name, $value ) {
$opt = update_option( $name, $value );
return ! empty( $opt ) ? $opt : null;
}
/**
* Loads ga notice HTML code with given message included.
*
* @param string $message Message.
*
* @return string
*/
public static function ga_oauth_notice( $message ) {
return Ga_View_Core::load(
'ga-oauth-notice',
array(
'msg' => $message,
),
true
);
}
/**
* Displays notice following the WP style.
*
* @param string $message Message string.
* @param string $type Type string.
* @param bool $is_dismissable Whether the notice is dismissable.
* @param string $action Action type.
*
* @return string
*/
public static function ga_wp_notice( $message, $type = '', $is_dismissable = false, $action = array() ) {
return Ga_View_Core::load(
'ga-wp-notice',
array(
'notice_type' => empty( $type ) ? Ga_Admin::NOTICE_WARNING : $type,
'msg' => $message,
'is_dismissable' => $is_dismissable,
'action' => $action,
),
true
);
}
/**
* Gets data according to selected GA account.
*
* @param boolean $assoc Whether the return should be an associative array.
*
* @return mixed
*/
public static function get_selected_account_data( $assoc = false ) {
$data = self::get_option( Ga_Admin::GA_SELECTED_ACCOUNT );
$data = ( false === empty( $data ) && 3 === count( $data ) ) ? json_decode( $data ) : false;
if ( $data ) {
if ( $assoc ) {
return array(
'account_id' => $data[0],
'web_property_id' => $data[1],
'view_id' => $data[2],
);
} else {
return $data;
}
}
return false;
}
/**
* Checks whether option for manually UA-code.
*
* @return boolean
*/
public static function is_code_manually_enabled() {
return boolval( self::get_option( Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME, false ) );
}
/**
* Adds percent sign to the given text.
*
* @param string $text Text string to format as a percentage.
*
* @return string
*/
public static function format_percent( $text ) {
$text = self::add_plus( $text );
return $text . '%';
}
/**
* Adds plus sign before number.
*
* @param string $number Number string.
*
* @return string
*/
public static function add_plus( $number ) {
if ( $number > 0 ) {
return '+' . $number;
}
return $number;
}
/**
* Check whether current user has administrator privileges.
*
* @return bool
*/
public static function is_administrator() {
if ( current_user_can( 'administrator' ) ) {
return true;
}
return false;
}
/**
* Is this WordPress version valid?
*
* @return bool|int
*/
public static function is_wp_version_valid() {
$wp_version = get_bloginfo( 'version' );
return version_compare( $wp_version, Ga_Admin::MIN_WP_VERSION, 'ge' );
}
/**
* Check if terms are accepted.
*
* @return bool
*/
public static function are_terms_accepted() {
return boolval( self::get_option( Ga_Admin::GA_SHARETHIS_TERMS_OPTION_NAME ) );
}
/**
* Check if sharethis scripts enabled.
*
* @return bool
*/
public static function is_sharethis_included() {
return boolval( GA_SHARETHIS_SCRIPTS_INCLUDED );
}
/**
* Is this PHP version valid?
*
* @return mixed
*/
public static function is_php_version_valid() {
$p = '#(\.0+)+($|-)#';
$ver1 = preg_replace( $p, '', phpversion() );
$ver2 = preg_replace( $p, '', self::PHP_VERSION_REQUIRED );
$operator = 'ge';
return version_compare( $ver1, $ver2, $operator );
}
/**
* Get current URL.
*
* @return mixed
*/
public static function get_current_url() {
return filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL );
}
/**
* Create URL.
*
* @param string $url URL.
* @param array $data Data array.
*
* @return mixed|string
*/
public static function create_url( $url, $data = array() ) {
return false === empty( $data ) ?
( strstr( $url, '?' ) ?
( $url . '&' ) :
( $url . '?' ) ) . http_build_query( $data ) :
$url;
}
/**
* Create base64 url message
*
* @param string $msg Message.
* @param string $status Status.
*
* @return string
*/
public static function create_url_msg( $msg, $status ) {
$msg = array(
'status' => $status,
'message' => $msg,
);
return base64_encode( wp_json_encode( $msg ) ); // phpcs:ignore
}
/**
* Are all features disabled?
*
* @return bool
*/
public static function is_all_feature_disabled() {
return boolval( self::get_option( Ga_Admin::GA_DISABLE_ALL_FEATURES, false ) );
}
/**
* Are features enabled?
*
* @return bool
*/
public static function are_features_enabled() {
return true === self::are_terms_accepted() && false === self::is_all_feature_disabled();
}
/**
* Are ShareThis properties verified?
*
* @return bool
*/
public static function are_sharethis_properties_verified() {
return (
false !== get_option( Ga_Admin::GA_SHARETHIS_VERIFICATION_RESULT )
&& true === self::are_sharethis_properties_set()
);
}
/**
* Are ShareThis properties ready to verify?
*
* @return bool
*/
public static function are_sharethis_properties_ready_to_verify() {
return (
true === self::are_sharethis_properties_set()
&& false === get_option( Ga_Admin::GA_SHARETHIS_VERIFICATION_RESULT )
);
}
/**
* Are ShareThis properties set?
*
* @return bool
*/
public static function are_sharethis_properties_set() {
return (
false !== get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_ID ) &&
false !== get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_SECRET )
);
}
/**
* Should we create the ShareThis property?
*
* @return bool
*/
public static function should_create_sharethis_property() {
return true === self::are_features_enabled() && false === self::are_sharethis_properties_set();
}
/**
* Should we verify the ShareThis installation?
*
* @return bool
*/
public static function should_verify_sharethis_installation() {
return true === self::are_features_enabled() && true === self::are_sharethis_properties_ready_to_verify();
}
/**
* Get tooltip.
*
* @return string
*/
public static function get_tooltip() {
if ( false === self::are_terms_accepted() ) {
return self::GA_TOOLTIP_TERMS_NOT_ACCEPTED;
} elseif ( false === self::are_features_enabled() ) {
return self::GA_TOOLTIP_FEATURES_DISABLED;
} else {
return '';
}
}
/**
* Is this version of WordPress considered old (< 4.1)?
*
* @return bool True if old, False if not.
*/
public static function is_wp_old() {
return version_compare( get_bloginfo( 'version' ), self::GA_WP_MODERN_VERSION, 'lt' );
}
/**
* Should we load GA JavaScript on this property?
*
* @param string $web_property_id Web property ID.
*
* @return bool
*/
public static function should_load_ga_javascript( $web_property_id ) {
return true === self::is_configured( $web_property_id )
&& (
true === self::can_add_ga_code()
|| true === self::is_all_feature_disabled()
);
}
/**
* Get account ID.
*
* @return string
*/
public static function get_account_id() {
$account_id = self::get_option( Ga_Admin::GA_SELECTED_ACCOUNT );
return false === empty( $account_id ) ? json_decode( $account_id )[0] : '';
}
/**
* Is curl disabled?
*
* @return bool True if disabled, false if enabled.
*/
public static function is_curl_disabled() {
return ! function_exists( 'curl_version' );
}
/**
* Get URL with correct protocol.
*
* @return string URL with correct protocol.
*/
public static function get_plugin_url_with_correct_protocol() {
return GA_PLUGIN_URL;
}
/**
* Get code to manually label classes.
*
* @return string
*/
public static function get_code_manually_label_classes() {
$classes = '';
if ( ! self::are_features_enabled() ) {
$classes = 'label-grey ga-tooltip';
} elseif ( self::is_account_selected() ) {
$classes = 'label-grey';
}
return $classes;
}
/**
* Get Previous Period for Dates (date start and date end).
*
* @param string $date_start Date string.
* @param string $date_end Date string.
*
* @return array Array of start and end dates in Y-m-d format.
* @since 2.5.2
*/
public static function get_previous_period_for_dates( $date_start = '', $date_end = '' ) {
try {
// Get distance between dates in days.
$start = new DateTime( $date_start );
$end = new DateTime( $date_end );
} catch ( \Exception $e ) {
return array(
'start' => gmdate( 'Y-m-d', strtotime( '-1 week' ) ),
'end' => gmdate( 'Y-m-d' ),
);
}
// Clone $start date into end_previous so we don't modify $start.
$end_previous = clone $start;
// Set the period to the difference between the start/end dates in days.
$period = $end->diff( $start )->days;
// Subtract 1 day from $end_previous so it's one day before $start.
$end_previous->modify( '-1 day' );
// Clone $end_previous so we can subtract $period from it in days.
$start_previous = clone $end_previous;
$start_previous->modify( sprintf( '-%d day', $period ) );
return array(
'start' => $start_previous->format( 'Y-m-d' ),
'end' => $end_previous->format( 'Y-m-d' ),
);
}
/**
* Get period between dates in days.
*
* @param string $date_start Start date string.
* @param string $date_end End date string.
*
* @return int
* @since 2.5.2
*/
public static function get_period_in_days( $date_start = '', $date_end = '' ) {
$date_start = empty( $date_start ) ? gmdate( 'Y-m-d', strtotime( '-1 week' ) ) : $date_start;
$date_end = empty( $date_end ) ? gmdate( 'Y-m-d' ) : $date_end;
try {
// Get distance between dates in days.
$start = new DateTime( $date_start );
$end = new DateTime( $date_end );
} catch ( \Exception $e ) {
return 0;
}
// Set the period to the difference between the start/end dates in days.
return intval( $start->diff( $end )->format( '%r%a' ) );
}
/**
* Get period in Days as words.
*
* @param string $date_start Start date string.
* @param string $date_end End date string.
*
* @return string Words to indicate days.
* @since 2.5.2
*/
public static function get_period_in_days_words( $date_start = '', $date_end = '' ) {
$days = self::get_period_in_days( $date_start, $date_end );
$date_end = empty( $date_end ) ? strtotime( 'now' ) : strtotime( $date_end );
// If today is the same as the end date.
if ( gmdate( 'Y-m-d', $date_end ) === gmdate( 'Y-m-d' ) ) {
if ( 0 === $days ) {
return __( 'Today', 'googleanalytics' );
}
if ( 7 === $days ) {
return __( 'This Week', 'googleanalytics' );
}
return sprintf(
/* translators: %d stands for the Day or Days. */
_n( 'Last %d Day', 'Last %d Days', $days, 'googleanalytics' ),
$days
);
}
return sprintf(
/* translators: %d stands for the Day or Days. */
_n( '%d Day', '%d Days', $days, 'googleanalytics' ),
$days
);
}
/**
* Get date range from GET request.
*
* @return array
* @since 2.5.2
*/
public static function get_date_range_from_request() {
$date_range = filter_input_array(
INPUT_GET,
array(
'date_from' => FILTER_UNSAFE_RAW,
'date_to' => FILTER_UNSAFE_RAW,
)
);
// If date_from is after date_to, let's reset 'from' to a week before 'to'.
if ( 0 > self::get_period_in_days( $date_range['date_from'], $date_range['date_to'] ) ) {
try {
$date = new DateTime( $date_range['date_to'] );
$date->modify( '-1 week' );
$date_from = $date->format( 'Y-m-d' );
} catch ( \Exception $e ) {
$date_from = gmdate( 'Y-m-d', strtotime( '-1 week' ) );
}
$date_range['date_from'] = $date_from;
}
return array(
'from' => $date_range['date_from'],
'to' => $date_range['date_to'],
);
}
}