7 dokumentów w .paul/codebase/ — overview, stack, architecture, conventions, testing, integrations, concerns (CRITICAL→LOW). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
162 lines
5.0 KiB
Markdown
162 lines
5.0 KiB
Markdown
# Coding Conventions
|
|
|
|
> Generated: 2026-04-26
|
|
|
|
## File Naming
|
|
|
|
| Layer | Convention | Example |
|
|
|-------|-----------|---------|
|
|
| Legacy (admin/front) | `class.{ClassName}.php` | `class.Articles.php` |
|
|
| Domain repositories | `{ClassName}.php` (PSR-4) | `ArticlesRepository.php` |
|
|
| Shared services | `{ClassName}.php` (PSR-4) | `CacheHandler.php` |
|
|
| Templates | `{feature-name}.php` | `articles/list.php` |
|
|
|
|
## Naming Conventions
|
|
|
|
| Element | Legacy code | New Domain code |
|
|
|---------|------------|-----------------|
|
|
| Methods | `snake_case` | `camelCase` |
|
|
| Classes | `PascalCase` | `PascalCase` |
|
|
| Properties | `$camelCase` | `$camelCase` |
|
|
| Constants | `UPPER_CASE` | `UPPER_CASE` |
|
|
| Namespaces | lowercase (`admin\`, `front\`) | PascalCase (`Domain\`, `Shared\`) |
|
|
|
|
## Class Patterns
|
|
|
|
### Controls (request handlers) — static methods only
|
|
```php
|
|
namespace admin\controls;
|
|
class Articles {
|
|
public static function article_delete() {
|
|
global $user;
|
|
if (!admin\factory\Users::check_privileges('articles', $user['id']))
|
|
return \S::alert('Brak uprawnień');
|
|
admin\factory\Articles::article_delete(\S::get('article_id'));
|
|
}
|
|
}
|
|
```
|
|
|
|
### Factories — @deprecated wrappers, static methods, delegate to repo
|
|
```php
|
|
namespace admin\factory;
|
|
/** @deprecated Wrapper — używaj \Domain\Articles\ArticlesRepository przez DI */
|
|
class Articles {
|
|
private static function repo(): \Domain\Articles\ArticlesRepository {
|
|
global $mdb;
|
|
return new \Domain\Articles\ArticlesRepository($mdb);
|
|
}
|
|
public static function article_delete($id): bool {
|
|
return self::repo()->deleteArticle((int)$id);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Domain Repositories — constructor DI, camelCase, typed returns
|
|
```php
|
|
namespace Domain\Articles;
|
|
class ArticlesRepository {
|
|
private $db;
|
|
public function __construct($db) { $this->db = $db; }
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Odczyt (Read)
|
|
// -------------------------------------------------------------------------
|
|
public function find(int $id): ?array {
|
|
return $this->db->get('pp_articles', '*', ['id' => $id]) ?: null;
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Zapis / usuwanie (Write / Delete)
|
|
// -------------------------------------------------------------------------
|
|
public function deleteArticle(int $id): bool {
|
|
$this->db->delete('pp_articles', ['id' => $id]);
|
|
return true;
|
|
}
|
|
}
|
|
```
|
|
|
|
### View classes — static rendering
|
|
```php
|
|
namespace admin\view;
|
|
class Articles {
|
|
public static function list($articles) {
|
|
$tpl = new \Tpl;
|
|
$tpl->articles = $articles;
|
|
return $tpl->render('articles/list');
|
|
}
|
|
}
|
|
```
|
|
|
|
## PHPDoc Style
|
|
|
|
Polish-language descriptions are standard in this project:
|
|
```php
|
|
/**
|
|
* Prosta lista autorów
|
|
* @return array|bool
|
|
*/
|
|
public function authorsList() { ... }
|
|
|
|
/**
|
|
* Zapis autora (insert lub update)
|
|
* @param int $authorId
|
|
* @param string $author
|
|
* @return object|bool
|
|
*/
|
|
public function authorSave(int $authorId, string $author) { ... }
|
|
```
|
|
|
|
Section separators in larger classes:
|
|
```php
|
|
// -------------------------------------------------------------------------
|
|
// Odczyt (Read operations)
|
|
// -------------------------------------------------------------------------
|
|
```
|
|
|
|
## Return Patterns
|
|
|
|
| Pattern | Usage |
|
|
|---------|-------|
|
|
| `?array` | Single record lookup (null = not found) |
|
|
| `array` (possibly `[]`) | List queries — `?: []` fallback |
|
|
| `bool` | Write/delete operations |
|
|
| `int` | Codes: `1 = OK`, `0 = bad credentials`, `-1 = blocked` |
|
|
| `void` | Side-effect-only writes |
|
|
| `['status' => 'ok'/'error', 'msg' => '...']` | AJAX JSON responses |
|
|
|
|
## Error Handling
|
|
|
|
- Repositories return `null`/`false`/`[]` for "not found", don't throw
|
|
- `ImageManipulator` uses typed exceptions (`\InvalidArgumentException`, `\RuntimeException`)
|
|
- AJAX endpoints: `json_encode(['status' => 'ok/error', 'msg' => '...'])`
|
|
- Error suppression with `@` is used in legacy code (avoid in new code)
|
|
|
|
## Database Access via Medoo
|
|
|
|
Always use parameterized Medoo methods — never string concatenation with string values:
|
|
```php
|
|
// Good
|
|
$this->db->get('pp_articles', '*', ['id' => $id]);
|
|
$this->db->select('pp_articles', '*', ['ORDER' => ['created' => 'DESC']]);
|
|
$this->db->update('pp_articles', ['status' => 1], ['id' => $id]);
|
|
$this->db->insert('pp_articles', ['title' => $title, 'slug' => $slug]);
|
|
|
|
// Acceptable (integer cast only)
|
|
$this->db->query("SELECT ... WHERE id = " . (int)$id)->fetchAll();
|
|
|
|
// Never
|
|
$this->db->query("SELECT ... WHERE slug = '" . $slug . "'"); // SQL injection risk
|
|
```
|
|
|
|
## Global Helper Facade (`\S::`)
|
|
|
|
Legacy code uses `\S::method()` — new code should use `\Shared\Helpers\Helpers::method()` directly or inject the dependency. Migrate `\S::` calls opportunistically but don't block on it.
|
|
|
|
## Template Rendering
|
|
|
|
```php
|
|
$tpl = new \Tpl; // or: new \Shared\Tpl\Tpl
|
|
$tpl->variable = $value; // assign template variables
|
|
return $tpl->render('module/template-name'); // checks templates_user/ first, then templates/
|
|
```
|