first commit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class CategoryModel extends Model
|
||||
{
|
||||
protected $table = 'categories';
|
||||
protected $primaryKey = 'id';
|
||||
protected $returnType = 'array';
|
||||
protected $useTimestamps = true;
|
||||
protected $allowedFields = ['name', 'type', 'parent_id'];
|
||||
|
||||
protected $validationRules = [
|
||||
'name' => 'required|max_length[100]',
|
||||
'type' => 'required|in_list[income,expense]',
|
||||
'parent_id' => 'permit_empty|is_natural_no_zero',
|
||||
];
|
||||
|
||||
/**
|
||||
* Plaska lista kategorii, opcjonalnie filtrowana typem.
|
||||
*/
|
||||
public function flatList(?string $type = null): array
|
||||
{
|
||||
$builder = $this->orderBy('type', 'ASC')->orderBy('name', 'ASC');
|
||||
if ($type !== null && $type !== '') {
|
||||
$builder = $builder->where('type', $type);
|
||||
}
|
||||
|
||||
return $builder->findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Czy kategoria jest uzywana przez jakies operacje.
|
||||
*/
|
||||
public function usedByOperations(int $id): bool
|
||||
{
|
||||
return (bool) model(OperationModel::class)->where('category_id', $id)->countAllResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Kategorie w porzadku drzewa, posortowane po nazwie na kazdym poziomie.
|
||||
* Kazdy element dostaje 'depth' oraz 'indent_label' (nazwa z wcieciem) do list i selectow.
|
||||
*/
|
||||
public function tree(?string $type = null): array
|
||||
{
|
||||
$builder = $this->orderBy('name', 'ASC');
|
||||
if ($type !== null && $type !== '') {
|
||||
$builder->where('type', $type);
|
||||
}
|
||||
$all = $builder->findAll();
|
||||
|
||||
// Grupowanie dzieci wg rodzica (0 = korzen)
|
||||
$childrenByParent = [];
|
||||
foreach ($all as $c) {
|
||||
$childrenByParent[(int) ($c['parent_id'] ?: 0)][] = $c;
|
||||
}
|
||||
|
||||
$indent = "\u{00A0}\u{00A0}\u{00A0}\u{00A0}"; // 4x twarda spacja na poziom
|
||||
$out = [];
|
||||
|
||||
$walk = static function (int $parentId, int $depth) use (&$walk, &$out, $childrenByParent, $indent): void {
|
||||
foreach ($childrenByParent[$parentId] ?? [] as $c) {
|
||||
$c['depth'] = $depth;
|
||||
$c['indent_label'] = str_repeat($indent, $depth) . $c['name'];
|
||||
$out[] = $c;
|
||||
$walk((int) $c['id'], $depth + 1);
|
||||
}
|
||||
};
|
||||
$walk(0, 0);
|
||||
|
||||
// Sieroty (np. rodzic odfiltrowany typem) — dopnij na koncu bez wciecia
|
||||
$seen = array_column($out, null, 'id');
|
||||
foreach ($all as $c) {
|
||||
if (! isset($seen[$c['id']])) {
|
||||
$c['depth'] = 0;
|
||||
$c['indent_label'] = $c['name'];
|
||||
$out[] = $c;
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user