active at one point in time and are still enabled on the site
*
* @return void
*/
public static function update_historically_active_jetpack_modules() {
$historically_active_modules = \Jetpack_Options::get_option( 'historically_active_modules', array() );
$products = Products::get_products();
foreach ( $products as $product ) {
$status = $product['status'];
$product_slug = $product['slug'];
// We want to leave modules in the array if they've been active in the past
// and were not manually disabled by the user.
if ( in_array( $status, Products::$broken_module_statuses, true ) ) {
continue;
}
// If the module is active and not already in the array, add it
if (
in_array( $status, Products::$active_module_statuses, true ) &&
! in_array( $product_slug, $historically_active_modules, true )
) {
$historically_active_modules[] = $product_slug;
}
// If the module has been disabled due to a manual user action,
// or because of a missing plan error, remove it from the array
if ( in_array( $status, Products::$disabled_module_statuses, true ) ) {
$historically_active_modules = array_values( array_diff( $historically_active_modules, array( $product_slug ) ) );
}
}
\Jetpack_Options::update_option( 'historically_active_modules', array_unique( $historically_active_modules ) );
}
/**
* Site full-data endpoint.
*
* @return object Site data.
*/
public static function get_site() {
$site_id = \Jetpack_Options::get_option( 'id' );
$wpcom_endpoint = sprintf( '/sites/%d?force=wpcom', $site_id );
$wpcom_api_version = '1.1';
$response = Client::wpcom_json_api_request_as_blog( $wpcom_endpoint, $wpcom_api_version );
$response_code = wp_remote_retrieve_response_code( $response );
$body = json_decode( wp_remote_retrieve_body( $response ) );
if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
return new WP_Error( 'site_data_fetch_failed', 'Site data fetch failed', array( 'status' => $response_code ) );
}
return rest_ensure_response( $body );
}
/**
* Populates the self::$site_info var with site data from the /sites/%d endpoint
*
* @return object|WP_Error
*/
public static function get_site_info() {
static $site_info = null;
if ( $site_info !== null ) {
return $site_info;
}
// Check for a cached value before doing lookup
$stored_site_info = get_transient( self::MY_JETPACK_SITE_INFO_TRANSIENT_KEY );
if ( $stored_site_info !== false ) {
return $stored_site_info;
}
$response = self::get_site();
if ( is_wp_error( $response ) ) {
return $response;
}
$site_info = $response->data;
set_transient( self::MY_JETPACK_SITE_INFO_TRANSIENT_KEY, $site_info, DAY_IN_SECONDS );
return $site_info;
}
/**
* Returns whether a site has been determined "commercial" or not.
*
* @return bool|null
*/
public static function is_commercial_site() {
if ( is_wp_error( self::$site_info ) ) {
return null;
}
return empty( self::$site_info->options->is_commercial ) ? false : self::$site_info->options->is_commercial;
}
/**
* Check if site is registered (has been connected before).
*
* @return bool
*/
public static function is_registered() {
return (bool) \Jetpack_Options::get_option( 'id' );
}
/**
* Dismiss the welcome banner.
*
* @return \WP_REST_Response
*/
public static function dismiss_welcome_banner() {
\Jetpack_Options::update_option( 'dismissed_welcome_banner', true );
return rest_ensure_response( array( 'success' => true ) );
}
/**
* Returns true if the site has file write access to the plugins folder, false otherwise.
*
* @return string
**/
public static function has_file_system_write_access() {
$cache = get_transient( 'my_jetpack_write_access' );
if ( false !== $cache ) {
return $cache;
}
if ( ! function_exists( 'get_filesystem_method' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
require_once ABSPATH . 'wp-admin/includes/template.php';
$write_access = 'no';
$filesystem_method = get_filesystem_method( array(), WP_PLUGIN_DIR );
if ( 'direct' === $filesystem_method ) {
$write_access = 'yes';
}
if ( ! $write_access ) {
ob_start();
$filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() );
ob_end_clean();
if ( $filesystem_credentials_are_stored ) {
$write_access = 'yes';
}
}
set_transient( 'my_jetpack_write_access', $write_access, 30 * MINUTE_IN_SECONDS );
return $write_access;
}
/**
* Get container IDC for the IDC screen.
*
* @return string
*/
public static function get_idc_container_id() {
return static::IDC_CONTAINER_ID;
}
/**
* Gets the plugins that need installed or activated for each paid plan.
*
* @return array
*/
public static function get_paid_plans_plugins_requirements() {
$plugin_requirements = array();
foreach ( Products::get_products_classes() as $slug => $product_class ) {
// Skip these- we don't show them in My Jetpack.
if ( in_array( $slug, Products::get_not_shown_products(), true ) ) {
continue;
}
if ( ! $product_class::has_paid_plan_for_product() ) {
continue;
}
$purchase = $product_class::get_paid_plan_purchase_for_product();
if ( ! $purchase ) {
continue;
}
// Check if required plugin needs installed or activated.
if ( ! $product_class::is_plugin_installed() ) {
// Plugin needs installed (and activated)
$plugin_requirements[ $purchase->product_slug ]['needs_installed'][] = $product_class::$slug;
} elseif ( ! $product_class::is_plugin_active() ) {
// Plugin is installed, but not activated.
$plugin_requirements[ $purchase->product_slug ]['needs_activated_only'][] = $product_class::$slug;
}
}
return $plugin_requirements;
}
/**
* Conditionally append the red bubble notification to the "Jetpack" menu item if there are alerts to show
*
* @return void
*/
public static function maybe_show_red_bubble() {
global $menu;
// filters for the items in this file
add_filter( 'my_jetpack_red_bubble_notification_slugs', array( __CLASS__, 'add_red_bubble_alerts' ) );
$red_bubble_alerts = array_filter(
self::get_red_bubble_alerts(),
function ( $alert ) {
// We don't want to show silent alerts
return empty( $alert['is_silent'] );
}
);
// The Jetpack menu item should be on index 3
if (
! empty( $red_bubble_alerts ) &&
is_countable( $red_bubble_alerts ) &&
isset( $menu[3] ) &&
$menu[3][0] === 'Jetpack'
) {
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$menu[3][0] .= sprintf( ' %d', count( $red_bubble_alerts ) );
}
}
/**
* Collect all possible alerts that we might use a red bubble notification for
*
* @param bool $bypass_cache - whether to bypass the red bubble cache.
* @return array
*/
public static function get_red_bubble_alerts( bool $bypass_cache = false ) {
static $red_bubble_alerts = array();
// using a static cache since we call this function more than once in the class
if ( ! empty( $red_bubble_alerts ) ) {
return $red_bubble_alerts;
}
// check for stored alerts
$stored_alerts = get_transient( self::MY_JETPACK_RED_BUBBLE_TRANSIENT_KEY );
// Cache bypass for red bubbles should only happen on the My Jetpack page
if ( $stored_alerts !== false && ! ( $bypass_cache ) ) {
return $stored_alerts;
}
// go find the alerts
$red_bubble_alerts = apply_filters( 'my_jetpack_red_bubble_notification_slugs', $red_bubble_alerts );
// cache the alerts for one hour
set_transient( self::MY_JETPACK_RED_BUBBLE_TRANSIENT_KEY, $red_bubble_alerts, 3600 );
return $red_bubble_alerts;
}
/**
* Get list of module names sorted by their recommendation score
*
* @return array|null
*/
public static function get_recommended_modules() {
$recommendations_evaluation = \Jetpack_Options::get_option( 'recommendations_evaluation', null );
if ( ! $recommendations_evaluation ) {
return null;
}
arsort( $recommendations_evaluation ); // Sort by scores in descending order
return array_keys( $recommendations_evaluation ); // Get only module names
}
/**
* Check for features broken by a disconnected user or site
*
* @return array
*/
public static function check_for_broken_modules() {
$connection = new Connection_Manager();
$is_user_connected = $connection->is_user_connected() || $connection->has_connected_owner();
$is_site_connected = $connection->is_connected();
$broken_modules = array(
'needs_site_connection' => array(),
'needs_user_connection' => array(),
);
if ( $is_user_connected && $is_site_connected ) {
return $broken_modules;
}
$products = Products::get_products_classes();
$historically_active_modules = \Jetpack_Options::get_option( 'historically_active_modules', array() );
foreach ( $products as $product ) {
if ( ! in_array( $product::$slug, $historically_active_modules, true ) ) {
continue;
}
if ( $product::$requires_user_connection && ! $is_user_connected ) {
if ( ! in_array( $product::$slug, $broken_modules['needs_user_connection'], true ) ) {
$broken_modules['needs_user_connection'][] = $product::$slug;
}
} elseif ( ! $is_site_connected ) {
if ( ! in_array( $product::$slug, $broken_modules['needs_site_connection'], true ) ) {
$broken_modules['needs_site_connection'][] = $product::$slug;
}
}
}
return $broken_modules;
}
/**
* Add relevant red bubble notifications
*
* @param array $red_bubble_slugs - slugs that describe the reasons the red bubble is showing.
* @return array
*/
public static function add_red_bubble_alerts( array $red_bubble_slugs ) {
if ( wp_doing_ajax() ) {
return array();
}
$connection = new Connection_Manager();
$welcome_banner_dismissed = \Jetpack_Options::get_option( 'dismissed_welcome_banner', false );
if ( self::is_jetpack_user_new() && ! $welcome_banner_dismissed ) {
$red_bubble_slugs['welcome-banner-active'] = array(
'is_silent' => $connection->is_connected(), // we don't display the red bubble if the user is connected
);
return $red_bubble_slugs;
} else {
return array_merge(
self::alert_if_missing_connection( $red_bubble_slugs ),
self::alert_if_last_backup_failed( $red_bubble_slugs ),
self::alert_if_paid_plan_expiring( $red_bubble_slugs ),
self::alert_if_protect_has_threats( $red_bubble_slugs ),
self::alert_if_paid_plan_requires_plugin_install_or_activation( $red_bubble_slugs )
);
}
}
/**
* Add an alert slug if the site is missing a site connection
*
* @param array $red_bubble_slugs - slugs that describe the reasons the red bubble is showing.
* @return array
*/
public static function alert_if_missing_connection( array $red_bubble_slugs ) {
$broken_modules = self::check_for_broken_modules();
$connection = new Connection_Manager();
// Checking for site connection issues first.
if ( ! empty( $broken_modules['needs_site_connection'] ) ) {
$red_bubble_slugs[ self::MISSING_CONNECTION_NOTIFICATION_KEY ] = array(
'type' => 'site',
'is_error' => true,
);
return $red_bubble_slugs;
}
if ( ! empty( $broken_modules['needs_user_connection'] ) ) {
$red_bubble_slugs[ self::MISSING_CONNECTION_NOTIFICATION_KEY ] = array(
'type' => 'user',
'is_error' => true,
);
return $red_bubble_slugs;
}
if ( ! $connection->is_connected() ) {
$red_bubble_slugs[ self::MISSING_CONNECTION_NOTIFICATION_KEY ] = array(
'type' => 'site',
'is_error' => false,
);
return $red_bubble_slugs;
}
return $red_bubble_slugs;
}
/**
* Add an alert slug if any paid plan/products are expiring or expired.
*
* @param array $red_bubble_slugs - slugs that describe the reasons the red bubble is showing.
* @return array
*/
public static function alert_if_paid_plan_expiring( array $red_bubble_slugs ) {
$connection = new Connection_Manager();
if ( ! $connection->is_connected() ) {
return $red_bubble_slugs;
}
$product_classes = Products::get_products_classes();
$products_included_in_expiring_plan = array();
foreach ( $product_classes as $key => $product ) {
// Skip these- we don't show them in My Jetpack.
if ( in_array( $key, Products::get_not_shown_products(), true ) ) {
continue;
}
if ( $product::has_paid_plan_for_product() ) {
$purchase = $product::get_paid_plan_purchase_for_product();
if ( $purchase ) {
$redbubble_notice_data = array(
'product_slug' => $purchase->product_slug,
'product_name' => $purchase->product_name,
'expiry_date' => $purchase->expiry_date,
'expiry_message' => $purchase->expiry_message,
'manage_url' => $product::get_manage_paid_plan_purchase_url(),
);
if ( $product::is_paid_plan_expired() ) {
$red_bubble_slugs[ "$purchase->product_slug--plan_expired" ] = $redbubble_notice_data;
if ( ! $product::is_bundle_product() ) {
$products_included_in_expiring_plan[ "$purchase->product_slug--plan_expired" ][] = $product::get_name();
}
}
if ( $product::is_paid_plan_expiring() ) {
$red_bubble_slugs[ "$purchase->product_slug--plan_expiring_soon" ] = $redbubble_notice_data;
$red_bubble_slugs[ "$purchase->product_slug--plan_expiring_soon" ]['manage_url'] = $product::get_renew_paid_plan_purchase_url();
if ( ! $product::is_bundle_product() ) {
$products_included_in_expiring_plan[ "$purchase->product_slug--plan_expiring_soon" ][] = $product::get_name();
}
}
}
}
}
foreach ( $products_included_in_expiring_plan as $expiring_plan => $products ) {
$red_bubble_slugs[ $expiring_plan ]['products_effected'] = $products;
}
return $red_bubble_slugs;
}
/**
* Add an alert slug if Backups are failing or having an issue.
*
* @param array $red_bubble_slugs - slugs that describe the reasons the red bubble is showing.
* @return array
*/
public static function alert_if_last_backup_failed( array $red_bubble_slugs ) {
// Make sure there's a Backup paid plan
if ( ! Products\Backup::is_plugin_active() || ! Products\Backup::has_paid_plan_for_product() ) {
return $red_bubble_slugs;
}
// Make sure the plan isn't just recently purchased in last 30min.
// Give some time to queue & run the first backup.
$purchase = Products\Backup::get_paid_plan_purchase_for_product();
if ( $purchase ) {
$thirty_minutes_after_plan_purchase = strtotime( $purchase->subscribed_date . ' +30 minutes' );
if ( strtotime( 'now' ) < $thirty_minutes_after_plan_purchase ) {
return $red_bubble_slugs;
}
}
$backup_failed_status = Products\Backup::does_module_need_attention();
if ( $backup_failed_status ) {
$red_bubble_slugs['backup_failure'] = $backup_failed_status;
}
return $red_bubble_slugs;
}
/**
* Add an alert slug if Protect has scan threats/vulnerabilities.
*
* @param array $red_bubble_slugs - slugs that describe the reasons the red bubble is showing.
* @return array
*/
public static function alert_if_protect_has_threats( array $red_bubble_slugs ) {
// Make sure we're dealing with the Protect product only
if ( ! Products\Protect::has_paid_plan_for_product() ) {
return $red_bubble_slugs;
}
$protect_threats_status = Products\Protect::does_module_need_attention();
if ( $protect_threats_status ) {
$red_bubble_slugs['protect_has_threats'] = $protect_threats_status;
}
return $red_bubble_slugs;
}
/**
* Add an alert slug if a site's paid plan requires a plugin install and/or activation.
*
* @param array $red_bubble_slugs - slugs that describe the reasons the red bubble is showing.
* @return array
*/
public static function alert_if_paid_plan_requires_plugin_install_or_activation( array $red_bubble_slugs ) {
$connection = new Connection_Manager();
// Don't trigger red bubble (and show notice) when the site is not connected or if the
// user doesn't have plugin installation/activation permissions.
if ( ! $connection->is_connected() || ! current_user_can( 'activate_plugins' ) ) {
return $red_bubble_slugs;
}
$plugins_needing_installed_activated = self::get_paid_plans_plugins_requirements();
if ( empty( $plugins_needing_installed_activated ) ) {
return $red_bubble_slugs;
}
foreach ( $plugins_needing_installed_activated as $plan_slug => $plugins_requirements ) {
$red_bubble_slugs[ "$plan_slug--plugins_needing_installed_activated" ] = $plugins_requirements;
}
return $red_bubble_slugs;
}
}
Fatal error: Uncaught Error: Class 'Automattic\Jetpack\My_Jetpack\Initializer' not found in /var/www/html/dportilho.com.br/web/wp-content/plugins/jetpack/class.jetpack.php:860
Stack trace:
#0 /var/www/html/dportilho.com.br/web/wp-includes/class-wp-hook.php(324): Jetpack->late_initialization('')
#1 /var/www/html/dportilho.com.br/web/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array)
#2 /var/www/html/dportilho.com.br/web/wp-includes/plugin.php(517): WP_Hook->do_action(Array)
#3 /var/www/html/dportilho.com.br/web/wp-settings.php(559): do_action('plugins_loaded')
#4 /var/www/html/dportilho.com.br/web/wp-config.php(126): require_once('/var/www/html/d...')
#5 /var/www/html/dportilho.com.br/web/wp-load.php(50): require_once('/var/www/html/d...')
#6 /var/www/html/dportilho.com.br/web/wp-blog-header.php(13): require_once('/var/www/html/d...')
#7 /var/www/html/dportilho.com.br/web/index.php(17): require('/var/www/html/d...')
#8 {main}
thrown in /var/www/html/dportilho.com.br/web/wp-content/plugins/jetpack/class.jetpack.php on line 860