FHM31052601IBL - populate decrypt cache sebelum semua BIRT/PDF fetch
- Ibl_patient_decrypt: tambah fetch_birt_pdf() + pre_cache_and_get_url() - Reporturl.php: auto pre-cache sebelum return URL atau fetch PDF - Rv_patient.php: pre_cache sebelum return URL ke frontend - tgram/Hasil.php: fetch_birt_pdf() via dl_report() - Qr_report_uploader.php: populate/delete cache wrapping download_file() - Ibl_merge_report_gateway.php: populate/delete cache wrapping Go merge service call - send_email.php: populate_birt_cache() + delete_birt_cache() untuk email attachment Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -790,6 +790,10 @@ private function get_fallback_report($group_name, $type, $ready_print)
|
||||
$url = "/birt/{$mode}?__report=report/onelab/{$folder}/{$rpt_name}.rptdesign&__format=pdf&username={$username}&PID={$order_id}&tm={$tm}";
|
||||
}
|
||||
|
||||
// Populate decrypt cache sebelum frontend buka URL ke BIRT
|
||||
$this->load->library('ibl_patient_decrypt');
|
||||
$this->ibl_patient_decrypt->pre_cache_and_get_url($url);
|
||||
|
||||
$this->sys_ok($url);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ class Hasil extends MY_Controller
|
||||
{
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->load->library('ibl_patient_decrypt');
|
||||
}
|
||||
/* WA ------ */
|
||||
function update_track() {
|
||||
@@ -524,14 +525,13 @@ class Hasil extends MY_Controller
|
||||
}
|
||||
}
|
||||
function dl_report($prm, $name) {
|
||||
$url = "http://localhost/birt/frameset?" ;
|
||||
$qry = "";
|
||||
$qry = "";
|
||||
foreach($prm as $k => $v) {
|
||||
if ($qry != "" ) $qry .= "&";
|
||||
if ($qry != "") $qry .= "&";
|
||||
$qry .= $k . "=" . urlencode($v);
|
||||
}
|
||||
$url .= $qry ;
|
||||
$data = file_get_contents($url);
|
||||
}
|
||||
$relative_url = "/birt/frameset?" . $qry;
|
||||
$data = $this->ibl_patient_decrypt->fetch_birt_pdf($relative_url);
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Disposition: attachment; filename=' . $name);
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
|
||||
@@ -8,6 +8,7 @@ class Qr_report_uploader extends MY_Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->load->library('ibl_patient_decrypt');
|
||||
$this->db_onedev = $this->load->database('onedev', true);
|
||||
$this->db_log = $this->load->database('one_lab_log', true);
|
||||
}
|
||||
@@ -120,7 +121,11 @@ class Qr_report_uploader extends MY_Controller
|
||||
$orderHeaderID = (int)$row['QR_PrintOutT_OrderHeaderID'];
|
||||
$reportUrl = $row['QR_PrintOutReportURL'];
|
||||
|
||||
// Populate cache sebelum fetch dari BIRT
|
||||
$cache_id = $this->ibl_patient_decrypt->populate_cache_by_order($orderHeaderID);
|
||||
$pdfContent = $this->download_file($reportUrl);
|
||||
$this->ibl_patient_decrypt->delete_cache($cache_id);
|
||||
|
||||
if ($pdfContent === false) {
|
||||
return $this->mark_failed($row, $orderHeaderID, '', 'DOWNLOAD_FAILED');
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class Ibl_merge_report_gateway
|
||||
{
|
||||
$this->CI = &get_instance();
|
||||
$this->db_onedev = $this->CI->load->database('onedev', true);
|
||||
$this->CI->load->library('ibl_patient_decrypt');
|
||||
}
|
||||
|
||||
public function create_merge_request_from_lab_number($labNumber, $creatorUserId, $customName = '')
|
||||
@@ -593,6 +594,9 @@ class Ibl_merge_report_gateway
|
||||
return $this->error('QR_PRINTOUT_EMPTY', 'URL report kosong setelah normalisasi.');
|
||||
}
|
||||
|
||||
// Populate decrypt cache sebelum Go merge service fetch PDF dari BIRT
|
||||
$cache_id = $this->CI->ibl_patient_decrypt->populate_cache_by_order($orderHeaderId);
|
||||
|
||||
$payload = array(
|
||||
'name' => 'merge-' . (int) $orderHeaderId . '.pdf',
|
||||
'urls' => $urls,
|
||||
@@ -600,7 +604,12 @@ class Ibl_merge_report_gateway
|
||||
'T_OrderHeaderID' => (int) $orderHeaderId,
|
||||
);
|
||||
|
||||
return $this->call_merge_service($payload);
|
||||
$result = $this->call_merge_service($payload);
|
||||
|
||||
// Hapus cache setelah merge service selesai
|
||||
$this->CI->ibl_patient_decrypt->delete_cache($cache_id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function call_merge_service(array $payload)
|
||||
|
||||
@@ -85,6 +85,38 @@ class Ibl_patient_decrypt
|
||||
$this->db->query("DELETE FROM patient_print_cache WHERE ppc_created < NOW() - INTERVAL 5 MINUTE");
|
||||
}
|
||||
|
||||
// Fetch PDF dari BIRT dengan auto decrypt cache
|
||||
// Ganti semua file_get_contents($birt_url) dengan ini
|
||||
public function fetch_birt_pdf($birt_relative_url)
|
||||
{
|
||||
// Parse PID dari URL query string
|
||||
parse_str(parse_url($birt_relative_url, PHP_URL_QUERY) ?? '', $params);
|
||||
$order_id = intval($params['PID'] ?? 0);
|
||||
|
||||
$cache_id = $order_id ? $this->populate_cache_by_order($order_id) : null;
|
||||
|
||||
// Build full internal URL ke BIRT server
|
||||
$full_url = 'http://localhost:8080' . $birt_relative_url;
|
||||
$context = stream_context_create(['http' => ['timeout' => 120]]);
|
||||
$pdf = @file_get_contents($full_url, false, $context);
|
||||
|
||||
$this->delete_cache($cache_id);
|
||||
|
||||
return $pdf;
|
||||
}
|
||||
|
||||
// Populate cache lalu return URL (untuk controller yang return URL ke frontend)
|
||||
// Cache hidup 5 menit — cukup untuk browser buka BIRT
|
||||
public function pre_cache_and_get_url($birt_relative_url)
|
||||
{
|
||||
parse_str(parse_url($birt_relative_url, PHP_URL_QUERY) ?? '', $params);
|
||||
$order_id = intval($params['PID'] ?? 0);
|
||||
if ($order_id) {
|
||||
$this->populate_cache_by_order($order_id);
|
||||
}
|
||||
return $birt_relative_url;
|
||||
}
|
||||
|
||||
private function _insert_cache($order_id, $patient_id, $name, $dob, $hp, $email, $address)
|
||||
{
|
||||
$this->db->query(
|
||||
|
||||
@@ -55,20 +55,18 @@ class Reporturl
|
||||
$final_url = str_replace($param_key, $replacement_value, $final_url);
|
||||
}
|
||||
|
||||
// Populate decrypt cache sebelum return URL atau fetch PDF
|
||||
$CI->load->library('ibl_patient_decrypt');
|
||||
$CI->ibl_patient_decrypt->pre_cache_and_get_url($final_url);
|
||||
|
||||
if($show == 'N'){
|
||||
return array(true, $final_url);
|
||||
}
|
||||
else{
|
||||
$final_url = 'http'.($_SERVER['HTTPS'] == 'on' ? 's' : '').'://'.$_SERVER['HTTP_HOST'].$final_url;
|
||||
|
||||
$response = file_get_contents($final_url);
|
||||
$pdf = $CI->ibl_patient_decrypt->fetch_birt_pdf($final_url);
|
||||
header("Content-type: application/pdf");
|
||||
header(
|
||||
'Content-Disposition: inline; filename="' .
|
||||
$output_file_name .
|
||||
'"'
|
||||
);
|
||||
echo ($response);
|
||||
header('Content-Disposition: inline; filename="' . ($output_file_name ?? 'report.pdf') . '"');
|
||||
echo $pdf;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,6 +60,58 @@ function download_pdf(string $url)
|
||||
return $data;
|
||||
}
|
||||
|
||||
// Load ibl_encryptor untuk decrypt PII sebelum fetch PDF dari BIRT
|
||||
define('BASEPATH', true);
|
||||
$_env_file = __DIR__ . '/../.env';
|
||||
if (file_exists($_env_file)) {
|
||||
foreach (file($_env_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $_l) {
|
||||
if (strpos(trim($_l), '#') === 0) continue;
|
||||
[$_k, $_v] = array_map('trim', explode('=', $_l, 2));
|
||||
if ($_k !== '') $_ENV[$_k] = $_v;
|
||||
}
|
||||
}
|
||||
require __DIR__ . '/../application/libraries/Ibl_encryptor.php';
|
||||
$_enc = new Ibl_encryptor();
|
||||
|
||||
// Populate patient_print_cache sebelum fetch PDF dari BIRT
|
||||
function populate_birt_cache(PDO $pdo, $enc, string $birt_url): ?int
|
||||
{
|
||||
parse_str(parse_url($birt_url, PHP_URL_QUERY) ?? '', $params);
|
||||
$order_id = intval($params['PID'] ?? 0);
|
||||
if (!$order_id) return null;
|
||||
|
||||
$patient = $pdo->query(
|
||||
"SELECT M_PatientID, M_PatientName_enc, M_PatientDOB_enc,
|
||||
M_PatientHP_enc, M_PatientEmail_enc, M_PatientDOB
|
||||
FROM t_orderheader
|
||||
JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID
|
||||
WHERE T_OrderHeaderID = {$order_id} LIMIT 1"
|
||||
)->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$patient) return null;
|
||||
|
||||
$addr = $pdo->query(
|
||||
"SELECT M_PatientAddressDescription_enc FROM m_patientaddress
|
||||
WHERE M_PatientAddressM_PatientID = {$patient['M_PatientID']}
|
||||
AND M_PatientAddressIsActive = 'Y' AND M_PatientAddressNote = 'Utama' LIMIT 1"
|
||||
)->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$name = $enc->decrypt($patient['M_PatientName_enc'] ?? '') ?? '';
|
||||
$dob = $enc->decrypt($patient['M_PatientDOB_enc'] ?? '') ?? date('d-m-Y', strtotime($patient['M_PatientDOB'] ?? 'now'));
|
||||
$hp = $enc->decrypt($patient['M_PatientHP_enc'] ?? '') ?? '';
|
||||
$email = $enc->decrypt($patient['M_PatientEmail_enc']?? '') ?? '';
|
||||
$address = $enc->decrypt($addr['M_PatientAddressDescription_enc'] ?? '') ?? '';
|
||||
|
||||
$pdo->exec("DELETE FROM patient_print_cache WHERE ppc_order_id = {$order_id} OR ppc_created < NOW() - INTERVAL 5 MINUTE");
|
||||
$stmt = $pdo->prepare("INSERT INTO patient_print_cache (ppc_order_id, ppc_patient_id, ppc_name, ppc_dob, ppc_hp, ppc_email, ppc_address) VALUES (?,?,?,?,?,?,?)");
|
||||
$stmt->execute([$order_id, $patient['M_PatientID'], $name, $dob, $hp, $email, $address]);
|
||||
return (int)$pdo->lastInsertId();
|
||||
}
|
||||
|
||||
function delete_birt_cache(PDO $pdo, ?int $cache_id): void
|
||||
{
|
||||
if ($cache_id) $pdo->exec("DELETE FROM patient_print_cache WHERE ppc_id = {$cache_id}");
|
||||
}
|
||||
|
||||
function encrypt_pdf(string $input_path, string $password)
|
||||
{
|
||||
$output_path = $input_path . '_enc.pdf';
|
||||
@@ -308,7 +360,9 @@ foreach ($rows as $row) {
|
||||
|
||||
log_msg(" Downloading attachment " . ($idx + 1) . " [{$result}]: {$url}");
|
||||
|
||||
$cache_id = populate_birt_cache($pdo, $GLOBALS['_enc'], $url);
|
||||
$pdf = download_pdf($url);
|
||||
delete_birt_cache($pdo, $cache_id);
|
||||
if ($pdf === false) {
|
||||
log_msg(" Download failed, skipping");
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user