Phase 5: Content and SEO - Yoast SEO, Schema.org markup, Open Graph, favicon support, XML sitemap
This commit is contained in:
Executable
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\AI_Consent\Application;
|
||||
|
||||
/**
|
||||
* Interface Consent_Handler_Interface
|
||||
*
|
||||
* This interface defines the methods for handling user consent.
|
||||
*/
|
||||
interface Consent_Handler_Interface {
|
||||
|
||||
/**
|
||||
* Handles consent revoked by deleting the consent user metadata from the database.
|
||||
*
|
||||
* @param int $user_id The user ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function revoke_consent( int $user_id );
|
||||
|
||||
/**
|
||||
* Handles consent granted by adding the consent user metadata to the database.
|
||||
*
|
||||
* @param int $user_id The user ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function grant_consent( int $user_id );
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\AI_Consent\Application;
|
||||
|
||||
use Yoast\WP\SEO\Helpers\User_Helper;
|
||||
|
||||
/**
|
||||
* Class Consent_Handler
|
||||
* Handles the consent given or revoked by the user.
|
||||
*
|
||||
* @makePublic
|
||||
*/
|
||||
class Consent_Handler implements Consent_Handler_Interface {
|
||||
|
||||
/**
|
||||
* Holds the user helper instance.
|
||||
*
|
||||
* @var User_Helper
|
||||
*/
|
||||
private $user_helper;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param User_Helper $user_helper The user helper.
|
||||
*/
|
||||
public function __construct( User_Helper $user_helper ) {
|
||||
$this->user_helper = $user_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles consent revoked by deleting the consent user metadata from the database.
|
||||
*
|
||||
* @param int $user_id The user ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function revoke_consent( int $user_id ) {
|
||||
$this->user_helper->delete_meta( $user_id, '_yoast_wpseo_ai_consent' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles consent granted by adding the consent user metadata to the database.
|
||||
*
|
||||
* @param int $user_id The user ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function grant_consent( int $user_id ) {
|
||||
$this->user_helper->update_meta( $user_id, '_yoast_wpseo_ai_consent', true );
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
|
||||
namespace Yoast\WP\SEO\AI_Consent\Domain\Endpoint;
|
||||
|
||||
interface Endpoint_Interface {
|
||||
|
||||
/**
|
||||
* Gets the name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name(): string;
|
||||
|
||||
/**
|
||||
* Gets the namespace.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_namespace(): string;
|
||||
|
||||
/**
|
||||
* Gets the route.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_route(): string;
|
||||
|
||||
/**
|
||||
* Gets the URL.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_url(): string;
|
||||
}
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
|
||||
namespace Yoast\WP\SEO\AI_Consent\Infrastructure\Endpoints;
|
||||
|
||||
use Exception;
|
||||
use Yoast\WP\SEO\AI_Consent\Domain\Endpoint\Endpoint_Interface;
|
||||
use Yoast\WP\SEO\AI_Consent\User_Interface\Consent_Route;
|
||||
|
||||
/**
|
||||
* Represents the setup steps tracking endpoint.
|
||||
*/
|
||||
class Consent_Endpoint implements Endpoint_Interface {
|
||||
|
||||
/**
|
||||
* Gets the name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name(): string {
|
||||
return 'consent';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the namespace.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_namespace(): string {
|
||||
return Consent_Route::ROUTE_NAMESPACE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the route.
|
||||
*
|
||||
* @throws Exception If the route prefix is not overwritten this throws.
|
||||
* @return string
|
||||
*/
|
||||
public function get_route(): string {
|
||||
return Consent_Route::ROUTE_PREFIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_url(): string {
|
||||
return \rest_url( $this->get_namespace() . $this->get_route() );
|
||||
}
|
||||
}
|
||||
Executable
+113
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\AI_Consent\User_Interface;
|
||||
|
||||
use WPSEO_Admin_Asset_Manager;
|
||||
use Yoast\WP\SEO\Conditionals\User_Profile_Conditional;
|
||||
use Yoast\WP\SEO\Helpers\Short_Link_Helper;
|
||||
use Yoast\WP\SEO\Helpers\User_Helper;
|
||||
use Yoast\WP\SEO\Integrations\Integration_Interface;
|
||||
|
||||
/**
|
||||
* Ai_Consent_Integration class.
|
||||
*/
|
||||
class Ai_Consent_Integration implements Integration_Interface {
|
||||
|
||||
/**
|
||||
* Represents the admin asset manager.
|
||||
*
|
||||
* @var WPSEO_Admin_Asset_Manager
|
||||
*/
|
||||
private $asset_manager;
|
||||
|
||||
/**
|
||||
* Represents the user helper.
|
||||
*
|
||||
* @var User_Helper
|
||||
*/
|
||||
private $user_helper;
|
||||
|
||||
/**
|
||||
* The short link helper.
|
||||
*
|
||||
* @var Short_Link_Helper
|
||||
*/
|
||||
protected $short_link_helper;
|
||||
|
||||
/**
|
||||
* Returns the conditionals based in which this loadable should be active.
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
public static function get_conditionals(): array {
|
||||
return [ User_Profile_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the class.
|
||||
*
|
||||
* @param WPSEO_Admin_Asset_Manager $asset_manager The admin asset manager.
|
||||
* @param User_Helper $user_helper The user helper.
|
||||
* @param Short_Link_Helper $short_link_helper The short link helper.
|
||||
*/
|
||||
public function __construct(
|
||||
WPSEO_Admin_Asset_Manager $asset_manager,
|
||||
User_Helper $user_helper,
|
||||
Short_Link_Helper $short_link_helper
|
||||
) {
|
||||
$this->asset_manager = $asset_manager;
|
||||
$this->user_helper = $user_helper;
|
||||
$this->short_link_helper = $short_link_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the integration.
|
||||
*
|
||||
* This is the place to register hooks and filters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
// Hide AI feature option in user profile if the user is not allowed to use it.
|
||||
if ( \current_user_can( 'edit_posts' ) ) {
|
||||
\add_action( 'wpseo_user_profile_additions', [ $this, 'render_user_profile' ], 12 );
|
||||
}
|
||||
\add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ], 11 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the script data for the AI consent button.
|
||||
*
|
||||
* @return array<string, string|bool>
|
||||
*/
|
||||
public function get_script_data(): array {
|
||||
return [
|
||||
'hasConsent' => $this->user_helper->get_meta( $this->user_helper->get_current_user_id(), '_yoast_wpseo_ai_consent', true ),
|
||||
'pluginUrl' => \plugins_url( '', \WPSEO_FILE ),
|
||||
'linkParams' => $this->short_link_helper->get_query_params(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues the required assets.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_assets() {
|
||||
$this->asset_manager->enqueue_style( 'ai-generator' );
|
||||
$this->asset_manager->localize_script( 'ai-consent', 'wpseoAiConsent', $this->get_script_data() );
|
||||
$this->asset_manager->enqueue_script( 'ai-consent' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the AI consent button for the user profile.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function render_user_profile() {
|
||||
echo '<label for="ai-generator-consent-button">',
|
||||
\esc_html__( 'AI features', 'wordpress-seo' ),
|
||||
'</label>',
|
||||
'<div id="ai-generator-consent" style="display:inline-block; margin-top: 28px; padding-left:5px;"></div>';
|
||||
}
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
|
||||
namespace Yoast\WP\SEO\AI_Consent\User_Interface;
|
||||
|
||||
use RuntimeException;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\AI_Authorization\Application\Token_Manager;
|
||||
use Yoast\WP\SEO\AI_Consent\Application\Consent_Handler;
|
||||
use Yoast\WP\SEO\AI_HTTP_Request\Domain\Exceptions\Bad_Request_Exception;
|
||||
use Yoast\WP\SEO\AI_HTTP_Request\Domain\Exceptions\Forbidden_Exception;
|
||||
use Yoast\WP\SEO\AI_HTTP_Request\Domain\Exceptions\Internal_Server_Error_Exception;
|
||||
use Yoast\WP\SEO\AI_HTTP_Request\Domain\Exceptions\Not_Found_Exception;
|
||||
use Yoast\WP\SEO\AI_HTTP_Request\Domain\Exceptions\Payment_Required_Exception;
|
||||
use Yoast\WP\SEO\AI_HTTP_Request\Domain\Exceptions\Request_Timeout_Exception;
|
||||
use Yoast\WP\SEO\AI_HTTP_Request\Domain\Exceptions\Service_Unavailable_Exception;
|
||||
use Yoast\WP\SEO\AI_HTTP_Request\Domain\Exceptions\Too_Many_Requests_Exception;
|
||||
use Yoast\WP\SEO\Conditionals\AI_Conditional;
|
||||
use Yoast\WP\SEO\Main;
|
||||
use Yoast\WP\SEO\Routes\Route_Interface;
|
||||
|
||||
/**
|
||||
* Registers a route toget suggestions from the AI API
|
||||
*
|
||||
* @makePublic
|
||||
*
|
||||
* @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded
|
||||
*/
|
||||
class Consent_Route implements Route_Interface {
|
||||
/**
|
||||
* The namespace for this route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const ROUTE_NAMESPACE = Main::API_V1_NAMESPACE;
|
||||
|
||||
/**
|
||||
* The prefix for this route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const ROUTE_PREFIX = '/ai_generator/consent';
|
||||
|
||||
/**
|
||||
* The consent handler instance.
|
||||
*
|
||||
* @var Consent_Handler
|
||||
*/
|
||||
private $consent_handler;
|
||||
|
||||
/**
|
||||
* The token manager instance.
|
||||
*
|
||||
* @var Token_Manager
|
||||
*/
|
||||
private $token_manager;
|
||||
|
||||
/**
|
||||
* Returns the conditionals based in which this loadable should be active.
|
||||
*
|
||||
* @return array<string> The conditionals.
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [ AI_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param Consent_Handler $consent_handler The consent handler.
|
||||
* @param Token_Manager $token_manager The token manager.
|
||||
*/
|
||||
public function __construct( Consent_Handler $consent_handler, Token_Manager $token_manager ) {
|
||||
$this->consent_handler = $consent_handler;
|
||||
$this->token_manager = $token_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
\register_rest_route(
|
||||
self::ROUTE_NAMESPACE,
|
||||
self::ROUTE_PREFIX,
|
||||
[
|
||||
'methods' => 'POST',
|
||||
'args' => [
|
||||
'consent' => [
|
||||
'required' => true,
|
||||
'type' => 'boolean',
|
||||
'description' => 'Whether the consent to use AI-based services has been given by the user.',
|
||||
],
|
||||
],
|
||||
'callback' => [ $this, 'consent' ],
|
||||
'permission_callback' => [ $this, 'check_permissions' ],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the callback to store the consent given by the user to use AI-based services.
|
||||
*
|
||||
* @param WP_REST_Request $request The request object.
|
||||
*
|
||||
* @return WP_REST_Response The response of the callback action.
|
||||
*/
|
||||
public function consent( WP_REST_Request $request ): WP_REST_Response {
|
||||
$user_id = \get_current_user_id();
|
||||
$consent = \boolval( $request->get_param( 'consent' ) );
|
||||
|
||||
try {
|
||||
if ( $consent ) {
|
||||
// Store the consent at user level.
|
||||
$this->consent_handler->grant_consent( $user_id );
|
||||
}
|
||||
else {
|
||||
// Delete the consent at user level.
|
||||
$this->consent_handler->revoke_consent( $user_id );
|
||||
// Invalidate the token if the user revoked the consent.
|
||||
$this->token_manager->token_invalidate( $user_id );
|
||||
}
|
||||
} catch ( Bad_Request_Exception | Forbidden_Exception | Internal_Server_Error_Exception | Not_Found_Exception | Payment_Required_Exception | Request_Timeout_Exception | Service_Unavailable_Exception | Too_Many_Requests_Exception | RuntimeException $e ) {
|
||||
return new WP_REST_Response( ( $consent ) ? 'Failed to store consent.' : 'Failed to revoke consent.', 500 );
|
||||
}
|
||||
|
||||
return new WP_REST_Response( ( $consent ) ? 'Consent successfully stored.' : 'Consent successfully revoked.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks:
|
||||
* - if the user is logged
|
||||
* - if the user can edit posts
|
||||
*
|
||||
* @return bool Whether the user is logged in, can edit posts and the feature is active.
|
||||
*/
|
||||
public function check_permissions(): bool {
|
||||
$user = \wp_get_current_user();
|
||||
if ( $user === null || $user->ID < 1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return \user_can( $user, 'edit_posts' );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user