<?php
declare(strict_types=1);

namespace WP_AUX\Services;

/**
 * Security-related configurations and setups. It provides methods to augment general
 * and Wordpress-specific security by utilizing available hooks and filters.
 *
 * @since 1.0.1
 */
class SecurityService
{
  /**
   * Prevent the users sitemap provider from being registered.
   * WordPress filters can pass false from previous filters, so we accept
   * either false or a WP_Sitemaps_Provider instance.
   *
   * Tested with:
   * http://(testurl)/wp-sitemap.xml // verified the author sitemap is not present in the sitemap index
   * http://(testurl)/wp-sitemap-users-1.xml
   * http://(testurl)/?sitemap=users
   *
   * @param false|\WP_Sitemaps_Provider $provider The sitemap provider or false.
   * @param string                       $name     The provider name.
   * @return false|\WP_Sitemaps_Provider Returns false for 'users' provider, or passes through the provider.
   * @since 1.0.2
   */
  public static function disableUserSitemapProvider(
    false|\WP_Sitemaps_Provider $provider,
    string $name
  ): false|\WP_Sitemaps_Provider {
    if ( 'users' === $name ) {
      return false;
    }

    return $provider;
  }

  /**
   * Register security-related actions and filters
   * @since 1.0.1
   */
  public static function prepareHooks(): void
  {
    // Disable XMLRPC
    // Verified in Postman with several XMLRPC methods.
    add_filter( 'xmlrpc_enabled', '__return_false' );

    // Disable user sitemaps
    add_filter( 'wp_sitemaps_add_provider', [ self::class, 'disableUserSitemapProvider' ], 10, 2);

    /*
     * Prevent Access to Users in the REST API
     * Tested (using valid author IDs and slugs) with:
     * http://(testurl)/wp-json/wp/v2/users/
     * http://(testurl)/wp-json/wp/v2/users/1/
     * http://(testurl)/wp-json/wp/v2/users/test-user/
     * http://(testurl)/wp-json/wp/v2/users/ // the users endpoint
     */
    add_action( 'rest_authentication_errors', function( $access ) {
      if ( is_user_logged_in() ) {
        return $access;
      }

      if ( ( preg_match( '/users/i', $_SERVER['REQUEST_URI'] ) !== 0 )
        || ( isset( $_REQUEST['rest_route'] ) && ( preg_match( '/users/i', $_REQUEST['rest_route'] ) !== 0 ) )
      ) {
        return new \WP_Error(
          'rest_cannot_access',
          'Only authenticated users can access the User endpoint REST API.',
          [
            'status' => rest_authorization_required_code()
          ]
        );
      }

      return $access;
    });

    // Remove the Author URL and Name from oEmbed data in the html head
    add_filter( 'remove_author_from_oembed', function( $data ) {
      unset( $data['author_url'] );
      unset( $data['author_name'] );

      return $data;
    }, 10, 2 );

    /*
     * Disable Author Archives Completely
     * Tested (using valid author IDs and slugs) with:
     * http://(testurl)/author/
     * http://(testurl)/author/1/
     * http://(testurl)/author/test-author/
     * http://(testurl)/author/test-author&post_type=post
     * http://(testurl)?author=1
     * http://(testurl)?author=test-author
     * http://(testurl)?author=test-author&post_type=post
     */
    add_filter( 'template_redirect', function() {
      if ( is_author() || isset( $_GET['author'] ) ) {
        wp_safe_redirect( esc_url( home_url( '/' ) ), 301 );
      }
    });
  }
}
