<?php
/**
 * @package PublishPress
 * @author  PublishPress
 *
 * Copyright (c) 2018 PublishPress
 *
 * ------------------------------------------------------------------------------
 * Based on Edit Flow
 * Author: Daniel Bachhuber, Scott Bressler, Mohammad Jangda, Automattic, and
 * others
 * Copyright (c) 2009-2016 Mohammad Jangda, Daniel Bachhuber, et al.
 * ------------------------------------------------------------------------------
 *
 * This file is part of PublishPress
 *
 * PublishPress is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PublishPress is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PublishPress.  If not, see <http://www.gnu.org/licenses/>.
 */

use MultipleAuthors\Capability;
use MultipleAuthors\Classes\Legacy\Module;
use MultipleAuthors\Classes\Legacy\Util;
use MultipleAuthors\Classes\Utils;
use MultipleAuthors\Factory;

if (!class_exists('MA_Settings')) {
    class MA_Settings extends Module
    {
        const SETTINGS_SLUG = 'ppma-settings';

        /**
         * @var string
         */
        const MENU_SLUG = 'ppma-modules-settings';

        public $module;
        public $module_url;
        public $viewsPath;
        public $view;

        /**
         * Register the module with PublishPress but don't do anything else
         */
        public function __construct()
        {
            $this->viewsPath = __DIR__ . '/views';

            parent::__construct();

            // Register the module with PublishPress
            $this->module_url = $this->get_module_url(__FILE__);
            $args             = [
                'title'                => __('PublishPress Authors', 'publishpress-authors'),
                'extended_description' => false,
                'module_url'           => $this->module_url,
                'icon_class'           => 'dashicons dashicons-admin-settings',
                'slug'                 => 'settings',
                'settings_slug'        => self::SETTINGS_SLUG,
                'default_options'      => [
                    'enabled' => 'on',
                ],
                'configure_page_cb'    => 'print_default_settings',
                'autoload'             => true,
                'add_menu'             => true,
            ];

            $legacyPlugin = Factory::getLegacyPlugin();

            $this->module = $legacyPlugin->register_module('settings', $args);
        }

        /**
         * Initialize the rest of the stuff in the class if the module is active
         */
        public function init()
        {
            add_action('admin_init', [$this, 'helper_settings_validate_and_save'], 100);

            add_action('multiple_authors_admin_submenu', [$this, 'action_admin_submenu'], 990);

            add_action('admin_print_styles', [$this, 'action_admin_print_styles']);
            add_action('admin_print_scripts', [$this, 'action_admin_print_scripts']);
        }

        /**
         * Add necessary things to the admin menu
         */
        public function action_admin_submenu()
        {
            // Main Menu
            add_submenu_page(
                MA_Multiple_Authors::MENU_SLUG,
                esc_html__('PublishPress Authors Settings', 'publishpress-authors'),
                esc_html__('Settings', 'publishpress-authors'),
                Capability::getManageOptionsCapability(),
                self::MENU_SLUG,
                [$this, 'options_page_controller'],
                20
            );
        }

        /**
         * Add settings styles to the settings page
         */
        public function action_admin_print_styles()
        {
            if ($this->is_whitelisted_settings_view()) {
                wp_enqueue_style('publishpress-settings-css', $this->module_url . 'lib/settings.css', false, PP_AUTHORS_VERSION);
            }
        }

        /**
         * Extra data we need on the page for transitions, etc.
         *
         * @since 0.7
         */
        public function action_admin_print_scripts()
        {
            ?>
			<script type="text/javascript">
				var ma_admin_url = '<?php echo esc_url(get_admin_url()); ?>';
			</script>
			<?php
        }

        /**
         *
         */
        public function print_default_header($current_module, $custom_text = null)
        {
            $display_text = '';

            // If there's been a message, let's display it
            $message = false;

            if (isset($_REQUEST['message'])) {
                $message = sanitize_text_field($_REQUEST['message']);
            }

            if ($message && isset($current_module->messages[$message])) {
                $display_text .= '<div class="is-dismissible notice notice-info"><p>' . esc_html($current_module->messages[$message]) . '</p></div>';
            }

            // If there's been an error, let's display it
            $error = false;

            if (isset($_REQUEST['error'])) {
                $error = sanitize_text_field($_REQUEST['error']);
            }

            if ($error && isset($current_module->messages[$error])) {
                $display_text .= '<div class="is-dismissible notice notice-error"><p>' . esc_html($current_module->messages[$error]) . '</p></div>';
            }
            ?>

			<div class="publishpress-admin pressshack-admin-wrapper wrap">
				<header>
                    <h1 class="wp-heading-inline"><?php echo esc_html($current_module->title); ?></h1>

					<?php echo !empty($display_text) ? $display_text : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
					<?php // We keep the H2 tag to keep notices tied to the header?>
					<h2>
						<?php if ($current_module->short_description && empty($custom_text)): ?>
							<?php echo esc_html($current_module->short_description); ?>
						<?php endif; ?>

						<?php if (!empty($custom_text)) : ?>
							<?php echo esc_html($custom_text); ?>
						<?php endif; ?>
					</h2>

				</header>
			<?php
        }

        /**
         * Adds Settings page for PublishPress.
         */
        public function print_default_settings()
        {
            ?>
			<div class="publishpress-modules">
				<?php $this->print_modules(); ?>
			</div>
			<?php
        }

        public function print_modules()
        {
            $legacyPlugin = Factory::getLegacyPlugin();

            if (!count($legacyPlugin->modules)) {
                echo '<div class="message error">' . esc_html__('There are no PublishPress modules registered', 'publishpress-authors') . '</div>';
            } else {
                foreach ($legacyPlugin->modules as $mod_name => $mod_data) {
                    $add_menu = isset($mod_data->add_menu) && $mod_data->add_menu === true;

                    if ($mod_data->autoload || !$add_menu) {
                        continue;
                    }

                    if ($mod_data->options->enabled !== 'off') {
                        $url = '';

                        if ($mod_data->configure_page_cb && (!isset($mod_data->show_configure_btn) || $mod_data->show_configure_btn === true)) {
                            $url = add_query_arg('page', $mod_data->settings_slug, get_admin_url(null, 'admin.php'));
                        } elseif ($mod_data->page_link) {
                            $url = $mod_data->page_link;
                        }

                        echo $this->view->render( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                            'module',
                            [
                                'has_config_link' => isset($mod_data->configure_page_cb) && !empty($mod_data->configure_page_cb),
                                'slug'            => esc_html($mod_data->slug),
                                'icon_class'      => isset($mod_data->icon_class) ? $mod_data->icon_class : false,
                                'form_action'     => esc_url(get_admin_url(null, 'options.php')),
                                'title'           => esc_html($mod_data->title),
                                'description'     => wp_kses($mod_data->short_description, 'a'),
                                'url'             => esc_url($url),
                            ],
                            $this->viewsPath
                        );
                    }
                }
            }
        }

        /**
         * Generate an option field to turn post type support on/off for a given module
         *
         * @param object $module      PublishPress module we're generating the option field for
         * @param array  $post_types  If empty, we consider all post types
         *
         * @since 0.7
         */
        public function helper_option_custom_post_type($module, $post_types = [])
        {
            if (empty($post_types)) {
                $post_types = [
                    'post' => esc_html__('Posts'),
                    'page' => esc_html__('Pages'),
                ];
                $custom_post_types = $this->get_supported_post_types_for_module();
                if (count($custom_post_types)) {
                    foreach ($custom_post_types as $custom_post_type => $args) {
                        $post_types[$custom_post_type] = $args->label;
                    }
                }
            }

            foreach ($post_types as $post_type => $title) {
                echo '<label for="' . esc_attr($post_type) . '-' . esc_attr($module->slug) . '">';
                echo '<input id="' . esc_attr($post_type) . '-' . esc_attr($module->slug) . '" name="'
                    . esc_attr($module->options_group_name) . '[post_types][' . esc_attr($post_type) . ']"';
                if (isset($module->options->post_types[$post_type])) {
                    checked($module->options->post_types[$post_type], 'on');
                }
                // Defining post_type_supports in the functions.php file or similar should disable the checkbox
                disabled(post_type_supports($post_type, $module->post_type_support), true);
                echo ' type="checkbox" value="on" />&nbsp;&nbsp;&nbsp;' . esc_html($title) . '</label>';
                // Leave a note to the admin as a reminder that add_post_type_support has been used somewhere in their code
                if (post_type_supports($post_type, $module->post_type_support)) {
                    echo '&nbsp&nbsp;&nbsp;<span class="description">' . sprintf(esc_html__('Disabled because add_post_type_support(\'%1$s\', \'%2$s\') is included in a loaded file.', 'publishpress-authors'), esc_html($post_type), esc_html($module->post_type_support)) . '</span>';
                }
                echo '<br />';
            }
        }

        /**
         * Validation and sanitization on the settings field
         * This method is called automatically/ doesn't need to be registered anywhere
         *
         * @since 0.7
         */
        public function helper_settings_validate_and_save()
        {
            if (!isset($_POST['action'], $_POST['_wpnonce'], $_POST['option_page'], $_POST['_wp_http_referer'], $_POST['multiple_authors_module_name'], $_POST['submit']) || !is_admin()) {
                return false;
            }

            if ($_POST['action'] != 'update'
                || (!isset($_GET['page']) || !in_array($_GET['page'], ['ppma-modules-settings', 'ppma-author-pages']))
            ) {
                return false;
            }

            if (!Capability::currentUserCanManageSettings() || !wp_verify_nonce(sanitize_key($_POST['_wpnonce']), 'edit-publishpress-settings')) {
                wp_die(esc_html__('Cheatin&#8217; uh?'));
            }

            $author_pages_settings = in_array($_GET['page'], ['ppma-author-pages']);

            $legacyPlugin = Factory::getLegacyPlugin();

            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
            foreach ($_POST['multiple_authors_module_name'] as $moduleSlug) {
                $module_name = sanitize_key(Util::sanitize_module_name($moduleSlug));

                // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
                $new_options = (isset($_POST[$legacyPlugin->$module_name->module->options_group_name])) ? Utils::sanitizeArray($_POST[$legacyPlugin->$module_name->module->options_group_name]) : [];

                /**
                 * Legacy way to validate the settings. Hook to the filter
                 * multiple_authors_validate_module_settings instead.
                 *
                 * @deprecated
                 */
                if (method_exists($legacyPlugin->$module_name, 'settings_validate')) {
                    $new_options = $legacyPlugin->$module_name->settings_validate($new_options);
                }

                // New way to validate settings
                $new_options = apply_filters('multiple_authors_validate_module_settings', $new_options, $module_name);

                // Cast our object and save the data.
                $new_options = (object)array_merge((array)$legacyPlugin->$module_name->module->options, $new_options);
                $legacyPlugin->update_all_module_options($legacyPlugin->$module_name->module->name, $new_options);

                // Check if the module has a custom save method
                if (method_exists($legacyPlugin->$module_name, 'settings_save')) {
                    $legacyPlugin->$module_name->settings_save($new_options);
                }
            }

            if ($author_pages_settings) {
                // Flush rewrite rules due to authors page slug
                set_transient('ppma_flush_rewrite_rules', true);
            }

            // Redirect back to the settings page that was submitted without any previous messages
            $goback = add_query_arg('message', 'settings-updated', remove_query_arg(['message'], wp_get_referer()));
            wp_safe_redirect($goback);

            exit;
        }

        public function options_page_controller()
        {
            $legacyPlugin = Factory::getLegacyPlugin();

            $module_settings_slug = isset($_GET['module']) && !empty($_GET['module']) ? sanitize_key($_GET['module']) : MA_Modules_Settings::SETTINGS_SLUG . '-settings';
            $requested_module     = $legacyPlugin->get_module_by('settings_slug', $module_settings_slug);
            $display_text         = '';

            // If there's been a message, let's display it
            $message = false;

            if (isset($_REQUEST['message'])) {
                $message = sanitize_text_field($_REQUEST['message']);
            }

            if ($message && isset($requested_module->messages[$message])) {
                $display_text .= '<div class="is-dismissible notice notice-info"><p>' . esc_html($requested_module->messages[$message]) . '</p></div>';
            }

            // If there's been an error, let's display it
            $error = false;

            if (isset($_REQUEST['error'])) {
                $error = sanitize_text_field($_REQUEST['error']);
            }

            if ($error && isset($requested_module->messages[$error])) {
                $display_text .= '<div class="is-dismissible notice notice-error"><p>' . esc_html($requested_module->messages[$error]) . '</p></div>';
            }

            $this->print_default_header($requested_module);

            // Get module output
            ob_start();
            $configure_callback    = $requested_module->configure_page_cb;

            if ( ! empty($configure_callback)) {
                $requested_module_name = $requested_module->name;

                $legacyPlugin->$requested_module_name->$configure_callback();
                $module_output = ob_get_clean();
            }

            /*
             * Check if we have more than one tab to display.
             */
            $show_tabs = false;
            foreach ($legacyPlugin->modules as $module) {
                if ( ! empty($module->options_page) && $module->options->enabled == 'on') {
                    $show_tabs = true;
                }
            }

            echo $this->view->render( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                'settings',
                [
                    'modules'        => (array)$legacyPlugin->modules, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                    'settings_slug'  => esc_html($module_settings_slug),
                    'slug'           => esc_html(MA_Modules_Settings::SETTINGS_SLUG),
                    'module_output'  => $module_output, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                    'sidebar_output' => '',
                    'text'           => esc_html($display_text),
                    'show_sidebar'   => false,
                    'show_tabs'      => $show_tabs, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                ],
                $this->viewsPath
            );
        }
    }
}