352 lines
15 KiB
Markdown
352 lines
15 KiB
Markdown
# Architecture & Structure
|
|
|
|
**Analysis Date:** 2026-04-30
|
|
|
|
---
|
|
|
|
## Directory Layout
|
|
|
|
```
|
|
centrumcopy.com.pl/ # Docroot / front controller
|
|
├── index.php # Front controller (entry point)
|
|
├── robots.txt
|
|
├── application/ # Application code (APPPATH)
|
|
│ ├── cache/ # Kohana internal cache (file-based)
|
|
│ ├── config/ # All configuration files
|
|
│ ├── controllers/ # MVC Controllers
|
|
│ │ ├── base_admin.php # Abstract base for admin controllers
|
|
│ │ ├── base_front.php # Abstract base for front controllers
|
|
│ │ ├── install.php # Installation controller
|
|
│ │ ├── admin/ # Admin panel controllers
|
|
│ │ └── front/ # Public-facing controllers
|
|
│ ├── helpers/ # (empty — helpers live in libraries/drivers)
|
|
│ ├── i18n/pl_PL/ # Polish locale strings
|
|
│ ├── libraries/ # Extended/custom libraries
|
|
│ │ └── drivers/ # Driver extensions
|
|
│ ├── logs/ # Error/application logs
|
|
│ ├── models/ # ORM models
|
|
│ └── views/ # PHP view templates
|
|
│ ├── admin/ # Admin panel partial views
|
|
│ ├── front/ # Public partial views
|
|
│ ├── gmaps/ # Google Maps JS view
|
|
│ ├── pagination/ # Pagination style templates
|
|
│ ├── admin_layout.php # Admin full-page layout
|
|
│ ├── admin_login.php # Admin login page
|
|
│ └── default_layout.php # Public full-page layout
|
|
├── modules/ # Kohana modules (MODPATH)
|
|
│ ├── gmaps/ # Google Maps integration module
|
|
│ └── debug_toolbar/ # Debug toolbar module
|
|
├── system/ # Kohana framework core (SYSPATH)
|
|
│ └── core/ # Bootstrap, Event, Kohana, Benchmark
|
|
├── css/ # Public stylesheets
|
|
├── js/ # Public JavaScript (jQuery, TinyMCE, etc.)
|
|
├── images/ # Public images
|
|
├── flash/ # Flash banner assets
|
|
├── uploads/ # User-uploaded files
|
|
└── stara/ # Legacy static HTML site (archived)
|
|
```
|
|
|
|
---
|
|
|
|
## MVC Structure
|
|
|
|
### Controllers
|
|
|
|
**Location:** `application/controllers/`
|
|
|
|
Controllers use Kohana 2.x naming: `{Name}_Controller` extends a base class. File name is lowercase, class name is `PascalCase_Controller`.
|
|
|
|
**Base classes (abstract):**
|
|
|
|
| File | Class | Extends | Role |
|
|
|------|-------|---------|------|
|
|
| `application/controllers/base_front.php` | `Base_Front_Controller` | `Controller` | Sets up front layout (`default_layout`), session, menu, SEO metadata |
|
|
| `application/controllers/base_admin.php` | `Base_Admin_Controller` | `Controller` | Sets up admin layout (`admin_layout`), enforces auth guard, manages flash messages |
|
|
|
|
**Front (public) controllers** — `application/controllers/front/`:
|
|
|
|
| File | Class | Handles |
|
|
|------|-------|---------|
|
|
| `front/page.php` | `Page_Controller` | Static CMS pages, homepage redirect, contact page with Google Maps |
|
|
| `front/welcome.php` | `Welcome_Controller` | (unused/fallback) |
|
|
|
|
**Admin controllers** — `application/controllers/admin/`:
|
|
|
|
| File | Class | Handles |
|
|
|------|-------|---------|
|
|
| `admin/page.php` | `Page_Controller` | Edit CMS page content via TinyMCE |
|
|
| `admin/user.php` | `User_Controller` | Login, logout, password change |
|
|
| `admin/welcome.php` | `Welcome_Controller` | Admin dashboard index |
|
|
|
|
Note: Both `front/page.php` and `admin/page.php` define `Page_Controller` — they are isolated by directory scoping during routing.
|
|
|
|
**Auth guard pattern in `Base_Admin_Controller`:**
|
|
```php
|
|
if (!$this->session->get('admin') && Router::$method != 'login' && Router::$method != 'logout') {
|
|
url::redirect('admin/login');
|
|
}
|
|
```
|
|
|
|
**`__call` magic method** is used in `Page_Controller` (front) to route any unknown URL segment to `show($name)`, enabling slug-based page lookup.
|
|
|
|
### Models
|
|
|
|
**Location:** `application/models/`
|
|
|
|
All models extend `ORM` (Kohana's ActiveRecord-style ORM). Model file name is lowercase; class name is `{Name}_Model`.
|
|
|
|
| File | Class | Table | Notes |
|
|
|------|-------|-------|-------|
|
|
| `models/page.php` | `Page_Model` | `page` | Singular table name; supports lookup by `name` slug |
|
|
| `models/user.php` | `User_Model` | `user` | Primary val = `username`; SHA1+salt password hashing |
|
|
| `models/news.php` | `News_Model` | `news` | Singular; sorted by `created_at DESC` |
|
|
| `models/gallery.php` | `Gallery_Model` | `gallery` | Has many `gallery_images`; sorted `created_at ASC` |
|
|
| `models/gallery_image.php` | `Gallery_Image_Model` | `gallery_image` | Belongs to `gallery`; sorted by `id ASC` |
|
|
|
|
**ORM lookup pattern:**
|
|
```php
|
|
ORM::factory('page')->where('name', $slug)->find();
|
|
if (!$page->loaded) { return $this->error404(); }
|
|
```
|
|
|
|
### Views
|
|
|
|
**Location:** `application/views/`
|
|
|
|
Views are plain PHP templates. Layout views are full HTML documents; partial views are HTML fragments assigned to `$content`.
|
|
|
|
**Layout views (full pages):**
|
|
|
|
| File | Used by |
|
|
|------|---------|
|
|
| `views/default_layout.php` | All front controllers via `Base_Front_Controller` |
|
|
| `views/admin_layout.php` | All admin controllers via `Base_Admin_Controller` |
|
|
| `views/admin_login.php` | `User_Controller::login()` |
|
|
|
|
**Partial views — front:** `views/front/`
|
|
|
|
| File | Rendered by |
|
|
|------|-------------|
|
|
| `front/page_show.php` | `Page_Controller::show()` |
|
|
| `front/page_contact.php` | `Page_Controller::contact()` |
|
|
| `front/error404.php` | `Base_Front_Controller::error404()` |
|
|
|
|
**Partial views — admin:** `views/admin/`
|
|
|
|
| File | Rendered by |
|
|
|------|-------------|
|
|
| `admin/page_edit.php` | `admin/Page_Controller::edit()` |
|
|
| `admin/password.php` | `User_Controller::password()` |
|
|
| `admin/welcome.php` | `admin/Welcome_Controller::index()` |
|
|
| `admin/error404.php` | `Base_Admin_Controller::error404()` |
|
|
|
|
**View rendering pattern:**
|
|
```php
|
|
$page_view = new View('front/page_show');
|
|
$page_view->page = $page; // assign data to partial
|
|
$this->view->content = $page_view; // embed partial in layout
|
|
$this->view->render(true); // output full layout
|
|
```
|
|
|
|
---
|
|
|
|
## Routing
|
|
|
|
**Config file:** `application/config/routes.php`
|
|
|
|
Kohana 2.x routing maps URL patterns (regex) to `directory/controller/method` targets. Routes are evaluated top-to-bottom; first match wins.
|
|
|
|
```php
|
|
$config['_default'] = 'front/page/homepage'; // / → Front\Page::homepage()
|
|
|
|
// Admin routes
|
|
$config['admin'] = 'admin/welcome/'; // /admin
|
|
$config['admin/login'] = 'admin/user/login'; // /admin/login
|
|
$config['admin/logout'] = 'admin/user/logout'; // /admin/logout
|
|
$config['admin/password'] = 'admin/user/password'; // /admin/password
|
|
$config['admin/page/(.*)'] = 'admin/page/edit/$1'; // /admin/page/{slug}
|
|
$config['admin/(.*)'] = 'admin/$1'; // /admin/...
|
|
|
|
// Front routes
|
|
$config['kontakt'] = 'front/page/contact'; // /kontakt
|
|
$config['galeria/?(.*)'] = 'front/gallery/$1'; // /galeria/...
|
|
$config['aktualnosci/?(.*)'] = 'front/news/$1'; // /aktualnosci/...
|
|
$config['(.+)'] = 'front/page/$1'; // /{any-slug} → Page::show()
|
|
```
|
|
|
|
**Slug routing:** The catch-all `(.+)` route passes the URL slug to `front/page/`. `Page_Controller::show($name)` then queries the database for a page with `name = $slug`. This means all CMS pages live in a flat namespace matched against the `page.name` column.
|
|
|
|
**URL rewriting:** `index_page` is commented out in `application/config/config.php`, meaning clean URLs (no `index.php` in path) require Apache `mod_rewrite` or equivalent.
|
|
|
|
---
|
|
|
|
## Module System
|
|
|
|
**Module path:** `modules/` (MODPATH)
|
|
|
|
Modules are configured in `application/config/config.php` under `$config['modules']`. Kohana merges module paths into the file search cascade (controllers, views, libraries, etc. from a module are auto-discoverable).
|
|
|
|
**Active modules:**
|
|
|
|
| Module | Path | Purpose |
|
|
|--------|------|---------|
|
|
| `gmaps` | `modules/gmaps/` | Google Maps v2 API wrapper — `Gmap` library, marker helpers, JS view |
|
|
|
|
**Available but disabled modules** (commented out in config):
|
|
- `auth`, `forge`, `kodoc`, `media`, `archive`, `payment`, `unit_test`, `object_db`
|
|
|
|
**`debug_toolbar` module** exists at `modules/debug_toolbar/` but is **not loaded** in config.
|
|
|
|
**Module internal structure** (gmaps example):
|
|
```
|
|
modules/gmaps/
|
|
├── config/ # Module config
|
|
├── controllers/ # Module controllers (if any)
|
|
├── i18n/
|
|
├── libraries/ # Gmap, Gmap_Marker libraries
|
|
├── models/
|
|
└── views/ # gmaps/javascript.php
|
|
```
|
|
|
|
**Custom application-level extensions** (not modules — override framework classes):
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `application/libraries/MY_Database.php` | Extends `Database_Core` — fixes `COUNT()` column escaping with table prefix |
|
|
| `application/libraries/MY_Gmap_Marker.php` | Extends Gmap marker from the gmaps module |
|
|
| `application/libraries/drivers/Database.php` | Custom database driver wrapper |
|
|
| `application/libraries/drivers/MY_form.php` | Extended form helper |
|
|
| `application/libraries/drivers/MY_html.php` | Extended html helper (adds `span_class()`, etc.) |
|
|
| `application/libraries/drivers/MY_valid.php` | Extended validation rules |
|
|
| `application/libraries/drivers/categories.php` | Category tree helper |
|
|
| `application/libraries/drivers/javascript.php` | JavaScript generation helper |
|
|
|
|
---
|
|
|
|
## Business Domains
|
|
|
|
This is a **B2B product catalogue + CMS** for a photocopier/office equipment distributor (Centrum Copy Rzeszów).
|
|
|
|
### CMS / Static Pages
|
|
- **Primary domain.** All content pages are rows in the `page` table, looked up by a URL `name` slug.
|
|
- Pages have: `title`, `header`, `content` (HTML via TinyMCE), `meta_description`, `meta_keywords`.
|
|
- Admin edits pages via WYSIWYG at `/admin/page/{slug}`.
|
|
- Menu structure is **hardcoded** in `application/config/application.php` under `$config['menu_nav']` — changing the menu requires a code deploy.
|
|
- Content domains visible in admin menu: O firmie, Powielacze cyfrowe RISO, Pełnokolorowe urządzenia Inkjet RISO ComColor, Urządzenia biurowe (kolorowe/monochromatyczne A4/A3), Plotery i skanery, Finansowanie, Serwis, Usługi, Kontakt, Szybki kontakt.
|
|
|
|
### Gallery
|
|
- Model: `Gallery_Model` (has_many `Gallery_Image_Model`)
|
|
- Route: `/galeria/...` → `front/gallery` controller
|
|
- Note: `application/controllers/front/gallery.php` does not exist as a file — gallery controller is **missing or not committed**.
|
|
|
|
### News / Aktualności
|
|
- Model: `News_Model`
|
|
- Route: `/aktualnosci/...` → `front/news` controller
|
|
- Note: `application/controllers/front/news.php` does not exist — news controller is **missing or not committed**.
|
|
|
|
### Contact Page
|
|
- Route `/kontakt` → `Page_Controller::contact()`
|
|
- Renders Google Maps v2 marker at configured lat/lon (`application/config/application.php` → `$config['gmaps']`).
|
|
- Google Maps centre: `50.0491231, 21.9869502` (Rzeszów, ul. Okulickiego 9).
|
|
|
|
### Admin Panel
|
|
- Session-based authentication. Credentials: SHA1(salt + password) stored in `user` table.
|
|
- Single-user admin — no roles enforced beyond session presence.
|
|
- Admin navigates to hardcoded page slugs from the sidebar in `admin_layout.php`.
|
|
- Features: edit page content, change admin password, logout.
|
|
|
|
---
|
|
|
|
## Request Lifecycle
|
|
|
|
```
|
|
Browser Request
|
|
|
|
|
v
|
|
index.php (front controller)
|
|
- defines DOCROOT, APPPATH, MODPATH, SYSPATH
|
|
- sets IN_PRODUCTION = false
|
|
- requires system/core/Bootstrap.php
|
|
|
|
|
v
|
|
system/core/Bootstrap.php
|
|
- loads Benchmark, utf8, Event, Kohana
|
|
- Kohana::setup() (loads config, modules, sets error handlers)
|
|
|
|
|
v
|
|
Event::run('system.ready') (hooks, if enabled — currently disabled)
|
|
|
|
|
v
|
|
Event::run('system.routing')
|
|
- Router matches URI against application/config/routes.php
|
|
- Determines: directory, controller, method, arguments
|
|
|
|
|
v
|
|
Event::run('system.execute')
|
|
- Instantiates controller: new {Name}_Controller()
|
|
- __construct() runs:
|
|
- parent::__construct() (Kohana base Controller)
|
|
- Base_Front/Admin_Controller::__construct()
|
|
- Creates View object for layout
|
|
- Starts Session
|
|
- Loads config (title, meta, menu_nav, etc.)
|
|
- [Admin only] Auth guard → redirect to login if not authed
|
|
- Calls controller method (e.g., show(), edit(), login())
|
|
- Method queries ORM models
|
|
- Creates partial View, assigns data
|
|
- Assigns partial to $this->view->content
|
|
- $this->view->render(true) → outputs full HTML
|
|
|
|
|
v
|
|
Event::run('system.shutdown') (cleanup)
|
|
|
|
|
v
|
|
Response sent to browser
|
|
```
|
|
|
|
**Session:** Native PHP sessions, 30-minute expiration, validated by `user_agent`. Session name: `Frisson_session`.
|
|
|
|
**Database:** MySQLi driver, single `default` connection, no table prefix, UTF-8 charset, query benchmarking enabled.
|
|
|
|
**Output compression:** gzip enabled (`$config['output_compression'] = TRUE`).
|
|
|
|
**Error handling:** Errors logged to `application/logs/` at threshold 1 (errors + exceptions). `display_errors` is off in production.
|
|
|
|
---
|
|
|
|
## Configuration Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `application/config/application.php` | Site title, email, Google Maps coords, navigation menu, Google Analytics |
|
|
| `application/config/config.php` | Kohana core settings: domain, modules list, cache, compression, hooks |
|
|
| `application/config/database.php` | MySQLi connection credentials |
|
|
| `application/config/routes.php` | URL routing rules |
|
|
| `application/config/session.php` | Session driver, name, expiration |
|
|
| `application/config/pagination.php` | Pagination defaults (5 items/page, segment 3) |
|
|
| `application/config/email.php` | Email settings |
|
|
| `application/config/cookie.php` | Cookie settings |
|
|
| `application/config/tiny_mce.php` | TinyMCE upload paths for admin editor |
|
|
| `application/config/upload.php` | File upload settings |
|
|
| `application/config/locale.php` | Locale/timezone |
|
|
| `application/config/gmaps.php` | Google Maps module config |
|
|
| `application/config/debug_toolbar.php` | Debug toolbar settings |
|
|
|
|
---
|
|
|
|
## Key Observations & Gaps
|
|
|
|
1. **Missing controllers:** `application/controllers/front/gallery.php` and `application/controllers/front/news.php` are referenced in routes but absent. Routes for `/galeria/` and `/aktualnosci/` will 404.
|
|
|
|
2. **Hardcoded navigation:** `$config['menu_nav']` in `application/config/application.php` defines the entire site menu statically. Adding/removing menu items requires editing this config file and redeploying.
|
|
|
|
3. **Admin menu also hardcoded:** `application/views/admin_layout.php` contains inline HTML listing every editable page slug. Must be manually updated to match `page` table contents.
|
|
|
|
4. **IN_PRODUCTION = false:** Set in `index.php`. Must be changed to `true` before deploying to live server to enable Google Analytics and suppress demo controllers.
|
|
|
|
5. **Kohana version:** 2.3.4 (codename "buteo regalis") — very old, unmaintained framework. No Composer, no autoloading beyond Kohana's own file cascade.
|
|
|
|
6. **Auth security:** `User_Controller::login()` contains `print_r($_POST)` debug statement (line 29). This leaks credentials in the HTTP response. Remove before any production use.
|
|
|
|
7. **No test runner configured.** No test files detected.
|