array( 'icon' => WPMUDEV_BLC_ASSETS_URL . 'images/social/facebook-dark-7x14.png', 'url' => 'https://www.facebook.com/wpmudev', ), 'instagram' => array( 'icon' => WPMUDEV_BLC_ASSETS_URL . 'images/social/instagram-dark-14x14.png', 'url' => 'https://www.instagram.com/wpmu_dev/', ), 'twitter' => array( 'icon' => WPMUDEV_BLC_ASSETS_URL . 'images/social/twitter-dark-13x11.png', 'url' => 'https://twitter.com/wpmudev/', ), ) ); } /** * Returns scan date. */ public static function scan_date() { $start_time = self::get_scan_results( 'start_time' ); if ( ! empty( $start_time ) ) { $start_time = Utilities::microtime_to_date( intval( $start_time ), 'full_date', true ); } return apply_filters( 'wpmudev_blc_scan_report_email_scan_date', $start_time ); } /** * Returns scan results. * * @param string $key Optional scan results key. */ public static function get_scan_results( string $key = '' ) { if ( empty( self::$scan_results ) ) { $scan_results = array(); $scan_defaults = Settings::instance()->default['scan_results'] ?? array(); self::$scan_results = wp_parse_args( Settings::instance()->get( 'scan_results' ), $scan_defaults ); } if ( ! empty( $key ) ) { return self::$scan_results[ $key ] ?? null; } return self::$scan_results; } /** * Returns array recipients email address and names. */ public static function get_recipients() { return self::unique_recipients( array_merge( self::get_registered_user_recipients(), self::get_email_recipients() ) ); } /** * Drops the recipients sharing an email address with a preceding one, so that each address is reported to once. * * The recipients screen and the settings endpoint both reject duplicates, but the same address can already be stored * in both recipient lists on sites that were saved before that. * * @param array $recipients The recipients, registered users first as those also carry the review link. * * @since 2.4.14 * * @return array */ private static function unique_recipients( array $recipients = array() ) { $sent_to = array(); return array_values( array_filter( $recipients, function ( $recipient ) use ( &$sent_to ) { if ( empty( $recipient['email'] ) ) { return false; } $email = strtolower( trim( $recipient['email'] ) ); if ( in_array( $email, $sent_to, true ) ) { return false; } $sent_to[] = $email; return true; } ) ); } public static function get_registered_user_recipients() { static $reviewers_ids = array(); if ( is_null( self::$registered_users_recipients ) ) { self::$registered_users_recipients = array(); $schedule = Settings::instance()->get( 'schedule' ); $registered_recipients_data = ! empty( $schedule['registered_recipients_data'] ) ? $schedule['registered_recipients_data'] : array(); $has_been_reviewed = Recipients::has_been_reviewed(); if ( ! empty( $registered_recipients_data ) ) { // Let's check which users will be allowed to review plugin. if ( empty( $reviewers_ids ) && ! $has_been_reviewed ) { $user_ids = array_keys( $registered_recipients_data ); $auth_user = Utilities::get_auth_user( true ); if ( $auth_user instanceof \WP_User && in_array( $auth_user->ID, $user_ids ) ) { $reviewers_ids[] = $auth_user->ID; } else { $reviewers_ids = array_intersect( Utilities::get_dash_users(), $user_ids ); } } array_walk( $registered_recipients_data, function ( $user_data, $user_id ) use ( $reviewers_ids, $has_been_reviewed ) { $review_link = ''; $token = base64_encode( md5( $user_data['email'] ) . '_' . $user_data['key'] ); if ( ! $has_been_reviewed ) { // If still there is no reviewer, we can include any of the recipients that have an administrator role. if ( ( ! empty( $reviewers_ids ) && in_array( $user_id, $reviewers_ids ) ) || ( empty( $reviewers_ids ) && user_can( $user_id, 'manage_options' ) ) ) { $review_link = self::review_link( $user_id, $token ); } } self::$registered_users_recipients[] = array( 'name' => $user_data['name'], 'email' => $user_data['email'], 'key' => $user_data['key'], 'unsubscribe_link' => self::unsubscribe_link( $token ), 'review_link' => $review_link, ); } ); } } return self::$registered_users_recipients; } /** * Returns a link where user can review. The link does not point directly to wp org. * Instead, it first links to an endpoint so that we can flag that user has reviewed and then redirect to wp org. * We need this flag so that we don't annoy user with every email to review. * * @param int|null $user_id * @param string|null $token * * @return void|string */ private static function review_link( int $user_id = null, string $token = null ) { return add_query_arg( array( 'token' => sanitize_text_field( $token ), ), Review_Webhook::instance()->webhook_url() ); } private static function unsubscribe_link( string $token = '' ) { return add_query_arg( array( 'action' => 'cancel', 'activation_code' => sanitize_text_field( $token ), ), Activation_Webhook::instance()->webhook_url() ); } public static function get_email_recipients() { $email_recipients = Settings::instance()->get_scan_active_email_recipients(); if ( ! empty( $email_recipients ) ) { array_walk( $email_recipients, function ( &$recipient ) { unset( $recipient['confirmed'] ); $recipient['unsubscribe_link'] = self::unsubscribe_link( base64_encode( md5( $recipient['email'] ) . '_' . $recipient['key'] ) ); } ); } return $email_recipients; } }