Skip to content

Commit

Permalink
Add support for Laravel's Attachable objects (spatie#2963)
Browse files Browse the repository at this point in the history
* add attachable support

* Fix styling

* fix phpstan errors

* remove static analysis as it keeps failing only on github

Co-authored-by: freekmurze <[email protected]>
  • Loading branch information
freekmurze and freekmurze authored Jun 22, 2022
1 parent 364949e commit 6f54cf4
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 41 deletions.
31 changes: 0 additions & 31 deletions .github/workflows/phpstan.yml

This file was deleted.

14 changes: 8 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
"ext-exif": "*",
"ext-fileinfo": "*",
"ext-json": "*",
"illuminate/bus": "^9.0",
"illuminate/console": "^9.0",
"illuminate/database": "^9.0",
"illuminate/pipeline": "^9.0",
"illuminate/support": "^9.0",
"illuminate/bus": "^9.18",
"illuminate/console": "^9.18",
"illuminate/database": "^9.18",
"illuminate/pipeline": "^9.18",
"illuminate/support": "^9.18",
"intervention/image": "^2.7",
"maennchen/zipstream-php": "^2.0",
"spatie/image": "^2.2.2",
Expand All @@ -52,7 +52,7 @@
"spatie/laravel-ray": "^1.28",
"spatie/pdf-to-image": "^2.1",
"spatie/phpunit-snapshot-assertions": "^4.2",
"pestphp/pest": "^1.20"
"pestphp/pest": "^1.21"
},
"conflict": {
"php-ffmpeg/php-ffmpeg": "<0.6.1"
Expand All @@ -69,6 +69,8 @@
},
"scripts": {
"analyse": "vendor/bin/phpstan analyse",
"baseline": "vendor/bin/phpstan analyse --generate-baseline",

"format": "vendor/bin/php-cs-fixer fix --allow-risky=yes",
"test": "vendor/bin/pest"
},
Expand Down
72 changes: 72 additions & 0 deletions docs/advanced-usage/attaching-media-in-mails.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
title: Attaching media in mails
weight: 9
---

Laravel allows [to attach all sorts of classes](https://laravel.com/docs/9.x/mail#attachable-objects) in mails. The `Media` model implements Laravel's `Attachable` interface, so you can attach `Media` models directly in mails.


```php
namespace App\Mails;

use Illuminate\Mail\Mailable;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use App\Models\Order;

class OrderConfirmationMail extends Mailable
{
public function __construct(public Order $order)
{

}

public function build()
{
/** @var \Spatie\MediaLibrary\MediaCollections\Models\Media $invoice */
$invoice = $this->order->getFirstMedia('invoice')

return $this
->view('invoice')
->attach($invoice);
}
}
```

## Using conversions as attachments

You can call `mailAttachment()` on a `Media` model to get back an `Attachment` that you can use in a Mailable. You can pass the name of a conversion to `mailAttachment()` to get an attachable conversion back.

```php
namespace App\Mails;

use Illuminate\Mail\Mailable;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use App\Models\BlogPost;

class BlogPostThumbnailMail extends Mailable
{
public function __construct(public BlogPost $blogPost)
{

}

public function build()
{
/** @var \Spatie\MediaLibrary\MediaCollections\Models\Media $mediaItem */
$mediaItem = $this->blogPost->getFirstMedia();

// pass the conversion name
$thumbnailAttachment = $mediaItem->mailAttachment('thumbnail');

return $this
->view('mails/blogpostThumbnail')
->attach($thumbnailAttachment);
}
}
```

## Customizing the attachment

By default, the attachment will use the `file_name` and `mime_type` properties to configure Laravel's `Attachment` class. To override how `Attachments` are made, [use a custom media model](https://spatie.be/docs/laravel-medialibrary/v10/advanced-usage/using-your-own-model), and override the `toMailAttachment` method.


21 changes: 18 additions & 3 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,11 @@ parameters:
count: 1
path: src/MediaCollections/FileAdder.php

-
message: "#^Cannot call static method created\\(\\) on class\\-string\\<Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\|null\\.$#"
count: 1
path: src/MediaCollections/FileAdder.php

-
message: "#^Class Spatie\\\\MediaLibraryPro\\\\Models\\\\TemporaryUpload not found\\.$#"
count: 2
Expand Down Expand Up @@ -1172,22 +1177,27 @@ parameters:

-
message: "#^Access to an undefined property Spatie\\\\MediaLibrary\\\\MediaCollections\\\\Models\\\\Media\\:\\:\\$disk\\.$#"
count: 2
count: 3
path: src/MediaCollections/Models/Media.php

-
message: "#^Access to an undefined property Spatie\\\\MediaLibrary\\\\MediaCollections\\\\Models\\\\Media\\:\\:\\$file_name\\.$#"
count: 3
count: 4
path: src/MediaCollections/Models/Media.php

-
message: "#^Access to an undefined property Spatie\\\\MediaLibrary\\\\MediaCollections\\\\Models\\\\Media\\:\\:\\$generated_conversions\\.$#"
count: 4
path: src/MediaCollections/Models/Media.php

-
message: "#^Access to an undefined property Spatie\\\\MediaLibrary\\\\MediaCollections\\\\Models\\\\Media\\:\\:\\$mime\\.$#"
count: 1
path: src/MediaCollections/Models/Media.php

-
message: "#^Access to an undefined property Spatie\\\\MediaLibrary\\\\MediaCollections\\\\Models\\\\Media\\:\\:\\$mime_type\\.$#"
count: 2
count: 3
path: src/MediaCollections/Models/Media.php

-
Expand Down Expand Up @@ -1215,6 +1225,11 @@ parameters:
count: 2
path: src/MediaCollections/Models/Media.php

-
message: "#^Call to an undefined method Spatie\\\\MediaLibrary\\\\Support\\\\UrlGenerator\\\\UrlGenerator\\:\\:getPathRelativeToRoot\\(\\)\\.$#"
count: 1
path: src/MediaCollections/Models/Media.php

-
message: "#^Cannot call method determineOrderColumnName\\(\\) on Illuminate\\\\Database\\\\Eloquent\\\\Collection\\<int, Spatie\\\\MediaLibrary\\\\MediaCollections\\\\Models\\\\Media\\>\\|Spatie\\\\MediaLibrary\\\\MediaCollections\\\\Models\\\\Media\\|null\\.$#"
count: 1
Expand Down
3 changes: 3 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@
<directory>tests</directory>
</testsuite>
</testsuites>
<php>
<env name="MAIL_MAILER" value="log"/>
</php>
</phpunit>
23 changes: 22 additions & 1 deletion src/MediaCollections/Models/Media.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
namespace Spatie\MediaLibrary\MediaCollections\Models;

use DateTimeInterface;
use Illuminate\Contracts\Mail\Attachable;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Mail\Attachment;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Spatie\MediaLibrary\Conversions\Conversion;
Expand Down Expand Up @@ -37,7 +39,7 @@
* @property-read string $previewUrl
* @property-read string $originalUrl
*/
class Media extends Model implements Responsable, Htmlable
class Media extends Model implements Responsable, Htmlable, Attachable
{
use IsSorted;
use CustomMediaProperties;
Expand Down Expand Up @@ -214,6 +216,7 @@ public function getCustomProperty(string $propertyName, $default = null): mixed

/**
* @param mixed $value
*
* @return $this
*/
public function setCustomProperty(string $name, $value): self
Expand Down Expand Up @@ -428,4 +431,22 @@ public static function findWithTemporaryUploadInCurrentSession(array $uuids)
)
->get();
}

public function mailAttachment(string $conversion = ''): Attachment
{
$path = $this->getUrlGenerator($conversion)->getPathRelativeToRoot();

$attachment = Attachment::fromStorageDisk($this->disk, $path)->as($this->file_name);

if ($this->mime_type) {
$attachment->withMime($this->mime);
}

return $attachment;
}

public function toMailAttachment(): Attachment
{
return $this->mailAttachment();
}
}
51 changes: 51 additions & 0 deletions tests/Feature/Media/ToMailAttachmentTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

use Illuminate\Mail\Attachment;
use Illuminate\Support\Facades\Mail;
use Spatie\MediaLibrary\MediaCollections\Exceptions\InvalidConversion;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\MediaLibrary\Tests\TestSupport\Mail\AttachmentMail;
use Spatie\MediaLibrary\Tests\TestSupport\Mail\InvalidMediaConversionAttachmentMail;
use Spatie\MediaLibrary\Tests\TestSupport\Mail\MediaConversionAttachmentMail;

beforeEach(function () {
$this->testModelWithConversion
->addMedia($this->getTestJpg())
->toMediaCollection();
});

it('can create a mail attachment from a media', function () {
$mailAttachment = Media::first()->toMailAttachment();

expect($mailAttachment)->toBeInstanceOf(Attachment::class);
});

it('can send a mail with a media attached', function () {
$mailable = new AttachmentMail(Media::first());

Mail::send($mailable);

// assert no exceptions thrown
expect(true)->toBeTrue();
});

it('can create an attachment to a conversion', function () {
$mailAttachment = $this->testModelWithConversion->getFirstMedia()->mailAttachment('thumb');

expect($mailAttachment)->toBeInstanceOf(Attachment::class);
});

it('can send a mail with conversion attached', function () {
$mailable = new MediaConversionAttachmentMail(Media::first());

Mail::send($mailable);

// assert no exceptions thrown
expect(true)->toBeTrue();
});

it('will throw an exception when attaching a media specifying a non-existing conversion', function () {
$mailable = new InvalidMediaConversionAttachmentMail(Media::first());

Mail::send($mailable);
})->throws(InvalidConversion::class);
21 changes: 21 additions & 0 deletions tests/TestSupport/Mail/AttachmentMail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Spatie\MediaLibrary\Tests\TestSupport\Mail;

use Illuminate\Mail\Mailable;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class AttachmentMail extends Mailable
{
public function __construct(public Media $media)
{
}

public function build()
{
return $this
->to('[email protected]')
->view('mailable')
->attach($this->media);
}
}
23 changes: 23 additions & 0 deletions tests/TestSupport/Mail/InvalidMediaConversionAttachmentMail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Spatie\MediaLibrary\Tests\TestSupport\Mail;

use Illuminate\Mail\Mailable;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class InvalidMediaConversionAttachmentMail extends Mailable
{
public function __construct(public Media $media)
{
}

public function build()
{
$thumbnailAttachment = $this->media->mailAttachment('non-existing-conversion');

return $this
->to('[email protected]')
->view('mailable')
->attach($thumbnailAttachment);
}
}
23 changes: 23 additions & 0 deletions tests/TestSupport/Mail/MediaConversionAttachmentMail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Spatie\MediaLibrary\Tests\TestSupport\Mail;

use Illuminate\Mail\Mailable;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class MediaConversionAttachmentMail extends Mailable
{
public function __construct(public Media $media)
{
}

public function build()
{
$thumbnailAttachment = $this->media->mailAttachment('thumb');

return $this
->to('[email protected]')
->view('mailable')
->attach($thumbnailAttachment);
}
}
1 change: 1 addition & 0 deletions tests/TestSupport/resources/views/mailable.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Test mailable

0 comments on commit 6f54cf4

Please sign in to comment.