PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.1
16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 All 504 releases
jetpack / extensions / blocks / premium-content / login-button / login-button.php

login-button.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-a.1, at extensions/blocks/premium-content/login-button/login-button.php

135 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Premium Content Login Button Child Block.
4 *
5 * @package automattic/jetpack
6 */
7
8 namespace Automattic\Jetpack\Extensions\Premium_Content;
9
10 use Automattic\Jetpack\Blocks;
11 use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Abstract_Token_Subscription_Service;
12 use Automattic\Jetpack\Status\Host;
13 use Jetpack_Gutenberg;
14 use Jetpack_Options;
15
16 require_once dirname( __DIR__ ) . '/_inc/subscription-service/include.php';
17
18 const LOGIN_BUTTON_NAME = 'premium-content/login-button';
19
20 /**
21 * Registers the block for use in Gutenberg
22 * This is done via an action so that we can disable
23 * registration if we need to.
24 */
25 function register_login_button_block() {
26 Blocks::jetpack_register_block(
27 LOGIN_BUTTON_NAME,
28 array(
29 'render_callback' => __NAMESPACE__ . '\render_login_button_block',
30 'render_email_callback' => __NAMESPACE__ . '\render_login_button_block_email',
31 )
32 );
33 }
34 add_action( 'init', __NAMESPACE__ . '\register_login_button_block' );
35
36 /**
37 * Returns current URL.
38 *
39 * @return string
40 */
41 function get_current_url() {
42 if ( ! isset( $_SERVER['HTTP_HOST'] ) || ! isset( $_SERVER['REQUEST_URI'] ) ) {
43 return '';
44 }
45
46 return ( is_ssl() ? 'https://' : 'http://' ) . wp_unslash( $_SERVER['HTTP_HOST'] ) . wp_unslash( $_SERVER['REQUEST_URI'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
47 }
48
49 /**
50 * Returns subscriber log in URL.
51 *
52 * @param string $redirect Path to redirect to on login.
53 *
54 * @return string
55 */
56 function get_subscriber_login_url( $redirect ) {
57 $redirect = ! empty( $redirect ) ? $redirect : get_site_url();
58
59 if ( ( new Host() )->is_wpcom_simple() ) {
60 // On WPCOM we will redirect immediately
61 return wpcom_logmein_redirect_url( $redirect, false, null, 'link', get_current_blog_id() );
62 }
63
64 // On self-hosted we will save and hide the token.
65 // rawurlencode the redirect before nesting it: it is already percent-encoded
66 // (e.g. an emoji or non-ASCII slug comes through as %F0%9F%8C%91), and add_query_arg
67 // does not encode the values it inserts. Without this extra layer the value is
68 // over-decoded to raw bytes by the time it reaches the subscribers/auth endpoint,
69 // which strips it and 404s. See NL-273.
70 $redirect_url = get_site_url() . '/wp-json/jetpack/v4/subscribers/auth';
71 $redirect_url = add_query_arg( 'redirect_url', rawurlencode( $redirect ), $redirect_url );
72
73 return add_query_arg(
74 array(
75 'site_id' => intval( Jetpack_Options::get_option( 'id' ) ),
76 'redirect_url' => rawurlencode( $redirect_url ),
77 ),
78 'https://subscribe.wordpress.com/memberships/jwt/'
79 );
80 }
81
82 /**
83 * Determines whether the visitor has a subscriber session for the login UI.
84 *
85 * WordPress sessions count on Simple; other hosts require the subscriber cookie.
86 * Content access validates the token separately.
87 *
88 * @return bool
89 */
90 function is_subscriber_logged_in() {
91 return ( ( new Host() )->is_wpcom_simple() && is_user_logged_in() ) || Abstract_Token_Subscription_Service::has_token_from_cookie();
92 }
93
94 /**
95 * Render callback.
96 *
97 * @param array $attributes Array containing the block attributes.
98 * @param string $content String containing the block content.
99 *
100 * @return string
101 */
102 function render_login_button_block( $attributes, $content ) {
103 if ( ! pre_render_checks() ) {
104 return '';
105 }
106
107 // The viewer is logged it, so they shouldn't see the login button.
108 if ( is_subscriber_logged_in() ) {
109 return '';
110 }
111
112 Jetpack_Gutenberg::load_styles_as_required( LOGIN_BUTTON_NAME );
113
114 $redirect_url = get_current_url();
115 $url = get_subscriber_login_url( $redirect_url );
116
117 $content = preg_replace( '/(<a\b[^><]*)>/i', '$1 href="' . esc_url( $url ) . '">', $content );
118
119 // Defense in depth: the label is inner block content (KSES-filtered on save for
120 // roles without `unfiltered_html`), but escape it again on output so a stored
121 // payload can never render as live markup.
122 return wp_kses_post( $content );
123 }
124
125 /**
126 * Render email callback.
127 *
128 * @return string
129 */
130 function render_login_button_block_email() {
131 // We don't want to render the login button in emails.
132 // The subscriber is already considered logged in in emails.
133 return '';
134 }
135