plugin updates
This commit is contained in:
@@ -1,101 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\Application;
|
||||
|
||||
use Yoast\WP\SEO\Helpers\Options_Helper;
|
||||
use Yoast\WP\SEO\Helpers\Product_Helper;
|
||||
use Yoast\WP\SEO\Introductions\Domain\Introduction_Interface;
|
||||
|
||||
/**
|
||||
* Represents the introduction for the AI generate titles and introduction upsell.
|
||||
*
|
||||
* @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded
|
||||
*/
|
||||
class Ai_Generate_Titles_And_Descriptions_Introduction_Upsell implements Introduction_Interface {
|
||||
|
||||
use Current_Page_Trait;
|
||||
use User_Allowed_Trait;
|
||||
use Version_Trait;
|
||||
|
||||
/**
|
||||
* Holds the product helper.
|
||||
*
|
||||
* @var Product_Helper
|
||||
*/
|
||||
private $product_helper;
|
||||
|
||||
/**
|
||||
* Holds the options' helper.
|
||||
*
|
||||
* @var Options_Helper
|
||||
*/
|
||||
private $options_helper;
|
||||
|
||||
/**
|
||||
* Constructs the introduction.
|
||||
*
|
||||
* @param Product_Helper $product_helper The product helper.
|
||||
* @param Options_Helper $options_helper The options' helper.
|
||||
*/
|
||||
public function __construct(
|
||||
Product_Helper $product_helper,
|
||||
Options_Helper $options_helper
|
||||
) {
|
||||
$this->product_helper = $product_helper;
|
||||
$this->options_helper = $options_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_id() {
|
||||
return 'ai-generate-titles-and-descriptions-upsell';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique name.
|
||||
*
|
||||
* @deprecated 21.6
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
\_deprecated_function( __METHOD__, 'Yoast SEO 21.6', 'Please use get_id() instead' );
|
||||
|
||||
return $this->get_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the requested pagination priority. Lower means earlier.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_priority() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this introduction should show.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function should_show() {
|
||||
if ( $this->product_helper->is_premium() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->options_helper->get( 'previous_version', '' ) === '' ) {
|
||||
// The current installation is a new one (not upgraded yet).
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->is_user_allowed( [ 'edit_posts' ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\Application;
|
||||
|
||||
trait Current_Page_Trait {
|
||||
|
||||
/**
|
||||
* Determines whether the current page is applicable.
|
||||
*
|
||||
* @param string[] $pages The applicable pages.
|
||||
*
|
||||
* @return bool Whether the current page is applicable.
|
||||
*/
|
||||
private function is_on_yoast_page( $pages ) {
|
||||
return \in_array( $this->get_page(), $pages, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the current page is one of our installation pages.
|
||||
*
|
||||
* @return bool Whether the current page is one of our installation pages.
|
||||
*/
|
||||
private function is_on_installation_page() {
|
||||
return $this->is_on_yoast_page( [ 'wpseo_installation_successful_free', 'wpseo_installation_successful' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the page variable.
|
||||
*
|
||||
* Note: the result is not safe to use in anything than strict comparisons!
|
||||
*
|
||||
* @return string The page variable.
|
||||
*/
|
||||
private function get_page() {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
|
||||
if ( isset( $_GET['page'] ) && \is_string( $_GET['page'] ) ) {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form information, only using it in strict comparison.
|
||||
return \wp_unslash( $_GET['page'] );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\Application;
|
||||
|
||||
use Yoast\WP\SEO\Introductions\Domain\Introduction_Interface;
|
||||
use Yoast\WP\SEO\Introductions\Domain\Introduction_Item;
|
||||
use Yoast\WP\SEO\Introductions\Domain\Introductions_Bucket;
|
||||
use Yoast\WP\SEO\Introductions\Infrastructure\Introductions_Seen_Repository;
|
||||
|
||||
/**
|
||||
* Manages the collection of introductions.
|
||||
*/
|
||||
class Introductions_Collector {
|
||||
|
||||
/**
|
||||
* Holds all the introductions.
|
||||
*
|
||||
* @var Introduction_Interface[]
|
||||
*/
|
||||
private $introductions;
|
||||
|
||||
/**
|
||||
* Constructs the collector.
|
||||
*
|
||||
* @param Introduction_Interface ...$introductions All the introductions.
|
||||
*/
|
||||
public function __construct( Introduction_Interface ...$introductions ) {
|
||||
$this->introductions = $this->add_introductions( ...$introductions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data for the introductions.
|
||||
*
|
||||
* @param int $user_id The user ID.
|
||||
*
|
||||
* @return array The list of introductions.
|
||||
*/
|
||||
public function get_for( $user_id ) {
|
||||
$bucket = new Introductions_Bucket();
|
||||
$metadata = $this->get_metadata( $user_id );
|
||||
|
||||
foreach ( $this->introductions as $introduction ) {
|
||||
if ( ! $introduction->should_show() ) {
|
||||
continue;
|
||||
}
|
||||
if ( $this->is_seen( $introduction->get_id(), $metadata ) ) {
|
||||
continue;
|
||||
}
|
||||
$bucket->add_introduction(
|
||||
new Introduction_Item( $introduction->get_id(), $introduction->get_priority() )
|
||||
);
|
||||
}
|
||||
|
||||
return $bucket->to_array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters introductions with the 'wpseo_introductions' filter.
|
||||
*
|
||||
* @param Introduction_Interface ...$introductions The introductions.
|
||||
*
|
||||
* @return Introduction_Interface[]
|
||||
*/
|
||||
private function add_introductions( Introduction_Interface ...$introductions ) {
|
||||
/**
|
||||
* Filter: Adds the possibility to add additional introductions to be included.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param Introduction_Interface $introductions This filter expects a list of Introduction_Interface instances and
|
||||
* expects only Introduction_Interface implementations to be added to the list.
|
||||
*/
|
||||
$filtered_introductions = (array) \apply_filters( 'wpseo_introductions', $introductions );
|
||||
|
||||
return \array_filter(
|
||||
$filtered_introductions,
|
||||
static function ( $introduction ) {
|
||||
return \is_a( $introduction, Introduction_Interface::class );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the introductions metadata for the user.
|
||||
*
|
||||
* @param int $user_id The user ID.
|
||||
*
|
||||
* @return array The introductions' metadata.
|
||||
*/
|
||||
private function get_metadata( $user_id ) {
|
||||
$metadata = \get_user_meta( $user_id, Introductions_Seen_Repository::USER_META_KEY, true );
|
||||
if ( \is_array( $metadata ) ) {
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the user has seen the introduction.
|
||||
*
|
||||
* @param string $name The name.
|
||||
* @param string[] $metadata The metadata.
|
||||
*
|
||||
* @return bool Whether the user has seen the introduction.
|
||||
*/
|
||||
private function is_seen( $name, $metadata ) {
|
||||
if ( \array_key_exists( $name, $metadata ) ) {
|
||||
return (bool) $metadata[ $name ];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given introduction ID is a known ID to the system.
|
||||
*
|
||||
* @param string $introduction_id The introduction ID to check.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available_introduction( string $introduction_id ): bool {
|
||||
foreach ( $this->introductions as $introduction ) {
|
||||
if ( $introduction->get_id() === $introduction_id ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\Application;
|
||||
|
||||
trait User_Allowed_Trait {
|
||||
|
||||
/**
|
||||
* Determines whether the user has the required capabilities.
|
||||
*
|
||||
* @param string[] $capabilities The required capabilities.
|
||||
*
|
||||
* @return bool Whether the user has the required capabilities.
|
||||
*/
|
||||
private function is_user_allowed( $capabilities ) {
|
||||
foreach ( $capabilities as $capability ) {
|
||||
if ( ! \current_user_can( $capability ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\Application;
|
||||
|
||||
trait Version_Trait {
|
||||
|
||||
/**
|
||||
* Determines whether the version is between a min (inclusive) and max (exclusive).
|
||||
*
|
||||
* @param string $version The version to compare.
|
||||
* @param string $min_version The minimum version.
|
||||
* @param string $max_version The maximum version.
|
||||
*
|
||||
* @return bool Whether the version is between a min and max.
|
||||
*/
|
||||
private function is_version_between( $version, $min_version, $max_version ) {
|
||||
return ( \version_compare( $version, $min_version, '>=' )
|
||||
&& \version_compare( $version, $max_version, '<' )
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\Domain;
|
||||
|
||||
/**
|
||||
* Represents an introduction.
|
||||
*/
|
||||
interface Introduction_Interface {
|
||||
|
||||
/**
|
||||
* Returns the ID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_id();
|
||||
|
||||
/**
|
||||
* Returns the unique name.
|
||||
*
|
||||
* @deprecated 21.6
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name();
|
||||
|
||||
/**
|
||||
* Returns the requested pagination priority. Lower means earlier.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_priority();
|
||||
|
||||
/**
|
||||
* Returns whether this introduction should show.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function should_show();
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\Domain;
|
||||
|
||||
/**
|
||||
* Domain object that holds introduction information.
|
||||
*/
|
||||
class Introduction_Item {
|
||||
|
||||
/**
|
||||
* The ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* The priority.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $priority;
|
||||
|
||||
/**
|
||||
* Constructs the instance.
|
||||
*
|
||||
* @param string $id The ID.
|
||||
* @param int $priority The priority.
|
||||
*/
|
||||
public function __construct( $id, $priority ) {
|
||||
$this->id = $id;
|
||||
$this->priority = $priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array representation of the data.
|
||||
*
|
||||
* @return array Returns in an array format.
|
||||
*/
|
||||
public function to_array() {
|
||||
return [
|
||||
'id' => $this->get_id(),
|
||||
'priority' => $this->get_priority(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_id() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the requested pagination priority. Higher means earlier.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_priority() {
|
||||
return $this->priority;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\Domain;
|
||||
|
||||
/**
|
||||
* A collection domain object.
|
||||
*/
|
||||
class Introductions_Bucket {
|
||||
|
||||
/**
|
||||
* Holds the introductions.
|
||||
*
|
||||
* @var Introduction_Item[]
|
||||
*/
|
||||
private $introductions;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->introductions = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an introduction to this bucket.
|
||||
*
|
||||
* @param Introduction_Item $introduction The introduction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_introduction( Introduction_Item $introduction ) {
|
||||
$this->introductions[] = $introduction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array representation of the introductions.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function to_array() {
|
||||
// No sorting here because that is done in JS.
|
||||
return \array_map(
|
||||
static function ( $item ) {
|
||||
return $item->to_array();
|
||||
},
|
||||
$this->introductions
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\Domain;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Invalid user ID.
|
||||
*/
|
||||
class Invalid_User_Id_Exception extends InvalidArgumentException {
|
||||
|
||||
/**
|
||||
* Constructs the exception.
|
||||
*
|
||||
* @link https://php.net/manual/en/exception.construct.php
|
||||
*
|
||||
* @param string $message Optional. The Exception message to throw.
|
||||
* @param int $code Optional. The Exception code.
|
||||
* @param Throwable|null $previous Optional. The previous throwable used for the exception chaining.
|
||||
*/
|
||||
public function __construct( // phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod.Found -- Reason: A default message is used.
|
||||
$message = 'Invalid User ID',
|
||||
$code = 0,
|
||||
$previous = null
|
||||
) {
|
||||
parent::__construct( $message, $code, $previous );
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\Infrastructure;
|
||||
|
||||
use Yoast\WP\SEO\Helpers\User_Helper;
|
||||
use Yoast\WP\SEO\Introductions\Domain\Invalid_User_Id_Exception;
|
||||
|
||||
/**
|
||||
* Stores and retrieves whether the user has seen certain introductions.
|
||||
*/
|
||||
class Introductions_Seen_Repository {
|
||||
|
||||
public const USER_META_KEY = '_yoast_wpseo_introductions';
|
||||
|
||||
public const DEFAULT_VALUE = [];
|
||||
|
||||
/**
|
||||
* Holds the User_Helper instance.
|
||||
*
|
||||
* @var User_Helper
|
||||
*/
|
||||
private $user_helper;
|
||||
|
||||
/**
|
||||
* Constructs the class.
|
||||
*
|
||||
* @param User_Helper $user_helper The User_Helper.
|
||||
*/
|
||||
public function __construct( User_Helper $user_helper ) {
|
||||
$this->user_helper = $user_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the introductions.
|
||||
*
|
||||
* @param int $user_id User ID.
|
||||
*
|
||||
* @return array The introductions.
|
||||
*
|
||||
* @throws Invalid_User_Id_Exception If an invalid user ID is supplied.
|
||||
*/
|
||||
public function get_all_introductions( $user_id ): array {
|
||||
$seen_introductions = $this->user_helper->get_meta( $user_id, self::USER_META_KEY, true );
|
||||
if ( $seen_introductions === false ) {
|
||||
throw new Invalid_User_Id_Exception();
|
||||
}
|
||||
|
||||
if ( \is_array( $seen_introductions ) ) {
|
||||
return $seen_introductions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Why could $value be invalid?
|
||||
* - When the database row does not exist yet, $value can be an empty string.
|
||||
* - Faulty data was stored?
|
||||
*/
|
||||
return self::DEFAULT_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the introductions.
|
||||
*
|
||||
* @param int $user_id The user ID.
|
||||
* @param array $introductions The introductions.
|
||||
*
|
||||
* @return bool True on successful update, false on failure or if the value passed to the function is the same as
|
||||
* the one that is already in the database.
|
||||
*/
|
||||
public function set_all_introductions( $user_id, array $introductions ): bool {
|
||||
return $this->user_helper->update_meta( $user_id, self::USER_META_KEY, $introductions ) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves whether an introduction is seen.
|
||||
*
|
||||
* @param int $user_id User ID.
|
||||
* @param string $introduction_id The introduction ID.
|
||||
*
|
||||
* @return bool Whether the introduction is seen.
|
||||
*
|
||||
* @throws Invalid_User_Id_Exception If an invalid user ID is supplied.
|
||||
*/
|
||||
public function is_introduction_seen( $user_id, string $introduction_id ): bool {
|
||||
$introductions = $this->get_all_introductions( $user_id );
|
||||
|
||||
if ( \array_key_exists( $introduction_id, $introductions ) ) {
|
||||
return (bool) $introductions[ $introduction_id ];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the introduction as seen.
|
||||
*
|
||||
* @param int $user_id The user ID.
|
||||
* @param string $introduction_id The introduction ID.
|
||||
* @param bool $is_seen Whether the introduction is seen. Defaults to true.
|
||||
*
|
||||
* @return bool False on failure. Not having to update is a success.
|
||||
*
|
||||
* @throws Invalid_User_Id_Exception If an invalid user ID is supplied.
|
||||
*/
|
||||
public function set_introduction( $user_id, string $introduction_id, bool $is_seen = true ): bool {
|
||||
$introductions = $this->get_all_introductions( $user_id );
|
||||
|
||||
// Check if the wanted value is already set.
|
||||
if ( \array_key_exists( $introduction_id, $introductions ) && $introductions[ $introduction_id ] === $is_seen ) {
|
||||
return true;
|
||||
}
|
||||
$introductions[ $introduction_id ] = $is_seen;
|
||||
|
||||
return $this->set_all_introductions( $user_id, $introductions );
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\Infrastructure;
|
||||
|
||||
use Exception;
|
||||
use Yoast\WP\SEO\Helpers\User_Helper;
|
||||
|
||||
/**
|
||||
* Takes care of the get/set in the WP user meta.
|
||||
*
|
||||
* @makePublic
|
||||
*/
|
||||
class Wistia_Embed_Permission_Repository {
|
||||
|
||||
public const USER_META_KEY = '_yoast_wpseo_wistia_embed_permission';
|
||||
|
||||
public const DEFAULT_VALUE = false;
|
||||
|
||||
/**
|
||||
* Holds the User_Helper instance.
|
||||
*
|
||||
* @var User_Helper
|
||||
*/
|
||||
private $user_helper;
|
||||
|
||||
/**
|
||||
* Constructs the class.
|
||||
*
|
||||
* @param User_Helper $user_helper The User_Helper.
|
||||
*/
|
||||
public function __construct( User_Helper $user_helper ) {
|
||||
$this->user_helper = $user_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current value for a user.
|
||||
*
|
||||
* @param int $user_id User ID.
|
||||
*
|
||||
* @return bool The current value.
|
||||
*
|
||||
* @throws Exception If an invalid user ID is supplied.
|
||||
*/
|
||||
public function get_value_for_user( $user_id ) {
|
||||
$value = $this->user_helper->get_meta( $user_id, self::USER_META_KEY, true );
|
||||
if ( $value === false ) {
|
||||
throw new Exception( 'Invalid User ID' );
|
||||
}
|
||||
|
||||
if ( $value === '0' || $value === '1' ) {
|
||||
// The value is stored as a string because otherwise we can not see the difference between false and an invalid user ID.
|
||||
return $value === '1';
|
||||
}
|
||||
|
||||
/**
|
||||
* Why could $value be invalid?
|
||||
* - When the database row does not exist yet, $value can be an empty string.
|
||||
* - Faulty data was stored?
|
||||
*/
|
||||
return self::DEFAULT_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Wistia embed permission value for the current user.
|
||||
*
|
||||
* @param int $user_id The user ID.
|
||||
* @param bool $value The value.
|
||||
*
|
||||
* @return bool Whether the update was successful.
|
||||
*
|
||||
* @throws Exception If an invalid user ID is supplied.
|
||||
*/
|
||||
public function set_value_for_user( $user_id, $value ) {
|
||||
// The value is stored as a string because otherwise we can not see the difference between false and an invalid user ID.
|
||||
$value_as_string = ( $value === true ) ? '1' : '0';
|
||||
|
||||
// Checking for only false, not interested in not having to update.
|
||||
return $this->user_helper->update_meta( $user_id, self::USER_META_KEY, $value_as_string ) !== false;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
# Introductions
|
||||
|
||||
Is for showing introductions to a user, on Yoast admin pages.
|
||||
Based on plugin version, page, user capabilities and whether the user has seen it already.
|
||||
|
||||
- `Introduction_Interface` defines what data is needed
|
||||
- `id` as unique identifier
|
||||
- `plugin` and `version` to determine if the introduction is new (version > plugin version)
|
||||
- `pages` to be able to only show on certain Yoast admin pages
|
||||
- `capabilities` to be able to only show for certain users
|
||||
- `Introductions_Collector` uses that data to determine whether an introduction should be "shown" to a user
|
||||
- uses the `wpseo_introductions` filter to be extendable from our other plugins
|
||||
- uses `Introductions_Seen_Repository` to get the data to determine if the user saw an introduction already
|
||||
- `Introductions_Seen_Repository` is the doorway whether a user has seen an introduction or not
|
||||
- uses the `_yoast_introductions` user metadata
|
||||
- `Introduction_Bucket` and `Introduction_Item` are used by the collector to get an array
|
||||
- `Introductions_Integration` runs on the Yoast Admin pages and loads the assets
|
||||
- only loads on our Yoast admin pages, but never on our installation success pages as to not disturb onboarding
|
||||
- only loads assets if there is an introduction to show
|
||||
- `js/src/introductions` holds the JS
|
||||
- `wpseoIntroductions` is the localized script to transfer data from PHP to JS
|
||||
- `css/src/ai-generator.css` holds the CSS
|
||||
|
||||
Inside JS, register the modal content via `window.YoastSEO._registerIntroductionComponent`, which takes a
|
||||
`id` and a `Component`. The id needs to be the same as the id in the `Introduction_Interface`.
|
||||
The action `yoast.introductions.ready` can be used to know whether the registration function is available and ready for
|
||||
use.
|
||||
@@ -1,164 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\User_Interface;
|
||||
|
||||
use WPSEO_Admin_Asset_Manager;
|
||||
use Yoast\WP\SEO\Conditionals\Admin\Yoast_Admin_Conditional;
|
||||
use Yoast\WP\SEO\Helpers\Product_Helper;
|
||||
use Yoast\WP\SEO\Helpers\Short_Link_Helper;
|
||||
use Yoast\WP\SEO\Helpers\User_Helper;
|
||||
use Yoast\WP\SEO\Integrations\Integration_Interface;
|
||||
use Yoast\WP\SEO\Introductions\Application\Current_Page_Trait;
|
||||
use Yoast\WP\SEO\Introductions\Application\Introductions_Collector;
|
||||
use Yoast\WP\SEO\Introductions\Infrastructure\Wistia_Embed_Permission_Repository;
|
||||
|
||||
/**
|
||||
* Loads introduction modal scripts, when there are applicable introductions.
|
||||
*/
|
||||
class Introductions_Integration implements Integration_Interface {
|
||||
|
||||
use Current_Page_Trait;
|
||||
|
||||
public const SCRIPT_HANDLE = 'introductions';
|
||||
|
||||
/**
|
||||
* Holds the admin asset manager.
|
||||
*
|
||||
* @var WPSEO_Admin_Asset_Manager
|
||||
*/
|
||||
private $admin_asset_manager;
|
||||
|
||||
/**
|
||||
* Holds the introduction collector.
|
||||
*
|
||||
* @var Introductions_Collector
|
||||
*/
|
||||
private $introductions_collector;
|
||||
|
||||
/**
|
||||
* Holds the product helper.
|
||||
*
|
||||
* @var Product_Helper
|
||||
*/
|
||||
private $product_helper;
|
||||
|
||||
/**
|
||||
* Holds the user helper.
|
||||
*
|
||||
* @var User_Helper
|
||||
*/
|
||||
private $user_helper;
|
||||
|
||||
/**
|
||||
* Holds the short link helper.
|
||||
*
|
||||
* @var Short_Link_Helper
|
||||
*/
|
||||
private $short_link_helper;
|
||||
|
||||
/**
|
||||
* Holds the repository.
|
||||
*
|
||||
* @var Wistia_Embed_Permission_Repository
|
||||
*/
|
||||
private $wistia_embed_permission_repository;
|
||||
|
||||
/**
|
||||
* Returns the conditionals based in which this loadable should be active.
|
||||
*
|
||||
* In this case: when on an admin page.
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [ Yoast_Admin_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the integration.
|
||||
*
|
||||
* @param WPSEO_Admin_Asset_Manager $admin_asset_manager The admin asset manager.
|
||||
* @param Introductions_Collector $introductions_collector The introductions' collector.
|
||||
* @param Product_Helper $product_helper The product helper.
|
||||
* @param User_Helper $user_helper The user helper.
|
||||
* @param Short_Link_Helper $short_link_helper The short link helper.
|
||||
* @param Wistia_Embed_Permission_Repository $wistia_embed_permission_repository The repository.
|
||||
*/
|
||||
public function __construct(
|
||||
WPSEO_Admin_Asset_Manager $admin_asset_manager,
|
||||
Introductions_Collector $introductions_collector,
|
||||
Product_Helper $product_helper,
|
||||
User_Helper $user_helper,
|
||||
Short_Link_Helper $short_link_helper,
|
||||
Wistia_Embed_Permission_Repository $wistia_embed_permission_repository
|
||||
) {
|
||||
$this->admin_asset_manager = $admin_asset_manager;
|
||||
$this->introductions_collector = $introductions_collector;
|
||||
$this->product_helper = $product_helper;
|
||||
$this->user_helper = $user_helper;
|
||||
$this->short_link_helper = $short_link_helper;
|
||||
$this->wistia_embed_permission_repository = $wistia_embed_permission_repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the action to enqueue the needed script(s).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
if ( $this->is_on_installation_page() ) {
|
||||
return;
|
||||
}
|
||||
\add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue the new features assets.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_assets() {
|
||||
$user_id = $this->user_helper->get_current_user_id();
|
||||
$introductions = $this->introductions_collector->get_for( $user_id );
|
||||
if ( ! $introductions ) {
|
||||
// Bail when there are no introductions to show.
|
||||
return;
|
||||
}
|
||||
// Update user meta to have "seen" these introductions.
|
||||
$this->update_user_introductions( $user_id, $introductions );
|
||||
|
||||
$this->admin_asset_manager->enqueue_script( self::SCRIPT_HANDLE );
|
||||
$this->admin_asset_manager->localize_script(
|
||||
self::SCRIPT_HANDLE,
|
||||
'wpseoIntroductions',
|
||||
[
|
||||
'introductions' => $introductions,
|
||||
'isPremium' => $this->product_helper->is_premium(),
|
||||
'isRtl' => \is_rtl(),
|
||||
'linkParams' => $this->short_link_helper->get_query_params(),
|
||||
'pluginUrl' => \plugins_url( '', \WPSEO_FILE ),
|
||||
'wistiaEmbedPermission' => $this->wistia_embed_permission_repository->get_value_for_user( $user_id ),
|
||||
]
|
||||
);
|
||||
$this->admin_asset_manager->enqueue_style( 'introductions' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the user metadata to have "seen" the introductions.
|
||||
*
|
||||
* @param int $user_id The user ID.
|
||||
* @param array $introductions The introductions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function update_user_introductions( $user_id, $introductions ) {
|
||||
$metadata = $this->user_helper->get_meta( $user_id, '_yoast_wpseo_introductions', true );
|
||||
if ( ! \is_array( $metadata ) ) {
|
||||
$metadata = [];
|
||||
}
|
||||
foreach ( $introductions as $introduction ) {
|
||||
$metadata[ $introduction['id'] ] = true;
|
||||
}
|
||||
$this->user_helper->update_meta( $user_id, '_yoast_wpseo_introductions', $metadata );
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\User_Interface;
|
||||
|
||||
use Exception;
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
||||
use Yoast\WP\SEO\Helpers\User_Helper;
|
||||
use Yoast\WP\SEO\Introductions\Application\Introductions_Collector;
|
||||
use Yoast\WP\SEO\Introductions\Infrastructure\Introductions_Seen_Repository;
|
||||
use Yoast\WP\SEO\Main;
|
||||
use Yoast\WP\SEO\Routes\Route_Interface;
|
||||
|
||||
/**
|
||||
* Registers a route to set whether the user has seen an introduction.
|
||||
*
|
||||
* @makePublic
|
||||
*/
|
||||
class Introductions_Seen_Route implements Route_Interface {
|
||||
|
||||
use No_Conditionals;
|
||||
|
||||
/**
|
||||
* Represents the prefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const ROUTE_PREFIX = '/introductions/(?P<introduction_id>[\w-]+)/seen';
|
||||
|
||||
/**
|
||||
* Holds the introductions collector instance.
|
||||
*
|
||||
* @var Introductions_Collector
|
||||
*/
|
||||
private $introductions_collector;
|
||||
|
||||
/**
|
||||
* Holds the repository.
|
||||
*
|
||||
* @var Introductions_Seen_Repository
|
||||
*/
|
||||
private $introductions_seen_repository;
|
||||
|
||||
/**
|
||||
* Holds the user helper.
|
||||
*
|
||||
* @var User_Helper
|
||||
*/
|
||||
private $user_helper;
|
||||
|
||||
/**
|
||||
* Constructs the class.
|
||||
*
|
||||
* @param Introductions_Seen_Repository $introductions_seen_repository The repository.
|
||||
* @param User_Helper $user_helper The user helper.
|
||||
* @param Introductions_Collector $introductions_collector The introduction collector.
|
||||
*/
|
||||
public function __construct(
|
||||
Introductions_Seen_Repository $introductions_seen_repository,
|
||||
User_Helper $user_helper,
|
||||
Introductions_Collector $introductions_collector
|
||||
) {
|
||||
$this->introductions_seen_repository = $introductions_seen_repository;
|
||||
$this->user_helper = $user_helper;
|
||||
$this->introductions_collector = $introductions_collector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
\register_rest_route(
|
||||
Main::API_V1_NAMESPACE,
|
||||
self::ROUTE_PREFIX,
|
||||
[
|
||||
[
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'set_introduction_seen' ],
|
||||
'permission_callback' => [ $this, 'permission_edit_posts' ],
|
||||
'args' => [
|
||||
'introduction_id' => [
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
],
|
||||
'is_seen' => [
|
||||
'required' => false,
|
||||
'type' => 'bool',
|
||||
'default' => true,
|
||||
'sanitize_callback' => 'rest_sanitize_boolean',
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the introduction is seen.
|
||||
*
|
||||
* @param WP_REST_Request $request The request object.
|
||||
*
|
||||
* @return WP_REST_Response|WP_Error The success or failure response.
|
||||
*/
|
||||
public function set_introduction_seen( WP_REST_Request $request ) {
|
||||
$params = $request->get_params();
|
||||
$introduction_id = $params['introduction_id'];
|
||||
$is_seen = $params['is_seen'];
|
||||
|
||||
if ( $this->introductions_collector->is_available_introduction( $introduction_id ) ) {
|
||||
try {
|
||||
$user_id = $this->user_helper->get_current_user_id();
|
||||
$result = $this->introductions_seen_repository->set_introduction( $user_id, $introduction_id, $is_seen );
|
||||
} catch ( Exception $exception ) {
|
||||
return new WP_Error(
|
||||
'wpseo_introductions_seen_error',
|
||||
$exception->getMessage(),
|
||||
(object) []
|
||||
);
|
||||
}
|
||||
|
||||
return new WP_REST_Response(
|
||||
[
|
||||
'json' => (object) [
|
||||
'success' => $result,
|
||||
],
|
||||
],
|
||||
( $result ) ? 200 : 400
|
||||
);
|
||||
}
|
||||
return new WP_REST_Response( [], 400 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission callback.
|
||||
*
|
||||
* @return bool True when user has 'edit_posts' permission.
|
||||
*/
|
||||
public function permission_edit_posts() {
|
||||
return \current_user_can( 'edit_posts' );
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Introductions\User_Interface;
|
||||
|
||||
use Exception;
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
||||
use Yoast\WP\SEO\Helpers\User_Helper;
|
||||
use Yoast\WP\SEO\Introductions\Infrastructure\Wistia_Embed_Permission_Repository;
|
||||
use Yoast\WP\SEO\Main;
|
||||
use Yoast\WP\SEO\Routes\Route_Interface;
|
||||
|
||||
/**
|
||||
* Registers a route to offer get/set of the wistia embed permission for a user.
|
||||
*/
|
||||
class Wistia_Embed_Permission_Route implements Route_Interface {
|
||||
|
||||
use No_Conditionals;
|
||||
|
||||
/**
|
||||
* Represents the prefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const ROUTE_PREFIX = '/wistia_embed_permission';
|
||||
|
||||
/**
|
||||
* Holds the repository.
|
||||
*
|
||||
* @var Wistia_Embed_Permission_Repository
|
||||
*/
|
||||
private $wistia_embed_permission_repository;
|
||||
|
||||
/**
|
||||
* Holds the user helper.
|
||||
*
|
||||
* @var User_Helper
|
||||
*/
|
||||
private $user_helper;
|
||||
|
||||
/**
|
||||
* Constructs the class.
|
||||
*
|
||||
* @param Wistia_Embed_Permission_Repository $wistia_embed_permission_repository The repository.
|
||||
* @param User_Helper $user_helper The user helper.
|
||||
*/
|
||||
public function __construct(
|
||||
Wistia_Embed_Permission_Repository $wistia_embed_permission_repository,
|
||||
User_Helper $user_helper
|
||||
) {
|
||||
$this->wistia_embed_permission_repository = $wistia_embed_permission_repository;
|
||||
$this->user_helper = $user_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers routes with WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes() {
|
||||
\register_rest_route(
|
||||
Main::API_V1_NAMESPACE,
|
||||
self::ROUTE_PREFIX,
|
||||
[
|
||||
[
|
||||
'methods' => 'GET',
|
||||
'callback' => [ $this, 'get_wistia_embed_permission' ],
|
||||
'permission_callback' => [ $this, 'permission_edit_posts' ],
|
||||
],
|
||||
[
|
||||
'methods' => 'POST',
|
||||
'callback' => [ $this, 'set_wistia_embed_permission' ],
|
||||
'permission_callback' => [ $this, 'permission_edit_posts' ],
|
||||
'args' => [
|
||||
'value' => [
|
||||
'required' => false,
|
||||
'type' => 'bool',
|
||||
'default' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the wistia embed permission.
|
||||
*
|
||||
* @return WP_REST_Response|WP_Error The response, or an error.
|
||||
*/
|
||||
public function get_wistia_embed_permission() {
|
||||
try {
|
||||
$user_id = $this->user_helper->get_current_user_id();
|
||||
$value = $this->wistia_embed_permission_repository->get_value_for_user( $user_id );
|
||||
} catch ( Exception $exception ) {
|
||||
return new WP_Error(
|
||||
'wpseo_wistia_embed_permission_error',
|
||||
$exception->getMessage(),
|
||||
(object) []
|
||||
);
|
||||
}
|
||||
|
||||
return new WP_REST_Response(
|
||||
[
|
||||
'json' => (object) [
|
||||
'value' => $value,
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the wistia embed permission.
|
||||
*
|
||||
* @param WP_REST_Request $request The request object.
|
||||
*
|
||||
* @return WP_REST_Response|WP_Error The success or failure response.
|
||||
*/
|
||||
public function set_wistia_embed_permission( WP_REST_Request $request ) {
|
||||
$params = $request->get_json_params();
|
||||
$value = \boolval( $params['value'] );
|
||||
|
||||
try {
|
||||
$user_id = $this->user_helper->get_current_user_id();
|
||||
$result = $this->wistia_embed_permission_repository->set_value_for_user( $user_id, $value );
|
||||
} catch ( Exception $exception ) {
|
||||
return new WP_Error(
|
||||
'wpseo_wistia_embed_permission_error',
|
||||
$exception->getMessage(),
|
||||
(object) []
|
||||
);
|
||||
}
|
||||
|
||||
return new WP_REST_Response(
|
||||
[
|
||||
'json' => (object) [
|
||||
'success' => $result,
|
||||
],
|
||||
],
|
||||
( $result ) ? 200 : 400
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission callback.
|
||||
*
|
||||
* @return bool True when user has 'edit_posts' permission.
|
||||
*/
|
||||
public function permission_edit_posts() {
|
||||
return \current_user_can( 'edit_posts' );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user