mirror of
https://gh.wpcy.net/https://github.com/discourse/wp-discourse.git
synced 2026-05-20 23:19:45 +08:00
* Don't try to add url to <head> if it's not present * Update js config and formatting for comment block and sidebar * PHP Linting * FIX: Don't auto-publish updates to existing posts. See: https://meta.discourse.org/t/disable-posting-wordpress-articles-to-discourse-when-theyre-updated/204488 * Bump version and release notes. * Fix remote-post.php linting * Update tests.yml to install svn * Re-generate comments js build
456 lines
14 KiB
PHP
Vendored
456 lines
14 KiB
PHP
Vendored
<?php
|
|
/**
|
|
* Used for creating form elements.
|
|
*
|
|
* @package WPDiscourse
|
|
*/
|
|
|
|
namespace WPDiscourse\Admin;
|
|
|
|
use WPDiscourse\Shared\PluginUtilities;
|
|
|
|
/**
|
|
* Class FormHelper
|
|
*/
|
|
class FormHelper {
|
|
use PluginUtilities;
|
|
|
|
/**
|
|
* Used for containing a single instance of the FormHelper class throughout a request.
|
|
*
|
|
* @access protected
|
|
* @var FormHelper
|
|
*/
|
|
protected static $instance;
|
|
|
|
/**
|
|
* Gives access to the plugin options.
|
|
*
|
|
* @access protected
|
|
* @var mixed|void
|
|
*/
|
|
protected $options;
|
|
|
|
/**
|
|
* Gets an instance of the FormHelper class.
|
|
*
|
|
* @return FormHelper
|
|
*/
|
|
public static function get_instance() {
|
|
if ( null === self::$instance ) {
|
|
self::$instance = new self();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* FormHelper constructor.
|
|
*/
|
|
protected function __construct() {
|
|
add_action( 'admin_init', array( $this, 'setup_options' ) );
|
|
}
|
|
|
|
/**
|
|
* Sets the plugin options.
|
|
*
|
|
* @param object $extra_options Extra options used for testing.
|
|
*/
|
|
public function setup_options( $extra_options = null ) {
|
|
$this->options = $this->get_options();
|
|
|
|
if ( ! empty( $extra_options ) ) {
|
|
foreach ( $extra_options as $key => $value ) {
|
|
$this->options[ $key ] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Outputs the markup for an input box, defaults to outputting a text input, but
|
|
* can be used for other types.
|
|
*
|
|
* @param string $option The name of the option.
|
|
* @param string $option_group The option group for the field to be saved to.
|
|
* @param string $description The description of the settings field.
|
|
* @param null|string $type The type of input ('number', 'url', etc).
|
|
* @param null|int $min The min value (applied to number inputs).
|
|
* @param null|int $max The max value (applies to number inputs).
|
|
* @param null|string $default The default value of the input.
|
|
*/
|
|
public function input( $option, $option_group, $description, $type = null, $min = null, $max = null, $default = null ) {
|
|
$options = $this->options;
|
|
$allowed = array(
|
|
'a' => array(
|
|
'href' => array(),
|
|
'target' => array(),
|
|
),
|
|
);
|
|
|
|
if ( ! empty( $options[ $option ] ) || ( isset( $options[ $option ] ) && 0 === $options[ $option ] ) ) {
|
|
$value = $options[ $option ];
|
|
} elseif ( ! empty( $default ) ) {
|
|
$value = $default;
|
|
} else {
|
|
$value = '';
|
|
}
|
|
|
|
?>
|
|
<input id='discourse-<?php echo esc_attr( $option ); ?>'
|
|
name='<?php echo esc_attr( $this->option_name( $option, $option_group ) ); ?>'
|
|
type="<?php echo isset( $type ) ? esc_attr( $type ) : 'text'; ?>"
|
|
<?php
|
|
if ( isset( $min ) ) {
|
|
echo 'min="' . esc_attr( $min ) . '"';
|
|
}
|
|
?>
|
|
<?php
|
|
if ( isset( $max ) ) {
|
|
echo 'max="' . esc_attr( $max ) . '"';
|
|
}
|
|
?>
|
|
value='<?php echo esc_attr( $value ); ?>' class="regular-text ltr"/>
|
|
<p class="description"><?php echo wp_kses( $description, $allowed ); ?></p>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Outputs the markup for a checkbox input.
|
|
*
|
|
* @param string $option The option name.
|
|
* @param string $option_group The option group for the field to be saved to.
|
|
* @param string $label The text for the label.
|
|
* @param string $description The description of the settings field.
|
|
*/
|
|
public function checkbox_input( $option, $option_group, $label = '', $description = '' ) {
|
|
$options = $this->options;
|
|
$allowed = array(
|
|
'a' => array(
|
|
'href' => array(),
|
|
'target' => array(),
|
|
),
|
|
'strong' => array(),
|
|
'code' => array(
|
|
'class' => array(),
|
|
),
|
|
);
|
|
if ( ! empty( $options[ $option ] ) && 1 === intval( $options[ $option ] ) ) {
|
|
$checked = 'checked="checked"';
|
|
} else {
|
|
$checked = '';
|
|
}
|
|
|
|
?>
|
|
<label>
|
|
<input name='<?php echo esc_attr( $this->option_name( $option, $option_group ) ); ?>'
|
|
type='hidden'
|
|
value='0'/>
|
|
<input id='discourse-<?php echo esc_attr( $option ); ?>'
|
|
name='<?php echo esc_attr( $this->option_name( $option, $option_group ) ); ?>'
|
|
type='checkbox'
|
|
value='1' <?php echo esc_attr( $checked ); ?> />
|
|
<?php echo wp_kses( $label, $allowed ); ?>
|
|
</label>
|
|
<p class="description"><?php echo wp_kses( $description, $allowed ); ?></p>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Outputs the post-type select input.
|
|
*
|
|
* @param string $option Used to set the selected option.
|
|
* @param array $post_types An array of available post types.
|
|
* @param string $description The description of the settings field.
|
|
*/
|
|
public function post_type_select_input( $option, $post_types, $description = '' ) {
|
|
$options = $this->options;
|
|
$allowed = array(
|
|
'strong' => array(),
|
|
);
|
|
|
|
echo "<select multiple id='discourse-allowed-post-types' class='discourse-select-input' name='discourse_publish[allowed_post_types][]'>";
|
|
$this->select_options( $option, $post_types );
|
|
echo '</select>';
|
|
echo '<p class="description">' . wp_kses( $description, $allowed ) . '</p>';
|
|
}
|
|
|
|
/**
|
|
* Outputs the tag select input.
|
|
*
|
|
* @param string $option Used to set the selected option.
|
|
* @param string $option_group The option group of the settings field.
|
|
* @param string $description The description of the settings field.
|
|
*/
|
|
public function tags_select_input( $option, $option_group, $description = '' ) {
|
|
$options = $this->options;
|
|
$tax_name = 'post_tag';
|
|
$comma = _x( ',', 'tag delimiter' );
|
|
$selected = isset( $options[ $option ] ) ? $options[ $option ] : array();
|
|
$value = join( "$comma ", $selected );
|
|
$name = $this->option_name( $option, $option_group );
|
|
|
|
?>
|
|
<div class="tagsdiv" id="wpdc-tags-select">
|
|
<div class="ajaxtag">
|
|
<input data-wp-taxonomy="<?php echo esc_attr( $tax_name ); ?>" type="text" id="discourse-<?php echo esc_attr( $option ); ?>" name="<?php echo esc_attr( $name ); ?>" class="newtag form-input-tip" size="16" autocomplete="off" value="<?php echo esc_attr( $value ); ?>" />
|
|
</div>
|
|
</div>
|
|
<p class="description"><?php echo esc_attr( $description ); ?></p>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Outputs the markup for the categories select input.
|
|
*
|
|
* @param string $option The name of the option.
|
|
* @param string $option_group The option group for the field to be saved to.
|
|
* @param string $description The description of the settings field.
|
|
*/
|
|
public function category_select( $option, $option_group, $description ) {
|
|
$options = $this->options;
|
|
|
|
$categories = $this->get_discourse_categories();
|
|
|
|
if ( is_wp_error( $categories ) ) {
|
|
esc_html_e( 'The Discourse category list will be available when you establish a connection with Discourse.', 'wp-discourse' );
|
|
|
|
return;
|
|
}
|
|
|
|
$selected = isset( $options['publish-category'] ) ? $options['publish-category'] : '';
|
|
$option_name = $this->option_name( $option, $option_group );
|
|
$this->option_input( $option, $option_name, $categories, $selected, $description );
|
|
}
|
|
|
|
/**
|
|
* Outputs the markup for an option input.
|
|
*
|
|
* @param string $option The name of the option to be saved.
|
|
* @param string $option_name Supplies the 'name' value for the select input.
|
|
* @param array $group The array of items to be selected.
|
|
* @param int $selected The value of the selected option.
|
|
* @param string $description The description of the option.
|
|
*/
|
|
public function option_input( $option, $option_name, $group, $selected, $description ) {
|
|
echo '<select id="discourse-' . esc_attr( $option ) . '" name="' . esc_attr( $option_name ) . '">';
|
|
|
|
foreach ( $group as $item ) {
|
|
printf(
|
|
'<option value="%s"%s>%s</option>',
|
|
esc_attr( $item['id'] ),
|
|
selected( $selected, $item['id'], false ),
|
|
esc_html( $item['name'] )
|
|
);
|
|
}
|
|
|
|
echo '</select>';
|
|
echo '<p class="description">' . esc_html( $description ) . '</p>';
|
|
}
|
|
|
|
|
|
/**
|
|
* Outputs the markup for a text area.
|
|
*
|
|
* @param string $option The name of the option.
|
|
* @param string $description The description of the settings field.
|
|
*/
|
|
public function text_area( $option, $description ) {
|
|
$options = $this->options;
|
|
|
|
if ( array_key_exists( $option, $options ) ) {
|
|
$value = $options[ $option ];
|
|
} else {
|
|
$value = '';
|
|
}
|
|
|
|
?>
|
|
<textarea cols=100 rows=6 id='discourse_<?php echo esc_attr( $option ); ?>'
|
|
name='<?php echo esc_attr( $option ); ?>'><?php echo esc_textarea( $value ); ?></textarea>
|
|
<p class="description"><?php echo esc_html( $description ); ?></p>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Returns the 'public' post-types minus the post-types in the 'excluded' array.
|
|
*
|
|
* @param array $excluded_types An array of post-types to exclude from publishing to Discourse.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function post_types_to_publish( $excluded_types = array() ) {
|
|
$post_types = get_post_types(
|
|
array(
|
|
'public' => true,
|
|
)
|
|
);
|
|
foreach ( $excluded_types as $excluded ) {
|
|
unset( $post_types[ $excluded ] );
|
|
}
|
|
|
|
return apply_filters( 'discourse_post_types_to_publish', $post_types );
|
|
}
|
|
|
|
/**
|
|
* The callback for validating the 'discourse' options.
|
|
*
|
|
* @param array $inputs The inputs to be validated.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function validate_options( $inputs ) {
|
|
$output = array();
|
|
|
|
if ( ! empty( $inputs ) ) {
|
|
foreach ( $inputs as $key => $input ) {
|
|
$filter = 'wpdc_validate_' . str_replace( '-', '_', $key );
|
|
$output[ $key ] = apply_filters( $filter, $input );
|
|
}
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
|
|
/**
|
|
* Adds notices to indicate the connection status with Discourse.
|
|
*
|
|
* This method is called by the `load-{settings_page_hook}` action - see https://codex.wordpress.org/Plugin_API/Action_Reference/load-(page).
|
|
*/
|
|
public function connection_status_notice() {
|
|
if ( ! empty( $_GET['tab'] ) ) { // Input var okay.
|
|
$current_page = sanitize_key( wp_unslash( $_GET['tab'] ) ); // Input var okay.
|
|
} elseif ( ! empty( $_GET['page'] ) ) { // Input var okay.
|
|
$current_page = sanitize_key( wp_unslash( $_GET['page'] ) ); // Input var okay.
|
|
} else {
|
|
$current_page = null;
|
|
}
|
|
|
|
$check_connection_on = array(
|
|
'wp_discourse_options',
|
|
'connection_options',
|
|
'sso_provider',
|
|
);
|
|
|
|
if ( $current_page && in_array( $current_page, $check_connection_on ) ) {
|
|
$connection_status = $this->check_connection_status();
|
|
|
|
if ( is_wp_error( $connection_status ) || empty( $connection_status ) || 0 === $connection_status ) {
|
|
add_action( 'admin_notices', array( $this, 'disconnected' ) );
|
|
} else {
|
|
add_action( 'admin_notices', array( $this, 'connected' ) );
|
|
}
|
|
}
|
|
|
|
if ( $current_page && 'sso_provider' === $current_page && ! empty( $this->options['enable-sso'] ) ) {
|
|
// Check if the user saving the options has an email address on Discourse.
|
|
$current_user_email = wp_get_current_user()->user_email;
|
|
$discourse_user = $this->get_discourse_user_by_email( $current_user_email );
|
|
if ( is_wp_error( $discourse_user ) || empty( $discourse_user->admin ) ) {
|
|
add_action( 'admin_notices', array( $this, 'no_matching_discourse_user' ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Outputs the markup for the no_matching_discourse_user notice.
|
|
*/
|
|
public function no_matching_discourse_user() {
|
|
?>
|
|
<div class="notice notice-error is-dismissible">
|
|
<p>
|
|
<?php
|
|
$current_user_email = wp_get_current_user()->user_email;
|
|
$message = sprintf(
|
|
// translators: Discourse admin-email-mismatch message. Placeholder: The current user's email address.
|
|
__(
|
|
'There is no admin user on Discourse with the email address <strong>%s</strong>. If you have
|
|
an existing Discourse admin account, before enabling DiscourseConnect please ensure that your email
|
|
addresses on Discourse and WordPress match. This is required for DiscourseConnect login to an
|
|
existing Discourse account.',
|
|
'wp-discourse'
|
|
),
|
|
esc_attr( $current_user_email )
|
|
);
|
|
|
|
$allowed = array(
|
|
'strong' => array(),
|
|
);
|
|
|
|
echo wp_kses( $message, $allowed );
|
|
?>
|
|
</p>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Outputs the markup for the 'disconnected' notice that is displayed on the 'connection_options' tab.
|
|
*/
|
|
public function disconnected() {
|
|
?>
|
|
<div class="notice notice-warning is-dismissible">
|
|
<p>
|
|
<strong>
|
|
<?php
|
|
esc_html_e( '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' );
|
|
?>
|
|
</strong>
|
|
</p>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Outputs the markup for the 'connected' notice that is displayed on the 'connection_options' tab.
|
|
*/
|
|
public function connected() {
|
|
?>
|
|
<div class="notice notice-success is-dismissible">
|
|
<p>
|
|
<strong><?php esc_html_e( 'You are connected to Discourse!', 'wp-discourse' ); ?></strong>
|
|
</p>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Creates the full option name for the form `name` fields.
|
|
*
|
|
* @param string $option The name of the option.
|
|
* @param string $option_group The group to save the option to, each option group is saved as an array in the `wp_options` table.
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function option_name( $option, $option_group ) {
|
|
return $option_group . '[' . esc_attr( $option ) . ']';
|
|
}
|
|
|
|
/**
|
|
* Outputs markup for select options
|
|
*
|
|
* @param string $option The name of the option.
|
|
* @param array $items An array of items to display as options.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function select_options( $option, $items ) {
|
|
$options = $this->options;
|
|
|
|
foreach ( $items as $item ) {
|
|
if ( is_a( $item, 'WP_Term' ) ) {
|
|
$item_id = strval( $item->term_id );
|
|
$item_name = $item->name;
|
|
} else {
|
|
$item_id = $item;
|
|
$item_name = $item;
|
|
}
|
|
|
|
if ( array_key_exists( $option, $options ) && in_array( $item_id, $options[ $option ], true ) ) {
|
|
$value = 'selected';
|
|
} else {
|
|
$value = '';
|
|
}
|
|
|
|
echo '<option ' . esc_attr( $value ) . ' value="' . esc_attr( $item_id ) . '">' . esc_html( $item_name ) . '</option>';
|
|
}
|
|
}
|
|
}
|