Update tools controllers and assets
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
- If a task changes live DB objects such as table schema, trigger, stored procedure, or function, always add a SQL record file under `sql/manual_changes/`.
|
||||
- Name the SQL record file with the pattern `YYYY-MM-DD-<commit-message-stem>.sql`.
|
||||
- The SQL record file must include the actual SQL change that was applied, not just a note.
|
||||
- Before every `commit` and `push`, always check first whether local branch needs to pull/rebase from remote.
|
||||
|
||||
## graphify
|
||||
|
||||
|
||||
20
CLAUDE.md
Normal file
20
CLAUDE.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Repo Working Notes
|
||||
|
||||
- Verify the actual file, class name, and call site before changing a library/controller reference.
|
||||
- If a class load error appears, check the existing library file and the current repo usage pattern first.
|
||||
- Do not swap to a different library name on assumption alone.
|
||||
- Keep fixes minimal and local unless the user asks for a broader refactor.
|
||||
- If a task changes live DB objects such as table schema, trigger, stored procedure, or function, always add a SQL record file under `sql/manual_changes/`.
|
||||
- Name the SQL record file with the pattern `YYYY-MM-DD-<commit-message-stem>.sql`.
|
||||
- The SQL record file must include the actual SQL change that was applied, not just a note.
|
||||
- Before every `commit` and `push`, always check first whether local branch needs to pull/rebase from remote.
|
||||
|
||||
## graphify
|
||||
|
||||
This project has a graphify knowledge graph at graphify-out/.
|
||||
|
||||
Rules:
|
||||
- Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure
|
||||
- If graphify-out/wiki/index.md exists, navigate it instead of reading raw files
|
||||
- For cross-module "how does X relate to Y" questions, prefer `graphify query "<question>"`, `graphify path "<A>" "<B>"`, or `graphify explain "<concept>"` over grep — these traverse the graph's EXTRACTED + INFERRED edges instead of scanning files
|
||||
- After modifying code files in this session, run `graphify update .` to keep the graph current (AST-only, no API cost)
|
||||
706
application/controllers/tools/Inform_consent.php
Normal file
706
application/controllers/tools/Inform_consent.php
Normal file
@@ -0,0 +1,706 @@
|
||||
<?php
|
||||
|
||||
class Inform_consent extends MY_Controller
|
||||
{
|
||||
private $pageContentBottom = 272.0;
|
||||
private $footerY = 286.0;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->db_onedev = $this->load->database('onedev', true);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$this->sys_ok([
|
||||
'message' => 'Use /tools/inform_consent/pdf?T_OrderHeaderID=<id>'
|
||||
]);
|
||||
}
|
||||
|
||||
public function pdf()
|
||||
{
|
||||
try {
|
||||
$orderHeaderId = intval($this->input->get('T_OrderHeaderID', true));
|
||||
if ($orderHeaderId <= 0) {
|
||||
$orderHeaderId = intval($this->input->get('PID', true));
|
||||
}
|
||||
if ($orderHeaderId <= 0) {
|
||||
$this->sys_error('T_OrderHeaderID mandatory');
|
||||
return;
|
||||
}
|
||||
|
||||
$patient = $this->get_patient_data($orderHeaderId);
|
||||
if (!$patient) {
|
||||
$this->sys_error('Order not found');
|
||||
return;
|
||||
}
|
||||
|
||||
$consent = $this->get_consent_content();
|
||||
$printBy = trim((string)$this->input->get('username', true));
|
||||
if ($printBy === '') {
|
||||
$printBy = 'ADMIN';
|
||||
}
|
||||
$printDate = date('M j, Y g:i A');
|
||||
|
||||
require_once APPPATH . 'third_party/fpdf/fpdf.php';
|
||||
$pdf = new FPDF('P', 'mm', 'A4');
|
||||
$pdf->SetAutoPageBreak(false);
|
||||
$pdf->SetMargins(10, 10, 10);
|
||||
|
||||
$remainingBlocks = $this->render_first_page($pdf, $patient, $consent, $printBy, $printDate);
|
||||
$this->render_second_page($pdf, $patient, $remainingBlocks, $printBy, $printDate);
|
||||
|
||||
header('Content-Type: application/pdf');
|
||||
header('Content-Disposition: inline; filename="inform_consent_' . $orderHeaderId . '.pdf"');
|
||||
echo $pdf->Output('S');
|
||||
} catch (Exception $e) {
|
||||
$this->sys_error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function get_patient_data($orderHeaderId)
|
||||
{
|
||||
$sql = "SELECT
|
||||
h.T_OrderHeaderID,
|
||||
h.T_OrderHeaderDate,
|
||||
DATE_FORMAT(h.T_OrderHeaderDate, '%d-%m-%Y') as tanggal,
|
||||
DATE_FORMAT(h.T_OrderHeaderDate, '%H:%i') as jam,
|
||||
p.M_PatientID,
|
||||
p.M_PatientNoReg,
|
||||
CONCAT(
|
||||
IF(TRIM(IFNULL(t.M_TitleName,''))='', '', CONCAT(TRIM(IFNULL(t.M_TitleName,'')), '. ')),
|
||||
TRIM(IFNULL(p.M_PatientPrefix,'')), ' ', TRIM(IFNULL(p.M_PatientName,'')), ' ', TRIM(IFNULL(p.M_PatientSuffix,''))
|
||||
) AS patient_name,
|
||||
s.M_SexCode,
|
||||
IFNULL(p.M_PatientPOB,'') as pob,
|
||||
DATE_FORMAT(p.M_PatientDOB, '%d-%m-%Y') as dob,
|
||||
IFNULL(pa.M_PatientAddressDescription,'') as alamat,
|
||||
IFNULL(p.M_PatientHP,'') as phone,
|
||||
IFNULL(c.M_CompanyName,'') as company_name,
|
||||
(
|
||||
SELECT ps.Patient_SignatureUrl
|
||||
FROM patient_signature ps
|
||||
WHERE ps.Patient_SignatureM_PatientID = p.M_PatientID
|
||||
AND ps.Patient_SignatureIsActive = 'Y'
|
||||
ORDER BY ps.Patient_SignatureID DESC
|
||||
LIMIT 1
|
||||
) AS signature_url
|
||||
FROM t_orderheader h
|
||||
JOIN m_patient p ON p.M_PatientID = h.T_OrderHeaderM_PatientID
|
||||
LEFT JOIN m_title t ON t.M_TitleID = p.M_PatientM_TitleID
|
||||
LEFT JOIN m_sex s ON s.M_SexID = p.M_PatientM_SexID
|
||||
LEFT JOIN m_company c ON c.M_CompanyID = h.T_OrderHeaderM_CompanyID
|
||||
LEFT JOIN m_patientaddress pa ON pa.M_PatientAddressM_PatientID = p.M_PatientID
|
||||
AND pa.M_PatientAddressNote = 'Utama'
|
||||
AND pa.M_PatientAddressIsActive = 'Y'
|
||||
WHERE h.T_OrderHeaderID = ?
|
||||
LIMIT 1";
|
||||
$qry = $this->db_onedev->query($sql, [$orderHeaderId]);
|
||||
if (!$qry) {
|
||||
return false;
|
||||
}
|
||||
return $qry->row_array();
|
||||
}
|
||||
|
||||
private function get_consent_content()
|
||||
{
|
||||
$sql = "SELECT M_InformConsentContent
|
||||
FROM m_informconsent
|
||||
WHERE M_InformConsentType = 'umum' AND M_InformConsentIsActive = 'Y'
|
||||
LIMIT 1";
|
||||
$qry = $this->db_onedev->query($sql);
|
||||
if (!$qry || !$qry->row_array()) {
|
||||
return '';
|
||||
}
|
||||
return (string)$qry->row_array()['M_InformConsentContent'];
|
||||
}
|
||||
|
||||
private function render_first_page($pdf, $patient, $consentHtml, $printBy, $printDate)
|
||||
{
|
||||
$pdf->AddPage();
|
||||
$this->render_header($pdf);
|
||||
|
||||
$pdf->SetFont('Arial', 'B', 10);
|
||||
$pdf->SetFillColor(220, 220, 220);
|
||||
$pdf->SetXY(10, 42);
|
||||
$pdf->Cell(190, 8, 'PENGKAJIAN DATA UMUM PASIEN', 1, 1, 'C', true);
|
||||
|
||||
$pdf->SetFont('Arial', '', 8);
|
||||
$pdf->SetX(10);
|
||||
$pdf->Cell(145, 6, 'Tanggal : ' . $patient['tanggal'], 1, 0, 'L');
|
||||
$pdf->Cell(45, 6, 'Jam : ' . $patient['jam'], 1, 1, 'L');
|
||||
|
||||
$pdf->SetFont('Arial', 'B', 10);
|
||||
$pdf->SetX(10);
|
||||
$pdf->Cell(190, 8, 'IDENTITAS PASIEN', 1, 1, 'L');
|
||||
$pdf->SetFont('Arial', 'I', 8);
|
||||
$pdf->SetX(10);
|
||||
$pdf->Cell(190, 5, '(Diisi sesuai Kartu Tanda Pengenal Pasien yang masih berlaku : KTP/ KK/ SIM/ Kartu Pelajar/ dsb)', 1, 1, 'L');
|
||||
|
||||
$boxStart = $pdf->GetY();
|
||||
$pdf->SetFont('Arial', '', 8);
|
||||
$this->kv($pdf, 'Nomor RM', $patient['M_PatientNoReg']);
|
||||
$this->kv($pdf, 'Nama', trim(preg_replace('/\s+/', ' ', $patient['patient_name'])));
|
||||
$this->kv($pdf, 'Jenis Kelamin', $patient['M_SexCode']);
|
||||
$this->kv($pdf, 'Tempat/Tgl Lahir', trim($patient['pob']) . ' / ' . trim($patient['dob']));
|
||||
$this->kv($pdf, 'Alamat', $patient['alamat']);
|
||||
$this->kv($pdf, 'No. Telepon', $patient['phone']);
|
||||
$this->kv($pdf, 'Status Pembiayaan', 'Umum / BPJS / PT..................................................');
|
||||
$boxEnd = $pdf->GetY();
|
||||
$pdf->Rect(10, $boxStart, 190, max(8, $boxEnd - $boxStart));
|
||||
|
||||
$pdf->Ln(4);
|
||||
$pdf->SetFont('Arial', 'B', 10);
|
||||
$pdf->SetFillColor(220, 220, 220);
|
||||
$pdf->SetX(10);
|
||||
$pdf->Cell(190, 7, 'PERSETUJUAN UMUM/ GENERAL CONSENT', 1, 1, 'C', true);
|
||||
$pdf->SetFont('Arial', 'BI', 8);
|
||||
$pdf->SetX(10);
|
||||
$pdf->Cell(190, 6, 'PASIEN/WALI PASIEN MEMBACA, MEMAHAMI DAN MENGISI INFORMASI BERIKUT', 1, 1, 'C');
|
||||
|
||||
$pdf->SetFont('Arial', '', 8);
|
||||
$pdf->SetX(10);
|
||||
$pdf->Cell(190, 6, 'Yang bertanda tangan di bawah ini, saya :', 1, 1, 'L');
|
||||
|
||||
$box2Start = $pdf->GetY();
|
||||
$this->kv($pdf, 'Nama', trim(preg_replace('/\s+/', ' ', $patient['patient_name'])));
|
||||
$this->kv($pdf, 'Jenis Kelamin', $patient['M_SexCode']);
|
||||
$this->kv($pdf, 'Tempat/Tgl Lahir', trim($patient['pob']) . ' / ' . trim($patient['dob']));
|
||||
$this->kv($pdf, 'Alamat', $patient['alamat']);
|
||||
$this->kv($pdf, 'No.Telepon', $patient['phone']);
|
||||
$this->kv($pdf, 'Bertindak atas', 'Diri Saya Sendiri/ Wali / Orang Tua / Anak / Saudara .*');
|
||||
$contentBoxStart = $box2Start;
|
||||
|
||||
$pdf->Ln(3);
|
||||
$pdf->SetFont('Arial', 'B', 8);
|
||||
$pdf->SetX(18);
|
||||
$pdf->Cell(182, 5, '1. PERSETUJUAN UNTUK PEMERIKSAAN DAN PERAWATAN', 0, 1, 'L');
|
||||
|
||||
$blocks = $this->html_to_blocks($consentHtml);
|
||||
$lineH = 4.6;
|
||||
$splitIndex = 0;
|
||||
|
||||
$pdf->SetFont('Arial', '', 8);
|
||||
for ($i = 0; $i < count($blocks); $i++) {
|
||||
$block = $blocks[$i];
|
||||
$blockH = $this->measure_block_height($pdf, $block, 22, 176, $lineH);
|
||||
if (($pdf->GetY() + $blockH) > $this->pageContentBottom) {
|
||||
break;
|
||||
}
|
||||
$this->render_block($pdf, $block, 22, 176, $lineH);
|
||||
$splitIndex = $i + 1;
|
||||
}
|
||||
|
||||
$contentBoxEnd = min($this->pageContentBottom, $pdf->GetY() + 2);
|
||||
$pdf->Rect(10, $contentBoxStart, 190, max(10, $contentBoxEnd - $contentBoxStart));
|
||||
|
||||
$this->draw_print_footer($pdf, $printBy, $printDate, 1, 2);
|
||||
return array_slice($blocks, $splitIndex);
|
||||
}
|
||||
|
||||
private function render_second_page($pdf, $patient, $remainingBlocks, $printBy, $printDate)
|
||||
{
|
||||
$pdf->AddPage();
|
||||
$this->render_header($pdf);
|
||||
|
||||
$boxStartY = 42;
|
||||
$pdf->SetY($boxStartY);
|
||||
$pdf->SetFont('Arial', '', 8);
|
||||
$lineH = 4.6;
|
||||
foreach ($remainingBlocks as $block) {
|
||||
$blockH = $this->measure_block_height($pdf, $block, 22, 176, $lineH);
|
||||
if (($pdf->GetY() + $blockH) > 248) {
|
||||
break;
|
||||
}
|
||||
$this->render_block($pdf, $block, 22, 176, $lineH);
|
||||
}
|
||||
|
||||
$top = $pdf->GetY() + 2;
|
||||
$signTop = $top;
|
||||
$signBoxHeight = 44;
|
||||
$signBottom = $signTop + $signBoxHeight;
|
||||
|
||||
$pdf->Rect(12, $signTop, 186, $signBoxHeight);
|
||||
|
||||
$rightX = 132;
|
||||
$rightW = 64;
|
||||
$pdf->SetFont('Arial', '', 9);
|
||||
$pdf->SetXY($rightX, $signTop + 2);
|
||||
$pdf->Cell($rightW, 6, 'Semarang, ' . $patient['tanggal'], 0, 1, 'L');
|
||||
|
||||
$pdf->SetXY(14, $signBottom - 29);
|
||||
$pdf->Cell(40, 6, 'Petugas', 0, 1, 'C');
|
||||
|
||||
$pdf->SetXY($rightX, $signBottom - 29);
|
||||
$pdf->Cell($rightW, 6, 'Pasien/ Wali Pasien', 0, 1, 'L');
|
||||
|
||||
$pdf->SetXY(16, $signBottom - 9);
|
||||
$pdf->Cell(62, 6, '........................................', 0, 1, 'L');
|
||||
|
||||
$signaturePath = $this->resolve_signature_path(isset($patient['signature_url']) ? $patient['signature_url'] : '');
|
||||
if ($signaturePath !== null) {
|
||||
$pdf->Image($signaturePath, $rightX - 6, $signBottom - 23, 42, 12);
|
||||
}
|
||||
$this->draw_full_name_block($pdf, $rightX, $signBottom - 9, $rightW, trim(preg_replace('/\s+/', ' ', $patient['patient_name'])));
|
||||
|
||||
$boxEndY = min($this->pageContentBottom, $signBottom + 2);
|
||||
$pdf->Rect(10, $boxStartY, 190, max(10, $boxEndY - $boxStartY));
|
||||
|
||||
$this->draw_print_footer($pdf, $printBy, $printDate, 2, 2);
|
||||
}
|
||||
|
||||
private function draw_print_footer($pdf, $printBy, $printDate, $page, $total)
|
||||
{
|
||||
$y = $this->footerY;
|
||||
$pdf->SetFont('Times', '', 7);
|
||||
|
||||
$pdf->SetXY(14, $y);
|
||||
$pdf->Cell(22, 4, 'Print Oleh :', 0, 0, 'L');
|
||||
$pdf->Cell(50, 4, $this->safe_text($printBy), 0, 0, 'L');
|
||||
$pdf->Cell(10, 4, (string)$page, 0, 0, 'C');
|
||||
$pdf->Cell(6, 4, '/', 0, 0, 'C');
|
||||
$pdf->Cell(10, 4, (string)$total, 0, 0, 'C');
|
||||
|
||||
$date = $this->safe_text($printDate);
|
||||
$dateW = $pdf->GetStringWidth($date);
|
||||
$rightMargin = 196;
|
||||
$xDate = max(120, $rightMargin - $dateW);
|
||||
$pdf->SetXY($xDate, $y);
|
||||
$pdf->Cell($dateW + 1, 4, $date, 0, 1, 'L');
|
||||
}
|
||||
|
||||
private function render_header($pdf)
|
||||
{
|
||||
$logoPath = APPPATH . '../assets/images/logo-ibl.png';
|
||||
if (is_file($logoPath)) {
|
||||
$pdf->Image($logoPath, 14, 10, 56, 12);
|
||||
} else {
|
||||
$pdf->SetFont('Arial', 'B', 16);
|
||||
$pdf->SetTextColor(220, 0, 0);
|
||||
$pdf->SetXY(14, 12);
|
||||
$pdf->Cell(80, 8, 'KLINIK IBL', 0, 1, 'L');
|
||||
$pdf->SetTextColor(0, 0, 0);
|
||||
}
|
||||
|
||||
$pdf->SetFont('Arial', '', 10);
|
||||
$pdf->SetXY(170, 20);
|
||||
$pdf->Cell(20, 6, 'RM. 01', 0, 1, 'L');
|
||||
}
|
||||
|
||||
private function kv($pdf, $label, $value)
|
||||
{
|
||||
$x = 12;
|
||||
$labelW = 35;
|
||||
$colonW = 4;
|
||||
$valueW = 149;
|
||||
|
||||
$pdf->SetX($x);
|
||||
$pdf->Cell($labelW, 5, $this->safe_text($label), 0, 0, 'L');
|
||||
$pdf->Cell($colonW, 5, ':', 0, 0, 'C');
|
||||
$pdf->MultiCell($valueW, 5, $this->safe_text($value), 0, 'L');
|
||||
}
|
||||
|
||||
private function html_to_blocks($html)
|
||||
{
|
||||
$input = (string)$html;
|
||||
$input = str_replace(['\\r\\n', '\\n', '\\r'], "\n", $input);
|
||||
$input = str_replace(["\r\n", "\r"], "\n", $input);
|
||||
|
||||
if (!class_exists('DOMDocument')) {
|
||||
return $this->html_to_blocks_fallback($input);
|
||||
}
|
||||
|
||||
libxml_use_internal_errors(true);
|
||||
$dom = new DOMDocument('1.0', 'UTF-8');
|
||||
$wrapped = '<!DOCTYPE html><html><body>' . $input . '</body></html>';
|
||||
$ok = $dom->loadHTML(mb_convert_encoding($wrapped, 'HTML-ENTITIES', 'UTF-8'));
|
||||
libxml_clear_errors();
|
||||
|
||||
if (!$ok) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$blocks = [];
|
||||
$ctx = ['indent' => 0, 'listType' => null, 'index' => 1];
|
||||
$body = $dom->getElementsByTagName('body')->item(0);
|
||||
if (!$body) {
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ($body->childNodes as $node) {
|
||||
$this->walk_html_node($node, $blocks, $ctx);
|
||||
}
|
||||
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
private function html_to_blocks_fallback($input)
|
||||
{
|
||||
$blocks = [];
|
||||
$s = (string)$input;
|
||||
$s = preg_replace('/\\\\r\\\\n|\\\\n|\\\\r/', "\n", $s);
|
||||
$s = preg_replace('/<br\\s*\\/?>/i', "\n", $s);
|
||||
$s = preg_replace('/<\\/(div|p|h[1-6]|li)>/i', "$0\n", $s);
|
||||
|
||||
preg_match_all('/<(h[1-6]|p|li)[^>]*>(.*?)<\\/\\1>/is', $s, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $m) {
|
||||
$tag = strtolower($m[1]);
|
||||
$inner = (string)$m[2];
|
||||
|
||||
// remove nested list blocks inside current node to avoid duplicate render
|
||||
$inner = preg_replace('/<(ul|ol)[^>]*>.*?<\\/\\1>/is', '', $inner);
|
||||
$plain = trim(preg_replace('/\\s+/', ' ', html_entity_decode(strip_tags($inner), ENT_QUOTES | ENT_HTML5, 'UTF-8')));
|
||||
if ($plain === '' || $plain === ':') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$indent = 0;
|
||||
$style = '';
|
||||
$text = $plain;
|
||||
|
||||
if ($tag === 'h1' || $tag === 'h2' || $tag === 'h3' || $tag === 'h4' || $tag === 'h5' || $tag === 'h6') {
|
||||
$style = 'B';
|
||||
$indent = 0;
|
||||
} elseif ($tag === 'li') {
|
||||
$indent = 8;
|
||||
$text = '• ' . $plain;
|
||||
} elseif ($tag === 'p') {
|
||||
if (stripos($inner, '<strong') !== false || preg_match('/^(hak pasien|kewajiban pasien)\\s*:/i', $plain)) {
|
||||
$style = 'B';
|
||||
}
|
||||
if (preg_match('/^[a-z]\\./i', $plain)) {
|
||||
$indent = 4;
|
||||
}
|
||||
}
|
||||
|
||||
$blocks[] = [
|
||||
'text' => $text,
|
||||
'indent' => $indent,
|
||||
'style' => $style
|
||||
];
|
||||
}
|
||||
|
||||
if (empty($blocks)) {
|
||||
$lines = preg_split('/\\n+/', trim(html_entity_decode(strip_tags($s), ENT_QUOTES | ENT_HTML5, 'UTF-8')));
|
||||
foreach ($lines as $line) {
|
||||
$line = trim(preg_replace('/\\s+/', ' ', (string)$line));
|
||||
if ($line === '') {
|
||||
continue;
|
||||
}
|
||||
$blocks[] = ['text' => $line, 'indent' => 0, 'style' => ''];
|
||||
}
|
||||
}
|
||||
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
private function walk_html_node($node, &$blocks, $ctx)
|
||||
{
|
||||
if (!$node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($node->nodeType === XML_TEXT_NODE) {
|
||||
$text = trim(preg_replace('/\s+/', ' ', html_entity_decode($node->nodeValue, ENT_QUOTES | ENT_HTML5, 'UTF-8')));
|
||||
if ($text !== '') {
|
||||
$blocks[] = [
|
||||
'text' => $text,
|
||||
'indent' => $ctx['indent'],
|
||||
'style' => ''
|
||||
];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($node->nodeType !== XML_ELEMENT_NODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tag = strtolower($node->nodeName);
|
||||
if ($tag === 'br') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($tag, ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'], true)) {
|
||||
$text = $this->node_plain_text($node);
|
||||
if ($text !== '') {
|
||||
$blocks[] = [
|
||||
'text' => $text,
|
||||
'indent' => max(0, $ctx['indent']),
|
||||
'style' => 'B'
|
||||
];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($tag === 'p') {
|
||||
$text = $this->node_plain_text($node);
|
||||
if ($text !== '') {
|
||||
$isBold = $this->node_has_tag($node, 'strong');
|
||||
$blocks[] = [
|
||||
'text' => $text,
|
||||
'indent' => max(0, $ctx['indent']),
|
||||
'style' => $isBold ? 'B' : ''
|
||||
];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($tag === 'ul' || $tag === 'ol') {
|
||||
$childCtx = [
|
||||
'indent' => $ctx['indent'] + 8,
|
||||
'listType' => $tag,
|
||||
'index' => 1
|
||||
];
|
||||
foreach ($node->childNodes as $child) {
|
||||
$this->walk_html_node($child, $blocks, $childCtx);
|
||||
if ($tag === 'ol' && $child->nodeType === XML_ELEMENT_NODE && strtolower($child->nodeName) === 'li') {
|
||||
$childCtx['index']++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($tag === 'li') {
|
||||
$prefix = '• ';
|
||||
if ($ctx['listType'] === 'ol') {
|
||||
$prefix = $ctx['index'] . '. ';
|
||||
}
|
||||
|
||||
$firstText = $this->node_direct_text($node);
|
||||
if ($firstText !== '') {
|
||||
$blocks[] = [
|
||||
'text' => $prefix . $firstText,
|
||||
'indent' => max(0, $ctx['indent']),
|
||||
'style' => ''
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($node->childNodes as $child) {
|
||||
if ($child->nodeType === XML_ELEMENT_NODE) {
|
||||
$childTag = strtolower($child->nodeName);
|
||||
if ($childTag === 'ul' || $childTag === 'ol' || $childTag === 'p') {
|
||||
$nestedCtx = [
|
||||
'indent' => $ctx['indent'] + 8,
|
||||
'listType' => $childTag === 'ol' ? 'ol' : ($childTag === 'ul' ? 'ul' : null),
|
||||
'index' => 1
|
||||
];
|
||||
$this->walk_html_node($child, $blocks, $nestedCtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($node->childNodes as $child) {
|
||||
$this->walk_html_node($child, $blocks, $ctx);
|
||||
}
|
||||
}
|
||||
|
||||
private function node_plain_text($node)
|
||||
{
|
||||
$txt = html_entity_decode($node->textContent, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$txt = preg_replace('/\s+/', ' ', (string)$txt);
|
||||
return trim($txt);
|
||||
}
|
||||
|
||||
private function node_direct_text($node)
|
||||
{
|
||||
$parts = [];
|
||||
foreach ($node->childNodes as $child) {
|
||||
if ($child->nodeType === XML_TEXT_NODE) {
|
||||
$t = trim(preg_replace('/\s+/', ' ', html_entity_decode($child->nodeValue, ENT_QUOTES | ENT_HTML5, 'UTF-8')));
|
||||
if ($t !== '') {
|
||||
$parts[] = $t;
|
||||
}
|
||||
}
|
||||
if ($child->nodeType === XML_ELEMENT_NODE && strtolower($child->nodeName) === 'strong') {
|
||||
$t = $this->node_plain_text($child);
|
||||
if ($t !== '') {
|
||||
$parts[] = $t;
|
||||
}
|
||||
}
|
||||
}
|
||||
return trim(implode(' ', $parts));
|
||||
}
|
||||
|
||||
private function node_has_tag($node, $tagName)
|
||||
{
|
||||
if (!$node || !$node->hasChildNodes()) {
|
||||
return false;
|
||||
}
|
||||
foreach ($node->childNodes as $child) {
|
||||
if ($child->nodeType === XML_ELEMENT_NODE && strtolower($child->nodeName) === strtolower($tagName)) {
|
||||
return true;
|
||||
}
|
||||
if ($this->node_has_tag($child, $tagName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function measure_block_height($pdf, $block, $baseX, $baseW, $lineH)
|
||||
{
|
||||
$indent = isset($block['indent']) ? floatval($block['indent']) : 0;
|
||||
$text = isset($block['text']) ? (string)$block['text'] : '';
|
||||
$w = max(20, $baseW - $indent);
|
||||
$txt = $this->safe_text($text);
|
||||
$lines = $this->nb_lines($pdf, $w, $txt);
|
||||
if ($lines < 1) {
|
||||
$lines = 1;
|
||||
}
|
||||
return $lines * $lineH;
|
||||
}
|
||||
|
||||
private function nb_lines($pdf, $w, $txt)
|
||||
{
|
||||
$text = (string)$txt;
|
||||
if ($text === '') {
|
||||
return 1;
|
||||
}
|
||||
$maxWidth = max(1.0, $w - 1.0);
|
||||
$paragraphs = explode("\n", str_replace("\r", '', $text));
|
||||
$lines = 0;
|
||||
|
||||
foreach ($paragraphs as $p) {
|
||||
$p = trim($p);
|
||||
if ($p === '') {
|
||||
$lines++;
|
||||
continue;
|
||||
}
|
||||
$words = preg_split('/\s+/', $p);
|
||||
$line = '';
|
||||
foreach ($words as $word) {
|
||||
$candidate = ($line === '') ? $word : ($line . ' ' . $word);
|
||||
if ($pdf->GetStringWidth($candidate) <= $maxWidth) {
|
||||
$line = $candidate;
|
||||
} else {
|
||||
if ($line !== '') {
|
||||
$lines++;
|
||||
$line = $word;
|
||||
} else {
|
||||
$lines++;
|
||||
$line = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($line !== '') {
|
||||
$lines++;
|
||||
}
|
||||
}
|
||||
return max(1, $lines);
|
||||
}
|
||||
|
||||
private function render_block($pdf, $block, $baseX, $baseW, $lineH)
|
||||
{
|
||||
$indent = isset($block['indent']) ? floatval($block['indent']) : 0;
|
||||
$text = isset($block['text']) ? (string)$block['text'] : '';
|
||||
$style = isset($block['style']) ? (string)$block['style'] : '';
|
||||
$w = max(20, $baseW - $indent);
|
||||
|
||||
$pdf->SetFont('Arial', $style, 8);
|
||||
$pdf->SetX($baseX + $indent);
|
||||
$pdf->MultiCell($w, $lineH, $this->safe_text($text), 0, 'L');
|
||||
}
|
||||
|
||||
private function safe_text($text)
|
||||
{
|
||||
$t = (string)$text;
|
||||
return iconv('UTF-8', 'windows-1252//TRANSLIT', $t);
|
||||
}
|
||||
|
||||
private function draw_full_name_block($pdf, $x, $yBottom, $w, $name)
|
||||
{
|
||||
$text = $this->safe_text($name);
|
||||
$pdf->SetFont('Arial', '', 9);
|
||||
$lines = $this->wrap_text_lines($pdf, $text, $w);
|
||||
if (empty($lines)) {
|
||||
$lines = ['-'];
|
||||
}
|
||||
|
||||
$lineH = 4.6;
|
||||
$blockH = count($lines) * $lineH;
|
||||
$topY = $yBottom - $blockH + 5.5;
|
||||
if ($topY < 10) {
|
||||
$topY = 10;
|
||||
}
|
||||
|
||||
$pdf->SetXY($x, $topY);
|
||||
foreach ($lines as $i => $line) {
|
||||
$pdf->Cell($w, $lineH, $line, 0, 2, 'L');
|
||||
}
|
||||
}
|
||||
|
||||
private function wrap_text_lines($pdf, $text, $w)
|
||||
{
|
||||
$words = preg_split('/\s+/', trim((string)$text));
|
||||
$lines = [];
|
||||
$line = '';
|
||||
foreach ($words as $word) {
|
||||
if ($word === '') {
|
||||
continue;
|
||||
}
|
||||
$try = ($line === '') ? $word : ($line . ' ' . $word);
|
||||
if ($pdf->GetStringWidth($try) <= $w) {
|
||||
$line = $try;
|
||||
} else {
|
||||
if ($line !== '') {
|
||||
$lines[] = $line;
|
||||
}
|
||||
$line = $word;
|
||||
}
|
||||
}
|
||||
if ($line !== '') {
|
||||
$lines[] = $line;
|
||||
}
|
||||
return $lines;
|
||||
}
|
||||
|
||||
private function resolve_signature_path($signatureUrl)
|
||||
{
|
||||
$url = trim((string)$signatureUrl);
|
||||
if ($url === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (preg_match('#^https?://#i', $url)) {
|
||||
$tmp = sys_get_temp_dir() . '/sig_' . md5($url) . '.png';
|
||||
if (!is_file($tmp)) {
|
||||
$ctx = stream_context_create([
|
||||
'http' => ['timeout' => 3],
|
||||
'ssl' => ['verify_peer' => false, 'verify_peer_name' => false]
|
||||
]);
|
||||
$bin = @file_get_contents($url, false, $ctx);
|
||||
if ($bin !== false && strlen($bin) > 0) {
|
||||
@file_put_contents($tmp, $bin);
|
||||
}
|
||||
}
|
||||
return is_file($tmp) ? $tmp : null;
|
||||
}
|
||||
|
||||
if (strpos($url, '/') === 0) {
|
||||
if (strpos($url, '/one-media/') === 0) {
|
||||
$absMedia = '/home/one/project' . $url;
|
||||
if (is_file($absMedia)) {
|
||||
return $absMedia;
|
||||
}
|
||||
$httpUrl = 'http://devone.aplikasi.web.id' . $url;
|
||||
return $this->resolve_signature_path($httpUrl);
|
||||
}
|
||||
|
||||
$abs = FCPATH . ltrim($url, '/');
|
||||
if (is_file($abs)) {
|
||||
return $abs;
|
||||
}
|
||||
}
|
||||
|
||||
$abs2 = FCPATH . 'assets/uploads/signature/' . ltrim($url, '/');
|
||||
if (is_file($abs2)) {
|
||||
return $abs2;
|
||||
}
|
||||
|
||||
return is_file($url) ? $url : null;
|
||||
}
|
||||
}
|
||||
365
application/controllers/tools/Inform_consent_cpmi.php
Normal file
365
application/controllers/tools/Inform_consent_cpmi.php
Normal file
@@ -0,0 +1,365 @@
|
||||
<?php
|
||||
|
||||
class Inform_consent_cpmi extends MY_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->db_onedev = $this->load->database('onedev', true);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$this->sys_ok([
|
||||
'message' => 'Use /tools/inform_consent_cpmi/pdf?T_OrderHeaderID=<id>'
|
||||
]);
|
||||
}
|
||||
|
||||
public function pdf()
|
||||
{
|
||||
try {
|
||||
$orderHeaderId = intval($this->input->get('T_OrderHeaderID', true));
|
||||
if ($orderHeaderId <= 0) {
|
||||
$orderHeaderId = intval($this->input->get('PID', true));
|
||||
}
|
||||
if ($orderHeaderId <= 0) {
|
||||
$this->sys_error('T_OrderHeaderID mandatory');
|
||||
return;
|
||||
}
|
||||
|
||||
$patient = $this->get_patient_data($orderHeaderId);
|
||||
if (!$patient) {
|
||||
$this->sys_error('Order not found');
|
||||
return;
|
||||
}
|
||||
|
||||
$content = $this->get_consent_content();
|
||||
$printBy = trim((string)$this->input->get('username', true));
|
||||
if ($printBy === '') {
|
||||
$printBy = 'ADMIN';
|
||||
}
|
||||
$printDate = date('M j, Y g:i A');
|
||||
|
||||
require_once APPPATH . 'third_party/fpdf/fpdf.php';
|
||||
$pdf = new FPDF('P', 'mm', 'A4');
|
||||
$pdf->SetAutoPageBreak(false);
|
||||
$pdf->SetMargins(10, 10, 10);
|
||||
|
||||
$this->render_report($pdf, $patient, $content, $printBy, $printDate);
|
||||
|
||||
header('Content-Type: application/pdf');
|
||||
header('Content-Disposition: inline; filename="inform_consent_cpmi_' . $orderHeaderId . '.pdf"');
|
||||
echo $pdf->Output('S');
|
||||
} catch (Exception $e) {
|
||||
$this->sys_error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function get_patient_data($orderHeaderId)
|
||||
{
|
||||
$sql = "SELECT
|
||||
h.T_OrderHeaderID,
|
||||
DATE_FORMAT(h.T_OrderHeaderDate, '%d-%m-%Y') as tanggal,
|
||||
IFNULL(h.T_OrderHeaderM_PatientAge, '') as age,
|
||||
p.M_PatientID,
|
||||
CONCAT(TRIM(IFNULL(t.M_TitleName,'')), ' ', TRIM(IFNULL(p.M_PatientPrefix,'')), ' ', TRIM(IFNULL(p.M_PatientName,'')), ' ', TRIM(IFNULL(p.M_PatientSuffix,''))) AS patient_name,
|
||||
IFNULL(s.M_SexCode, '') as sex_code,
|
||||
DATE_FORMAT(p.M_PatientDOB, '%d-%m-%Y') as dob,
|
||||
IFNULL(pa.M_PatientAddressDescription,'') as alamat,
|
||||
(
|
||||
SELECT ps.Patient_SignatureUrl
|
||||
FROM patient_signature ps
|
||||
WHERE ps.Patient_SignatureM_PatientID = p.M_PatientID
|
||||
AND ps.Patient_SignatureIsActive = 'Y'
|
||||
ORDER BY ps.Patient_SignatureID DESC
|
||||
LIMIT 1
|
||||
) AS signature_url
|
||||
FROM t_orderheader h
|
||||
JOIN m_patient p ON p.M_PatientID = h.T_OrderHeaderM_PatientID
|
||||
LEFT JOIN m_title t ON t.M_TitleID = p.M_PatientM_TitleID
|
||||
LEFT JOIN m_sex s ON s.M_SexID = p.M_PatientM_SexID
|
||||
LEFT JOIN m_patientaddress pa ON pa.M_PatientAddressM_PatientID = p.M_PatientID
|
||||
AND pa.M_PatientAddressNote = 'Utama'
|
||||
AND pa.M_PatientAddressIsActive = 'Y'
|
||||
WHERE h.T_OrderHeaderID = ?
|
||||
LIMIT 1";
|
||||
$qry = $this->db_onedev->query($sql, [$orderHeaderId]);
|
||||
return $qry ? $qry->row_array() : null;
|
||||
}
|
||||
|
||||
private function get_consent_content()
|
||||
{
|
||||
$sql = "SELECT M_InformConsentContent
|
||||
FROM m_informconsent
|
||||
WHERE M_InformConsentType = 'cpmi' AND M_InformConsentIsActive = 'Y'
|
||||
LIMIT 1";
|
||||
$qry = $this->db_onedev->query($sql);
|
||||
if (!$qry || !$qry->row_array()) {
|
||||
return '';
|
||||
}
|
||||
return (string)$qry->row_array()['M_InformConsentContent'];
|
||||
}
|
||||
|
||||
private function render_report($pdf, $patient, $contentHtml, $printBy, $printDate)
|
||||
{
|
||||
$pdf->AddPage();
|
||||
|
||||
$logoPath = APPPATH . '../assets/images/logo-ibl-round.png';
|
||||
if (is_file($logoPath)) {
|
||||
$pdf->Image($logoPath, 14, 21, 22);
|
||||
}
|
||||
|
||||
$pdf->SetFont('Times', 'B', 17);
|
||||
$pdf->SetXY(40, 18);
|
||||
$pdf->Cell(70, 8, 'KLINIK UTAMA', 0, 1, 'L');
|
||||
|
||||
$pdf->SetFont('Times', 'BI', 18);
|
||||
$pdf->SetXY(40, 26);
|
||||
$pdf->Cell(70, 8, 'IMAM', 0, 1, 'L');
|
||||
$pdf->SetXY(40, 34);
|
||||
$pdf->Cell(70, 8, 'BONJOL', 0, 1, 'L');
|
||||
$pdf->SetFont('Arial', '', 9);
|
||||
$pdf->SetXY(40, 42);
|
||||
$pdf->Cell(70, 6, 'Jl. Imam Bonjol 173 Semarang', 0, 1, 'L');
|
||||
|
||||
$pdf->SetFont('Times', '', 10);
|
||||
$pdf->SetXY(140, 12);
|
||||
$pdf->Cell(55, 6, 'FR/IBL-IB/Lab/PM-4.2/02', 0, 1, 'R');
|
||||
$pdf->SetFont('Arial', '', 11);
|
||||
$pdf->SetXY(98, 32);
|
||||
$pdf->MultiCell(80, 6, "GENERAL CONSENT\nMEDICAL TEST CPMI", 0, 'L');
|
||||
|
||||
$y = 56;
|
||||
$pdf->SetFont('Arial', '', 9);
|
||||
$pdf->SetXY(14, $y);
|
||||
$pdf->Cell(80, 5, 'Saya yang bertanda tangan dibawah ini :', 0, 1, 'L');
|
||||
$y += 8;
|
||||
|
||||
$y = $this->line_form($pdf, $y, 'Nama lengkap', trim(preg_replace('/\s+/', ' ', $patient['patient_name'])));
|
||||
$y = $this->line_form($pdf, $y, 'Bin / Binti', '...............................................................');
|
||||
$ttlUsia = trim($patient['dob']) . ' / ' . trim((string)$patient['age']);
|
||||
$y = $this->line_form($pdf, $y, 'Tanggal lahir / Usia', $ttlUsia . ' tahun');
|
||||
$y = $this->line_form($pdf, $y, 'Status', 'Kawin / Tidak Kawin');
|
||||
$y = $this->line_form($pdf, $y, 'Alamat', $patient['alamat']);
|
||||
|
||||
$y += 2;
|
||||
$blocks = $this->html_to_blocks($contentHtml);
|
||||
$pdf->SetFont('Arial', '', 8.2);
|
||||
$lineH = 5.2;
|
||||
foreach ($blocks as $b) {
|
||||
$indent = (float)$b['indent'];
|
||||
$style = (string)$b['style'];
|
||||
$text = (string)$b['text'];
|
||||
$w = max(20, 182 - $indent);
|
||||
if ($y > 228) {
|
||||
break;
|
||||
}
|
||||
$pdf->SetFont('Arial', $style, 8.2);
|
||||
$pdf->SetXY(14 + $indent, $y);
|
||||
$pdf->MultiCell($w, $lineH, $this->safe_text($text), 0, 'L');
|
||||
$y = $pdf->GetY();
|
||||
}
|
||||
|
||||
$y += 3;
|
||||
$pdf->SetFont('Arial', '', 8);
|
||||
$pdf->SetXY(104, $y - 4);
|
||||
$pdf->Cell(90, 5, 'Semarang, ' . $patient['tanggal'], 0, 1, 'R');
|
||||
$pdf->SetXY(14, $y);
|
||||
$pdf->Cell(90, 5, 'Petugas yang memberi penjelasan', 0, 0, 'L');
|
||||
$pdf->Cell(90, 5, 'Yang membuat pernyataan', 0, 1, 'R');
|
||||
$y += 12;
|
||||
$pdf->SetXY(14, $y);
|
||||
$pdf->Cell(90, 5, '( ................................ )', 0, 0, 'L');
|
||||
$signaturePath = $this->resolve_signature_path(isset($patient['signature_url']) ? $patient['signature_url'] : '');
|
||||
if ($signaturePath !== null) {
|
||||
$pdf->Image($signaturePath, 156, $y - 8, 34, 10);
|
||||
}
|
||||
$pdf->SetFont('Arial', 'U', 8.5);
|
||||
$pdf->SetXY(149, $y);
|
||||
$pdf->Cell(54, 5, $this->safe_text(trim(preg_replace('/\s+/', ' ', $patient['patient_name']))), 0, 1, 'C');
|
||||
|
||||
$y += 8;
|
||||
$pdf->Line(14, $y, 196, $y);
|
||||
$y += 4;
|
||||
$pdf->SetFont('Arial', '', 10);
|
||||
$pdf->SetXY(14, $y);
|
||||
$pdf->Cell(182, 5, 'CHECK LIST PEMERIKSAAN', 0, 1, 'C');
|
||||
|
||||
$y += 6;
|
||||
$labelsPage1 = ['Online Sidik Jari', 'Foto', 'Fisik', 'Darah + Urine', 'Feses', 'Sputum', 'Radiologi'];
|
||||
$this->draw_checklist_table($pdf, 26, $y, $labelsPage1);
|
||||
|
||||
$pdf->SetFont('Times', '', 7);
|
||||
$pdf->SetXY(14, 286);
|
||||
$pdf->Cell(22, 4, 'Print Oleh :', 0, 0, 'L');
|
||||
$pdf->Cell(50, 4, $this->safe_text($printBy), 0, 0, 'L');
|
||||
$pdf->Cell(12, 4, '1', 0, 0, 'C');
|
||||
$pdf->Cell(6, 4, '/', 0, 0, 'C');
|
||||
$pdf->Cell(12, 4, '2', 0, 0, 'C');
|
||||
$date = $this->safe_text($printDate);
|
||||
$dateW = $pdf->GetStringWidth($date);
|
||||
$xDate = max(120, 196 - $dateW);
|
||||
$pdf->SetXY($xDate, 286);
|
||||
$pdf->Cell($dateW + 1, 4, $date, 0, 1, 'L');
|
||||
|
||||
$this->render_second_checklist_page($pdf, $printBy, $printDate);
|
||||
}
|
||||
|
||||
private function render_second_checklist_page($pdf, $printBy, $printDate)
|
||||
{
|
||||
$pdf->AddPage();
|
||||
$pdf->SetFont('Arial', '', 10);
|
||||
$pdf->SetXY(140, 12);
|
||||
$pdf->Cell(55, 6, 'FR/IBL-IB/Lab/PM-4.2/02', 0, 1, 'R');
|
||||
|
||||
$labelsPage2 = ['EKG', 'Audiometri', 'Lain-Lain', 'Cetak Hasil', 'Cek I', 'Cek II', 'Revisi'];
|
||||
$this->draw_checklist_table($pdf, 26, 30, $labelsPage2);
|
||||
|
||||
$pdf->SetFont('Times', '', 7);
|
||||
$pdf->SetXY(14, 286);
|
||||
$pdf->Cell(22, 4, 'Print Oleh :', 0, 0, 'L');
|
||||
$pdf->Cell(50, 4, $this->safe_text($printBy), 0, 0, 'L');
|
||||
$pdf->Cell(12, 4, '2', 0, 0, 'C');
|
||||
$pdf->Cell(6, 4, '/', 0, 0, 'C');
|
||||
$pdf->Cell(12, 4, '2', 0, 0, 'C');
|
||||
$date = $this->safe_text($printDate);
|
||||
$dateW = $pdf->GetStringWidth($date);
|
||||
$xDate = max(120, 196 - $dateW);
|
||||
$pdf->SetXY($xDate, 286);
|
||||
$pdf->Cell($dateW + 1, 4, $date, 0, 1, 'L');
|
||||
}
|
||||
|
||||
private function draw_checklist_table($pdf, $xStart, $yStart, $labels)
|
||||
{
|
||||
$cols = count($labels);
|
||||
if ($cols < 1) {
|
||||
return;
|
||||
}
|
||||
$tableW = 156;
|
||||
$colW = $tableW / $cols;
|
||||
$topH = 11;
|
||||
$bottomH = 10;
|
||||
|
||||
for ($i = 0; $i < $cols; $i++) {
|
||||
$x = $xStart + ($i * $colW);
|
||||
$pdf->Rect($x, $yStart, $colW, $topH);
|
||||
$pdf->Rect($x, $yStart + $topH, $colW, $bottomH);
|
||||
$pdf->Rect($x + 1, $yStart + 1, 4, 4);
|
||||
|
||||
$label = $labels[$i];
|
||||
if ($label === 'Online Sidik Jari') {
|
||||
$label = "Online\nSidik Jari";
|
||||
} elseif ($label === 'Darah + Urine') {
|
||||
$label = "Darah +\nUrine";
|
||||
}
|
||||
$pdf->SetFont('Arial', '', 8);
|
||||
$pdf->SetXY($x + 5.5, $yStart + 1.5);
|
||||
$pdf->MultiCell($colW - 6, 4, $this->safe_text($label), 0, 'C');
|
||||
}
|
||||
}
|
||||
|
||||
private function line_form($pdf, $y, $label, $value)
|
||||
{
|
||||
$pdf->SetFont('Arial', '', 9);
|
||||
$pdf->SetXY(16, $y);
|
||||
$pdf->Cell(28, 5, $this->safe_text($label), 0, 0, 'L');
|
||||
$pdf->Cell(3, 5, ':', 0, 0, 'C');
|
||||
$pdf->SetXY(47, $y);
|
||||
$pdf->MultiCell(147, 5, $this->safe_text($value), 0, 'L');
|
||||
return $pdf->GetY() + 1;
|
||||
}
|
||||
|
||||
private function html_to_blocks($html)
|
||||
{
|
||||
$input = (string)$html;
|
||||
$input = str_replace(['\\r\\n', '\\n', '\\r'], "\n", $input);
|
||||
$input = str_replace(["\r\n", "\r"], "\n", $input);
|
||||
|
||||
$blocks = [];
|
||||
$s = preg_replace('/<br\s*\/?>/i', "\n", $input);
|
||||
$s = preg_replace('/<\/(div|p|h[1-6]|li)>/i', "$0\n", $s);
|
||||
preg_match_all('/<(h[1-6]|p|li)[^>]*>(.*?)<\/\1>/is', $s, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $m) {
|
||||
$tag = strtolower($m[1]);
|
||||
$inner = preg_replace('/<(ul|ol)[^>]*>.*?<\/\1>/is', '', (string)$m[2]);
|
||||
$plain = trim(preg_replace('/\s+/', ' ', html_entity_decode(strip_tags($inner), ENT_QUOTES | ENT_HTML5, 'UTF-8')));
|
||||
if ($plain === '' || $plain === ':') {
|
||||
continue;
|
||||
}
|
||||
$indent = 0;
|
||||
$style = '';
|
||||
$text = $plain;
|
||||
|
||||
if ($tag === 'h1' || $tag === 'h2' || $tag === 'h3' || $tag === 'h4' || $tag === 'h5' || $tag === 'h6') {
|
||||
$style = 'B';
|
||||
} elseif ($tag === 'li') {
|
||||
if (preg_match('/^[0-9]+\./', $plain) || preg_match('/^[IVX]+\./i', $plain)) {
|
||||
$text = $plain;
|
||||
$indent = 0;
|
||||
} else {
|
||||
$text = '• ' . $plain;
|
||||
$indent = 5;
|
||||
}
|
||||
} elseif ($tag === 'p' && (stripos((string)$m[2], '<strong') !== false || preg_match('/^[IVX]+\./i', $plain))) {
|
||||
$style = 'B';
|
||||
}
|
||||
|
||||
$blocks[] = [
|
||||
'text' => $text,
|
||||
'indent' => $indent,
|
||||
'style' => $style
|
||||
];
|
||||
}
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
private function safe_text($text)
|
||||
{
|
||||
return iconv('UTF-8', 'windows-1252//TRANSLIT', (string)$text);
|
||||
}
|
||||
|
||||
private function resolve_signature_path($signatureUrl)
|
||||
{
|
||||
$url = trim((string)$signatureUrl);
|
||||
if ($url === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (preg_match('#^https?://#i', $url)) {
|
||||
$tmp = sys_get_temp_dir() . '/sig_' . md5($url) . '.png';
|
||||
if (!is_file($tmp)) {
|
||||
$ctx = stream_context_create([
|
||||
'http' => ['timeout' => 3],
|
||||
'ssl' => ['verify_peer' => false, 'verify_peer_name' => false]
|
||||
]);
|
||||
$bin = @file_get_contents($url, false, $ctx);
|
||||
if ($bin !== false && strlen($bin) > 0) {
|
||||
@file_put_contents($tmp, $bin);
|
||||
}
|
||||
}
|
||||
return is_file($tmp) ? $tmp : null;
|
||||
}
|
||||
|
||||
if (strpos($url, '/one-media/') === 0) {
|
||||
$absMedia = '/home/one/project' . $url;
|
||||
if (is_file($absMedia)) {
|
||||
return $absMedia;
|
||||
}
|
||||
return $this->resolve_signature_path('http://devone.aplikasi.web.id' . $url);
|
||||
}
|
||||
|
||||
if (strpos($url, '/') === 0) {
|
||||
$abs = FCPATH . ltrim($url, '/');
|
||||
if (is_file($abs)) {
|
||||
return $abs;
|
||||
}
|
||||
}
|
||||
|
||||
$abs2 = FCPATH . 'assets/uploads/signature/' . ltrim($url, '/');
|
||||
if (is_file($abs2)) {
|
||||
return $abs2;
|
||||
}
|
||||
|
||||
return is_file($url) ? $url : null;
|
||||
}
|
||||
}
|
||||
@@ -567,6 +567,8 @@ class Medical_checkup_report extends MY_Controller
|
||||
$available = $pdf->GetPageHeight() - $bottomMargin - $pdf->GetY();
|
||||
if ($available < $neededHeight) {
|
||||
$pdf->AddPage();
|
||||
// Samakan jarak awal konten di halaman lanjutan.
|
||||
$pdf->SetY(35);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BIN
assets/images/logo-ibl-round.png
Normal file
BIN
assets/images/logo-ibl-round.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
BIN
assets/images/logo-ibl.png
Normal file
BIN
assets/images/logo-ibl.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 248 KiB |
Reference in New Issue
Block a user