-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #84 from sectsect/feature/tag-update-programmatically
feat: add support for programmatic tag order management
- Loading branch information
Showing
7 changed files
with
331 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
<?php | ||
/** | ||
* WP Tag Order Tag Updater Class | ||
* | ||
* Provides a method to update tag order for a specific post and taxonomy. | ||
* | ||
* @package WP_Tag_Order | ||
* @since 3.11.0 | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace WP_Tag_Order; | ||
|
||
/** | ||
* Class responsible for updating tag order for a specific post. | ||
*/ | ||
class Tag_Updater { | ||
/** | ||
* Update tag order for a specific post and taxonomy. | ||
* | ||
* @param int $post_id The post ID to update tags for. | ||
* @param string $taxonomy The taxonomy name. | ||
* @param array<int>|string $tag_ids Array of tag IDs or comma-separated tag IDs. | ||
* | ||
* @return int|bool True if meta update was successful, false otherwise. | ||
* @throws \InvalidArgumentException If input validation fails. | ||
*/ | ||
public function update_tag_order( int $post_id, string $taxonomy, array|string $tag_ids ): int|bool { | ||
// Validate inputs. | ||
if ( $post_id <= 0 ) { | ||
throw new \InvalidArgumentException( 'Invalid post ID' ); | ||
} | ||
|
||
if ( empty( $taxonomy ) ) { | ||
throw new \InvalidArgumentException( 'Taxonomy cannot be empty' ); | ||
} | ||
|
||
if ( ! taxonomy_exists( $taxonomy ) ) { | ||
throw new \InvalidArgumentException( sprintf( 'Invalid taxonomy: %s', esc_html( $taxonomy ) ) ); | ||
} | ||
|
||
if ( is_taxonomy_hierarchical( $taxonomy ) ) { | ||
throw new \InvalidArgumentException( sprintf( 'Taxonomy %s is hierarchical and not supported', esc_html( $taxonomy ) ) ); | ||
} | ||
|
||
// Convert string to array if needed. | ||
if ( is_string( $tag_ids ) ) { | ||
$tag_ids = explode( ',', wp_unslash( $tag_ids ) ); | ||
} | ||
|
||
if ( empty( $tag_ids ) ) { | ||
throw new \InvalidArgumentException( 'Tag IDs cannot be empty' ); | ||
} | ||
|
||
if ( ! wto_is_enabled_taxonomy( $taxonomy ) ) { | ||
throw new \InvalidArgumentException( sprintf( 'Taxonomy %s is not enabled for tag ordering', esc_html( $taxonomy ) ) ); | ||
} | ||
|
||
// Sanitize tag IDs. | ||
$sanitized_tag_ids = array_map( | ||
function ( $tag_id ): int { | ||
// Ensure each tag ID is a positive integer. | ||
$sanitized_id = filter_var( | ||
$tag_id, | ||
FILTER_VALIDATE_INT, | ||
array( | ||
'options' => array( | ||
'min_range' => 1, | ||
), | ||
) | ||
); | ||
|
||
if ( false === $sanitized_id ) { | ||
throw new \InvalidArgumentException( 'Invalid tag ID: ' . esc_html( is_string( $tag_id ) ? $tag_id : (string) $tag_id ) ); | ||
} | ||
|
||
return $sanitized_id; | ||
}, | ||
$tag_ids | ||
); | ||
|
||
// Serialize tags for storage. | ||
$meta_box_tags_value = serialize( $sanitized_tag_ids ); | ||
|
||
// Update post meta. | ||
return update_post_meta( $post_id, 'wp-tag-order-' . $taxonomy, $meta_box_tags_value ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
<?php | ||
/** | ||
* Test Tag_Updater Class | ||
* | ||
* @package WP_Tag_Order | ||
* @since 3.11.0 | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace WP_Tag_Order\Tests; | ||
|
||
use WP_Tag_Order\Tag_Updater; | ||
use WP_UnitTestCase; | ||
|
||
/** | ||
* Test cases for Tag_Updater class | ||
*/ | ||
class Test_Tag_Updater extends WP_UnitTestCase { | ||
/** | ||
* Tag_Updater instance | ||
* | ||
* @var Tag_Updater | ||
*/ | ||
private $tag_updater; | ||
|
||
/** | ||
* Test taxonomy name | ||
* | ||
* @var string | ||
*/ | ||
private $test_taxonomy; | ||
|
||
/** | ||
* Setup before each test. | ||
* Enables specific taxonomy for the plugin. | ||
*/ | ||
protected function setUp(): void { | ||
parent::setUp(); | ||
$this->tag_updater = new Tag_Updater(); | ||
$this->test_taxonomy = 'post_tag'; | ||
|
||
// Ensure the test taxonomy is enabled for the plugin. | ||
add_filter( 'wto_is_enabled_taxonomy', array( $this, 'enable_test_taxonomy' ), 10, 1 ); | ||
|
||
// Register test taxonomy if not already registered. | ||
if ( ! taxonomy_exists( $this->test_taxonomy ) ) { | ||
register_taxonomy( $this->test_taxonomy, 'post' ); | ||
} | ||
|
||
// Enable specific taxonomy for the test. | ||
$enabled_taxonomies = array( 'post_tag' ); | ||
update_option( 'wpto_enabled_taxonomies', $enabled_taxonomies ); | ||
} | ||
|
||
/** | ||
* Teardown after each test. | ||
* Resets the enabled taxonomies option. | ||
*/ | ||
protected function tearDown(): void { | ||
// Remove the filter after the test. | ||
remove_filter( 'wto_is_enabled_taxonomy', array( $this, 'enable_test_taxonomy' ) ); | ||
|
||
// Reset the enabled taxonomies option. | ||
delete_option( 'wpto_enabled_taxonomies' ); | ||
|
||
parent::tearDown(); | ||
} | ||
|
||
/** | ||
* Mock method to enable test taxonomy for the plugin | ||
* | ||
* @param string $taxonomy Taxonomy name. | ||
* @return bool | ||
*/ | ||
public function enable_test_taxonomy( $taxonomy ): bool { | ||
return $taxonomy === $this->test_taxonomy; | ||
} | ||
|
||
/** | ||
* Test successful tag order update | ||
* | ||
* @covers Tag_Updater::update_tag_order | ||
*/ | ||
public function test_update_tag_order_with_array(): void { | ||
// Create a test post. | ||
$post_id = $this->factory()->post->create(); | ||
|
||
// Create test tags. | ||
$tag_ids = array( | ||
$this->factory()->term->create( array( 'taxonomy' => $this->test_taxonomy ) ), | ||
$this->factory()->term->create( array( 'taxonomy' => $this->test_taxonomy ) ), | ||
$this->factory()->term->create( array( 'taxonomy' => $this->test_taxonomy ) ), | ||
); | ||
|
||
// Update tag order. | ||
$result = $this->tag_updater->update_tag_order( $post_id, $this->test_taxonomy, $tag_ids ); | ||
|
||
$this->assertNotFalse( $result, 'Failed to update metadata for tag order' ); | ||
|
||
// Verify meta was saved correctly. | ||
$saved_tags = unserialize( get_post_meta( $post_id, 'wp-tag-order-' . $this->test_taxonomy, true ) ); | ||
$this->assertSame( $tag_ids, $saved_tags ); | ||
} | ||
|
||
/** | ||
* Test tag order update with comma-separated string | ||
* | ||
* @covers Tag_Updater::update_tag_order | ||
*/ | ||
public function test_update_tag_order_with_string(): void { | ||
// Create a test post. | ||
$post_id = $this->factory()->post->create(); | ||
|
||
// Create test tags. | ||
$tag_ids = array( | ||
$this->factory()->term->create( array( 'taxonomy' => $this->test_taxonomy ) ), | ||
$this->factory()->term->create( array( 'taxonomy' => $this->test_taxonomy ) ), | ||
); | ||
|
||
$tag_ids_string = implode( ',', $tag_ids ); | ||
|
||
// Update tag order. | ||
$result = $this->tag_updater->update_tag_order( $post_id, $this->test_taxonomy, $tag_ids_string ); | ||
|
||
$this->assertNotFalse( $result, 'Failed to update metadata for tag order' ); | ||
|
||
// Verify meta was saved correctly. | ||
$saved_tags = unserialize( get_post_meta( $post_id, 'wp-tag-order-' . $this->test_taxonomy, true ) ); | ||
$this->assertSame( $tag_ids, $saved_tags ); | ||
} | ||
|
||
/** | ||
* Test invalid post ID throws exception | ||
* | ||
* @covers Tag_Updater::update_tag_order | ||
*/ | ||
public function test_update_tag_order_with_invalid_post_id(): void { | ||
$this->expectException( \InvalidArgumentException::class ); | ||
$this->expectExceptionMessage( 'Invalid post ID' ); | ||
|
||
$this->tag_updater->update_tag_order( 0, $this->test_taxonomy, array( 1 ) ); | ||
} | ||
|
||
/** | ||
* Test empty taxonomy throws exception | ||
* | ||
* @covers Tag_Updater::update_tag_order | ||
*/ | ||
public function test_update_tag_order_with_empty_taxonomy(): void { | ||
$this->expectException( \InvalidArgumentException::class ); | ||
$this->expectExceptionMessage( 'Taxonomy cannot be empty' ); | ||
|
||
$post_id = $this->factory()->post->create(); | ||
$this->tag_updater->update_tag_order( $post_id, '', array( 1 ) ); | ||
} | ||
|
||
/** | ||
* Test non-existent taxonomy throws exception | ||
* | ||
* @covers Tag_Updater::update_tag_order | ||
*/ | ||
public function test_update_tag_order_with_non_existent_taxonomy(): void { | ||
$this->expectException( \InvalidArgumentException::class ); | ||
$this->expectExceptionMessage( 'Invalid taxonomy: non_existent_taxonomy' ); | ||
|
||
$post_id = $this->factory()->post->create(); | ||
$this->tag_updater->update_tag_order( $post_id, 'non_existent_taxonomy', array( 1 ) ); | ||
} | ||
|
||
/** | ||
* Test empty tag IDs throws exception | ||
* | ||
* @covers Tag_Updater::update_tag_order | ||
*/ | ||
public function test_update_tag_order_with_empty_tag_ids(): void { | ||
$this->expectException( \InvalidArgumentException::class ); | ||
$this->expectExceptionMessage( 'Tag IDs cannot be empty' ); | ||
|
||
$post_id = $this->factory()->post->create(); | ||
$this->tag_updater->update_tag_order( $post_id, $this->test_taxonomy, array() ); | ||
} | ||
|
||
/** | ||
* Test invalid tag ID throws exception | ||
* | ||
* @covers Tag_Updater::update_tag_order | ||
*/ | ||
public function test_update_tag_order_with_invalid_tag_id(): void { | ||
$this->expectException( \InvalidArgumentException::class ); | ||
$this->expectExceptionMessage( 'Invalid tag ID: invalid' ); | ||
|
||
$post_id = $this->factory()->post->create(); | ||
$this->tag_updater->update_tag_order( $post_id, $this->test_taxonomy, array( 'invalid' ) ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters