commit ff90e0eb2918fb122f2297a2435ca04bab0dcd6b Author: mahdahar <89adham@gmail.com> Date: Wed Jan 14 16:49:27 2026 +0700 Initial commit: Add CodeIgniter 4 QC application with full MVC structure - CodeIgniter 4 framework setup with SQL Server database config - Models: Control, Test, Dept, Result, Daily/ Monthly entry models - Controllers: Dashboard, Control, Test, Dept, Entry, Report, API endpoints - Views: CRUD pages with modal dialogs, dashboard, reports - Database: Migrations for control test and daily/monthly result tables - Legacy v1 PHP application preserved in /v1 directory - Documentation: AGENTS.md, VIEWS_RULES.md for development guidelines diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..87e86b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,126 @@ +#------------------------- +# Operating Specific Junk Files +#------------------------- + +# OS X +.DS_Store +.AppleDouble +.LSOverride + +# OS X Thumbnails +._* + +# Windows image file caches +Thumbs.db +ehthumbs.db +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Linux +*~ + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +#------------------------- +# Environment Files +#------------------------- +# These should never be under version control, +# as it poses a security risk. +.env +.vagrant +Vagrantfile + +#------------------------- +# Temporary Files +#------------------------- +writable/cache/* +!writable/cache/index.html + +writable/logs/* +!writable/logs/index.html + +writable/session/* +!writable/session/index.html + +writable/uploads/* +!writable/uploads/index.html + +writable/debugbar/* +!writable/debugbar/index.html + +php_errors.log + +#------------------------- +# User Guide Temp Files +#------------------------- +user_guide_src/build/* +user_guide_src/cilexer/build/* +user_guide_src/cilexer/dist/* +user_guide_src/cilexer/pycilexer.egg-info/* + +#------------------------- +# Test Files +#------------------------- +tests/coverage* + +# Don't save phpunit under version control. +phpunit + +#------------------------- +# Composer +#------------------------- +vendor/ + +#------------------------- +# IDE / Development Files +#------------------------- + +# Modules Testing +_modules/* + +# phpenv local config +.php-version + +# Jetbrains editors (PHPStorm, etc) +.idea/ +*.iml + +# NetBeans +/nbproject/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/nbactions.xml +/nb-configuration.xml +/.nb-gradle/ + +# Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache +*.sublime-workspace +*.sublime-project +.phpintel +/api/ + +# Visual Studio Code +.vscode/ + +/results/ +/phpunit*.xml diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ca17ce0 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,340 @@ +# AGENTS.md - QC Application Development Guide + +This document provides guidelines for agentic coding agents working on this PHP QC (Quality Control) application built with CodeIgniter 4. + +## Project Overview + +This is a CodeIgniter 4 PHP application using SQL Server database for quality control data management. The app handles control tests, daily/monthly entries, and reporting. Uses Tailwind CSS and Alpine.js for UI. + +## Build/Lint/Test Commands + +```bash +# PHP syntax check single file +php -l app/Controllers/Dashboard.php + +# PHP syntax check all files recursively +find . -name "*.php" -exec php -l {} \; 2>&1 | grep -v "No syntax errors" + +# Run all PHPUnit tests +./vendor/bin/phpunit + +# Run single test class +./vendor/bin/phpunit tests/unit/HealthTest.php + +# Run single test method +./vendor/bin/phpunit tests/unit/HealthTest.php --filter=testIsDefinedAppPath + +# Run with coverage report +./vendor/bin/phpunit --coverage-html coverage/ + +# Start development server +php spark serve +``` + +## Code Style Guidelines + +### General Principles + +- Follow CodeIgniter 4 MVC patterns +- Maintain consistency with surrounding code +- Keep files focused (<200 lines preferred) +- Use clear, descriptive names + +### PHP Style + +- Use `dictTestModel = new DictTestModel(); + } + + public function index(): string + { + $data = [ + 'title' => 'Test Dictionary', + 'tests' => $this->dictTestModel->findAll(), + ]; + + return view('layout', [ + 'content' => view('test/index', $data), + 'page_title' => 'Test Dictionary', + 'active_menu' => 'test' + ]); + } +} +``` + +**Models** extend `CodeIgniter\Model`: +```php +namespace App\Models; + +use CodeIgniter\Model; + +class TestModel extends Model +{ + protected $table = 'dict_test'; + protected $primaryKey = 'id'; + protected $returnType = 'array'; + protected $useSoftDeletes = false; + protected $allowedFields = ['deptid', 'name', 'unit', 'method']; +} +``` + +**Views** use PHP short tags `` for output: +```php +
+

+ +
+ +
+``` + +### Database Operations + +- Configure connections in `app/Config/Database.php` +- Use CodeIgniter's Query Builder for queries +- Use parameterized queries to prevent SQL injection: + ```php + $builder = $this->db->table('results'); + $builder->select('*'); + $builder->where('control_ref_id', $controlId); + $results = $builder->get()->getResultArray(); + ``` +- For SQL Server, set `DBDriver` to `'SQLSRV'` in config + +### Error Handling + +- Use CodeIgniter's exception handling: `throw new \CodeIgniter\Exceptions\PageNotFoundException('Not found')` +- Return JSON responses for AJAX endpoints: + ```php + return $this->response->setJSON(['success' => true, 'data' => $results]); + ``` +- Use `log_message('error', $message)` for logging +- Validate input with `$this->validate()` in controllers + +### Frontend (Tailwind CSS + Alpine.js) + +The layout already includes Tailwind via CDN and Alpine.js: +```html + + +``` + +**Common JavaScript (`public/js/app.js`):** +- Contains global `App` object with shared utilities +- Handles sidebar toggle functionality +- Provides `App.showToast()`, `App.confirmSave()`, `App.closeAllModals()` +- Initialize with `App.init()` on DOMContentLoaded + +**Page-Specific Alpine.js:** +- Complex Alpine.js components should be defined inline in the view PHP file +- Use `x-data` with an object containing all properties and methods +- Example: + ```html +
+ +
+ ``` + +### File Organization + +- Controllers: `app/Controllers/` +- Models: `app/Models/` +- Views: `app/Views/` (subfolders for modules: `entry/`, `test/`, `control/`, `report/`, `dept/`) +- Config: `app/Config/` +- Routes: `app/Config/Routes.php` + +### Modal-based CRUD Pattern + +All CRUD operations use a single modal dialog file (`dialog.php`) that handles both add and edit modes. + +**File Naming:** +- Single dialog: `dialog.php` (no `_add` or `_edit` suffix) + +**Controller Pattern:** +```php +class Dept extends BaseController +{ + protected $dictDeptModel; + + public function __construct() + { + $this->dictDeptModel = new DictDeptModel(); + } + + public function index(): string + { + $data = [ + 'title' => 'Department Dictionary', + 'depts' => $this->dictDeptModel->findAll(), + ]; + + return view('layout', [ + 'content' => view('dept/index', $data), + 'page_title' => 'Department Dictionary', + 'active_menu' => 'dept' + ]); + } + + public function save(): \CodeIgniter\HTTP\RedirectResponse + { + $data = ['name' => $this->request->getPost('name')]; + $this->dictDeptModel->insert($data); + return redirect()->to('/dept'); + } + + public function update($id): \CodeIgniter\HTTP\RedirectResponse + { + $data = ['name' => $this->request->getPost('name')]; + $this->dictDeptModel->update($id, $data); + return redirect()->to('/dept'); + } + + public function delete($id): \CodeIgniter\HTTP\RedirectResponse + { + $this->dictDeptModel->delete($id); + return redirect()->to('/dept'); + } +} +``` + +**Dialog View Pattern (`dialog.php`):** +```php + + +
+ + + + + +
+``` + +**Index View Pattern (`index.php`):** +```php +
+ + + + + + + + + + +
+ + +
+
+ + + + + +``` + +**Searchable Multi-Select:** +- Use Select2 for searchable dropdowns (already included in layout.php) +- Initialize with: `$('#selectId').select2({ placeholder: 'Search...', allowClear: true })` + +### Security Considerations + +- Use CodeIgniter's built-in CSRF protection (`$this->validate('csrf')`) +- Escape all output in views with `` (auto-escaped) +- Use `$this->request->getPost()` instead of `$_POST` +- Never commit `.env` files with credentials + +## Common Operations + +**Add a new CRUD resource:** +1. Create model in `app/Models/` +2. Create controller in `app/Controllers/` +3. Add routes in `app/Config/Routes.php` +4. Create views in `app/Views/[module]/` + +**Add a menu item:** +- Add to sidebar in `app/Views/layout.php` +- Add route in `app/Config/Routes.php` +- Create controller method +- Set `active_menu` parameter in view() call diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..24728f6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014-2019 British Columbia Institute of Technology +Copyright (c) 2019-present CodeIgniter Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d14b4c9 --- /dev/null +++ b/README.md @@ -0,0 +1,68 @@ +# CodeIgniter 4 Application Starter + +## What is CodeIgniter? + +CodeIgniter is a PHP full-stack web framework that is light, fast, flexible and secure. +More information can be found at the [official site](https://codeigniter.com). + +This repository holds a composer-installable app starter. +It has been built from the +[development repository](https://github.com/codeigniter4/CodeIgniter4). + +More information about the plans for version 4 can be found in [CodeIgniter 4](https://forum.codeigniter.com/forumdisplay.php?fid=28) on the forums. + +You can read the [user guide](https://codeigniter.com/user_guide/) +corresponding to the latest version of the framework. + +## Installation & updates + +`composer create-project codeigniter4/appstarter` then `composer update` whenever +there is a new release of the framework. + +When updating, check the release notes to see if there are any changes you might need to apply +to your `app` folder. The affected files can be copied or merged from +`vendor/codeigniter4/framework/app`. + +## Setup + +Copy `env` to `.env` and tailor for your app, specifically the baseURL +and any database settings. + +## Important Change with index.php + +`index.php` is no longer in the root of the project! It has been moved inside the *public* folder, +for better security and separation of components. + +This means that you should configure your web server to "point" to your project's *public* folder, and +not to the project root. A better practice would be to configure a virtual host to point there. A poor practice would be to point your web server to the project root and expect to enter *public/...*, as the rest of your logic and the +framework are exposed. + +**Please** read the user guide for a better explanation of how CI4 works! + +## Repository Management + +We use GitHub issues, in our main repository, to track **BUGS** and to track approved **DEVELOPMENT** work packages. +We use our [forum](http://forum.codeigniter.com) to provide SUPPORT and to discuss +FEATURE REQUESTS. + +This repository is a "distribution" one, built by our release preparation script. +Problems with it can be raised on our forum, or as issues in the main repository. + +## Server Requirements + +PHP version 8.1 or higher is required, with the following extensions installed: + +- [intl](http://php.net/manual/en/intl.requirements.php) +- [mbstring](http://php.net/manual/en/mbstring.installation.php) + +> [!WARNING] +> - The end of life date for PHP 7.4 was November 28, 2022. +> - The end of life date for PHP 8.0 was November 26, 2023. +> - If you are still using PHP 7.4 or 8.0, you should upgrade immediately. +> - The end of life date for PHP 8.1 will be December 31, 2025. + +Additionally, make sure that the following extensions are enabled in your PHP: + +- json (enabled by default - don't turn it off) +- [mysqlnd](http://php.net/manual/en/mysqlnd.install.php) if you plan to use MySQL +- [libcurl](http://php.net/manual/en/curl.requirements.php) if you plan to use the HTTP\CURLRequest library diff --git a/VIEWS_RULES.md b/VIEWS_RULES.md new file mode 100644 index 0000000..36d8feb --- /dev/null +++ b/VIEWS_RULES.md @@ -0,0 +1,531 @@ +# TinyLab View Rules + +This document defines the view patterns and conventions used in TinyLab. Follow these rules when creating new views or modifying existing ones. + +## 1. Directory Structure + +``` +app/Views/ +├── layout/ +│ ├── main_layout.php # Primary app layout (sidebar, navbar, dark mode) +│ └── form_layout.php # Lightweight layout for standalone forms +├── [module_name]/ # Feature module (e.g., patients, requests) +│ ├── index.php # Main list page +│ ├── dialog_form.php # Modal form (Create/Edit) +│ └── drawer_filter.php # Filter drawer (optional) +├── master/ +│ └── [entity]/ # Master data entity (e.g., doctors, samples) +│ ├── index.php +│ └── dialog_form.php +└── errors/ + └── html/ + ├── error_404.php + └── error_exception.php +``` + +## 2. Layout Extension + +All pages must extend the appropriate layout: + +```php +extend("layout/main_layout"); ?> +section("content") ?> + +endSection(); ?> +section("script") ?> + +endSection(); ?> +``` + +Use `form_layout.php` for standalone pages like login: +```php +extend("layout/form_layout"); ?> +``` + +## 3. Alpine.js Integration + +### 3.1 Component Definition + +Always use `alpine:init` event listener: + +```php +section("script") ?> + +endSection(); ?> +``` + +### 3.2 Alpine Data Attribute + +Wrap page content in the component: + +```php +
+ +
+``` + +## 4. Modal/Dialog Pattern + +### 4.1 Standard Modal Structure + +```php + +
+
+ + +
+
+ +
+

+ +
+ + +
+
+ +
+
+ + +

+
+
+
+ + +
+ + +
+
+
+
+``` + +## 5. Page Structure Pattern + +### 5.1 Standard CRUD Page + +```php +extend("layout/main_layout"); ?> +section("content") ?> +
+ +
+
+

Module Title

+

Module description

+
+ +
+ + +
+
+
+ + +
+ +
+
+ + +
+
+ + +
+
+ + +
+ + + + + + + + +
+ + + include('module/dialog_form'); ?> +
+endSection(); ?> +``` + +### 5.2 Master-Detail Pattern + +```php + +
+ +
+
+ +
+
+ +
+
+ + +
+ + +
+
+``` + +## 6. Form Field Patterns + +### 6.1 Input with Icon +```php +
+ + +
+``` + +### 6.2 Select Dropdown +```php + +``` + +### 6.3 Checkbox +```php + +``` + +### 6.4 Radio Group +```php +
+ +
+``` + +## 7. Status Badges + +```php + + +``` + +## 8. CSS Classes Reference + +### Layout +- `flex`, `flex-col`, `grid`, `grid-cols-2`, `gap-4` +- `w-full`, `max-w-2xl`, `min-h-0` +- `overflow-hidden`, `overflow-y-auto` + +### Spacing +- `p-4`, `px-6`, `py-3`, `m-4`, `mb-6` +- `space-x-4`, `gap-3` + +### Typography +- `text-sm`, `text-xs`, `text-lg`, `text-2xl` +- `font-medium`, `font-semibold`, `font-bold` +- `text-slate-500`, `text-slate-800` + +### Borders & Backgrounds +- `bg-white`, `bg-slate-50`, `bg-blue-50` +- `border`, `border-slate-100`, `border-red-300` +- `rounded-lg`, `rounded-xl`, `rounded-2xl` + +### Components +- `btn btn-primary`, `btn btn-ghost` +- `checkbox checkbox-sm` +- `radio radio-primary` +- `input`, `select`, `textarea` + +### Icons +FontAwesome 7 via CDN: `` + +## 9. API Response Format + +Views expect API responses in this format: + +```json +{ + "status": "success", + "message": "Operation successful", + "data": [...] +} +``` + +## 10. Validation Pattern + +```javascript +validate() { + this.errors = {}; + + if (!this.form.field1) { + this.errors.field1 = 'Field 1 is required'; + } + if (!this.form.field2) { + this.errors.field2 = 'Field 2 is required'; + } + if (this.form.field3 && !/^\d+$/.test(this.form.field3)) { + this.errors.field3 = 'Must be numeric'; + } + + return Object.keys(this.errors).length === 0; +} +``` + +## 11. Error Handling + +```javascript +async save() { + this.loading = true; + try { + const res = await fetch(url, { ... }); + const data = await res.json(); + if (data.status === 'success') { + this.showToast('Saved successfully'); + this.fetchList(); + } else { + this.error = data.message || 'An error occurred'; + } + } catch (err) { + this.error = 'Network error. Please try again.'; + console.error(err); + } finally { + this.loading = false; + } +} +``` + +## 12. Quick Reference: File Templates + +### Standard List Page Template +See: `app/Views/master/doctors/doctors_index.php` + +### Modal Form Template +See: `app/Views/master/doctors/dialog_doctors_form.php` + +### Master-Detail Page Template +See: `app/Views/patients/patients_index.php` + +### Result Entry Table Template +See: `app/Views/requests/dialog_result_entry.php` + +## 13. Checklist for New Views + +- [ ] Create view file in correct directory +- [ ] Extend appropriate layout (`main_layout` or `form_layout`) +- [ ] Define `content` and `script` sections +- [ ] Wrap content in `x-data` component +- [ ] Include modal form if needed +- [ ] Use DaisyUI components for buttons, inputs, selects +- [ ] Add loading and empty states +- [ ] Implement proper error handling +- [ ] Use FontAwesome icons consistently +- [ ] Follow naming conventions (snake_case for PHP, camelCase for JS) + +## 14. Conventions Summary + +| Aspect | Convention | +|--------|------------| +| File naming | snake_case (e.g., `patients_index.php`) | +| PHP variables | snake_case | +| JavaScript variables | camelCase | +| HTML classes | kebab-case (Tailwind) | +| Icons | FontAwesome 7 | +| UI Framework | TailwindCSS + DaisyUI | +| State management | Alpine.js | +| API format | JSON with `status`, `message`, `data` | +| Primary key | `{table}_id` (e.g., `pat_id`) | +| Soft deletes | All tables use `deleted_at` | diff --git a/app/.htaccess b/app/.htaccess new file mode 100644 index 0000000..3462048 --- /dev/null +++ b/app/.htaccess @@ -0,0 +1,6 @@ + + Require all denied + + + Deny from all + diff --git a/app/Common.php b/app/Common.php new file mode 100644 index 0000000..95f5544 --- /dev/null +++ b/app/Common.php @@ -0,0 +1,15 @@ + + */ + public array $allowedHostnames = []; + + /** + * -------------------------------------------------------------------------- + * Index File + * -------------------------------------------------------------------------- + * + * Typically, this will be your `index.php` file, unless you've renamed it to + * something else. If you have configured your web server to remove this file + * from your site URIs, set this variable to an empty string. + */ + public string $indexPage = 'index.php'; + + /** + * -------------------------------------------------------------------------- + * URI PROTOCOL + * -------------------------------------------------------------------------- + * + * This item determines which server global should be used to retrieve the + * URI string. The default setting of 'REQUEST_URI' works for most servers. + * If your links do not seem to work, try one of the other delicious flavors: + * + * 'REQUEST_URI': Uses $_SERVER['REQUEST_URI'] + * 'QUERY_STRING': Uses $_SERVER['QUERY_STRING'] + * 'PATH_INFO': Uses $_SERVER['PATH_INFO'] + * + * WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded! + */ + public string $uriProtocol = 'REQUEST_URI'; + + /* + |-------------------------------------------------------------------------- + | Allowed URL Characters + |-------------------------------------------------------------------------- + | + | This lets you specify which characters are permitted within your URLs. + | When someone tries to submit a URL with disallowed characters they will + | get a warning message. + | + | As a security measure you are STRONGLY encouraged to restrict URLs to + | as few characters as possible. + | + | By default, only these are allowed: `a-z 0-9~%.:_-` + | + | Set an empty string to allow all characters -- but only if you are insane. + | + | The configured value is actually a regular expression character group + | and it will be used as: '/\A[]+\z/iu' + | + | DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! + | + */ + public string $permittedURIChars = 'a-z 0-9~%.:_\-'; + + /** + * -------------------------------------------------------------------------- + * Default Locale + * -------------------------------------------------------------------------- + * + * The Locale roughly represents the language and location that your visitor + * is viewing the site from. It affects the language strings and other + * strings (like currency markers, numbers, etc), that your program + * should run under for this request. + */ + public string $defaultLocale = 'en'; + + /** + * -------------------------------------------------------------------------- + * Negotiate Locale + * -------------------------------------------------------------------------- + * + * If true, the current Request object will automatically determine the + * language to use based on the value of the Accept-Language header. + * + * If false, no automatic detection will be performed. + */ + public bool $negotiateLocale = false; + + /** + * -------------------------------------------------------------------------- + * Supported Locales + * -------------------------------------------------------------------------- + * + * If $negotiateLocale is true, this array lists the locales supported + * by the application in descending order of priority. If no match is + * found, the first locale will be used. + * + * IncomingRequest::setLocale() also uses this list. + * + * @var list + */ + public array $supportedLocales = ['en']; + + /** + * -------------------------------------------------------------------------- + * Application Timezone + * -------------------------------------------------------------------------- + * + * The default timezone that will be used in your application to display + * dates with the date helper, and can be retrieved through app_timezone() + * + * @see https://www.php.net/manual/en/timezones.php for list of timezones + * supported by PHP. + */ + public string $appTimezone = 'UTC'; + + /** + * -------------------------------------------------------------------------- + * Default Character Set + * -------------------------------------------------------------------------- + * + * This determines which character set is used by default in various methods + * that require a character set to be provided. + * + * @see http://php.net/htmlspecialchars for a list of supported charsets. + */ + public string $charset = 'UTF-8'; + + /** + * -------------------------------------------------------------------------- + * Force Global Secure Requests + * -------------------------------------------------------------------------- + * + * If true, this will force every request made to this application to be + * made via a secure connection (HTTPS). If the incoming request is not + * secure, the user will be redirected to a secure version of the page + * and the HTTP Strict Transport Security (HSTS) header will be set. + */ + public bool $forceGlobalSecureRequests = false; + + /** + * -------------------------------------------------------------------------- + * Reverse Proxy IPs + * -------------------------------------------------------------------------- + * + * If your server is behind a reverse proxy, you must whitelist the proxy + * IP addresses from which CodeIgniter should trust headers such as + * X-Forwarded-For or Client-IP in order to properly identify + * the visitor's IP address. + * + * You need to set a proxy IP address or IP address with subnets and + * the HTTP header for the client IP address. + * + * Here are some examples: + * [ + * '10.0.1.200' => 'X-Forwarded-For', + * '192.168.5.0/24' => 'X-Real-IP', + * ] + * + * @var array + */ + public array $proxyIPs = []; + + /** + * -------------------------------------------------------------------------- + * Content Security Policy + * -------------------------------------------------------------------------- + * + * Enables the Response's Content Secure Policy to restrict the sources that + * can be used for images, scripts, CSS files, audio, video, etc. If enabled, + * the Response object will populate default values for the policy from the + * `ContentSecurityPolicy.php` file. Controllers can always add to those + * restrictions at run time. + * + * For a better understanding of CSP, see these documents: + * + * @see http://www.html5rocks.com/en/tutorials/security/content-security-policy/ + * @see http://www.w3.org/TR/CSP/ + */ + public bool $CSPEnabled = false; +} diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php new file mode 100644 index 0000000..9a92824 --- /dev/null +++ b/app/Config/Autoload.php @@ -0,0 +1,92 @@ +|string> + */ + public $psr4 = [ + APP_NAMESPACE => APPPATH, + ]; + + /** + * ------------------------------------------------------------------- + * Class Map + * ------------------------------------------------------------------- + * The class map provides a map of class names and their exact + * location on the drive. Classes loaded in this manner will have + * slightly faster performance because they will not have to be + * searched for within one or more directories as they would if they + * were being autoloaded through a namespace. + * + * Prototype: + * $classmap = [ + * 'MyClass' => '/path/to/class/file.php' + * ]; + * + * @var array + */ + public $classmap = []; + + /** + * ------------------------------------------------------------------- + * Files + * ------------------------------------------------------------------- + * The files array provides a list of paths to __non-class__ files + * that will be autoloaded. This can be useful for bootstrap operations + * or for loading functions. + * + * Prototype: + * $files = [ + * '/path/to/my/file.php', + * ]; + * + * @var list + */ + public $files = []; + + /** + * ------------------------------------------------------------------- + * Helpers + * ------------------------------------------------------------------- + * Prototype: + * $helpers = [ + * 'form', + * ]; + * + * @var list + */ + public $helpers = []; +} diff --git a/app/Config/Boot/development.php b/app/Config/Boot/development.php new file mode 100644 index 0000000..a868447 --- /dev/null +++ b/app/Config/Boot/development.php @@ -0,0 +1,34 @@ + WRITEPATH . 'cache/', + 'mode' => 0640, + ]; + + /** + * ------------------------------------------------------------------------- + * Memcached settings + * ------------------------------------------------------------------------- + * + * Your Memcached servers can be specified below, if you are using + * the Memcached drivers. + * + * @see https://codeigniter.com/user_guide/libraries/caching.html#memcached + * + * @var array{host?: string, port?: int, weight?: int, raw?: bool} + */ + public array $memcached = [ + 'host' => '127.0.0.1', + 'port' => 11211, + 'weight' => 1, + 'raw' => false, + ]; + + /** + * ------------------------------------------------------------------------- + * Redis settings + * ------------------------------------------------------------------------- + * + * Your Redis server can be specified below, if you are using + * the Redis or Predis drivers. + * + * @var array{host?: string, password?: string|null, port?: int, timeout?: int, database?: int} + */ + public array $redis = [ + 'host' => '127.0.0.1', + 'password' => null, + 'port' => 6379, + 'timeout' => 0, + 'database' => 0, + ]; + + /** + * -------------------------------------------------------------------------- + * Available Cache Handlers + * -------------------------------------------------------------------------- + * + * This is an array of cache engine alias' and class names. Only engines + * that are listed here are allowed to be used. + * + * @var array> + */ + public array $validHandlers = [ + 'dummy' => DummyHandler::class, + 'file' => FileHandler::class, + 'memcached' => MemcachedHandler::class, + 'predis' => PredisHandler::class, + 'redis' => RedisHandler::class, + 'wincache' => WincacheHandler::class, + ]; + + /** + * -------------------------------------------------------------------------- + * Web Page Caching: Cache Include Query String + * -------------------------------------------------------------------------- + * + * Whether to take the URL query string into consideration when generating + * output cache files. Valid options are: + * + * false = Disabled + * true = Enabled, take all query parameters into account. + * Please be aware that this may result in numerous cache + * files generated for the same page over and over again. + * ['q'] = Enabled, but only take into account the specified list + * of query parameters. + * + * @var bool|list + */ + public $cacheQueryString = false; +} diff --git a/app/Config/Constants.php b/app/Config/Constants.php new file mode 100644 index 0000000..fb56bb1 --- /dev/null +++ b/app/Config/Constants.php @@ -0,0 +1,79 @@ +|string|null + */ + public $defaultSrc; + + /** + * Lists allowed scripts' URLs. + * + * @var list|string + */ + public $scriptSrc = 'self'; + + /** + * Lists allowed stylesheets' URLs. + * + * @var list|string + */ + public $styleSrc = 'self'; + + /** + * Defines the origins from which images can be loaded. + * + * @var list|string + */ + public $imageSrc = 'self'; + + /** + * Restricts the URLs that can appear in a page's `` element. + * + * Will default to self if not overridden + * + * @var list|string|null + */ + public $baseURI; + + /** + * Lists the URLs for workers and embedded frame contents + * + * @var list|string + */ + public $childSrc = 'self'; + + /** + * Limits the origins that you can connect to (via XHR, + * WebSockets, and EventSource). + * + * @var list|string + */ + public $connectSrc = 'self'; + + /** + * Specifies the origins that can serve web fonts. + * + * @var list|string + */ + public $fontSrc; + + /** + * Lists valid endpoints for submission from `
` tags. + * + * @var list|string + */ + public $formAction = 'self'; + + /** + * Specifies the sources that can embed the current page. + * This directive applies to ``, `