Skip to content

Instantly share code, notes, and snippets.

@Wiejeben
Last active October 11, 2020 00:38
Show Gist options
  • Save Wiejeben/b6c3f069ffd790f12af960f0b6b6d706 to your computer and use it in GitHub Desktop.
Save Wiejeben/b6c3f069ffd790f12af960f0b6b6d706 to your computer and use it in GitHub Desktop.
Generates and stores SEOmatic OpenGraph image from Twig file via spatie/browsershot.
<?php
namespace modules\jobs;
use Craft;
use craft\elements\Asset;
use craft\elements\Entry;
use craft\queue\BaseJob;
use craft\web\View;
use nystudio107\seomatic\models\MetaBundle;
use Spatie\Browsershot\Browsershot;
/**
* Generates and stores SEOmatic OpenGraph image from Twig file.
*/
class GenerateProductOpenGraphImage extends BaseJob
{
public $description = 'Generates product OpenGraph image';
/** @var int */
public $productId;
/** @var string */
public $volumeHandle = 'opengraph';
/** @var string */
public $template = '_products/opengraph.twig';
/** @var string */
public $seomaticFieldHandle = 'seo';
public function __construct(int $productId)
{
$this->productId = $productId;
parent::__construct();
}
/**
* @param \craft\queue\QueueInterface|\yii\queue\Queue $queue
* @return mixed|void
* @throws \Spatie\Browsershot\Exceptions\CouldNotTakeBrowsershot
* @throws \Throwable
* @throws \Twig\Error\LoaderError
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
* @throws \craft\errors\ElementNotFoundException
* @throws \craft\errors\InvalidFieldException
* @throws \yii\base\Exception
*/
public function execute($queue)
{
$entry = Entry::find()->id($this->productId)->anyStatus()->one();
if (! $entry) {
return;
}
/** @var MetaBundle $meta */
$meta = $entry->getFieldValue($this->seomaticFieldHandle);
// Already has an image
if (! empty($meta->metaBundleSettings->seoImageIds)) {
return;
}
$volume = Craft::$app->getVolumes()->getVolumeByHandle($this->volumeHandle);
if (! $volume) {
return;
}
$folder = Craft::$app->getAssets()->getRootFolderByVolumeId($volume->id);
if (! $folder) {
return;
}
$fileName = $entry->id . '.png';
// Check if file already exists
$asset = Asset::find()->volumeId($volume->id)->folderId($folder->id)->filename($fileName)->one();
if ($asset) {
// Assign existing asset to entry
$this->applyAssetToEntry($entry, $asset);
return;
}
$tempFilePath = tempnam(sys_get_temp_dir(), 'opengraph_') . '.png';
// Generate image
$html = Craft::$app->getView()->renderTemplate($this->template, [
'entry' => $entry
], View::TEMPLATE_MODE_SITE);
Browsershot::html($html)->windowSize(1200, 630)->save($tempFilePath);
// Store asset
$asset = new Asset();
$asset->title = $entry->productStyleCode;
$asset->tempFilePath = $tempFilePath;
$asset->filename = $fileName;
$asset->newFolderId = $folder->id;
$asset->volumeId = $folder->volumeId;
$asset->setScenario(Asset::SCENARIO_CREATE);
Craft::$app->getElements()->saveElement($asset);
$this->applyAssetToEntry($entry, $asset);
}
/**
* Applies asset to SEOmatic image field inside entry.
*
* @param Entry $entry
* @param Asset $asset
* @throws \Throwable
* @throws \craft\errors\ElementNotFoundException
* @throws \craft\errors\InvalidFieldException
* @throws \yii\base\Exception
*/
protected function applyAssetToEntry(Entry $entry, Asset $asset): void
{
/** @var MetaBundle $meta */
$meta = $entry->getFieldValue($this->seomaticFieldHandle);
$meta->metaBundleSettings->seoImageTransform = false;
$meta->metaBundleSettings->seoImageIds = [$asset->id];
$entry->setFieldValue($this->seomaticFieldHandle, $meta);
Craft::$app->getElements()->saveElement($entry);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment