Files
cmsPRO/.paul/codebase/conventions.md
Jacek Pyziak bf4b7c6429 docs(codebase): mapa kodu wygenerowana przez /paul:map-codebase
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>
2026-04-26 00:46:01 +02:00

5.0 KiB

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

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

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

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

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:

/**
 * 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:

// -------------------------------------------------------------------------
// 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:

// 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

$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/