Skip to content

Commit

Permalink
Define a relationship for thumbnails on posts using the attachment mo…
Browse files Browse the repository at this point in the history
…del (#601)

* Define a relationship for thumbnails on posts using the attachment model

* CHANGELOG

* Lint fix
  • Loading branch information
srtfisher authored Nov 11, 2024
1 parent 025d616 commit 5edb71f
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 11 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added

- Define a `thumbnail` relationship on the post model that when defined will return an attachment model.

### Changed

- Post factories that are passed a term slug to `with_terms()` will create the
Expand Down
4 changes: 2 additions & 2 deletions src/mantle/database/model/class-attachment.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ class Attachment extends Post {
/**
* Get an attachment's URL by size.
*
* @param array|string $size Image URL.
* @param array|string $size Image size or array of dimensions.
*
* @throws Model_Exception Thrown when getting image.
*/
public function image_url( $size ): ?string {
public function image_url( array|string $size ): ?string {
if ( ! $this->id() ) {
throw new Model_Exception( 'Unable to get attachment URL for unsaved attachment.' );
}
Expand Down
16 changes: 13 additions & 3 deletions src/mantle/database/model/class-post.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use DateTime;
use DateTimeInterface;
use Mantle\Contracts;
use Mantle\Database\Model\Relations\Belongs_To;
use Mantle\Database\Model\Relations\Has_One;
use Mantle\Database\Query\Builder;
use Mantle\Database\Query\Post_Query_Builder;
use Mantle\Support\Helpers;
Expand Down Expand Up @@ -54,6 +56,7 @@
* @property string $slug Alias to post_name.
* @property string $status Alias to post_status.
* @property string $title Alias to post_title.
* @property \Mantle\Database\Model\Attachment|null $thumbnail
*
* @method static \Mantle\Database\Factory\Post_Factory<static, \WP_Post, static> factory( array|callable|null $state = null )
* @method static \Mantle\Database\Query\Post_Query_Builder<static> anyStatus()
Expand Down Expand Up @@ -289,6 +292,13 @@ public function permalink(): ?string {
return (string) \get_permalink( $this->id() );
}

/**
* Post thumbnail relationship.
*/
public function thumbnail(): Belongs_To {
return $this->belongs_to( Attachment::class, local_key: '_thumbnail_id' );
}

/**
* Retrieve the core object for the underlying object.
*/
Expand All @@ -312,10 +322,10 @@ public function publish(): bool {
/**
* Schedule a post for publication.
*
* @param string|DateTime $date Date to schedule the post for.
* @param DateTimeInterface|string $date Date to schedule the post for.
*/
public function schedule( $date ): bool {
if ( $date instanceof DateTime ) {
public function schedule( DateTimeInterface|string $date ): bool {
if ( $date instanceof DateTimeInterface ) {
$date = $date->format( 'Y-m-d H:i:s' );
} else {
$date = Carbon::parse( $date )->format( 'Y-m-d H:i:s' );
Expand Down
16 changes: 12 additions & 4 deletions src/mantle/database/model/relations/class-belongs-to.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,20 @@ public function get_results() {
/**
* Associate a model with a relationship.
*
* @param Model $model Model to save to.
* @param int|Model $model Model to save to.
* @return Model
*
* @throws Model_Exception Thrown on error setting term for relationship.
*/
public function associate( Model $model ) {
public function associate( int|Model $model ) {
if ( is_int( $model ) ) {
$model = $this->related::find_or_fail( $model );

if ( ! $model instanceof Model ) {
throw new Model_Exception( 'Model must be an instance of Core_Object.' );
}
}

if ( ! $model->exists && $model instanceof Updatable ) {
$model->save();
}
Expand Down Expand Up @@ -185,10 +193,10 @@ public function associate( Model $model ) {
/**
* Proxy to `Belongs_To::associate()`.
*
* @param Model $model Model to save to.
* @param int|Model $model Model to save to.
* @return Model
*/
public function save( Model $model ) {
public function save( int|Model $model ) {
return $this->associate( $model );
}

Expand Down
9 changes: 7 additions & 2 deletions src/mantle/database/model/relations/class-has-one-or-many.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,22 @@ public function add_eager_constraints( Collection $models ): void {
*
* @param Model[]|Model $model Model instance to save.
*/
public function save( array|Model $model ): Model {
public function save( array|Model|int $model ): Model {
if ( is_array( $model ) ) {
// Return the first model if saving many.
return collect( $this->save_many( $model ) )->first();
}

// Save the model if it doesn't exist.
if ( ! $model->exists && $model instanceof Updatable ) {
if ( $model instanceof Model && ! $model->exists && $model instanceof Updatable ) {
$model->save();
}

// Resolve the model to the object if it's an ID.
if ( is_int( $model ) ) {
$model = $this->related::find_or_fail( $model );
}

$append = Has_Many::class === static::class || is_subclass_of( $this, Has_Many::class );

if ( $this->is_post_term_relationship() && $this->parent instanceof Post ) {
Expand Down
19 changes: 19 additions & 0 deletions tests/Database/Model/PostObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use Carbon\Carbon;
use Mantle\Contracts\Database\Registrable;
use Mantle\Database\Model\Attachment;
use Mantle\Database\Model\Dates\Model_Date_Proxy;
use Mantle\Database\Model\Model_Exception;
use Mantle\Database\Model\Post;
Expand Down Expand Up @@ -472,6 +473,24 @@ public function test_dates_attribute() {
$this->assertEquals( $newDate->toDateTimeString(), $post->dates->modified->toDateTimeString() );
}

public function test_thumbnail_relationship() {
$post = static::factory()->post->as_models()->create_and_get();
$attachment_id = static::factory()->attachment->with_real_thumbnail()->create();

$this->assertInstanceOf( Post::class, $post );

$post->thumbnail()->save( $attachment_id );

$this->assertInstanceOf( Attachment::class, $post->thumbnail );
$this->assertEquals( $attachment_id, $post->thumbnail->id );
$this->assertEquals( $attachment_id, get_post_thumbnail_id( $post->id() ) );

$post->thumbnail()->dissociate();

$this->assertEmpty( $post->thumbnail );
$this->assertEmpty( get_post_thumbnail_id( $post->id() ) );
}

/**
* Get a random post ID, ensures the post ID is not the last in the set.
*
Expand Down

0 comments on commit 5edb71f

Please sign in to comment.