Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f03abc8ac8 |
@@ -26,19 +26,3 @@ jobs:
|
||||
docker push $REGISTRY
|
||||
docker push $REGISTRY:$IMAGE_TAG
|
||||
docker rmi $(docker images -q $REGISTRY:$IMAGE_TAG) -f
|
||||
deploy:
|
||||
name: Deploy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Pull & Restart
|
||||
uses: appleboy/ssh-action@v1.0.3
|
||||
with:
|
||||
host: ${{ secrets.SSH_VM_DEPLOYMENT_HOST }}
|
||||
key: ${{ secrets.SSH_VM_DEPLOYMENT }}
|
||||
username: ${{ secrets.SSH_VM_DEPLOYMENT_USERNAME }}
|
||||
port: ${{ secrets.SSH_VM_DEPLOYMENT_PORT }}
|
||||
script: |
|
||||
cd ~/deployment/genpdf
|
||||
docker compose pull
|
||||
docker compose down -v
|
||||
docker compose up -d
|
||||
@@ -30,6 +30,7 @@ RUN apt-get update && apt-get install -y \
|
||||
RUN mkdir -p /usr/share/fonts/truetype/custom
|
||||
COPY ./fonts/gilroy/* /usr/share/fonts/truetype/custom
|
||||
COPY ./fonts/lexend/* /usr/share/fonts/truetype/custom
|
||||
COPY ./fonts/visby/* /usr/share/fonts/truetype/custom
|
||||
RUN fc-cache -f -v
|
||||
|
||||
# Download and install Composer
|
||||
|
||||
25
base.Dockerfile
Normal file
25
base.Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
||||
FROM php:8.2-cli
|
||||
|
||||
# Install dependencies needed for Composer and PHP zip extension
|
||||
RUN echo "deb http://deb.debian.org/debian bookworm contrib non-free" > /etc/apt/sources.list.d/contrib.list
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
unzip \
|
||||
libzip-dev \
|
||||
libreoffice \
|
||||
fontconfig \
|
||||
gcc \
|
||||
g++ \
|
||||
build-essential \
|
||||
ttf-mscorefonts-installer \
|
||||
&& docker-php-ext-install zip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install fonts
|
||||
RUN mkdir -p /usr/share/fonts/truetype/custom
|
||||
COPY ./fonts/gilroy/* /usr/share/fonts/truetype/custom
|
||||
COPY ./fonts/lexend/* /usr/share/fonts/truetype/custom
|
||||
RUN fc-cache -f -v
|
||||
|
||||
# Download and install Composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
@@ -19,6 +19,7 @@ RUN apt-get update && apt-get install -y \
|
||||
RUN mkdir -p /usr/share/fonts/truetype/custom
|
||||
COPY ./fonts/gilroy/* /usr/share/fonts/truetype/custom
|
||||
COPY ./fonts/lexend/* /usr/share/fonts/truetype/custom
|
||||
COPY ./fonts/visby/* /usr/share/fonts/truetype/custom
|
||||
RUN fc-cache -f -v
|
||||
|
||||
# Download and install Composer
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
,pande,pandewidya.local,15.08.2024 07:34,file:///Users/pande/Library/Application%20Support/LibreOffice/4;
|
||||
BIN
examples/Cover.png
Normal file
BIN
examples/Cover.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
BIN
examples/Raport.docx
Normal file
BIN
examples/Raport.docx
Normal file
Binary file not shown.
5058
examples/pembahasan.json
Normal file
5058
examples/pembahasan.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
fonts/visby/Visby Round CF Bold Oblique.otf
Normal file
BIN
fonts/visby/Visby Round CF Bold Oblique.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Bold.otf
Normal file
BIN
fonts/visby/Visby Round CF Bold.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Demibold Oblique.otf
Normal file
BIN
fonts/visby/Visby Round CF Demibold Oblique.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Demibold.otf
Normal file
BIN
fonts/visby/Visby Round CF Demibold.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Extrabold Oblique.otf
Normal file
BIN
fonts/visby/Visby Round CF Extrabold Oblique.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Extrabold.otf
Normal file
BIN
fonts/visby/Visby Round CF Extrabold.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Extralight Oblique.otf
Normal file
BIN
fonts/visby/Visby Round CF Extralight Oblique.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Extralight.otf
Normal file
BIN
fonts/visby/Visby Round CF Extralight.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Heavy Oblique.otf
Normal file
BIN
fonts/visby/Visby Round CF Heavy Oblique.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Heavy.otf
Normal file
BIN
fonts/visby/Visby Round CF Heavy.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Light Oblique.otf
Normal file
BIN
fonts/visby/Visby Round CF Light Oblique.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Light.otf
Normal file
BIN
fonts/visby/Visby Round CF Light.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Medium Oblique.otf
Normal file
BIN
fonts/visby/Visby Round CF Medium Oblique.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Medium.otf
Normal file
BIN
fonts/visby/Visby Round CF Medium.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF Oblique.otf
Normal file
BIN
fonts/visby/Visby Round CF Oblique.otf
Normal file
Binary file not shown.
BIN
fonts/visby/Visby Round CF.otf
Normal file
BIN
fonts/visby/Visby Round CF.otf
Normal file
Binary file not shown.
BIN
src/.DS_Store
vendored
BIN
src/.DS_Store
vendored
Binary file not shown.
@@ -10,7 +10,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
|
||||
class Generate extends Command
|
||||
class GenerateEbook extends Command
|
||||
{
|
||||
protected static $defaultName = "generate:ebook";
|
||||
|
||||
55
src/Command/GenerateTest.php
Normal file
55
src/Command/GenerateTest.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace MenulisAi\Pdfgen\Command;
|
||||
|
||||
use MenulisAi\Pdfgen\Document\Ebook;
|
||||
use MenulisAi\Pdfgen\Document\Table;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
|
||||
class GenerateTest extends Command
|
||||
{
|
||||
protected static $defaultName = "generate:test";
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setDescription('Generate a PDF document file from JSON data')
|
||||
->addArgument("input", InputArgument::REQUIRED, "Input path file JSON")
|
||||
->addArgument("output", InputArgument::OPTIONAL, "Set the output path");
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$inPath = $input->getArgument("input");
|
||||
|
||||
$doc = new Table($inPath);
|
||||
|
||||
$path = $doc->compile();
|
||||
|
||||
$output->writeln($path);
|
||||
|
||||
$cmd = new Process([
|
||||
"soffice",
|
||||
"--headless",
|
||||
"--convert-to",
|
||||
"pdf",
|
||||
"--outdir",
|
||||
"/app/storage/",
|
||||
$path
|
||||
]);
|
||||
|
||||
$cmd->run();
|
||||
|
||||
if (!$cmd->isSuccessful()) {
|
||||
throw new ProcessFailedException($cmd);
|
||||
}
|
||||
|
||||
$output->writeln(rootPath("storage/" . pathinfo($path, PATHINFO_FILENAME) . ".pdf"));
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,25 @@
|
||||
|
||||
namespace MenulisAi\Pdfgen\Document;
|
||||
|
||||
interface Document {}
|
||||
use Exception;
|
||||
|
||||
class Document
|
||||
{
|
||||
protected $object;
|
||||
|
||||
protected function openFile(string $path)
|
||||
{
|
||||
$file = file_get_contents($path);
|
||||
if ($file === false) {
|
||||
throw new Exception("Unable to read or open the file", 1);
|
||||
}
|
||||
|
||||
$data = json_decode($file);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
// Handle error if the JSON could not be parsed
|
||||
throw new Exception("Error read the json file: " . json_last_error_msg(), 1);
|
||||
}
|
||||
|
||||
$this->object = $data;
|
||||
}
|
||||
}
|
||||
|
||||
9
src/Document/Documentable.php
Normal file
9
src/Document/Documentable.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace MenulisAi\Pdfgen\Document;
|
||||
|
||||
interface Documentable
|
||||
{
|
||||
public function templateSource(): string;
|
||||
public function compile(): string;
|
||||
}
|
||||
@@ -5,10 +5,8 @@ namespace MenulisAi\Pdfgen\Document;
|
||||
use PhpOffice\PhpWord\TemplateProcessor;
|
||||
use Exception;
|
||||
|
||||
class Ebook implements Document
|
||||
class Ebook extends Document implements Documentable
|
||||
{
|
||||
protected $object;
|
||||
|
||||
public function __construct(string $jsonPath)
|
||||
{
|
||||
$this->openFile($jsonPath);
|
||||
@@ -114,21 +112,7 @@ class Ebook implements Document
|
||||
return $proc->save();
|
||||
}
|
||||
|
||||
protected function openFile(string $path)
|
||||
{
|
||||
$file = file_get_contents($path);
|
||||
if ($file === false) {
|
||||
throw new Exception("Unable to read or open the file", 1);
|
||||
}
|
||||
|
||||
$data = json_decode($file);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
// Handle error if the JSON could not be parsed
|
||||
throw new Exception("Error read the json file: " . json_last_error_msg(), 1);
|
||||
}
|
||||
|
||||
$this->object = $data;
|
||||
}
|
||||
|
||||
protected function intToAlphabet(int $number): string
|
||||
{
|
||||
|
||||
103
src/Document/Table.php
Normal file
103
src/Document/Table.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace MenulisAi\Pdfgen\Document;
|
||||
|
||||
use PhpOffice\PhpWord\Element\Table as ElementTable;
|
||||
use PhpOffice\PhpWord\IOFactory;
|
||||
use PhpOffice\PhpWord\SimpleType\Border;
|
||||
use PhpOffice\PhpWord\SimpleType\Jc;
|
||||
use PhpOffice\PhpWord\SimpleType\JcTable;
|
||||
use PhpOffice\PhpWord\TemplateProcessor;
|
||||
use PhpOffice\PhpWord\SimpleType\TblWidth;
|
||||
use PhpOffice\PhpWord\SimpleType\TextAlignment;
|
||||
use PhpOffice\PhpWord\Style\Table as StyleTable;
|
||||
|
||||
const PER_INCH = 1440;
|
||||
|
||||
class Table extends Document implements Documentable
|
||||
{
|
||||
public function __construct(string $jsonPath)
|
||||
{
|
||||
// $this->openFile($jsonPath);
|
||||
}
|
||||
|
||||
public function templateSource(): string
|
||||
{
|
||||
return appPath("Template/Doc1.docx");
|
||||
}
|
||||
|
||||
public function compile(): string
|
||||
{
|
||||
/**
|
||||
* 1 Inch = 1440 point for TWIP / dxa
|
||||
* A4 Paper (W x H) = 8.27 x 11.69 = 11908.9 x 16833.6
|
||||
* Margin Left = 0.44" = 633.6
|
||||
* Margin Right = 0.44" = 633.6
|
||||
* Margin Top = 0.79" = 1137.6
|
||||
* Margin Bottom = 0.79" = 1137.6
|
||||
*/
|
||||
|
||||
$proc = new TemplateProcessor($this->templateSource());
|
||||
|
||||
$proc->setValue("name", "Pande Ganteng");
|
||||
$proc->setValue("full_name", "Pande Ganteng");
|
||||
$proc->setValue("email", "Pande@gmail.com");
|
||||
|
||||
$tableWidth = (8.27 * PER_INCH) - ((0.44 * 2) * PER_INCH);
|
||||
$col1Width = $tableWidth * 0.4;
|
||||
$col2Width = $tableWidth * 0.15;
|
||||
$col3Width = $tableWidth * 0.15;
|
||||
$col4Width = $tableWidth * 0.15;
|
||||
$col5Width = $tableWidth * 0.15;
|
||||
|
||||
$table = new ElementTable([
|
||||
'alignment' => JcTable::CENTER,
|
||||
'borderColor' => '#072442',
|
||||
'borderSize' => 10,
|
||||
'width' => $tableWidth,
|
||||
'unit' => TblWidth::TWIP,
|
||||
'layout' => StyleTable::LAYOUT_AUTO,
|
||||
'cellMarginTop' => 100,
|
||||
'cellMarginLeft' => 100,
|
||||
'cellMarginBottom' => 0,
|
||||
'cellMarginRight' => 100,
|
||||
]);
|
||||
$table->addRow(800);
|
||||
$table->addCell($col1Width, ['valign' => 'center', 'bgColor' => '#4169E1'])->addText('Kategori', ['bold' => true, 'name' => 'Visby Round CF', 'size' => 10, 'color' => '#ffffff'], ['alignment' => Jc::CENTER]);
|
||||
$table->addCell($col2Width, ['valign' => 'center', 'bgColor' => '#4169E1'])->addText('Jawaban Benar', ['bold' => true, 'name' => 'Visby Round CF', 'size' => 10, 'color' => '#ffffff'], ['alignment' => Jc::CENTER]);
|
||||
$table->addCell($col3Width, ['valign' => 'center', 'bgColor' => '#4169E1'])->addText('Jawaban Salah', ['bold' => true, 'name' => 'Visby Round CF', 'size' => 10, 'color' => '#ffffff'], ['alignment' => Jc::CENTER]);
|
||||
$table->addCell($col4Width, ['valign' => 'center', 'bgColor' => '#4169E1'])->addText('Tidak Menjawab', ['bold' => true, 'name' => 'Visby Round CF', 'size' => 10, 'color' => '#ffffff'], ['alignment' => Jc::CENTER]);
|
||||
$table->addCell($col5Width, ['valign' => 'center', 'bgColor' => '#4169E1'])->addText('% Jawaban Benar', ['bold' => true, 'name' => 'Visby Round CF', 'size' => 10, 'color' => '#ffffff'], ['alignment' => Jc::CENTER]);
|
||||
|
||||
// TWK
|
||||
$table->addRow();
|
||||
$table->addCell($col1Width, ['valign' => 'center', 'bgColor' => '#f0f3fd', 'borderBottomSize' => 0, 'borderBottomStyle' => Border::NONE])->addText("Tes Wawasan Kebangsaan", ['bold' => true, 'name' => 'Visby Round CF', 'size' => 9, 'color' => '#072442']);
|
||||
$table->addCell($col2Width, ['valign' => 'center', 'bgColor' => '#f0f3fd', 'borderBottomSize' => 0, 'borderBottomStyle' => Border::NONE])->addText("17", ['bold' => true, 'name' => 'Visby Round CF', 'size' => 9, 'color' => '#072442'], ['alignment' => Jc::CENTER]);
|
||||
$table->addCell($col3Width, ['valign' => 'center', 'bgColor' => '#f0f3fd', 'borderBottomSize' => 0, 'borderBottomStyle' => Border::NONE])->addText("13", ['bold' => true, 'name' => 'Visby Round CF', 'size' => 9, 'color' => '#072442'], ['alignment' => Jc::CENTER]);
|
||||
$table->addCell($col4Width, ['valign' => 'center', 'bgColor' => '#f0f3fd', 'borderBottomSize' => 0, 'borderBottomStyle' => Border::NONE])->addText("0", ['bold' => true, 'name' => 'Visby Round CF', 'size' => 9, 'color' => '#072442'], ['alignment' => Jc::CENTER]);
|
||||
$table->addCell($col5Width, ['valign' => 'center', 'bgColor' => '#f0f3fd', 'borderBottomSize' => 0, 'borderBottomStyle' => Border::NONE])->addText("56%", ['bold' => true, 'name' => 'Visby Round CF', 'size' => 9, 'color' => '#072442'], ['alignment' => Jc::CENTER]);
|
||||
|
||||
$dataTwk = ['Nasionalisme', 'Integritas', 'Bela Negara', 'Pilar Negara', 'Bahasa Indonesia', 'Bahasa Bali'];
|
||||
foreach ($dataTwk as $key => $dt) {
|
||||
$isLast = false;
|
||||
if (count($dataTwk) == $key + 1) {
|
||||
$isLast = true;
|
||||
}
|
||||
|
||||
$table->addRow();
|
||||
$table->addCell($col1Width, ['valign' => 'center', 'bgColor' => '#f0f3fd', 'borderTopSize' => 0, 'borderBottomSize' => $isLast ? 10 : 0, 'borderTopStyle' => Border::NONE, 'borderBottomStyle' => $isLast ? Border::SINGLE : Border::NONE])->addText(" " . mb_chr(8226, 'UTF-8') . " " . $dt, ['bold' => false, 'name' => 'Visby Round CF', 'size' => 8, 'color' => '#072442']);
|
||||
$table->addCell($col2Width, ['valign' => 'center', 'bgColor' => '#f0f3fd', 'borderTopSize' => 0, 'borderBottomSize' => $isLast ? 10 : 0, 'borderTopStyle' => Border::NONE, 'borderBottomStyle' => $isLast ? Border::SINGLE : Border::NONE])->addText("17", ['bold' => false, 'name' => 'Visby Round CF', 'size' => 8, 'color' => '#072442'], ['alignment' => Jc::CENTER]);
|
||||
$table->addCell($col3Width, ['valign' => 'center', 'bgColor' => '#f0f3fd', 'borderTopSize' => 0, 'borderBottomSize' => $isLast ? 10 : 0, 'borderTopStyle' => Border::NONE, 'borderBottomStyle' => $isLast ? Border::SINGLE : Border::NONE])->addText("13", ['bold' => false, 'name' => 'Visby Round CF', 'size' => 8, 'color' => '#072442'], ['alignment' => Jc::CENTER]);
|
||||
$table->addCell($col4Width, ['valign' => 'center', 'bgColor' => '#f0f3fd', 'borderTopSize' => 0, 'borderBottomSize' => $isLast ? 10 : 0, 'borderTopStyle' => Border::NONE, 'borderBottomStyle' => $isLast ? Border::SINGLE : Border::NONE])->addText("0", ['bold' => false, 'name' => 'Visby Round CF', 'size' => 8, 'color' => '#072442'], ['alignment' => Jc::CENTER]);
|
||||
$table->addCell($col5Width, ['valign' => 'center', 'bgColor' => '#f0f3fd', 'borderTopSize' => 0, 'borderBottomSize' => $isLast ? 10 : 0, 'borderTopStyle' => Border::NONE, 'borderBottomStyle' => $isLast ? Border::SINGLE : Border::NONE])->addText("56%", ['bold' => false, 'name' => 'Visby Round CF', 'size' => 8, 'color' => '#072442'], ['alignment' => Jc::CENTER]);
|
||||
}
|
||||
|
||||
$dataTkp = ['Verbal Analogi'];
|
||||
|
||||
$proc->setComplexValue('table', $table);
|
||||
|
||||
$proc->saveAs(rootPath("examples/Raport.docx"));
|
||||
|
||||
return rootPath("examples/Raport.docx");
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
namespace MenulisAi\Pdfgen;
|
||||
|
||||
use MenulisAi\Pdfgen\Command\Generate;
|
||||
use MenulisAi\Pdfgen\Command\GenerateEbook;
|
||||
use MenulisAi\Pdfgen\Command\GenerateTest;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
class Register
|
||||
@@ -13,7 +14,8 @@ class Register
|
||||
public function init(): array
|
||||
{
|
||||
return [
|
||||
new Generate("generate:ebook")
|
||||
new GenerateEbook("generate:ebook"),
|
||||
new GenerateTest("generate:test")
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
BIN
src/Template/Doc1.docx
Normal file
BIN
src/Template/Doc1.docx
Normal file
Binary file not shown.
BIN
src/Template/Raport.docx
Normal file
BIN
src/Template/Raport.docx
Normal file
Binary file not shown.
BIN
src/Template/Raport.odt
Normal file
BIN
src/Template/Raport.odt
Normal file
Binary file not shown.
Reference in New Issue
Block a user