10 Commits
39 changed files with 1399 additions and 1255 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
[![Software License][ico-license]](LICENSE.md)
[![Total Downloads][ico-downloads]][link-downloads]
webapp adalah framework webbase aplikasi yang dibuat dengan basis kode PHP dan digabungkan dengan beberapa repo lain, sehingga menghasilkan webbase framework yang efisien dan efektif.
Webapp adalah framework webbase aplikasi yang dibuat dengan basis kode PHP dan digabungkan dengan beberapa repo lain, sehingga menghasilkan webbase framework yang efisien dan efektif.
Maintenance versi repo tambahan, akan dilakukan secara periodik dengan mempertimbangkan kesiapan infrastruktur framework secara utuh.
+1 -1
View File
@@ -1882,7 +1882,7 @@ progress {
.table > :not(caption) > * > * {
padding: 0.5rem 0.5rem;
color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));
background-color: var(--bs-table-bg);
/*background-color: var(--bs-table-bg);*/
border-bottom-width: var(--bs-border-width);
box-shadow: inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg)));
}
+20 -1
View File
@@ -4,7 +4,7 @@
Desc. : CSS Default Configuration
Created By : Siau Pheng ([email protected]).
Created Date : December 20th, 2007.
Last Modified : February 7th, 2026.
Last Modified : September 27th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -343,6 +343,14 @@ ul.dtr-details li.hidden { visibility: hidden !important; display: none !importa
cursor: pointer;
}
.bootstrap-autocomplete.dropdown-menu .dropdown-item.active .text-primary {
color: #93f6c5 !important;
}
.bootstrap-autocomplete.dropdown-menu .dropdown-item.active .text-danger {
color: #f4c8d2 !important;
}
/******************************** text field ********************************/
input.double, input.integer, input.number {
@@ -493,3 +501,14 @@ input.double, input.integer, input.number {
background-color: #d8dbe0;
opacity: 1;
}
/** bashboard **/
.my-bashboard {
height: auto;
}
@media (min-width: 992px) {
.my-bashboard {
height: 500px;
}
}
+5 -7
View File
@@ -39,7 +39,7 @@ var AjaxResolver = (function (_super) {
url: '',
method: 'post',
queryKey: 'Auto_Query',
extraData: {},
param: [],
timeout: 0,
requestThrottling: 500
};
@@ -51,7 +51,7 @@ var AjaxResolver = (function (_super) {
}
var data = {};
data[this._settings.queryKey] = q;
$.extend(data, this._settings.extraData);
if (this._settings.param.length > 0) $.extend(data, FoniaJS.RequestParam(this._settings.param));
if (this.requestTID) {
window.clearTimeout(this.requestTID);
}
@@ -97,13 +97,12 @@ var DropdownV5 = (function () {
DropdownV5.prototype.init = function () {
var _this = this;
var pos = this.getElPos();
var fontsize = _this._$el.css('font-size');
this._dd = $('<div />');
this._dd.addClass('bootstrap-autocomplete dropdown-menu');
this._dd.insertAfter(this._$el);
this._dd.css({ top: pos.top + this._$el.outerHeight(), left: pos.left, width: this._$el.outerWidth() });
this._dd.css({ top: pos.top + this._$el.outerHeight(), left: pos.left, width: this._$el.outerWidth(), 'font-size': fontsize });
this._dd.on('click', '.dropdown-item', function (evt) {
//console.log('clicked', evt.currentTarget);
//console.log($(evt.currentTarget));
var item = $(evt.currentTarget).data('item');
_this.itemSelectedLaunchEvent(item);
evt.preventDefault();
@@ -239,8 +238,7 @@ var DropdownV5 = (function () {
itemText = _this.showMatchedText(itemFormatted.text, _this.searchText);
if (itemFormatted.html !== undefined) {
itemHtml = itemFormatted.html;
}
else {
} else {
itemHtml = itemText;
}
var disabledItem = itemFormatted.disabled;
+85
View File
@@ -0,0 +1,85 @@
/*******************************************************************
Module : /assets/js/download.js
Desc. : Fungsi-fungsi download data & laporan
Created By : Siau Pheng ([email protected]).
Created Date : April 1st, 2011.
Last Modified : October 2nd, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
var Download = function(options) {
var _options = {
'url': '',
'filename': 'file.bin',
'title': '',
'text': 'share dari aplikasi'
};
var _params = [];
this.construct = function(options){
if (typeof options == 'object') {
$.extend(_options, options);
} else _options.url = options;
};
this.set_url = function (url){
_options.url = url;
};
this.add_param = function(par_id, par_val) {
var _getvalue = (par_val) ? par_id + '=' + encodeURIComponent(par_val) : par_id;
_params.push(_getvalue);
};
this._exec = async function(is_share) {
if (!_options.url) {
console.warn('cek url !');
return false;
}
try {
const blob = await $.ajax({
type: 'POST',
url: _options.url,
data: FoniaJS.RequestParam(_params),
xhrFields: {
responseType: 'blob'
},
success: async function (data, status, xhr) {
const disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
const matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
_options.filename = matches[1].replace(/['"]/g, '');
}
}
}
});
const file = new File([blob], _options.filename, { type: blob.type });
if (is_share === true && navigator.canShare && navigator.canShare({ files: [file] })) {
await navigator.share({
files: [file],
title: _options.title ?? _options.filename,
text: _options.text
});
} else {
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = _options.filename;
link.click();
}
} catch (error) {
console.error('Download / sharing gagal :', error);
};
return this;
};
this.share = async function() {
await this._exec(true);
};
this.download = async function() {
await this._exec(false);
};
this.construct(options);
};
-63
View File
@@ -1,63 +0,0 @@
/*******************************************************************
Module : /assets/js/export.js
Desc. : Fungsi-fungsi export data & laporan
Created By : Siau Pheng ([email protected]).
Created Date : April 1st, 2011.
Last Modified : January 19th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
var cEXPORT = function(url, options){
var _options = {
'url': '',
'filename': ''
};
var _params = [];
this.construct = function(url, options){
if (typeof url == 'object') {
$.extend(_options, url);
} else {
$.extend(_options, options);
_options.url = url;
}
};
this.set_url = function (url){
_options.url = url;
};
this.add_param = function (par_id, par_val){
var _getvalue = (par_val) ? par_id + "=" + escape(par_val) : par_id;
_params.push(_getvalue);
},
this.download = async function(){
if (!_options.url) {
console.warn('cek url !');
return false;
}
var _pro = (window.location.protocol=='https:') ? 'https://' : 'http://';
var _src = _pro+FoniaJS.WEB_HOST + _options.url + '?' + (FoniaJS.RequestParam(_params)).join('&');
try {
const response = await fetch(_src)
.then(response => {
const cDispo = response.headers.get('Content-Disposition');
if (cDispo && cDispo.indexOf('filename=') !== -1) {
_options.filename = cDispo.split('filename=')[1].split(';')[0].replace(/"/g, '');
}
return response;
})
const blob = await response.blob();
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = _options.filename;
link.click();
} catch (error) {
console.error('Download gagal:', error);
}
return this;
};
this.construct(url, options);
};
+123 -92
View File
@@ -4,7 +4,7 @@
Desc. : JS - Fonia Custom Class v3
Created By : Siau Pheng ([email protected]).
Created Date : June 19th, 2009.
Last Modified : February 10th, 2026.
Last Modified : September 28th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -58,8 +58,8 @@ var FoniaJS = {
},
callMenu: function(p, q) {
var apar = ["p=" + p];
if (q != null) apar.push("q=" + q);
new Request.JSON({
if (q !== null) apar.push("q=" + q);
new Request({
url: "auth/menu",
sendParam: apar,
onSuccess: (apop) => {
@@ -68,29 +68,29 @@ var FoniaJS = {
setTimeout(() => { self.location = self.location.href; }, 1600);
return false;
}
if (apop.php == "" || !window[apop.func]) {
if (apop.php === "" || !window[apop.func]) {
this.showErrorLocale("Fonia.page404");
return false;
}
window[apop.func]['PHP'] = apop.php;
window[apop.func]['KODE'] = apop.kode;
if (apop.iswindow == true) {
if (IndexJS.loading) IndexJS.loading();
new Request.JSON({
if (apop.iswindow === true) {
if (IndexJS.index) IndexJS.index();
new Request({
url: apop.php + '/index',
onSuccess: (ajson) => {
this.showWindow(apop.kode, apop.title, ajson.html, apop.width, apop.button, () => {
if (typeof window[apop.func]['loading'] === 'function') window[apop.func]['loading'](q);
if (typeof window[apop.func]['index'] === 'function') window[apop.func]['index'](q);
});
}
}).send();
} else {
$("#pageToolbarBot").html(this.genToolButton(apop.button));
new Request.JSON({
new Request({
url: apop.php + '/index',
onSuccess: (ajson) => {
$('#pageContent').html(ajson.html);
if (typeof window[apop.func]['loading'] === 'function') window[apop.func]['loading'](q);
if (typeof window[apop.func]['index'] === 'function') window[apop.func]['index'](q);
}
}).send();
}
@@ -112,12 +112,12 @@ var FoniaJS = {
if ($('#HomeLink').length){
$('#HomeLink').click(() => {
this.closeAllWindows();
if (IndexJS.loading) IndexJS.loading();
if (IndexJS.index) IndexJS.index();
});
}
if ($('#ExitLink').length) {
$('#ExitLink').click(() => {
new Request.JSON({
new Request({
url: "auth/logout",
onFailure: () => {
self.location = self.location.href;
@@ -157,11 +157,11 @@ var FoniaJS = {
var _buover = (buserover == null) ? false : buserover;
var _tsid = parseInt(Math.random() * 99999999);
var _ceksuper = null;
var _isi = new String('<div class="row mb-1" id="Auth_SP1"><div class="col-sm-6 col-lg-5">Username</div><div class="col-sm-6 col-lg-7"><input type="text" class="form-control" id="UID" name="UID" value="'+((_bsuper==false)?this.User.ID:'')+'" required="true"></div></div><div class="row mb-1" id="Auth_SP2"><div class="col-sm-6 col-lg-5">Password</div><div class="col-sm-6 col-lg-7"><input type="password" class="form-control" id="PWD" name="PWD" value="" required="true"></div></div><div class="row mb-1 d-none" id="Auth_SP3"><div class="col-12 text-center"><p>'+this.locale("Fonia.auth_wait_msg")+'</p></div></div><hr class="my-2"><div class="row mt-1"><div class="col-4"><button type="button" class="btn btn-outline-primary shadow-none" id="butSReq">Request</button></div><div class="col-8 text-end"><button type="button" class="btn btn-danger me-2" id="butSBatal" data-bs-dismiss="modal">Batal</button><button type="button" class="btn btn-success" id="butSOK">OK</button></div></div>');
var _isi = new String('<div class="row mb-1" id="Auth_SP1"><div class="col-sm-6 col-lg-5 col-form-label">Username</div><div class="col-sm-6 col-lg-7"><input type="text" class="form-control" id="UID" name="UID" value="'+((_bsuper===false)?this.User.ID:'')+'" required="true"></div></div><div class="row mb-1" id="Auth_SP2"><div class="col-sm-6 col-lg-5 col-form-label">Password</div><div class="col-sm-6 col-lg-7"><input type="password" class="form-control" id="PWD" name="PWD" value="" required="true"></div></div><div class="row mb-1 d-none" id="Auth_SP3"><div class="col-12 text-center"><p>'+this.locale("Fonia.auth_wait_msg")+'</p></div></div><hr class="my-2"><div class="row mt-1"><div class="col-4"><button type="button" class="btn btn-outline-primary shadow-none" id="butSReq">Request</button></div><div class="col-8 text-end"><button type="button" class="btn btn-danger me-2" id="butSBatal" data-bs-dismiss="modal">Batal</button><button type="button" class="btn btn-success" id="butSOK">OK</button></div></div>');
this.winSAuth = this.showWindow('SAuth', ((this.AUTH_LEVEL < 9 && _bsuper == true) ? this.locale("Fonia.auth_super") : this.locale("Fonia.auth_user")), _isi, 200, '', () => {
$('#butSOK').click(() => {
$('#butSOK').prop('disabled', true);
new Request.JSON({
new Request({
url: "auth/supervisi",
sendParam: ["data=super-check", "UID", "PWD", "SUPER=" + _bsuper, "UOVER=" + _buover],
onSuccess: (adata) => {
@@ -177,7 +177,7 @@ var FoniaJS = {
$('#butSBatal').click(() => {
if (_ceksuper) {
clearInterval(_ceksuper);
new Request.JSON({
new Request({
url: "auth/supervisi",
sendParam: ["data=super-cancel", "KODE=" + ocall.KODE, "REQ_SID=" + this.APP_SID, "REQ=" + _tsid]
}).send();
@@ -189,16 +189,16 @@ var FoniaJS = {
$('#Auth_SP2').addClass('d-none');
$('#Auth_SP3').removeClass('d-none');
$('#butSOK').prop('disabled', true);
new Request.JSON({
new Request({
url: "auth/supervisi",
sendParam: ["data=super-request", "KODE=" + ocall.KODE, "REQ_SID=" + this.APP_SID, "REQ=" + _tsid, "MSG=" + tmsg]
}).send();
var _cobalagi = 5;
_ceksuper = setInterval(() => {
$('#butSBatal').html(this.locale("Fonia.cancel") + " (" + _cobalagi + ")");
if (_cobalagi == 0) {
if (_cobalagi === 0) {
clearInterval(_ceksuper);
new Request.JSON({
new Request({
url: "auth/supervisi",
sendParam: ["data=super-cancel", "KODE=" + ocall.KODE, "REQ_SID=" + this.APP_SID, "REQ=" + _tsid]
}).send();
@@ -206,11 +206,11 @@ var FoniaJS = {
this.showErrorLocale("Fonia.auth_fail");
return false;
}
new Request.JSON({
new Request({
url: "auth/supervisi",
sendParam: ["data=request-check", "KODE=" + ocall.KODE, "REQ_SID=" + this.APP_SID, "REQ=" + _tsid],
onSuccess: (adata) => {
if (adata.status == 1) {
if (adata.status === 1) {
clearInterval(_ceksuper);
this.showInfoLocale("Fonia.auth_success");
fungcall();
@@ -224,14 +224,14 @@ var FoniaJS = {
});
$('#UID').keyup((e) => {
if (-1!==$.inArray(e.which, [13,9])) {
if (e.currentTarget.value != '') $('#PWD').focus();
if (e.currentTarget.value !== '') $('#PWD').focus();
}
});
$('#PWD').keyup((e) => {
if (e.currentTarget.value == '') return false;
if (e.currentTarget.value === '') return false;
if (13 == e.which) $('#butSOK').trigger('click');
});
if (_bsuper == false) {
if (_bsuper === false) {
FoniaJS.setFocus("#PWD");
} else {
FoniaJS.setFocus("#UID");
@@ -242,10 +242,10 @@ var FoniaJS = {
if (!menu) return '';
var smenu = '';
if (typeof menu === 'object'){
var ma = ' me-sm-2'; smenu = '<div class="col-12 col-sm-6 my-0 mx-sm-0 text-center text-sm-start">';
var ma = ' me-sm-2'; smenu = '<div class="col-12 col-md-auto px-0 text-center text-sm-start">';
$(menu).each((i, atom) => {
if (Object.keys(atom).length === 0) {
smenu += '</div><div class="col-12 col-sm-6 my-0 mx-sm-0 text-center text-sm-end">';
smenu += '</div><div class="col-12 col-sm-auto px-0 text-center text-sm-end">';
ma = ' ms-sm-2';
} else {
if (atom.i == 'butTutup') { atom.v='Tutup', atom.c='danger', atom.d='' };
@@ -273,8 +273,7 @@ var FoniaJS = {
} else {
if (atom.i == 'butTutup') { atom.v='Tutup', atom.c='danger', atom.d='' };
if (atom.i == 'butBatal') { atom.v='Batal', atom.c='danger', atom.d='' };
var _xt = "";//(typeof atom?.d !== 'undefined') ? ' data-bs-dismiss="modal"' : '';
smenu += '<button type="button" class="btn btn-'+(atom?.c ?? 'info')+' mb-2 mb-sm-0'+ma+' col-10 col-sm-3" id="'+atom.i+'"'+_xt+'>' + atom.v + '</button>';
smenu += '<button type="button" class="btn btn-'+(atom?.c ?? 'info')+' mb-2 mb-sm-0'+ma+' col-10 col-sm-3" id="'+atom.i+'">' + atom.v + '</button>';
}
});
smenu += '</div></div>';
@@ -287,18 +286,29 @@ var FoniaJS = {
FormDecorated: function() {
$('input.form-control[class*=integer], input.form-control[class*=angka]').each((i, el) => {
const elm = $(el);
elm.on('keypress keyup blur paste', (e) => {
if ((elm.attr('o3') ?? '') !== '') return;
elm.attr('o3', '1');
elm.on('keypress keyup paste', (e) => {
elm.val(elm.val().replace(/[^\d].+/, ""));
if ((e.which < 48 || e.which > 57)) e.preventDefault();
});
});
$('input.form-control[class*=double]').each((i, el) => {
const elm = $(el);
elm.on('keypress keyup blur paste', (e) => {
elm.val(elm.val().replace(/[^0-9\.]/g,''));
if (e.type === 'blur') elm.val( FoniaJS.FloatToStr(elm.val(), 2) );
if ((e.which != 46 || elm.val().indexOf('.') != -1) && (e.which < 48 || e.which > 57)) e.preventDefault();
if ((elm.attr('o3') ?? '') !== '') return;
elm.attr('o3', '1');
elm.on('keypress keyup input', (e) => {
if (e.type === 'keypress') {
if ((e.which != 45 || elm.val().indexOf('-') != -1) && (e.which != 46 || elm.val().indexOf('.') != -1) && (e.which < 48 || e.which > 57)) e.preventDefault();
} else {
var _val = elm.val().replace(/[^0-9.-]/g, '');
if (_val.indexOf('-') > 0) _val = _val.charAt(0) + _val.slice(1).replace(/-/g, '');
var _parts = _val.split('.');
if (_parts.length > 2) _val = _parts[0] + '.' + _parts.slice(1).join('');
elm.val(_val);
}
});
elm.on('blur', () => elm.val( FoniaJS.FloatToStr(elm.val(), 2) ));
elm.on('focus', (e) => {
elm.val( FoniaJS.StrToFloat(elm.val()) );
elm.select();
@@ -307,9 +317,18 @@ var FoniaJS = {
});
$('input.form-control[type=number]').each((i, el) => {
const elm = $(el);
elm.on('keypress keyup blur paste', (e) => {
elm.val(elm.val().replace(/[^0-9]/g,''));
if ((e.which != 46 || elm.val().indexOf('.') != -1) && (e.which < 48 || e.which > 57)) e.preventDefault();
if ((elm.attr('o3') ?? '') !== '') return;
elm.attr('o3', '1');
elm.on('keypress keyup input', (e) => {
if (e.type === 'keypress') {
if ((e.which != 45 || elm.val().indexOf('-') != -1) && (e.which != 46 || elm.val().indexOf('.') != -1) && (e.which < 48 || e.which > 57)) e.preventDefault();
} else {
var _val = elm.val().replace(/[^0-9.-]/g, '');
if (_val.indexOf('-') > 0) _val = _val.charAt(0) + _val.slice(1).replace(/-/g, '');
var _parts = _val.split('.');
if (_parts.length > 2) _val = _parts[0] + '.' + _parts.slice(1).join('');
elm.val(_val);
}
});
});
$('input.form-control, textarea.form-control, select.form-select').each((i, el) => {
@@ -317,6 +336,8 @@ var FoniaJS = {
const okyup = elm.attr('okyup') ?? '';
const oblur = elm.attr('oblur') ?? '';
const ochan = elm.attr('ochan') ?? '';
if ((elm.attr('o3') ?? '') !== '') return;
elm.attr('o3', '1');
elm.on('keyup blur change', (e) => {
if (e.type === 'keyup' && okyup) {
var fnc = okyup.split('.');
@@ -341,10 +362,12 @@ var FoniaJS = {
});
$('input.form-check-input[type=radio]').each((i, el) => {
const elm = $(el);
if ((elm.attr('o3') ?? '') !== '') return;
elm.attr('o3', '1');
elm.on('click', () => {
const oclic = elm.attr('ochan') ?? '';
const elp = $('#'+elm.attr('name'));
if (elm.is(':checked')) elp.val(elm.val());
if (elp && elm.is(':checked')) elp.val(elm.val());
if (oclic) {
var fnc = oclic.split('.');
if (typeof window[fnc[0]][fnc[1]] === 'function'){
@@ -355,10 +378,12 @@ var FoniaJS = {
});
$('input.form-check-input[type=checkbox]').each((i, el) => {
const elm = $(el);
if ((elm.attr('o3') ?? '') !== '') return;
elm.attr('o3', '1');
elm.on('change', () => {
const odata = JSON.parse(elm.attr('odata') ?? '[]');
const ochan = elm.attr('ochan') ?? '';
elm.val(elm.is(':checked') ? odata[0] : odata[1]);
if (odata.length > 0) elm.val(elm.is(':checked') ? odata[0] : odata[1]);
if (ochan) {
var fnc = ochan.split('.');
if (typeof window[fnc[0]][fnc[1]] === 'function'){
@@ -373,7 +398,7 @@ var FoniaJS = {
});
$('.option-tags').each((i, el) => {
const elm = $(el);
if (!jQuery.isFunction(jQuery.fn.select2)) return;
if (typeof jQuery.fn.select2 !== 'function') return;
var _opts = {tags: false, dropdownAutoWidth: true, width: 'auto', theme: 'bootstrap-5', language: 'id'};
var _dmodal = elm.closest('div.modal');
if (_dmodal.length) _opts.dropdownParent = _dmodal;
@@ -394,49 +419,47 @@ var FoniaJS = {
}
if ('function' == typeof autosize) autosize($('textarea'));
},
RequestParam: function(aparam) {
var tmp_hasil = [];
var tmp_array = aparam;
var tmp_cblist = {};
var _cblist = {};
var _ohasil = {};
$('tbody input[id*="cbox"][type="checkbox"]:checked').map((i, b) => {
const arr = b.id.split('_');
if (!tmp_cblist[arr[0]]) tmp_cblist[arr[0]] = [];
tmp_cblist[arr[0]].push(arr[2]);
// for compatible only
tmp_array.push(b.id + '=' + b.value);
if (!_cblist[arr[0]]) _cblist[arr[0]] = [];
_cblist[arr[0]].push(arr[2]);
});
$.each(tmp_cblist, (i, b) => {
tmp_array.push('List_CB_' + i + '=' + b.join());
$.each(_cblist, (i, b) => {
_ohasil['List_CB_' + i] = b.join();
});
tmp_array.map(nilai => {
if (typeof nilai === "string") {
var tmp_value = "";
if (nilai.indexOf("=") == -1) {
if ($('#'+nilai).length) {
tmp_value = $('#'+nilai).val();
if (typeof tmp_value === 'undefined') {
tmp_value = ($('#'+nilai).is('.integer, .number, .double')) ? '0' : '';
if (typeof aparam === 'object') {
aparam.map(_par => {
if (typeof _par !== "string") this.return;
var _key = _par, _val = "";
const _ind = _par.indexOf('=');
if (_ind !== -1) {
_key = _par.slice(0, _ind);
_val = _par.slice(_ind + 1);
} else {
if ($('#'+_par).length) {
_val = $('#'+_par).val();
if (typeof _val === 'undefined') {
_val = ($('#'+_par).is('.integer, .number, .double')) ? 0 : '';
} else {
tmp_value = ($('#'+nilai).is('.integer, .number, .double')) ? this.StrToFloat(tmp_value) : encodeURIComponent(tmp_value);
_val = ($('#'+_par).is('.integer, .number, .double')) ? this.StrToFloat(_val) : encodeURIComponent(_val);
}
}
tmp_value = nilai + "=" + tmp_value;
} else {
tmp_value = nilai;
}
tmp_hasil.push(tmp_value);
}
});
tmp_hasil.push('SID=' + parseInt(Math.random() * 99999999));
return tmp_hasil;
_ohasil[_key] = _val;
});
}
_ohasil['SID'] = parseInt(Math.random() * 99999999);
return _ohasil;
},
StrToFloat: function(str_val) {
var nstr = str_val + "";
var hasil = "";
var fkali = 1;
if (nstr.substr(0, 3) == "Rp.") {
nstr = nstr.substr(3);
if (nstr.slice(0, 4) == "Rp.") {
nstr = nstr.slice(4);
}
for (var i = 0; i < nstr.length; i++) {
if ((parseFloat(nstr.charAt(i))) || (nstr.charAt(i) == "0") || (nstr.charAt(i) == ".")) {
@@ -505,7 +528,7 @@ var FoniaJS = {
'<div class="modal-dialog modal-dialog-centered '+_ctipe+' modal-400" role="document">'+
'<div class="modal-content">'+
'<div class="modal-header"><h5 class="modal-title" id="winAPPConfLabel">'+str_judul+'</h5><button class="btn-close" type="button" data-bs-dismiss="modal" aria-label="Close"></button></div>'+
'<div class="modal-body text-center mh-100">'+str_isi+'</div>'+
'<div class="modal-body text-center text-break mh-100">'+str_isi+'</div>'+
'<div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tidak</button><button type="button" class="btn '+_btipe+' ms-2" id="winConfirmY">Ya</button></div>'+
'</div></div></div>';
if ($('#winAPPConf').length) $('#winAPPConf').modal('dispose').remove();
@@ -605,13 +628,12 @@ var FoniaJS = {
}
},
AutoComplete: function(elm, turl, aparam, func_comp, func_key){
var arrData = [], objComp = {};
if ('string' !== typeof aparam) arrData = this.RequestParam(aparam);
var objComp = {};
objComp = {
preventEnter: true,
resolverSettings: {
url: turl,
extraData: arrData.reduce(function(o, val) { var t = val.split('='); o[t[0]] = t[1]; return o; }, {})
param: (typeof aparam === 'object') ? aparam : []
}
};
if ('object' === typeof func_comp){
@@ -641,7 +663,7 @@ class _Request {
onSuccess: () => {},
onFailure: () => {},
data: null,
dataType: 'text'
dataType: 'json'
}
constructor(options) {
@@ -653,11 +675,11 @@ class _Request {
console.log(this.options.sendParam + ", cek url php!");
return false;
}
this.options.data = FoniaJS.RequestParam(this.options.sendParam);
this.options.data = $.extend(this.options.data, FoniaJS.RequestParam(this.options.sendParam));
$.ajax({
type: 'POST',
url: this.options.url,
data: (this.options.data).join('&'),
data: this.options.data,
success: (typeof this.options.onSuccess === "function") ? this.options.onSuccess : () => {},
error: (typeof this.options.onFailure === "function") ? this.options.onFailure : () => {},
complete: FoniaJS.FormDecorated,
@@ -669,7 +691,7 @@ class _Request {
class _Request_JSONF extends _Request {
constructor(options) {
const _options = Object.assign({}, options, {'dataType':'json'});
const _options = Object.assign({}, options);
_options.onSuccess = (data) => {
if (data.length > 0) {
$(data).each((i, ini) => {
@@ -798,23 +820,20 @@ class _Request_JSONF extends _Request {
strBody += '</tbody>';
$(divData).append(strTab + strHead + strBody + strFoot + '</table>');
var opsi = { responsive: true, columnDefs: [{responsivePriority:1,targets:0},{responsivePriority:2,targets:1}], lengthMenu: [], dom: '<"row"<"col-sm-12"tr>><"row"<"col-sm-12 col-lg-auto"<"toolbar">><"col-sm-3 col-lg-auto ms-lg-auto"l><"col-sm-9 col-lg-auto"p>>', autoWidth: false, processing: true, searching: false, columns: aSortCol, order: [[iCol, (ini.config.sort_dir=='A'?'asc':'desc')]], pageLength: ini.config.row_count, stateSave: true, stateSaveCallback: function(sett,data){localStorage.setItem(ini.id,JSON.stringify(data));}, stateLoadCallback: function(sett){try{var data=JSON.parse(localStorage.getItem(ini.id))??{};data.length=ini.config.row_count;return data;}catch(e){console.log(e)}} };
var opsi = { responsive: true, columnDefs: [{responsivePriority:1,targets:0},{responsivePriority:2,targets:1},{responsivePriority:0,targets:-1}], lengthMenu: [], dom: '<"row"<"col-sm-12"tr>><"row"<"col-sm-12 col-lg-auto"<"toolbar">><"col-sm-3 col-lg-auto ms-lg-auto"l><"col-sm-9 col-lg-auto"p>>', autoWidth: false, processing: true, searching: false, columns: aSortCol, order: [[iCol, (ini.config.sort_dir=='A'?'asc':'desc')]], pageLength: ini.config.row_count, stateSave: true, stateSaveCallback: function(sett,data){localStorage.setItem(ini.id,JSON.stringify(data));}, stateLoadCallback: function(sett){try{var data=JSON.parse(localStorage.getItem(ini.id))??{};data.length=ini.config.row_count;return data;}catch(e){console.log(e)}} };
/** start live db **/
if (ini.config.live){
var post_data = {};
$(this.options.data).map((key, item) => {
var keyval = item.split("=");
if (keyval[0] == 'SID') keyval[1] = parseInt(Math.random() * 99999999);
$(this.options.data).map((key, val) => {
if (key === 'SID') val = parseInt(Math.random() * 99999999);
// fixed bug for duplicate saving
if (keyval[0] == 'mode_detail') keyval[1] = 'live-data';
if ((''+keyval[1]).indexOf('%') != -1) keyval[1] = decodeURIComponent(keyval[1]);
return post_data[keyval[0]] = keyval[1];
if (key === 'mode_detail') val = 'live-data';
//if ((''+val).indexOf('%') != -1) val = decodeURIComponent(val);
});
opsi.serverSide = true;
opsi.ajax = {
url: this.options.url,
type: 'POST',
data: post_data,
data: this.options.data,
dataFilter: (data) => {
var json = {}, jsono = {'draw':0,'recordsTotal':0,'recordsFiltered':0,'data':[]};
try {
@@ -932,7 +951,10 @@ class _Request_JSONF extends _Request {
// apply select function
if (ini.config.func_select){
$('#'+ini.id+'Tabel tbody').on('click', 'tr', (e) => {
var dta = otabel.row(e.currentTarget).data();
var elm = $(e.currentTarget);
if ((elm.attr('o3') ?? '') !== '') return;
elm.attr('o3', '1');
var dta = otabel.row(elm).data();
var fnc = ini.config.func_select.split('.');
if (typeof window[fnc[0]][fnc[1]] === 'function') { window[fnc[0]][fnc[1]](dta); }
else console.warn('fungsi '+ini.config.func_select+' tidak ada !');
@@ -946,16 +968,19 @@ class _Request_JSONF extends _Request {
$(ini.option).map((key, val) => {
if (val.type == 'checkbox'){
$('#'+ini.id+'Tabel thead input[type=checkbox][id*=_cbhead_]').on('change', (e) => {
var _chek = e.currentTarget.is(':checked');
e.currentTarget.val(e.currentTarget.is(':checked') ? val.avalue[0] : val.avalue[1]);
var _etarg = $(e.currentTarget);
var _chek = _etarg.is(':checked');
_etarg.val(_chek ? val.avalue[0] : val.avalue[1]);
$('#'+ini.id+'Tabel tbody input[type=checkbox][id*='+val.field+'_cbox_]').each((i, el) => {
el.prop('checked', _chek);
el.val(el.is(':checked') ? val.avalue[0] : val.avalue[1]);
var _el = $(el);
_el.prop('checked', _chek);
_el.val(_el.is(':checked') ? val.avalue[0] : val.avalue[1]);
});
});
$('#'+ini.id+'Tabel tbody input[type=checkbox][id*=_cbox_]').on('change', (e) => {
e.currentTarget.val(e.currentTarget.val() == val.avalue[1] ? val.avalue[0] : val.avalue[1]);
e.currentTarget.prop('checked', e.currentTarget.val() == val.avalue[0]);
var _ctarg = $(e.currentTarget);
_ctarg.val(_ctarg.val() == val.avalue[1] ? val.avalue[0] : val.avalue[1]);
_ctarg.prop('checked', _ctarg.val() == val.avalue[0]);
});
} else if (val.type == 'button'){
$('#'+ini.id+'Tabel tbody').on('click', '.'+val.icon, (e) => {
@@ -1009,7 +1034,6 @@ class _Request_JSONF extends _Request {
tr.addClass('dt-hasChild parent');
}
});
// disnini
}
var otabel = $('#'+ini.id+'Tabel').DataTable(opsi);
}
@@ -1019,11 +1043,18 @@ var Request = function (options) {
return new _Request(options);
};
/*
Request.JSON = function (options) {
const _options = Object.assign({}, options, { 'dataType': 'json' });
return new _Request(_options);
};
Request.TEXT = function (options) {
const _options = Object.assign({}, options, { 'dataType': 'text' });
return new _Request(_options);
};
*/
Request.JSONF = function(options){
return new _Request_JSONF(options);
}
+8 -8
View File
@@ -10,15 +10,16 @@
*******************************************************************/
var cPDF = function(url, options){
var Pdf = function(options){
var vars = {
'url': '',
'zoom': 80,
'param': []
};
this.construct = function(url, options){
$.extend(vars, options);
vars.url = url;
this.construct = function(options){
if (typeof options == 'object') {
$.extend(vars, options);
} else vars.url = options;
};
this.set_url = function (url){
vars.url = url;
@@ -35,11 +36,10 @@ var cPDF = function(url, options){
console.warn(vars.param + ", cek url php!");
return false;
}
vars.data = FoniaJS.RequestParam(vars.param);
$.ajax({
type: 'POST',
url: vars.url,
data: (vars.data).join('&'),
data: FoniaJS.RequestParam(vars.param),
success: (typeof vars.onSuccess === "function") ? vars.onSuccess : null,
error: (typeof vars.onFailure === "function") ? vars.onFailure : null,
}).always(FoniaJS.FormDecorated);
@@ -47,7 +47,7 @@ var cPDF = function(url, options){
};
this.showPDF = function(){
var _proto = window.location.protocol + '//';
var _src = _proto + FoniaJS.WEB_HOST + vars.url + '?' + (FoniaJS.RequestParam(vars.param)).join('&') + '#zoom='+vars.zoom+',0,0&page=1';
var _src = _proto + FoniaJS.WEB_HOST + vars.url + '?' + $.param(FoniaJS.RequestParam(vars.param)) + '#zoom='+vars.zoom+',0,0&page=1';
var _wtxt =
'<div class="modal fade" id="winAPPPDF" tabindex="-1" role="dialog" data-bs-keyboard="false" data-bs-show="false" data-bs-backdrop="static" aria-labelledby="winAPPPDFLabel" aria-hidden="true">'+
'<div class="modal-dialog modal-dialog-centered modal-fs" role="document">'+
@@ -62,5 +62,5 @@ var cPDF = function(url, options){
$(this).remove();
}).modal('show');
};
this.construct(url, options);
this.construct(options);
};
+1 -1
View File
@@ -9,7 +9,7 @@
*******************************************************************/
var cPOLEDISPLAY = function(port, options){
var PoleDisplay = function(port, options){
var _cd_port = '';
var _cd_pole = '';
var _options = {
+19 -17
View File
@@ -4,21 +4,22 @@
Desc. : JS Class Printer & Printer POS
Created By : Siau Pheng ([email protected]).
Created Date : May 27th, 2007.
Last Modified : August 21st, 2026.
Last Modified : September 21st, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
var cPRINTER = function(url, options){
var Printer = function(options){
var vars = {
'url': '',
'zoom': 90,
'param': []
};
this.construct = function(url, options){
$.extend(vars, options);
vars.url = url;
this.construct = function(options){
if (typeof options == 'object') {
$.extend(vars, options);
} else vars.url = options;
};
this.set_url = function (url){
vars.url = url;
@@ -35,11 +36,10 @@ var cPRINTER = function(url, options){
console.warn(vars.param + ", cek url php!");
return false;
}
vars.data = FoniaJS.RequestParam(vars.param);
$.ajax({
type: 'POST',
url: vars.url,
data: (vars.data).join('&'),
data: FoniaJS.RequestParam(vars.param),
success: (txt) => {
var $printData = $('#dataPrint');
if (!$printData.length) {
@@ -54,11 +54,10 @@ var cPRINTER = function(url, options){
};
this.doPreview = function(){
if (!vars.url) console.warn(vars.param + ", cek url php!");
vars.data = FoniaJS.RequestParam(vars.param);
$.ajax({
type: 'POST',
url: vars.url,
data: (vars.data).join('&'),
data: FoniaJS.RequestParam(vars.param),
success: (txt) => {
if ('' == txt) {
FoniaJS.showInfo('Tidak ada data untuk pembuatan laporan !');
@@ -89,10 +88,10 @@ var cPRINTER = function(url, options){
error: (typeof vars.onFailure === "function") ? vars.onFailure : null,
});
};
this.construct(url, options);
this.construct(options);
};
var cPRINTERPOS = function(url, options) {
var PrinterPos = function(options) {
var b_default = false;
var _options = {
'url': '',
@@ -105,9 +104,10 @@ var cPRINTERPOS = function(url, options) {
'chr_sbold': "\x1B\x21\x31",
'chr_uline': "\x1B\x21\x80"
};
this.construct = function(url, options) {
$.extend(_options, options);
_options.url = url;
this.construct = function(options) {
if (typeof options == 'object') {
$.extend(_options, options);
} else _options.url = options;
if (FoniaJS._def_printer) _options.printer = FoniaJS._def_printer;
};
this.detectPrinter = function() {
@@ -162,7 +162,7 @@ var cPRINTERPOS = function(url, options) {
};
this.do_print = function(nama_p, url, params) {
var qzcfg = qz.configs.create(nama_p);
new Request.JSON({
new Request({
url: url,
sendParam: params,
onSuccess: (ajson) => {
@@ -181,7 +181,9 @@ var cPRINTERPOS = function(url, options) {
ohead.push("\x1B\x40");
ohead.push("\x1B\x61\x01");
if (adata.config.logo != null) {
ohead.push({type:'raw',format:'image',data:adata.config.logo,options:{language:'ESCPOS',dotDensity:'double'}});
//ohead.push({type:'raw',format:'image',data:adata.config.logo,options:{language:'ESCPOS',dotDensity:'double'}});
//ohead.push("\x1B\x32");
ohead.push({type:'raw',format:'image',flavor:'base64',data:adata.config.logo,options:{language:'ESCPOS',dotDensity:'double'}});
ohead.push("\x1B\x32");
}
if (parseInt(adata.config.fontsize) == 2) {
@@ -230,5 +232,5 @@ var cPRINTERPOS = function(url, options) {
}
return notaout;
};
this.construct(url, options);
this.construct(options);
};
-73
View File
@@ -1,73 +0,0 @@
/*******************************************************************
Module : /assets/js/share.js
Desc. : JS Class Share File Cross Browser
Created By : Siau Pheng ([email protected]).
Created Date : May 27th, 2007.
Last Modified : January 19th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
var cSHARE = function(url, options) {
var _options = {
'url': '',
'filename': '',
'title': '',
'text': 'share dari aplikasi'
};
var _params = [];
this.construct = function(url, options){
if (typeof url == 'object') {
$.extend(_options, url);
} else {
$.extend(_options, options);
_options.url = url;
}
};
this.set_url = function (url){
_options.url = url;
};
this.add_param = function(par_id, par_val) {
var _getvalue = (par_val) ? par_id + '=' + escape(par_val) : par_id;
_params.push(_getvalue);
};
this.share = async function() {
if (!_options.url) {
console.warn('cek url !');
return false;
}
var _pro = (window.location.protocol=='https:') ? 'https://' : 'http://';
var _src = _pro+FoniaJS.WEB_HOST + _options.url + '?' + (FoniaJS.RequestParam(_params)).join('&');
try {
const response = await fetch(_src)
.then(response => {
const cDispo = response.headers.get('Content-Disposition');
if (cDispo && cDispo.indexOf('filename=') !== -1) {
_options.filename = cDispo.split('filename=')[1].split(';')[0].replace(/"/g, '');
}
return response;
});
const blob = await response.blob();
const file = new File([blob], _options.filename, { type: blob.type });
if (navigator.canShare && navigator.canShare({ files: [file] })) {
await navigator.share({
files: [file],
title: _options.title ?? _options.filename,
text: _options.text
});
} else {
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = _options.filename;
link.click();
}
} catch (error) {
console.error('Sharing gagal:', error);
}
};
this.construct(url, options);
};
+7 -7
View File
@@ -10,14 +10,15 @@
*******************************************************************/
var cSIMULATOR = function(url, options){
var Simulator = function(options){
var vars = {
'url': '',
'param': []
};
this.construct = function(url, options){
$.extend(vars, options);
vars.url = url;
this.construct = function(options){
if (typeof options == 'object') {
$.extend(vars, options);
} else vars.url = options;
};
this.set_url = function (url){
vars.url = url;
@@ -28,11 +29,10 @@ var cSIMULATOR = function(url, options){
},
this.doPreview = function(){
if (!vars.url) console.warn(vars.param + ", cek url php!");
vars.data = FoniaJS.RequestParam(vars.param);
$.ajax({
type: 'POST',
url: vars.url,
data: (vars.data).join('&'),
data: FoniaJS.RequestParam(vars.param),
success: function(data){
if (data.length == 0) {
FoniaJS.showInfo('Tidak ada data !');
@@ -80,5 +80,5 @@ var cSIMULATOR = function(url, options){
dataType: 'json'
});
};
this.construct(url, options);
this.construct(options);
};
+8 -9
View File
@@ -17,21 +17,20 @@
}
],
"require": {
"php" : ">=8.3",
"flightphp/core": "^3.18",
"php": ">=8.3",
"flightphp/core": "^3.19",
"flightphp/session": "^0.3",
"mpdf/mpdf": ">=8.0",
"matthiasmullie/minify": ">=1.3",
"endroid/qr-code": ">=4.4",
"phpoffice/phpspreadsheet": ">=1.29",
"shuchkin/simplexlsxgen": "^1.3"
"mpdf/mpdf": "^8.3",
"avadim/fast-excel-writer": "^6.19",
"matthiasmullie/minify": "^1.3",
"endroid/qr-code": "^6.1"
},
"autoload": {
"classmap": ["src/"],
"psr-4": {
"siaupheng\\webapp\\": "src/"
"Webapp\\": "src/"
},
"files": [
"src/Function/Auth.php",
"src/Function/Misc.php"
]
},
+51 -44
View File
@@ -2,11 +2,10 @@
/*******************************************************************
Module : /Web/Auth.php
Desc. : Class User Control dan Manajemen
Module : /App/Auth.php
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : March 16th, 2008.
Last Modified : August 22nd, 2026.
Last Modified : October 21st, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -14,82 +13,78 @@
declare(strict_types=1);
namespace siaupheng\webapp\Web;
namespace Webapp\App;
use \flight\Engine;
use \flight\Session;
use \flight\database\SimplePdo;
/**
* Class Auth
*
* Kontrol dan Manajemen User Session.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\App
*/
final class Auth {
private int $__id_reg = 0;
private int $id_reg = 0;
protected Engine $app;
protected SimplePdo $db;
protected Session $session;
public function __construct(Engine $app, SimplePdo $db, Session $session){
/**
* @param Engine $app
*/
public function __construct(Engine $app){
$this->app = $app;
$this->db = $db;
$this->session = $session;
$this->__id_reg = (int)$this->session->get('__WEB_APP', ['REG_ID'=>0])['REG_ID'];
}
public function set_id_reg(int|string $id = 0): void {
if ($id > 0) $this->__id_reg = (int)$id;
$this->db = $app->db();
$this->session = $app->session();
$this->id_reg = (int) $this->session->get('WEB_APP', ['PARENT_CODE'=>0])['PARENT_CODE'];
}
public function user_check(string $user, string $pass): bool {
$i_hasil = (int)$this->db->fetchField('SELECT COUNT(*) FROM app_operator WHERE Username=? AND Password=MD5(?) AND Aktif=1', [$user, $pass]);
$i_hasil = (int) $this->db->fetchField('SELECT COUNT(*) FROM app_operator WHERE Username=? AND Password=MD5(?) AND Aktif=1', [$user, $pass]) ?? 0;
return ($i_hasil > 0 ? true : false);
}
public function user_data(string $user): array {
$adata = $this->db->fetchRow('SELECT *,DECODE(Menu,?) Menu2 FROM app_operator WHERE Username=?', [$this->__id_reg, $user])->getData();
$adata['Menu'] = $adata['Menu2'];
unset($adata['Menu2']);
public function user_data(string $user, bool $gen_module=true): array {
$adata = [ 'Grup_MenuID' => 0 ];
$xdata = $this->db->fetchRow('SELECT UserID,Grup_MenuID,Username,Nama,Posisi,Email,HP,Level,Last_IP,Last_Date FROM app_operator WHERE Username=?', [$user]);
if ($xdata) $adata = $xdata->getData();
if (empty($this->session->get('APP_TOKEN'))) {
$_token = $this->genToken(60);
$this->session->set('APP_TOKEN', $_token);
$this->db->insert('app_token', [ 'Token' => $_token, 'UserID' => $adata['UserID'], 'IP' => $this->app->request()->ip ]);
}
if ((int)$adata['Grup_MenuID'] > 0) $adata['Menu_Grup'] = $this->user_allmenu((int)$adata['Grup_MenuID']);
$adata['UNIX'] = time();
$adata['LOCALE'] = $this->session->get('__WEB_APP', ['DEF_LOCALE'=>'id'])['DEF_LOCALE'];
$adata['LOCALE'] = $this->session->get('WEB_APP', ['DEF_LOCALE'=>'id'])['DEF_LOCALE'];
$adata['MENU_MODUL'] = [];
return $adata;
}
public function gen_module_menu(): void {
$amodul = []; $aallow = []; $tallow = '';
if ($this->session->get('__WEB_APP', ['APP_MODULE'=>0])['APP_MODULE']) {
$tallow = $this->db->fetchField('SELECT Modul_Akses FROM app_menu_grup WHERE Grup_MenuID=?', [$this->session->get('__WEB_USER', ['Grup_MenuID'=>0])['Grup_MenuID']]);
if ($gen_module === true && !empty($this->session->get('WEB_APP')['APP_MODULE'])) {
$tallow = $this->db->fetchField('SELECT Modul_Akses FROM app_menu_grup WHERE Grup_MenuID=?', [$adata['Grup_MenuID']]) ?? '';
$aallow = explode(",", $tallow);
if (count($aallow) > 0) {
$stat = $this->db->runQuery('SELECT * FROM (SELECT APP_MODULE,APP_PATH FROM app_config) A LEFT JOIN (SELECT Modul,Urut,Judul,Icon FROM app_menu WHERE Level=0) B ON (A.APP_MODULE=B.Modul) ORDER BY B.Urut');
while ($row = $stat->fetch()) {
if (!in_array($row['Modul'], $aallow) || $row['Modul']==$this->session->get('__WEB_APP')['APP_MODULE']) continue;
$amodul[] = $row;
if (!in_array($row['Modul'], $aallow) || $row['Modul'] === $this->session->get('WEB_APP')['APP_MODULE']) continue;
$adata['MENU_MODUL'][] = $row;
}
}
}
$auser = $this->session->get('__WEB_USER', []);
$auser['MENU_MODUL'] = $amodul;
$this->session->set('__WEB_USER', $auser);
}
public function user_allmenu(int $id_grup = 0): string {
$allmenu = $this->db->fetchField('SELECT DECODE(Menu,?) MenuX FROM app_menu_grup WHERE Grup_MenuID=?', [$this->__id_reg, $id_grup]);
return $allmenu;
return $adata;
}
public function user_check_level(string $user, int $level = 9): bool {
$i_hasil = (int)$this->db->fetchField('SELECT COUNT(*) FROM app_operator WHERE Username=? AND Level<=? AND Aktif=1', [$user, $level]);
$i_hasil = (int) $this->db->fetchField('SELECT COUNT(*) FROM app_operator WHERE Username=? AND Level<=? AND Aktif=1', [$user, $level]);
return ($i_hasil > 0 ? true : false);
}
public function user_log(): void {
$_user_id = $this->session->get('__WEB_USER')['UserID'] ?? 0;
$_user_id = $this->session->get('WEB_USER')['UserID'] ?? 0;
if ($_user_id === 0) return;
$a_hasil = $this->db->fetchRow('SELECT * FROM app_logs WHERE UserID=? ORDER BY Last_Date DESC LIMIT 1', [$_user_id])->getData();
if (count($a_hasil) > 0) {
@@ -103,13 +98,13 @@ final class Auth {
}
public function token_check(string $token): bool {
$hasil = (bool)$this->db->fetchField('SELECT 1 FROM app_token WHERE Token=?', [$token ?? $this->session->get('APP_TOKEN')]);
if ($hasil === true) $this->db->update('app_token', ['DateStamp' => 'NOW()'], 'Token=?', [$token ?? $this->session->get('APP_TOKEN')]);
$hasil = (bool) $this->db->fetchField('SELECT 1 FROM app_token WHERE Token=?', [$token ?? $this->session->get('APP_TOKEN')]);
if ($hasil === true) $this->db->runQuery('UPDATE app_token SET DateStamp=NOW() WHERE Token=?', [$token ?? $this->session->get('APP_TOKEN')]);
return $hasil;
}
public function token_update(): void {
$this->db->update('app_token', ['DateStamp' => 'NOW()'], 'Token=?', [$this->session->get('APP_TOKEN')]);
$this->db->runQuery('UPDATE app_token SET DateStamp=NOW() WHERE Token=?', [$this->session->get('APP_TOKEN')]);
}
public function redirect(string $appUrl): string {
@@ -126,9 +121,21 @@ final class Auth {
}
public function getUserByToken(string $token): string {
$hasil = $this->db->fetchField('SELECT Username FROM app_operator WHERE UserID IN (SELECT UserID FROM app_token WHERE Token=?) LIMIT 1', [$token ?? $this->session->get('APP_TOKEN')]);
$hasil = $this->db->fetchField('SELECT Username FROM app_operator WHERE UserID IN (SELECT UserID FROM app_token WHERE Token=?) LIMIT 1', [$token ?? $this->session->get('APP_TOKEN')]) ?? '';
return $hasil;
}
public function pos_login(int $id_cab, int $id_user, int $unix, string $ip): void {
if (empty($id_cab) || empty($id_user) || empty($ip)) return;
$this->db->delete('disp_login', 'CabID=? AND UserID=?', [$id_cab, $id_user]);
$this->db->runQuery('INSERT INTO disp_login (IP, CabID, UserID, Unix, Date) VALUES (?, ?, ?, ?, NOW())', [ $ip, $id_cab, $id_user, $unix ?? 0 ]);
}
public function pos_logout(int $id_cab, int $id_user, int $unix, string $ip): void {
if (empty($id_cab) || empty($id_user) || empty($ip)) return;
$this->db->delete('disp_login', 'CabID=? AND UserID=? AND IP=? AND Unix=?', [$id_cab, $id_user, $ip, $unix ?? 0 ]);
}
}
?>
+58
View File
@@ -0,0 +1,58 @@
<?php
/*******************************************************************
Module : /App/Register.php
Created By : Siau Pheng ([email protected]).
Created Date : November 23th, 2011.
Last Modified : September 10th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
declare(strict_types=1);
namespace Webapp\App;
use \flight\Engine;
use \flight\Session;
use \flight\database\SimplePdo;
/**
* Class Register
*
* Registrasi aplikasi.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <[email protected]>
*
* @package Webapp\App
*/
final class Register {
public function __construct(){
}
public static function reg_id(Session $session): string {
$id = (string) $session->get('WEB_APP', ['REG_ID'=>''])['REG_ID'];
return (substr($id,0,3).".".substr($id,3,3).".".substr($id,6));
}
public static function reg_code(Session $session): string {
$id = (string) $session->get('WEB_APP', ['REG_CODE'=>''])['REG_CODE'];
return (substr($id,0,6)."-".substr($id,6,5)."-".substr($id,11,5)."-".substr($id,16,5)."-".substr($id,21,5)."-".substr($id,26,6));
}
public static function reg_check(Session $session): bool {
$webapp = $session->get('WEB_APP');
return (bool) (isset($webapp['REG_STATUS']) && $webapp['REG_STATUS']) ?? false;
}
public static function reg_status(SimplePdo $db, array $apps): array {
$kode_db = (bool) $db->fetchField('SELECT UPPER(CONVERT(MD5(CONCAT(REG_YEAR,CONVERT(MD5(CONCAT(REG_ID,REG_NAME)) using latin1),REG_ID,REG_NAME)) using latin1))=REG_CODE FROM app_config WHERE REG_ID=?', [$apps['APP_CODE'] ?? '']);
return [ 'REG_STATUS' => $kode_db === true ];
}
}
?>
+27 -18
View File
@@ -2,8 +2,7 @@
/*******************************************************************
Module : /Web/Update.php
Desc. : Class Update Aplikasi Otomatis
Module : /App/Update.php
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : June 14th, 2013.
Last Modified : August 22nd, 2026.
@@ -14,26 +13,37 @@
declare(strict_types=1);
namespace siaupheng\webapp\Web;
namespace Webapp\App;
use \flight\Engine;
use \flight\Session;
/**
* Class Update
*
* Update Otomatis Aplikasi berbasis GIT.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\App
*/
final class Update {
protected Array $__conf = [];
protected Bool $is_git = false;
private Array $__conf = [];
private Bool $is_git = false;
protected Engine $app;
public function __construct(Engine $app, Session $session){
/**
* @param Engine $app
*/
public function __construct(Engine $app){
$this->app = $app;
$this->__conf = $session->get('__WEB_APP');
$this->__conf = $app->session()->get('WEB_APP');
$this->current();
}
public function current() {
$_target = $this->__conf['REAL_PATH'];
if (isset($_target)) chdir($_target);
public function current(): void {
if (defined('PROJECT_ROOT')) chdir(PROJECT_ROOT);
try {
$output = shell_exec("git log -1 --pretty=format:\"%H||%s||%ci\" --abbrev-commit 2>&1");
if ($output) {
@@ -57,7 +67,7 @@ final class Update {
}
}
public function check() {
public function check(): array {
$_ainfo['cur_version'] = $this->__conf['APP_BUILD'];
$_ainfo['cur_sha'] = substr($this->__conf['GIT_SHA1'], 0, 10);
$_ainfo['cur_sha1'] = $this->__conf['GIT_SHA1'];
@@ -89,14 +99,13 @@ final class Update {
return $_ainfo;
}
public function go() {
$_target = $this->__conf['REAL_PATH'];
public function go(): array {
$_branch = $this->__conf['GIT_BRANCH'] ?? "main";
if (isset($_target)) {
chdir($_target);
if (defined('PROJECT_ROOT')) {
chdir(PROJECT_ROOT);
$output = shell_exec("git reset --hard HEAD && git pull origin {$_branch} 2>&1");
return ['success'=>true,'message'=>$output];
} else return ['success'=>false,'message'=>"Tanpa REAL_PATH !"];
} else return ['success'=>false,'message'=>"Tanpa PROJECT_ROOT !"];
}
public function mysql() {
+79
View File
@@ -0,0 +1,79 @@
<?php
/*******************************************************************
Module : /App/User.php
Created By : Siau Pheng ([email protected]).
Created Date : September 10th, 2026.
Last Modified : September 10th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
declare(strict_types=1);
namespace Webapp\App;
use \flight\Engine;
/**
* Class User
*
* User & Role Class.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <[email protected]>
*
* @package Webapp\App
*/
final class User {
private array $web_user;
protected Engine $app;
/**
* @param Engine $app
*/
public function __construct(Engine $app) {
$this->app = $app;
$this->web_user = (array) $app->session()->get('WEB_USER');
}
public function logged(): bool {
return !empty($this->web_user);
}
public function is_level(int $level = 9): bool {
if (($this->web_user['Level'] ?? 9) <= $level) return true;
return false;
}
public function not_level(int $level = 9): bool {
if (($this->web_user['Level'] ?? 9) !== $level) return true;
return false;
}
public function id(int $digit = 0): string|int {
$id_user = (int) $this->web_user['UserID'] ?? 0;
if ($digit > 0) return isi_nol($id_user, $digit);
return $id_user;
}
public function username(): string {
return (string) $this->web_user['Username'] ?? '';
}
public function level(): int {
return (int) $this->web_user['Level'] ?? 9;
}
public function unix(): string {
return (string) $this->web_user['UNIX'] ?? '0';
}
public function nama(): string {
return (string) $this->web_user['Nama'] ?? '';
}
}
+17 -4
View File
@@ -3,7 +3,6 @@
/*******************************************************************
Module : /DB/CheckSQL.php
Desc. : Class Check SQL / Repair Database
Created By : Siau Pheng ([email protected]).
Created Date : May 11th, 2011.
Last Modified : August 21st, 2026.
@@ -14,20 +13,34 @@
declare(strict_types=1);
namespace siaupheng\webapp\DB;
namespace Webapp\DB;
use \Exception;
use \flight\Engine;
use \flight\database\SimplePdo;
/**
* Class CheckSQL
*
* Check Database Mysql/MariaDB dan Repair.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <[email protected]>
*
* @package Webapp\DB
*/
final class CheckSQL {
private Array $__atabel = [];
protected Engine $app;
protected SimplePdo $db;
public function __construct(Engine $app, SimplePdo $db) {
/**
* @param Engine $app
*/
public function __construct(Engine $app) {
$this->app = $app;
$this->db = $db;
$this->db = $app->db();
$nama_db = $this->db->fetchField('SELECT DATABASE()');
$arow = $this->db->fetchAll("SELECT TABLE_NAME,ENGINE,TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='".$nama_db."' AND TABLE_TYPE='BASE TABLE'");
foreach ($arow as $row) {
+6 -6
View File
@@ -15,7 +15,7 @@
//todo: deprecated
declare(strict_types=1);
namespace siaupheng\webapp\DB;
namespace Webapp\DB;
final class DumpSQL {
private $__adata = array();
@@ -24,7 +24,7 @@ final class DumpSQL {
public function __construct($db = null){
if (is_resource($db)) { $this->__db = $db; }
else { $this->__db = new \siaupheng\webapp\DB\MySQL(); }
else { $this->__db = new Webapp\DB\MySQL(); }
$this->__adata = $this->__db->getConfig();
}
@@ -56,7 +56,7 @@ final class DumpSQL {
public function create_backup($folder="backups") {
$namafile = date("Ymd").".gz";
$folder = $_SESSION['__WEB_APP']['REAL_PATH'].$folder."/".date("Y");
$folder = PROJECT_ROOT.$folder."/".date("Y");
if (!is_dir($folder)) mkdir($folder);
if (file_exists($folder."/".$namafile)) unlink($folder."/".$namafile);
$_cmd = "mysqldump -C --hex-blob -h ".$this->__adata['host']." -P ".$this->__adata['port']." -u ".$this->__adata['user']." -p".$this->__adata['pwd']." ".$this->__adata['db'];
@@ -97,8 +97,8 @@ final class DumpSQL {
}
public function disk_space() {
$_free = disk_free_space($_SESSION['__WEB_APP']['REAL_PATH']);
$_tot = disk_total_space($_SESSION['__WEB_APP']['REAL_PATH']);
$_free = disk_free_space(PROJECT_ROOT);
$_tot = disk_total_space(PROJECT_ROOT);
$_used = $_tot - $_free;
$_aret = array();
$_aret['TOTAL'] = $this->format_bytes($_tot);
@@ -110,7 +110,7 @@ final class DumpSQL {
}
public function update_list($folder="backups") {
$folder = $_SESSION['__WEB_APP']['REAL_PATH'].$folder;
$folder = PROJECT_ROOT.$folder;
$this->__db->Query("TRUNCATE TABLE app_backup");
$afile = $this->get_file_list($folder);
foreach($afile as $_key => $_val) {
+29 -18
View File
@@ -3,10 +3,9 @@
/*******************************************************************
Module : /DB/SQL.php
Desc. : Class Query database
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : February 2nd, 2007.
Last Modified : August 21st, 2026.
Last Modified : September 11th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -14,12 +13,24 @@
declare(strict_types=1);
namespace siaupheng\webapp\DB;
namespace Webapp\DB;
use ErrorException;
use \flight\Engine;
use \flight\Session;
use \flight\database\SimplePdo;
use siaupheng\webapp\Web\Param;
use Webapp\Web\Param;
/**
* Class SQL
*
* Database CRUD dengan data dari GET/POST.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\DB
*/
final class SQL {
private string $_ttable;
@@ -27,12 +38,15 @@ final class SQL {
private array $_awhere = [];
protected Engine $app;
protected SimplePdo $db;
protected array webuser;
protected array $webuser;
public function __construct(Engine $app, Ssssion $session, SimplePdo $db){
/**
* @param Engine $app
*/
public function __construct(Engine $app){
$this->app = $app;
$this->db = $db;
$this->webuser = $session->get('__WEB_USER', ['UserID'=>0, 'UNIX'=>0]);
$this->db = $app->db();
$this->webuser = $app->session()->get('WEB_USER', ['UserID'=>0, 'UNIX'=>0]);
}
//todo: deprecated
@@ -44,20 +58,18 @@ final class SQL {
$this->_ttable = $table;
}
public function add_param(string $param = "", string|int|null $value = null, bool $nomor = false): void {
$req = Param::Get($param);
public function add_param(string $param = "", mixed $value = null, bool $nomor = false): void {
$this->_afield[] = [
'field' => $param,
'value' => (is_null($value) && !empty($req)) ? $req : $value,
'value' => is_null($value) ? Param::Get($param) : $value,
'numbe' => $nomor,
];
}
public function add_param_date(string $param = "", string|null $value = null): void {
$req = Param::Get($param);
$this->_afield[] = [
'field' => $param,
'value' => tgl_sql2str((is_null($value) && !empty($req)) ? $req : $value),
'value' => tgl_sql2str(is_null($value) ? Param::Get($param, '00-00-0000') : $value),
'numbe' => false,
];
}
@@ -102,11 +114,10 @@ final class SQL {
];
}
public function add_where(string $field = "", string|int|null $value = null, bool $nomor = false): void {
$req = Param::Get($param);
public function add_where(string $field = "", mixed $value = null, bool $nomor = false): void {
$this->_awhere[] = [
'field' => $field,
'value' => (is_null($value) && !empty($req)) ? $req : $value,
'value' => is_null($value) ? Param::Get($field) : $value,
'numbe' => $nomor,
];
}
@@ -175,8 +186,8 @@ final class SQL {
$this->db->runQuery($tsql, $__aexec);
}
public function LastInsertID(): int {
return $this->db->lastInsertId();
public function LastInsertID(?string $name = null): mixed {
return $this->db->lastInsertId($name);
}
}
+14 -4
View File
@@ -2,8 +2,7 @@
/*******************************************************************
Module : /Data/CSV.php
Desc. : Class pembuatan file CSV
Module : /Data/Csv.php
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : April 2rd, 2011.
Last Modified : August 21st, 2026.
@@ -14,12 +13,23 @@
declare(strict_types=1);
namespace siaupheng\webapp\Data;
namespace Webapp\Data;
define( DELI_CSV, ";" );
define( CRLF_CSV, "\r\n" );
final class CSV {
/**
* Class Csv
*
* Membuat file Csv.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Data
*/
final class Csv {
private $__avalue = [];
private $__atabel = [];
+155 -80
View File
@@ -3,10 +3,9 @@
/*******************************************************************
Module : /Data/Cache.php
Desc. : Class cache css dan js aplikasi
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : March 16th, 2008.
Last Modified : August 21st, 2026.
Last Modified : October 12th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -14,64 +13,93 @@
declare(strict_types=1);
namespace siaupheng\webapp\Data;
namespace Webapp\Data;
use \flight\Engine;
use \flight\Session;
use \flight\database\SimplePdo;
use \FilesystemIterator;
use \MatthiasMullie\Minify;
use \SplFileInfo;
final class Cache {
private $__cachedir = "";
private $__cssdir = "";
private $__localedir = "";
private $__jsdir = "";
private $__jsapp = "";
private $__rootdir = "";
private $__ini = [];
protected Engine $app;
protected Session $session;
protected array $__asset = [];
/**
* Class Cache
*
* Membuat Cache gabungan CSS dan JS sesuai dengan session.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Data
*/
public function __construct(Engine $app, Session $session) {
final class Cache {
private string $cachedir;
private string $cssdir;
private string $localedir;
private string $jsdir;
private string $jsapp;
private string $rootdir;
private array $ini;
private array $web_app;
private array $web_user;
private array $my_menu = [];
private bool $is_login;
private bool $IS_DEV = false;
protected Engine $app;
protected SimplePdo $db;
protected array $asset = [];
/**
* @param Engine $app
*/
public function __construct(Engine $app) {
$this->app = $app;
$this->session = $session;
$rootdir = (defined('PROJECT_ROOT')) ? PROJECT_ROOT : $this->app->get('app.project_root');
$this->__cachedir = $rootdir . '/public/chunks/';
$this->__localedir = $rootdir . '/app/Scripts/locale/';
$this->__jsapp = $rootdir . '/app/Scripts/';
$this->__cssdir = __DIR__ . '/../../assets/css/';
$this->__jsdir = __DIR__ . '/../../assets/js/';
$this->__rootdir = $rootdir . '/';
if (!is_dir($this->__cachedir)) mkdir($this->__cachedir, 0755, true);
if (!file_exists($this->__cachedir . "cache.ini")) {
$this->__ini = [
'login' => [ 'stamp' => 0, 'css' => "", 'js' => "", 'app' => "", ],
'index' => [ 'stamp' => 0, 'css' => "", 'js' => "", 'app' => "", ],
'display' => [ 'stamp' => 0, 'css' => "", 'js' => "", 'app' => "", ],
$this->db = $app->db();
$this->web_app = $app->session()->get('WEB_APP') ?? [];
$this->web_user = $app->session()->get('WEB_USER') ?? [];
$this->is_login = (count($this->web_user) > 0);
$rootdir = (defined('PROJECT_ROOT')) ? PROJECT_ROOT : $app->get('app.project_root');
$this->cachedir = $rootdir . '/temp/cache/';
$this->localedir = $rootdir . '/app/Scripts/locale/';
$this->jsapp = $rootdir . '/app/Scripts/';
$this->cssdir = realpath(__DIR__ . '/../../assets/css') . '/';
$this->jsdir = realpath(__DIR__ . '/../../assets/js') . '/';
$this->rootdir = $rootdir . '/';
if (!is_dir($this->cachedir)) mkdir($this->cachedir, 0755, true);
if (!file_exists($this->cachedir . "cache.ini")) {
$this->ini = [
'login' => [ 'css' => "", 'js' => "", 'app' => "", ],
'index' => [ 'css' => "", 'js' => "", 'app' => "", ],
'monitor' => [ 'css' => "", 'js' => "", 'app' => "", ],
];
$this->save_ini();
} else $this->__ini = parse_ini_file($this->__cachedir . "cache.ini", true);
} else $this->ini = parse_ini_file($this->cachedir . "cache.ini", true);
}
public function set_dev(bool $is_dev = false): void {
$this->IS_DEV = $is_dev;
}
public function set_asset(array $asset = []): void {
$this->__asset = $asset;
$this->asset = $asset;
}
private function gen_file(string $mode = "index", string $type = "css"): array {
$itime = 0;
$afile = [];
if ($type == "css") {
$_afile = array_unique($this->__asset['css'][$mode] ?? []);
if ($type === "css") {
$_afile = array_unique($this->asset['css'][$mode] ?? []);
foreach ($_afile as $__key => $val) {
if (!file_exists($this->__cssdir . $val)) continue;
$_file = new SplFileInfo($this->__cssdir . $val);
if (!file_exists($this->cssdir . $val)) continue;
$_file = new SplFileInfo($this->cssdir . $val);
$afile[] = $_file->getRealPath();
$itime += $_file->getMTime();
}
if (is_dir($this->__rootdir . 'app/Styles/')) {
$iterator = new FilesystemIterator($this->__rootdir . 'app/Styles/', FilesystemIterator::SKIP_DOTS);
if (is_dir($this->rootdir . 'app/Styles/')) {
$iterator = new FilesystemIterator($this->rootdir . 'app/Styles/', FilesystemIterator::SKIP_DOTS);
foreach ($iterator as $_file) {
if ($_file->isFile()) {
$afile[] = $_file->getRealPath();
@@ -79,18 +107,18 @@ final class Cache {
}
}
}
} else if ($type == "js") {
$_afile = array_unique($this->__asset['js'][$mode] ?? []);
} else if ($type === "js") {
$_afile = array_unique($this->asset['js'][$mode] ?? []);
foreach ($_afile as $__key => $val) {
if (!file_exists($this->__jsdir . $val)) continue;
$_file = new SplFileInfo($this->__jsdir . $val);
if (!file_exists($this->jsdir . $val)) continue;
$_file = new SplFileInfo($this->jsdir . $val);
$afile[] = $_file->getRealPath();
$itime += $_file->getMTime();
}
// add locale file
$ljs = ($this->session->get('__WEB_USER')['LOCALE'] ?? $this->session->get('__WEB_APP')['DEF_LOCALE']).'.js';
if (is_dir($this->__localedir)) {
$iterator = new \FilesystemIterator($this->__localedir, \FilesystemIterator::SKIP_DOTS);
$ljs = ($this->web_user['LOCALE'] ?? $this->web_app['DEF_LOCALE']).'.js';
if (is_dir($this->localedir)) {
$iterator = new \FilesystemIterator($this->localedir, \FilesystemIterator::SKIP_DOTS);
foreach ($iterator as $_file) {
if ($_file->isFile() && str_ends_with($_file->getFilename(), $ljs)) {
$afile[] = $_file->getRealPath();
@@ -98,25 +126,30 @@ final class Cache {
}
}
}
} else if ($type == "app") {
if ($mode === 'index') {
if (is_dir($this->__jsapp)) {
$dirIterator = new \RecursiveDirectoryIterator($this->__jsapp, \RecursiveDirectoryIterator::SKIP_DOTS);
} else if ($type === "app") {
if (is_dir($this->jsapp)) {
if (file_exists($this->jsapp . $mode . '.js')) {
$_file = new SplFileInfo($this->jsapp . $mode . '.js');
$afile[] = $_file->getRealPath();
$itime += $_file->getMTime();
}
if ($mode === 'index') {
$_ajs = ['system/profile', 'system/chpasswd'];
$amenu = array_values($this->my_menu ?? []);
$_ops = $this->db->fetchColumn("SELECT Link FROM app_menu WHERE Kode IN (?) AND Link<>'' ORDER BY Kode", [$amenu]);
if ($_ops) $_ajs = array_merge($_ajs, $_ops);
$dirIterator = new \RecursiveDirectoryIterator($this->jsapp, \RecursiveDirectoryIterator::SKIP_DOTS);
$dirFilter = new \RecursiveCallbackFilterIterator($dirIterator, fn($curr, $key, $iter) => !($curr->isDir() && in_array($curr->getFilename(), ['locale'])));
$iterator = new \RecursiveIteratorIterator($dirFilter);
foreach ($iterator as $_file) {
if ($_file->isFile() && !in_array($_file->getFilename(), ['login.js','display.js'])) {
if ($_file->isFile() &&
!in_array($_file->getFilename(), ['login.js','index.js','monitor.js']) &&
array_any($_ajs, fn($js) => str_ends_with(str_replace(['_','\\'],['','/'],$_file->getRealPath()), $js.'.js'))) {
$afile[] = $_file->getRealPath();
$itime += $_file->getMTime();
}
}
}
} else {
if (file_exists($this->__jsapp . $mode . '.js')) {
$_file = new SplFileInfo($this->__jsapp . $mode . '.js');
$afile[] = $_file->getRealPath();
$itime += $_file->getMTime();
}
}
}
return [ $afile, $itime ];
@@ -125,8 +158,8 @@ final class Cache {
private function create_cache(string $type = "css", array $afile = [], string $cachefile = ""): void {
$contents = ''; $smini = null;
$bpublic = ($this->app->request()->ip === '127.0.0.1') ? false : true;
if ($bpublic == true) {
if ($type=="css") {
if ($bpublic === true) {
if ($type === "css") {
$smini = new Minify\CSS;
} else {
$smini = new Minify\JS;
@@ -134,7 +167,7 @@ final class Cache {
}
foreach ($afile as $nfile) {
if (file_exists($nfile)) {
if ($bpublic == true) {
if ($bpublic === true) {
$smini->add($nfile);
} else {
$contents .= "\n". file_get_contents($nfile);
@@ -142,61 +175,103 @@ final class Cache {
}
}
if ($bpublic) $contents = $smini->minify();
file_put_contents($this->__cachedir . $cachefile, $contents);
file_put_contents($this->cachedir . $cachefile, $contents);
}
private function save_ini(): void {
$content = "";
foreach ($this->__ini as $key => $elem) {
$content .= ($content==""?"":"\n"). "[".$key."]\n";
unset ($this->ini['index']['app']);
foreach ($this->ini as $key => $elem) {
$content .= ($content === ""?"" : "\n"). "[".$key."]\n";
foreach ($elem as $key2 => $elem2) {
if ($elem2=="") $content .= $key2." = \n";
if ($key)
if ($elem2 === "") $content .= $key2." = \n";
else $content .= $key2." = \"".$elem2."\"\n";
}
}
file_put_contents($this->__cachedir . "cache.ini", $content);
file_put_contents($this->cachedir . "cache.ini", $content);
}
public function Cache(string $mode = "index"): array {
if ($mode === 'index') {
$this->ini['index']['app'] = (string) $this->db->fetchField("SELECT JS FROM app_operator_profile WHERE UserID=?", [$this->web_user['UserID']]) ?? '';
$_menu = $this->db->fetchField("SELECT CONVERT(DECODE(Menu,?) USING UTF8MB4) Menu FROM app_operator WHERE UserID=?", [$this->web_app['PARENT_CODE'], $this->web_user['UserID']]) ?? '';
$_gmenu = '';
if ($this->web_user['Grup_MenuID'] > 0) $_gmenu = $this->db->fetchField('SELECT CONVERT(DECODE(Menu,?) USING UTF8MB4) Menu FROM app_menu_grup WHERE Grup_MenuID=?', [$this->web_app['PARENT_CODE'], $this->web_user['Grup_MenuID']]) ?? '';
$this->my_menu = array_filter(array_unique(explode(",", $_gmenu .",". $_menu)));
}
$is_modif = false;
foreach (['css','js','app'] as $type) {
[ $afile, $lastmod ] = $this->gen_file($mode, $type);
$cachefile = md5($mode . $type . $lastmod) . ($type=='css'?'.css':'.js');
if (!file_exists($this->__cachedir . $cachefile) || ((time()-(int)$this->__ini[$mode]['stamp']) > (86400*14))) {
$is_index_app = ($mode === 'index' && $type === 'app');
if (empty($this->ini[$mode][$type]) || !file_exists($this->cachedir . $this->ini[$mode][$type]) || ($this->IS_DEV)) {
[ $afile, $lastmod ] = $this->gen_file($mode, $type);
$cachefile = md5($mode . '-' . $type . '-' . $lastmod) . ($type === 'css' ? '.css' : '.js');
if ($is_index_app) $cachefile = md5('index-app-' . (string) $this->web_user['UserID'] . $lastmod) . '.js';
$this->create_cache($type, $afile, $cachefile);
$this->__ini[$mode][$type] = $cachefile;
$this->__ini[$mode]['stamp'] = time();
$this->ini[$mode][$type] = $cachefile;
if ($is_index_app) $this->db->runQuery("INSERT INTO app_operator_profile (UserID,JS) VALUES (?, ?) ON DUPLICATE KEY UPDATE JS=VALUES(JS)", [$this->web_user['UserID'], $cachefile]);
$is_modif = true;
}
}
if ($is_modif === true) $this->save_ini();
$acache = [ 'CSS' => [], 'JS' => [], 'JSX' => [] ];
foreach ($this->__ini[$mode] as $_type => $_file) {
if ($_type == 'stamp') continue;
if (file_exists($this->__cachedir . $_file)) {
foreach ($this->ini[$mode] as $_type => $_file) {
if (file_exists($this->cachedir . $_file)) {
if ($_type === 'css') {
$acache['CSS'][] = 'chunks/' . $_file;
} else $acache['JS'][] = 'chunks/' . $_file;
$acache['CSS'][] = 'cache/' . $_file;
} else $acache['JS'][] = 'cache/' . $_file;
}
}
if ($is_modif === true) $this->save_ini();
$aoption = $this->session->get('__WEB_APP');
$auser = $this->session->get('__WEB_USER');
$nonce = $this->app->get('csp_nonce');
$islog = user_logged($this->session);
$_secret = $aoption['APP_CODE'] .";". $aoption['APP_SID'] .";". $this->app->request()->getVar('HTTP_HOST') .";". "http://".$this->app->request()->getVar('HTTP_HOST') .";". isMobile() .";". ($aoption['AUTH_LEVEL']?$aoption['AUTH_LEVEL']:0);
$_suser = ($islog) ? $auser['Username'] .";". $auser['UserID'] .";". $auser['Grup_MenuID'] .";". $auser['Level'] : "nobody;999;999;9";
$_secret = $this->web_app['APP_CODE'] .";". $this->web_app['APP_SID'] .";". $this->app->request()->getVar('HTTP_HOST') .";". "http://".$this->app->request()->getVar('HTTP_HOST') .";". isMobile() .";". ($this->web_app['AUTH_LEVEL']?$this->web_app['AUTH_LEVEL']:0);
$_suser = ($this->is_login) ? $this->web_user['Username'] .";". $this->web_user['UserID'] .";". $this->web_user['Grup_MenuID'] .";". $this->web_user['Level'] : "nobody;999;999;9";
$acache['JSX'][] = '<script nonce="'.$nonce.'" type="text/javascript">';
$acache['JSX'][] = 'FoniaJS.setConfig("'.base64_encode($_secret).'", "'.base64_encode($_suser).'");';
$acache['JSX'][] = '$(document).ready(function(){';
if ($islog) $acache['JSX'][] = 'FoniaJS.loadMenu();';
if ($this->is_login) $acache['JSX'][] = 'FoniaJS.loadMenu();';
$acache['JSX'][] = '});';
$acache['JSX'][] = '</script>';
return $acache;
}
public function Make_Cache(array $amode = ['login', 'index', 'monitor']): array {
$is_modif = false;
foreach ($amode as $mode) {
foreach (['css','js','app'] as $type) {
if ($mode === 'index' && $type === 'app') continue;
if (empty($this->ini[$mode][$type]) || !file_exists($this->cachedir . $this->ini[$mode][$type])) {
[ $afile, $lastmod ] = $this->gen_file($mode, $type);
$cachefile = md5($mode . '-' . $type . '-' . $lastmod) . ($type === 'css' ? '.css' : '.js');
$this->create_cache($type, $afile, $cachefile);
$this->ini[$mode][$type] = $cachefile;
$is_modif = true;
}
}
}
if ($is_modif === true) $this->save_ini();
if (in_array('index', $amode)) {
$agrup = $this->db->fetchAll('SELECT Grup_MenuID,CONVERT(DECODE(Menu,?) USING UTF8MB4) Menu FROM app_menu_grup', [$this->web_app['PARENT_CODE']]);
$auser = $this->db->fetchAll("SELECT A.*,IFNULL(B.JS,'') JS FROM (SELECT UserID,Grup_MenuID,CONVERT(DECODE(Menu,?) USING UTF8MB4) Menu FROM app_operator) A LEFT JOIN app_operator_profile B ON (A.UserID=B.UserID)", [$this->web_app['PARENT_CODE']]);
foreach ($auser as $user) {
if (empty($user['JS']) || !file_exists($this->cachedir . $user['JS'])) {
$this->my_menu = array_filter(array_unique(explode(",", $user['Menu'] .",". ($agrup[$user['Grup_MenuID']]['Menu'] ?? ''))));
[ $afile, $lastmod ] = $this->gen_file('index', 'app');
$cachefile = md5('index-app-' . (string) $user['UserID'] . $lastmod) . '.js';
$this->create_cache('app', $afile, $cachefile);
$this->db->runQuery("INSERT INTO app_operator_profile (UserID,JS) VALUES (?, ?) ON DUPLICATE KEY UPDATE JS=VALUES(JS)", [$user['UserID'], $cachefile]);
}
}
}
return [ 'status' => 1, 'user_count' => count($auser) ];
}
}
?>
+44 -30
View File
@@ -2,8 +2,7 @@
/*******************************************************************
Module : /Data/PDF.php
Desc. : Class pembuatan file PDF
Module : /Data/Pdf.php
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : April 18th, 2015.
Last Modified : August 21st, 2026.
@@ -14,40 +13,55 @@
declare(strict_types=1);
namespace siaupheng\webapp\Data;
namespace Webapp\Data;
use \flight\Session;
use \flight\Engine;
use \Mpdf;
final class PDF {
private $__avalue = [];
private $__atabel = [];
private $__theader = "";
private $__tcolname = "";
/**
* Class Pdf
*
* Membuat file Pdf.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Data
*/
final class Pdf {
private array $avalue = [];
private array $atabel = [];
private string $__theader = "";
private string $__tcolname = "";
protected array $webapp;
protected array $webuser;
public function __construct(Session $session) {
$this->webapp = $session->get('__WEB_APP', ['REG_NAME'=>'', 'APP_NAME'=>'', 'APP_VER'=>'']);
$this->webuser = $session->get('__WEB_USER', ['UserID'=>0, 'Username'=>'']);
/**
* @param Engine $app
*/
public function __construct(Engine $app) {
$this->webapp = $app->session()->get('WEB_APP', ['REG_NAME'=>'', 'APP_NAME'=>'', 'APP_VER'=>'']);
$this->webuser = $app->session()->get('WEB_USER', ['UserID'=>0, 'Username'=>'']);
}
public function add_field(string $nama, string|int $lebar=0, string $align="L", string $func="", int $kol=1): void {
$this->__atabel[] = [ $nama, (string)$lebar.'%', $func, $align, $kol ];
$this->atabel[] = [ $nama, (string)$lebar.'%', $func, $align, $kol ];
}
public function show_fields(): void {
$tmp_out = "<thead><tr>";
for ($i=0; $i<count($this->__atabel); $i++) {
if ($this->__atabel[$i][4]==0) continue;
$tmp_out .= $this->set_align($this->__atabel[$i][0], $this->__atabel[$i][1], "C", false, true, $this->__atabel[$i][4]);
for ($i=0; $i<count($this->atabel); $i++) {
if ($this->atabel[$i][4]==0) continue;
$tmp_out .= $this->set_align($this->atabel[$i][0], $this->atabel[$i][1], "C", false, true, $this->atabel[$i][4]);
}
$tmp_out .= "</tr></thead>";
$this->__tcolname = $tmp_out;
}
public function clear(): void {
$this->__avalue = [];
$this->avalue = [];
$this->__theader = "";
$this->__tcolname = "";
}
@@ -64,18 +78,18 @@ final class PDF {
$tmp_arr = func_get_args();
if (is_array($tmp_arr[0])) $tmp_arr = $tmp_arr[0];
$tmp_out = "<tr>";
for ($i=0; $i<count($this->__atabel); $i++) {
for ($i=0; $i<count($this->atabel); $i++) {
$tmp_val = $tmp_arr[$i];
if (is_array($this->__atabel[$i][2]) && trim($tmp_val)<>"") {
$tmp_val = $this->__atabel[$i][2][$tmp_val];
} else if (function_exists($this->__atabel[$i][2]) && trim($tmp_val)<>"") {
$tmp_val = call_user_func($this->__atabel[$i][2], $tmp_val);
if (is_array($this->atabel[$i][2]) && trim($tmp_val)<>"") {
$tmp_val = $this->atabel[$i][2][$tmp_val];
} else if (function_exists($this->atabel[$i][2]) && trim($tmp_val)<>"") {
$tmp_val = call_user_func($this->atabel[$i][2], $tmp_val);
}
$tmp_val = $this->set_align($tmp_val, $this->__atabel[$i][1], $this->__atabel[$i][3]);
$tmp_val = $this->set_align($tmp_val, $this->atabel[$i][1], $this->atabel[$i][3]);
$tmp_out .= $tmp_val;
}
$tmp_out .= "</tr>";
$this->__avalue[] = $tmp_out;
$this->avalue[] = $tmp_out;
}
public function add_span(): void {
@@ -90,15 +104,15 @@ final class PDF {
$tmp_out .= $tmp_val;
}
$tmp_out .= "</tr>";
$this->__avalue[] = $tmp_out;
$this->avalue[] = $tmp_out;
}
public function add_empty(): void {
$this->__avalue[] = $this->set_align("&nbsp;", 0, "L,NB", true);
$this->avalue[] = $this->set_align("&nbsp;", 0, "L,NB", true);
}
public function add_stamp(int $ctk_ke=1, bool $tampil_nama=false): void {
$this->__avalue[] = $this->set_align($this->get_stamp($ctk_ke, $tampil_nama), 0, "L,NB", true);
$this->avalue[] = $this->set_align($this->get_stamp($ctk_ke, $tampil_nama), 0, "L,NB", true);
}
public function get_stamp(int $ctk_ke=1, bool $tampil_nama=false): string {
@@ -149,8 +163,8 @@ final class PDF {
$html .= '<tbody>';
// content out
for ($i=0; $i<count($this->__avalue); $i++) {
$html .= $this->__avalue[$i];
for ($i=0; $i<count($this->avalue); $i++) {
$html .= $this->avalue[$i];
}
$html .= '</tbody></table></div></div></body>';
$mpdf = new mPDF('c', 'A4'.($orien==="L"?"-L":""), $fontz, '', 5, 5, 5, 10, 5, 5);
@@ -163,7 +177,7 @@ final class PDF {
$tstyle = $this->create_style($dir);
if (strpos(strtolower($text), "<tr>")===false) {
if ($line===true) {
return '<tr><td colspan="'.count($this->__atabel).'" class="'.$tstyle.'">'.$text."</td></tr>";
return '<tr><td colspan="'.count($this->atabel).'" class="'.$tstyle.'">'.$text."</td></tr>";
} else {
return (($head===true)?"<th":"<td").(($col>1)?' colspan="'.(string)$col.'"':"").' class="'.$tstyle.'" '.(($head===true)?'width="'.(string)$width.'"':"").">".$text.(($head===true)?"</th>":"</td>");
}
-164
View File
@@ -1,164 +0,0 @@
<?php
/*******************************************************************
Module : /Data/SimpleXLS.php
Desc. : Class pembuatan file Simple XLS
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : November 18th, 2012.
Last Modified : September 30th, 2025.
(c) 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
//todo: deprecated
declare(strict_types=1);
namespace siaupheng\webapp\Data;
final class SimpleXLS {
private $__wbook = null;
private $__atabel = [];
private $__astyle = [];
private $__aheader = [];
private $__amerge = [];
private $__avalue = [];
private $__tsheet = null;
public function __construct($oprop=[]) {
$this->__wbook = new \Shuchkin\SimpleXLSXGen();
$this->__wbook
->setAuthor($_SESSION['__WEB_APP']['APP_NAME']." v".$_SESSION['__WEB_APP']['APP_VER'])
->setLastModifiedBy($_SESSION['__WEB_APP']['APP_NAME']." v".$_SESSION['__WEB_APP']['APP_VER'])
->setTitle($oprop['title'] ?? "")
->setSubject($oprop['subject'] ?? $_SESSION['__WEB_APP']['REG_NAME'])
->setDescription($oprop['desc'] ?? "")
->setCompany($_SESSION['__WEB_APP']['REG_NAME'])
->setDefaultFont("Calibri")
->setDefaultFontSize(11);
}
private function coord2cell($x, $y) {
$c = '';
for ($i = $x; $i >= 0; $i = ((int)($i / 26)) - 1) {
$c = chr(ord('A') + $i % 26) . $c;
}
return $c . ($y + 1);
}
private function create_style($tstyle="L") {
$_astyle = explode(",", $tstyle);
$_s_style = ""; $_e_style = "";
foreach ($_astyle as $_key => $_val) {
if ($_val == "L") {$_s_style .= '<left>'; $_e_style .= '</left>';}
if ($_val == "R") {$_s_style .= '<right>'; $_e_style .= '</right>';}
if ($_val == "C") {$_s_style .= '<center>'; $_e_style .= '</center>';}
if ($_val == "W") {$_s_style .= '<wraptext>'; $_e_style .= '</wraptext>';}
if ($_val == "B") {$_s_style .= '<b>'; $_e_style .= '</b>';}
if ($_val == "I") {$_s_style .= '<i>'; $_e_style .= '</i>';}
if ($_val == "S") {$_s_style .= "\0"; $_e_style .= '';}
if ($_val == "N") {$_s_style .= '<style nf="#,##0.00">'; $_e_style .= '</style>';}
if ($_val == "N0") {$_s_style .= '<style nf="#,##0">'; $_e_style .= '</style>';}
}
return ['s'=>$_s_style, 'e'=>$_e_style];
}
public function clear_field() {
$this->__atabel = [];
}
public function add_header($tjudul="") {
if ($tjudul=="") return;
$this->__aheader[] = $tjudul;
}
public function add_empty_row($nrow=1) {
$_jkolom = count($this->__atabel);
for ($i=0; $i<$nrow; $i++) {
$this->__avalue[] = array_fill(0,$_jkolom,"");
}
}
public function add_field($tnama="", $nlebar=0, $talign="L", $ffunc="") {
$this->__atabel[] = [$tnama, $nlebar, $ffunc];
$this->__astyle[] = $this->create_style($talign);
}
public function add_sheet($tnama_sheet="BARU", $bw_header=true) {
$this->__tsheet = $tnama_sheet;
$_jkolom = count($this->__atabel);
foreach ($this->__aheader as $_key => $_val) {
$a_out = ['<style font-size="12"><center>'.$_val."</center></style>"];
$this->__amerge[] = $this->coord2cell(0, count($this->__avalue)) . ":" . $this->coord2cell($_jkolom-1, count($this->__avalue));
$this->__avalue[] = $a_out;
}
if ($bw_header==true) $this->show_headers();
}
public function add_value() {
$tmp_arr = func_get_args();
if (is_array($tmp_arr[0])) $tmp_arr = $tmp_arr[0];
$a_out = [];
for ($i=0; $i<count($this->__atabel); $i++) {
$tmp_val = $tmp_arr[$i];
if (is_array($this->__atabel[$i][2]) && trim($tmp_val)<>"") {
$tmp_val = $this->__atabel[$i][2][$tmp_val];
} else if (function_exists($this->__atabel[$i][2]) && trim($tmp_val)<>"") {
$tmp_val = call_user_func($this->__atabel[$i][2], $tmp_val);
}
$a_out[] = $this->__astyle[$i]['s'] . $tmp_val . $this->__astyle[$i]['e'];
}
$this->__avalue[] = $a_out;
}
public function add_span() {
$tmp_arr = func_get_args();
$a_out = [];
for ($i=0; $i<count($tmp_arr); $i++) {
$tmp_val = $tmp_arr[$i]; // CONTENT, COLSPAN=1, L, FUNC
if (!isset($tmp_val[1])) $tmp_val[1] = 1;
if (!isset($tmp_val[2])) $tmp_val[2] = "L";
if (isset($tmp_val[3])) {
if (function_exists($tmp_val[3]) && trim("".$tmp_val[0])<>"") {
$tmp_val[0] = call_user_func($tmp_val[3], $tmp_val[0]);
}
}
$tmp_style = $this->create_style($tmp_val[2]);
if ($tmp_val[1]>1) $this->__amerge[] = $this->coord2cell(count($a_out), count($this->__avalue)) . ":" . $this->coord2cell((count($a_out)+$tmp_val[1])-1, count($this->__avalue));
$a_out[] = $tmp_style['s'] . $tmp_val[0] . $tmp_style['e'];
for ($k=1; $k<$tmp_val[1]; $k++) $a_out[] = null;
}
$this->__avalue[] = $a_out;
}
public function add_stamp($ctk_ke=1, $bnama=false) {
$this->__avalue[] = ["<i>".$_SESSION['__WEB_APP']['APP_NAME']."v".$_SESSION['__WEB_APP']['APP_VER'].date("\@ymd.His")."-".user_id(3).(($bnama==true)?"/".strtoupper(user_user()):"").(($ctk_ke>0)?"#".isi_nol($ctk_ke,2):"")."</i>"];
}
public function get_stamp($ctk_ke=1, $bnama=false) {
return $_SESSION['__WEB_APP']['APP_NAME']."v".$_SESSION['__WEB_APP']['APP_VER'].date("\@ymd.His")."-".user_id(3).(($bnama==true)?"/".strtoupper(user_user()):"").(($ctk_ke>0)?"#".isi_nol($ctk_ke,2):"");
}
public function show_headers() {
$a_out = [];
for ($i=0; $i<count($this->__atabel); $i++) {
$a_out[] = '<style bgcolor="#D0D0D0"><center>'.$this->__atabel[$i][0].'</center></style>';
}
$this->__avalue[] = $a_out;
}
public function send($tnama_file="File_Excel") {
$this->__wbook->addSheet($this->__avalue, $this->__tsheet);
for ($i=0; $i<count($this->__atabel); $i++) {
$this->__wbook->setColWidth(($i+1), $this->__atabel[$i][1]);
}
for ($i=0; $i<count($this->__amerge); $i++) {
$this->__wbook->mergeCells($this->__amerge[$i]);
}
$this->__wbook->downloadAs($tnama_file);
}
}
?>
-156
View File
@@ -1,156 +0,0 @@
<?php
/*******************************************************************
Module : /Data/XLS.php
Desc. : Class pembuatan file XLS
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : November 18th, 2012.
Last Modified : October 26th, 2023.
(c) 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
//todo: deprecated
declare(strict_types=1);
namespace siaupheng\webapp\Data;
use PhpOffice\PhpSpreadsheet\IOFactory;
final class XLS {
private $__tnamafile = null;
private $__bline = true;
private $__wbook = null;
private $__wsheet = null;
private $__baris = 0;
private $__kolom = 0;
private $__atabel = [];
private $__astyle =[];
private $__aheader = [];
private $__fhead = null;
private $__isheet = 0;
public function __construct($tnama_file="", $oprop=[]) {//oke
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );
$this->__tnamafile = $tnama_file;
$this->__wbook = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$this->__wbook->getProperties()
->setCreator($_SESSION['__WEB_APP']['APP_NAME']." v".$_SESSION['__WEB_APP']['APP_VER'])
->setLastModifiedBy($_SESSION['__WEB_APP']['APP_NAME']." v".$_SESSION['__WEB_APP']['APP_VER'])
->setTitle($oprop['title'] ?? "")
->setSubject($oprop['subject'] ?? "")
->setDescription($oprop['desc'] ?? "")
->setCompany($_SESSION['__WEB_APP']['REG_NAME']);
$this->__wsheet = $this->__wbook->getActiveSheet();
$this->__fhead = [
'font' => ['bold' => true],
'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, 'wrapText' => true],
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb'=>"D0D0D0"]],
'borders' => ['allBorders' => ['borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['rgb'=>"C0C0C0"]]]
];
}
public function create_style($tstyle="L") {//oke
$_astyle = explode(",", $tstyle);
$_tmp_style = [];
$_bline = $this->__bline;
foreach ($_astyle as $_key => $_val) {
if ($_val == "L") $_tmp_style['alignment'] = ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT];
if ($_val == "R") $_tmp_style['alignment'] = ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT];
if ($_val == "C") $_tmp_style['alignment'] = ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER];
if ($_val == "W") $_tmp_style['alignment'] = ['wrapText' => true];
if ($_val == "B") $_tmp_style['font'] = ['bold' => true];
if ($_val == "S") $_tmp_style['numberFormat'] = ['formatCode' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_TEXT];
if ($_val == "N") $_tmp_style['numberFormat'] = ['formatCode' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED2];
if ($_val == "N0") $_tmp_style['numberFormat'] = ['formatCode' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED2];
if ($_val == "NL") $_bline = false;
if ($_val == "H") {
$_bline = false;
$_tmp_style = $this->__fhead;
}
}
return $_tmp_style;
}
public function clear_field() {//up : 2014-06-19
$this->__atabel = [];
$this->__astyle = [];
}
public function set_pos($nbaris=0, $nkolom=0) {
$this->__baris = $nbaris;
$this->__kolom = $nkolom;
}
public function set_garis_bawah($bgaris=true) {}//todo: deleted
public function add_header($tjudul="") {//oke
if ($tjudul=="") return;
$this->__aheader[] = $tjudul;
}
public function add_empty_row($nrow=1) {//oke
$this->__baris += $nrow;
}
public function add_field($tnama="", $nlebar=0, $talign="L", $ffunc="") {//oke
$this->__atabel[] = [$tnama, $nlebar, $ffunc];
$this->__astyle[] = $this->create_style($talign);
}
public function add_sheet($tnama_sheet="BARU", $bw_header=true) {//not yet !!!
if ($this->__isheet > 0) {
$this->__wbook->createSheet();
$this->__wsheet = $this->__wbook->setActiveSheetIndex(++$this->__isheet);
}
$this->__wsheet->setTitle($tnama_sheet);
for ($i=0; $i<count($this->__atabel); $i++) {
//sampai disini dulu !!
$this->__wsheet->getColumnDimension($this->__kolom+$i)->setWidth($this->__atabel[$i][1]);
}
$_fjudul = $this->__wbook->addFormat();
$_fjudul->setBold();
$_fjudul->setAlign("center");
$_jkolom = count($this->__atabel);
if ($_jkolom>0) $_jkolom--;
foreach ($this->__aheader as $_key => $_val) {
$this->__wsheet->write($this->__baris,$this->__kolom,$_val,$_fjudul);
$this->__wsheet->setMerge($this->__baris,$this->__kolom,$this->__baris,$this->__kolom+$_jkolom);
$this->__baris++;
}
$this->__baris++;
if ($bw_header==true) $this->show_headers();
}
public function add_value() {
$tmp_arr = func_get_args();
if (is_array($tmp_arr[0])) $tmp_arr = $tmp_arr[0];
$tmp_out = "";
for ($i=0; $i<count($this->__atabel); $i++) {
$tmp_val = $tmp_arr[$i];
if (is_array($this->__atabel[$i][1]) && trim($tmp_val)<>"") {
$tmp_val = $this->__atabel[$i][1][$tmp_val];
} else if (function_exists($this->__atabel[$i][1]) && trim($tmp_val)<>"") {
$tmp_val = call_user_func($this->__atabel[$i][1], $tmp_val);
}
$tmp_out .= DELI_CSV . $tmp_val;
}
$tmp_out = substr($tmp_out, 1);
$this->__avalue[] = $tmp_out;
}
public function send($tnama_file="File_Excel") {//oke
$this->__wsheet->setActiveSheetIndex(0);
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="'.$tnama_file.'"');
header('Cache-Control: max-age=0');
$writer = IOFactory::createWriter($this->__wsheet, 'Xlsx');
$writer->save('php://output');
}
}
?>
+155
View File
@@ -0,0 +1,155 @@
<?php
/*******************************************************************
PHP Class : /Data/Xlsx.php
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : November 18th, 2012.
Last Modified : October 24th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
declare(strict_types=1);
namespace Webapp\Data;
use \flight\Engine;
use \avadim\FastExcelWriter\Excel;
use \avadim\FastExcelWriter\Options;
use \avadim\FastExcelWriter\Sheet;
use \avadim\FastExcelWriter\Style\Style;
/**
* Class Xlsx
*
* Membuat file Excel XLSX
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Data
*/
final class Xlsx {
private Options $options;
private Excel $excel;
private Sheet $sheet;
private array $webapp;
private array $webuser;
private array $meta = [];
private array $titles = [];
private array $subtitles = [];
private array $atabel = [];
private int $baris = 1;
/**
* @param Engine $app
*/
public function __construct(Engine $app) {
$this->webapp = (array) $app->session()->get('WEB_APP', ['REG_NAME'=>'', 'APP_NAME'=>'', 'APP_VER'=>'']);
$this->webuser = (array) $app->session()->get('WEB_USER', ['UserID'=>0, 'Username'=>'']);
$this->meta = [
'company' => $this->webapp['REG_NAME'],
'subject' => $this->webapp['REG_NAME'],
'author' => $this->webapp['APP_NAME'].' v'.$this->webapp['APP_VER'],
];
$this->options = Options::create()
->DefaultFont([ Style::FONT_NAME => "Calibri", Style::FONT_SIZE => 11 ])
->defaultDateFormat('DD-MM-YYYY')
->defaultTimeFormat('HH:MM')
->defaultDateTimeFormat('DD-MM-YYYY HH:MM');
}
public function set_meta(array $meta): void {
if (!empty($meta)) $this->meta = array_merge($this->meta, $meta);
}
public function add_title(string|array $judul): void {
if (empty($judul)) return;
if (is_array($judul)) {
$this->titles = $judul;
} else array_push($this->titles, $judul);
}
public function add_sub_title(string|array $judul): void {
if (empty($judul)) return;
if (is_array($judul)) {
$this->subtitles = $judul;
} else array_push($this->subtitles, $judul);
}
public function add_field(string $nama="", int $lebar=0, string $style="@text", ?callable $func=null): void {
$this->atabel[] = ['n' => $nama, 'l' => $lebar, 's' => $style, 'f' => $func];
}
public function add_sheet(string $nama_sheet="BARU", bool $show_header=false): void {
if (empty($this->excel)) {
$this->excel = Excel::create([$nama_sheet], $this->options)
->setCompany($this->meta['company'] ?? "")
->setAuthor($this->meta['author'] ?? "")
->setTitle($this->meta['title'] ?? "")
->setDescription($this->meta['desc'] ?? "")
->setSubject($this->meta['subject'] ?? "");
$this->sheet = $this->excel->sheet(); //getSheet();
} else {
$this->sheet = $this->excel->makeSheet($nama_sheet);
}
if ($show_header === true) {
$this->show_titles();
$this->show_headers();
}
}
public function add_row(array $row): void {
if (is_array($row) && !empty($row)) $this->sheet->writeRow($row);
}
public function add_row_bold(array $row): void {
if (is_array($row) && !empty($row)) $this->sheet->writeRow($row)->applyFontStyleBold();
}
public function show_titles(): void {
$this->baris = $this->sheet->getCurrentRow();
$jum_kolom = count($this->atabel);
foreach ($this->titles as $title) {
$this->sheet->writeTo('A'.(string) $this->baris.':'.$this->excel->colLetter($jum_kolom).(string) $this->baris, $title)
->applyFontStyleBold()
->applyTextCenter();
$this->baris++;
}
if (count($this->subtitles) > 0) {
$this->baris++;
foreach ($this->subtitles as $title) {
$this->sheet->writeTo('A'.(string) $this->baris++, $title);
}
} else
$this->sheet->writeTo('A'.(string) $this->baris, '');
}
public function show_headers(bool $is_hide=false): void {
if (!$is_hide) $this->sheet->writeHeader(array_column($this->atabel, 'n'))
->applyFontStyleBold()
->applyTextCenter()
->applyBorder(Style::BORDER_STYLE_THIN);
$this->sheet->setColFormats(array_column($this->atabel, 's'))
->setColWidths(array_column($this->atabel, 'l'));
}
public function add_stamp(int $ctk_ke=1, bool $tampil_nama=false): void {
$this->sheet->nextRow();
$this->sheet->writeCell($this->get_stamp($ctk_ke, $tampil_nama), ['font-size' => 8, 'font-style' => 'italic']);
}
public function get_stamp(int $ctk_ke=1, bool $tampil_nama=false): string {
return $this->webapp['APP_NAME']."v".$this->webapp['APP_VER'].date("\@ymd.His")."-".isi_nol($this->webuser['UserID'], 3).(($tampil_nama)?"/".strtoupper($this->webuser['Username']):"").(($ctk_ke>0)?"#".isi_nol($ctk_ke,2):"");
}
public function download(string $nama_file="File_Excel.xlsx"): void {
$this->excel->download($nama_file);
}
}
-64
View File
@@ -1,64 +0,0 @@
<?php
/*******************************************************************
Module : /Function/Auth.php
Desc. : Fungsi Custom Auth
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : January 27th, 2008.
Last Modified : January 21st, 2024.
(c) 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
declare(strict_types=1);
use \flight\Session;
if (!function_exists('user_level')) {
function user_level(Session $session, int $level = 9): bool {
if ($session->get('__WEB_USER', ['Level'=>9]) <= $level) return true;
return false;
}
}
if (!function_exists('user_level_not')) {
function user_level_not(Session $session, int $level = 9): bool {
if ($session->get('__WEB_USER', ['Level'=>9]) !== $level) return true;
return false;
}
}
if (!function_exists('user_logged')) {
function user_logged(Session $session): bool {
return !empty($session->get('__WEB_USER'));
}
}
if (!function_exists('user_id')) {
function user_id(Session $session, int $digit = 0): string|int {
if ($digit > 0) return isi_nol($session->get('__WEB_USER', ['UserID'=>0])['UserID'], $digit);
return (int)$session->get('__WEB_USER', ['UserID'=>0])['UserID'];
}
}
if (!function_exists('user_user')) {
function user_user(Session $session): string {
return (string)$session->get('__WEB_USER', ['Username'=>''])['Username'];
}
}
if (!function_exists('user_unix')) {
function user_unix(Session $session): string {
return (string)$session->get('__WEB_USER', ['UNIX'=>'0'])['UNIX'];
}
}
if (!function_exists('user_nama')) {
function user_nama(Session $session): string {
return (string)$session->get('__WEB_USER', ['Nama'=>''])['Nama'];
}
}
?>
+129 -90
View File
@@ -6,7 +6,7 @@
Desc. : Fungsi Custom Lain Lain
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : January 27th, 2008.
Last Modified : August 21st, 2026.
Last Modified : October 27th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -16,20 +16,20 @@ declare(strict_types=1);
/*************************** FORMAT ANGKA / CURRENCY *****************************/
if (!function_exists('rupiah')) {//oke
function rupiah(string|float $angka = 0, int $desi = 0): string {
return number_format((float)$angka, $desi, ",", ".");
if (!function_exists('rupiah')) {
function rupiah(mixed $angka = 0, int $desi = 0): string {
return number_format((float) $angka, $desi, ",", ".");
}
}
if (!function_exists('rupiah2')) {//oke
function rupiah2($angka = 0): string {
if (!function_exists('rupiah2')) {
function rupiah2(mixed $angka = 0): string {
return rupiah($angka, 2);
}
}
//todo: deprecated
/*if (!function_exists('rupiah30')) {
/* todo: deprecated
if (!function_exists('rupiah30')) {
function rupiah30($angka = 0): string {
$nilai = explode(".", $angka);
$hasil = (intval($nilai[1])==0) ? rupiah($angka, 0) : rupiah($angka, 3);
@@ -38,77 +38,78 @@ if (!function_exists('rupiah2')) {//oke
}*/
if (!function_exists('kurung_rup')) {
function kurung_rup($angka = 0, $desi = 0) {
$thasil = rupiah(abs($angka), $desi);
if ($angka<0) return "(".$thasil.")";
function kurung_rup(mixed $angka = 0, int $desi = 0): string {
$thasil = rupiah(abs((float) $angka), $desi);
if ((float) $angka < 0) return "(".$thasil.")";
return $thasil." ";
}
}
if (!function_exists('kurung')) {
function kurung($angka = 0, $desi = 0) {
$thasil = uang(abs($angka), $desi);
if ($angka<0) return "(".$thasil.")";
function kurung(mixed $angka = 0, int $desi = 0): string {
$thasil = uang(abs((float) $angka), $desi);
if ((float) $angka < 0) return "(".$thasil.")";
return $thasil." ";
}
}
if (!function_exists('kurung2')) {
function kurung2($angka = 0) {
function kurung2(mixed $angka = 0): string {
return kurung($angka, 2);
}
}
if (!function_exists('uang')) {//oke
function uang(string|float $angka = '0', int $desi = 0) {
$angka = str_replace(",", "", (string)$angka);
return number_format((float)$angka, $desi);
if (!function_exists('uang')) {
function uang(mixed $angka = 0, int $desi = 0): string {
$angka = str_replace(",", "", (string) $angka);
return number_format((float) $angka, $desi);
}
}
if (!function_exists('uang2')) {
function uang2($angka = 0) {
function uang2(mixed $angka = 0): string {
return uang($angka, 2);
}
}
/* todo: deprecated
if (!function_exists('koma30')) {
function koma30($angka = 0) {
$nilai = explode(".", $angka);
$hasil = (intval($nilai[1])==0) ? uang($angka, 0) : uang($angka, 3);
return $hasil;
}
}
}*/
if (!function_exists('items')) {
function items($item = 0) {
function items(mixed $item = 0): string {
return rupiah($item)." Items";
}
}
if (!function_exists('records')) {
function records($item = 0) {
function records(mixed $item = 0): string {
return rupiah($item)." Records";
}
}
if (!function_exists('baris')) {
function baris($item = 0) {
function baris(mixed $item = 0): string {
return rupiah($item)." Baris";
}
}
if (!function_exists('npwp')) {
function npwp($nomor = "000000000000000") {
function npwp(string $nomor = "000000000000000"): string {
return substr($nomor,0,2).".".substr($nomor,2,3).".".substr($nomor,5,3).".".substr($nomor,8,1)."-".substr($nomor,9,3).".".substr($nomor,12,3);
}
}
if (!function_exists('romawi')) {
function romawi($n) {
function romawi(int $n): string {
$hasil = "";
$iromawi = array("","I","II","III","IV","V","VI","VII","VIII","IX","X",20=>"XX",30=>"XXX",40=>"XL",50=>"L",60=>"LX",70=>"LXX",80=>"LXXX",90=>"XC",100=>"C",200=>"CC",300=>"CCC",400=>"CD",500=>"D",600=>"DC",700=>"DCC",800=>"DCCC",900=>"CM",1000=>"M",2000=>"MM",3000=>"MMM");
if (array_key_exists($n,$iromawi)) {
$iromawi = ["","I","II","III","IV","V","VI","VII","VIII","IX","X",20=>"XX",30=>"XXX",40=>"XL",50=>"L",60=>"LX",70=>"LXX",80=>"LXXX",90=>"XC",100=>"C",200=>"CC",300=>"CCC",400=>"CD",500=>"D",600=>"DC",700=>"DCC",800=>"DCCC",900=>"CM",1000=>"M",2000=>"MM",3000=>"MMM"];
if (array_key_exists($n, $iromawi)) {
$hasil = $iromawi[$n];
} else if ($n >= 11 && $n <= 99) {
$i = $n % 10;
@@ -125,7 +126,7 @@ if (!function_exists('romawi')) {
}
if (!function_exists('abjad')) {
function abjad($n) {
function abjad(int $n): string {
$_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return substr($_str, ($n-1), 1);
}
@@ -134,8 +135,8 @@ if (!function_exists('abjad')) {
/*************************** FORM CONTROL *****************************/
if (!function_exists('checkbox')) {
function checkbox($nilai = 0) {
$thasil = ((is_string($nilai) && ($nilai=="N" || $nilai=="0")) or (is_numeric($nilai) && $nilai==0) or (is_bool($nilai) && $nilai==false)) ? "circle text-secondary" : "check-circle text-info";
function checkbox(mixed $nilai): string {
$thasil = (empty($nilai) or (is_string($nilai) && ($nilai=="N" || $nilai=="0")) or (is_numeric($nilai) && $nilai==0) or (is_bool($nilai) && $nilai==false)) ? "circle text-secondary" : "check-circle text-info";
return '<i class="fs-6 bi-'.$thasil.'"></i>';
}
}
@@ -143,34 +144,34 @@ if (!function_exists('checkbox')) {
/*************************** FORMAT TANGGAL / KALENDER *****************************/
if (!function_exists('sqltgl')) {
function sqltgl($waktu = "0") {
function sqltgl(string $waktu): string {
return tgl_sql2str($waktu);
}
}
if (!function_exists('sqltgls')) {
function sqltgls($waktu = "0") {
function sqltgls(string $waktu): string {
return tgl_sql2str($waktu, false, true);
}
}
if (!function_exists('sqljam')) {
function sqljam($waktu = "0") {
function sqljam(string $waktu): string {
return tgl_sql2str($waktu, true);
}
}
if (!function_exists('sqljams')) {
function sqljams($waktu = "0") {
function sqljams(string $waktu): string {
return tgl_sql2str($waktu, true, true);
}
}
if (!function_exists('tgl_sql2str')) {
function tgl_sql2str($waktu = "0", $jam = false, $short = false) {
if ($waktu=="0" || $waktu=="") return;
function tgl_sql2str(string $waktu, bool $jam = false, bool $short = false): string {
if (empty($waktu)) return '';
$atgl = explode(" ", $waktu);
$sjam = ($jam) ? ((empty($atgl[1]))?date("H:i:s"):$atgl[1]) : "";
$sjam = ($jam) ? ((empty($atgl[1])) ? date("H:i:s") : $atgl[1]) : "";
$atgl = explode("-", $atgl[0]);
$stgl = $atgl[2]."-".$atgl[1]."-".$atgl[0];
if ($short) $stgl = $atgl[2].".".$atgl[1].".".substr($atgl[0],2);
@@ -179,66 +180,66 @@ if (!function_exists('tgl_sql2str')) {
}
if (!function_exists('tgl_ymd')) {
function tgl_ymd($jam = false) {
function tgl_ymd(bool $jam = false): string {
return (($jam) ? date("Y-m-d H:i:s") : date("Y-m-d"));
}
}
if (!function_exists('tgl_dmy')) {
function tgl_dmy($jam = false) {
function tgl_dmy(bool $jam = false): string {
return (($jam) ? date("d-m-Y H:i:s") : date("d-m-Y"));
}
}
if (!function_exists('tgl_operasi')) {
function tgl_operasi($dtgl = "", $nhari = 0, $nbln = 0, $nthn = 0) {
$atgl = explode("-", $dtgl);
return date("d-m-Y", mktime(0,0,0, $atgl[1]+$nbln, $atgl[0]+$nhari, $atgl[2]+$nthn));
function tgl_operasi(string $tgl, int $hari = 0, int $bln = 0, int $thn = 0): string {
$atgl = explode("-", $tgl);
return date("d-m-Y", mktime(0,0,0, (int) $atgl[1]+$bln, (int) $atgl[0]+$hari, (int) $atgl[2]+$thn));
}
}
if (!function_exists('tgl_range_hari')) {
function tgl_range_hari($dftgl="", $dttgl="", $bhitung_awal=false) {
$_start = strtotime(tgl_sql2str($dftgl));
$_end = strtotime(tgl_sql2str($dttgl));
return ceil(abs($_end - $_start) / 86400) + (($bhitung_awal==true)?1:0);
function tgl_range_hari(string $tgl_from, string $tgl_to, bool $hitung_awal = false): float {
if (empty($tgl_to) or empty($tgl_from)) return 0;
$_start = strtotime(tgl_sql2str($tgl_from));
$_end = strtotime(tgl_sql2str($tgl_to));
return ceil(abs($_end - $_start) / 86400) + (($hitung_awal)?1:0);
}
}
if (!function_exists('tgl_akhbln')) {
function tgl_akhbln($tgl) {
function tgl_akhbln(string $tgl): string {
if (empty($tgl)) return '';
$atgl = explode("-", $tgl);
$ablna = array(31,28,31,30,31,30,31,31,30,31,30,31);
$ablna = ['31','28','31','30','31','30','31','31','30','31','30','31'];
// jika tahun masehi dan bulan 2
if ( (round($atgl[2]/4)==($atgl[2]/4)) && intval($atgl[1])==2 ) return "29-02-".$atgl[2];
return $ablna[(intval($atgl[1])-1)]."-".isi_nol($atgl[1],2)."-".$atgl[2];
if ((round((int) $atgl[2]/4) === ((int) $atgl[2]/4)) && (int) $atgl[1] === 2) return "29-02-".$atgl[2];
return $ablna[(int) $atgl[1]-1]."-".isi_nol($atgl[1],2)."-".$atgl[2];
}
}
if (!function_exists('tgl_panjang')) {
function tgl_panjang($dtgl = "") {
if (trim($dtgl)=="") $dtgl = tgl_dmy();
$atgl = explode("-", $dtgl);
function tgl_panjang(string $tgl): string {
if (empty($tgl)) $tgl = tgl_dmy();
$atgl = explode("-", $tgl);
$abulan = bulan_array();
return $atgl[0]." ".$abulan[intval($atgl[1])]." ".$atgl[2];
return $atgl[0]." ".$abulan[$atgl[1]]." ".$atgl[2];
}
}
if (!function_exists('tgl_hari')) {
function tgl_hari($dtgl = "") {
function tgl_hari(string $tgl): string {
$nhari = date("w");
if (trim($dtgl)!="") {
//$atgl = getdate($dtgl);
//$nhari = $atgl[wday];
$nhari = date("w", strtotime(tgl_sql2str($dtgl)));
if (!empty($tgl)) {
$nhari = date("w", strtotime(tgl_sql2str($tgl)));
}
$ahari = array("0"=>"Minggu","1"=>"Senin","2"=>"Selasa","3"=>"Rabu","4"=>"Kamis","5"=>"Jum'at","6"=>"Sabtu");
$ahari = ["0"=>"Minggu","1"=>"Senin","2"=>"Selasa","3"=>"Rabu","4"=>"Kamis","5"=>"Jum'at","6"=>"Sabtu"];
return $ahari[$nhari];
}
}
if (!function_exists('tgl_triwulan')) {
function tgl_triwulan($dtgl = "") {
if ($dtgl == "") {
function tgl_triwulan(string $tgl): int {
if (empty($tgl)) {
$dtgl = date("m");
} else {
$atgl = explode("-", $tgl);
@@ -254,13 +255,13 @@ if (!function_exists('tgl_triwulan')) {
}
if (!function_exists('bulan_array')) {
function bulan_array() {
return array("1"=>"Januari","2"=>"Februari","3"=>"Maret","4"=>"April","5"=>"Mei","6"=>"Juni","7"=>"Juli","8"=>"Agustus","9"=>"September","10"=>"Oktober","11"=>"November","12"=>"Desember");
function bulan_array(): array {
return ["1"=>"Januari","2"=>"Februari","3"=>"Maret","4"=>"April","5"=>"Mei","6"=>"Juni","7"=>"Juli","8"=>"Agustus","9"=>"September","10"=>"Oktober","11"=>"November","12"=>"Desember"];
}
}
if (!function_exists('triwulan_array')) {
function triwulan_array() {
function triwulan_array(): array {
return ["1"=>"Triwulan 1","2"=>"Triwulan 2","3"=>"Triwulan 3","4"=>"Triwulan 4"];
}
}
@@ -268,24 +269,25 @@ if (!function_exists('triwulan_array')) {
/*************************** FORMAT TAMPILAN & ERROR *****************************/
if (!function_exists('subjudul')) {
function subjudul($tjudul) {
return '<table border="0" align="center" valign="middle" width="100%" height="26px"><tr><td width="50%"><hr /></td><td>&nbsp;&nbsp;<span style="text-align:center;font-weight:bold;white-space:nowrap;">'.$tjudul.'</span>&nbsp;&nbsp;</td><td width="50%"><hr /></td></tr></table>';
function subjudul(string $judul): string {
return '<table border="0" align="center" valign="middle" width="100%" height="26px"><tr><td width="50%"><hr /></td><td>&nbsp;&nbsp;<span style="text-align:center;font-weight:bold;white-space:nowrap;">'.$judul.'</span>&nbsp;&nbsp;</td><td width="50%"><hr /></td></tr></table>';
}
}
/* todo: deprecated
if (!function_exists('showerror')) {
function showerror($terror) {
echo '<input type="hidden" id="_Error" class="error" value="'.$terror.'!" />';
function showerror(string $error): void {
echo '<input type="hidden" id="_Error" class="error" value="'.$error.'!" />';
}
}
}*/
if (!function_exists('br2nl')) {
function br2nl($string) {
function br2nl(string $string): string {
return preg_replace('/\<br(\s*)?\/?\>/i', "\n\r", $string);
}
}
if (!function_exists('isi_nol')) {//oke
if (!function_exists('isi_nol')) {
function isi_nol(string|int $nilai = 0, int $panjang = 1): string {
$nilai = (string)$nilai;
return ($panjang>strlen($nilai) ? str_repeat("0", $panjang-strlen($nilai)):'').$nilai;
@@ -293,7 +295,7 @@ if (!function_exists('isi_nol')) {//oke
}
if (!function_exists('isMobile')) {
function isMobile() {
function isMobile(): bool {
$agen = $_SERVER['HTTP_USER_AGENT'];
$amobile = ['Android', 'webOS', 'iPhone', 'iPad', 'iPod', 'BlackBerry', 'Windows Phone', 'Mobile'];
foreach ($amobile as $keyword) {
@@ -304,46 +306,47 @@ if (!function_exists('isMobile')) {
}
if (!function_exists('isLinux')) {
function isLinux() {
function isLinux(): bool {
$agen = $_SERVER['HTTP_USER_AGENT'];
if (stripos($agen,'linux') !== false) return true;
if (stripos($agen, 'linux') !== false) return true;
return false;
}
}
if (!function_exists('isIE')) {
function isIE() {
function isIE(): bool {
$agen = $_SERVER['HTTP_USER_AGENT'];
if (stripos($agen,'msie') !== false) return true;
if (stripos($agen, 'msie') !== false) return true;
return false;
}
}
if (!function_exists('isChrome')) {
function isChrome() {
function isChrome(): bool {
$agen = $_SERVER['HTTP_USER_AGENT'];
if (stripos($agen,'chrome') !== false) return true;
if (stripos($agen, 'chrome') !== false) return true;
return false;
}
}
if (!function_exists('isFirefox')) {
function isFirefox() {
function isFirefox(): bool {
$agen = $_SERVER['HTTP_USER_AGENT'];
if (stripos($agen,'firefox') !== false) return true;
if (stripos($agen, 'firefox') !== false) return true;
return false;
}
}
/* todo: deprecated
if (!function_exists('potong')) {
function potong($nilai) {//utk rkpd
return substr($nilai, 0, 60);
}
}
}*/
if (!function_exists('format_bytes')) {
function format_bytes($bytes) {
if ($bytes < 1024) return $bytes.' B';
function format_bytes(int $bytes): string {
if ($bytes < 1024) return (string) $bytes.' B';
elseif ($bytes < 1048576) return uang2($bytes / 1024).' KB';
elseif ($bytes < 1073741824) return uang2($bytes / 1048576).' MB';
elseif ($bytes < 1099511627776) return uang2($bytes / 1073741824).' GB';
@@ -352,12 +355,48 @@ if (!function_exists('format_bytes')) {
}
if (!function_exists('random_color')) {
function random_color($trans = "0.6") {
$col_r = mt_rand( 0, 255 );
$col_g = mt_rand( 0, 255 );
$col_b = mt_rand( 0, 255 );
function random_color(string $trans = "0.6"): string {
$col_r = (string) mt_rand( 0, 255 );
$col_g = (string) mt_rand( 0, 255 );
$col_b = (string) mt_rand( 0, 255 );
return "rgba(".$col_r.",".$col_g.",".$col_b.",".$trans.")";
}
}
?>
if (!function_exists('gen_uuidv4')) {
function gen_uuidv4(): string {
$data = random_bytes(16);
// Set version to 0100 (UUID v4)
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
// Set bits 6-7 to 10
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
}
if (!function_exists('gen_uuidv7')) {
function gen_uuidv7(int $time=0): string {
// Get timestamp in milliseconds (48 bits)
if (empty($time)) $time = (int) floor(microtime(true) * 1000);
// Generate 16 bytes of random data
$randomBytes = random_bytes(16);
// Pack the 48-bit timestamp into the first 6 bytes
$timeHex = str_pad(dechex($time), 12, '0', STR_PAD_LEFT);
$bytes = hex2bin($timeHex);
// Append 10 bytes of randomness (we need 16 total bytes)
$bytes .= substr($randomBytes, 0, 10);
// Apply the version bits (Version 7 -> 0b0111) onto byte 6
$bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x70);
// Apply the variant bits (Variant 1 -> 0b10xx) onto byte 8
$bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80);
// Unpack to hex string and format with hyphens
$hex = bin2hex($bytes);
return sprintf('%08s-%04s-%04s-%04s-%012s',
substr($hex, 0, 8),
substr($hex, 8, 4),
substr($hex, 12, 4),
substr($hex, 16, 4),
substr($hex, 20, 12)
);
}
}
+113 -83
View File
@@ -3,10 +3,9 @@
/*******************************************************************
Module : /Printer/PrintHTML.php
Desc. : Class cetak HTML
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : June 15th, 2008.
Last Modified : August 21st, 2026.
Last Modified : October 24th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -14,111 +13,145 @@
declare(strict_types=1);
namespace siaupheng\webapp\Printer;
namespace Webapp\Printer;
use \flight\Session;
use \flight\Engine;
/**
* Class PrintHTML
*
* Menghasilkan bentuk laporan dalam format HTML.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Printer
*/
final class PrintHTML {
private $__avalue = [];
private $__atabel = [];
private $__css = "table";
private $__tstamp = "";
private array $avalue = [];
private array $atabel = [];
private string $css = "table";
private string $stamp = "";
private array $titles = [];
private array $subtitles = [];
protected array $webapp;
protected array $webuser;
public function __construct(Session $session) {
$this->webapp = $session->get('__WEB_APP', ['APP_NAME'=>'', 'APP_VER'=>'']);
$this->webuser = $session->get('__WEB_USER', ['UserID'=>0, 'Username'=>'']);
/**
* @param Engine $app
*/
public function __construct(Engine $app) {
$this->webapp = (array) $app->session()->get('WEB_APP', ['APP_NAME'=>'', 'APP_VER'=>'']);
$this->webuser = (array) $app->session()->get('WEB_USER', ['UserID'=>0, 'Username'=>'']);
}
public function set_css(string $style): void {
if (!empty($style)) $this->__css = $style;
if (!empty($style)) $this->css = $style;
}
public function add_field(string $nama, int $lebar=0, string $align="L", string $func="", int $kol=1): void {
$this->__atabel[] = [ $nama, $lebar, $func, $align, $kol ];
public function add_title(string|array $judul): void {
if (empty($judul)) return;
if (is_array($judul)) {
$this->titles = $judul;
} else array_push($this->titles, $judul);
}
public function clear(): void {
$this->__avalue = [];
public function add_sub_title(string|array $judul): void {
if (empty($judul)) return;
if (is_array($judul)) {
$this->subtitles = $judul;
} else array_push($this->subtitles, $judul);
}
public function add_value(): void {
$tmp_arr = func_get_args();
if (is_array($tmp_arr[0])) $tmp_arr = $tmp_arr[0];
$tmp_out = "<tr>";
for ($i=0; $i<count($this->__atabel); $i++) {
$tmp_val = $tmp_arr[$i];
if (is_array($this->__atabel[$i][2]) && trim("".$tmp_val)<>"") {
$tmp_val = $this->__atabel[$i][2][$tmp_val];
} else if (function_exists($this->__atabel[$i][2]) && trim("".$tmp_val)<>"") {
$tmp_val = call_user_func($this->__atabel[$i][2], $tmp_val);
}
$tmp_val = $this->set_align($tmp_val, $this->__atabel[$i][1], $this->__atabel[$i][3]);
$tmp_out .= $tmp_val;
}
$tmp_out .= "</tr>";
$this->__avalue[] = $tmp_out;
public function add_field(string $nama, int $lebar=0, string $align="L", callable|array|null $func=null, int $kol=1): void {
$this->atabel[] = [ 'n' => $nama, 'l' => $lebar, 'f' => $func, 'a' => $align, 'k' => $kol ];
}
public function add_span(): void {
$tmp_arr = func_get_args();
$tmp_out = "<tr>";
for ($i=0; $i<count($tmp_arr); $i++) {
$tmp_val = $tmp_arr[$i];// CONTENT, COLSPAN=1, L, FUNC, EXTRA
if (!isset($tmp_val[1])) $tmp_val[1] = 1;
if (!isset($tmp_val[2])) $tmp_val[2] = "L";
if (!isset($tmp_val[4])) $tmp_val[4] = "";
if (isset($tmp_val[3])) {
if (function_exists($tmp_val[3]) && trim("".$tmp_val[0])<>"") {
$tmp_val[0] = call_user_func($tmp_val[3], $tmp_val[0]);
public function add_row(array $row): void {
if (!is_array($row) || empty($row)) return;
$row_out = "<tr>";
foreach ($this->atabel as $i => $tabel) {
$col_val = $row[$i] ?? '';
if (!empty($col_val)) {
if (is_array($tabel['f'])) {
$col_val = $tabel['f'][$col_val];
} else if (is_callable($tabel['f'])) {
$col_val = call_user_func($tabel['f'], $col_val);
}
}
$tmp_val = $this->set_align($tmp_val[0], 0, $tmp_val[2], false, false, $tmp_val[1], $tmp_val[4]);
$tmp_out .= $tmp_val;
$row_out .= $this->set_align((string) $col_val, $tabel['l'], $tabel['a']);
}
$tmp_out .= "</tr>";
$this->__avalue[] = $tmp_out;
$row_out .= "</tr>";
echo $row_out;
}
public function add_stamp(int $ctk_ke=1, bool $cetak_nama=false): void {
$this->__tstamp = $this->get_stamp($ctk_ke, $cetak_nama);
}
public function get_stamp(int $ctk_ke=1, bool $cetak_nama=false): string {
return $this->webapp['APP_NAME']."v".$this->webapp['APP_VER'].date("\@ymd.His")."-".isi_nol($this->webuser['UserID'], 3).(($cetak_nama)?"/".strtoupper($this->webuser['Username']):"").(($ctk_ke>0)?"#".isi_nol($ctk_ke,2):"");
}
public function show(int $jumlah_ctk=1) {
$out = "<table class=\"".$this->__css."\"><thead>";
// header out
$tmp_out = "<tr>";
for ($i=0; $i<count($this->__atabel); $i++) {
if ($this->__atabel[$i][4]==0) continue;
$tmp_out .= $this->set_align($this->__atabel[$i][0], $this->__atabel[$i][1], "C", false, true, $this->__atabel[$i][4]);
public function add_span(array $span): void {
if (!is_array($span) || empty($span)) return;
$row_out = "<tr>";
foreach ($span as $col) {
// CONTENT, COLSPAN=1, L, FUNC, EXTRA
if (!isset($col[1])) $col[1] = 1;
if (!isset($col[2])) $col[2] = "L";
if (!isset($col[4])) $col[4] = "";
if (isset($col[3]) && is_callable($col[3])) {
if (function_exists($col[3]) && !empty($col[0])) {
$col[0] = call_user_func($col[3], $col[0]);
}
}
$row_out .= $this->set_align($col[0], 0, $col[2], false, false, $col[1], $col[4]);
}
$tmp_out .= "</tr>";
$out .= "</thead>".$tmp_out."<tbody>";
// content out
for ($i=0; $i<count($this->__avalue); $i++) {
$tmp_str = $this->__avalue[$i];
if (strpos($tmp_str, "_LINE")>0) $tmp_str = "<hr />";
$out .= $tmp_str;
}
$out .= "</tbody></table>";
$out .= $this->__tstamp;
for ($i=1; $i<=$jumlah_ctk; $i++) echo $out;
$row_out .= "</tr>";
echo $row_out;
}
public function set_align(string $text, int $width=0, string $dir="L", bool $line=false, bool $head=false, int $col=1, string $extra=""): string {
public function show_titles(): void {
$_afs = [0=>"4", 1=>"5", 2=>"6"];
foreach ($this->titles as $i => $title) {
vprintf('<div class="fs-%s text-center">%s</div>', [($_afs[$i] ?? '6'), $title]);
}
if (count($this->subtitles) > 0) {
foreach ($this->subtitles as $title) {
vprintf('<div>%s</div>', [$title]);
}
} else
echo '<br />';
}
public function show_headers(bool $is_hide=false): void {
vprintf('<table class="%s"><thead>', [$this->css]);
// 0-n, 1=l, 2-f, 3-a, 4-k
$head_out = "<tr>";
foreach ($this->atabel as $tabel) {
if ($tabel['k'] === 0) continue;
$head_out .= $this->set_align($tabel['n'], $tabel['l'], "C", false, true, $tabel['k'], ($is_hide?'d-none':''));
}
$head_out .= "</tr>";
echo $head_out."</thead><tbody>";
// start content row
}
public function add_stamp(int $ctk_ke=1, bool $tampil_nama=false): void {
$this->stamp = $this->get_stamp($ctk_ke, $tampil_nama);
}
public function get_stamp(int $ctk_ke=1, bool $tampil_nama=false): string {
return $this->webapp['APP_NAME']."v".$this->webapp['APP_VER'].date("\@ymd.His")."-".isi_nol($this->webuser['UserID'], 3).(($tampil_nama)?"/".strtoupper($this->webuser['Username']):"").(($ctk_ke>0)?"#".isi_nol($ctk_ke,2):"");
}
public function show() {
// end content row
echo "</tbody></table>";
if (!empty($this->stamp)) vprintf('<span class="small fst-italic">%s</span>', [$this->stamp]);
}
public function set_align(mixed $text, int $width=0, string $dir="L", bool $line=false, bool $head=false, int $col=1, string $extra=""): string {
$tstyle = $this->create_style($dir);
if ($line===true) {
return "<tr><td colspan=\"".count($this->__atabel)."\" class=\"".$tstyle." ".$extra."\">".$text."</td></tr>";
return "<tr><td colspan=\"".count($this->atabel)."\" class=\"".$tstyle." ".$extra."\">".$text."</td></tr>";
} else {
return (($head===true)?"<th":"<td").(($col>1)?" colspan=\"".(string)$col."\"":"")." class=\"".$tstyle." ".$extra."\" ".(($head===true)?"width=\"".(string)$width."\"":"").">".$text.(($head===true)?"</th>":"</td>");
return (($head===true)?"<th":"<td").(($col>1)?" colspan=\"".(string) $col."\"":"")." class=\"".$tstyle." ".$extra."\" ".(($head===true)?"width=\"".(string) $width."\"":"").">".$text.(($head===true)?"</th>":"</td>");
}
}
@@ -133,9 +166,6 @@ final class PrintHTML {
return implode(' ', $ahasil);
}
//todo: deprecated
public function show_fields() {}
public function add_pagebreak() {}
}
?>
+46 -51
View File
@@ -3,10 +3,9 @@
/*******************************************************************
Module : /Printer/PrintPOS.php
Desc. : Class cetak POS
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : June 15th, 2008.
Last Modified : August 21st, 2026.
Last Modified : October 3rd, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -14,18 +13,27 @@
declare(strict_types=1);
namespace siaupheng\webapp\Printer;
namespace Webapp\Printer;
use \flight\Engine;
use \flight\Session;
/**
* Class PrintPOS
*
* Pembuatan Nota/Struk untuk cetak ke Printer POS.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Printer
*/
class PrintPOS {
private $_header = [];
private $_avalue = [];
private $_astyle = [];
private $_ncont = 0;
private $_maxchr = 40;
private $_config = [
private int $sheet = 0;
private int $maxchr = 40;
private array $header = [];
private array $acontent = [];
private array $config = [
'fontsize' => 1,
'opendraw' => false,
'cutpaper' => false,
@@ -35,59 +43,62 @@ class PrintPOS {
private array $webuser;
protected Engine $app;
public function __construct(Engine $app, Session $session) {
/**
* @param Engine $app
*/
public function __construct(Engine $app) {
$this->app = $app;
$this->webapp = $session->get('__WEB_APP', ['APP_NAME'=>'', 'APP_VER'=>'', 'REAL_PATH'=>'']);
$this->webuser = $session->get('__WEB_USER', ['UserID'=>0, 'Username'=>'']);
$this->webapp = $app->session()->get('WEB_APP', ['APP_NAME'=>'', 'APP_VER'=>'']);
$this->webuser = $app->session()->get('WEB_USER', ['UserID'=>0, 'Username'=>'']);
}
public function set_opendrawer(): void {
$this->_config['opendraw'] = true;
$this->config['opendraw'] = true;
}
public function set_cutpaper(): void {
$this->_config['cutpaper'] = true;
$this->config['cutpaper'] = true;
}
public function set_maxchr(int $max = 0): void {
if ($max > 0) $this->_maxchr = $max;
if ($max > 0) $this->maxchr = $max;
}
public function set_fontsize(int $size = 1): void {
if ($size > 0) $this->_config['fontsize'] = $size;
if ($size > 0) $this->config['fontsize'] = $size;
}
public function set_header_logo(string $logo_file = ""): void {
if (!empty($logo_file) && file_exists($this->webapp['REAL_PATH']."assets/images/".$logo_file)) {
$this->_config['logo'] = $this->webapp['WEB_PATH']."assets/images/".$logo_file;
if (!empty($logo_file) && file_exists(PROJECT_ROOT."public/assets/images/".$logo_file)) {
//$this->config['logo'] = PROJECT_BASE."assets/images/".$logo_file;
$this->config['logo'] = base64_encode(file_get_contents(PROJECT_ROOT."public/assets/images/".$logo_file));
}
}
public function add_header(): void {
$extra = func_get_args();
if (count($extra) > 0) {
foreach ($extra as $_val) {
$this->_header[] = $_val;
}
}
if (count($extra) > 0) $this->header = $extra;
}
public function add_sheet(): void {
$this->_ncont++;
$this->sheet++;
}
public function add(): void {
$val_arr = func_get_args(); $ttext = ""; $tstyle = "L";
if (is_array($val_arr[0])) {
foreach($val_arr as $aval) {
$ttext .= $this->set_align((isset($aval[0])?$aval[0]:""), (isset($aval[1])?$aval[1]:0), (isset($aval[2])?$aval[2]:$tstyle));
foreach ($val_arr as $aval) {
$ttext .= $this->set_align(($aval[0] ?? ""), ($aval[1] ?? 0), ($aval[2] ?? $tstyle));
}
} else {
$ttext = (isset($val_arr[0])) ? $val_arr[0] : "";
$tstyle = (isset($val_arr[1])) ? $val_arr[1] : $tstyle;
$ttext = $val_arr[0] ?? "";
$tstyle = $val_arr[1] ?? $tstyle;
}
$this->_avalue[$this->_ncont][] = $ttext;
$this->_astyle[$this->_ncont][] = $tstyle;
if (str_contains($ttext, "_LINE")) {
$tmp_arr = explode(" ", $ttext);
$ttext = str_pad($tmp_arr[1], $this->maxchr, $tmp_arr[1]);
}
$this->acontent[$this->sheet][] = ($tstyle === "X") ? $ttext : $this->set_align($ttext, $this->maxchr, $tstyle);
}
public function addl(string $text = ""): void {
@@ -115,25 +126,11 @@ class PrintPOS {
}
public function show(int $jumlah_ctk=1): void {
$acontent = [];
$nmax = $this->_maxchr;
for ($s=0; $s<count($this->_avalue); $s++) {
for ($i=0; $i<count($this->_avalue[$s]); $i++) {
$tmp_str = $this->_avalue[$s][$i];
if (strpos($tmp_str, "_LINE")>0) {
$tmp_arr = explode(" ", $tmp_str);
$tmp_str = str_pad($tmp_arr[1], $nmax, $tmp_arr[1]);
}
$acontent[$s][] = ($this->_astyle[$s][$i]=="X") ? $tmp_str : $this->set_align($tmp_str, $nmax, $this->_astyle[$s][$i]);
}
}
$this->_config['times'] = $jumlah_ctk;
$this->config['times'] = $jumlah_ctk;
$aout = ['type' => "escp"];
$aout['config'] = $this->_config;
$aout['header'] = $this->_header;
$aout['content'] = $acontent;
$aout['config'] = $this->config;
$aout['header'] = $this->header;
$aout['content'] = $this->acontent;
$this->app->json($aout);
}
@@ -144,8 +141,6 @@ class PrintPOS {
return str_pad($text, $len, " ", $apad[$dir]);
}
//todo: deprecated
public function set_printnv_logo() {}//delete
}
?>
+20 -8
View File
@@ -3,7 +3,6 @@
/*******************************************************************
Module : /Printer/PrintRAW.php
Desc. : Class cetak RAW
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : June 15th, 2008.
Last Modified : November 1st, 2023.
@@ -14,10 +13,20 @@
declare(strict_types=1);
namespace siaupheng\webapp\Printer;
namespace Webapp\Printer;
use \flight\Engine;
use \flight\Session;
/**
* Class PrintRAW
*
* Pembuatan Laporan dalam bentuk RAW / Natural.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Printer
*/
class PrintRAW {
private $_header = [];
@@ -32,14 +41,17 @@ class PrintRAW {
'opendraw' => false,
'cutpaper' => false,
];
private array $webapp;
private array $webuser;
protected Engine $app;
protected array $webapp;
protected array $webuser;
public function __construct(Engine $app, Session $session) {
/**
* @param Engine $app
*/
public function __construct(Engine $app) {
$this->app = $app;
$this->webapp = $session->get('__WEB_APP', ['APP_NAME'=>'', 'APP_VER'=>'', 'REAL_PATH'=>'']);
$this->webuser = $session->get('__WEB_USER', ['UserID'=>0, 'Username'=>'']);
$this->webapp = $app->session()->get('WEB_APP', ['APP_NAME'=>'', 'APP_VER'=>'']);
$this->webuser = $app->session()->get('WEB_USER', ['UserID'=>0, 'Username'=>'']);
}
public function set_opendrawer(): void {
+12 -2
View File
@@ -3,7 +3,6 @@
/*******************************************************************
Module : /Web/Button.php
Desc. : Button Generator (jQuery & Bootstrap)
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : February 27th, 2008.
Last Modified : August 22nd, 2026.
@@ -14,7 +13,18 @@
declare(strict_types=1);
namespace siaupheng\webapp\Web;
namespace Webapp\Web;
/**
* Class Button
*
* Pembuatan tombol aplikasi (jQuery & Bootstrap).
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Web
*/
class Button {
private $__abutton =[];
+47 -33
View File
@@ -3,10 +3,9 @@
/*******************************************************************
Module : /Web/Form.php
Desc. : Form Generator (jQuery & Bootstrap)
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : February 27th, 2008.
Last Modified : August 22nd, 2026.
Last Modified : September 5th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -14,12 +13,23 @@
declare(strict_types=1);
namespace siaupheng\webapp\Web;
namespace Webapp\Web;
use \flight\Engine;
use \flight\Session;
use \flight\database\SimplePdo;
/**
* Class Form
*
* Pembuatan form (jQuery & Bootstrap).
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Web
*/
final class Form {
private $__aform = [];
private $__ahide = [];
@@ -27,15 +37,18 @@ final class Form {
protected SimplePdo $db;
protected Session $session;
public function __construct(Engine $app, SimplePdo $db, Session $session){
/**
* @param Engine $app
*/
public function __construct(Engine $app){
$this->app = $app;
$this->db = $db;
$this->session = $session;
$this->db = $app->db();
$this->session = $app->session();
}
public function option(string $label, string $field, string|int|null $value=null, bool $enable=true, bool $req=false, array $arr=[], ?string $help=null, ?string $change=null, bool $multi=false, bool $group=false): string {
public function option(string $label, string $field, mixed $value=null, bool $enable=true, bool $req=false, array $arr=[], ?string $help=null, ?string $change=null, bool $multi=false, bool $group=false): string {
$_opsi = '';
if (!empty($change)) $_opsi .= ' ochan="'.$change.'"';
if (!empty($change)) $_opsi .= ' ochan="'.rtrim($change, '();').'"';
if ($enable===false) $_opsi .= ' disabled=true';
if ($req===true) $_opsi .= ' required=true';
if ($multi===true) $_opsi .= ' multiple';
@@ -69,7 +82,7 @@ final class Form {
return $tout;
}
public function option_db(string $label, string $field, string|int|null $value=null, bool $enable=true, bool $req=false, ?string $table=null, ?array $afield=null, ?string $where=null, ?array $aarray=null, ?string $help=null, ?string $change=null, bool $multi=false): string {
public function option_db(string $label, string $field, mixed $value=null, bool $enable=true, bool $req=false, ?string $table=null, ?array $afield=null, ?string $where=null, ?array $aarray=null, ?string $help=null, ?string $change=null, bool $multi=false): string {
$_twhere = '';
if (!is_array($afield)) $afield = ["ID", "Nama", "Label"];
if (!empty($where)) {
@@ -87,7 +100,7 @@ final class Form {
return $this->option($label, $field, $value, $enable, $req, $ahasil, $help, $change, $multi);
}
public function option_que(string $label, string $field, string|int|null $value=null, bool $enable=true, bool $req=false, ?string $query=null, ?array $afield=null, ?array $aarray=null, ?string $help=null, ?string $change=null): string {
public function option_que(string $label, string $field, mixed $value=null, bool $enable=true, bool $req=false, ?string $query=null, ?array $afield=null, ?array $aarray=null, ?string $help=null, ?string $change=null): string {
if (!is_array($afield)) $afield = ["ID", "Nama", "Label"];
$ahasil = [];
if (is_array($aarray)) $ahasil[$aarray[0]] = (!isset($afield[2])) ? $aarray[1] : [$aarray[1], $aarray[2]];
@@ -100,19 +113,19 @@ final class Form {
return $this->option($label, $field, $value, $enable, $req, $ahasil, $help, $change);
}
public function option_jkl(string $label, string $field, string|int|null $value=null, bool $enable=true, bool $req=false, ?string $help=null, ?string $change=null): string {
public function option_jkl(string $label, string $field, mixed $value=null, bool $enable=true, bool $req=false, ?string $help=null, ?string $change=null): string {
return $this->option($label, $field, $value, $enable, $req, ["L" => "Laki-Laki", "P" => "Perempuan"], $help, $change);
}
public function option_ulevel(string $label, string $field, int $value=9, bool $enable=true, bool $req=false, ?string $help=null, ?string $change=null): string {
return $this->option($label, $field, $value, $enable, $req, $this->session->get('__WEB_APP')['USER_LEVEL'], $help, $change);
return $this->option($label, $field, $value, $enable, $req, $this->session->get('WEB_APP')['USER_LEVEL'], $help, $change);
}
public function radio(string $label, string $field, string|int|null $value=null, bool $enable=true, bool $req=false, array $arr=[], ?string $help=null, ?string $change=null): string {
$_val = array_values($arr);
if (empty($value)) $value = $_val[0];
public function radio(string $label, string $field, mixed $value=null, bool $enable=true, bool $req=false, array $arr=[], ?string $help=null, ?string $change=null): string {
$_val = array_keys($arr);
if (is_null($value)) $value = $_val[0];
$_opsi = '';
if (!empty($change)) $_opsi .= ' ochan="'.$change.'"';
if (!empty($change)) $_opsi .= ' ochan="'.rtrim($change, '();').'"';
if ($enable===false) $_opsi .= ' disabled=true';
if ($req===true) $_opsi .= ' required=true';
$tout = '<input type="hidden" id="'.$field.'" value="'.$value.'" />';
@@ -136,11 +149,11 @@ final class Form {
return $this->radio($label, $field, $value, $enable, $req, ["A"=>"A", "B"=>"B", "AB"=>"AB", "O"=>"O", "X"=>"NONE"], $help, $change);
}
public function checkbox(string $label, string $field, string|int|null $value=null, bool $enable=true, bool $req=false, array $arr=[], ?string $help=null, ?string $change=null): string {
public function checkbox(string $label, string $field, mixed $value=null, bool $enable=true, bool $req=false, array $arr=[], ?string $help=null, ?string $change=null): string {
$_val = array_values($arr);
if (empty($value)) $value = $_val[1];
if (is_null($value)) $value = $_val[0];
$_opsi = ' odata="'.htmlspecialchars(json_encode($arr)).'"';
if (!empty($change)) $_opsi .= ' ochan="'.$change.'"';
if (!empty($change)) $_opsi .= ' ochan="'.rtrim($change, '();').'"';
if ($enable===false) $_opsi .= ' disabled=true';
if ($req===true) $_opsi .= ' required=true';
$tout = '<div class="col-form-label form-check"><input type="checkbox" class="form-check-input" id="'.$field.'" name="'.$field.'" value="'.$value.'"'.$_opsi;
@@ -150,11 +163,11 @@ final class Form {
return $tout;
}
public function switch(string $label, string $field, string|int|null $value=null, bool $enable=true, bool $req=false, array $arr=[], ?string $help=null, ?string $change=null): string {
public function switch(string $label, string $field, mixed $value=null, bool $enable=true, bool $req=false, array $arr=[], ?string $help=null, ?string $change=null): string {
$_val = array_values($arr);
if (empty($value)) $value = $_val[1];
if (is_null($value)) $value = $_val[0];
$_opsi = ' odata="'.htmlspecialchars(json_encode($arr)).'"';
if (!empty($change)) $_opsi .= ' ochan="'.$change.'"';
if (!empty($change)) $_opsi .= ' ochan="'.rtrim($change, '();').'"';
if ($enable===false) $_opsi .= ' disabled=true';
if ($req===true) $_opsi .= ' required=true';
$tout = '<div class="col-form-label form-check form-switch"><input class="form-check-input" id="'.$field.'" name="'.$field.'" type="checkbox" role="switch" value="'.$value.'"'.$_opsi;
@@ -164,10 +177,10 @@ final class Form {
return $tout;
}
public function textbox(string $label, string $field, string|int|null $value=null, bool $enable=true, bool $req=false, string $type="text", ?string $holdtxt=null, ?int $maxsize=null, ?string $help=null, ?string $keyup=null, ?string $blur=null): string {
public function textbox(string $label, string $field, mixed $value=null, bool $enable=true, bool $req=false, string $type="text", ?string $holdtxt=null, ?int $maxsize=null, ?string $help=null, ?string $keyup=null, ?string $blur=null): string {
$_opsi = '';
if (!empty($keyup)) $_opsi .= ' okyup="'.$keyup.'"';
if (!empty($blur)) $_opsi .= ' oblur="'.$blur.'"';
if (!empty($keyup)) $_opsi .= ' okyup="'.rtrim($keyup, '();').'"';
if (!empty($blur)) $_opsi .= ' oblur="'.rtrim($blur, '();').'"';
if (!empty($holdtxt)) $_opsi .= ' placeholder="'.$holdtxt.'"';
if (!empty($maxsize)) $_opsi .= ' maxlength="'.$maxsize.'"';
if ($enable===false) $_opsi .= ' readonly';
@@ -178,13 +191,14 @@ final class Form {
if ($type === 'double') $value = uang2($value);
$type = "text";
}
$tout = '<input type="'.$type.'" class="form-control'.$_tclass.'" id="'.$field.'" name="'.$field.'" value="'.$value.'"'.$_opsi.' />';
$tout = '<input type="'.$type.'" class="form-control'.$_tclass.'" id="'.$field.'" name="'.$field.'" value="'.(string)$value.'"'.$_opsi.' />';
$this->__aform[$field] = [ 'label' => $label, 'help' => $help, 'form' => $tout ];
return $tout;
}
public function textauto(string $label, string $field, array $avalue=['value'=>0,'text'=>""], bool $enable=true, bool $req=false, ?string $holdtxt=null, ?int $maxsize=null, ?string $help=null): string {
public function textauto(string $label, string $field, array $avalue, bool $enable=true, bool $req=false, ?string $holdtxt=null, ?int $maxsize=null, ?string $help=null): string {
$_opsi = '';
if (count($avalue) === 0) $avalue = [ 'value' => 0, 'text' => "" ];
if (!empty($holdtxt)) $_opsi .= ' placeholder="'.$holdtxt.'"';
if (!empty($maxsize)) $_opsi .= ' maxlength="'.$maxsize.'"';
if ($enable===false) $_opsi .= ' disabled=true';
@@ -209,8 +223,8 @@ final class Form {
public function textarea(string $label, string $field, ?string $value=null, bool $enable=true, bool $req=false, int $rows=1, ?string $holdtxt=null, ?string $help=null, ?string $keyup=null, ?string $blur=null): string {
$_opsi = '';
if (!empty($keyup)) $_opsi .= ' okyup="'.$keyup.'"';
if (!empty($blur)) $_opsi .= ' oblur="'.$blur.'"';
if (!empty($keyup)) $_opsi .= ' okyup="'.rtrim($keyup, '();').'"';
if (!empty($blur)) $_opsi .= ' oblur="'.rtrim($blur, '();').'"';
if (!empty($holdtxt)) $_opsi .= ' placeholder="'.$holdtxt.'"';
if ($enable===false) $_opsi .= ' disabled=true';
if ($req===true) $_opsi .= ' required=true';
@@ -219,7 +233,7 @@ final class Form {
return $tout;
}
public function plaintext(string $label, string $field, string|int|null $value=null): string {
public function plaintext(string $label, string $field, mixed $value=null): string {
$tout = '<input type="text" class="form-control-plaintext" id="'.$field.'" name="'.$field.'" value="'.$value.'" readonly />';
$this->__aform[$field] = ['label' => $label, 'help' => "", 'form' => $tout];
return $tout;
@@ -231,7 +245,7 @@ final class Form {
public function color(string $label, string $field, ?string $value=null, bool $enable=true, bool $req=false, ?string $help=null, ?string $change=null): string {
$_opsi = '';
if (!empty($change)) $_opsi .= ' ochan="'.$change.'"';
if (!empty($change)) $_opsi .= ' ochan="'.rtrim($change, '();').'"';
if ($enable===false) $_opsi .= ' disabled=true';
if ($req===true) $_opsi .= ' required=true';
$tout = '<input type="color" class="form-control form-control-color" id="'.$field.'" name="'.$field.'" value="'.$value.'"'.$_opsi.' />';
@@ -239,7 +253,7 @@ final class Form {
return $tout;
}
public function hidden(string $field, string|int|null $value=null, string $class="text"): string {
public function hidden(string $field, mixed $value=null, string $class="text"): string {
$tout = '<input type="hidden" id="'.$field.'" value="'.$value.'" class="'.$class.'" />';
$this->__ahide[$field] = $tout;
return $tout;
@@ -254,7 +268,7 @@ final class Form {
$col_right = 'col-sm-' . (10-$lebar_kolom) . ' col-lg-' . (12-$lebar_kolom);
$tres = '';
foreach ($this->__aform as $_key => $_val) {
$tres .= sprintf('<div class="row mb-1"><label class="%s col-form-label" for="%s">%s</label><div class="%s">%s %s</div></div>', $col_left, $_key, $_val['label'], $col_right, $_val['form'], (empty($_val['help'])?'':'<span class="help-block"><small>'.$_val['help'].'</small></span>'));
$tres .= sprintf('<div class="row mb-1"><label class="%s col-form-label" for="%s">%s</label><div class="%s">%s %s</div></div>', $col_left, $_key, $_val['label'], $col_right.(str_contains($_val['form'],'type="radio"')?' d-flex gap-2':''), $_val['form'], (empty($_val['help'])?'':'<span class="help-block"><small>'.$_val['help'].'</small></span>'));
}
foreach ($this->__ahide as $_key => $_val) {
$tres .= $_val;
+42 -28
View File
@@ -3,10 +3,9 @@
/*******************************************************************
Module : /Web/Menu.php
Desc. : Class Menu Manajemen
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : January 16th, 2008.
Last Modified : August 22nd, 2026.
Last Modified : October 21st, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -14,44 +13,60 @@
declare(strict_types=1);
namespace siaupheng\webapp\Web;
namespace Webapp\Web;
use \flight\Engine;
use \flight\Session;
use \flight\database\SimplePdo;
/**
* Class Menu
*
* Manajemen Menu aplikasi.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Web
*/
final class Menu {
private array $webapp;
private array $webuser;
private array $web_app;
private array $web_user;
private array $my_menu;
protected Engine $app;
protected SimplePdo $db;
protected Session $session;
public function __construct(Engine $app, SimplePdo $db, Session $session){
/**
* @param Engine $app
*/
public function __construct(Engine $app){
$this->app = $app;
$this->db = $db;
$this->session = $session;
$this->webapp = $session->get('__WEB_APP', ['APP_MODULE'=>'', 'PARENT_SITE'=>'', 'PARENT_SUB'=>false]);
$this->webuser = $session->get('__WEB_USER', ['Menu'=>'', 'Menu_Grup'=>'', 'MENU_MODUL'=>[]]);
$this->db = $app->db();
$this->session = $app->session();
$this->web_app = $this->session->get('WEB_APP', ['APP_MODULE'=>'', 'PARENT_SITE'=>'', 'PARENT_SUB'=>false]);
$this->web_user = $this->session->get('WEB_USER', ['Menu'=>'', 'Menu_Grup'=>'', 'MENU_MODUL'=>[]]);
$_gmenu = '';
$_umenu = $this->db->fetchField("SELECT CONVERT(DECODE(Menu,?) USING UTF8MB4) Menu FROM app_operator WHERE UserID=?", [$this->web_app['PARENT_CODE'], $this->web_user['UserID']]) ?? '';
if ($this->web_user['Grup_MenuID'] > 0) $_gmenu = $this->db->fetchField('SELECT CONVERT(DECODE(Menu,?) USING UTF8MB4) Menu FROM app_menu_grup WHERE Grup_MenuID=?', [$this->web_app['PARENT_CODE'], $this->web_user['Grup_MenuID']]) ?? '';
$this->my_menu = array_unique(array_filter(explode(",", $_gmenu.",".$_umenu)));
}
public function Sidebar(): string {
$a_modul = [];
$is_modul = ($this->webapp['APP_MODULE'] !== '') ? true : false;
if ($is_modul == true) {
$a_modul[] = $this->webapp['APP_MODULE'];
$is_modul = !empty($this->web_app['APP_MODULE']);
if ($is_modul === true) {
$a_modul[] = $this->web_app['APP_MODULE'];
} else {
$atmp = $this->db->fetchAll('SELECT * FROM app_menu WHERE Level=0 AND Aktif=1 AND Modul<>"IND" ORDER BY Urut');
foreach ($atmp as $tmp) {
$a_modul[] = $tmp['Modul'];
}
foreach ($atmp as $tmp) $a_modul[] = $tmp['Modul'];
}
$my_menu = array_unique(array_filter(explode(",", $this->webuser['Menu_Grup'].",".$this->webuser['Menu'])));
$tsql = 'SELECT * FROM app_menu WHERE Aktif=1 AND Modul IN (?) AND Kode IN (?)';
if ($is_modul == true) $tsql .= ' AND Level>0';
$amodul = $this->db->fetchAll($tsql . ' ORDER BY Kode', [$a_modul, $my_menu]);
$amodul = $this->db->fetchAll($tsql . ' ORDER BY Kode', [$a_modul, $this->my_menu]);
$thasil = '';
$last_level = 0;
@@ -75,10 +90,10 @@ final class Menu {
public function Header(): string {
$a_modul = [];
$is_modul = ($this->webapp['APP_MODULE'] !== '') ? true : false;
$is_modul = !empty($this->web_app['APP_MODULE']);
$mulai_level = 0;
if ($is_modul == true) {
$a_modul[] = $this->webapp['APP_MODULE'];
if ($is_modul === true) {
$a_modul[] = $this->web_app['APP_MODULE'];
$mulai_level = 1;
} else {
$atmp = $this->db->fetchAll('SELECT * FROM app_menu WHERE Level=0 AND Aktif=1 AND Modul<>"IND" ORDER BY Urut');
@@ -87,11 +102,10 @@ final class Menu {
}
}
$my_menu = array_unique(array_filter(explode(",", $this->webuser['Menu_Grup'].",".$this->webuser['Menu'])));
$tsql = 'SELECT * FROM app_menu WHERE Aktif=1 AND Modul IN (?) AND Kode IN (?)';
if ($is_modul == true) $tsql .= ' AND Level>0';
$amodul = $this->db->fetchAll($tsql . ' ORDER BY Kode', [$a_modul, $my_menu]);
$amodul = $this->db->fetchAll($tsql . ' ORDER BY Kode', [$a_modul, $this->my_menu]);
$thasil = '';
$last_level = 0;
@@ -121,15 +135,15 @@ final class Menu {
public function Modul(): string {
$t_modul = '';
if (is_array($this->webuser['MENU_MODUL']) && count($this->webuser['MENU_MODUL'])>0) {
if (is_array($this->web_user['MENU_MODUL']) && count($this->web_user['MENU_MODUL'])>0) {
$t_modul = '<div class="dropdown-divider"></div>';
if ($this->app->request()->getVar('SERVER_ADDR') === '127.0.0.1') {
$href1 = '//127.0.0.1/';
$href2 = "";
} else {
$_host = $this->app->request()->getVar('HTTP_ORIGIN') ?? $this->app->request()->getVar('HTTP_HOST') ?? $this->webapp['PARENT_SITE'];
$_host = $this->app->request()->getVar('HTTP_ORIGIN') ?? $this->app->request()->getVar('HTTP_HOST') ?? $this->web_app['PARENT_SITE'];
$_host = str_replace(['http://','https://'], "", $_host);
if ($this->webapp['PARENT_SUB'] === true) {
if ($this->web_app['PARENT_SUB'] === true) {
$_subs = explode('.', $_host);
if (count($_subs) > 2) array_shift($_subs);
$href1 = "//";
@@ -139,7 +153,7 @@ final class Menu {
$href2 = "";
}
}
foreach ($this->webuser['MENU_MODUL'] as $modul) {
foreach ($this->web_user['MENU_MODUL'] as $modul) {
$href = $href1 . $modul['APP_PATH'] . $href2 . '/' . $this->session->get('APP_TOKEN');
$t_modul .= '<a class="dropdown-item slink" href="'.$href.'"><i class="'.$modul['Icon'].' me-2"></i> '.$modul['Judul'].'</a>';
}
@@ -160,7 +174,7 @@ final class Menu {
$apage = $acus_page[$page];
} else if ($page <> "") {
$apage = $db->fetchRow('SELECT * FROM app_menu WHERE Kode=?', [$page]);
$apage['Width'] = (int)$apage['Width'];
$apage['Width'] = (int) $apage['Width'];
}
$ajson['iswindow'] = ($apage['Width'] > 0) ? true : false;
+32 -20
View File
@@ -3,10 +3,9 @@
/*******************************************************************
Module : /Web/Param.php
Desc. : Class Parameter Manajemen
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : November 14th, 2013.
Last Modified : August 22nd, 2026.
Last Modified : October 16th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -14,10 +13,21 @@
declare(strict_types=1);
namespace siaupheng\webapp\Web;
namespace Webapp\Web;
use \flight\Engine;
/**
* Class Param
*
* Manajemen Variable Request dari GET / POST.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Web
*/
final class Param {
private static $__ahasil = [];
@@ -28,41 +38,43 @@ final class Param {
private static function __data(): void {
global $app;
if (empty($app)) $app = \Flight::app();
$_asumber = array_merge($app->request()->query->getData(), $app->request()->data->getData());
$_asumber = $app->request()->query->getData() + $app->request()->data->getData();
foreach ($_asumber as $__key => $__val) {
self::$__ahasil[$__key] = self::safeSQL($__val);
if (in_array($__val, ['true','false'])) { $__val = ($__val === 'true'); }
else if (is_string($__val)) $__val = urldecode(self::safeSQL($__val));
self::$__ahasil[$__key] = $__val;
}
}
public static function safeSQL(string $str = ""): string {
$_se = array("\\","\0","\n","\r","\x1a","'",'"');
$_re = array("\\\\","\\0","\\n","\\r","\Z","\'",'\"');
$_se = ["\\","\0","\n","\r","\x1a","'",'"'];
$_re = ["\\\\","\\0","\\n","\\r","\Z","\'",'\"'];
return str_replace($_se, $_re, $str);
}
public static function Get(string $key = "", mixed $def = null): mixed {
if (count(self::$__ahasil)==0) self::__data();
if (isset(self::$__ahasil[$key]) && self::$__ahasil[$key]) return self::$__ahasil[$key];
if (empty(self::$__ahasil)) self::__data();
if (isset(self::$__ahasil[$key])) return self::$__ahasil[$key];
return $def;
}
public static function Get_Text(string $key, mixed $def = null): mixed {
if (count(self::$__ahasil)==0) self::__data();
$_str = (isset(self::$__ahasil[$key])) ? self::$__ahasil[$key] : $def;
$_str = str_replace("\\r", "", $_str);
$_str = str_replace("\\n", " ", $_str);
$_str = str_replace("\\t", " ", $_str);
return (trim($_str));
public static function Int(string $key = "", int $def = 0): int {
if (empty(self::$__ahasil)) self::__data();
if (isset(self::$__ahasil[$key])) return (int) self::$__ahasil[$key];
return $def;
}
public static function Get_Array(): array {
public static function Float(string $key = "", float $def = 0): float {
if (empty(self::$__ahasil)) self::__data();
if (isset(self::$__ahasil[$key])) return (float) self::$__ahasil[$key];
return $def;
}
public static function Get_All(): array {
if (count(self::$__ahasil)==0) self::__data();
return self::$__ahasil;
}
public static function Get_ArrayCBOX() {//delete
return [];
}
}
?>
-58
View File
@@ -1,58 +0,0 @@
<?php
/*******************************************************************
Module : /Web/Register.php
Desc. : Class Registrasi Aplikasi
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : November 23th, 2011.
Last Modified : August 11th, 2026.
(c) 2011 - 2026, 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
//OK
declare(strict_types=1);
namespace siaupheng\webapp\Web;
use flight\Engine;
use flight\Session;
use flight\database\SimplePdo;
final class Register {
protected Engine $app;
protected SimplePdo $db;
protected Session $session;
public function __construct(Engine $app, SimplePdo $db, Session $session){
$this->app = $app;
$this->db = $db;
$this->session = $session;
}
public static function reg_id() {
$webapp = (array)\Flight::app()->session()->get('__WEB_APP');
$id = (string)$webapp['REG_ID'] ?? '';
return (substr($id,0,3).".".substr($id,3,3).".".substr($id,6));
}
public static function reg_code() {
$webapp = (array)\Flight::app()->session()->get('__WEB_APP');
$id = (string)$webapp['REG_CODE'] ?? '';
return (substr($id,0,6)."-".substr($id,6,5)."-".substr($id,11,5)."-".substr($id,16,5)."-".substr($id,21,5)."-".substr($id,26,6));
}
static function reg_check(Session $session) {//oke
$webapp = $session->get('__WEB_APP');
return (bool)(isset($webapp['REG_STATUS']) && $webapp['REG_STATUS']) ?? false;
}
static function reg_status(SimplePdo $db, array $apps) {//oke
$kode_db = (bool)$db->fetchField('SELECT UPPER(CONVERT(MD5(CONCAT(REG_YEAR,CONVERT(MD5(CONCAT(REG_ID,REG_NAME)) using latin1),REG_ID,REG_NAME)) using latin1))=REG_CODE FROM app_config WHERE REG_ID=?', [$apps['APP_CODE'] ?? '']);
return [ 'REG_STATUS' => $kode_db === true ];
}
}
?>
+33 -12
View File
@@ -3,10 +3,9 @@
/*******************************************************************
Module : /Web/Table.php
Desc. : Datatable (jQuery & Bootstrap)
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : January 16th, 2008.
Last Modified : August 22nd, 2026.
Last Modified : September 16th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
@@ -14,11 +13,22 @@
declare(strict_types=1);
namespace siaupheng\webapp\Web;
namespace Webapp\Web;
use \flight\Engine;
use \flight\database\SimplePdo;
/**
* Class Table
*
* Pembuatan DataTable (jQuery & Bootstrap).
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Web
*/
final class Table {
private $__ttable = "";
private $__tfield = "";
@@ -45,9 +55,12 @@ final class Table {
protected SimplePdo $db;
protected array $data;
public function __construct(Engine $app, SimplePdo $db) {
/**
* @param Engine $app
*/
public function __construct(Engine $app) {
$this->app = $app;
$this->db = $db;
$this->db = $app->db();
$this->data = $this->app->request()->data->getData();
}
@@ -81,7 +94,7 @@ final class Table {
}
public function set_row_color(string $field = "", string $val = "", string $css = ""): void {
if (epmty($field)) return;
if (empty($field)) return;
$this->__arowcol[] = [ 'F' => $field, 'V' => $val, 'C' => $css ];
}
@@ -131,7 +144,7 @@ final class Table {
$this->__bnobutton = true;
}
public function add_field(string $field = "", string $header = "", string $style = "l", string $format = "", string $footer = "", string $otype = ""): void {
public function add_field(string $field = "", string $header = "", string $style = "l", mixed $format = "", string $footer = "", string $otype = ""): void {
$this->__afield[] = [ 'a' => $field, 'h' => $header, 's' => $style, 'f' => $format, 't' => $footer, 'o' => $otype ];
}
@@ -149,7 +162,7 @@ final class Table {
$row = $this->db->fetchRow("SELECT ".$this->__tfooter." FROM ".$this->__ttable.$this->__twhere, $this->__aparam);
foreach ($this->__afield as $col) {
$tval = $row[$col['a']] ?? '';
if (is_set($col['t']) && !empty($col['t'])) {
if (isset($col['t']) && !empty($col['t'])) {
if (is_array($col['t'])) {
$tval2 = $col['t'][$tval] ?? '';
} else if (function_exists($col['t'])) {
@@ -173,8 +186,7 @@ final class Table {
// adding all option
foreach ($this->__aoption as $opsi) {
if (in_array($opsi['type'], ["button","button-dt"])) {
if (!isset($opsi['field'])) continue;
if (!empty($opsi['field']) && ($row[$opsi['field']] !== (!empty($opsi['value']) ? $opsi['value'] : (string)$this->app->session()->get('__WEB_USER')['UNIX']))) {} else {
if (!empty($opsi['field']) && ((string) $row[$opsi['field']] !== (string) $opsi['value'])) {} else {
$aoption['button'][] = [ $opsi['icon'], (empty($opsi['field_css'])?'':$opsi['avalue_css'][$row[$opsi['field_css']]]??'') ];
}
}
@@ -196,6 +208,11 @@ final class Table {
$tval = $row[$col['a']];
if (is_array($col['f'])) {
$tval = $col['f'][$tval];
} else if (!is_null($col['f']) && str_contains($col['f'], '::')) {
$tclass = explode("::", $col['f']);
if (class_exists($tclass[0]) && method_exists($tclass[0], $tclass[1])) {
$tval = call_user_func($col['f'], $tval);
}
} else if (!is_null($col['f']) && function_exists($col['f'])) {
$tval = call_user_func($col['f'], $tval);
} else if (is_string($tval)) {
@@ -257,8 +274,7 @@ final class Table {
// adding all option
foreach ($this->__aoption as $opsi) {
if (in_array($opsi['type'], ["button","button-dt"])) {
if (!isset($opsi['field'])) continue;
if (!empty($opsi['field']) && ($row[$opsi['field']] !== (!empty($opsi['value']) ? $opsi['value'] : $this->app->session()->get('__WEB_USER')['UNIX']))) {} else {
if (!empty($opsi['field']) && ((string) $row[$opsi['field']] !== (string) $opsi['value'])) {} else {
$aoption['button'][] = [ $opsi['icon'], (empty($opsi['field_css'])?'':$opsi['avalue_css'][$row[$opsi['field_css']]]??'') ];
}
}
@@ -280,6 +296,11 @@ final class Table {
$tval = $row[$col['a']];
if (is_array($col['f'])) {
$tval = $col['f'][$tval];
} else if (!is_null($col['f']) && str_contains($col['f'], '::')) {
$tclass = explode("::", $col['f']);
if (class_exists($tclass[0]) && method_exists($tclass[0], $tclass[1])) {
$tval = call_user_func($col['f'], $tval);
}
} else if (!is_null($col['f']) && function_exists($col['f'])) {
$tval = call_user_func($col['f'], $tval);
} else if (is_string($tval)) {
+12 -2
View File
@@ -3,7 +3,6 @@
/*******************************************************************
Module : /Web/Terbilang.php
Desc. : Class Format Angka & Terbilang
Created By : Siau Pheng (siaupheng@3fonia.com).
Created Date : February 12th, 2009.
Last Modified : August 22nd, 2026.
@@ -14,7 +13,18 @@
declare(strict_types=1);
namespace siaupheng\webapp\Web;
namespace Webapp\Web;
/**
* Class Terbilang
*
* Pembuatan text terbilang.
*
* @license MIT, https://www.3fonia.com
* @copyright Copyright (c) 2008-2026, Siau Pheng <siaupheng@3fonia.com>
*
* @package Webapp\Web
*/
final class Terbilang {
private $numb = ["","Satu","Dua","Tiga","Empat","Lima","Enam","Tujuh","Delapan","Sembilan"];