plugin updates
This commit is contained in:
@@ -113,8 +113,7 @@ class Ai_Consent_Integration implements Integration_Interface {
|
||||
'wpseoPremiumManageAiConsentButton',
|
||||
[
|
||||
'hasConsent' => $this->user_helper->get_meta( $user_id, '_yoast_wpseo_ai_consent', true ),
|
||||
// Note: this is passing the Free plugin URL! As the image is located in there.
|
||||
'pluginUrl' => \plugins_url( '', \WPSEO_FILE ),
|
||||
'pluginUrl' => \plugins_url( '', \WPSEO_PREMIUM_FILE ),
|
||||
'wistiaEmbedPermission' => $this->wistia_embed_permission_repository->get_value_for_user( $user_id ),
|
||||
]
|
||||
);
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Premium\Integrations\Admin;
|
||||
|
||||
use WP_Screen;
|
||||
use WPSEO_Addon_Manager;
|
||||
use WPSEO_Admin_Asset_Manager;
|
||||
use Yoast\WP\SEO\Conditionals\Admin\Post_Conditional;
|
||||
use Yoast\WP\SEO\Helpers\Options_Helper;
|
||||
use Yoast\WP\SEO\Helpers\User_Helper;
|
||||
use Yoast\WP\SEO\Integrations\Integration_Interface;
|
||||
use Yoast\WP\SEO\Introductions\Infrastructure\Introductions_Seen_Repository;
|
||||
use Yoast\WP\SEO\Premium\Helpers\AI_Generator_Helper;
|
||||
use Yoast\WP\SEO\Premium\Introductions\Application\Ai_Fix_Assessments_Introduction;
|
||||
|
||||
/**
|
||||
* Ai_Fix_Assessments_Integration class.
|
||||
*
|
||||
* @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded
|
||||
*/
|
||||
class Ai_Fix_Assessments_Integration implements Integration_Interface {
|
||||
|
||||
/**
|
||||
* Represents the admin asset manager.
|
||||
*
|
||||
* @var WPSEO_Admin_Asset_Manager
|
||||
*/
|
||||
private $asset_manager;
|
||||
|
||||
/**
|
||||
* Represents the add-on manager.
|
||||
*
|
||||
* @var WPSEO_Addon_Manager
|
||||
*/
|
||||
private $addon_manager;
|
||||
|
||||
/**
|
||||
* Represents the AI generator helper.
|
||||
*
|
||||
* @var AI_Generator_Helper
|
||||
*/
|
||||
private $ai_generator_helper;
|
||||
|
||||
/**
|
||||
* Represents the options manager.
|
||||
*
|
||||
* @var Options_Helper
|
||||
*/
|
||||
private $options_helper;
|
||||
|
||||
/**
|
||||
* Represents the user helper.
|
||||
*
|
||||
* @var User_Helper
|
||||
*/
|
||||
private $user_helper;
|
||||
|
||||
/**
|
||||
* Represents the introductions seen repository.
|
||||
*
|
||||
* @var Introductions_Seen_Repository
|
||||
*/
|
||||
private $introductions_seen_repository;
|
||||
|
||||
/**
|
||||
* Returns the conditionals based in which this loadable should be active.
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
public static function get_conditionals(): array {
|
||||
return [ Post_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the class.
|
||||
*
|
||||
* @param WPSEO_Admin_Asset_Manager $asset_manager The admin asset manager.
|
||||
* @param WPSEO_Addon_Manager $addon_manager The addon manager.
|
||||
* @param AI_Generator_Helper $ai_generator_helper The AI generator helper.
|
||||
* @param Options_Helper $options_helper The options helper.
|
||||
* @param User_Helper $user_helper The user helper.
|
||||
* @param Introductions_Seen_Repository $introductions_seen_repository The introductions seen repository.
|
||||
*/
|
||||
public function __construct(
|
||||
WPSEO_Admin_Asset_Manager $asset_manager,
|
||||
WPSEO_Addon_Manager $addon_manager,
|
||||
AI_Generator_Helper $ai_generator_helper,
|
||||
Options_Helper $options_helper,
|
||||
User_Helper $user_helper,
|
||||
Introductions_Seen_Repository $introductions_seen_repository
|
||||
) {
|
||||
$this->asset_manager = $asset_manager;
|
||||
$this->addon_manager = $addon_manager;
|
||||
$this->ai_generator_helper = $ai_generator_helper;
|
||||
$this->options_helper = $options_helper;
|
||||
$this->user_helper = $user_helper;
|
||||
$this->introductions_seen_repository = $introductions_seen_repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the integration.
|
||||
*
|
||||
* This is the place to register hooks and filters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
if ( ! $this->options_helper->get( 'enable_ai_generator', false ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
\add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
|
||||
\add_action( 'admin_head', [ $this, 'render_react_container' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the React container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function render_react_container(): void {
|
||||
if ( ! WP_Screen::get()->is_block_editor() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<div id="yoast-seo-premium-ai-fix-assessments"></div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the subscription status for Yoast SEO Premium and Yoast WooCommerce SEO.
|
||||
*
|
||||
* @return array<string, bool>
|
||||
*/
|
||||
public function get_product_subscriptions() {
|
||||
return [
|
||||
'premiumSubscription' => $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG ),
|
||||
'wooCommerceSubscription' => $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::WOOCOMMERCE_SLUG ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues the required assets.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_assets() {
|
||||
if ( ! WP_Screen::get()->is_block_editor() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user_id = $this->user_helper->get_current_user_id();
|
||||
|
||||
\wp_enqueue_script( 'wp-seo-premium-ai-fix-assessments' );
|
||||
\wp_localize_script(
|
||||
'wp-seo-premium-fix-assessments',
|
||||
'wpseoPremiumAiFixAssessments',
|
||||
[
|
||||
'adminUrl' => \admin_url( 'admin.php' ),
|
||||
'hasConsent' => $this->user_helper->get_meta( $user_id, '_yoast_wpseo_ai_consent', true ),
|
||||
'productSubscriptions' => $this->get_product_subscriptions(),
|
||||
'hasSeenIntroduction' => $this->introductions_seen_repository->is_introduction_seen( $user_id, Ai_Fix_Assessments_Introduction::ID ),
|
||||
'pluginUrl' => \plugins_url( '', \WPSEO_PREMIUM_FILE ),
|
||||
'requestTimeout' => $this->ai_generator_helper->get_request_timeout(),
|
||||
]
|
||||
);
|
||||
$this->asset_manager->enqueue_style( 'premium-ai-fix-assessments' );
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ use Yoast\WP\SEO\Introductions\Infrastructure\Introductions_Seen_Repository;
|
||||
use Yoast\WP\SEO\Premium\Conditionals\Ai_Editor_Conditional;
|
||||
use Yoast\WP\SEO\Premium\Helpers\AI_Generator_Helper;
|
||||
use Yoast\WP\SEO\Premium\Helpers\Current_Page_Helper;
|
||||
use Yoast\WP\SEO\Premium\Introductions\Application\Ai_Generate_Titles_And_Descriptions_Introduction;
|
||||
use Yoast\WP\SEO\Premium\Introductions\Application\Ai_Fix_Assessments_Introduction;
|
||||
|
||||
/**
|
||||
* Ai_Generator_Integration class.
|
||||
@@ -150,7 +150,7 @@ class Ai_Generator_Integration implements Integration_Interface {
|
||||
'adminUrl' => \admin_url( 'admin.php' ),
|
||||
'hasConsent' => $this->user_helper->get_meta( $user_id, '_yoast_wpseo_ai_consent', true ),
|
||||
'productSubscriptions' => $this->get_product_subscriptions(),
|
||||
'hasSeenIntroduction' => $this->introductions_seen_repository->is_introduction_seen( $user_id, Ai_Generate_Titles_And_Descriptions_Introduction::ID ),
|
||||
'hasSeenIntroduction' => $this->introductions_seen_repository->is_introduction_seen( $user_id, Ai_Fix_Assessments_Introduction::ID ),
|
||||
'pluginUrl' => \plugins_url( '', \WPSEO_PREMIUM_FILE ),
|
||||
'postType' => $this->get_post_type(),
|
||||
'contentType' => $this->get_content_type(),
|
||||
|
||||
@@ -138,9 +138,8 @@ class Update_Premium_Notification implements Integration_Interface {
|
||||
'action': 'dismiss_update_premium_notification',
|
||||
};
|
||||
|
||||
jQuery.post( ajaxurl, data, function( response ) {
|
||||
jQuery( '#yoast-update-premium-notification' ).hide();
|
||||
});
|
||||
jQuery( '#yoast-update-premium-notification' ).hide();
|
||||
jQuery.post( ajaxurl, data, function( response ) {});
|
||||
}
|
||||
|
||||
jQuery( document ).ready( function() {
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
namespace Yoast\WP\SEO\Premium\Integrations\Blocks;
|
||||
|
||||
use Yoast\WP\SEO\Integrations\Blocks\Dynamic_Block;
|
||||
use Yoast\WP\SEO\Integrations\Blocks\Dynamic_Block_V3;
|
||||
|
||||
/**
|
||||
* Estimated_Reading_Time_Block class.
|
||||
*
|
||||
* @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded
|
||||
*/
|
||||
class Estimated_Reading_Time_Block extends Dynamic_Block {
|
||||
class Estimated_Reading_Time_Block extends Dynamic_Block_V3 {
|
||||
|
||||
/**
|
||||
* The name of the block.
|
||||
@@ -33,47 +33,17 @@ class Estimated_Reading_Time_Block extends Dynamic_Block {
|
||||
protected $script = 'wp-seo-premium-dynamic-blocks';
|
||||
|
||||
/**
|
||||
* Registers the block.
|
||||
*
|
||||
* @return void
|
||||
* The constructor.
|
||||
*/
|
||||
public function register_block() {
|
||||
\register_block_type(
|
||||
'yoast-seo/' . $this->block_name,
|
||||
[
|
||||
'editor_script' => $this->script,
|
||||
'render_callback' => [ $this, 'present' ],
|
||||
'attributes' => [
|
||||
'className' => [
|
||||
'default' => '',
|
||||
'type' => 'string',
|
||||
],
|
||||
'estimatedReadingTime' => [
|
||||
'type' => 'number',
|
||||
'default' => 0,
|
||||
],
|
||||
'descriptiveText' => [
|
||||
'type' => 'string',
|
||||
'default' => \__( 'Estimated reading time:', 'wordpress-seo-premium' ) . ' ',
|
||||
],
|
||||
'showDescriptiveText' => [
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
],
|
||||
'showIcon' => [
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
public function __construct() {
|
||||
$this->base_path = \WPSEO_PREMIUM_PATH . 'assets/blocks/dynamic-blocks/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Presents the block output.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $content The content.
|
||||
* @param array<string, bool|string|int|array> $attributes The block attributes.
|
||||
* @param string $content The content.
|
||||
*
|
||||
* @return string The block output.
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,7 @@ class Related_Links_Block implements Integration_Interface {
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
\register_block_type( 'yoast-seo/related-links', [ 'editor_script' => 'wp-seo-premium-blocks' ] );
|
||||
$base_path = \WPSEO_PREMIUM_PATH . 'assets/blocks/dynamic-blocks/';
|
||||
\register_block_type( $base_path . 'related-links-block/block.json', [ 'editor_script_handles' => [ 'wp-seo-premium-blocks' ] ] );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ use WPSEO_Remote_Request;
|
||||
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
||||
use Yoast\WP\SEO\Helpers\Options_Helper;
|
||||
use Yoast\WP\SEO\Helpers\Post_Type_Helper;
|
||||
use Yoast\WP\SEO\Helpers\Request_Helper;
|
||||
use Yoast\WP\SEO\Integrations\Integration_Interface;
|
||||
|
||||
/**
|
||||
@@ -24,13 +23,6 @@ class Index_Now_Ping implements Integration_Interface {
|
||||
*/
|
||||
private $options_helper;
|
||||
|
||||
/**
|
||||
* The request helper.
|
||||
*
|
||||
* @var Request_Helper
|
||||
*/
|
||||
private $request_helper;
|
||||
|
||||
/**
|
||||
* The post type helper.
|
||||
*
|
||||
@@ -49,16 +41,13 @@ class Index_Now_Ping implements Integration_Interface {
|
||||
* Index_Now_Ping integration constructor.
|
||||
*
|
||||
* @param Options_Helper $options_helper The option helper.
|
||||
* @param Request_Helper $request_helper The request helper.
|
||||
* @param Post_Type_Helper $post_type_helper The post type helper.
|
||||
*/
|
||||
public function __construct(
|
||||
Options_Helper $options_helper,
|
||||
Request_Helper $request_helper,
|
||||
Post_Type_Helper $post_type_helper
|
||||
) {
|
||||
$this->options_helper = $options_helper;
|
||||
$this->request_helper = $request_helper;
|
||||
$this->post_type_helper = $post_type_helper;
|
||||
|
||||
/**
|
||||
@@ -111,7 +100,7 @@ class Index_Now_Ping implements Integration_Interface {
|
||||
}
|
||||
|
||||
// The block editor saves published posts twice, we want to ping only on the first request.
|
||||
if ( $new_status === 'publish' && $this->request_helper->is_rest_request() ) {
|
||||
if ( $new_status === 'publish' && \wp_is_serving_rest_request() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,21 @@ class AI_Generator_Route implements Route_Interface {
|
||||
public const GET_SUGGESTIONS_ROUTE = self::ROUTE_PREFIX . '/get_suggestions';
|
||||
|
||||
/**
|
||||
* The get_suggestions route constant.
|
||||
* The fix_assessments route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const FIX_ASSESSMENTS_ROUTE = self::ROUTE_PREFIX . '/fix_assessments';
|
||||
|
||||
/**
|
||||
* The get_usage route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const GET_USAGE_ROUTE = self::ROUTE_PREFIX . '/get_usage';
|
||||
|
||||
/**
|
||||
* The consent route constant.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
@@ -167,6 +181,8 @@ class AI_Generator_Route implements Route_Interface {
|
||||
'meta-description',
|
||||
'product-seo-title',
|
||||
'product-meta-description',
|
||||
'product-taxonomy-seo-title',
|
||||
'product-taxonomy-meta-description',
|
||||
'taxonomy-seo-title',
|
||||
'taxonomy-meta-description',
|
||||
],
|
||||
@@ -203,6 +219,59 @@ class AI_Generator_Route implements Route_Interface {
|
||||
]
|
||||
);
|
||||
|
||||
\register_rest_route(
|
||||
Main::API_V1_NAMESPACE,
|
||||
self::FIX_ASSESSMENTS_ROUTE,
|
||||
[
|
||||
'methods' => 'POST',
|
||||
'args' => [
|
||||
'assessment' => [
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'enum' => [
|
||||
'keyphrase-introduction',
|
||||
'keyphrase-density',
|
||||
'keyphrase-distribution',
|
||||
'keyphrase-subheadings',
|
||||
],
|
||||
'description' => 'The assessment.',
|
||||
],
|
||||
'prompt_content' => [
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'description' => 'The content needed by the prompt to ask for suggestions.',
|
||||
],
|
||||
'focus_keyphrase' => [
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'description' => 'The focus keyphrase associated to the post.',
|
||||
],
|
||||
'synonyms' => [
|
||||
'required' => false,
|
||||
'type' => 'string',
|
||||
'description' => 'The synonyms for the focus keyphrase.',
|
||||
],
|
||||
'language' => [
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'description' => 'The language the post is written in.',
|
||||
],
|
||||
],
|
||||
'callback' => [ $this, 'fix_assessments' ],
|
||||
'permission_callback' => [ $this, 'check_permissions' ],
|
||||
]
|
||||
);
|
||||
|
||||
\register_rest_route(
|
||||
Main::API_V1_NAMESPACE,
|
||||
self::GET_USAGE_ROUTE,
|
||||
[
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'get_usage' ],
|
||||
'permission_callback' => [ $this, 'check_permissions' ],
|
||||
]
|
||||
);
|
||||
|
||||
\register_rest_route(
|
||||
Main::API_V1_NAMESPACE,
|
||||
self::BUST_SUBSCRIPTION_CACHE_ROUTE,
|
||||
@@ -238,7 +307,7 @@ class AI_Generator_Route implements Route_Interface {
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the callback to get ai-generated suggestions.
|
||||
* Runs the callback to get AI-generated suggestions.
|
||||
*
|
||||
* @param WP_REST_Request $request The request object.
|
||||
*
|
||||
@@ -267,6 +336,36 @@ class AI_Generator_Route implements Route_Interface {
|
||||
return new WP_REST_Response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the callback to improve assessment results through AI.
|
||||
*
|
||||
* @param WP_REST_Request $request The request object.
|
||||
*
|
||||
* @return WP_REST_Response The response of the assess action.
|
||||
*/
|
||||
public function fix_assessments( WP_REST_Request $request ) {
|
||||
try {
|
||||
$user = \wp_get_current_user();
|
||||
$data = $this->ai_generator_action->fix_assessments( $user, $request['assessment'], $request['prompt_content'], $request['focus_keyphrase'], $request['synonyms'], $request['language'] );
|
||||
} catch ( Remote_Request_Exception $e ) {
|
||||
$message = [
|
||||
'message' => $e->getMessage(),
|
||||
'errorIdentifier' => $e->get_error_identifier(),
|
||||
];
|
||||
if ( $e instanceof Payment_Required_Exception ) {
|
||||
$message['missingLicenses'] = $e->get_missing_licenses();
|
||||
}
|
||||
return new WP_REST_Response(
|
||||
$message,
|
||||
$e->getCode()
|
||||
);
|
||||
} catch ( RuntimeException $e ) {
|
||||
return new WP_REST_Response( 'Failed to retrieve text improvements.', 500 );
|
||||
}
|
||||
|
||||
return new WP_REST_Response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the callback to store the consent given by the user to use AI-based services.
|
||||
*
|
||||
@@ -287,6 +386,26 @@ class AI_Generator_Route implements Route_Interface {
|
||||
return new WP_REST_Response( ( $consent ) ? 'Consent successfully stored.' : 'Consent successfully revoked.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the callback that gets the monthly usage of the user.
|
||||
*
|
||||
* @return WP_REST_Response The response of the callback action.
|
||||
*/
|
||||
public function get_usage() {
|
||||
$user = \wp_get_current_user();
|
||||
|
||||
try {
|
||||
$data = $this->ai_generator_action->get_usage( $user );
|
||||
} catch ( Remote_Request_Exception $e ) {
|
||||
return new WP_REST_Response(
|
||||
'Failed to get usage: ' . $e->getMessage(),
|
||||
$e->getCode()
|
||||
);
|
||||
}
|
||||
|
||||
return new WP_REST_Response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the callback that busts the subscription cache.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user