Codebase tour
What is where in an INACT repository, and how a click becomes a query. Written for the master repository; every fork has the same layout.
How this page was verified
Written from master on 2026-09-06. Directory counts are from that day.
Top-level layout
| Path | What it holds |
|---|---|
main.php | The single entry point for the UI. Loads the bootstrap, then dispatches on page= and cmd=. |
setting.php, connect.php, db_config.php, globals.php | The bootstrap: .env, the $_DB array, the PDO connection, the config table, sessions. globals.php is Joomla-derived code that emulates register_globals. |
_menu.php | Builds the sidebar from the module, report and dashboard registries. |
modules/ | 54 folders, one per module. The application proper. |
templates/tracking_v2/ | 839 HTML templates and the JavaScript under js/. One folder for the whole app. |
libraries/ | Shared PHP: the function libraries, the PDO layer, the template engine, and vendored third-party code (Zend, FPDF, TCPDF, html2pdf, jpgraph, PhpMailer). |
src/ | PSR-4 code: basic/ (the Base class with the module registry config, helpers for Color, DateTime, Html, Number, Path) and the flavours custom/, resindo/, minerba/. |
models/ | ActiveRecord-style models on illuminate/database, mostly procurement: spb, rfq, purchase_order, mrr, expediting, routing, vendor. |
contracts/ | Interfaces: routing_procurement.interfaces.php and an email abstract. |
db/ | phinx: 431 migrations, 52 seeds, the migration template. |
cron/ | The scheduled jobs, see Cron jobs. |
dashlets/ | The self-contained widget folders, see Dashboards. |
includes/ | Front-end assets: javascripts/tracking/ with the dhtmlx code, the PDF viewers (pdfviewer, pdfviewer_mozilla, pdfviewern, inactviewer), calendars and jQuery; pdfjs/; style/; richhtml5/. The PDF viewer API scripts under javascripts/tracking/pdfviewer/web/api/ do server work, for example the auto-publish after approval. |
download/ | File delivery: download.php, watermark.php, downloadattachment.php. |
rest/ | A Slim-based REST layer used by the mobile and touch front-ends: rout.php, checkLogin.php, restIpad.php, touch.php. |
touch/ | The touch front-end. |
registration/ | The first-run setup wizard: company, departments, numbering, bank account, privileges. |
docUpload/, docTemp/ | Uploaded files and temporary files. Configured by fileupload and filetemp in inweb_config. |
image/, minify/, plugins/ | Static images, the minifier, a query profiler. |
ioncube/ | The ionCube loader wizard for encoded deployments. Not used on a plain checkout. |
deploy/, .github/workflows/ | The GitHub Actions deploy, see Environments and deploy. Never synced into the encrypted twin. |
vendor/ | Composer. |
From a click to a query
- Every UI request hits
main.php. It requiressetting.php, which loads.env(symfony/dotenv), builds$_DBinconnect.php, opens the PDO connection throughInactPDO::connect(), wraps it as$pdo = new PDOLogActivity(), loadsinweb_configinto$rconfigand the$inweb_*globals, and starts the session.main.phpthen sets$INWEB_CONFIG = getInwebConfigList(). page=membersends the request tomodules/member/member.php, which handles login, logout, the dashboard, downloads, and the module dispatch.- The module is chosen by
cid. The sidebar links aremain.php?page=member&cid=<md5 of modules_code>.getModuleList()inreference_function.inc.phpindexes thets_modulesrows by that md5, and theBaseclass (src/basic/Base.php) resolves the selected module, its reference sub-screen (modref=) and, for reports, thereport_code. Only installed modules the user has aviewprivilege on are reachable. - The module folder takes over.
modules/<code>/<code>.phpis the controller. It defines its templates, checks privileges, and includes the handler that matches the request. - Grids load twice. The page renders the template with an empty dhtmlxGrid; the grid then requests the same URL with
&xml=1, and the module answers with XML rows. A blank grid on a rendered page means the XML request failed.
The shape of a module
Almost every module folder follows one pattern. Learn it once:
| File | Role |
|---|---|
<code>.php | Controller: template definitions, privilege checks, dispatch on cmd= and act=. |
<code>_header.inc.php | Toolbar buttons, each behind a havePrivilegesResource() check. |
<code>_handler_form.php | GET handlers keyed on cmd=: forms, dialogs, exports, prints. |
<code>_handler_post.php | POST handlers keyed on act=: add, edit, delete, submit. |
<code>.inc.php | Query helpers used by the handlers. Often the oldest code in the folder. |
<code>_groupby.inc.php, <code>_subgrid.inc.php | Tree and sub-grid XML. |
<code>_handler_print_browse.inc.php | Print mode, reached by print= from the Reporting menu. |
<code>_multiupload_form.php, <code>_multiupload_upload.php | The multi-file uploader. |
<code>_sendmail_*.php | Send-by-email dialogs. |
<code>.class.php | Where present, the class that implements RoutingProcurementInterface for approval. |
*_041214.php, *.bak | Dated backups. Not routed. Ignore them. |
Templates are templates/tracking_v2/<code>_browse.htm, <code>_form.htm, <code>_search.htm and so on, rendered by Inweb_Template (libraries/inweb/Inweb/Template.php): $tpl->Define(), $tpl->Assign(), $tpl->Parse(). Template variables are {name} and dynamic blocks are defined with DefineDynamic().
The libraries you will read most
| File | What is in it |
|---|---|
libraries/tracking_function.inc.php | The big one: privileges (havePrivilegesResource()), library folders, people and projects, DMS reference helpers. |
libraries/reference_function.inc.php | getInwebConfigList(), the module and report lists, action-indicated lists, getMdrMatrixTypeList(), the operator-role helpers. |
libraries/additional_global_variables.inc.php | $INACT_CONFIG, $ACTION_CODE_FOR_ROUTING, $LIST_ORGANIZATION, $PAGE_TYPE_ONLOADED_AS, $KEYCONFIG_*. Constants that shape behaviour. |
libraries/procure_function.inc.php, numbering_function.inc.php, print_template_function.inc.php, purchase_order_pdf.inc.php | Procurement helpers, document numbering, the print flavour selection, PO PDF. |
libraries/InactPDO.php, PDOLogActivity.php | The PDO layer, see Database portability. |
libraries/inweb.lib.php | The legacy helpers, including iw_mysql_query(), which throws on entry in four of the five forks. |
src/basic/Base.php | MODULE_REFERENCE_TABLE_CONFIG: which table, columns and labels every generic reference screen binds to. Add a reference screen by adding an entry here. |
modules/routing/routing.inc.php | Routing helpers, the Transmittal class lives next to it, RoutingProcurementUc.class.php too. |
Things that surprise new readers
register_globalsemulation.$_GET['doc_no']is also$doc_no. Many handlers read the bare variable.br_form_vars('name')is the sanitising accessor used in newer code.cidis an md5. Grep for the module code, not the hash.- Two data-access layers coexist. Legacy
iw_mysql_query()/mysqli_*and$pdo. Where the legacy helper throws, any screen that reaches it is dead. The module pages list which paths those are. - Comments in Bahasa Indonesia are common in the older code (
// buat rout return status menjadi N). They are worth reading; they often explain a client's rule. - Dead code is left in place: commented-out blocks,
if (false)guards, dated backup files. A function existing is not evidence that a feature works. Check the live path. - Flavours.
Feature\PrintDoc\Htmlininweb_configselects whichsrc/<flavour>/class renders printed documents. The default isResindo. - The seeds are the reference data.
db/seeds/is where menu entries, config keys, action codes and report rows come from. When a fork "has a feature master lacks", start by diffing its seed.