Skip to content

Commit

Permalink
Service::refreshEmbeddedAsset()
Browse files Browse the repository at this point in the history
  • Loading branch information
ttempleton committed May 19, 2022
1 parent 69c8d07 commit bd55978
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 52 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Added
- Added `spicyweb\embeddedassets\Service::refreshEmbeddedAsset()`
- Added `spicyweb\embeddedassets\errors\RefreshException`

## 3.0.1 - 2022-05-18

### Fixed
Expand Down
40 changes: 40 additions & 0 deletions src/Service.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Embed\Embed;
use Embed\Http\CurlDispatcher;
use Embed\Http\Url;
use spicyweb\embeddedassets\errors\RefreshException;
use spicyweb\embeddedassets\events\BeforeCreateAdapterEvent;
use spicyweb\embeddedassets\jobs\InstagramRefreshCheck;
use spicyweb\embeddedassets\models\EmbeddedAsset;
Expand Down Expand Up @@ -281,6 +282,45 @@ public function createEmbeddedAsset(array $array): ?EmbeddedAsset
return $embeddedAsset->validate() ? $embeddedAsset : null;
}

/**
* Refreshes an embedded asset with the current data from the embedded asset's URL.
*
* @param Asset $asset
* @param EmbeddedAsset|null $embeddedAsset
* @return EmbeddedAsset the refreshed embedded asset
* @throws RefreshException if the embedded asset could not be refreshed
* @since 3.0.2
*/
public function refreshEmbeddedAsset(Asset $asset, ?EmbeddedAsset $embeddedAsset = null): EmbeddedAsset
{
if ($embeddedAsset === null) {
$embeddedAsset = $this->getEmbeddedAsset($asset) ?? throw new RefreshException('Asset is not an embedded asset');
}

$assetsService = Craft::$app->getAssets();
$elementsService = Craft::$app->getElements();
$folder = $asset->getFolder();
$newEmbeddedAsset = $this->requestUrl($embeddedAsset->url, false);
$newAsset = $this->createAsset($newEmbeddedAsset, $folder);
$result = $elementsService->saveElement($newAsset);

if (!$result) {
throw new RefreshException(implode('; ', $newAsset->getFirstErrors()));
}

$tempPath = $newAsset->getCopyOfFile();
$assetsService->replaceAssetFile($asset, $tempPath, $asset->filename);
$elementsService->deleteElement($newAsset);

// Replace the old cached data for the embedded asset
Craft::$app->getCache()->set(
$this->getCachedAssetKey($asset),
Json::encode($newEmbeddedAsset->jsonSerialize(), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)
);

return $newEmbeddedAsset;
}

/**
* Creates an asset element ready to be saved from an embedded asset model.
*
Expand Down
27 changes: 7 additions & 20 deletions src/console/controllers/RefreshController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Craft;
use craft\console\Controller;
use craft\elements\Asset;
use spicyweb\embeddedassets\errors\RefreshException;
use spicyweb\embeddedassets\Plugin as EmbeddedAssets;
use yii\console\ExitCode;
use yii\helpers\Console;
Expand Down Expand Up @@ -83,8 +84,6 @@ public function actionByProvider(): int

private function _refresh(?array $volume, ?array $providers): int
{
$assetsService = Craft::$app->getAssets();
$elementsService = Craft::$app->getElements();
$embeddedAssets = [];
$successCount = 0;
$errorCount = 0;
Expand Down Expand Up @@ -121,26 +120,14 @@ private function _refresh(?array $volume, ?array $providers): int
}

foreach ($embeddedAssets as $assetId => $assetData) {
$assetToReplace = $assetData['asset'];
$embeddedAssetToReplace = $assetData['embeddedAsset'];
$this->stdout('Refreshing ' . $assetToReplace->getPath() . ' ... ');

$folder = $assetToReplace->getFolder();
$newEmbeddedAsset = EmbeddedAssets::$plugin->methods->requestUrl($embeddedAssetToReplace->url, false);
$newAsset = EmbeddedAssets::$plugin->methods->createAsset($newEmbeddedAsset, $folder);
$result = $elementsService->saveElement($newAsset);

if (!$result) {
$errorCount++;
$errors = $newAsset->getFirstErrors();
$this->stderr('Failed to save the Asset:' . PHP_EOL . implode(';' . PHP_EOL, $errors), Console::FG_RED);
} else {
$tempPath = $newAsset->getCopyOfFile();
$assetsService->replaceAssetFile($assetToReplace, $tempPath, $assetToReplace->filename);
$elementsService->deleteElement($newAsset);

try {
$this->stdout('Refreshing ' . $assetData['asset']->getPath() . ' ... ');
EmbeddedAssets::$plugin->methods->refreshEmbeddedAsset($assetData['asset'], $assetData['embeddedAsset']);
$successCount++;
$this->stdout('done.' . PHP_EOL);
} catch (RefreshException $e) {
$errorCount++;
$this->stderr('Failed to save the Asset: ' . $e->getMessage() . PHP_EOL, Console::FG_RED);
}
}

Expand Down
23 changes: 23 additions & 0 deletions src/errors/RefreshException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace spicyweb\embeddedassets\errors;

use yii\base\Exception;

/**
* RefreshException represents an exception when refreshing an embedded asset.
*
* @package spicyweb\embeddedassets\errors
* @author Spicy Web <plugins@spicyweb.com.au>
* @since 3.0.2
*/
class RefreshException extends Exception
{
/**
* @inheritdoc
*/
public function getName(): string
{
return 'Failed to refresh embedded asset';
}
}
47 changes: 15 additions & 32 deletions src/jobs/InstagramRefreshCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use craft\elements\Asset;
use craft\helpers\Json;
use craft\queue\BaseJob;
use spicyweb\embeddedassets\models\EmbeddedAsset;
use spicyweb\embeddedassets\Plugin as EmbeddedAssets;

/**
Expand Down Expand Up @@ -36,14 +37,16 @@ public function execute($queue): void
{
// Check if the data was sent through, and if not, get it from the asset contents
if ($this->embeddedAssetData === null) {
$this->embeddedAssetData = Json::decode($asset->getContents());
$embeddedAsset = EmbeddedAssets::$plugin->methods->getEmbeddedAsset($asset);
} else {
$embeddedAsset = EmbeddedAssets::$plugin->methods->createEmbeddedAsset($this->embeddedAssetData);
}

$hasImageExpired = $this->_hasInstagramImageExpired($this->embeddedAssetData['image']);
$hasImageExpired = $this->_hasInstagramImageExpired($embeddedAsset->image);
$this->setProgress($queue, 0.5);

if ($hasImageExpired) {
$this->_updateInstagramFile($this->asset, $this->embeddedAssetData['url']);
$this->_updateInstagramFile($this->asset, $embeddedAsset);
} else {
// If it hasn't expired yet, update the date modified so it checks in another seven days
$this->asset->dateModified = new \DateTime();
Expand Down Expand Up @@ -93,41 +96,21 @@ private function _hasInstagramImageExpired(?string $imageUrl = null): bool
* Refreshes an Instagram embedded asset with data from the given URL.
*
* @param Asset $asset
* @param string $url
* @param EmbeddedAsset $embeddedAsset
*/
private function _updateInstagramFile(Asset $asset, string $url)
private function _updateInstagramFile(Asset $asset, EmbeddedAsset $embeddedAsset)
{
// Fix URL in case we got a login URL and not an Instagram URL referring to a post
// We add the post ID at the end
if (strpos($url, 'login') !== false) {
parse_str(parse_url($url)['query'], $params);
$url = "https://www.instagram.com" . $params['next'];
if (strpos($embeddedAsset->url, 'login') !== false) {
parse_str(parse_url($embeddedAsset->url)['query'], $params);
$embeddedAsset->url = "https://www.instagram.com" . $params['next'];
}

// Get new data from the URL
$newEmbeddedAsset = EmbeddedAssets::$plugin->methods->requestUrl($url, false);

if ($newEmbeddedAsset) {
try {
$assetsService = Craft::$app->getAssets();
$elementsService = Craft::$app->getElements();

$folder = $assetsService->findFolder(['id' => $asset->folderId]);
$assetToReplace = EmbeddedAssets::$plugin->methods->createAsset($newEmbeddedAsset, $folder);
$elementsService->saveElement($assetToReplace);

$tempPath = $assetToReplace->getCopyOfFile();
$assetsService->replaceAssetFile($asset, $tempPath, $asset->filename);
$elementsService->deleteElement($assetToReplace);

// Replace the old cached data for the embedded asset
Craft::$app->getCache()->set(
EmbeddedAssets::$plugin->methods->getCachedAssetKey($asset),
Json::encode($newEmbeddedAsset->jsonSerialize(), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)
);
} catch (\Throwable $e) {
Craft::warning("Couldn't refresh Instagram embedded asset with asset ID '{$asset->id}': " . $e->getMessage());
}
try {
EmbeddedAssets::$plugin->methods->refreshEmbeddedAsset($asset, $embeddedAsset);
} catch (\Throwable $e) {
Craft::warning("Couldn't refresh Instagram embedded asset with asset ID '{$asset->id}': " . $e->getMessage());
}
}
}

0 comments on commit bd55978

Please sign in to comment.