1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Jetpack's JITM class. |
4
|
|
|
* |
5
|
|
|
* @package automattic/jetpack-jitm |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace Automattic\Jetpack\JITMS; |
9
|
|
|
|
10
|
|
|
use Automattic\Jetpack\Assets; |
11
|
|
|
use Automattic\Jetpack\Assets\Logo as Jetpack_Logo; |
12
|
|
|
use Automattic\Jetpack\Connection\Manager as Connection_Manager; |
13
|
|
|
use Automattic\Jetpack\Status; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Jetpack just in time messaging through out the admin |
17
|
|
|
* |
18
|
|
|
* @since 5.6.0 |
19
|
|
|
*/ |
20
|
|
|
class JITM { |
21
|
|
|
|
22
|
|
|
const PACKAGE_VERSION = '1.15.2-alpha'; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* The configuration method that is called from the jetpack-config package. |
26
|
|
|
*/ |
27
|
|
|
public static function configure() { |
28
|
|
|
$jitm = self::get_instance(); |
29
|
|
|
$jitm->register(); |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Pre/Post Connection JITM factory metod |
34
|
|
|
* |
35
|
|
|
* @return Post_Connection_JITM|Pre_Connection_JITM JITM instance. |
36
|
|
|
*/ |
37
|
|
|
public static function get_instance() { |
38
|
|
|
if ( ( new Connection_Manager() )->is_connected() ) { |
39
|
|
|
$jitm = new Post_Connection_JITM(); |
40
|
|
|
} else { |
41
|
|
|
$jitm = new Pre_Connection_JITM(); |
42
|
|
|
} |
43
|
|
|
return $jitm; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Determines if JITMs are enabled. |
48
|
|
|
* |
49
|
|
|
* @return bool Enable JITMs. |
50
|
|
|
*/ |
51
|
|
|
public function register() { |
52
|
|
|
/** |
53
|
|
|
* Filter to turn off all just in time messages |
54
|
|
|
* |
55
|
|
|
* @since 3.7.0 |
56
|
|
|
* @since 5.4.0 Correct docblock to reflect default arg value |
57
|
|
|
* |
58
|
|
|
* @param bool true Whether to show just in time messages. |
59
|
|
|
*/ |
60
|
|
|
if ( ! apply_filters( 'jetpack_just_in_time_msgs', true ) ) { |
61
|
|
|
return false; |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
// Folks cannot connect to WordPress.com and won't really be able to act on the pre-connection messages. So bail. |
65
|
|
|
if ( ( new Status() )->is_offline_mode() ) { |
66
|
|
|
return false; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
add_action( 'rest_api_init', array( __NAMESPACE__ . '\\Rest_Api_Endpoints', 'register_endpoints' ) ); |
70
|
|
|
|
71
|
|
|
add_action( 'current_screen', array( $this, 'prepare_jitms' ) ); |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* These are sync actions that we need to keep track of for jitms. |
75
|
|
|
*/ |
76
|
|
|
add_filter( 'jetpack_sync_before_send_updated_option', array( $this, 'jetpack_track_last_sync_callback' ), 99 ); |
77
|
|
|
|
78
|
|
|
return true; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Prepare actions according to screen and post type. |
83
|
|
|
* |
84
|
|
|
* @since 3.8.2 |
85
|
|
|
* |
86
|
|
|
* @uses Jetpack_Autoupdate::get_possible_failures() |
87
|
|
|
* |
88
|
|
|
* @param \WP_Screen $screen WP Core's screen object. |
89
|
|
|
*/ |
90
|
|
|
public function prepare_jitms( $screen ) { |
91
|
|
|
/** |
92
|
|
|
* Filter to hide JITMs on certain screens. |
93
|
|
|
* |
94
|
|
|
* @since 9.5.0 |
95
|
|
|
* |
96
|
|
|
* @param bool true Whether to show just in time messages. |
97
|
|
|
* @param string $string->id The ID of the current screen. |
98
|
|
|
*/ |
99
|
|
|
if ( apply_filters( 'jetpack_display_jitms_on_screen', true, $screen->id ) ) { |
|
|
|
|
100
|
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'jitm_enqueue_files' ) ); |
101
|
|
|
add_action( 'admin_notices', array( $this, 'ajax_message' ) ); |
102
|
|
|
add_action( 'edit_form_top', array( $this, 'ajax_message' ) ); |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Function to enqueue jitm css and js |
108
|
|
|
*/ |
109
|
|
|
public function jitm_enqueue_files() { |
110
|
|
|
if ( $this->is_gutenberg_page() ) { |
111
|
|
|
return; |
112
|
|
|
} |
113
|
|
|
$min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min'; |
114
|
|
|
wp_register_style( |
115
|
|
|
'jetpack-jitm-css', |
116
|
|
|
plugins_url( "css/jetpack-admin-jitm{$min}.css", __FILE__ ), |
117
|
|
|
false, |
118
|
|
|
self::PACKAGE_VERSION . |
119
|
|
|
'-201243242' |
120
|
|
|
); |
121
|
|
|
wp_style_add_data( 'jetpack-jitm-css', 'rtl', 'replace' ); |
122
|
|
|
wp_style_add_data( 'jetpack-jitm-css', 'suffix', $min ); |
123
|
|
|
wp_enqueue_style( 'jetpack-jitm-css' ); |
124
|
|
|
|
125
|
|
|
wp_enqueue_script( |
126
|
|
|
'jetpack-jitm-new', |
127
|
|
|
Assets::get_file_url_for_environment( 'js/jetpack-jitm.min.js', 'js/jetpack-jitm.js', __FILE__ ), |
128
|
|
|
array( 'jquery' ), |
129
|
|
|
self::PACKAGE_VERSION, |
130
|
|
|
true |
131
|
|
|
); |
132
|
|
|
wp_localize_script( |
133
|
|
|
'jetpack-jitm-new', |
134
|
|
|
'jitm_config', |
135
|
|
|
array( |
136
|
|
|
'api_root' => esc_url_raw( rest_url() ), |
137
|
|
|
'activate_module_text' => esc_html__( 'Activate', 'jetpack' ), |
138
|
|
|
'activated_module_text' => esc_html__( 'Activated', 'jetpack' ), |
139
|
|
|
'activating_module_text' => esc_html__( 'Activating', 'jetpack' ), |
140
|
|
|
'nonce' => wp_create_nonce( 'wp_rest' ), |
141
|
|
|
) |
142
|
|
|
); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Is the current page a block editor page? |
147
|
|
|
* |
148
|
|
|
* @since 8.0.0 |
149
|
|
|
*/ |
150
|
|
|
public function is_gutenberg_page() { |
151
|
|
|
$current_screen = get_current_screen(); |
152
|
|
|
return ( method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor() ); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
/** |
156
|
|
|
* Get's the current message path for display of a JITM |
157
|
|
|
* |
158
|
|
|
* @return string The message path |
159
|
|
|
*/ |
160
|
|
|
public function get_message_path() { |
161
|
|
|
$screen = get_current_screen(); |
162
|
|
|
|
163
|
|
|
return 'wp:' . $screen->id . ':' . current_filter(); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Injects the dom to show a JITM inside of wp-admin. |
168
|
|
|
*/ |
169
|
|
|
public function ajax_message() { |
170
|
|
|
if ( ! is_admin() ) { |
171
|
|
|
return; |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
// do not display on Gutenberg pages. |
175
|
|
|
if ( $this->is_gutenberg_page() ) { |
176
|
|
|
return; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
$message_path = $this->get_message_path(); |
180
|
|
|
$query_string = _http_build_query( $_GET, '', ',' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
181
|
|
|
$current_screen = wp_unslash( $_SERVER['REQUEST_URI'] ); |
182
|
|
|
?> |
183
|
|
|
<div class="jetpack-jitm-message" |
184
|
|
|
data-nonce="<?php echo esc_attr( wp_create_nonce( 'wp_rest' ) ); ?>" |
185
|
|
|
data-ajax-nonce="<?php echo esc_attr( wp_create_nonce( 'wp_ajax_action' ) ); ?>" |
186
|
|
|
data-message-path="<?php echo esc_attr( $message_path ); ?>" |
187
|
|
|
data-query="<?php echo urlencode_deep( $query_string ); ?>" |
188
|
|
|
data-redirect="<?php echo urlencode_deep( $current_screen ); ?>" |
189
|
|
|
></div> |
190
|
|
|
<?php |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Generate the icon to display on the JITM |
195
|
|
|
* |
196
|
|
|
* @param string $content_icon Icon type name. |
197
|
|
|
* @param bool $full_jp_logo_exists Is there a big JP logo already displayed on this screen. |
198
|
|
|
*/ |
199
|
|
|
public function generate_icon( $content_icon, $full_jp_logo_exists ) { |
200
|
|
|
switch ( $content_icon ) { |
201
|
|
|
case 'jetpack': |
202
|
|
|
$jetpack_logo = new Jetpack_Logo(); |
203
|
|
|
$content_icon = '<div class="jp-emblem">' . ( ( $full_jp_logo_exists ) ? $jetpack_logo->get_jp_emblem() : $jetpack_logo->get_jp_emblem_larger() ) . '</div>'; |
204
|
|
|
break; |
205
|
|
|
case 'woocommerce': |
206
|
|
|
$content_icon = '<div class="jp-emblem"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 168 100" xml:space="preserve" enable-background="new 0 0 168 100" width="50" height="30"><style type="text/css"> |
207
|
|
|
.st0{clip-path:url(#SVGID_2_);enable-background:new ;} |
208
|
|
|
.st1{clip-path:url(#SVGID_4_);} |
209
|
|
|
.st2{clip-path:url(#SVGID_6_);} |
210
|
|
|
.st3{clip-path:url(#SVGID_8_);fill:#8F567F;} |
211
|
|
|
.st4{clip-path:url(#SVGID_10_);fill:#FFFFFE;} |
212
|
|
|
.st5{clip-path:url(#SVGID_12_);fill:#FFFFFE;} |
213
|
|
|
.st6{clip-path:url(#SVGID_14_);fill:#FFFFFE;} |
214
|
|
|
</style><g><defs><polygon id="SVGID_1_" points="83.8 100 0 100 0 0.3 83.8 0.3 167.6 0.3 167.6 100 "/></defs><clipPath id="SVGID_2_"><use xlink:href="#SVGID_1_" overflow="visible"/></clipPath><g class="st0"><g><defs><rect id="SVGID_3_" width="168" height="100"/></defs><clipPath id="SVGID_4_"><use xlink:href="#SVGID_3_" overflow="visible"/></clipPath><g class="st1"><defs><path id="SVGID_5_" d="M15.6 0.3H152c8.6 0 15.6 7 15.6 15.6v52c0 8.6-7 15.6-15.6 15.6h-48.9l6.7 16.4L80.2 83.6H15.6C7 83.6 0 76.6 0 67.9v-52C0 7.3 7 0.3 15.6 0.3"/></defs><clipPath id="SVGID_6_"><use xlink:href="#SVGID_5_" overflow="visible"/></clipPath><g class="st2"><defs><rect id="SVGID_7_" width="168" height="100"/></defs><clipPath id="SVGID_8_"><use xlink:href="#SVGID_7_" overflow="visible"/></clipPath><rect x="-10" y="-9.7" class="st3" width="187.6" height="119.7"/></g></g></g></g></g><g><defs><path id="SVGID_9_" d="M8.4 14.5c1-1.3 2.4-2 4.3-2.1 3.5-0.2 5.5 1.4 6 4.9 2.1 14.3 4.4 26.4 6.9 36.4l15-28.6c1.4-2.6 3.1-3.9 5.2-4.1 3-0.2 4.9 1.7 5.6 5.7 1.7 9.1 3.9 16.9 6.5 23.4 1.8-17.4 4.8-30 9-37.7 1-1.9 2.5-2.9 4.5-3 1.6-0.1 3 0.3 4.3 1.4 1.3 1 2 2.3 2.1 3.9 0.1 1.2-0.1 2.3-0.7 3.3 -2.7 5-4.9 13.2-6.6 24.7 -1.7 11.1-2.3 19.8-1.9 26.1 0.1 1.7-0.1 3.2-0.8 4.5 -0.8 1.5-2 2.4-3.7 2.5 -1.8 0.1-3.6-0.7-5.4-2.5C52.4 66.7 47.4 57 43.7 44.1c-4.4 8.8-7.7 15.3-9.9 19.7 -4 7.7-7.5 11.7-10.3 11.9 -1.9 0.1-3.5-1.4-4.8-4.7 -3.5-9-7.3-26.3-11.3-52C7.1 17.3 7.5 15.8 8.4 14.5"/></defs><clipPath id="SVGID_10_"><use xlink:href="#SVGID_9_" overflow="visible"/></clipPath><rect x="-2.7" y="-0.6" class="st4" width="90.6" height="86.4"/></g><g><defs><path id="SVGID_11_" d="M155.6 25.2c-2.5-4.3-6.1-6.9-11-7.9 -1.3-0.3-2.5-0.4-3.7-0.4 -6.6 0-11.9 3.4-16.1 10.2 -3.6 5.8-5.3 12.3-5.3 19.3 0 5.3 1.1 9.8 3.3 13.6 2.5 4.3 6.1 6.9 11 7.9 1.3 0.3 2.5 0.4 3.7 0.4 6.6 0 12-3.4 16.1-10.2 3.6-5.9 5.3-12.4 5.3-19.4C159 33.4 157.9 28.9 155.6 25.2zM147 44.2c-0.9 4.5-2.7 7.9-5.2 10.1 -2 1.8-3.9 2.5-5.5 2.2 -1.7-0.3-3-1.8-4-4.4 -0.8-2.1-1.2-4.2-1.2-6.2 0-1.7 0.2-3.4 0.5-5 0.6-2.8 1.8-5.5 3.6-8.1 2.3-3.3 4.7-4.8 7.1-4.2 1.7 0.3 3 1.8 4 4.4 0.8 2.1 1.2 4.2 1.2 6.2C147.5 40.9 147.3 42.6 147 44.2z"/></defs><clipPath id="SVGID_12_"><use xlink:href="#SVGID_11_" overflow="visible"/></clipPath><rect x="109.6" y="6.9" class="st5" width="59.4" height="71.4"/></g><g><defs><path id="SVGID_13_" d="M112.7 25.2c-2.5-4.3-6.1-6.9-11-7.9 -1.3-0.3-2.5-0.4-3.7-0.4 -6.6 0-11.9 3.4-16.1 10.2 -3.5 5.8-5.3 12.3-5.3 19.3 0 5.3 1.1 9.8 3.3 13.6 2.5 4.3 6.1 6.9 11 7.9 1.3 0.3 2.5 0.4 3.7 0.4 6.6 0 12-3.4 16.1-10.2 3.5-5.9 5.3-12.4 5.3-19.4C116 33.4 114.9 28.9 112.7 25.2zM104.1 44.2c-0.9 4.5-2.7 7.9-5.2 10.1 -2 1.8-3.9 2.5-5.5 2.2 -1.7-0.3-3-1.8-4-4.4 -0.8-2.1-1.2-4.2-1.2-6.2 0-1.7 0.2-3.4 0.5-5 0.6-2.8 1.8-5.5 3.6-8.1 2.3-3.3 4.7-4.8 7.1-4.2 1.7 0.3 3 1.8 4 4.4 0.8 2.1 1.2 4.2 1.2 6.2C104.6 40.9 104.4 42.6 104.1 44.2z"/></defs><clipPath id="SVGID_14_"><use xlink:href="#SVGID_13_" overflow="visible"/></clipPath><rect x="66.7" y="6.9" class="st6" width="59.4" height="71.4"/></g></svg></div>'; |
215
|
|
|
break; |
216
|
|
|
default: |
217
|
|
|
$content_icon = ''; |
218
|
|
|
break; |
219
|
|
|
} |
220
|
|
|
return $content_icon; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Stores dismiss data into an option |
225
|
|
|
* |
226
|
|
|
* @param string $key Dismiss key. |
227
|
|
|
*/ |
228
|
|
|
public function save_dismiss( $key ) { |
229
|
|
|
$hide_jitm = \Jetpack_Options::get_option( 'hide_jitm' ); |
230
|
|
|
if ( ! is_array( $hide_jitm ) ) { |
231
|
|
|
$hide_jitm = array(); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
if ( ! isset( $hide_jitm[ $key ] ) || ! is_array( $hide_jitm[ $key ] ) ) { |
235
|
|
|
$hide_jitm[ $key ] = array( |
236
|
|
|
'last_dismissal' => 0, |
237
|
|
|
'number' => 0, |
238
|
|
|
); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
$hide_jitm[ $key ] = array( |
242
|
|
|
'last_dismissal' => time(), |
243
|
|
|
'number' => $hide_jitm[ $key ]['number'] + 1, |
244
|
|
|
); |
245
|
|
|
|
246
|
|
|
\Jetpack_Options::update_option( 'hide_jitm', $hide_jitm ); |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
/** |
250
|
|
|
* Sets the 'jetpack_last_plugin_sync' transient when the active_plugins option is synced. |
251
|
|
|
* |
252
|
|
|
* @param array $params The action parameters. |
253
|
|
|
* |
254
|
|
|
* @return array Returns the action parameters unchanged. |
255
|
|
|
*/ |
256
|
|
|
public function jetpack_track_last_sync_callback( $params ) { |
257
|
|
|
/** |
258
|
|
|
* This filter is documented in the Automattic\Jetpack\JITMS\Post_Connection_JITM class. |
259
|
|
|
*/ |
260
|
|
|
if ( ! apply_filters( 'jetpack_just_in_time_msg_cache', true ) ) { |
261
|
|
|
return $params; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
if ( is_array( $params ) && isset( $params[0] ) ) { |
265
|
|
|
$option = $params[0]; |
266
|
|
|
if ( 'active_plugins' === $option ) { |
267
|
|
|
// Use the cache if we can, but not terribly important if it gets evicted. |
268
|
|
|
set_transient( 'jetpack_last_plugin_sync', time(), HOUR_IN_SECONDS ); |
269
|
|
|
} |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
return $params; |
273
|
|
|
} |
274
|
|
|
} |
275
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.