dashboard for org
This commit is contained in:
@@ -7,8 +7,9 @@ use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use App\Models\OrganizationModel;
|
||||
use App\Services\AccessService;
|
||||
|
||||
/**
|
||||
/**
|
||||
* BaseController provides a convenient place for loading components
|
||||
* and performing functions that are needed by all your controllers.
|
||||
*
|
||||
@@ -27,6 +28,7 @@ abstract class BaseController extends Controller
|
||||
*/
|
||||
|
||||
protected $session;
|
||||
protected AccessService $access;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
@@ -42,6 +44,33 @@ abstract class BaseController extends Controller
|
||||
|
||||
// Preload any models, libraries, etc, here.
|
||||
$this->session = service('session');
|
||||
$this->access = service('access');
|
||||
|
||||
// Загружаем хелпер доступа для Twig
|
||||
helper('access');
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка права на действие ( shortcut для $this->access->can() )
|
||||
*
|
||||
* @param string $action
|
||||
* @param string $resource
|
||||
* @return bool
|
||||
*/
|
||||
protected function can(string $action, string $resource): bool
|
||||
{
|
||||
return $this->access->can($action, $resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка роли (shortcut для $this->access->isRole() )
|
||||
*
|
||||
* @param string|array $roles
|
||||
* @return bool
|
||||
*/
|
||||
protected function isRole($roles): bool
|
||||
{
|
||||
return $this->access->isRole($roles);
|
||||
}
|
||||
|
||||
public function renderTwig($template, $data = [])
|
||||
@@ -55,6 +84,9 @@ abstract class BaseController extends Controller
|
||||
$oldInput = $this->session->get('_ci_old_input') ?? [];
|
||||
$data['old'] = $data['old'] ?? $oldInput;
|
||||
|
||||
// Добавляем access в данные шаблона для функций can(), isRole() и т.д.
|
||||
$data['access'] = $this->access;
|
||||
|
||||
ob_start();
|
||||
$twig->display($template, $data);
|
||||
$content = ob_get_clean();
|
||||
@@ -129,19 +161,39 @@ abstract class BaseController extends Controller
|
||||
}
|
||||
|
||||
$model = $config['model'];
|
||||
$builder = $model->builder();
|
||||
|
||||
// Сбрасываем все предыдущие условия
|
||||
$builder->resetQuery();
|
||||
|
||||
// Если есть кастомный scope - создаём новый чистый запрос
|
||||
// scope будет полностью контролировать FROM, JOIN, SELECT
|
||||
if (isset($config['scope']) && is_callable($config['scope'])) {
|
||||
$builder = $model->db()->newQuery();
|
||||
$config['scope']($builder);
|
||||
} else {
|
||||
// Стандартный путь - используем builder модели
|
||||
$builder = $model->builder();
|
||||
$builder->resetQuery();
|
||||
|
||||
// Автоматическая фильтрация по организации для моделей с TenantScopedModel
|
||||
$modelClass = get_class($model);
|
||||
$traits = class_uses($modelClass);
|
||||
if (in_array('App\Models\Traits\TenantScopedModel', $traits)) {
|
||||
$model->forCurrentOrg();
|
||||
}
|
||||
}
|
||||
|
||||
// Применяем фильтры
|
||||
foreach ($filters as $field => $value) {
|
||||
if ($value !== '' && in_array($field, $config['searchable'])) {
|
||||
$builder->like($field, $value);
|
||||
foreach ($filters as $filterKey => $value) {
|
||||
if ($value === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Сначала проверяем fieldMap (алиасы) — они имеют приоритет
|
||||
if (isset($config['fieldMap']) && isset($config['fieldMap'][$filterKey])) {
|
||||
$realField = $config['fieldMap'][$filterKey];
|
||||
$builder->like($realField, $value);
|
||||
}
|
||||
// Потом проверяем прямое совпадение
|
||||
elseif (in_array($filterKey, $config['searchable'])) {
|
||||
$builder->like($filterKey, $value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,13 +202,11 @@ abstract class BaseController extends Controller
|
||||
$builder->orderBy($sort, $order);
|
||||
}
|
||||
|
||||
// Исправлено: countAllResults(false) вместо countAll()
|
||||
// Сохраняем текущее состояние builder для подсчета
|
||||
$countBuilder = clone $builder;
|
||||
$total = $countBuilder->countAllResults(false);
|
||||
|
||||
// Получаем данные с пагинацией
|
||||
$builder->select('*');
|
||||
// Получаем данные с пагинацией (scope уже установил нужный SELECT)
|
||||
$items = $builder->limit($perPage, ($page - 1) * $perPage)->get()->getResultArray();
|
||||
|
||||
$from = ($page - 1) * $perPage + 1;
|
||||
@@ -180,6 +230,8 @@ abstract class BaseController extends Controller
|
||||
'filters' => $filters,
|
||||
'columns' => $config['columns'],
|
||||
'actionsConfig' => $config['actionsConfig'] ?? [],
|
||||
'can_edit' => $config['can_edit'] ?? true,
|
||||
'can_delete' => $config['can_delete'] ?? true,
|
||||
];
|
||||
|
||||
return $data;
|
||||
@@ -221,12 +273,42 @@ abstract class BaseController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX endpoint для таблицы - возвращает partial (tbody + tfoot)
|
||||
* Если запрос не AJAX - возвращает полную таблицу
|
||||
* AJAX endpoint для таблицы
|
||||
*
|
||||
* Логика:
|
||||
* - Если format=partial или AJAX → возвращает только tbody + tfoot
|
||||
* - Если прямой GET → редиректит на основную страницу с теми же параметрами
|
||||
*
|
||||
* @param array|null $config Кастомная конфигурация таблицы (если null, используется getTableConfig())
|
||||
* @param string|null $pageUrl URL основной страницы таблицы (для редиректа)
|
||||
* @return string|ResponseInterface
|
||||
*/
|
||||
public function table()
|
||||
public function table(?array $config = null, ?string $pageUrl = null)
|
||||
{
|
||||
$isPartial = $this->request->getGet('format') === 'partial' || $this->isAjax();
|
||||
return $this->renderTable(null, $isPartial);
|
||||
|
||||
// Если это частичный запрос (AJAX) — возвращаем только таблицу
|
||||
if ($isPartial) {
|
||||
return $this->renderTable($config, true);
|
||||
}
|
||||
|
||||
// Прямой запрос к /table — редиректим на основную страницу
|
||||
// Сохраняем все параметры: page, perPage, sort, order, filters
|
||||
$params = $this->request->getGet();
|
||||
unset($params['format']); // Убираем format=partial если был
|
||||
|
||||
if ($pageUrl) {
|
||||
$redirectUrl = $pageUrl;
|
||||
} else {
|
||||
// Пытаемся извлечь URL из config['url']
|
||||
$tableUrl = $config['url'] ?? '/table';
|
||||
$redirectUrl = $tableUrl;
|
||||
}
|
||||
|
||||
if (!empty($params)) {
|
||||
$redirectUrl .= '?' . http_build_query($params);
|
||||
}
|
||||
|
||||
return redirect()->to($redirectUrl);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user