Skip to content

Commit 0332281

Browse files
authored
refactor: Convert to PNG without using files (DenverCoder1#394)
1 parent 898015e commit 0332281

File tree

1 file changed

+60
-26
lines changed

1 file changed

+60
-26
lines changed

src/card.php

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -500,50 +500,84 @@ function convertSvgToPng(string $svg): string
500500
$svg = preg_replace("/(animation: currstreak[^;'\"]+)/m", "font-size: 28px;", $svg);
501501
$svg = preg_replace("/<a \X*?>(\X*?)<\/a>/m", '\1', $svg);
502502

503-
// save svg to random file
504-
$filename = uniqid();
505-
file_put_contents("$filename.svg", $svg);
503+
// escape svg for shell
504+
$svg = escapeshellarg($svg);
505+
506+
// `--pipe`: read input from pipe (stdin)
507+
// `--export-filename -`: write output to stdout
508+
// `-w 495 -h 195`: set width and height of the output image
509+
// `--export-type png`: set the output format to PNG
510+
$cmd = "echo {$svg} | inkscape --pipe --export-filename - -w 495 -h 195 --export-type png";
506511

507512
// convert svg to png
508-
$out = shell_exec("inkscape -w 495 -h 195 {$filename}.svg -o {$filename}.png"); // skipcq: PHP-A1009
509-
if ($out !== null) {
510-
throw new Exception("Error converting SVG to PNG: $out");
513+
$png = shell_exec($cmd); // skipcq: PHP-A1009
514+
515+
// check if the conversion was successful
516+
if (empty($png)) {
517+
// `2>&1`: redirect stderr to stdout
518+
$error = shell_exec("$cmd 2>&1"); // skipcq: PHP-A1009
519+
throw new Exception("Failed to convert SVG to PNG: {$error}", 500);
511520
}
512521

513-
// read png data and delete temporary files
514-
$png = file_get_contents("{$filename}.png");
515-
unlink("{$filename}.svg");
516-
unlink("{$filename}.png");
522+
// return the generated png
517523
return $png;
518524
}
519525

520526
/**
521-
* Set headers and echo response based on type
527+
* Return headers and response based on type
522528
*
523529
* @param string|array $output The stats (array) or error message (string) to display
530+
*
531+
* @return array The Content-Type header and the response body, and status code in case of an error
524532
*/
525-
function renderOutput(string|array $output, int $responseCode = 200): void
533+
function generateOutput(string|array $output): array
526534
{
527535
$requestedType = $_REQUEST["type"] ?? "svg";
528-
http_response_code($responseCode);
529536

530537
// output JSON data
531538
if ($requestedType === "json") {
532-
// set content type to JSON
533-
header("Content-Type: application/json");
534539
// generate array from output
535540
$data = gettype($output) === "string" ? ["error" => $output] : $output;
536-
// output as JSON
537-
echo json_encode($data);
541+
return [
542+
"contentType" => "application/json",
543+
"body" => json_encode($data),
544+
];
538545
}
539-
// output SVG or PNG card
540-
else {
541-
// set content type to SVG or PNG
542-
header("Content-Type: image/" . ($requestedType === "png" ? "png" : "svg+xml"));
543-
// render SVG card
544-
$svg = gettype($output) === "string" ? generateErrorCard($output) : generateCard($output);
545-
// output PNG if PNG is requested, otherwise output SVG
546-
echo $requestedType === "png" ? convertSvgToPng($svg) : $svg;
546+
// Generate SVG card
547+
$svg = gettype($output) === "string" ? generateErrorCard($output) : generateCard($output);
548+
// output PNG card
549+
if ($requestedType === "png") {
550+
try {
551+
$png = convertSvgToPng($svg);
552+
return [
553+
"contentType" => "image/png",
554+
"body" => $png,
555+
];
556+
} catch (Exception $e) {
557+
return [
558+
"contentType" => "image/svg+xml",
559+
"status" => 500,
560+
"body" => generateErrorCard($e->getMessage()),
561+
];
562+
}
547563
}
548-
exit();
564+
// output SVG card
565+
return [
566+
"contentType" => "image/svg+xml",
567+
"body" => $svg,
568+
];
569+
}
570+
571+
/**
572+
* Set headers and output response
573+
*
574+
* @param string|array $output The Content-Type header and the response body
575+
* @param int $responseCode The HTTP response code to send
576+
*/
577+
function renderOutput(string|array $output, int $responseCode = 200): void
578+
{
579+
$response = generateOutput($output);
580+
http_response_code($response["status"] ?? $responseCode);
581+
header("Content-Type: {$response["contentType"]}");
582+
exit($response["body"]);
549583
}

0 commit comments

Comments
 (0)