263 lines
8.1 KiB
PHP
263 lines
8.1 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace Hura8\System\Controller;
|
||
|
|
|
||
|
|
use Hura8\Interfaces\iEntityLanguageModel;
|
||
|
|
use Hura8\Interfaces\iEntityModel;
|
||
|
|
use Hura8\System\Security\DataClean;
|
||
|
|
use Hura8\System\Security\DataType;
|
||
|
|
use Hura8\Traits\ClassCacheTrait;
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @description shared controller for aAdminEntityBaseController and aPublicEntityBaseController
|
||
|
|
* DO NOT EXTEND THIS CLASS from other classes
|
||
|
|
*/
|
||
|
|
abstract class aEntityBaseController
|
||
|
|
{
|
||
|
|
use ClassCacheTrait;
|
||
|
|
|
||
|
|
/* @var iEntityModel $iEntityModel */
|
||
|
|
protected $iEntityModel;
|
||
|
|
|
||
|
|
/* @var ?iEntityLanguageModel $iEntityLanguageModel */
|
||
|
|
protected $iEntityLanguageModel = null;
|
||
|
|
|
||
|
|
protected $view_language = LANGUAGE;
|
||
|
|
|
||
|
|
public function __construct(
|
||
|
|
iEntityModel $iEntityModel,
|
||
|
|
?iEntityLanguageModel $iEntityLanguageModel = null
|
||
|
|
) {
|
||
|
|
|
||
|
|
$this->iEntityModel = $iEntityModel;
|
||
|
|
|
||
|
|
if(!$this->isDefaultLanguage() && $iEntityLanguageModel instanceof iEntityLanguageModel) {
|
||
|
|
$this->iEntityLanguageModel = $iEntityLanguageModel;
|
||
|
|
|
||
|
|
// only controller allow to control the language for the model
|
||
|
|
$this->iEntityLanguageModel->setLanguage($this->view_language);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public function getLanguage() {
|
||
|
|
return $this->view_language;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public function isDefaultLanguage() {
|
||
|
|
return IS_DEFAULT_LANGUAGE;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public function getFilterConditions() : array {
|
||
|
|
return array_merge(
|
||
|
|
$this->baseFilterConditions(),
|
||
|
|
$this->extendFilterConditions()
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// this is supposed to be overwritten by the extending class if required
|
||
|
|
protected function extendFilterConditions() : array {
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
|
||
|
|
// just here to show the reserved keys. That's all
|
||
|
|
protected function baseFilterConditions() {
|
||
|
|
$base_filter = [
|
||
|
|
'q' => getRequest("q", ''), // keyword search
|
||
|
|
'q_options' => [
|
||
|
|
'field_filters' => [],
|
||
|
|
'fulltext_fields' => [],
|
||
|
|
'limit_result' => 2000
|
||
|
|
], // q_options as in iSearch->find($keyword, array $field_filters = [], array $fulltext_fields = ["keywords"], $limit_result = 2000)
|
||
|
|
'featured' => getRequestInt("featured", 0), // 1|-1
|
||
|
|
'status' => getRequestInt("status", 0), // 1|-1
|
||
|
|
'excluded_ids' => null, // [id1, id2, ...]
|
||
|
|
'included_ids' => null,// [id1, id2, ...]
|
||
|
|
|
||
|
|
// to special filters for language
|
||
|
|
'translated' => getRequestInt("translated", 0), // 1|-1
|
||
|
|
|
||
|
|
// for sorting
|
||
|
|
'sort_by' => getRequest('sort', ''),
|
||
|
|
|
||
|
|
// for pagination, not exactly for filter but put here to reserve the keys
|
||
|
|
'numPerPage' => getRequestInt("show", 20),
|
||
|
|
'page' => getPageId(),
|
||
|
|
];
|
||
|
|
|
||
|
|
if(getRequest("excluded_ids", '') != '') {
|
||
|
|
$base_filter['excluded_ids'] = explode("-", getRequest("excluded_ids", ''));
|
||
|
|
}
|
||
|
|
|
||
|
|
if(getRequest("included_ids", '') != '') {
|
||
|
|
$base_filter['included_ids'] = explode("-", getRequest("included_ids", ''));
|
||
|
|
}
|
||
|
|
|
||
|
|
return $base_filter;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
protected function formatItemInList(array $item_info)
|
||
|
|
{
|
||
|
|
return $item_info;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
protected function formatItemInfo(array $item_info)
|
||
|
|
{
|
||
|
|
return $item_info;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public function getListByIds(array $list_id, array $condition = array()) : array
|
||
|
|
{
|
||
|
|
$item_list = array_map(function ($item){
|
||
|
|
return $this->formatItemInList($item);
|
||
|
|
}, $this->iEntityModel->getListByIds($list_id, $condition));
|
||
|
|
|
||
|
|
if($this->iEntityLanguageModel) {
|
||
|
|
$item_list_language_info = $this->iEntityLanguageModel->getListByIds($list_id);
|
||
|
|
|
||
|
|
$final_list = [];
|
||
|
|
foreach ($item_list as $item) {
|
||
|
|
$item_language_info = $item_list_language_info[$item['id']] ?? ["not_translated" => true];
|
||
|
|
$final_list[] = array_merge($item, $item_language_info);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $final_list;
|
||
|
|
}
|
||
|
|
|
||
|
|
return $item_list;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// for extending controller class to validate and clean data in the $raw_filter_condition (ie. from URL)
|
||
|
|
// before sending to model for data querying
|
||
|
|
// extending controller must overwrite this
|
||
|
|
protected function validateAndCleanFilterCondition(array $raw_filter_condition) : array {
|
||
|
|
|
||
|
|
$clean_values = [];
|
||
|
|
|
||
|
|
foreach ($raw_filter_condition as $key => $value) {
|
||
|
|
// default
|
||
|
|
if(is_array($value)) {
|
||
|
|
$clean_values[$key] = DataClean::makeListOfInputSafe($value, DataType::ID);
|
||
|
|
}else{
|
||
|
|
$clean_values[$key] = DataClean::makeInputSafe($value, DataType::ID);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $clean_values;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @description utility to inspect the actual filters which will be used in getList
|
||
|
|
* make sure to edit the ::_buildQueryConditionExtend method on the Model so the Model will parse the filters provided by controller here
|
||
|
|
* @param array $raw_filter_condition
|
||
|
|
* @return string[]
|
||
|
|
*/
|
||
|
|
public function getActualFilterCondition(array $raw_filter_condition) : array
|
||
|
|
{
|
||
|
|
return $this->buildFilterQuery($raw_filter_condition);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @description utility to inspect the actual filters which will be used in getList by Model
|
||
|
|
* @param array $raw_filter_condition
|
||
|
|
* @return string[]
|
||
|
|
*/
|
||
|
|
public function getModelFilterCondition(array $raw_filter_condition) : array
|
||
|
|
{
|
||
|
|
return $this->iEntityModel->getQueryCondition($this->buildFilterQuery($raw_filter_condition));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public function getList(array $raw_filter_condition) : array
|
||
|
|
{
|
||
|
|
|
||
|
|
$filter_condition = $this->buildFilterQuery($raw_filter_condition);
|
||
|
|
//debug_var($filter_condition);
|
||
|
|
|
||
|
|
$item_list = array_map(function ($item){
|
||
|
|
return $this->formatItemInList($item);
|
||
|
|
}, $this->iEntityModel->getList($filter_condition));
|
||
|
|
|
||
|
|
|
||
|
|
if($this->iEntityLanguageModel) {
|
||
|
|
|
||
|
|
$item_list_ids = array_map(function ($item){ return $item['id']; }, $item_list);
|
||
|
|
$item_list_language_info = $this->iEntityLanguageModel->getListByIds($item_list_ids);
|
||
|
|
|
||
|
|
$final_list = [];
|
||
|
|
foreach ($item_list as $item) {
|
||
|
|
$item_language_info = $item_list_language_info[$item['id']] ?? ["not_translated" => true];
|
||
|
|
$final_list[] = array_merge($item, $item_language_info);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $final_list;
|
||
|
|
}
|
||
|
|
|
||
|
|
return $item_list;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public function getTotal(array $raw_filter_condition) : int
|
||
|
|
{
|
||
|
|
$filter_condition = $this->buildFilterQuery($raw_filter_condition);
|
||
|
|
|
||
|
|
return $this->iEntityModel->getTotal($filter_condition);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
protected function buildFilterQuery(array $raw_filter_condition) : array
|
||
|
|
{
|
||
|
|
$filter_condition = $this->validateAndCleanFilterCondition($raw_filter_condition);
|
||
|
|
|
||
|
|
// special case to filter out which ids have not been translated
|
||
|
|
if(isset($filter_condition['translated']) && $filter_condition['translated'] && $this->iEntityLanguageModel) {
|
||
|
|
if($filter_condition['translated'] == 1) {
|
||
|
|
$filter_condition['included_ids'] = $this->iEntityLanguageModel->getTranslatedIds();
|
||
|
|
}else{
|
||
|
|
$filter_condition['excluded_ids'] = $this->iEntityLanguageModel->getTranslatedIds();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $filter_condition;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public function getInfo($id): ?array
|
||
|
|
{
|
||
|
|
if(!$id) return null;
|
||
|
|
|
||
|
|
return self::getCache("getInfo-".$id."-".$this->view_language, function () use ($id){
|
||
|
|
|
||
|
|
$info = $this->iEntityModel->getInfo($id);
|
||
|
|
|
||
|
|
if($this->iEntityLanguageModel && $info) {
|
||
|
|
$item_language_info = $this->iEntityLanguageModel->getInfo($id);
|
||
|
|
//debug_var($item_language_info);
|
||
|
|
|
||
|
|
if($item_language_info) {
|
||
|
|
return $this->formatItemInfo(array_merge($info, $item_language_info));
|
||
|
|
}else{
|
||
|
|
$info["not_translated"] = true;
|
||
|
|
|
||
|
|
return $this->formatItemInfo($info);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return ($info) ? $this->formatItemInfo($info) : null;
|
||
|
|
|
||
|
|
});
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
}
|