Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Lint

on:
push:
branches: [master]
pull_request:
branches: [master]

jobs:
phpcs:
name: PHPCS
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: cs2pr

- name: Install dependencies
run: composer install --no-interaction --prefer-dist

- name: Run PHPCS
run: composer phpcs -- --report-full --report-checkstyle=./phpcs-report.xml

- name: Show PHPCS results in PR
if: always()
run: cs2pr ./phpcs-report.xml

phpstan:
name: PHPStan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'

- name: Install dependencies
run: composer install --no-interaction --prefer-dist

- name: Run PHPStan
run: composer phpstan
35 changes: 24 additions & 11 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,43 @@
{
"name": "spock/shadow-taxonomies",
"description": "A library used for create relationships between CPT's",
"type": "package",
"keywords": [],
"description": "A Composer library for creating relationships between custom post types using shadow taxonomies in WordPress.",
"type": "library",
"keywords": ["wordpress", "taxonomy", "custom-post-type", "relationships"],
"homepage": "https://github.com/patelutkarsh/shadow-taxonomy",
"license": "GPL-2.0+",
"author": {
"name": "Utkarsh Patel",
"email": "utkarshpatel@outlook.com",
"homepage": "utkarshpatel.com",
"homepage": "https://utkarshpatel.com",
"role": "Developer"
},
"repositories": [
{
"type": "composer",
"url": "https://packagist.org"
}
],
"require": {
"php": ">=7.2"
"php": ">=8.2"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"wp-coding-standards/wpcs": "^3.0",
"phpcompatibility/phpcompatibility-wp": "^2.1",
"phpstan/phpstan": "^2.0",
"szepeviktor/phpstan-wordpress": "^2.0"
},
"autoload": {
"files": [
"index.php"
]
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"scripts": {
"phpcs": "phpcs",
"phpcbf": "phpcbf",
"phpstan": "phpstan analyse",
"lint": [
"@phpcs",
"@phpstan"
]
}
}
97 changes: 70 additions & 27 deletions includes/shadow-taxonomy-cli.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
<?php
/**
* Shadow Taxonomy WP-CLI commands.
*
* @package Shadow_Taxonomy
*/

declare(strict_types=1);

namespace Shadow_Taxonomy\CLI;

use Shadow_Taxonomy\Core as Core;
use Shadow_Taxonomy\Core;

if ( ! ( defined( 'WP_CLI' ) && WP_CLI ) ) {
return;
}

\WP_CLI::add_command( 'shadow', __NAMESPACE__ . '\Shadow_Terms' );

/**
* WP-CLI commands for managing shadow taxonomy relationships.
*/
class Shadow_Terms extends \WP_CLI_Command {

/**
Expand All @@ -26,11 +37,11 @@ class Shadow_Terms extends \WP_CLI_Command {
*/
private function validate_cpt_and_tax( string $cpt, string $tax ): void {
if ( ! post_type_exists( $cpt ) ) {
\WP_CLI::error( esc_html__( 'The Post Type you provided does not exist.' ) );
\WP_CLI::error( esc_html__( 'The Post Type you provided does not exist.', 'shadow-taxonomy' ) );
}

if ( ! taxonomy_exists( $tax ) ) {
\WP_CLI::error( esc_html__( 'The Taxonomy you provided does not exist.' ) );
\WP_CLI::error( esc_html__( 'The Taxonomy you provided does not exist.', 'shadow-taxonomy' ) );
}
}

Expand All @@ -44,15 +55,15 @@ private function validate_cpt_and_tax( string $cpt, string $tax ): void {
*/
private function get_posts_missing_shadow_meta( string $cpt, string $tax ): array {
$all_posts = [];
$page = 1;
$page = 1;

do {
$query = new \WP_Query( [
'post_type' => $cpt,
'post_status' => 'publish',
'posts_per_page' => self::BATCH_SIZE,
'paged' => $page,
'meta_query' => [
'meta_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Required to find posts missing shadow meta.
[
'key' => Core\get_meta_key( $tax, 'term_id' ),
'compare' => 'NOT EXISTS',
Expand All @@ -61,14 +72,14 @@ private function get_posts_missing_shadow_meta( string $cpt, string $tax ): arra
] );

if ( is_wp_error( $query ) ) {
\WP_CLI::error( esc_html__( 'An error occurred while searching for posts.' ) );
\WP_CLI::error( esc_html__( 'An error occurred while searching for posts.', 'shadow-taxonomy' ) );
}

if ( ! empty( $query->posts ) ) {
$all_posts = array_merge( $all_posts, $query->posts );
}

$page++;
++$page;
} while ( $page <= $query->max_num_pages );

return $all_posts;
Expand Down Expand Up @@ -142,7 +153,7 @@ private function delete_orphan_term( $term, string $tax, bool $verbose = false )
* @param array $items Array of [ 'action' => string, 'count' => int ] items.
*/
private function output_dry_run_table( array $items ): void {
\WP_CLI::warning( esc_html__( 'View the below table to see how many terms will be created or deleted.' ) );
\WP_CLI::warning( esc_html__( 'View the below table to see how many terms will be created or deleted.', 'shadow-taxonomy' ) );
\WP_CLI\Utils\format_items( 'table', $items, [ 'action', 'count' ] );
}

Expand All @@ -166,6 +177,9 @@ private function output_dry_run_table( array $items ): void {
* : Allows you to see the number of shadow terms which need to be created or deleted.
*
* @subcommand sync
*
* @param array $args Positional arguments.
* @param array $assoc_args Associative arguments.
*/
public function sync_shadow_terms( $args, $assoc_args ) {
$tax = $assoc_args['tax'];
Expand All @@ -180,7 +194,7 @@ public function sync_shadow_terms( $args, $assoc_args ) {
*/
$posts = $this->get_posts_missing_shadow_meta( $cpt, $tax );

$terms_to_create = array_filter( $posts, function( $post ) use ( $tax ) {
$terms_to_create = array_filter( $posts, function ( $post ) use ( $tax ) {
return empty( Core\get_associated_term( $post->ID, $tax ) );
} );

Expand All @@ -189,7 +203,7 @@ public function sync_shadow_terms( $args, $assoc_args ) {
*/
$all_terms = $this->get_all_terms( $tax );

$terms_to_delete = array_filter( $all_terms, function( $term ) use ( $cpt ) {
$terms_to_delete = array_filter( $all_terms, function ( $term ) use ( $cpt ) {
return empty( Core\get_associated_post( $term, $cpt ) );
} );

Expand All @@ -200,20 +214,26 @@ public function sync_shadow_terms( $args, $assoc_args ) {
*/
if ( $dry_run ) {
$this->output_dry_run_table( [
[ 'action' => 'Create', 'count' => count( $terms_to_create ) ],
[ 'action' => 'Delete', 'count' => count( $terms_to_delete ) ],
[
'action' => 'Create',
'count' => count( $terms_to_create ),
],
[
'action' => 'Delete',
'count' => count( $terms_to_delete ),
],
] );
return;
}

if ( 0 === $count ) {
\WP_CLI::success( esc_html__( 'Shadow Taxonomy is in sync, no action needed.' ) );
\WP_CLI::success( esc_html__( 'Shadow Taxonomy is in sync, no action needed.', 'shadow-taxonomy' ) );
return;
}

/**
* Process Shadow Taxonomy Additions and Deletions.
*/
*/
\WP_CLI::log( sprintf( 'Processing %d items...', absint( $count ) ) );

foreach ( $terms_to_create as $post ) {
Expand Down Expand Up @@ -243,11 +263,14 @@ public function sync_shadow_terms( $args, $assoc_args ) {
* : The taxonomy name for the shadow relationship.
*
* @subcommand check
*
* @param array $args Positional arguments.
* @param array $assoc_args Associative arguments.
*/
public function check_sync( $args, $assoc_args ) {

if ( ! isset( $assoc_args['tax'] ) || ! taxonomy_exists( $assoc_args['tax'] ) ) {
\WP_CLI::error( esc_html__( 'Please provide a valid taxonomy using --tax.' ) );
\WP_CLI::error( esc_html__( 'Please provide a valid taxonomy using --tax.', 'shadow-taxonomy' ) );
}

if ( 'post_type' === $args[0] ) {
Expand Down Expand Up @@ -306,6 +329,9 @@ public function check_sync( $args, $assoc_args ) {
* : Allows you to see the number of shadow terms which need to be created or deleted.
*
* @subcommand sync-terms
*
* @param array $args Positional arguments.
* @param array $assoc_args Associative arguments.
*/
public function migrate_shadow_terms( $args, $assoc_args ) {
$tax = $assoc_args['tax'];
Expand All @@ -320,7 +346,7 @@ public function migrate_shadow_terms( $args, $assoc_args ) {
*/
$posts = $this->get_posts_missing_shadow_meta( $cpt, $tax );

$terms_to_create = [];
$terms_to_create = [];
$posts_missing_metadata = [];

foreach ( $posts as $post ) {
Expand Down Expand Up @@ -353,14 +379,14 @@ public function migrate_shadow_terms( $args, $assoc_args ) {
'post_type' => $cpt,
'posts_per_page' => 1,
'post_status' => 'publish',
'tax_query' => [
'tax_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required to find posts by taxonomy term.
[
'taxonomy' => $tax,
'field' => 'id',
'terms' => $term->term_id,
],
],
'no_found_rows' => true,
'no_found_rows' => true,
] );

if ( empty( $term_query->posts ) || is_wp_error( $term_query ) ) {
Expand All @@ -382,10 +408,22 @@ public function migrate_shadow_terms( $args, $assoc_args ) {
*/
if ( $dry_run ) {
$this->output_dry_run_table( [
[ 'action' => 'Create', 'count' => count( $terms_to_create ) ],
[ 'action' => 'Delete', 'count' => count( $terms_to_delete ) ],
[ 'action' => 'Missing Term Meta', 'count' => count( $terms_missing_metadata ) ],
[ 'action' => 'Missing Post Meta', 'count' => count( $posts_missing_metadata ) ],
[
'action' => 'Create',
'count' => count( $terms_to_create ),
],
[
'action' => 'Delete',
'count' => count( $terms_to_delete ),
],
[
'action' => 'Missing Term Meta',
'count' => count( $terms_missing_metadata ),
],
[
'action' => 'Missing Post Meta',
'count' => count( $posts_missing_metadata ),
],
] );
return;
}
Expand All @@ -394,7 +432,7 @@ public function migrate_shadow_terms( $args, $assoc_args ) {
empty( $terms_to_delete ) &&
empty( $terms_missing_metadata ) &&
empty( $posts_missing_metadata ) ) {
\WP_CLI::success( esc_html__( 'Shadow Taxonomy is in sync, no action needed.' ) );
\WP_CLI::success( esc_html__( 'Shadow Taxonomy is in sync, no action needed.', 'shadow-taxonomy' ) );
return;
}

Expand Down Expand Up @@ -460,6 +498,9 @@ public function migrate_shadow_terms( $args, $assoc_args ) {
* : Allows you to see the number of shadow terms which need to be created or deleted.
*
* @subcommand deep-sync
*
* @param array $args Positional arguments.
* @param array $assoc_args Associative arguments.
*/
public function deep_sync( $args, $assoc_args ) {
$tax = $assoc_args['tax'];
Expand All @@ -474,7 +515,7 @@ public function deep_sync( $args, $assoc_args ) {
*/
$posts = $this->get_posts_missing_shadow_meta( $cpt, $tax );

$terms_to_create = array_filter( $posts, function( $post ) use ( $tax ) {
$terms_to_create = array_filter( $posts, function ( $post ) use ( $tax ) {
$shadow_term = get_post_meta( $post->ID, Core\get_meta_key( $tax, 'term_id' ), true );

if ( ! empty( $shadow_term ) ) {
Expand All @@ -493,13 +534,16 @@ public function deep_sync( $args, $assoc_args ) {
*/
if ( $dry_run ) {
$this->output_dry_run_table( [
[ 'action' => 'Create', 'count' => $count ],
[
'action' => 'Create',
'count' => $count,
],
] );
return;
}

if ( 0 === $count ) {
\WP_CLI::success( esc_html__( 'Shadow Taxonomy is in sync, no action needed.' ) );
\WP_CLI::success( esc_html__( 'Shadow Taxonomy is in sync, no action needed.', 'shadow-taxonomy' ) );
return;
}

Expand All @@ -514,5 +558,4 @@ public function deep_sync( $args, $assoc_args ) {

\WP_CLI::success( sprintf( 'Process Complete. Successfully synced %d posts and terms.', absint( $count ) ) );
}

}
Loading