PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 10.9.1
WooCommerce v10.9.1
10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / src / Admin / RemoteInboxNotifications / RemoteInboxNotificationsEngine.php
woocommerce / src / Admin / RemoteInboxNotifications Last commit date
RemoteInboxNotificationsDataSourcePoller.php 2 months ago RemoteInboxNotificationsEngine.php 1 year ago RuleProcessorInterface.php 1 year ago SpecRunner.php 4 weeks ago TransformerInterface.php 1 year ago
RemoteInboxNotificationsEngine.php
343 lines
1 <?php
2 /**
3 * Handles running specs
4 */
5
6 namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
7
8 defined( 'ABSPATH' ) || exit;
9
10 use Automattic\WooCommerce\Admin\Features\Features;
11 use Automattic\WooCommerce\Admin\Notes\Notes;
12 use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProvider;
13 use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
14 use Automattic\WooCommerce\Admin\Notes\Note;
15 use Automattic\WooCommerce\Admin\RemoteSpecs\RemoteSpecsEngine;
16 use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\StoredStateSetupForProducts;
17
18 /**
19 * Remote Inbox Notifications engine.
20 * This goes through the specs and runs (creates admin notes) for those
21 * specs that are able to be triggered.
22 */
23 class RemoteInboxNotificationsEngine extends RemoteSpecsEngine {
24 const STORED_STATE_OPTION_NAME = 'wc_remote_inbox_notifications_stored_state';
25 const WCA_UPDATED_OPTION_NAME = 'wc_remote_inbox_notifications_wca_updated';
26
27 /**
28 * Initialize the engine.
29 * phpcs:disable WooCommerce.Functions.InternalInjectionMethod.MissingFinal
30 * phpcs:disable WooCommerce.Functions.InternalInjectionMethod.MissingInternalTag
31 */
32 public static function init() {
33 // Init things that need to happen before admin_init.
34 add_action( 'init', array( __CLASS__, 'on_init' ), 0, 0 );
35
36 // Continue init via admin_init.
37 add_action( 'admin_init', array( __CLASS__, 'on_admin_init' ) );
38
39 // Trigger when the profile data option is updated (during onboarding).
40 add_action(
41 'update_option_' . OnboardingProfile::DATA_OPTION,
42 array( __CLASS__, 'update_profile_option' ),
43 10,
44 2
45 );
46
47 // Hook into WCA updated. This is hooked up here rather than in
48 // on_admin_init because that runs too late to hook into the action.
49 add_action(
50 'woocommerce_run_on_woocommerce_admin_updated',
51 array( __CLASS__, 'run_on_woocommerce_admin_updated' )
52 );
53 add_action(
54 'woocommerce_updated',
55 function () {
56 $next_hook = WC()->queue()->get_next(
57 'woocommerce_run_on_woocommerce_admin_updated',
58 array(),
59 'woocommerce-remote-inbox-engine'
60 );
61 if ( null === $next_hook ) {
62 WC()->queue()->schedule_single(
63 time(),
64 'woocommerce_run_on_woocommerce_admin_updated',
65 array(),
66 'woocommerce-remote-inbox-engine'
67 );
68 }
69 }
70 );
71
72 add_filter( 'woocommerce_get_note_from_db', array( __CLASS__, 'get_note_from_db' ), 10, 1 );
73 add_filter( 'woocommerce_debug_tools', array( __CLASS__, 'add_debug_tools' ) );
74 add_action(
75 'wp_ajax_woocommerce_json_inbox_notifications_search',
76 array( __CLASS__, 'ajax_action_inbox_notification_search' )
77 );
78 }
79
80 /**
81 * This is triggered when the profile option is updated and if the
82 * profiler is being completed, triggers a run of the engine.
83 *
84 * @param mixed $old_value Old value.
85 * @param mixed $new_value New value.
86 */
87 public static function update_profile_option( $old_value, $new_value ) {
88 // Return early if we're not completing the profiler.
89 if (
90 ( isset( $old_value['completed'] ) && $old_value['completed'] ) ||
91 ! isset( $new_value['completed'] ) ||
92 ! $new_value['completed']
93 ) {
94 return;
95 }
96
97 self::run();
98 }
99
100 /**
101 * Init is continued via admin_init so that WC is loaded when the product
102 * query is used, otherwise the query generates a "0 = 1" in the WHERE
103 * condition and thus doesn't return any results.
104 */
105 public static function on_admin_init() {
106 add_action( 'activated_plugin', array( __CLASS__, 'run' ) );
107 add_action( 'deactivated_plugin', array( __CLASS__, 'run_on_deactivated_plugin' ), 10, 1 );
108 StoredStateSetupForProducts::admin_init();
109
110 // Pre-fetch stored state so it has the correct initial values.
111 self::get_stored_state();
112 }
113
114 /**
115 * An init hook is used here so that StoredStateSetupForProducts can set
116 * up a hook that gets triggered by action-scheduler - this is needed
117 * because the admin_init hook doesn't get triggered by WP Cron.
118 */
119 public static function on_init() {
120 StoredStateSetupForProducts::init();
121 }
122
123 /**
124 * Go through the specs and run them.
125 */
126 public static function run() {
127 $specs = RemoteInboxNotificationsDataSourcePoller::get_instance()->get_specs_from_data_sources();
128
129 if ( false === $specs || ! is_countable( $specs ) || count( $specs ) === 0 ) {
130 return;
131 }
132
133 $stored_state = self::get_stored_state();
134 $errors = array();
135
136 foreach ( $specs as $spec ) {
137 $error = SpecRunner::run_spec( $spec, $stored_state );
138 if ( isset( $error ) ) {
139 $errors[] = $error;
140 }
141 }
142
143 if ( count( $errors ) > 0 ) {
144 self::log_errors( $errors );
145 }
146 }
147
148 /**
149 * Set an option indicating that WooCommerce Admin has just been updated,
150 * run the specs, then clear that option. This lets the
151 * WooCommerceAdminUpdatedRuleProcessor trigger on WCA update.
152 */
153 public static function run_on_woocommerce_admin_updated() {
154 update_option( self::WCA_UPDATED_OPTION_NAME, true, false );
155
156 self::run();
157
158 update_option( self::WCA_UPDATED_OPTION_NAME, false, false );
159 }
160
161 /**
162 * Gets the stored state option, and does the initial set up if it doesn't
163 * already exist.
164 *
165 * @return object The stored state option.
166 */
167 public static function get_stored_state() {
168 $stored_state = get_option( self::STORED_STATE_OPTION_NAME );
169
170 if ( false === $stored_state || ! is_object( $stored_state ) ) {
171 $stored_state = new \stdClass();
172
173 $stored_state = StoredStateSetupForProducts::init_stored_state(
174 $stored_state
175 );
176
177 update_option(
178 self::STORED_STATE_OPTION_NAME,
179 $stored_state,
180 false
181 );
182 }
183
184 return $stored_state;
185 }
186
187 /**
188 * The deactivated_plugin hook happens before the option is updated
189 * (https://github.com/WordPress/WordPress/blob/master/wp-admin/includes/plugin.php#L826)
190 * so this captures the deactivated plugin path and pushes it into the
191 * PluginsProvider.
192 *
193 * @param string $plugin Path to the plugin file relative to the plugins directory.
194 */
195 public static function run_on_deactivated_plugin( $plugin ) {
196 PluginsProvider::set_deactivated_plugin( $plugin );
197 self::run();
198 }
199
200 /**
201 * Update the stored state option.
202 *
203 * @param object $stored_state The stored state.
204 */
205 public static function update_stored_state( $stored_state ) {
206 update_option( self::STORED_STATE_OPTION_NAME, $stored_state, false );
207 }
208
209 /**
210 * Get the note. This is used to display localized note.
211 *
212 * @param Note $note_from_db The note object created from db.
213 *
214 * @return Note The note.
215 */
216 public static function get_note_from_db( $note_from_db ) {
217 if ( ! $note_from_db instanceof Note || get_user_locale() === $note_from_db->get_locale() ) {
218 return $note_from_db;
219 }
220 $specs = RemoteInboxNotificationsDataSourcePoller::get_instance()->get_specs_from_data_sources();
221 foreach ( $specs as $spec ) {
222 if ( $spec->slug !== $note_from_db->get_name() ) {
223 continue;
224 }
225 $locale = SpecRunner::get_locale( $spec->locales, true );
226 if ( null === $locale ) {
227 // No locale found, so don't update the note.
228 break;
229 }
230
231 $localized_actions = SpecRunner::get_actions( $spec );
232
233 // Manually copy the action id from the db to the localized action, since they were not being provided.
234 foreach ( $localized_actions as $localized_action ) {
235 $action = $note_from_db->get_action( $localized_action->name );
236 if ( $action ) {
237 $localized_action->id = $action->id;
238 }
239 }
240
241 $note_from_db->set_title( $locale->title );
242 $note_from_db->set_content( $locale->content );
243 $note_from_db->set_actions( $localized_actions );
244 }
245
246 return $note_from_db;
247 }
248
249 /**
250 * Add the debug tools to the WooCommerce debug tools (WooCommerce > Status > Tools).
251 *
252 * @param array $tools a list of tools.
253 *
254 * @return mixed
255 *
256 * @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
257 */
258 public static function add_debug_tools( $tools ) {
259 // Check if the feature flag is disabled.
260 if ( ! Features::is_enabled( 'remote-inbox-notifications' ) ) {
261 return false;
262 }
263
264 // Check if the site has opted out of marketplace suggestions.
265 if ( get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) !== 'yes' ) {
266 return false;
267 }
268
269 $tools['refresh_remote_inbox_notifications'] = array(
270 'name' => __( 'Refresh Remote Inbox Notifications', 'woocommerce' ),
271 'button' => __( 'Refresh', 'woocommerce' ),
272 'desc' => __( 'This will refresh the remote inbox notifications', 'woocommerce' ),
273 'callback' => function () {
274 RemoteInboxNotificationsDataSourcePoller::get_instance()->read_specs_from_data_sources();
275 RemoteInboxNotificationsEngine::run();
276
277 return __( 'Remote inbox notifications have been refreshed', 'woocommerce' );
278 },
279 );
280
281 $tools['delete_inbox_notification'] = array(
282 'name' => __( 'Delete an Inbox Notification', 'woocommerce' ),
283 'button' => __( 'Delete', 'woocommerce' ),
284 'desc' => __( 'This will delete an inbox notification by slug', 'woocommerce' ),
285 'selector' => array(
286 'description' => __( 'Select an inbox notification to delete:', 'woocommerce' ),
287 'class' => 'wc-product-search',
288 'search_action' => 'woocommerce_json_inbox_notifications_search',
289 'name' => 'delete_inbox_notification_note_id',
290 'placeholder' => esc_attr__( 'Search for an inbox notification&hellip;', 'woocommerce' ),
291 ),
292 'callback' => function () {
293 check_ajax_referer( 'debug_action', '_wpnonce' );
294
295 if ( ! isset( $_GET['delete_inbox_notification_note_id'] ) ) {
296 return __( 'No inbox notification selected', 'woocommerce' );
297 }
298 $note_id = wc_clean( sanitize_text_field( wp_unslash( $_GET['delete_inbox_notification_note_id'] ) ) );
299 $note = Notes::get_note( $note_id );
300
301 if ( ! $note ) {
302 return __( 'Inbox notification not found', 'woocommerce' );
303 }
304
305 $note->delete( true );
306 return __( 'Inbox notification has been deleted', 'woocommerce' );
307 },
308 );
309
310 return $tools;
311 }
312
313 /**
314 * Add ajax action for remote inbox notification search.
315 *
316 * @return void
317 *
318 * @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
319 */
320 public static function ajax_action_inbox_notification_search() {
321 global $wpdb;
322
323 check_ajax_referer( 'search-products', 'security' );
324
325 if ( ! isset( $_GET['term'] ) ) {
326 wp_send_json( array() );
327 }
328
329 $search = wc_clean( sanitize_text_field( wp_unslash( $_GET['term'] ) ) );
330 $results = $wpdb->get_results(
331 $wpdb->prepare(
332 "SELECT note_id, name FROM {$wpdb->prefix}wc_admin_notes WHERE name LIKE %s",
333 '%' . $wpdb->esc_like( $search ) . '%'
334 )
335 );
336 $rows = array();
337 foreach ( $results as $result ) {
338 $rows[ $result->note_id ] = $result->name;
339 }
340 wp_send_json( $rows );
341 }
342 }
343