*/ class Helpers { /** * Get page type. * * @since 2.0.0 * @return string */ public static function get_page_type() { $page_type = 'notfound'; if ( is_home() || is_front_page() ) { $page_type = 'home'; } elseif ( is_page() ) { $page_type = 'page'; } elseif ( is_single() ) { $page_type = 'article'; } elseif ( is_category() ) { $page_type = 'category'; } elseif ( is_tag() ) { $page_type = 'tag'; } elseif ( is_tax() ) { $page_type = 'tax'; } elseif ( is_archive() ) { $page_type = 'archive'; } elseif ( is_search() ) { $page_type = 'search'; } elseif ( is_404() ) { $page_type = 'notfound'; } return $page_type; } /** * Get page url. * * @since 2.0.0 * @return string */ public static function get_url() { return esc_url_raw( self::get_server_details()['host'] . self::get_server_details()['uri'] ); } /** * Get all options for FastCmp * * @since 2.2.0 * @param bool $light If true, return only the light options. * @return array{name: string, enabled: boolean, headOffice: string, logo: string, privacyPolicy: string, targetedAudience: string, excludedIabVendors: array, excludedGoogleVendors: array, stubLight: string, vendors: array, uuid: string, customsVendor: array{name: string, id: string}, acceptButtonStyle: array{bg: string, font: string}, declineButtonStyle: array{bg: string, font: string, border: string}, parametersButtonStyle: array{bg: string, font: string, border: string}, customStyle: string, consentV2: string, googleTagsStatus: string, googleAdStorage: string, googleAnalyticsStorage: string, googlePersonalizationStorage: string, googleFunctionalityStorage: string, googleSecurityStorage: string, googleAdPersonalization: string, googleAdUserData: string, googleSpecificEnabled: string, googleSpecificData: string} */ public static function get_fastcmp_options( $light ) { $default_country_code = substr( get_bloginfo( 'language', 'raw' ), 3 ); /** @var string $image */ $image = Options::get( 'fastcmp-logo', '' ); if ( $image === '' ) { /** @var int|boolean $logo_id */ $logo_id = get_theme_mod( 'custom_logo' ); if ( $logo_id ) { /** @var int $logo_id */ $image_attachment = wp_get_attachment_image_src( $logo_id, 'full' ); if ( $image_attachment !== false && count( $image_attachment ) > 0 ) { /** @var string $image */ $image = $image_attachment[0]; } } } $privacy_policy_option = Options::get( 'fastcmp-privacypolicy', '' ); if ( function_exists( 'get_privacy_policy_url' ) ) { /** @var string $privacy_policy */ $privacy_policy = get_privacy_policy_url(); } else { $privacy_policy = ''; } /** @var string $privacy_policy */ $privacy_policy = $privacy_policy_option === '' ? $privacy_policy : $privacy_policy_option; /** @var string $name */ $name = Options::get( 'fastcmp-name', get_bloginfo( 'name', 'raw' ) ); /** @var boolean $enabled */ $enabled = Options::get( 'fastcmp-enabled', null ); /** @var string $head_office */ $head_office = Options::get( 'fastcmp-headoffice', $default_country_code ); /** @var array $excluded_iab_vendors */ $excluded_iab_vendors = Options::get( 'fastcmp-excludediabvendors', array() ); /** @var array $excluded_google_vendors */ $excluded_google_vendors = Options::get( 'fastcmp-excludedgooglevendors', array() ); /** @var string $stub_light */ $stub_light = Options::get( 'fastcmp-stub-light', '' ); /** @var string $targeted_audience */ $targeted_audience = Options::get( 'fastcmp-targetedaudience', 'tcfeuv2' ); /** @var array $vendors */ $vendors = $light ? array() : Options::get( 'fastcmp-vendors', array() ); /** @var string $uuid */ $uuid = Options::get( 'fastcmp-uuid', '' ); /** @var array{name: string, id: string} $customs_vendor */ $customs_vendor = Options::get( 'fastcmp-customsvendor', array() ); /** @var array{bg: string, font: string} $accept_button_style */ $accept_button_style = Options::get( 'fastcmp-acceptButtonStyle', array( 'bg' => 'transparent', 'font' => '#6f6f6f', ) ); /** @var string $accept_button_style_string */ $accept_button_style_string = wp_json_encode( $accept_button_style ); /** @var array{bg: string, font: string} $accept_button_style */ $accept_button_style = json_decode( $accept_button_style_string, true ); /** @var array{bg: string, font: string, border: string} $decline_button_style */ $decline_button_style = Options::get( 'fastcmp-declineButtonStyle', array( 'bg' => 'transparent', 'font' => '#6f6f6f', 'border' => '#6f6f6f', ) ); /** @var string $decline_button_style_string */ $decline_button_style_string = wp_json_encode( $decline_button_style ); /** @var array{bg: string, font: string, border: string} $decline_button_style */ $decline_button_style = json_decode( $decline_button_style_string, true ); /** @var array{bg: string, font: string, border: string} $parameters_button_style */ $parameters_button_style = Options::get( 'fastcmp-parametersButtonStyle', array( 'bg' => 'transparent', 'font' => '#6f6f6f', 'border' => '#6f6f6f', ) ); /** @var string $parameters_button_style_string */ $parameters_button_style_string = wp_json_encode( $parameters_button_style ); /** @var array{bg: string, font: string, border: string} $parameters_button_style */ $parameters_button_style = json_decode( $parameters_button_style_string, true ); /** @var string $custom_style */ $custom_style = Options::get( 'fastcmp-customStyle', '' ); /** @var string $lastupdate */ $lastupdate = Options::get( 'fastcmp-lastupdate', '' ); /** @var string $consent_v2 */ $consent_v2 = Options::get( 'fastcmp-consentV2', false ); /** @var string $google_tags_status */ $google_tags_status = Options::get( 'fastcmp-googleTagsStatus', false ); /** @var string $google_ad_storage */ $google_ad_storage = Options::get( 'fastcmp-googleAdStorage', false ); /** @var string $google_analytics_storage */ $google_analytics_storage = Options::get( 'fastcmp-googleAnalyticsStorage', false ); /** @var string $google_personalization_storage */ $google_personalization_storage = Options::get( 'fastcmp-googlePersonalizationStorage', false ); /** @var string $google_functionality_storage */ $google_functionality_storage = Options::get( 'fastcmp-googleFunctionalityStorage', false ); /** @var string $google_security_storage */ $google_security_storage = Options::get( 'fastcmp-googleSecurityStorage', false ); /** @var string $google_ad_personalization */ $google_ad_personalization = Options::get( 'fastcmp-googleAdPersonalization', false ); /** @var string $google_ad_user_data */ $google_ad_user_data = Options::get( 'fastcmp-googleAdUserData', false ); /** @var string $google_specific_enabled */ $google_specific_enabled = Options::get( 'fastcmp-googleSpecificEnabled', false ); /** @var string $google_specific_data */ $google_specific_data = Options::get( 'fastcmp-googleSpecificData', '' ); return array( 'name' => $name, 'enabled' => $enabled, 'headOffice' => $head_office, 'logo' => $image, 'privacyPolicy' => $privacy_policy, 'targetedAudience' => $targeted_audience, 'excludedIabVendors' => $excluded_iab_vendors, 'excludedGoogleVendors' => $excluded_google_vendors, 'customsVendor' => $customs_vendor, 'stubLight' => $stub_light, 'vendors' => $vendors, 'uuid' => $uuid, 'acceptButtonStyle' => $accept_button_style, 'declineButtonStyle' => $decline_button_style, 'parametersButtonStyle' => $parameters_button_style, 'customStyle' => $custom_style, 'lastUpdate' => $lastupdate, 'consentV2' => $consent_v2, 'googleTagsStatus' => $google_tags_status, 'googleAdStorage' => $google_ad_storage, 'googleAnalyticsStorage' => $google_analytics_storage, 'googlePersonalizationStorage' => $google_personalization_storage, 'googleFunctionalityStorage' => $google_functionality_storage, 'googleSecurityStorage' => $google_security_storage, 'googleAdPersonalization' => $google_ad_personalization, 'googleAdUserData' => $google_ad_user_data, 'googleSpecificEnabled' => $google_specific_enabled, 'googleSpecificData' => $google_specific_data, ); } /** * Get server details. * * @since 2.3.0 * @return array */ public static function get_server_details() { $data = array(); $data['host'] = null; $data['scheme'] = isset( $_SERVER['REQUEST_SCHEME'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_SCHEME'] ) ) : ''; $data['uri'] = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; $data['method'] = isset( $_SERVER['REQUEST_METHOD'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : ''; $website_domain = wp_parse_url( get_bloginfo( 'url' ) ); if ( is_array( $website_domain ) && isset( $website_domain['host'] ) ) { $data['host'] = $website_domain['host']; } if ( empty( $data['host'] ) ) { $data['host'] = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : ''; } if ( ! empty( $data['host'] ) ) { /** @var string $host */ $host = preg_replace( '/^w{3,}\.(.*)$/', '$1', strtolower( $data['host'] ) ); $data['host'] = $host; } return $data; } /** * Check if plugin auto update is active. * * @since 2.4.0 * @return bool */ public static function has_auto_update() { /** @var string $plugin_file */ $plugin_file = plugin_basename( ACTIRISE_FILE ); /** @var array $auto_updates */ $auto_updates = get_site_option( 'auto_update_plugins', array() ); /** @var bool $auto_updates_enabled */ $auto_updates_enabled = in_array( $plugin_file, $auto_updates, true ); return $auto_updates_enabled; } /** * Get all custom value. * * @since 2.0.0 * @param string $type_custom The type of custom. * @param string $custom_name The name of custom. * @return string */ public static function get_custom_value( $type_custom, $custom_name ) { $value = ''; if ( is_home() || is_front_page() ) { $value = self::apply_custom_value_filter( $custom_name, $value ); return $value; } if ( $type_custom !== '' ) { $custom_exploded = explode( '_', $type_custom, 2 ); $type_custom_key = $custom_exploded[0]; $level_custom = '0'; $key = $custom_exploded[1]; if ( $type_custom_key === 'category' || $type_custom_key === 'tag' ) { $custom_exploded = explode( '_', $type_custom, 3 ); $level_custom = $custom_exploded[1]; $key = $custom_exploded[2]; } $post_id = get_the_ID(); $post_value = get_post( ! $post_id ? null : $post_id ); if ( ! $post_value || ! $post_id ) { $value = ''; } else { switch ( $type_custom_key ) { case 'post': if ( is_single() || is_page() ) { if ( $post_value->$key ) { /** @var string $value */ $value = $post_value->$key; } } break; case 'category': $category = get_the_category(); if ( $category && isset( $category[ $level_custom ] ) ) { /** @var string $value */ $value = $category[ $level_custom ]->$key; } break; case 'tag': $tags = get_the_tags( $post_id ); if ( $tags && ! is_wp_error( $tags ) && isset( $tags[ $level_custom ] ) ) { /** @var string $value */ $value = $tags[ $level_custom ]->$key; } break; case 'author': if ( is_single() || is_page() ) { /** @var int $author_id */ $author_id = $post_value->post_author; /** @var string $value */ $value = get_the_author_meta( 'display_name', $author_id ); if ( $value === '' ) { /** @var string $value */ $value = get_the_author_meta( $key, $author_id ); } } break; case 'customFields': /** @var string $value */ $value = get_post_meta( $post_id, $key, true ); break; default: $value = ''; break; } } } $value = self::apply_custom_value_filter( $custom_name, $value ); /** @var string $value */ return $value; } /** * Get WordPress filesystem. * * @since 2.5.0 * @return WP_Filesystem_Base|WP_Error */ public static function get_wp_fs() { global $wp_filesystem; if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) { $initialized = self::init_wp_fs(); if ( false === $initialized ) { return new WP_Error( 'WP_FS_HELPER', 'The WordPress filesystem could not be initialized.' ); } } /** @var WP_Filesystem_Base $wp_filesystem */ return $wp_filesystem; } /** * Init WP_Filesystem. * * @since 2.5.0 * @return bool */ protected static function init_wp_fs() { global $wp_filesystem; if ( $wp_filesystem instanceof WP_Filesystem_Base ) { return true; } /** @phpstan-ignore requireOnce.fileNotFound */ require_once ABSPATH . 'wp-admin/includes/file.php'; $method = get_filesystem_method(); $initialized = false; if ( 'direct' === $method ) { $initialized = WP_Filesystem(); } elseif ( false !== $method ) { // See https://core.trac.wordpress.org/changeset/56341. ob_start(); $credentials = request_filesystem_credentials( '' ); ob_end_clean(); $initialized = $credentials && WP_Filesystem( $credentials ); } return is_null( $initialized ) ? false : $initialized; } /** * Generate a random token in uuid v4 format * * @since 2.5.5 * @param string $prefix * @return string */ public static function generate_token( $prefix = '' ) { $uid = uniqid( '', true ); $uid = str_replace( '.', '', $uid ); $uid = str_shuffle( $uid ); $uuid = sprintf( '%05s-%05s-%05d-%05d', substr( $uid, 0, 5 ), substr( $uid, 5, 5 ), ( hexdec( substr( $uid, 10, 5 ) ) & 0x0fff ) | 0x5000, ( hexdec( substr( $uid, 15, 5 ) ) & 0x3fff ) | 0x5000 ); return $prefix . $uuid; } /** * Hash token for API request * * @since 2.5.5 * @param string $token * @return string */ public static function hash_token( $token = '' ) { /** @var string $domain */ $domain = self::get_server_details()['host']; /** @var string $datetime */ $datetime = ( new DateTime( 'now', new DateTimeZone( 'UTC' ) ) )->format( 'Y-m-d' ); /** @var string $concatenated_string */ $concatenated_string = $token . $domain . $datetime; return md5( $concatenated_string ); } /** * Get website informations * * @since 3.0.0 * @return array */ public static function get_website_info() { /** @var array $website */ $website = array(); /** @var string $token */ $token = Options::get( 'settings-analytics-token', '' ); if ( $token !== '' ) { $api = new Api(); $args = array( 'exact[domain]' => rawurlencode( self::get_server_details()['host'] ), 'websiteProduct' => '/v2.0/website_products/3', ); $response = $api->get( 'api', 'websites', $args, $token, true ); if ( is_wp_error( $response ) || ! is_array( $response ) || ! is_array( $response['hydra:member'] ) ) { Logger::add_log( 'get_website_info error', 'include/helpers', 'error' ); return $website; } if ( empty( $response['hydra:member'] ) ) { return $website; } /** @var array $website */ $website = array_shift( $response['hydra:member'] ); if ( ! is_array( $website ) ) { /** @var array $website */ $website = array(); } } return $website; } /** * Send error * * @since 3.0.0 * @param string $code * @param string $message * @return void */ public static function send_error( $code, $message ) { wp_send_json_error( new WP_Error( $code, $message ) ); } /** * Check if JS custom code for cmp consent is valid * * @since 2.6.9 * @param string $code * @return bool|WP_Error */ public static function cmp_consent_valid_code( $code ) { $code = trim( $code ); if ( empty( $code ) ) { return false; } $requiredKeys = array( 'region', 'ad_storage', 'analytics_storage', 'personalization_storage', 'functionality_storage', 'security_storage', 'ad_personalization', 'ad_user_data', ); $allowedValues = array( 'granted', 'denied' ); /** @var string $code */ $code = '[' . preg_replace( '/}\s*,\s*{/', '},{', $code ) . ']'; /** @var string $code */ $code = preg_replace_callback( '/([a-zA-Z_]+)\s*:/', function ( $matches ) { return '"' . $matches[1] . '":'; }, $code ); /** @var string $code */ $code = preg_replace( "/'([^']*)'/", '"$1"', $code ); /** @var string $code */ $code = preg_replace_callback( '/"region"\s*:\s*\[(.*?)\]/', function ( $matches ) { $regions = array_map( 'trim', explode( ',', $matches[1] ) ); $regions = array_map( function ( $item ) { return '"' . trim( $item, '"\' ' ) . '"'; }, $regions ); return '"region":[' . implode( ',', $regions ) . ']'; }, $code ); /** @var string $code */ $code = preg_replace( '/\s+/', '', $code ); /** @var string $code */ $code = preg_replace( '/,}/', '}', $code ); /** @var string $code */ $data = json_decode( $code, true ); if ( json_last_error() !== JSON_ERROR_NONE ) { return new WP_Error( 'cmp_consent_invalid_code', 'Invalid JSON format.' ); } if ( ! is_array( $data ) || empty( $data ) ) { return new WP_Error( 'cmp_consent_invalid_code', 'Invalid JSON format.' ); } foreach ( $data as $object ) { $foundKey = 0; /** @var array $object */ foreach ( $object as $key => $value ) { if ( ! in_array( $key, $requiredKeys, true ) ) { continue; } ++$foundKey; if ( $key === 'region' ) { if ( ! is_array( $value ) || empty( $value ) ) { return new WP_Error( 'cmp_consent_invalid_code', 'Invalid region format.' ); } continue; } if ( ! in_array( $value, $allowedValues, true ) ) { return new WP_Error( 'cmp_consent_invalid_code', 'Invalid value for key: ' . $key ); } } if ( $foundKey !== count( $requiredKeys ) ) { return new WP_Error( 'cmp_consent_invalid_code', 'Missing required keys.' ); } } return false; } /** * Get user role * * @since 3.0.0 * @param string $user_id * @param string $token * @return string */ public static function get_user_role( $user_id, $token ) { $api = new Api(); $user_role = 'user'; $response_user = $api->get( 'api', 'users/' . $user_id, array(), $token ); if ( is_wp_error( $response_user ) || ! is_array( $response_user ) ) { Logger::add_log( 'get_user_role error', 'include/helpers', 'error' ); return $user_role; } if ( ! empty( $response_user['userGroups'][0]['role']['name'] ) && is_string( $response_user['userGroups'][0]['role']['name'] ) ) { $user_role = $response_user['userGroups'][0]['role']['name']; } return $user_role; } /** * Extract id from iri * * @since 3.0.0 * @param string $iri * @return string */ public static function extract_id( $iri ) { $iri_parts = explode( '/', $iri ); return end( $iri_parts ); } /** * Get user id from API and save it in options * * @since 3.2.0 * @return void */ public static function get_user_id() { $api = new Api(); $token = Options::get( 'settings-analytics-token', '' ); if ( ! is_string( $token ) ) { $token = ''; } $response = $api->get( 'api', 'authentication/auth', array(), $token, true ); if ( is_wp_error( $response ) || ! is_array( $response ) || ! self::is_valid_user( $response ) ) { Options::delete( 'settings-analytics-token' ); Options::delete( 'settings-analytics-userid' ); return; } // PHPStan: After is_valid_user validation, we know $response['user']['@id'] is a string /** @var string $user_iri */ $user_iri = $response['user']['@id']; $user_id = self::extract_id( $user_iri ); Options::update( 'settings-analytics-userid', $user_id ); } /** * Validate user response structure * * @since 3.2.0 * @param array $response * @return bool */ private static function is_valid_user( array $response ) { return isset( $response['user'] ) && is_array( $response['user'] ) && isset( $response['user']['@id'] ) && is_string( $response['user']['@id'] ); } /** * Apply custom value filter * * @since 3.1.0 * @param string $custom_name * @param string $value * @return string */ private static function apply_custom_value_filter( $custom_name, $value ) { $filter_name = $custom_name . '_value'; /** @var string|null $filter_value */ $filter_value = apply_filters( 'actirise_' . $filter_name, $value ); if ( ! empty( $filter_value ) ) { /** @var string $filter_value */ return sanitize_text_field( $filter_value ); } /** @var string $value */ return $value; } /** * Test if XPath expression works against HTML content * * @since 2.0.0 * @param \DOMDocument $dom DOMDocument object containing the HTML content. * @param string $xpath_expression XPath expression to validate. * @param bool $return_result Whether to return the found elements. * @return array{success: bool, found_elements: int, elements?: \DOMNodeList<\DOMNode>, error: string|null} */ public static function test_xpath( $dom, $xpath_expression, $return_result = false ) { if ( empty( $dom ) || empty( $xpath_expression ) ) { return array( 'success' => false, 'found_elements' => 0, 'error' => 'HTML content or XPath expression is empty', ); } try { $xpath_dom = new \DOMXPath( $dom ); $result = $xpath_dom->query( $xpath_expression ); if ( $result === false ) { return array( 'success' => false, 'found_elements' => 0, 'error' => 'Invalid XPath expression', ); } $response = array( 'success' => true, 'found_elements' => $result->length, 'error' => null, ); if ( $return_result ) { $response['elements'] = $result; } return $response; } catch ( \Exception $e ) { return array( 'success' => false, 'found_elements' => 0, 'error' => $e->getMessage(), ); } } }