Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions Libs/Utils/FileUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ public static function getFileFromRemoteStorageOnTempStorage(string $file_name,
stream_set_blocking($stream, true);
@stream_set_read_buffer($stream, 0);

$localPath = rtrim(self::getLocalTmpStorage(), '/')."/".$file_name;
$localPath = tempnam(self::getLocalTmpStorage(), 'fproc_');
if ($localPath === false) {
throw new ValidationException("Unable to create local temporary file.");
}

$out = fopen($localPath, 'wb'); // binary mode
if ($out === false) {
Expand Down Expand Up @@ -115,7 +118,7 @@ public static function getFileFromRemoteStorageOnTempStorage(string $file_name,
);
}
} catch (\Throwable $e) {
throw new ValidationException($e->getMessage());
throw new ValidationException($e->getMessage(), 0, $e);
}

return $localPath;
Expand All @@ -134,4 +137,17 @@ public static function cleanLocalAndRemoteFile(string $localPath, string $remote
Log::debug(sprintf("cleanLocalFile deleting local file %s", $localPath));
unlink($localPath);
}

/**
* Deletes only the local temp file. Use in finally blocks where the remote
* file must be preserved on failure so queue job retries can re-download it.
* @param string $localPath
* @return void
*/
public static function cleanLocalFile(string $localPath): void {
if (file_exists($localPath)) {
Log::debug(sprintf("FileUtils::cleanLocalFile deleting local temp file %s", $localPath));
@unlink($localPath);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@ public static function build(array $data, $update = false)
'overview' => 'nullable|string',
'commitment' => 'nullable|string',
'commitment_author' => 'nullable|string',
'big_logo' => 'sometimes|file_dto',
'logo' =>'sometimes|file_dto',
];
}
}


public static function buildForFileInfo(): array {
return [
'filepath' => 'required|string',
'filename' => 'required|string',
'md5' => 'required|string',
'size' => 'required|integer',
'mime_type'=> 'sometimes|string',
'source_bucket' => 'sometimes|string',
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
use App\Rules\Boolean;
use App\Security\CompanyScopes;
use App\Security\SummitScopes;
use App\Services\Model\FileInfoDTO;
use App\Services\Model\ICompanyService;
use Illuminate\Http\Request as LaravelRequest;
use Illuminate\Http\Response;
use models\exceptions\ValidationException;
use models\main\Company;
use models\main\ICompanyRepository;
use models\oauth2\IResourceServerContext;
use models\utils\IEntity;
Expand Down Expand Up @@ -505,7 +507,7 @@ protected function updateEntity($id, array $payload): IEntity
path: "/api/v1/companies/{id}/logo",
operationId: "addCompanyLogo",
summary: "Add company logo",
description: "Uploads a logo image for the company",
description: "Uploads a logo image for the company. Accepts either a multipart file upload or a JSON payload referencing a file already stored in the file API.",
security: [
[
"companies_oauth2" => [
Expand All @@ -531,20 +533,36 @@ protected function updateEntity($id, array $payload): IEntity
],
requestBody: new OA\RequestBody(
required: true,
content: new OA\MediaType(
mediaType: "multipart/form-data",
schema: new OA\Schema(
required: ["file"],
properties: [
new OA\Property(
property: "file",
type: "string",
format: "binary",
description: "Logo image file"
)
]
)
)
content: [
new OA\MediaType(
mediaType: "multipart/form-data",
schema: new OA\Schema(
required: ["file"],
properties: [
new OA\Property(
property: "file",
type: "string",
format: "binary",
description: "Logo image file"
)
]
)
),
new OA\MediaType(
mediaType: "application/json",
schema: new OA\Schema(
required: ["filepath", "filename", "md5", "size"],
properties: [
new OA\Property(property: "filepath", type: "string", description: "Remote storage path of the uploaded file"),
new OA\Property(property: "filename", type: "string", description: "Original file name"),
new OA\Property(property: "md5", type: "string", description: "MD5 hash of the file for integrity verification"),
new OA\Property(property: "size", type: "integer", description: "File size in bytes"),
new OA\Property(property: "mime_type", type: "string", description: "MIME type of the file"),
new OA\Property(property: "source_bucket", type: "string", description: "Source storage bucket"),
]
)
),
]
),
responses: [
new OA\Response(
Expand All @@ -556,20 +574,33 @@ protected function updateEntity($id, array $payload): IEntity
new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"),
new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"),
new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Company not found"),
new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "File parameter not set"),
]
)]
public function addCompanyLogo(LaravelRequest $request, $company_id)
{
return $this->processRequest(function () use ($request, $company_id) {

$file = $request->file('file');
if (is_null($file)) {
return $this->error412(array('file param not set!'));
}
if (!is_null($file)) {
$logo = $this->service->addCompanyLogo(intval($company_id), $file);

$logo = $this->service->addCompanyLogo(intval($company_id), $file);
return $this->created(SerializerRegistry::getInstance()->getSerializer($logo)->serialize());
}

// file api post processing ( new flow )
$payload = $this->getJsonPayload(CompanyValidationRulesFactory::buildForFileInfo());

$logo = $this->service->processFileForChildEntity(new FileInfoDTO(
owner_entity_id: intval($company_id),
owner_entity_class: Company::class,
owner_member_name: 'logo',
filepath: $payload['filepath'],
filename: $payload['filename'],
size: intval($payload['size']),
md5: $payload['md5'] ?? null,
mime_type: $payload['mime_type'] ?? null,
source_bucket: $payload['source_bucket'] ?? null,
));
return $this->created(SerializerRegistry::getInstance()->getSerializer($logo)->serialize());
});
}
Expand Down Expand Up @@ -624,7 +655,7 @@ public function deleteCompanyLogo($company_id)
path: "/api/v1/companies/{id}/logo/big",
operationId: "addCompanyBigLogo",
summary: "Add company big logo",
description: "Uploads a big logo image for the company",
description: "Uploads a big logo image for the company. Accepts either a multipart file upload or a JSON payload referencing a file already stored in the file API.",
security: [
[
"companies_oauth2" => [
Expand All @@ -650,20 +681,36 @@ public function deleteCompanyLogo($company_id)
],
requestBody: new OA\RequestBody(
required: true,
content: new OA\MediaType(
mediaType: "multipart/form-data",
schema: new OA\Schema(
required: ["file"],
properties: [
new OA\Property(
property: "file",
type: "string",
format: "binary",
description: "Big logo image file"
)
]
)
)
content: [
new OA\MediaType(
mediaType: "multipart/form-data",
schema: new OA\Schema(
required: ["file"],
properties: [
new OA\Property(
property: "file",
type: "string",
format: "binary",
description: "Big logo image file"
)
]
)
),
new OA\MediaType(
mediaType: "application/json",
schema: new OA\Schema(
required: ["filepath", "filename", "md5", "size"],
properties: [
new OA\Property(property: "filepath", type: "string", description: "Remote storage path of the uploaded file"),
new OA\Property(property: "filename", type: "string", description: "Original file name"),
new OA\Property(property: "md5", type: "string", description: "MD5 hash of the file for integrity verification"),
new OA\Property(property: "size", type: "integer", description: "File size in bytes"),
new OA\Property(property: "mime_type", type: "string", description: "MIME type of the file"),
new OA\Property(property: "source_bucket", type: "string", description: "Source storage bucket"),
]
)
),
]
),
responses: [
new OA\Response(
Expand All @@ -675,19 +722,31 @@ public function deleteCompanyLogo($company_id)
new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"),
new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"),
new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Company not found"),
new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "File parameter not set"),
]
)]
public function addCompanyBigLogo(LaravelRequest $request, $company_id)
{
return $this->processRequest(function () use ($request, $company_id) {
$file = $request->file('file');
if (is_null($file)) {
return $this->error412(array('file param not set!'));
if (!is_null($file)) {
$logo = $this->service->addCompanyBigLogo(intval($company_id), $file);
return $this->created(SerializerRegistry::getInstance()->getSerializer($logo)->serialize());
}

$logo = $this->service->addCompanyBigLogo(intval($company_id), $file);

// file api post processing ( new flow )
$payload = $this->getJsonPayload(CompanyValidationRulesFactory::buildForFileInfo());

$logo = $this->service->processFileForChildEntity(new FileInfoDTO(
owner_entity_id: intval($company_id),
owner_entity_class: Company::class,
owner_member_name: 'big_logo',
filepath: $payload['filepath'],
filename: $payload['filename'],
size: intval($payload['size']),
md5: $payload['md5'] ?? null,
mime_type: $payload['mime_type'] ?? null,
source_bucket: $payload['source_bucket'] ?? null,
));
return $this->created(SerializerRegistry::getInstance()->getSerializer($logo)->serialize());
});
}
Expand Down
Loading
Loading