rebase code on oct-10-2023
This commit is contained in:
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Internal\Admin\BlockTemplateRegistry;
|
||||
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
|
||||
|
||||
/**
|
||||
* Block template registry.
|
||||
*/
|
||||
final class BlockTemplateRegistry {
|
||||
|
||||
/**
|
||||
* Class instance.
|
||||
*
|
||||
* @var BlockTemplateRegistry|null
|
||||
*/
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* Templates.
|
||||
*/
|
||||
protected $templates = array();
|
||||
|
||||
/**
|
||||
* Get the instance of the class.
|
||||
*/
|
||||
public static function get_instance(): BlockTemplateRegistry {
|
||||
if ( null === self::$instance ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a single template.
|
||||
*
|
||||
* @param string $id Template ID.
|
||||
* @param array $template Template layout.
|
||||
*/
|
||||
public function register( BlockTemplateInterface $template ) {
|
||||
$id = $template->get_id();
|
||||
|
||||
if ( isset( $this->templates[ $id ] ) ) {
|
||||
throw new \ValueError( 'A template with the specified ID already exists in the registry.' );
|
||||
}
|
||||
|
||||
$this->templates[ $id ] = $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the registered templates.
|
||||
*/
|
||||
public function get_all_registered(): array {
|
||||
return $this->templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single registered template.
|
||||
*
|
||||
* @param string $id ID of the template
|
||||
*/
|
||||
public function get_registered( $id ): BlockTemplateInterface {
|
||||
return isset( $this->templates[ $id ] ) ? $this->templates[ $id ] : null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Internal\Admin\BlockTemplateRegistry;
|
||||
|
||||
/**
|
||||
* Block template controller.
|
||||
*/
|
||||
class BlockTemplatesController {
|
||||
|
||||
/**
|
||||
* Block template registry
|
||||
*
|
||||
* @var BlockTemplateRegistry
|
||||
*/
|
||||
private $block_template_registry;
|
||||
|
||||
/**
|
||||
* Block template transformer.
|
||||
*
|
||||
* @var TemplateTransformer
|
||||
*/
|
||||
private $template_transformer;
|
||||
|
||||
/**
|
||||
* Init.
|
||||
*/
|
||||
public function init( $block_template_registry, $template_transformer ) {
|
||||
$this->block_template_registry = $block_template_registry;
|
||||
$this->template_transformer = $template_transformer;
|
||||
add_action( 'rest_api_init', array( $this, 'register_templates' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register templates in the blocks endpoint.
|
||||
*/
|
||||
public function register_templates() {
|
||||
$templates = $this->block_template_registry->get_all_registered();
|
||||
|
||||
foreach ( $templates as $template ) {
|
||||
add_filter( 'pre_get_block_templates', function( $query_result, $query, $template_type ) use( $template ) {
|
||||
if ( ! isset( $query['area'] ) || $query['area'] !== $template->get_area() ) {
|
||||
return $query_result;
|
||||
}
|
||||
|
||||
$wp_block_template = $this->template_transformer->transform( $template );
|
||||
$query_result[] = $wp_block_template;
|
||||
|
||||
return $query_result;
|
||||
}, 10, 3 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Internal\Admin\BlockTemplateRegistry;
|
||||
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
|
||||
|
||||
/**
|
||||
* Template transformer.
|
||||
*/
|
||||
class TemplateTransformer {
|
||||
|
||||
/**
|
||||
* Transform the WooCommerceBlockTemplate to a WP_Block_Template.
|
||||
*
|
||||
* @param object $block_template The product template.
|
||||
*/
|
||||
public function transform( BlockTemplateInterface $block_template ): \WP_Block_Template {
|
||||
$template = new \WP_Block_Template();
|
||||
$template->id = $block_template->get_id();
|
||||
$template->theme = 'woocommerce/woocommerce';
|
||||
$template->content = $block_template->get_formatted_template();
|
||||
$template->source = 'plugin';
|
||||
$template->slug = $block_template->get_id();
|
||||
$template->type = 'wp_template';
|
||||
$template->title = $block_template->get_title();
|
||||
$template->description = $block_template->get_description();
|
||||
$template->status = 'publish';
|
||||
$template->has_theme_file = true;
|
||||
$template->origin = 'plugin';
|
||||
$template->is_custom = false; // Templates loaded from the filesystem aren't custom, ones that have been edited and loaded from the DB are.
|
||||
$template->post_types = array(); // Don't appear in any Edit Post template selector dropdown.
|
||||
$template->area = $block_template->get_area();
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Internal\Admin\BlockTemplates;
|
||||
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Block configuration used to specify blocks in BlockTemplate.
|
||||
*/
|
||||
class AbstractBlock implements BlockInterface {
|
||||
/**
|
||||
* The block name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* The block ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* The block order.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $order = 10;
|
||||
|
||||
/**
|
||||
* The block attributes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $attributes = [];
|
||||
|
||||
/**
|
||||
* The block template that this block belongs to.
|
||||
*
|
||||
* @var BlockTemplate
|
||||
*/
|
||||
private $root_template;
|
||||
|
||||
/**
|
||||
* The parent container.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $parent;
|
||||
|
||||
/**
|
||||
* Block constructor.
|
||||
*
|
||||
* @param array $config The block configuration.
|
||||
* @param BlockTemplateInterface $root_template The block template that this block belongs to.
|
||||
* @param BlockContainerInterface|null $parent The parent block container.
|
||||
*
|
||||
* @throws \ValueError If the block configuration is invalid.
|
||||
* @throws \ValueError If the parent block container does not belong to the same template as the block.
|
||||
*/
|
||||
public function __construct( array $config, BlockTemplateInterface &$root_template, ContainerInterface &$parent = null ) {
|
||||
$this->validate( $config, $root_template, $parent );
|
||||
|
||||
$this->root_template = $root_template;
|
||||
$this->parent = is_null( $parent ) ? $root_template : $parent;
|
||||
|
||||
$this->name = $config[ self::NAME_KEY ];
|
||||
|
||||
if ( ! isset( $config[ self::ID_KEY ] ) ) {
|
||||
$this->id = $this->root_template->generate_block_id( $this->get_name() );
|
||||
} else {
|
||||
$this->id = $config[ self::ID_KEY ];
|
||||
}
|
||||
|
||||
if ( isset( $config[ self::ORDER_KEY ] ) ) {
|
||||
$this->order = $config[ self::ORDER_KEY ];
|
||||
}
|
||||
|
||||
if ( isset( $config[ self::ATTRIBUTES_KEY ] ) ) {
|
||||
$this->attributes = $config[ self::ATTRIBUTES_KEY ];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate block configuration.
|
||||
*
|
||||
* @param array $config The block configuration.
|
||||
* @param BlockTemplateInterface $root_template The block template that this block belongs to.
|
||||
* @param ContainerInterface|null $parent The parent block container.
|
||||
*
|
||||
* @throws \ValueError If the block configuration is invalid.
|
||||
* @throws \ValueError If the parent block container does not belong to the same template as the block.
|
||||
*/
|
||||
protected function validate( array $config, BlockTemplateInterface &$root_template, ContainerInterface &$parent = null ) {
|
||||
if ( isset( $parent ) && ( $parent->get_root_template() !== $root_template ) ) {
|
||||
throw new \ValueError( 'The parent block must belong to the same template as the block.' );
|
||||
}
|
||||
|
||||
if ( ! isset( $config[ self::NAME_KEY ] ) || ! is_string( $config[ self::NAME_KEY ] ) ) {
|
||||
throw new \ValueError( 'The block name must be specified.' );
|
||||
}
|
||||
|
||||
if ( isset( $config[ self::ORDER_KEY ] ) && ! is_int( $config[ self::ORDER_KEY ] ) ) {
|
||||
throw new \ValueError( 'The block order must be an integer.' );
|
||||
}
|
||||
|
||||
if ( isset( $config[ self::ATTRIBUTES_KEY ] ) && ! is_array( $config[ self::ATTRIBUTES_KEY ] ) ) {
|
||||
throw new \ValueError( 'The block attributes must be an array.' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block name.
|
||||
*/
|
||||
public function get_name(): string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block ID.
|
||||
*/
|
||||
public function get_id(): string {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block order.
|
||||
*/
|
||||
public function get_order(): int {
|
||||
return $this->order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block order.
|
||||
*
|
||||
* @param int $order The block order.
|
||||
*/
|
||||
public function set_order( int $order ) {
|
||||
$this->order = $order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block attributes.
|
||||
*/
|
||||
public function get_attributes(): array {
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block attributes.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
*/
|
||||
public function set_attributes( array $attributes ) {
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the template that this block belongs to.
|
||||
*/
|
||||
public function &get_root_template(): BlockTemplateInterface {
|
||||
return $this->root_template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent block container.
|
||||
*/
|
||||
public function &get_parent(): ContainerInterface {
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block configuration as a formatted template.
|
||||
*
|
||||
* @return array The block configuration as a formatted template.
|
||||
*/
|
||||
public function get_formatted_template(): array {
|
||||
$arr = [
|
||||
$this->get_name(),
|
||||
$this->get_attributes(),
|
||||
];
|
||||
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Internal\Admin\BlockTemplates;
|
||||
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\ContainerInterface;
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
|
||||
|
||||
/**
|
||||
* Block template class.
|
||||
*/
|
||||
abstract class AbstractBlockTemplate implements BlockTemplateInterface {
|
||||
use BlockContainerTrait;
|
||||
|
||||
/**
|
||||
* Get the template ID.
|
||||
*/
|
||||
public abstract function get_id(): string;
|
||||
|
||||
/**
|
||||
* Get the template title.
|
||||
*/
|
||||
public function get_title(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the template description.
|
||||
*/
|
||||
public function get_description(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the template area.
|
||||
*/
|
||||
public function get_area(): string {
|
||||
return 'uncategorized';
|
||||
}
|
||||
|
||||
/**
|
||||
* The block cache.
|
||||
*
|
||||
* @var BlockInterface[]
|
||||
*/
|
||||
private $block_cache = [];
|
||||
|
||||
/**
|
||||
* Get a block by ID.
|
||||
*
|
||||
* @param string $block_id The block ID.
|
||||
*/
|
||||
public function get_block( string $block_id ): ?BlockInterface {
|
||||
return $this->block_cache[ $block_id ] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches a block in the template. This is an internal method and should not be called directly
|
||||
* except for classes that implement BlockContainerInterface, in their add_block() method.
|
||||
*
|
||||
* @param BlockInterface $block The block to cache.
|
||||
*
|
||||
* @throws \ValueError If a block with the specified ID already exists in the template.
|
||||
* @throws \ValueError If the block template that the block belongs to is not this template.
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
public function cache_block( BlockInterface &$block ) {
|
||||
$id = $block->get_id();
|
||||
|
||||
if ( isset( $this->block_cache[ $id ] ) ) {
|
||||
throw new \ValueError( 'A block with the specified ID already exists in the template.' );
|
||||
}
|
||||
|
||||
if ( $block->get_root_template() !== $this ) {
|
||||
throw new \ValueError( 'The block template that the block belongs to must be the same as this template.' );
|
||||
}
|
||||
|
||||
$this->block_cache[ $id ] = $block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a block ID based on a base.
|
||||
*
|
||||
* @param string $id_base The base to use when generating an ID.
|
||||
* @return string
|
||||
*/
|
||||
public function generate_block_id( string $id_base ): string {
|
||||
$instance_count = 0;
|
||||
|
||||
do {
|
||||
$instance_count++;
|
||||
$block_id = $id_base . '-' . $instance_count;
|
||||
} while ( isset( $this->block_cache[ $block_id ] ) );
|
||||
|
||||
return $block_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root template.
|
||||
*/
|
||||
public function &get_root_template(): BlockTemplateInterface {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inner blocks as a formatted template.
|
||||
*/
|
||||
public function get_formatted_template(): array {
|
||||
$inner_blocks = $this->get_inner_blocks_sorted_by_order();
|
||||
|
||||
$inner_blocks_formatted_template = array_map(
|
||||
function( Block $block ) {
|
||||
return $block->get_formatted_template();
|
||||
},
|
||||
$inner_blocks
|
||||
);
|
||||
|
||||
return $inner_blocks_formatted_template;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Internal\Admin\BlockTemplates;
|
||||
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockContainerInterface;
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
|
||||
|
||||
/**
|
||||
* Generic block with container properties to be used in BlockTemplate.
|
||||
*/
|
||||
class Block extends AbstractBlock implements BlockContainerInterface {
|
||||
use BlockContainerTrait;
|
||||
|
||||
/**
|
||||
* Get the block configuration as a formatted template.
|
||||
*
|
||||
* @return array The block configuration as a formatted template.
|
||||
*/
|
||||
public function get_formatted_template(): array {
|
||||
$arr = [
|
||||
$this->get_name(),
|
||||
$this->get_attributes(),
|
||||
];
|
||||
|
||||
$inner_blocks = $this->get_inner_blocks_sorted_by_order();
|
||||
|
||||
if ( ! empty( $inner_blocks ) ) {
|
||||
$arr[] = array_map(
|
||||
function( BlockInterface $block ) {
|
||||
return $block->get_formatted_template();
|
||||
},
|
||||
$inner_blocks
|
||||
);
|
||||
}
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an inner block to this block.
|
||||
*
|
||||
* @param array $block_config The block data.
|
||||
*/
|
||||
public function &add_block( array $block_config ): BlockInterface {
|
||||
$block = new Block( $block_config, $this->get_root_template(), $this );
|
||||
return $this->add_inner_block( $block );
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Internal\Admin\BlockTemplates;
|
||||
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
|
||||
|
||||
/**
|
||||
* Trait for block containers.
|
||||
*/
|
||||
trait BlockContainerTrait {
|
||||
/**
|
||||
* The inner blocks.
|
||||
*
|
||||
* @var BlockInterface[]
|
||||
*/
|
||||
private $inner_blocks = [];
|
||||
|
||||
// phpcs doesn't take into account exceptions thrown by called methods.
|
||||
// phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
|
||||
|
||||
/**
|
||||
* Add a block to the block container.
|
||||
*
|
||||
* @param BlockInterface $block The block.
|
||||
*
|
||||
* @throws \ValueError If the block configuration is invalid.
|
||||
* @throws \ValueError If a block with the specified ID already exists in the template.
|
||||
* @throws \UnexpectedValueException If the block container is not the parent of the block.
|
||||
*/
|
||||
protected function &add_inner_block( BlockInterface $block ): BlockInterface {
|
||||
if ( ! $block instanceof BlockInterface ) {
|
||||
throw new \UnexpectedValueException( 'The block must return an instance of BlockInterface.' );
|
||||
}
|
||||
|
||||
if ( $block->get_parent() !== $this ) {
|
||||
throw new \UnexpectedValueException( 'The block container is not the parent of the block.' );
|
||||
}
|
||||
|
||||
$root_template = $block->get_root_template();
|
||||
$root_template->cache_block( $block );
|
||||
$this->inner_blocks[] = &$block;
|
||||
return $block;
|
||||
}
|
||||
|
||||
// phpcs:enable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
|
||||
|
||||
/**
|
||||
* Get the inner blocks sorted by order.
|
||||
*/
|
||||
private function get_inner_blocks_sorted_by_order(): array {
|
||||
$sorted_inner_blocks = $this->inner_blocks;
|
||||
|
||||
usort(
|
||||
$sorted_inner_blocks,
|
||||
function( Block $a, Block $b ) {
|
||||
return $a->get_order() <=> $b->get_order();
|
||||
}
|
||||
);
|
||||
|
||||
return $sorted_inner_blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inner blocks as a formatted template.
|
||||
*/
|
||||
public function get_formatted_template(): array {
|
||||
$arr = [
|
||||
$this->get_name(),
|
||||
$this->get_attributes(),
|
||||
];
|
||||
|
||||
$inner_blocks = $this->get_inner_blocks_sorted_by_order();
|
||||
|
||||
if ( ! empty( $inner_blocks ) ) {
|
||||
$arr[] = array_map(
|
||||
function( BlockInterface $block ) {
|
||||
return $block->get_formatted_template();
|
||||
},
|
||||
$inner_blocks
|
||||
);
|
||||
}
|
||||
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Internal\Admin\BlockTemplates;
|
||||
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\ContainerInterface;
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
|
||||
|
||||
/**
|
||||
* Block template class.
|
||||
*/
|
||||
class BlockTemplate extends AbstractBlockTemplate {
|
||||
/**
|
||||
* Get the template ID.
|
||||
*/
|
||||
public function get_id(): string {
|
||||
return 'woocommerce-block-template';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a block ID based on a base.
|
||||
*
|
||||
* @param array $block_config The block data.
|
||||
*/
|
||||
public function add_block( array $block_config ): BlockInterface {
|
||||
$block = new Block( $block_config, $this->get_root_template(), $this );
|
||||
return $this->add_inner_block( $block );
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ namespace Automattic\WooCommerce\Internal\Admin;
|
||||
use Automattic\WooCommerce\Admin\Features\Features;
|
||||
use Automattic\WooCommerce\Admin\PageController;
|
||||
use Automattic\WooCommerce\Admin\PluginsHelper;
|
||||
use Automattic\WooCommerce\Internal\Admin\BlockTemplateRegistry\BlockTemplatesController;
|
||||
use Automattic\WooCommerce\Internal\Admin\ProductReviews\Reviews;
|
||||
use Automattic\WooCommerce\Internal\Admin\ProductReviews\ReviewsCommentsOverrides;
|
||||
use Automattic\WooCommerce\Internal\Admin\Settings;
|
||||
@@ -73,7 +72,6 @@ class Loader {
|
||||
|
||||
wc_get_container()->get( Reviews::class );
|
||||
wc_get_container()->get( ReviewsCommentsOverrides::class );
|
||||
wc_get_container()->get( BlockTemplatesController::class );
|
||||
|
||||
add_filter( 'admin_body_class', array( __CLASS__, 'add_admin_body_classes' ) );
|
||||
add_filter( 'admin_title', array( __CLASS__, 'update_admin_title' ) );
|
||||
|
||||
@@ -136,41 +136,34 @@ class MarketingSpecs {
|
||||
/**
|
||||
* Load knowledge base posts from WooCommerce.com
|
||||
*
|
||||
* @param string|null $term Term of posts to retrieve.
|
||||
* @param string|null $category Category of posts to retrieve.
|
||||
* @return array
|
||||
*/
|
||||
public function get_knowledge_base_posts( ?string $term ): array {
|
||||
$terms = array(
|
||||
'marketing' => array(
|
||||
'taxonomy' => 'category',
|
||||
'term_id' => 1744,
|
||||
'argument' => 'categories',
|
||||
),
|
||||
'coupons' => array(
|
||||
'taxonomy' => 'post_tag',
|
||||
'term_id' => 1377,
|
||||
'argument' => 'tags',
|
||||
),
|
||||
public function get_knowledge_base_posts( ?string $category ): array {
|
||||
$kb_transient = self::KNOWLEDGE_BASE_TRANSIENT;
|
||||
|
||||
$categories = array(
|
||||
'marketing' => 1744,
|
||||
'coupons' => 25202,
|
||||
);
|
||||
|
||||
// Default to the marketing category (if no term is set on the kb component).
|
||||
if ( empty( $term ) || ! array_key_exists( $term, $terms ) ) {
|
||||
$term = 'marketing';
|
||||
// Default to marketing category (if no category set on the kb component).
|
||||
if ( ! empty( $category ) && array_key_exists( $category, $categories ) ) {
|
||||
$category_id = $categories[ $category ];
|
||||
$kb_transient = $kb_transient . '_' . strtolower( $category );
|
||||
} else {
|
||||
$category_id = $categories['marketing'];
|
||||
}
|
||||
|
||||
$term_id = $terms[ $term ]['term_id'];
|
||||
$argument = $terms[ $term ]['argument'];
|
||||
$kb_transient = self::KNOWLEDGE_BASE_TRANSIENT . '_' . strtolower( $term );
|
||||
|
||||
$posts = get_transient( $kb_transient );
|
||||
|
||||
if ( false === $posts ) {
|
||||
$request_url = add_query_arg(
|
||||
array(
|
||||
$argument => $term_id,
|
||||
'page' => 1,
|
||||
'per_page' => 8,
|
||||
'_embed' => 1,
|
||||
'categories' => $category_id,
|
||||
'page' => 1,
|
||||
'per_page' => 8,
|
||||
'_embed' => 1,
|
||||
),
|
||||
'https://woocommerce.com/wp-json/wp/v2/posts?utm_medium=product'
|
||||
);
|
||||
|
||||
@@ -58,10 +58,10 @@ class COTRedirectionController {
|
||||
$params['_wpnonce'] = wp_create_nonce( 'bulk-posts' );
|
||||
}
|
||||
|
||||
// If an `id` array parameter is present, rename as `post`.
|
||||
if ( isset( $params['id'] ) && is_array( $params['id'] ) ) {
|
||||
$params['post'] = $params['id'];
|
||||
unset( $params['id'] );
|
||||
// If an `order` array parameter is present, rename as `post`.
|
||||
if ( isset( $params['order'] ) && is_array( $params['order'] ) ) {
|
||||
$params['post'] = $params['order'];
|
||||
unset( $params['order'] );
|
||||
}
|
||||
|
||||
$params['post_type'] = 'shop_order';
|
||||
|
||||
@@ -388,7 +388,6 @@ class Edit {
|
||||
<input type="hidden" id="hiddenaction" name="action" value="<?php echo esc_attr( $form_action ); ?>"/>
|
||||
<input type="hidden" id="original_order_status" name="original_order_status" value="<?php echo esc_attr( $this->order->get_status() ); ?>"/>
|
||||
<input type="hidden" id="referredby" name="referredby" value="<?php echo $referer ? esc_url( $referer ) : ''; ?>"/>
|
||||
<input type="hidden" id="post_ID" name="post_ID" value="<?php echo esc_attr( $this->order->get_id() ); ?>"/>
|
||||
<div id="poststuff">
|
||||
<div id="post-body"
|
||||
class="metabox-holder columns-<?php echo ( 1 === get_current_screen()->get_columns() ) ? '1' : '2'; ?>">
|
||||
|
||||
@@ -100,7 +100,7 @@ class EditLock {
|
||||
}
|
||||
|
||||
$order = wc_get_order( $order_id );
|
||||
if ( ! $order || ( ! current_user_can( get_post_type_object( $order->get_type() )->cap->edit_post, $order->get_id() ) && ! current_user_can( 'manage_woocommerce' ) ) ) {
|
||||
if ( ! current_user_can( get_post_type_object( $order->get_type() )->cap->edit_post, $order->get_id() ) && ! current_user_can( 'manage_woocommerce' ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
@@ -867,7 +867,7 @@ class ListTable extends WP_List_Table {
|
||||
public function column_cb( $item ) {
|
||||
ob_start();
|
||||
?>
|
||||
<input id="cb-select-<?php echo esc_attr( $item->get_id() ); ?>" type="checkbox" name="id[]" value="<?php echo esc_attr( $item->get_id() ); ?>" />
|
||||
<input id="cb-select-<?php echo esc_attr( $item->get_id() ); ?>" type="checkbox" name="<?php echo esc_attr( $this->_args['singular'] ); ?>[]" value="<?php echo esc_attr( $item->get_id() ); ?>" />
|
||||
|
||||
<div class="locked-indicator">
|
||||
<span class="locked-indicator-icon" aria-hidden="true"></span>
|
||||
@@ -1197,7 +1197,7 @@ class ListTable extends WP_List_Table {
|
||||
|
||||
$action = 'delete';
|
||||
} else {
|
||||
$ids = isset( $_REQUEST['id'] ) ? array_reverse( array_map( 'absint', (array) $_REQUEST['id'] ) ) : array();
|
||||
$ids = isset( $_REQUEST['order'] ) ? array_reverse( array_map( 'absint', (array) $_REQUEST['order'] ) ) : array();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1340,11 +1340,13 @@ class ListTable extends WP_List_Table {
|
||||
* @return int Number of orders that were trashed.
|
||||
*/
|
||||
private function do_delete( array $ids, bool $force_delete = false ): int {
|
||||
$orders_store = wc_get_container()->get( OrdersTableDataStore::class );
|
||||
$delete_args = $force_delete ? array( 'force_delete' => true ) : array();
|
||||
$changed = 0;
|
||||
|
||||
foreach ( $ids as $id ) {
|
||||
$order = wc_get_order( $id );
|
||||
$order->delete( $force_delete );
|
||||
$orders_store->delete( $order, $delete_args );
|
||||
$updated_order = wc_get_order( $id );
|
||||
|
||||
if ( ( $force_delete && false === $updated_order ) || ( ! $force_delete && $updated_order->get_status() === 'trash' ) ) {
|
||||
|
||||
@@ -290,6 +290,11 @@ class PageController {
|
||||
switch ( $this->current_action ) {
|
||||
case 'edit_order':
|
||||
case 'new_order':
|
||||
if ( ! isset( $this->order_edit_form ) ) {
|
||||
$this->order_edit_form = new Edit();
|
||||
$this->order_edit_form->setup( $this->order );
|
||||
}
|
||||
$this->order_edit_form->set_current_action( $this->current_action );
|
||||
$this->order_edit_form->display();
|
||||
break;
|
||||
case 'list_orders':
|
||||
@@ -335,22 +340,6 @@ class PageController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the order edit form for creating or editing an order.
|
||||
*
|
||||
* @see \Automattic\WooCommerce\Internal\Admin\Orders\Edit.
|
||||
* @since 8.1.0
|
||||
*/
|
||||
private function prepare_order_edit_form(): void {
|
||||
if ( ! $this->order || ! in_array( $this->current_action, array( 'new_order', 'edit_order' ), true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->order_edit_form = $this->order_edit_form ?? new Edit();
|
||||
$this->order_edit_form->setup( $this->order );
|
||||
$this->order_edit_form->set_current_action( $this->current_action );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles initialization of the orders edit form.
|
||||
*
|
||||
@@ -362,8 +351,6 @@ class PageController {
|
||||
$this->verify_edit_permission();
|
||||
$this->handle_edit_lock();
|
||||
$theorder = $this->order;
|
||||
|
||||
$this->prepare_order_edit_form();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -393,8 +380,6 @@ class PageController {
|
||||
}
|
||||
|
||||
$theorder = $this->order;
|
||||
|
||||
$this->prepare_order_edit_form();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -84,7 +84,7 @@ class PostsRedirectionController {
|
||||
$new_url = add_query_arg(
|
||||
array(
|
||||
'action' => $action,
|
||||
'id' => $posts,
|
||||
'order' => $posts,
|
||||
'_wp_http_referer' => $this->page_controller->get_orders_url(),
|
||||
'_wpnonce' => wp_create_nonce( 'bulk-orders' ),
|
||||
),
|
||||
|
||||
@@ -400,16 +400,6 @@ class DefaultFreeExtensions {
|
||||
'value' => 'SE',
|
||||
'operation' => '=',
|
||||
),
|
||||
array(
|
||||
'type' => 'base_location_country',
|
||||
'value' => 'JP',
|
||||
'operation' => '=',
|
||||
),
|
||||
array(
|
||||
'type' => 'base_location_country',
|
||||
'value' => 'AE',
|
||||
'operation' => '=',
|
||||
),
|
||||
),
|
||||
),
|
||||
DefaultPaymentGateways::get_rules_for_cbd( false ),
|
||||
@@ -885,9 +875,9 @@ class DefaultFreeExtensions {
|
||||
'install_priority' => 3,
|
||||
),
|
||||
'jetpack' => array(
|
||||
'label' => __( 'Boost content creation with Jetpack AI Assistant', 'woocommerce' ),
|
||||
'label' => __( 'Enhance security with Jetpack', 'woocommerce' ),
|
||||
'image_url' => plugins_url( '/assets/images/core-profiler/logo-jetpack.svg', WC_PLUGIN_FILE ),
|
||||
'description' => __( 'Save time on content creation — unlock high-quality blog posts and pages using AI.', 'woocommerce' ),
|
||||
'description' => __( 'Get auto real-time backups, malware scans, and spam protection.', 'woocommerce' ),
|
||||
'learn_more_link' => 'https://woocommerce.com/products/jetpack',
|
||||
'install_priority' => 8,
|
||||
),
|
||||
|
||||
@@ -9,7 +9,6 @@ use Automattic\WooCommerce\Admin\API\Plugins;
|
||||
use Automattic\WooCommerce\Admin\PageController;
|
||||
use Automattic\WooCommerce\Admin\API\Reports\Orders\DataStore as OrdersDataStore;
|
||||
use Automattic\WooCommerce\Admin\PluginsHelper;
|
||||
use Automattic\WooCommerce\Internal\Admin\WCPayPromotion\Init as WCPayPromotionInit;
|
||||
use Automattic\WooCommerce\Utilities\FeaturesUtil;
|
||||
use WC_Marketplace_Suggestions;
|
||||
|
||||
@@ -237,8 +236,6 @@ class Settings {
|
||||
|
||||
$settings['features'] = $this->get_features();
|
||||
|
||||
$settings['isWooPayEligible'] = WCPayPromotionInit::is_woopay_eligible();
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
|
||||
@@ -141,15 +141,6 @@ class Init {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get merchant WooPay eligibility.
|
||||
*/
|
||||
public static function is_woopay_eligible() {
|
||||
$wcpay_promotion = self::get_wc_pay_promotion_spec();
|
||||
|
||||
return $wcpay_promotion && 'woocommerce_payments:woopay' === $wcpay_promotion->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the specs transient.
|
||||
*/
|
||||
|
||||
@@ -12,8 +12,7 @@ use Automattic\WooCommerce\Admin\PageController;
|
||||
* @package Automattic\WooCommerce\Admin\Features
|
||||
*/
|
||||
class WcPayWelcomePage {
|
||||
const CACHE_TRANSIENT_NAME = 'wcpay_welcome_page_incentive';
|
||||
const HAD_WCPAY_OPTION_NAME = 'wcpay_was_in_use';
|
||||
const TRANSIENT_NAME = 'wcpay_welcome_page_incentive';
|
||||
|
||||
/**
|
||||
* Plugin instance.
|
||||
@@ -53,11 +52,6 @@ class WcPayWelcomePage {
|
||||
* @return boolean
|
||||
*/
|
||||
public function must_be_visible(): bool {
|
||||
// The WooPayments plugin must not be active.
|
||||
if ( $this->is_wcpay_active() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Suggestions not disabled via a setting.
|
||||
if ( get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) === 'no' ) {
|
||||
return false;
|
||||
@@ -74,7 +68,12 @@ class WcPayWelcomePage {
|
||||
return false;
|
||||
}
|
||||
|
||||
// An incentive must be available.
|
||||
// The WooPayments plugin must not be active.
|
||||
if ( $this->is_wcpay_active() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Incentive is available.
|
||||
if ( empty( $this->get_incentive() ) ) {
|
||||
return false;
|
||||
}
|
||||
@@ -134,17 +133,11 @@ class WcPayWelcomePage {
|
||||
}
|
||||
|
||||
// Add badge.
|
||||
$badge = ' <span class="wcpay-menu-badge awaiting-mod count-1"><span class="plugin-count">1</span></span>';
|
||||
foreach ( $menu as $index => $menu_item ) {
|
||||
// Only add the badge markup if not already present and the menu item is the WooPayments menu item.
|
||||
if ( false === strpos( $menu_item[0], $badge )
|
||||
&& ( 'wc-admin&path=/wc-pay-welcome-page' === $menu_item[2]
|
||||
|| 'admin.php?page=wc-admin&path=/wc-pay-welcome-page' === $menu_item[2] )
|
||||
) {
|
||||
$menu[ $index ][0] .= $badge; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
|
||||
// One menu item with a badge is more than enough.
|
||||
break;
|
||||
if ( 'wc-admin&path=/wc-pay-welcome-page' === $menu_item[2]
|
||||
|| 'admin.php?page=wc-admin&path=/wc-pay-welcome-page' === $menu_item[2] ) {
|
||||
//phpcs:ignore
|
||||
$menu[ $index ][0] .= ' <span class="wcpay-menu-badge awaiting-mod count-1"><span class="plugin-count">1</span></span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,8 +154,8 @@ class WcPayWelcomePage {
|
||||
return $settings;
|
||||
}
|
||||
|
||||
// Return early if the incentive must not be visible.
|
||||
if ( ! $this->must_be_visible() ) {
|
||||
// Return early if there is no eligible incentive.
|
||||
if ( empty( $this->get_incentive() ) ) {
|
||||
return $settings;
|
||||
}
|
||||
|
||||
@@ -178,8 +171,8 @@ class WcPayWelcomePage {
|
||||
* @return array
|
||||
*/
|
||||
public function allowed_promo_notes( $promo_notes = [] ): array {
|
||||
// Return early if the incentive must not be visible.
|
||||
if ( ! $this->must_be_visible() ) {
|
||||
// Return early if there is no eligible incentive.
|
||||
if ( empty( $this->get_incentive() ) ) {
|
||||
return $promo_notes;
|
||||
}
|
||||
|
||||
@@ -190,34 +183,20 @@ class WcPayWelcomePage {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the WooPayments payment gateway is active and set up or was at some point,
|
||||
* Check if the WooPayments payment gateway is active and set up,
|
||||
* or there are orders processed with it, at some moment.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function has_wcpay(): bool {
|
||||
// First, get the stored value, if it exists.
|
||||
// This way we avoid costly DB queries and API calls.
|
||||
// Basically, we only want to know if WooPayments was in use in the past.
|
||||
// Since the past can't be changed, neither can this value.
|
||||
$had_wcpay = get_option( self::HAD_WCPAY_OPTION_NAME );
|
||||
if ( false !== $had_wcpay ) {
|
||||
return $had_wcpay === 'yes';
|
||||
}
|
||||
|
||||
// We need to determine the value.
|
||||
// Start with the assumption that the store didn't have WooPayments in use.
|
||||
$had_wcpay = false;
|
||||
|
||||
// We consider the store to have WooPayments if there is meaningful account data in the WooPayments account cache.
|
||||
// This implies that WooPayments was active at some point and that it was connected.
|
||||
// If WooPayments is active right now, we will not get to this point since the plugin is active check is done first.
|
||||
// This implies that WooPayments is or was active at some point and that it was connected.
|
||||
if ( $this->has_wcpay_account_data() ) {
|
||||
$had_wcpay = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If there is at least one order processed with WooPayments, we consider the store to have WooPayments.
|
||||
if ( false === $had_wcpay && ! empty(
|
||||
if ( ! empty(
|
||||
wc_get_orders(
|
||||
[
|
||||
'payment_method' => 'woocommerce_payments',
|
||||
@@ -226,13 +205,10 @@ class WcPayWelcomePage {
|
||||
]
|
||||
)
|
||||
) ) {
|
||||
$had_wcpay = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Store the value for future use.
|
||||
update_option( self::HAD_WCPAY_OPTION_NAME, $had_wcpay ? 'yes' : 'no' );
|
||||
|
||||
return $had_wcpay;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,21 +240,14 @@ class WcPayWelcomePage {
|
||||
* @return boolean
|
||||
*/
|
||||
private function is_incentive_dismissed(): bool {
|
||||
$dismissed_incentives = get_option( 'wcpay_welcome_page_incentives_dismissed', [] );
|
||||
|
||||
// If there are no dismissed incentives, return early.
|
||||
if ( empty( $dismissed_incentives ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return early if there is no eligible incentive.
|
||||
$incentive = $this->get_incentive();
|
||||
if ( empty( $incentive ) ) {
|
||||
if ( empty( $this->get_incentive() ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Search the incentive ID in the dismissed incentives list.
|
||||
if ( in_array( $incentive['id'], $dismissed_incentives, true ) ) {
|
||||
$dismissed_incentives = get_option( 'wcpay_welcome_page_incentives_dismissed', [] );
|
||||
|
||||
if ( in_array( $this->get_incentive()['id'], $dismissed_incentives, true ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -296,19 +265,6 @@ class WcPayWelcomePage {
|
||||
return $this->incentive;
|
||||
}
|
||||
|
||||
// Get the cached data.
|
||||
$cache = get_transient( self::CACHE_TRANSIENT_NAME );
|
||||
|
||||
// If the cached data is not expired and it's a WP_Error,
|
||||
// it means there was an API error previously and we should not retry just yet.
|
||||
if ( is_wp_error( $cache ) ) {
|
||||
// Initialize the in-memory cache and return it.
|
||||
$this->incentive = [];
|
||||
|
||||
return $this->incentive;
|
||||
}
|
||||
|
||||
// Gather the store context data.
|
||||
$store_context = [
|
||||
// Store ISO-2 country code, e.g. `US`.
|
||||
'country' => WC()->countries->get_base_country(),
|
||||
@@ -337,16 +293,25 @@ class WcPayWelcomePage {
|
||||
|
||||
// Use the transient cached incentive if it exists, it is not expired,
|
||||
// and the store context hasn't changed since we last requested from the WooPayments API (based on context hash).
|
||||
if ( false !== $cache
|
||||
&& ! empty( $cache['context_hash'] ) && is_string( $cache['context_hash'] )
|
||||
&& hash_equals( $store_context_hash, $cache['context_hash'] ) ) {
|
||||
$transient_cache = get_transient( self::TRANSIENT_NAME );
|
||||
if ( false !== $transient_cache ) {
|
||||
if ( is_null( $transient_cache ) ) {
|
||||
// This means there was an error and we shouldn't retry just yet.
|
||||
// Initialize the in-memory cache.
|
||||
$this->incentive = [];
|
||||
} elseif ( ! empty( $transient_cache['context_hash'] ) && is_string( $transient_cache['context_hash'] )
|
||||
&& hash_equals( $store_context_hash, $transient_cache['context_hash'] ) ) {
|
||||
|
||||
// We have a store context hash and it matches with the current context one.
|
||||
// We can use the cached incentive data.
|
||||
// Store the incentive in the in-memory cache and return it.
|
||||
$this->incentive = $cache['incentive'] ?? [];
|
||||
// We have a store context hash and it matches with the current context one.
|
||||
// We can use the cached incentive data.
|
||||
// Store the incentive in the in-memory cache.
|
||||
$this->incentive = $transient_cache['incentive'] ?? [];
|
||||
}
|
||||
|
||||
return $this->incentive;
|
||||
// If the in-memory cache has been set, return it.
|
||||
if ( isset( $this->incentive ) ) {
|
||||
return $this->incentive;
|
||||
}
|
||||
}
|
||||
|
||||
// By this point, we have an expired transient or the store context has changed.
|
||||
@@ -358,22 +323,16 @@ class WcPayWelcomePage {
|
||||
|
||||
$response = wp_remote_get(
|
||||
$url,
|
||||
[
|
||||
array(
|
||||
'user-agent' => 'WooCommerce/' . WC()->version . '; ' . get_bloginfo( 'url' ),
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
// Return early if there is an error, waiting 6 hours before the next attempt.
|
||||
if ( is_wp_error( $response ) ) {
|
||||
// Store a trimmed down, lightweight error.
|
||||
$error = new \WP_Error(
|
||||
$response->get_error_code(),
|
||||
$response->get_error_message(),
|
||||
wp_remote_retrieve_response_code( $response )
|
||||
);
|
||||
// Store the error in the transient so we know this is due to an API error.
|
||||
set_transient( self::CACHE_TRANSIENT_NAME, $error, HOUR_IN_SECONDS * 6 );
|
||||
// Initialize the in-memory cache and return it.
|
||||
// Store a null value in the transient so we know this is due to an API error.
|
||||
set_transient( self::TRANSIENT_NAME, null, HOUR_IN_SECONDS * 6 );
|
||||
// Initialize the in-memory cache.
|
||||
$this->incentive = [];
|
||||
|
||||
return $this->incentive;
|
||||
@@ -403,21 +362,19 @@ class WcPayWelcomePage {
|
||||
// Skip transient cache if `cache-for` header equals zero.
|
||||
if ( '0' === $cache_for ) {
|
||||
// If we have a transient cache that is not expired, delete it so there are no leftovers.
|
||||
if ( false !== $cache ) {
|
||||
delete_transient( self::CACHE_TRANSIENT_NAME );
|
||||
if ( false !== $transient_cache ) {
|
||||
delete_transient( self::TRANSIENT_NAME );
|
||||
}
|
||||
|
||||
return $this->incentive;
|
||||
}
|
||||
|
||||
// Store incentive in transient cache (together with the context hash) for the given number of seconds
|
||||
// or 1 day in seconds. Also attach a timestamp to the transient data so we know when we last fetched.
|
||||
// Store incentive in transient cache (together with the context hash) for the given number of seconds or 24h.
|
||||
set_transient(
|
||||
self::CACHE_TRANSIENT_NAME,
|
||||
self::TRANSIENT_NAME,
|
||||
[
|
||||
'incentive' => $this->incentive,
|
||||
'context_hash' => $store_context_hash,
|
||||
'timestamp' => time(),
|
||||
],
|
||||
! empty( $cache_for ) ? (int) $cache_for : DAY_IN_SECONDS
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user