diff options
| author | Lester Caine <lester@lsces.co.uk> | 2026-06-06 15:05:23 +0100 |
|---|---|---|
| committer | Lester Caine <lester@lsces.co.uk> | 2026-06-06 15:05:23 +0100 |
| commit | 1582b5b504970da3049d6691b37db6f8c15c0d30 (patch) | |
| tree | 1223fc78f506551df99b460bf7f225473a87a81e /README.md | |
| parent | ffdc5f6c7a825995e78e20e5bc84d5de0d2457d8 (diff) | |
| download | bitweaver-1582b5b504970da3049d6691b37db6f8c15c0d30.tar.gz bitweaver-1582b5b504970da3049d6691b37db6f8c15c0d30.tar.bz2 bitweaver-1582b5b504970da3049d6691b37db6f8c15c0d30.zip | |
README: comprehensive architecture overview
Covers stack, package system, request lifecycle, class hierarchy,
key globals, adodb layer, Smarty conventions, permission/role system,
liberty content engine, xref system, session/auth, deploy path,
and package inventory.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 258 |
1 files changed, 251 insertions, 7 deletions
@@ -1,7 +1,251 @@ -Having been using bitweaver for many years I have now retired from buisness and am -carrying on things for enjoyment, not that maintaining PHP is a joy at times. -I have several sites that have been live on bitweaver under PHP7.3 from their creating -and now I have moved them to a more modern webstack under PHP8.4 with Firebird5. -This form of the code is a little of a tangent from the main code base as I have also -hacking into Smarty5 and andded namespace to the mix. It's published here in the hope -someone might find parts of it useful. +# bitweaver-lsces + +A personal fork of [bitweaver](http://www.bitweaver.org/) — a PHP CMS and application framework +originally derived from TikiWiki. This organisation holds one repository per package. All packages +are deployed together under a single web root (`bitweaver5/`). + +Having used bitweaver for many years across several live sites, this fork has been carried forward +into a modern stack: PHP 8.5, Firebird 5, Smarty 5 with namespaces, and adodb on a custom branch. +It is published here in the hope that parts of it are useful to others. + +--- + +## Stack + +| Layer | Technology | +|---|---| +| Language | PHP 8.5 | +| Database | Firebird 5 via adodb (`v5.22.11-lsc` branch) | +| Templates | Smarty 5 | +| CSS/JS | Bootstrap 3, jQuery — no npm, no Node.js | +| Web server | nginx + php-fpm | + +--- + +## Architecture Overview + +Bitweaver is built around a **package system**. Every feature area (articles, blogs, contact, +stock, etc.) is a self-contained directory under the web root. Packages are loosely coupled +through a small set of global objects and a shared database. + +### Packages + +Each package directory follows this layout: + +``` +<package>/ + admin/ package administration pages + includes/ + bit_setup_inc.php package self-registration (always loaded) + classes/ PHP classes for this package + config_defaults_inc.php package-level config defaults (optional) + templates/ Smarty templates (.tpl) + modules/ sidebar/layout module templates + index.php package landing page + *.php entry-point pages (list, edit, view, add…) +``` + +`bit_setup_inc.php` is the only file loaded unconditionally for every request. It calls +`$gBitSystem->registerPackage()` to declare the package and `$gBitSystem->registerAppMenu()` +to add a navbar dropdown. + +### Request Lifecycle + +1. `index.php` (web root) → `kernel/includes/setup_inc.php` +2. `setup_inc.php` initialises global objects (`$gBitDb`, `$gBitSystem`, `$gBitSmarty`, + `$gBitUser`), detoxifies `$_GET`, and loads `bit_setup_inc.php` for every active package. +3. The requested page file runs: loads a content object, does DB work, assigns Smarty + variables, calls `$gBitSmarty->display( 'bitpackage:pkg/template.tpl' )`. +4. Smarty renders through `kernel/templates/html.tpl` → layout columns → modules → page body. + +--- + +## Class Hierarchy + +``` +BitBase (kernel — abstract, DB-aware base) +└── LibertyBase (liberty — adds mContentId, mContentTypeGuid) + └── LibertyContent (liberty — full content lifecycle: store, load, expunge) + └── <Package class> e.g. Contact, StockAssembly, StockComponent, StockMovement +``` + +Additional kernel classes (not in the content hierarchy): + +- **`BitSystem`** (`$gBitSystem`) — package registry, config store, menu registration, + layout, error handling. +- **`BitDbAdodb`** (`$gBitDb`) — thin adodb wrapper; all DB access goes through this. +- **`BitSingleton`** — base for objects that must exist once (BitSystem inherits from this). +- **`KernelTools`** — static utility methods: `tra()` (translation), `detoxify()`, etc. +- **`RolePermUser`** (`$gBitUser`) — the logged-in user; holds roles, permissions, preferences. + +--- + +## Key Globals + +| Variable | Class | Purpose | +|---|---|---| +| `$gBitDb` | `BitDbAdodb` | Database connection | +| `$gBitSystem` | `BitSystem` | Package registry, config, menus | +| `$gBitSmarty` | Smarty subclass | Template engine | +| `$gBitUser` | `RolePermUser` | Current user (anonymous or authenticated) | +| `$gContent` | `LibertyContent` subclass | The content object for the current page | + +--- + +## Database Layer + +All queries use **adodb** — no raw PDO or mysqli. The wrapper is `BitDbAdodb` in +`kernel/includes/classes/BitDbAdodb.php`. + +Key adodb methods used throughout the codebase: + +| Method | Purpose | +|---|---| +| `getArray($sql, $vals)` | Returns all rows as a numerically-indexed array | +| `getAssoc($sql, $vals)` | Returns rows keyed by the first column | +| `getOne($sql, $vals)` | Returns a single scalar value | +| `getRow($sql, $vals)` | Returns a single row as an associative array | +| `query($sql, $vals)` | Execute; returns a recordset (iterate with `fetchRow()`) | +| `executeQuery($sql, $vals, $numrows, $offset)` | Paginated query | + +Placeholders are always positional `?`. Named binds are not used. + +The database is **Firebird 5**. Firebird is stricter than MySQL in several ways that matter: +- Every non-aggregate `SELECT` column must appear in `GROUP BY`. +- `IN ()` with an empty list is a syntax error — always guard with a fallback. +- `FIRST n` / `ROWS n` for limiting result sets (not `LIMIT`). +- `LOCALTIMESTAMP` / `CURRENT_TIMESTAMP` as default expressions behave differently from MySQL. + +--- + +## Template System (Smarty) + +Templates live in `<package>/templates/`. The `bitpackage:` Smarty resource prefix resolves +templates through a search path that allows per-site overrides: + +1. `config/themes/<site>/` (symlink to `/etc/webstack/domains/<site>/themes/<site>/`) +2. `<package>/templates/` + +This means dropping a template file into the site-specific path silently overrides the +package default — useful for site-specific customisation without forking the package. + +**Important Smarty conventions in this codebase:** + +- `{tr}...{/tr}` for user-visible strings (maps to `KernelTools::tra()`). + `"string"|tra` is **not** a valid Smarty modifier and will throw a compiler error. +- `{form}...{/form}` block plugin auto-injects the CSRF ticket hidden field. +- `{strip}` removes inter-tag whitespace; keep content like `•` inside valid elements. +- Per-site footer scripts go in `kernel/footer_inc.tpl`, not `kernel/footer.tpl`. + `footer_inc.tpl` is loaded via the `mAuxFiles` loop in `html.tpl` and is reliable. + `footer.tpl` as a theme override only loads when the active style name matches exactly. + +--- + +## Permission / Role System + +Roles are stored in the `users_roles` table. Default role IDs: + +| role_id | Name | perm_level | +|---|---|---| +| 1 | Administrators | admin | +| 2 | Editors | editors | +| 3 | Registered | registered | +| -1 | Anonymous | basic | + +Permissions are declared in `<package>/admin/schema_inc.php` and stored in +`users_role_permissions`. `$gBitUser->hasPermission('p_pkg_action')` is the standard check. + +When writing role-filter queries, guard the `IN()` list with: +```php +array_keys($gBitUser->mRoles ?? []) ?: [-1] +``` +Firebird rejects `IN ()` with an empty list. + +--- + +## Liberty Content System + +The **liberty** package is the content engine. All content types (pages, articles, contacts, +stock items, movements, …) share a single `liberty_content` table row identified by a +`content_id` and a `content_type_guid` string. + +A package registers its content type in `schema_inc.php` and provides a class that extends +`LibertyContent`. The class overrides `store()`, `load()`, and `expunge()` to handle its +own additional tables/xrefs on top of the base liberty row. + +### XRef System + +`liberty_xref` is a flexible key-value extension table attached to any content item. +Rows are grouped by `x_group` and typed by `item`. The OOP layer wraps this: + +- **`LibertyXrefType`** — describes one xref slot (group, item key, cardinality, etc.) +- **`LibertyXref`** — one populated xref row +- **`LibertyXrefGroup`** — a collection of xref rows sharing an `x_group` +- **`LibertyXrefInfo`** — the full set of xref groups for a content item + +**Loading pattern** (display and edit pages): +```php +$gContent->loadXrefInfo(); +$gBitSmarty->assign('gXrefInfo', $gContent->mXrefInfo); +``` + +**Template pattern**: +```smarty +{foreach $gXrefInfo->mGroups as $xrefGroup} + {include file=$gContent->getXrefListTemplate($xrefGroup->mTemplate) + xrefGroup=$xrefGroup allow_edit=false} +{/foreach} +``` + +Group templates receive `$xrefGroup` (a `LibertyXrefGroup` object). The first two lines +of every group template set local flags: +```smarty +{assign var=xrefAllowEdit value=$allow_edit|default:false} +{assign var=isHistory value=($xrefGroup->mXGroup eq 'history')} +``` + +--- + +## Session / Authentication + +Cookie name: `bit-user-{site_title_stripped}` (lowercase alphanumeric). + +Login stores the PHP `session_id()` in `users_cnxn.cookie` mapped to `user_id`. Subsequent +requests look up the cookie value in `users_cnxn` to identify the user. This is independent +of PHP's own session mechanism even though they share the same cookie name. + +--- + +## Deploy Path + +Code is developed and tested live in `/srv/website/bitweaver5/` (with xdebug available). +Proven changes are copied to the matching package repo under `~/Development/bitweaver-lsces/<pkg>/`, +reviewed with BeyondCompare, then committed and pushed. + +Servers (`srv9`, `srv10`) pull from the desktop's local git repos — **not** from GitHub. +The deploy script is `/etc/webstack/scripts/server-pull-all.sh <package>`. + +Test on **srv9** first. `srv10` is production and only receives changes proven on srv9. + +After any deploy that touches Smarty templates: clear the template cache and restart php-fpm. + +--- + +## Packages in This Organisation + +| Package | Content type | Notes | +|---|---|---| +| kernel | — | Bootstrap, globals, BitSystem, BitBase | +| liberty | `liberty_content` | Content engine, xref system | +| users | — | Auth, roles, permissions | +| themes | — | Layout, CSS loading, module system | +| languages | — | Translations, `tra()` string lookup | +| config | — | Site-level overrides (CSS, templates) | +| contact | `contact` | Person and business contacts, CSV import | +| stock | `stockassembly`, `stockcomponent`, `stockmovement` | BOM, stock levels, movement CSV import | +| articles | `article` | — | +| blogs | `blog`, `blogpost` | — | +| wiki | `wiki page` | — | +| fisheye | `fisheye` | Image gallery | +| messages | — | Internal messaging | +| util | — | Shared JavaScript, icons, cross-package utilities | |
