PluginProbe
WP Discourse / trunk
WP Discourse vtrunk
2.6.4 2.6.3 1.2.1 1.2.2 1.2.5 1.2.6 1.2.7 1.2.8 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.85 1.4.0 1.4.15 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 All 150 releases
wp-discourse / admin / network-options.php

network-options.php in WP Discourse trunk, at admin/network-options.php

959 lines 29.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Network Options.
4 *
5 * @package WPDiscourse
6 */
7
8 namespace WPDiscourse\Admin;
9
10 use WPDiscourse\Shared\PluginUtilities;
11
12 /**
13 * Class NetworkOptions
14 *
15 * Saves site_options with matching keys to the blog_options to the 'wpdc_site_options' array.
16 */
17 class NetworkOptions {
18 use PluginUtilities;
19
20 /**
21 * NetworkOptions constructor.
22 */
23 public function __construct() {
24 add_action( 'admin_init', array( $this, 'setup' ) );
25 add_action( 'network_admin_menu', array( $this, 'add_network_settings_page' ) );
26 add_action( 'network_admin_edit_discourse_network_options', array( $this, 'save_network_settings' ) );
27
28 add_action( 'network_admin_notices', array( $this, 'network_config_notices' ) );
29 }
30
31 /**
32 * Adds settings section and settings fields.
33 */
34 public function setup() {
35
36 add_settings_section(
37 'discourse_network_settings_section',
38 __( 'Multisite Configuration', 'wp-discourse' ),
39 array(
40 $this,
41 'network_settings_details',
42 ),
43 'discourse_network_options'
44 );
45
46 add_settings_field(
47 'discourse_network_multisite_configuration',
48 __( 'Enable Multisite Configuration', 'wp-discourse' ),
49 array(
50 $this,
51 'multisite_configuration_checkbox',
52 ),
53 'discourse_network_options',
54 'discourse_network_settings_section'
55 );
56
57 add_settings_field(
58 'discourse_network_url',
59 __( 'Discourse URL', 'wp-discourse' ),
60 array(
61 $this,
62 'url_input',
63 ),
64 'discourse_network_options',
65 'discourse_network_settings_section'
66 );
67
68 add_settings_field(
69 'discourse_network_api_key',
70 __( 'API Key', 'wp-discourse' ),
71 array(
72 $this,
73 'api_key_input',
74 ),
75 'discourse_network_options',
76 'discourse_network_settings_section'
77 );
78
79 add_settings_field(
80 'discourse_network_publish_username',
81 __( 'Publishing Username', 'wp-discourse' ),
82 array(
83 $this,
84 'publish_username_input',
85 ),
86 'discourse_network_options',
87 'discourse_network_settings_section'
88 );
89
90 add_settings_field(
91 'discourse_network_connection_logs',
92 __( 'Connection Logs', 'wp-discourse' ),
93 array(
94 $this,
95 'connection_logs',
96 ),
97 'discourse_network_options',
98 'discourse_network_settings_section'
99 );
100
101 add_settings_field(
102 'discourse_network_use_discourse_webhook',
103 __( 'Sync Comment Data', 'wp-discourse' ),
104 array(
105 $this,
106 'use_discourse_webhook_checkbox',
107 ),
108 'discourse_network_options',
109 'discourse_network_settings_section'
110 );
111
112 add_settings_field(
113 'discourse_network_use_discourse_user_webhook',
114 __( 'Update Userdata', 'wp-discourse' ),
115 array(
116 $this,
117 'use_discourse_user_webhook_checkbox',
118 ),
119 'discourse_network_options',
120 'discourse_network_settings_section'
121 );
122
123 add_settings_field(
124 'discourse_network_webhook_match_user_email',
125 __( 'Match Users by Email Address', 'wp-discourse' ),
126 array(
127 $this,
128 'webhook_match_user_email_checkbox',
129 ),
130 'discourse_network_options',
131 'discourse_network_settings_section'
132 );
133
134 add_settings_field(
135 'discourse_network_webhook_secret',
136 __( 'Webhook Secret Key', 'wp-discourse' ),
137 array(
138 $this,
139 'webhook_secret_input',
140 ),
141 'discourse_network_options',
142 'discourse_network_settings_section'
143 );
144
145 add_settings_field(
146 'discourse_network_verbose_webhook_logs',
147 __( 'Verbose Webhook Logs', 'wp-discourse' ),
148 array(
149 $this,
150 'verbose_webhook_logs',
151 ),
152 'discourse_network_options',
153 'discourse_network_settings_section'
154 );
155
156 add_settings_field(
157 'discourse_network_hide_name_field',
158 __( 'Do Not Display Discourse Name Field', 'wp-discourse' ),
159 array(
160 $this,
161 'hide_discourse_name_field_checkbox',
162 ),
163 'discourse_network_options',
164 'discourse_network_settings_section'
165 );
166
167 add_settings_field(
168 'discourse_network_verbose_publication_logs',
169 __( 'Verbose Publication Logs', 'wp-discourse' ),
170 array(
171 $this,
172 'verbose_publication_logs',
173 ),
174 'discourse_network_options',
175 'discourse_network_settings_section'
176 );
177
178 add_settings_field(
179 'discourse_network_verbose_comment_logs',
180 __( 'Verbose Comment Logs', 'wp-discourse' ),
181 array(
182 $this,
183 'verbose_comment_logs',
184 ),
185 'discourse_network_options',
186 'discourse_network_settings_section'
187 );
188
189 add_settings_field(
190 'discourse_network_enable_sso',
191 __( 'Enable DiscourseConnect Provider', 'wp-discourse' ),
192 array(
193 $this,
194 'enable_sso_provider_checkbox',
195 ),
196 'discourse_network_options',
197 'discourse_network_settings_section'
198 );
199
200 add_settings_field(
201 'discourse_network_enable_discourse_sso',
202 __( 'Enable DiscourseConnect Client', 'wp-discourse' ),
203 array(
204 $this,
205 'enable_sso_client_checkbox',
206 ),
207 'discourse_network_options',
208 'discourse_network_settings_section'
209 );
210
211 add_settings_field(
212 'discourse_network_sso_secret',
213 __( 'DiscourseConnect Secret Key', 'wp-discourse' ),
214 array(
215 $this,
216 'sso_secret_input',
217 ),
218 'discourse_network_options',
219 'discourse_network_settings_section'
220 );
221
222 add_settings_field(
223 'discourse_network_verbose_sso_logs',
224 __( 'Verbose DiscourseConnect Logs', 'wp-discourse' ),
225 array(
226 $this,
227 'verbose_sso_logs',
228 ),
229 'discourse_network_options',
230 'discourse_network_settings_section'
231 );
232 }
233
234 /**
235 * Adds the network menu page.
236 */
237 public function add_network_settings_page() {
238 add_menu_page(
239 __( 'Discourse', 'wp-discourse' ),
240 __( 'Discourse', 'wp-discourse' ),
241 'manage_network_options',
242 'discourse_network_options',
243 array( $this, 'network_options_page' ),
244 WPDISCOURSE_LOGO,
245 5
246 );
247 }
248
249 /**
250 * ******************************
251 *
252 * Multisite Configuration Fields.
253 *********************************/
254
255 /**
256 * Outputs markup for multisite-configuration-enabled-checkbox.
257 */
258 public function multisite_configuration_checkbox() {
259 $this->checkbox_input(
260 'multisite-configuration-enabled',
261 __( 'Configure the plugin for a WordPress multisite setup.', 'wp-discourse' ),
262 __(
263 "Enabling this setting will create a wpdc_topic_blog database table so that Discourse topics can be associated
264 with the blog they were posted from. This makes it possible to sync topic data between Discourse and WordPress with a single webhook.
265 When Multisite Configuration is enabled, the settings on this page will be used to configure their related settings on your network's subsites.",
266 'wp-discourse'
267 )
268 );
269 $this->next_setting_heading( __( 'Connection Settings', 'wp-discourse' ) );
270 }
271
272 /**
273 * ***************************
274 *
275 * Connection Settings Fields.
276 *****************************/
277
278 /**
279 * Outputs markup for the url input.
280 */
281 public function url_input() {
282 $this->input( 'url', __( 'The base URL of your forum, for example http://discourse.example.com', 'wp-discourse' ), 'url' );
283 }
284
285 /**
286 * Outputs markup for the api-key input.
287 */
288 public function api_key_input() {
289 $url = $this->get_site_option( 'url' );
290 if ( $url ) {
291 $this->input(
292 'api-key',
293 __( 'Found on your forum at ', 'wp-discourse' ) . '<a href="' . esc_url( $url ) .
294 '/admin/api/keys" target="_blank" rel="noreferrer noopener">' . esc_url( $url ) . '/admin/api/keys</a>. ' .
295 "If you haven't yet created an API key, Click 'New API Key', set User Level to 'Single User', set 'User' to an admin account, select 'Global Key' and click 'Save'. Copy and paste the API key here.",
296 'wp-discourse'
297 );
298 } else {
299 $this->input(
300 'api-key',
301 __(
302 "Found on your forum at /admin/api/keys.
303 If you haven't yet created an API key, Click 'New API Key', set User Level to 'Single User', set 'User' to an admin account, select 'Global Key' and click 'Save'. Copy and paste the API key here.",
304 'wp-discourse'
305 )
306 );
307 }
308 }
309
310 /**
311 * Outputs markup for the publish-username input.
312 */
313 public function publish_username_input() {
314 $this->input(
315 'publish-username',
316 __(
317 'The default Discourse username under which WordPress posts will be published on your forum.
318 The Publishing Username is also used for making API calls to Discourse. It must be set to a Discourse admin username.',
319 'wp-discourse'
320 ),
321 null,
322 null,
323 null,
324 'system'
325 );
326 }
327
328 /**
329 * Outputs markup for the discourse_connection_logs checkbox.
330 */
331 public function connection_logs() {
332 $this->checkbox_input(
333 'connection-logs',
334 __(
335 'Enable connection logs.',
336 'wp-discourse'
337 ),
338 __( 'Log attempts to check the connection with Discourse.', 'wp-discourse' )
339 );
340 $this->next_setting_heading( __( 'Webhook Settings', 'wp-discourse' ) );
341 }
342
343 /**
344 * ************************
345 *
346 * Webhook Settings Fields.
347 **************************/
348
349 /**
350 * Outputs markup for use-discourse-webhook checkbox.
351 */
352 public function use_discourse_webhook_checkbox() {
353 $webhook_payload_url = network_site_url( '/wp-json/wp-discourse/v1/update-topic-content' );
354 $discourse_url = $this->get_site_option( 'url' );
355 if ( ! empty( $discourse_url ) ) {
356 $discourse_webhooks_url = '<a href="' . esc_url( $discourse_url ) . '/admin/api/web_hooks" target="_blank" rel="noreferrer noopener">' .
357 esc_url( $discourse_url ) . '/admin/api/web_hooks</a>';
358 } else {
359 $discourse_webhooks_url = 'http://forum.example.com/admin/api/web_hooks';
360 }
361
362 $description = sprintf(
363 // translators: Discourse webhook description. Placeholder: discourse_webhook_url, webhook_payload_url.
364 __(
365 '<strong>URL:</strong><code>%2$s</code>
366 <strong>Events:</strong> "Post is created", "Post is updated".',
367 'wp-discourse'
368 ),
369 $discourse_webhooks_url,
370 $webhook_payload_url
371 );
372
373 $this->checkbox_input(
374 'use-discourse-webhook',
375 __(
376 'Enable the Sync Comment Data webhook endpoint.',
377 'wp-discourse'
378 ),
379 $description
380 );
381 }
382
383 /**
384 * Outputs markup for use-discourse-user-webhook checkbox.
385 */
386 public function use_discourse_user_webhook_checkbox() {
387 $webhook_payload_url = network_site_url( '/wp-json/wp-discourse/v1/update-user' );
388 $url = $this->get_site_option( 'url' );
389 if ( ! empty( $url ) ) {
390 $discourse_webhooks_url = '<a href="' . esc_url( $url ) . '/admin/api/web_hooks" target="_blank" rel="noreferrer noopener">' .
391 esc_url( $url ) . '/admin/api/web_hooks</a>';
392 } else {
393 $discourse_webhooks_url = 'http://forum.example.com/admin/api/web_hooks';
394 }
395
396 $description = sprintf(
397 // translators: Discourse webhook description. Placeholder: discourse_webhook_url, webhook_payload_url.
398 __(
399 '<strong>URL:</strong><code>%2$s</code>
400 <strong>Events:</strong> "User is created", "User is Updated".',
401 'wp-discourse'
402 ),
403 $discourse_webhooks_url,
404 $webhook_payload_url
405 );
406
407 $this->checkbox_input( 'use-discourse-user-webhook', __( 'Enable the Update Userdata webhook endpoint.', 'wp-discourse' ), $description );
408 }
409
410 /**
411 * Outputs markup for the webhook-match-user-email-checkbox.
412 */
413 public function webhook_match_user_email_checkbox() {
414 $this->checkbox_input(
415 'webhook-match-user-email',
416 __(
417 'Match WordPress users with Discourse users by email.',
418 'wp-discourse'
419 ),
420 __(
421 'Update Userdata will attempt to match users by email if other methods of matching have not worked.',
422 'wp-discourse'
423 )
424 );
425 }
426
427 /**
428 * Outputs markup for webhook-secret input.
429 */
430 public function webhook_secret_input() {
431 $description = __(
432 'String of text at least 12 characters long.',
433 'wp-discourse'
434 );
435 $this->input( 'webhook-secret', $description );
436 }
437
438 /**
439 * Outputs markup for the verbose-webhook-logs checkbox.
440 */
441 public function verbose_webhook_logs() {
442 $this->checkbox_input(
443 'verbose-webhook-logs',
444 __(
445 'Enable verbose logs for webhooks.',
446 'wp-discourse'
447 ),
448 __( 'Will log successful syncs as well as errors.', 'wp-discourse' )
449 );
450 $this->next_setting_heading( __( 'Publishing Settings', 'wp-discourse' ) );
451 }
452
453 /**
454 * ***********************
455 *
456 * Publish Settings Fields.
457 **************************/
458
459 /**
460 * Outputs markup for hide-discourse-name-field checkbox.
461 */
462 public function hide_discourse_name_field_checkbox() {
463 $this->checkbox_input(
464 'hide-discourse-name-field',
465 __(
466 'Removes the Discourse Username field
467 from the WordPress user profile page.',
468 'wp-discourse'
469 ),
470 __(
471 'If you enable this setting and also enable the Update
472 Userdata webhook, new users created on Discourse will have the their Discourse Username automatically filled in and be
473 uneditable on WordPress.',
474 'wp-discourse'
475 )
476 );
477 }
478
479 /**
480 * Outputs markup for the verbose-publication-logs checkbox.
481 */
482 public function verbose_publication_logs() {
483 $this->checkbox_input(
484 'verbose-publication-logs',
485 __(
486 'Enable verbose logs for publication.',
487 'wp-discourse'
488 ),
489 __( 'Will log successful publications as well as errors.', 'wp-discourse' )
490 );
491 $this->next_setting_heading( __( 'Comment Settings', 'wp-discourse' ) );
492 }
493
494 /**
495 * ***********************
496 *
497 * Comment Settings Fields.
498 **************************/
499
500 /**
501 * Outputs markup for the verbose-comment-logs checkbox.
502 */
503 public function verbose_comment_logs() {
504 $this->checkbox_input(
505 'verbose-comment-logs',
506 __(
507 'Enable verbose logs for comments.',
508 'wp-discourse'
509 ),
510 __( 'Will log successful operations as well as errors.', 'wp-discourse' )
511 );
512 $this->next_setting_heading( __( 'DiscourseConnect Settings', 'wp-discourse' ) );
513 }
514
515 /**
516 * *******************
517 *
518 * DiscourseConnect Settings Fields.
519 **********************/
520
521
522 /**
523 * Outputs markup for the enable-sso checkbox.
524 */
525 public function enable_sso_provider_checkbox() {
526 $sso_documentation_url = get_admin_url( BLOG_ID_CURRENT_SITE, '/admin.php?page=wp_discourse_options&tab=sso_provider&parent_tab=sso_options' );
527 $sso_documentation_link = '<a href="' . esc_url( $sso_documentation_url ) . '" target="_blank" rel="noreferrer noopener">' . __( 'DiscourseConnect Provider tab', 'wp-discourse' ) . '</a>';
528 $description = __( 'Use this WordPress instance as the DiscourseConnect provider for your Discourse forum.', 'wp-discourse' );
529 $details = sprintf(
530 // translators: enable_sso_provider input. Placeholder: sso_documentation_link.
531 __( 'For details about using WordPress as the DiscourseConnect Provider, please visit the %1s of the main site in your network.', 'wp-discourse' ),
532 $sso_documentation_link
533 );
534 $this->checkbox_input( 'enable-sso', $description, $details );
535 }
536
537 /**
538 * Outputs markup for sso-client-enabled checkbox.
539 */
540 public function enable_sso_client_checkbox() {
541 $sso_documentation_url = get_admin_url( BLOG_ID_CURRENT_SITE, '/admin.php?page=wp_discourse_options&tab=sso_client&parent_tab=sso_options' );
542 $sso_documentation_link = '<a href="' . esc_url( $sso_documentation_url ) . '" target="_blank" rel="noreferrer noopener">' . __( 'DiscourseConnect Client tab', 'wp-discourse' ) . '</a>';
543 $description = __( 'Allow your WordPress site to function as a DiscourseConnect client to Discourse.', 'wp-discourse' );
544 $details = sprintf(
545 // translators: enable_sso_client checkbox. Placeholder: sso_documentation_link.
546 __( 'For details about using WordPress as a DiscourseConnect Client for Discourse, please visit the %1s of the main site in your network.', 'wp-discourse' ),
547 $sso_documentation_link
548 );
549 $this->checkbox_input( 'sso-client-enabled', $description, $details );
550 }
551
552 /**
553 * Outputs markup for the sso-secret input.
554 */
555 public function sso_secret_input() {
556 $url = $this->get_site_option( 'url' );
557 if ( ! empty( $url ) ) {
558 $discourse_sso_url = '<a href="' . esc_url( $url ) . '/admin/site_settings/category/all_results?filter=sso" target="_blank" rel="noreferrer noopener">' .
559 esc_url( $url ) . '/admin/site_settings/category/all_results?filter=sso</a>';
560 } else {
561 $discourse_sso_url = 'http://forum.example.com/admin/site_settings/category/all_results?filter=sso';
562 }
563
564 $description = sprintf(
565 // translators: SSO secret input. Placeholder: discourse_sso_url.
566 __(
567 'The secret key used to verify Discourse DiscourseConnect requests. Set it to a string of text, at least 10
568 characters long. It needs to match the key set at %1$s.',
569 'wp-discourse'
570 ),
571 $discourse_sso_url
572 );
573 $this->input( 'sso-secret', $description );
574 }
575
576 /**
577 * Outputs markup for the verbose-sso-logs checkbox.
578 */
579 public function verbose_sso_logs() {
580 $this->checkbox_input(
581 'verbose-sso-logs',
582 __(
583 'Enable verbose logs for DiscourseConnect.',
584 'wp-discourse'
585 ),
586 __( 'Will log successful operations as well as errors.', 'wp-discourse' )
587 );
588 }
589
590 /**
591 * Creates the network options page.
592 */
593 public function network_options_page() {
594 if ( ! current_user_can( 'manage_network_options' ) ) {
595
596 exit;
597 }
598 $action_url = add_query_arg(
599 'action',
600 'discourse_network_options',
601 network_admin_url( 'edit.php' )
602 )
603 ?>
604 <div class="wrap discourse-options-page-wrap">
605 <h2>
606 <img
607 src="<?php echo esc_attr( WPDISCOURSE_LOGO ); ?>"
608 alt="Discourse logo" class="discourse-logo">
609 <?php esc_html_e( 'WP Discourse Network Settings', 'wp-discourse' ); ?>
610 </h2>
611
612 <form class="wp-discourse-network-options-form" action="<?php echo esc_url( $action_url ); ?>"
613 method="post">
614 <?php wp_nonce_field( 'update_discourse_network_options', 'update_discourse_network_options_nonce' ); ?>
615 <?php
616 settings_fields( 'discourse_network_options' );
617 do_settings_sections( 'discourse_network_options' );
618 submit_button( 'Save Options', 'primary', 'discourse_save_options', false );
619 ?>
620 </form>
621 </div>
622 <?php
623 }
624
625 /**
626 * Saves the options.
627 *
628 * @return null
629 */
630 public function save_network_settings() {
631 if ( ! isset( $_POST['update_discourse_network_options_nonce'] ) || // Input var okay.
632 ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['update_discourse_network_options_nonce'] ) ), 'update_discourse_network_options' ) // Input var okay.
633 ) {
634
635 return null;
636 }
637
638 if ( ! current_user_can( 'manage_network_options' ) ) {
639
640 return null;
641 }
642 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
643
644 return null;
645 }
646
647 if ( isset( $_POST['wpdc_site_options'] ) ) { // Input var okay.
648
649 // See: https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/wiki/Sanitizing-array-input-data.
650 // @codingStandardsIgnoreStart
651 $site_options = array_map( array( $this, 'sanitize_item' ), wp_unslash( $_POST['wpdc_site_options'] ) ); // Input var okay.
652 // @codingStandardsIgnoreEnd
653 $this->validate_site_options( $site_options );
654 }
655
656 wp_redirect(
657 add_query_arg(
658 array(
659 'page' => 'discourse_network_options',
660 'updated' => 'true',
661 ),
662 network_admin_url( 'admin.php' )
663 )
664 );
665
666 exit();
667 }
668
669 /**
670 * A callback function used for sanitizing array values.
671 *
672 * @param string $item The item to be sanitized.
673 *
674 * @return array|string
675 */
676 protected function sanitize_item( $item ) {
677
678 return esc_attr( $item );
679 }
680
681 /**
682 * Adds documentation to the top of the settings page.
683 */
684 public function network_settings_details() {
685 ?>
686 <p>
687 <em>
688 <?php
689 esc_html_e(
690 "The Multisite Configuration option is for the case where one Discourse forum is connected
691 to a network of WordPress sites. If, instead, you would like to connect many forums to
692 many subsites, don't enable the Multisite Configuration option or any settings on this page. For that case you can
693 configure the settings individually on each of your subsites' WP Discourse options pages.",
694 'wp-discourse'
695 );
696 ?>
697 </em>
698 </p>
699 <h2><?php esc_html_e( 'Connection', 'wp-discourse' ); ?></h2>
700 <p>
701 <em>
702 <?php
703 esc_html_e(
704 "If the Multisite Configuration option is enabled, all the subsites in your network will
705 be configured to use the API credentials entered on this page. Your forum's API credentials will not be displayed
706 on your subsites' settings pages.",
707 'wp-discourse'
708 );
709 ?>
710 </em>
711 </p>
712 <h2><?php esc_html_e( 'Webhooks', 'wp-discourse' ); ?></h2>
713 <p>
714 <em>
715 <?php
716 esc_html_e(
717 "Webhooks can be used to sync data between Discourse and WordPress. Their use is optional,
718 but they're easy to setup. In a multisite environment the Sync Comment Data webhook will improve the efficiency of syncing Discourse
719 topic data with WordPress. The Update User Data webhook is used to sync user data between WordPress and Discourse when
720 a Discourse user is created or updated. When Multisite Configuration is enabled, all webhook options for your network
721 are set on this page.",
722 'wp-discourse'
723 );
724 ?>
725 </em>
726 </p>
727 <h2><?php esc_html_e( 'DiscourseConnect', 'wp-discourse' ); ?></h2>
728 <p>
729 <em>
730 <?php
731 esc_html_e(
732 'When Multisite Configuration is enabled, DiscourseConnect functionality to either use WordPress as the
733 DiscourseConnect provider for Discourse, or WordPress as a DiscourseConnect client to Discourse is enabled on this page. The DiscourseConnect Secret
734 Key is also set here. In a multisite setup, the DiscourseConnect Client functionality is only available when Multisite Configuration
735 is enabled.',
736 'wp-discourse'
737 );
738 ?>
739 </em>
740 </p>
741 <div class="discourse-doc-section-end">
742 <hr class="discourse-options-section-hr">
743 <h2><?php esc_html_e( 'Multisite Settings', 'wp-discourse' ); ?></h2>
744 </div>
745 <?php
746 }
747
748 /**
749 * Validates the options and saves them as a site option with the key wpdc_site_options.
750 *
751 * @param array $site_options The array of options to be validated.
752 */
753 public function validate_site_options( $site_options ) {
754 $updated_options = array();
755 foreach ( $site_options as $key => $value ) {
756 $filter = 'wpdc_validate_site_' . str_replace( '-', '_', $key );
757 $value = apply_filters( $filter, $value );
758 $updated_options[ $key ] = $value;
759
760 if ( 'multisite-configuration-enabled' === $key ) {
761 update_site_option( 'wpdc_multisite_configuration', $value );
762 }
763 }
764
765 update_site_option( 'wpdc_site_options', $updated_options );
766 }
767
768 /**
769 * Sets success and error notices.
770 *
771 * This is an awkward way to do it, but I'm not finding a better option.
772 */
773 public function network_config_notices() {
774 $screen = get_current_screen();
775 $discourse_screen = ! empty( $screen->parent_base ) && 'discourse_network_options' === $screen->parent_base;
776 $multisite_configuration_enabled = $this->get_site_option( 'multisite-configuration-enabled' );
777 if ( $discourse_screen && $multisite_configuration_enabled ) {
778 $notices = '';
779 $url = $this->get_site_option( 'url' );
780 $api_key = $this->get_site_option( 'api-key' );
781 $publish_username = $this->get_site_option( 'publish-username' );
782 $use_discourse_webhook = $this->get_site_option( 'use-discourse-webhook' );
783 $use_discourse_user_webhook = $this->get_site_option( 'use-discourse-user-webhook' );
784 $webhook_secret = $this->get_site_option( 'webhook-secret' );
785 $sso_secret = $this->get_site_option( 'sso-secret' );
786 $enable_sso = $this->get_site_option( 'enable-sso' );
787 $sso_client_enabled = $this->get_site_option( 'sso-client-enabled' );
788
789 if ( ! ( $url && $api_key && $publish_username ) ) {
790 $notices .= '<div class="notice notice-warning is-dismissible"><p>' .
791 __( 'To connect with Discourse, you need to supply the Discourse URL, API Key, and Publishing Username.', 'wp-discourse' ) .
792 '</p></div>';
793 } elseif ( empty( $this->check_connection_status() ) ) {
794 $notices .= '<div class="notice notice-error is-dismissible"><p>' .
795 __( 'You are not connected to Discourse. Check that your connection settings are correct. If the issue persists, enable connection logs and check Logs.', 'wp-discourse' ) .
796 '</p></div>';
797 } else {
798 $notices .= '<div class="notice notice-success is-dismissible"><p>' .
799 __( 'You are connected to Discourse!', 'wp-discourse' ) .
800 '</p></div>';
801 }
802
803 if ( ( ! empty( $use_discourse_webhook ) && empty( $webhook_secret ) ) ||
804 ( ! empty( $use_discourse_user_webhook ) && empty( $webhook_secret ) )
805 ) {
806 $notices .= '<div class="notice notice-error is-dismissible"><p>' .
807 __( 'To use Discourse webhooks, you need to supply a webhook secret key.', 'wp-discourse' ) .
808 '</p></div>';
809 }
810
811 if ( ! empty( $webhook_secret ) && strlen( $webhook_secret ) < 12 ) {
812 $notices .= '<div class="notice notice-error is-dismissible"><p>' .
813 __( 'The Webhook Secret Key must be at least 12 characters long.', 'wp-discourse' ) .
814 '</p></div>';
815 }
816
817 if ( ! empty( $enable_sso ) && empty( $sso_secret )
818 ) {
819 $notices .= '<div class="notice notice-error is-dismissible"><p>' .
820 __( 'To use WordPress as the DiscourseConnect Provider, you need to supply a DiscourseConnect Secret Key.', 'wp-discourse' ) .
821 '</p></div>';
822 }
823
824 if ( ! empty( $sso_client_enabled ) && empty( $sso_secret )
825 ) {
826 $notices .= '<div class="notice notice-error is-dismissible"><p>' .
827 __( 'To use WordPress as the DiscourseConnect Client, you need to supply a DiscourseConnect Secret Key.', 'wp-discourse' ) .
828 '</p></div>';
829 }
830
831 if ( ! empty( $enable_sso ) && ! empty( $sso_client_enabled ) ) {
832 $notices .= '<div class="notice notice-error is-dismissible"><p>' .
833 __( "You can't enable both the DiscourseConnect Client and DiscourseConnect Provider functionality.", 'wp-discourse' ) .
834 '</p></div>';
835 }
836
837 if ( ! empty( $sso_secret ) && strlen( $sso_secret ) < 10 ) {
838 $notices .= '<div class="notice notice-error is-dismissible"><p>' .
839 __( 'The DiscourseConnect Secret Key must be at least 10 characters long.', 'wp-discourse' ) .
840 '</p></div>';
841 }
842 }// End if().
843
844 if ( ! empty( $notices ) ) {
845 echo wp_kses_post( $notices );
846 }
847 }
848
849 /**
850 * Returns a single option from the wpdc_site_options array.
851 *
852 * @param string $key The option to find.
853 *
854 * @return bool|mixed
855 */
856 protected function get_site_option( $key ) {
857 static $site_options = array();
858
859 if ( empty( $site_options ) ) {
860 $site_options = get_site_option( 'wpdc_site_options' );
861 }
862
863 $option = ! empty( $site_options[ $key ] ) ? $site_options[ $key ] : false;
864
865 return $option;
866 }
867
868 /**
869 * Outputs the markup for an input box, defaults to outputting a text input, but
870 * can be used for other types.
871 *
872 * @param string $option The name of the option.
873 * @param string $description The description of the settings field.
874 * @param null|string $type The type of input ('number', 'url', etc).
875 * @param null|int $min The min value (applied to number inputs).
876 * @param null|int $max The max value (applies to number inputs).
877 * @param null|int|string $default An optional default value.
878 */
879 protected function input( $option, $description, $type = null, $min = null, $max = null, $default = null ) {
880 $value = $this->get_site_option( $option );
881 $value = empty( $value ) && $default ? $default : $value;
882 $allowed = array(
883 'a' => array(
884 'href' => array(),
885 'target' => array(),
886 ),
887 );
888
889 ?>
890 <input id='discourse-<?php echo esc_attr( $option ); ?>'
891 name='<?php echo 'wpdc_site_options[' . esc_attr( $option ) . ']'; ?>'
892 type="<?php echo isset( $type ) ? esc_attr( $type ) : 'text'; ?>"
893 <?php
894 if ( isset( $min ) ) {
895 echo 'min="' . esc_attr( $min ) . '"';
896 }
897 ?>
898 <?php
899 if ( isset( $max ) ) {
900 echo 'max="' . esc_attr( $max ) . '"';
901 }
902 ?>
903 value='<?php echo esc_attr( $value ); ?>' class="regular-text ltr"/>
904 <p class="description"><?php echo wp_kses( $description, $allowed ); ?></p>
905 <?php
906 }
907
908 /**
909 * Outputs the markup for a checkbox input.
910 *
911 * @param string $option The option name.
912 * @param string $label The text for the label.
913 * @param string $description The description of the settings field.
914 */
915 protected function checkbox_input( $option, $label = '', $description = '' ) {
916 $value = $this->get_site_option( $option );
917 $allowed = array(
918 'a' => array(
919 'href' => array(),
920 'target' => array(),
921 ),
922 'strong' => array(),
923 'code' => array(),
924 );
925
926 $checked = ! empty( $value ) ? 'checked="checked"' : '';
927
928 ?>
929 <label>
930 <input name='<?php echo 'wpdc_site_options[' . esc_attr( $option ) . ']'; ?>'
931 type='hidden'
932 value='0'/>
933 <input id='discourse-<?php echo esc_attr( $option ); ?>'
934 name='<?php echo 'wpdc_site_options[' . esc_attr( $option ) . ']'; ?>'
935 type='checkbox'
936 value='1' <?php echo esc_attr( $checked ); ?> />
937 <?php echo wp_kses( $label, $allowed ); ?>
938 </label>
939 <p class="description"><?php echo wp_kses( $description, $allowed ); ?></p>
940 <?php
941 }
942
943 /**
944 * A workaround for creating subsections when option fields are displayed using settings_fields function.
945 *
946 * @param null|string $title The title of the next setting.
947 */
948 protected function next_setting_heading( $title = null ) {
949 ?>
950 <div class="discourse-options-section-end">
951 <hr class="discourse-options-section-hr">
952 <?php if ( $title ) : ?>
953 <h2><?php echo esc_attr( $title ); ?></h2>
954 <?php endif; ?>
955 </div>
956 <?php
957 }
958 }
959