PHP Classes

File: README_FIRST.md

Recommend this page to a friend!
  Packages of Uku-Kaarel Jo~esaar   too-vark   README_FIRST.md   Download  
File: README_FIRST.md
Role: Documentation
Content type: text/markdown
Description: Documentation
Class: too-vark
Manage people work schedule times and tasks
Author: By
Last change: Add files via upload

Role updated with ponytal thing
Date: 5 days ago
Size: 12,111 bytes
 

Contents

Class file image Download

TOOAJAD PROJECT CONTEXT

<!-- LLM working document. Human spec: TooVark-Specification.md --> <!-- FORMAT: Sections: CONSTRAINT, STACK, APP, FILES, SCHEMA, AUTH CONTEXT, PATTERNS (P1..P14), RULE FORMAT, COMPILE, STYLE, PROHIBIT, STATE, ROLE. Terse. No narrative. -->

Today is 2026-05-10

CONSTRAINT AND STACK

PHP 8.3+ | SQLite3 PDO | Vanilla JS ES2017+ | CSS mobile-first 600px monospace Zero dependencies. Single-file deploy: compile.php $\rightarrow$ index_release.php + app.sqlite. SQLite constraints handle business logic. Don't duplicate in PHP. strict_types=1. Arrow functions, match, array destructuring, never return type.

APP

Work scheduler, ~40 workers. Manager defines rules via Visual UI $\rightarrow$ generates monthly tasks. Workers: see today's/yesterday's tasks, progress 0$\rightarrow$1$\rightarrow$2. Admin: team overview, assign tasks, print, user/location/config mgmt, CSV. i18n: Estonian(et)/English(en), session-based. __('key') $\rightarrow$ $i18n['key'][$langi].

FILES

index.php	entry: defines(ORG_NAME,DB_FILE,USER1,APP_DEBUG)$\rightarrow$session$\rightarrow$CSRF$\rightarrow$auth context$\rightarrow$HTML shell
compile.php	merges src/ + plugins/ $\rightarrow$ index_release.php. Per-file php_strip_whitespace + css_compress.
src/i18n.php	$i18n=['key'=>['EN','ET']], $i18ni=['en'=>0,'et'=>1]
src/helpers.php	utilities: get_ip(), rl_ok/rl_fail/rl_clear(), location_exit(), json_exit(), json_input(), validate_task(), timeShift(), upsert_task(), insert_user(), known_titles(), db_try($tag,$fn,$unique_msg), workers_list(), users_full_list()
src/plugins.php	plugin loader: glob plugins/*.php, registers routes/views/nav/schema/etag/write lists.
src/api_handlers.php  core api_*() handler functions. [code,body] returns. Called by api.php and tests/run.php.
src/database.php	PDO+PRAGMA+CREATE TABLE (users, rules, tasks, task_details, config, rl) + admin seed.
src/api.php	REST router: CSRF gate $\rightarrow$ pre-auth $\rightarrow$ auth gate $\rightarrow$ admin gate ($_admin_routes) $\rightarrow$ ETag Cache $\rightarrow$ match dispatch $\rightarrow$ plugin fallback.
src/views.php	HTML shell only. NO data, NO $pdo, NO json_encode. Plugin nav/view merge. Uses centralized auth vars.
src/init.js	CURRENT_VIEW/SCOPE/YM, escHtml(), h(), optionsHtml(), lazyRender(). No rendering logic.
src/app.js	apiCall(CSRF header), init*() per view, fetch $\rightarrow$ template render, surgical DOM updates.
src/debug.js	JS error/promise logging via app_log(). Included only if APP_DEBUG=true.
src/style.css	mobile-first, print @media, utility classes. 4-step spacing (--sp-1..4), single --radius.
plugins/debug.php	PLUGIN: debug_log, timer_log, app_log. Removable without breaking core.
plugins/config.php  PLUGIN: config CRUD, archive_year, api_can_archive. Removable without breaking core.
plugins/audit*	PLUGIN: Removable without breaking core.
tests/run.php	23 test groups, in-memory SQLite, zero deps.
tests/run_js.html	8 test groups: isoWeek, escHtml, visual rules sync, setStatusBtn, syncStatusColor.
TooVark-Specification.md	Human-facing spec.
Styleguide.html	Dev reference for :root vars.

SCHEMA

PRAGMA foreign_keys=ON;

users(id INTEGER PK, username TEXT UNIQUE, password TEXT, real_name TEXT, contact TEXT, force_password_change INTEGER DEFAULT 0)
user_rules(user_id INTEGER PK REFERENCES users(id) ON DELETE CASCADE, rules_text TEXT)
tasks(id INTEGER PK, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
  task_date TEXT, title TEXT, start_time TEXT, end_time TEXT, status INTEGER DEFAULT 0, notes TEXT DEFAULT '',
  source TEXT DEFAULT 'manual',
  UNIQUE(user_id,task_date,title))
CREATE INDEX idx_tasks_date ON tasks(task_date)
task_details (title TEXT PRIMARY KEY NOT NULL, address TEXT, description TEXT, related_person TEXT, checklist TEXT)
config(key TEXT PK, val TEXT)
rl(ip TEXT PK, fails INTEGER, expire INTEGER)

AUTH CONTEXT

Centralized auth variables ? Set once in index.php: $logged_in, $uid, $u_name, $is_admin, $today_date, $current_time, $view, $scope, $ym, $current_month. Refer to P9/P10 for security protocol.

PATTERNS ? DO NOT BREAK

P1 Smart Merge ? Use INSERT OR IGNORE + UNIQUE(user_id,task_date,title). Existing/started tasks are never overwritten.

P2 True Sync ? Rules generation auto-deletes status=0 AND source='rule' tasks for the target month before generating new ones. source='manual' tasks are untouched.

P3 Status ? min(status+1, 2). Worker updates own only (AND user_id=?). Delete guard: AND status<2.

P4 Cascade ? ON DELETE CASCADE on both FKs. Admin (USER1, id=1) protected: if($id<=1).

P5 REST API ? Client: fetch('?api=endpoint',{method:'POST',body:JSON.stringify(d),headers:{'X-CSRF-Token':CSRF_TOKEN}}).then(r=>r.json()). Server: match($api){...}; json_exit([...]);.

P6 Routing ? ?api=X $\rightarrow$ REST JSON. ?view=X $\rightarrow$ HTML shell. ?scope=X $\rightarrow$ team sub-tab. ?ym=YYYY-MM $\rightarrow$ month context.

P7 View/Data Separation ? api_handlers.php (SQL/JSON) $\rightarrow$ api.php (Router) $\rightarrow$ Client $\rightarrow$ app.js (Render). views.php is an empty shell.

P8 Visual Rules Editor Sync ? Two-way JS sync (syncTextToVisual / syncVisualToText) on #rules-textarea. The JSON in the textarea is the single source of truth.

P9 Centralized Auth ? Use variables set in index.php. Never re-read $_SESSION in downstream files.

P10 CSRF on All POSTs ? Every POST to ?api= must include X-CSRF-Token header. Validated in api.php.

P11 Handler Testability ? api_*() functions in api_handlers.php take explicit parameters (PDO, data, uid) and return [int $code, array $body]. No globals inside handlers. Exception: $cfg is a read-only boot constant loaded once in database.php (line 64), never mutated by handlers. Three handlers use global $cfg: api_tasks_print, api_details_get, plugin_config GET. Tests set $cfg in setup before calling these handlers.

P12 Surgical DOM & State Updates ? saveTaskUI() updates specific DOM nodes and mutates JS state (teamData/rulesData) via Object.assign(). Avoid heavy DOM thrashing.

P13 ETag Caching ? api.php uses DB/WAL file stats for 304 Not Modified responses on GET.

P14 Lazy Loading ? Use IntersectionObserver to fill data-lazy="1" shells (month tasks, user cards, detail cards).

P15 Plugin Contract ? Plugins return ['id'=>..., 'routes'=>..., 'views'=>..., 'nav'=>..., 'schema'=>..., 'schema_version'=>...]. Handlers follow P11: (PDO,$d,$uid,$is_admin,$dc,$method) ? [code,body]. Core guards plugin functions with function_exists().

PLUGINS

plugins/            drop-in directory, scanned by src/plugins.php via glob()
  debug.php         debug_log + timer_log + app_log (removable)
  config.php        config CRUD + archive_year (removable)
  *.js              auto-included after app.js
  *.css             auto-included after style.css

Plugin PHP file returns array: id (required), routes, views, nav, admin_only, schema, schema_version, etag_routes, write_routes. Schema versions tracked in config table as plugin_schema_{id}. compile.php inlines plugin files into single-file output ? no plugins/ dir needed in production.

RULE FORMAT

[{"title":"Cleaning","days":"ER","weeks":"1234","start":"08:00","end":"16:00"}]

days: 1-7 or ETKN RLP. weeks: 1-4 (ISO full-weeks in month).

COMPILE

compile.php merges src/ + plugins/ $\rightarrow$ index_release.php. Uses tokenizer-safe line splitting. Plugin PHP inlined after plugins.php marker, JS appended, CSS injected before </style>.

STYLE

Tabs only. CSS 4-step spacing (--sp-1..4) + single --radius. JS uses compiled string templates. No inline styles/colors.

PROHIBIT

  • External dependencies or build tools
  • Changing `UNIQUE(user_id,task_date,title)`
  • Plain `INSERT` in rule engine (must be `INSERT OR IGNORE`)
  • Forgetting `PRAGMA foreign_keys=ON`
  • HTML in API handlers (must `json_exit+exit`)
  • SQL/$pdo in `view_*()` functions (must be HTML shell only)
  • `<script>const X = <?= json_encode(...) ?></script>` (data via API)
  • String concat in SQL (must use prepared stmts)
  • Exposing `$e->getMessage()` to client
  • Re-declaring auth variables outside `index.php`
  • POST requests without CSRF token validation
  • Passing prepared statements as function parameters
  • `return;` at file scope in any `src/*.php` file
  • Editing `index_release.php` (edit `src/`, run `compile.php`)
  • Handler logic in `api.php`
  • Schema or seed logic outside `database.php`
  • Date calculations in `views.php`
  • Inline styles or hardcoded px/rem spacing/colors

STATE v3.2.0

Working: auth, CSRF, login rate limiting, input validation, ETag caching, Surgical DOM updates, lazy loading, compiled string templates, rule engine (ISO full-week), multi-month navigation, admin/user CRUD, config/location mgmt, print/CSV, i18n, compile, performance instrumentation, plugin system (routes/views/nav/schema), audit plugin (checklists, access control, report). High concurrency (WAL). REST API active. All handlers testable. No inline styles.

ROLE

You modify this codebase. Follow constraints above. Read src/ files before editing. Use str_replace, not full rewrites.

The best code is the code never written. Before writing any code: Does this need to be built at all? (YAGNI) Does it already exist in this codebase? Reuse the helper, util, or pattern that's already here, don't re-write it. Does the standard library already do this? Use it. Does a native platform feature cover it? Use it. Can this be one line? Make it one line. Only then: write the minimum code that works.

No abstractions that weren't explicitly requested. No new dependency if it can be avoided. No boilerplate nobody asked for. Lazy means less code, not the flimsier algorithm. Not lazy about: understanding the problem. Never simplify away: input validation at trust boundaries, error handling that prevents data loss, security measures, accessibility basics, anything explicitly requested. User insists on the full version ? build it, no re-arguing. Trace the whole thing first ? every file the change touches, the actual flow. Code first, code without its check is unfinished. Trivial one-liners need no test, YAGNI applies to tests too.

Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer. Ask the questions one at a time. If a question can be answered by exploring the codebase, explore the codebase instead. Ultra-compressed communication mode. Cuts token usage ~75% by dropping filler, articles, and pleasantries while keeping full technical accuracy. All technical substance stay. Drop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging. Fragments OK. Short synonyms (big not extensive, fix not "implement a solution for"). Abbreviate common terms (DB/auth/config/req/res/fn/impl). Strip conjunctions. Use arrows for causality (X -> Y). One word when one word enough. Technical terms stay exact. Code blocks unchanged. Errors quoted exact. Pattern: [thing] [action] [reason]. [next step].

CHANGELOG FORMAT

<!-- FORMAT: ## vX.Y.Z ? Short Title, then ### Category heading, then prose or - bullet items. Newest version first. -->

SESSION END

Compact the current conversation into a handoff document for another agent to pick up. What will the next session be used for? When asked for a session summary, produce draft CHANGELOG entry in the project's format

Session: YYYY-MM-DD
Version: vX.Y.Z ? vX.Y.Z (if changed)
Changed: one-line description
Files: list of modified files
Details:
- what changed and why, one bullet per logical change
Docs to update: which docs need edits (CHANGELOG, Spec, TESTING, README)