Skip to content

Commit c7e6c96

Browse files
Benmarkharding
authored andcommitted
Bootstrap flow asset save diagnotics minds#5160
1 parent 3c7d46e commit c7e6c96

File tree

8 files changed

+272
-36
lines changed

8 files changed

+272
-36
lines changed

Core/MultiTenant/Bootstrap/Delegates/UpdateLogosDelegate.php

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@
1010
use Minds\Core\MultiTenant\Configs\Image\Manager as ConfigImageManager;
1111
use Minds\Core\MultiTenant\MobileConfigs\Enums\MobileConfigImageTypeEnum;
1212
use Minds\Core\MultiTenant\MobileConfigs\Services\MobileConfigAssetsService;
13+
use Minds\Exceptions\ServerErrorException;
1314

1415
/**
1516
* Delegate for updating the logos.
1617
*/
1718
class UpdateLogosDelegate
1819
{
20+
/** Whether any uploads failed. */
21+
private bool $failedUpload = false;
22+
1923
public function __construct(
2024
private ConfigImageManager $configImageManager,
2125
private MobileConfigAssetsService $mobileConfigAssetsService,
@@ -31,14 +35,16 @@ public function __construct(
3135
* @param string $faviconBlob - The blob of the favicon.
3236
* @param string $horizontalLogoBlob - The blob of the horizontal logo.
3337
* @param string $splashBlob - The blob of the splash.
34-
* @return void
38+
* @return bool - Whether the upload was successful.
3539
*/
3640
public function onUpdate(
3741
string $squareLogoBlob = null,
3842
string $faviconBlob = null,
3943
string $horizontalLogoBlob = null,
4044
string $splashBlob = null
41-
) {
45+
): bool {
46+
$this->failedUpload = false;
47+
4248
if ($squareLogoBlob) {
4349
$this->uploadSquareLogo($squareLogoBlob);
4450
$this->uploadMobileIcon($squareLogoBlob);
@@ -57,6 +63,14 @@ public function onUpdate(
5763
if ($splashBlob) {
5864
$this->uploadMobileSplash($splashBlob);
5965
}
66+
67+
if ($this->failedUpload) {
68+
$this->logger->error("Failed to upload all logos, some may have been saved.");
69+
} else {
70+
$this->logger->info("Done uploading logos");
71+
}
72+
73+
return !$this->failedUpload;
6074
}
6175

6276
/**
@@ -67,9 +81,13 @@ public function onUpdate(
6781
private function uploadSquareLogo(string $bigIconBlob): void
6882
{
6983
try {
70-
$this->configImageManager->uploadBlob($bigIconBlob, MultiTenantConfigImageType::SQUARE_LOGO);
71-
$this->logger->info("Uploaded web square logo");
84+
if ($this->configImageManager->uploadBlob($bigIconBlob, MultiTenantConfigImageType::SQUARE_LOGO)) {
85+
$this->logger->info("Uploaded web square logo");
86+
} else {
87+
throw new ServerErrorException("Upload failed");
88+
}
7289
} catch (\Exception $e) {
90+
$this->failedUpload = true;
7391
$this->logger->error("Failed to upload web square logo: " . $e->getMessage());
7492
}
7593
}
@@ -82,9 +100,13 @@ private function uploadSquareLogo(string $bigIconBlob): void
82100
private function uploadHorizontalLogo(string $logoBlob): void
83101
{
84102
try {
85-
$this->configImageManager->uploadBlob($logoBlob, MultiTenantConfigImageType::HORIZONTAL_LOGO);
86-
$this->logger->info("Uploaded web horizontal logo");
103+
if ($this->configImageManager->uploadBlob($logoBlob, MultiTenantConfigImageType::HORIZONTAL_LOGO)) {
104+
$this->logger->info("Uploaded web horizontal logo");
105+
} else {
106+
throw new ServerErrorException("Upload failed");
107+
}
87108
} catch (\Exception $e) {
109+
$this->failedUpload = true;
88110
$this->logger->error("Failed to upload web horizontal logo: " . $e->getMessage());
89111
}
90112
}
@@ -97,9 +119,13 @@ private function uploadHorizontalLogo(string $logoBlob): void
97119
private function uploadFavicon(string $faviconBlob): void
98120
{
99121
try {
100-
$this->configImageManager->uploadBlob($faviconBlob, MultiTenantConfigImageType::FAVICON);
101-
$this->logger->info("Uploaded web favicon");
122+
if ($this->configImageManager->uploadBlob($faviconBlob, MultiTenantConfigImageType::FAVICON)) {
123+
$this->logger->info("Uploaded web favicon");
124+
} else {
125+
throw new ServerErrorException("Upload failed");
126+
}
102127
} catch (\Exception $e) {
128+
$this->failedUpload = true;
103129
$this->logger->error("Failed to upload web favicon: " . $e->getMessage());
104130
}
105131
}
@@ -112,9 +138,13 @@ private function uploadFavicon(string $faviconBlob): void
112138
private function uploadMobileHorizontalLogo(string $logoBlob): void
113139
{
114140
try {
115-
$this->mobileConfigAssetsService->uploadBlob($logoBlob, MobileConfigImageTypeEnum::HORIZONTAL_LOGO);
116-
$this->logger->info("Uploaded mobile horizontal logo");
141+
if ($this->mobileConfigAssetsService->uploadBlob($logoBlob, MobileConfigImageTypeEnum::HORIZONTAL_LOGO)) {
142+
$this->logger->info("Uploaded mobile horizontal logo");
143+
} else {
144+
throw new ServerErrorException("Upload failed");
145+
}
117146
} catch (\Exception $e) {
147+
$this->failedUpload = true;
118148
$this->logger->error("Failed to upload mobile horizontal logo: " . $e->getMessage());
119149
}
120150
}
@@ -127,9 +157,13 @@ private function uploadMobileHorizontalLogo(string $logoBlob): void
127157
private function uploadMobileIcon(string $bigIconBlob): void
128158
{
129159
try {
130-
$this->mobileConfigAssetsService->uploadBlob($bigIconBlob, MobileConfigImageTypeEnum::ICON);
131-
$this->logger->info("Uploaded mobile icon");
160+
if ($this->mobileConfigAssetsService->uploadBlob($bigIconBlob, MobileConfigImageTypeEnum::ICON)) {
161+
$this->logger->info("Uploaded mobile icon");
162+
} else {
163+
throw new ServerErrorException("Upload failed");
164+
}
132165
} catch (\Exception $e) {
166+
$this->failedUpload = true;
133167
$this->logger->error("Failed to upload mobile icon: " . $e->getMessage());
134168
}
135169
}
@@ -142,9 +176,13 @@ private function uploadMobileIcon(string $bigIconBlob): void
142176
private function uploadMobileSquareLogo(string $bigIconBlob): void
143177
{
144178
try {
145-
$this->mobileConfigAssetsService->uploadBlob($bigIconBlob, MobileConfigImageTypeEnum::SQUARE_LOGO);
146-
$this->logger->info("Uploaded mobile square logo");
179+
if ($this->mobileConfigAssetsService->uploadBlob($bigIconBlob, MobileConfigImageTypeEnum::SQUARE_LOGO)) {
180+
$this->logger->info("Uploaded mobile square logo");
181+
} else {
182+
throw new ServerErrorException("Upload failed");
183+
}
147184
} catch (\Exception $e) {
185+
$this->failedUpload = true;
148186
$this->logger->error("Failed to upload mobile square logo: " . $e->getMessage());
149187
}
150188
}
@@ -157,9 +195,13 @@ private function uploadMobileSquareLogo(string $bigIconBlob): void
157195
private function uploadMobileSplash(string $splashBlob): void
158196
{
159197
try {
160-
$this->mobileConfigAssetsService->uploadBlob($splashBlob, MobileConfigImageTypeEnum::SPLASH);
161-
$this->logger->info("Uploaded mobile splash");
198+
if ($this->mobileConfigAssetsService->uploadBlob($splashBlob, MobileConfigImageTypeEnum::SPLASH)) {
199+
$this->logger->info("Uploaded mobile splash");
200+
} else {
201+
throw new ServerErrorException("Upload failed");
202+
}
162203
} catch (\Exception $e) {
204+
$this->failedUpload = true;
163205
$this->logger->error("Failed to upload mobile splash: " . $e->getMessage());
164206
}
165207
}

Core/MultiTenant/Bootstrap/Services/Handlers/LogoGenerationHandler.php

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use Minds\Core\MultiTenant\Bootstrap\Repositories\BootstrapProgressRepository;
1212
use Minds\Core\MultiTenant\Bootstrap\Services\Extractors\HorizontalLogoExtractor;
1313
use Minds\Core\MultiTenant\Bootstrap\Services\Extractors\MobileSplashLogoExtractor;
14+
use Minds\Exceptions\ServerErrorException;
15+
use Minds\Helpers\Image as ImageHelpers;
1416

1517
/**
1618
* Handles the generation of logos.
@@ -24,7 +26,8 @@ public function __construct(
2426
private MobileSplashLogoExtractor $mobileSplashLogoExtractor,
2527
private UpdateLogosDelegate $updateLogosDelegate,
2628
private BootstrapProgressRepository $progressRepository,
27-
private Logger $logger
29+
private ImageHelpers $imageHelpers,
30+
private Logger $logger,
2831
) {
2932
}
3033

@@ -40,6 +43,11 @@ public function handle(string $siteUrl): void
4043

4144
$squareLogoBlob = $this->getSquareLogoBlob($siteUrl);
4245
$faviconBlob = $this->getFaviconBlob($siteUrl);
46+
47+
if (!$squareLogoBlob && !$faviconBlob) {
48+
throw new ServerErrorException("No logos found");
49+
}
50+
4351
$horizontalLogoBlob = null;
4452
$splashBlob = null;
4553

@@ -48,13 +56,14 @@ public function handle(string $siteUrl): void
4856
$splashBlob = $this->getSplashBlob($squareLogoBlob);
4957
}
5058

51-
$this->updateLogosDelegate->onUpdate(
59+
if (!$this->updateLogosDelegate->onUpdate(
5260
squareLogoBlob: $squareLogoBlob,
5361
faviconBlob: $faviconBlob,
5462
horizontalLogoBlob: $horizontalLogoBlob,
5563
splashBlob: $splashBlob
56-
);
57-
$this->logger->info("Logos updated");
64+
)) {
65+
throw new ServerErrorException("Failed to upload all logos");
66+
}
5867

5968
$this->progressRepository->updateProgress(BootstrapStepEnum::LOGO_STEP, true);
6069
$this->logger->info("Updated bootstrap progress for logos step to success");
@@ -74,6 +83,11 @@ private function getSquareLogoBlob(string $siteUrl): ?string
7483
{
7584
try {
7685
$squareLogoBlob = $this->websiteIconExtractor->extract($siteUrl, 256);
86+
87+
if (!$squareLogoBlob || !$this->imageHelpers->isValidImage($squareLogoBlob)) {
88+
throw new ServerErrorException("Valid square logo not extracted");
89+
}
90+
7791
$this->logger->info("Square logo retrieved");
7892
return $squareLogoBlob;
7993
} catch (\Exception $e) {
@@ -92,6 +106,11 @@ private function getFaviconBlob(string $siteUrl): ?string
92106
{
93107
try {
94108
$faviconBlob = $this->websiteIconExtractor->extract($siteUrl, 32);
109+
110+
if (!$faviconBlob || !$this->imageHelpers->isValidImage($faviconBlob)) {
111+
throw new ServerErrorException("Valid favicon not extracted");
112+
}
113+
95114
$this->logger->info("Favicon retrieved");
96115
return $faviconBlob;
97116
} catch (\Exception $e) {
@@ -109,6 +128,11 @@ private function getHorizontalLogoBlob(string $squareLogoBlob): ?string
109128
{
110129
try {
111130
$horizontalLogoBlob = $this->horizontalLogoExtractor->extract($squareLogoBlob);
131+
132+
if (!$horizontalLogoBlob || !$this->imageHelpers->isValidImage($horizontalLogoBlob)) {
133+
throw new ServerErrorException("Valid horizontal logo not extracted");
134+
}
135+
112136
$this->logger->info("Horizontal logo retrieved");
113137
return $horizontalLogoBlob;
114138
} catch (\Exception $e) {
@@ -126,6 +150,11 @@ private function getSplashBlob(string $squareLogoBlob): ?string
126150
{
127151
try {
128152
$splashBlob = $this->mobileSplashLogoExtractor->extract($squareLogoBlob);
153+
154+
if (!$splashBlob || !$this->imageHelpers->isValidImage($splashBlob)) {
155+
throw new ServerErrorException("Valid splash logo not extracted");
156+
}
157+
129158
$this->logger->info("Splash logo retrieved");
130159
return $splashBlob;
131160
} catch (\Exception $e) {

Core/MultiTenant/Bootstrap/Services/ServicesProvider.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use Minds\Core\MultiTenant\Bootstrap\Services\Processors\LogoImageProcessor;
3333
use Minds\Core\MultiTenant\Bootstrap\Repositories\BootstrapProgressRepository;
3434
use Minds\Core\MultiTenant\Services\MultiTenantBootService;
35+
use Minds\Helpers\Image as ImageHelpers;
3536

3637
class ServicesProvider extends DiProvider
3738
{
@@ -134,7 +135,8 @@ function (Di $di): LogoGenerationHandler {
134135
mobileSplashLogoExtractor: $di->get(MobileSplashLogoExtractor::class),
135136
updateLogosDelegate: $di->get(UpdateLogosDelegate::class),
136137
progressRepository: $di->get(BootstrapProgressRepository::class),
137-
logger: $di->get('Logger')
138+
imageHelpers: new ImageHelpers(),
139+
logger: $di->get('Logger'),
138140
);
139141
}
140142
);

Core/MultiTenant/Configs/Image/Manager.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,22 @@ public function upload(string $fileName, MultiTenantConfigImageType $imageType):
5151
* Upload an image blob for the passed in type.
5252
* @param string $imageBlob - binary image data to upload.
5353
* @param MultiTenantConfigImageType $imageType - type of image being uploaded.
54-
* @return void
54+
* @return bool
5555
*/
56-
public function uploadBlob(string $imageBlob, MultiTenantConfigImageType $imageType): void
56+
public function uploadBlob(string $imageBlob, MultiTenantConfigImageType $imageType): bool
5757
{
5858
$file = new File();
5959
$file->setFilename("config/{$imageType->value}.png");
6060
$file->owner_guid = $this->getTenantOwnerGuid();
6161
$file->open('write');
62-
$file->write($imageBlob);
62+
$success = (bool) $file->write($imageBlob);
6363
$file->close();
6464

6565
$this->multiTenantConfigManager->upsertConfigs(
6666
lastCacheTimestamp: time()
6767
);
68+
69+
return $success;
6870
}
6971

7072
/**

Core/MultiTenant/MobileConfigs/Services/MobileConfigAssetsService.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,22 @@ public function upload(MobileConfigImageTypeEnum $imageType, string $filename):
5555
* Upload an image blob for the specified mobile config image type.
5656
* @param string $imageBlob - The image data as a binary string.
5757
* @param MobileConfigImageTypeEnum $imageType - The type of mobile config image being uploaded.
58-
* @return void
58+
* @return bool
5959
*/
60-
public function uploadBlob(string $imageBlob, MobileConfigImageTypeEnum $imageType): void
60+
public function uploadBlob(string $imageBlob, MobileConfigImageTypeEnum $imageType): bool
6161
{
6262
$file = new File();
6363
$file->setFilename("mobile_config/{$imageType->value}.png");
6464
$file->owner_guid = $this->getTenantOwnerGuid();
6565
$file->open('write');
66-
$file->write($imageBlob);
66+
$success = (bool) $file->write($imageBlob);
6767
$file->close();
6868

6969
$this->multiTenantConfigManager->upsertConfigs(
7070
lastCacheTimestamp: time()
7171
);
72+
73+
return $success;
7274
}
7375

7476
/**

Helpers/Image.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
<?php
22
namespace Minds\Helpers;
33

4+
use Minds\Core\Di\Di;
5+
use Minds\Core\Log\Logger;
6+
47
class Image
58
{
9+
public function __construct(
10+
private ?Logger $logger = null
11+
) {
12+
$this->logger ??= Di::_()->get('Logger');
13+
}
14+
615
/**
716
* Get the size of an image
817
* @param string
@@ -11,4 +20,24 @@ public function getimagesize($path)
1120
{
1221
return getimagesize($path);
1322
}
23+
24+
/**
25+
* Validates whether the given blob is a valid image.
26+
* @param string $imageBlob - The image blob to validate.
27+
* @return bool - True if the blob is a valid image.
28+
*/
29+
public function isValidImage(string $imageBlob): bool
30+
{
31+
try {
32+
$image = imagecreatefromstring($imageBlob);
33+
if ($image === false) {
34+
return false;
35+
}
36+
imagedestroy($image);
37+
return true;
38+
} catch (\Exception $e) {
39+
$this->logger->error("Error validating image: " . $e->getMessage());
40+
return false;
41+
}
42+
}
1443
}

0 commit comments

Comments
 (0)