Skip to content

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

PathWhat it holds
main.phpThe single entry point for the UI. Loads the bootstrap, then dispatches on page= and cmd=.
setting.php, connect.php, db_config.php, globals.phpThe bootstrap: .env, the $_DB array, the PDO connection, the config table, sessions. globals.php is Joomla-derived code that emulates register_globals.
_menu.phpBuilds 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

  1. Every UI request hits main.php. It requires setting.php, which loads .env (symfony/dotenv), builds $_DB in connect.php, opens the PDO connection through InactPDO::connect(), wraps it as $pdo = new PDOLogActivity(), loads inweb_config into $rconfig and the $inweb_* globals, and starts the session. main.php then sets $INWEB_CONFIG = getInwebConfigList().
  2. page=member sends the request to modules/member/member.php, which handles login, logout, the dashboard, downloads, and the module dispatch.
  3. The module is chosen by cid. The sidebar links are main.php?page=member&cid=<md5 of modules_code>. getModuleList() in reference_function.inc.php indexes the ts_modules rows by that md5, and the Base class (src/basic/Base.php) resolves the selected module, its reference sub-screen (modref=) and, for reports, the report_code. Only installed modules the user has a view privilege on are reachable.
  4. The module folder takes over. modules/<code>/<code>.php is the controller. It defines its templates, checks privileges, and includes the handler that matches the request.
  5. 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:

FileRole
<code>.phpController: template definitions, privilege checks, dispatch on cmd= and act=.
<code>_header.inc.phpToolbar buttons, each behind a havePrivilegesResource() check.
<code>_handler_form.phpGET handlers keyed on cmd=: forms, dialogs, exports, prints.
<code>_handler_post.phpPOST handlers keyed on act=: add, edit, delete, submit.
<code>.inc.phpQuery helpers used by the handlers. Often the oldest code in the folder.
<code>_groupby.inc.php, <code>_subgrid.inc.phpTree and sub-grid XML.
<code>_handler_print_browse.inc.phpPrint mode, reached by print= from the Reporting menu.
<code>_multiupload_form.php, <code>_multiupload_upload.phpThe multi-file uploader.
<code>_sendmail_*.phpSend-by-email dialogs.
<code>.class.phpWhere present, the class that implements RoutingProcurementInterface for approval.
*_041214.php, *.bakDated 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

FileWhat is in it
libraries/tracking_function.inc.phpThe big one: privileges (havePrivilegesResource()), library folders, people and projects, DMS reference helpers.
libraries/reference_function.inc.phpgetInwebConfigList(), 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.phpProcurement helpers, document numbering, the print flavour selection, PO PDF.
libraries/InactPDO.php, PDOLogActivity.phpThe PDO layer, see Database portability.
libraries/inweb.lib.phpThe legacy helpers, including iw_mysql_query(), which throws on entry in four of the five forks.
src/basic/Base.phpMODULE_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.phpRouting helpers, the Transmittal class lives next to it, RoutingProcurementUc.class.php too.

Things that surprise new readers

  • register_globals emulation. $_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.
  • cid is 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\Html in inweb_config selects which src/<flavour>/ class renders printed documents. The default is Resindo.
  • 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.