Skip to content

Commit

Permalink
Create terms when passed an unknown slug
Browse files Browse the repository at this point in the history
  • Loading branch information
srtfisher committed Oct 30, 2024
1 parent f85a079 commit 5662008
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 8 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Changed

- Post factories that are passed a term slug to `with_terms()` will create the
term if it doesn't exist by default. This can be disabled by calling the
`create_terms()` method on the factory or replacing the with terms method call
with `with_terms_only_existing()`.

### Fixed

- Ensure that the `delete()` method of the HTTP Client doesn't set a body by default.
Expand Down
38 changes: 37 additions & 1 deletion src/mantle/database/factory/class-post-factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class Post_Factory extends Factory {
*/
protected string $model = Post::class;

/**
* Flag to create terms by default.
*/
protected bool $create_terms = true;

/**
* Constructor.
*
Expand All @@ -46,9 +51,21 @@ public function __construct( Generator $faker, public string $post_type = 'post'
parent::__construct( $faker );
}

/**
* Change the default creation of terms with the post factory.
*
* @param bool $value Value to set.
*/
public function create_terms( bool $value = true ): void {
$this->create_terms = $value;
}

/**
* Create a new factory instance to create posts with a set of terms.
*
* Any slugs passed that are not found will be created. If you want to
* only use existing terms, use `with_terms_only_existing()`.
*
* @param array<int|string, \WP_Term|int|string|array<string, mixed>>|\WP_Term|int|string ...$terms Terms to assign to the post.
*/
public function with_terms( ...$terms ): static {
Expand All @@ -60,7 +77,26 @@ public function with_terms( ...$terms ): static {
$terms = collect( $terms )->all();

return $this->with_middleware(
fn ( array $args, Closure $next ) => $next( $args )->set_terms( $terms ),
fn ( array $args, Closure $next ) => $next( $args )->set_terms( $terms, append: true, create: $this->create_terms ),
);
}

/**
* Create a new factory instance to create posts with a set of terms without creating
* any unknown terms.
*
* @param array<int|string, \WP_Term|int|string|array<string, mixed>>|\WP_Term|int|string ...$terms Terms to assign to the post.
*/
public function with_terms_only_existing( ...$terms ): static {
// Handle an array in the first argument.
if ( 1 === count( $terms ) && isset( $terms[0] ) && is_array( $terms[0] ) ) {
$terms = $terms[0];
}

$terms = collect( $terms )->all();

return $this->with_middleware(
fn ( array $args, Closure $next ) => $next( $args )->set_terms( $terms, append: true, create: false ),
);
}

Expand Down
23 changes: 18 additions & 5 deletions src/mantle/database/model/term/trait-model-term.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Mantle\Database\Model\Term;
use Mantle\Support\Arr;
use Mantle\Support\Collection;
use Mantle\Support\Str;
use WP_Term;

use function Mantle\Support\Helpers\collect;
Expand Down Expand Up @@ -120,18 +121,19 @@ public function get_terms( string $taxonomy ): array {
* @param mixed $terms Accepts an array of or a single instance of terms.
* @param string $taxonomy Taxonomy name, optional.
* @param bool $append Append to the object's terms, defaults to false.
* @param bool $create Create the term if it does not exist, defaults to false.
* @return static
*
* @throws Model_Exception Thrown if the $taxonomy cannot be inferred from $terms.
* @throws Model_Exception Thrown if error saving the post's terms.
*/
public function set_terms( $terms, ?string $taxonomy = null, bool $append = false ) {
public function set_terms( $terms, ?string $taxonomy = null, bool $append = false, bool $create = false ) {
$terms = collect( Arr::wrap( $terms ) );

// If taxonomy is not specified, chunk the terms into taxonomy groups.
if ( ! $taxonomy ) {
$terms = $terms->reduce(
function ( array $carry, $term, $index ): array {
function ( array $carry, $term, $index ) use ( $create ): array {
if ( $term instanceof WP_Term ) {
$carry[ $term->taxonomy ][] = $term;

Expand Down Expand Up @@ -177,10 +179,21 @@ function ( array $carry, $term, $index ): array {
continue;
}

$item = get_term_object_by( 'slug', $item, $taxonomy );
$term = get_term_object_by( 'slug', $item, $taxonomy );

if ( $item ) {
$carry[ $taxonomy ][] = $item;
// Optionally create the term if it does not exist.
if ( ! $term && $create ) {
$term = wp_insert_term( Str::headline( $item ), $taxonomy, [ 'slug' => $item ] );

if ( is_wp_error( $term ) ) {
throw new Model_Exception( "Error creating term: [{$term->get_error_message()}]" );
}

$term = get_term( $term['term_id'], $taxonomy );
}

if ( $term instanceof WP_Term ) {
$carry[ $taxonomy ][] = $term;
}
}

Expand Down
11 changes: 9 additions & 2 deletions tests/Database/Factory/UnitTestingFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,8 @@ public function test_posts_with_multiple_terms_spread_array_argument() {
);
}

#[Group( 'with_terms' )]
#[DataProvider( 'slug_id_dataprovider' )]
#[Group( 'with_terms' )]
public function test_posts_with_multiple_terms_single_array( string $field ) {
$tags = collect( static::factory()->tag->create_many( 5 ) )
->map( fn ( $term_id ) => get_term( $term_id ) )
Expand All @@ -300,7 +300,14 @@ public function test_posts_with_multiple_terms_single_array( string $field ) {

#[Group( 'with_terms' )]
public function test_posts_with_terms_create_unknown_term() {
$this->markTestIncomplete( 'This test is incomplete.' );
$post = static::factory()->post->with_terms( [
'post_tag' => [ 'unknown-term' ],
] )->create_and_get();

$post_tags = get_the_terms( $post, 'post_tag' );

$this->assertCount( 1, $post_tags );
$this->assertEquals( 'unknown-term', $post_tags[0]->slug );
}

public function test_terms_with_posts() {
Expand Down

0 comments on commit 5662008

Please sign in to comment.