RemoteInboxNotificationsEngine.php
6.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
<?php
/**
* Handles running specs
*/
namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
defined( 'ABSPATH' ) || exit;
use \Automattic\WooCommerce\Admin\PluginsProvider\PluginsProvider;
use \Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
use \Automattic\WooCommerce\Admin\Notes\Note;
/**
* Remote Inbox Notifications engine.
* This goes through the specs and runs (creates admin notes) for those
* specs that are able to be triggered.
*/
class RemoteInboxNotificationsEngine {
const STORED_STATE_OPTION_NAME = 'wc_remote_inbox_notifications_stored_state';
const WCA_UPDATED_OPTION_NAME = 'wc_remote_inbox_notifications_wca_updated';
/**
* Initialize the engine.
*/
public static function init() {
// Init things that need to happen before admin_init.
add_action( 'init', array( __CLASS__, 'on_init' ), 0, 0 );
// Continue init via admin_init.
add_action( 'admin_init', array( __CLASS__, 'on_admin_init' ) );
// Trigger when the profile data option is updated (during onboarding).
add_action(
'update_option_' . OnboardingProfile::DATA_OPTION,
array( __CLASS__, 'update_profile_option' ),
10,
2
);
// Hook into WCA updated. This is hooked up here rather than in
// on_admin_init because that runs too late to hook into the action.
add_action(
'woocommerce_updated',
function() {
$next_hook = WC()->queue()->get_next(
'woocommerce_run_on_woocommerce_admin_updated',
array( __CLASS__, 'run_on_woocommerce_admin_updated' ),
'woocommerce-remote-inbox-engine'
);
if ( $next_hook === null ) {
WC()->queue()->schedule_single(
time(),
'woocommerce_run_on_woocommerce_admin_updated',
array( __CLASS__, 'run_on_woocommerce_admin_updated' ),
'woocommerce-remote-inbox-engine'
);
}
}
);
add_filter( 'woocommerce_get_note_from_db', array( __CLASS__, 'get_note_from_db' ), 10, 1 );
}
/**
* This is triggered when the profile option is updated and if the
* profiler is being completed, triggers a run of the engine.
*
* @param mixed $old_value Old value.
* @param mixed $new_value New value.
*/
public static function update_profile_option( $old_value, $new_value ) {
// Return early if we're not completing the profiler.
if (
( isset( $old_value['completed'] ) && $old_value['completed'] ) ||
! isset( $new_value['completed'] ) ||
! $new_value['completed']
) {
return;
}
self::run();
}
/**
* Init is continued via admin_init so that WC is loaded when the product
* query is used, otherwise the query generates a "0 = 1" in the WHERE
* condition and thus doesn't return any results.
*/
public static function on_admin_init() {
add_action( 'activated_plugin', array( __CLASS__, 'run' ) );
add_action( 'deactivated_plugin', array( __CLASS__, 'run_on_deactivated_plugin' ), 10, 1 );
StoredStateSetupForProducts::admin_init();
// Pre-fetch stored state so it has the correct initial values.
self::get_stored_state();
}
/**
* An init hook is used here so that StoredStateSetupForProducts can set
* up a hook that gets triggered by action-scheduler - this is needed
* because the admin_init hook doesn't get triggered by WP Cron.
*/
public static function on_init() {
StoredStateSetupForProducts::init();
}
/**
* Go through the specs and run them.
*/
public static function run() {
$specs = DataSourcePoller::get_instance()->get_specs_from_data_sources();
if ( $specs === false || count( $specs ) === 0 ) {
return;
}
$stored_state = self::get_stored_state();
foreach ( $specs as $spec ) {
SpecRunner::run_spec( $spec, $stored_state );
}
}
/**
* Set an option indicating that WooCommerce Admin has just been updated,
* run the specs, then clear that option. This lets the
* WooCommerceAdminUpdatedRuleProcessor trigger on WCA update.
*/
public static function run_on_woocommerce_admin_updated() {
update_option( self::WCA_UPDATED_OPTION_NAME, true, false );
self::run();
update_option( self::WCA_UPDATED_OPTION_NAME, false, false );
}
/**
* Gets the stored state option, and does the initial set up if it doesn't
* already exist.
*
* @return object The stored state option.
*/
public static function get_stored_state() {
$stored_state = get_option( self::STORED_STATE_OPTION_NAME );
if ( $stored_state === false ) {
$stored_state = new \stdClass();
$stored_state = StoredStateSetupForProducts::init_stored_state(
$stored_state
);
add_option(
self::STORED_STATE_OPTION_NAME,
$stored_state,
'',
false
);
}
return $stored_state;
}
/**
* The deactivated_plugin hook happens before the option is updated
* (https://github.com/WordPress/WordPress/blob/master/wp-admin/includes/plugin.php#L826)
* so this captures the deactivated plugin path and pushes it into the
* PluginsProvider.
*
* @param string $plugin Path to the plugin file relative to the plugins directory.
*/
public static function run_on_deactivated_plugin( $plugin ) {
PluginsProvider::set_deactivated_plugin( $plugin );
self::run();
}
/**
* Update the stored state option.
*
* @param object $stored_state The stored state.
*/
public static function update_stored_state( $stored_state ) {
update_option( self::STORED_STATE_OPTION_NAME, $stored_state, false );
}
/**
* Get the note. This is used to display localized note.
*
* @param Note $note_from_db The note object created from db.
* @return Note The note.
*/
public static function get_note_from_db( $note_from_db ) {
if ( ! $note_from_db instanceof Note || get_user_locale() === $note_from_db->get_locale() ) {
return $note_from_db;
}
$specs = DataSourcePoller::get_instance()->get_specs_from_data_sources();
foreach ( $specs as $spec ) {
if ( $spec->slug !== $note_from_db->get_name() ) {
continue;
}
$locale = SpecRunner::get_locale( $spec->locales, true );
if ( $locale === null ) {
// No locale found, so don't update the note.
break;
}
$note_from_db->set_title( $locale->title );
$note_from_db->set_content( $locale->content );
$note_from_db->set_actions( SpecRunner::get_actions( $spec ) );
}
return $note_from_db;
}
}