update
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Analytics\Controller;
|
||||
|
||||
use Hura8\Components\Analytics\Model\TrackingModel;
|
||||
|
||||
class bTrackingController
|
||||
{
|
||||
|
||||
protected $objTrackingModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objTrackingModel = new TrackingModel();
|
||||
}
|
||||
|
||||
}
|
||||
19
inc/Hura8/Components/Analytics/Model/TrackDeviceInfo.php
Normal file
19
inc/Hura8/Components/Analytics/Model/TrackDeviceInfo.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Analytics\Model;
|
||||
|
||||
class TrackDeviceInfo
|
||||
{
|
||||
public $ip_address;
|
||||
public $user_agent;
|
||||
public $referrer;
|
||||
public $is_mobile;
|
||||
|
||||
public function __construct(string $ip_address, string $user_agent, string $referrer, bool $is_mobile)
|
||||
{
|
||||
$this->ip_address = $ip_address;
|
||||
$this->user_agent = $user_agent;
|
||||
$this->referrer = $referrer;
|
||||
$this->is_mobile = $is_mobile;
|
||||
}
|
||||
}
|
||||
28
inc/Hura8/Components/Analytics/Model/TrackRouteInfo.php
Normal file
28
inc/Hura8/Components/Analytics/Model/TrackRouteInfo.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Analytics\Model;
|
||||
|
||||
class TrackRouteInfo
|
||||
{
|
||||
public $url;
|
||||
public $module;
|
||||
public $view;
|
||||
public $view_id;
|
||||
public $query;
|
||||
|
||||
public function __construct(
|
||||
string $url,
|
||||
string $module,
|
||||
string $view,
|
||||
string $view_id,
|
||||
array $query = []
|
||||
)
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->module = $module;
|
||||
$this->view = $view;
|
||||
$this->view_id = $view_id;
|
||||
$this->query = $query;
|
||||
}
|
||||
|
||||
}
|
||||
19
inc/Hura8/Components/Analytics/Model/TrackUserInfo.php
Normal file
19
inc/Hura8/Components/Analytics/Model/TrackUserInfo.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Analytics\Model;
|
||||
|
||||
class TrackUserInfo
|
||||
{
|
||||
|
||||
public $web_user_id;
|
||||
public $customer_id;
|
||||
public $is_crawler;
|
||||
|
||||
public function __construct(string $web_user_id, string $customer_id, bool $is_crawler)
|
||||
{
|
||||
$this->web_user_id = $web_user_id;
|
||||
$this->customer_id = $customer_id;
|
||||
$this->is_crawler = $is_crawler ? 1 : 0;
|
||||
}
|
||||
|
||||
}
|
||||
32
inc/Hura8/Components/Analytics/Model/TrackingModel.php
Normal file
32
inc/Hura8/Components/Analytics/Model/TrackingModel.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Analytics\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
|
||||
class TrackingModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
protected $tb_track_ip = "tb_analyics_track_ip";
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(
|
||||
"analyics_user_log"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions(): array
|
||||
{
|
||||
// TODO: Implement extendedFilterOptions() method.
|
||||
}
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition): ?array
|
||||
{
|
||||
// TODO: Implement _buildQueryConditionExtend() method.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Article\AdminController;
|
||||
|
||||
use Hura8\Components\Article\Controller\bArticleCategoryController;
|
||||
use Hura8\Interfaces\iEntityAdminCategoryController;
|
||||
use Hura8\Traits\AdminEntityCategoryControllerTraits;
|
||||
|
||||
|
||||
class AArticleCategoryController extends bArticleCategoryController implements iEntityAdminCategoryController
|
||||
{
|
||||
use AdminEntityCategoryControllerTraits;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Article\AdminController;
|
||||
|
||||
use Hura8\Components\Article\Controller\bArticleController;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
class AArticleController extends bArticleController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
public function updateTableInfo($item_id, array $new_item_info) {
|
||||
if(!$this->isDefaultLanguage()) {
|
||||
return $this->iEntityLanguageModel->update($item_id, $new_item_info);
|
||||
}
|
||||
|
||||
return $this->objArticleModel->updateTableInfo($item_id, $new_item_info);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Article\Controller;
|
||||
|
||||
use Hura8\Components\Article\Model\ArticleCategoryLanguageModel;
|
||||
use Hura8\Components\Article\Model\ArticleCategoryModel;
|
||||
use Hura8\System\Controller\aCategoryBaseController;
|
||||
|
||||
|
||||
class bArticleCategoryController extends aCategoryBaseController
|
||||
{
|
||||
|
||||
/* @var ArticleCategoryModel $objArticleCategoryModel */
|
||||
protected $objArticleCategoryModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objArticleCategoryModel = new ArticleCategoryModel();
|
||||
|
||||
if(!$this->isDefaultLanguage()) {
|
||||
|
||||
parent::__construct(
|
||||
$this->objArticleCategoryModel,
|
||||
new ArticleCategoryLanguageModel()
|
||||
);
|
||||
|
||||
} else {
|
||||
|
||||
parent::__construct($this->objArticleCategoryModel);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Article\Controller;
|
||||
|
||||
|
||||
use Hura8\Components\Article\Model\ArticleLanguageModel;
|
||||
use Hura8\Components\Article\Model\ArticleModel;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
class bArticleController extends aEntityBaseController
|
||||
{
|
||||
static $image_folder = "media/article";
|
||||
|
||||
static $resized_sizes = array(
|
||||
't' => ['width' => 200,] ,
|
||||
'l' => ['width' => 600,] ,
|
||||
);
|
||||
|
||||
/* @var ArticleModel $objArticleModel */
|
||||
protected $objArticleModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objArticleModel = new ArticleModel();
|
||||
|
||||
if(!$this->isDefaultLanguage()) {
|
||||
parent::__construct(
|
||||
$this->objArticleModel,
|
||||
new ArticleLanguageModel()
|
||||
);
|
||||
|
||||
} else {
|
||||
parent::__construct($this->objArticleModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getFullInfo($id)
|
||||
{
|
||||
|
||||
if(!$id) return null;
|
||||
|
||||
return self::getCache("getFullInfo-".$id."-".$this->view_language, function () use ($id){
|
||||
|
||||
$info = $this->objArticleModel->getFullInfo($id);
|
||||
|
||||
if($this->iEntityLanguageModel && $info ) {
|
||||
$item_language_info = $this->iEntityLanguageModel->getInfo($id) ?? ["not_translated" => true];
|
||||
return $this->formatItemInfo(array_merge($info, $item_language_info));
|
||||
}
|
||||
|
||||
return ($info) ? $this->formatItemInfo($info) : null;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInList(array $item_info)
|
||||
{
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInfo(array $item_info)
|
||||
{
|
||||
if(!$item_info) return null;
|
||||
|
||||
$info = $item_info;
|
||||
$info['image'] = self::getResizedImageCollection($info['thumbnail']);
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
||||
public static function getResizedImageCollection($image_name) {
|
||||
$image = [];
|
||||
|
||||
$size_in_full = [
|
||||
't' => 'thumb' ,
|
||||
's' => 'small' ,
|
||||
'l' => 'large' ,
|
||||
];
|
||||
|
||||
foreach (static::$resized_sizes as $size => $value) {
|
||||
$image[$size_in_full[$size]] = ($image_name) ? STATIC_DOMAIN . "/". static::$image_folder . "/". $size. IMAGE_FILE_SEPARATOR . $image_name : '';
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Article\Model;
|
||||
|
||||
|
||||
use Hura8\System\Model\EntityLanguageModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
|
||||
|
||||
class ArticleCategoryLanguageModel extends EntityLanguageModel
|
||||
{
|
||||
|
||||
protected $richtext_fields = [
|
||||
'description',
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::ARTICLE_CATEGORY, '', $this->richtext_fields);
|
||||
}
|
||||
|
||||
}
|
||||
33
inc/Hura8/Components/Article/Model/ArticleCategoryModel.php
Normal file
33
inc/Hura8/Components/Article/Model/ArticleCategoryModel.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Article\Model;
|
||||
|
||||
|
||||
use Hura8\System\Model\aCategoryBaseModel;
|
||||
use Hura8\Interfaces\iEntityCategoryModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
|
||||
|
||||
class ArticleCategoryModel extends aCategoryBaseModel implements iEntityCategoryModel
|
||||
{
|
||||
|
||||
static $url_module = "article";
|
||||
static $url_view = "category";
|
||||
static $url_type = "article:category";
|
||||
|
||||
protected $tb_article_per_category = "tb_article_per_category";
|
||||
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::ARTICLE_CATEGORY);
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
19
inc/Hura8/Components/Article/Model/ArticleLanguageModel.php
Normal file
19
inc/Hura8/Components/Article/Model/ArticleLanguageModel.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Article\Model;
|
||||
|
||||
use Hura8\System\Model\EntityLanguageModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
|
||||
class ArticleLanguageModel extends EntityLanguageModel
|
||||
{
|
||||
|
||||
protected $richtext_fields = [
|
||||
'description',
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::ARTICLE, '', $this->richtext_fields);
|
||||
}
|
||||
|
||||
}
|
||||
150
inc/Hura8/Components/Article/Model/ArticleModel.php
Normal file
150
inc/Hura8/Components/Article/Model/ArticleModel.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Article\Model;
|
||||
|
||||
use Hura8\System\Controller\UrlManagerController;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\System\ModuleManager;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
|
||||
|
||||
class ArticleModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
static $url_type = "article:detail";
|
||||
|
||||
protected $tb_article_info = "tb_article_info";
|
||||
protected $tb_article_per_category = 'tb_article_per_category';
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(
|
||||
EntityType::ARTICLE,
|
||||
"",
|
||||
new ArticleSearchModel()
|
||||
);
|
||||
}
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getFullInfo($id) : ?array
|
||||
{
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT * FROM `".$this->tb_entity."` basic, `".$this->tb_article_info."` info
|
||||
WHERE basic.`id` = info.`article_id` AND basic.id = ?
|
||||
LIMIT 1 ",
|
||||
['d'], [$id]
|
||||
);
|
||||
|
||||
if( $item_info = $this->db->fetchAssoc($query)){
|
||||
return $item_info;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
/*$condition = array(
|
||||
"category" => getRequestInt("category"),
|
||||
"no_image" => 0,//1
|
||||
);*/
|
||||
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
//Tim danh muc
|
||||
if(isset($filter_condition["category"]) && $filter_condition["category"]) {
|
||||
|
||||
$objArticleCategoryModel = new ArticleCategoryModel();
|
||||
$category_info = $objArticleCategoryModel->getInfo($filter_condition["category"]);
|
||||
|
||||
if($category_info) {
|
||||
if($category_info['is_parent']) {
|
||||
$catCondition[] = " AND `id` IN (SELECT `item_id` FROM `".$this->tb_article_per_category."` WHERE `category_id` IN (".$category_info['child_ids'].") ) ";
|
||||
//$bind_types[] = 'd';
|
||||
//$bind_values[] = $filter_condition["category"];
|
||||
}else{
|
||||
$catCondition[] = " AND `id` IN (SELECT `item_id` FROM `".$this->tb_article_per_category."` WHERE `category_id` = ? ) ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = $filter_condition["category"];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
protected function addArticleToCategory($item_id, array $category_list_id) {
|
||||
$this->db->runQuery("DELETE FROM `".$this->tb_article_per_category."` WHERE `item_id` = ? ", ['d'], [$item_id]);
|
||||
|
||||
$bulk_inserts = [];
|
||||
foreach($category_list_id as $cat_id) {
|
||||
if (! $cat_id) continue;
|
||||
|
||||
$bulk_inserts[] = [
|
||||
'category_id' => $cat_id,
|
||||
'item_id' => $item_id,
|
||||
'status' => 1,
|
||||
'create_time' => CURRENT_TIME,
|
||||
];
|
||||
}
|
||||
|
||||
if(sizeof($bulk_inserts)) {
|
||||
$this->db->bulk_insert($this->tb_article_per_category, $bulk_inserts);
|
||||
}
|
||||
|
||||
// update counter
|
||||
$objArticleCategoryModel = new ArticleCategoryModel();
|
||||
foreach($category_list_id as $cat_id) {
|
||||
$objArticleCategoryModel->updateItemCount($cat_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function updateUrl($id, $url_index): bool
|
||||
{
|
||||
|
||||
$module_routing = ModuleManager::getModuleRouting("article");
|
||||
$request_path_config = isset($module_routing["detail"]) ? $module_routing["detail"]['url_manager']['request_path'] : '';
|
||||
|
||||
if(!$request_path_config) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$request_path = UrlManagerController::translateRequestPathConfig($request_path_config, $id, $url_index);
|
||||
$id_path = UrlManagerController::createIdPath("article", "detail", $id);
|
||||
|
||||
$objUrlManager = new UrlManagerController();
|
||||
$new_request_path = $objUrlManager->createUrl("article:detail", $request_path, $id_path, 0);
|
||||
|
||||
if($new_request_path) {
|
||||
$this->db->update(
|
||||
$this->tb_entity,
|
||||
[
|
||||
'request_path' => $new_request_path,
|
||||
],
|
||||
[
|
||||
'id' => $id,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
29
inc/Hura8/Components/Article/Model/ArticleSearchModel.php
Normal file
29
inc/Hura8/Components/Article/Model/ArticleSearchModel.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Article\Model;
|
||||
|
||||
use Hura8\Interfaces\iSearch;
|
||||
use Hura8\System\Model\aSearchBaseModel;
|
||||
|
||||
class ArticleSearchModel extends aSearchBaseModel implements iSearch
|
||||
{
|
||||
|
||||
private $filter_fields = [
|
||||
"status"=> "tb_article.status",
|
||||
];
|
||||
|
||||
private $fulltext_fields = [
|
||||
"keywords" => ["tb_article.title", ],
|
||||
];
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
"tb_article",
|
||||
$this->fulltext_fields,
|
||||
$this->filter_fields
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
55
inc/Hura8/Components/Article/Model/UArticleModel.php
Normal file
55
inc/Hura8/Components/Article/Model/UArticleModel.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Article\Model;
|
||||
|
||||
class UArticleModel extends ArticleModel
|
||||
{
|
||||
|
||||
public function getSameCategoryArticle($main_id, $category_id){
|
||||
|
||||
$query = $this->db->runQuery("
|
||||
(
|
||||
SELECT `item_id`
|
||||
FROM ".$this->tb_article_per_category."
|
||||
WHERE `category_id` = ? AND `status`=1 AND `item_id` > ?
|
||||
ORDER BY `item_id` DESC
|
||||
LIMIT 10
|
||||
|
||||
) UNION ALL (
|
||||
SELECT `item_id`
|
||||
FROM ".$this->tb_article_per_category."
|
||||
WHERE `category_id` = ? AND `status`=1 AND `item_id` < ?
|
||||
ORDER BY `item_id` DESC
|
||||
LIMIT 10
|
||||
)
|
||||
",
|
||||
['d', 'd', 'd', 'd'],
|
||||
[$category_id, $main_id, $category_id, $main_id]
|
||||
);
|
||||
|
||||
$article_list_id = [];
|
||||
$article_item_info = array();
|
||||
$article_item = [];
|
||||
|
||||
foreach ( $this->db->fetchAll($query) as $rs ) {
|
||||
if(!isset($article_item_info[$rs["item_id"]])) $article_item_info[$rs["item_id"]] = array();
|
||||
if(!in_array($rs["item_id"], $article_list_id)) $article_list_id[] = $rs["item_id"];
|
||||
|
||||
if($rs["item_id"] > $main_id) {
|
||||
$article_item['new'][$rs["item_id"]] = &$article_item_info[$rs["item_id"]];
|
||||
}
|
||||
else {
|
||||
$article_item['old'][$rs["item_id"]] = &$article_item_info[$rs["item_id"]];
|
||||
}
|
||||
}
|
||||
|
||||
$list_article_info = $this->getListByIds($article_list_id);
|
||||
foreach ($article_list_id as $_id) {
|
||||
if(isset($list_article_info[$_id])) $article_item_info[$_id] = $list_article_info[$_id];
|
||||
}
|
||||
|
||||
|
||||
return $article_item;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Banner\AdminController;
|
||||
|
||||
use Hura8\Components\Banner\Controller\bBannerController;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
class ABannerController extends bBannerController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Banner\AdminController;
|
||||
|
||||
use Hura8\Components\Banner\Model\BannerLocationModel;
|
||||
use Hura8\System\Controller\aAdminEntityBaseController;
|
||||
|
||||
|
||||
class ABannerLocationController extends aAdminEntityBaseController
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(new BannerLocationModel());
|
||||
}
|
||||
|
||||
public function getTemplateBanner() {
|
||||
return ABannerController::$template_banners;
|
||||
}
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
67
inc/Hura8/Components/Banner/Controller/bBannerController.php
Normal file
67
inc/Hura8/Components/Banner/Controller/bBannerController.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Banner\Controller;
|
||||
|
||||
use Hura8\Components\Banner\Model\BannerLocationModel;
|
||||
use Hura8\Components\Banner\Model\BannerModel;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
class bBannerController extends aEntityBaseController
|
||||
{
|
||||
|
||||
static $image_folder = "media/banner";
|
||||
|
||||
static $template_banners = array(
|
||||
//"index" => "Toàn bộ website" ,
|
||||
"header" => "Đầu trang" ,
|
||||
"homepage" => "Trang chủ" ,
|
||||
"column_left" => "Cột trái" ,
|
||||
"column_right" => "Cột phải" ,
|
||||
"footer" => "Chân trang" ,
|
||||
"product_detail"=> "Chi tiết sản phẩm" ,
|
||||
"product_list" => "Danh sách & Danh mục sản phẩm" ,
|
||||
"collection_list" => "Bộ sưu tập" ,
|
||||
"article_home" => "Trang chủ tin tức" ,
|
||||
"brand_detail" => "Chi tiết thương hiệu",
|
||||
);
|
||||
|
||||
|
||||
protected $objBannerModel;
|
||||
protected $objBannerLocationModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objBannerModel = new BannerModel();
|
||||
$this->objBannerLocationModel = new BannerLocationModel();
|
||||
|
||||
parent::__construct($this->objBannerModel);
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInList(array $item_info)
|
||||
{
|
||||
return self::formatFile($item_info);
|
||||
}
|
||||
|
||||
protected function formatItemInfo(array $item_info)
|
||||
{
|
||||
return self::formatFile($item_info);
|
||||
}
|
||||
|
||||
|
||||
public static function formatFile(array $item_info)
|
||||
{
|
||||
|
||||
if($item_info['file_url']) {
|
||||
$item_info['display_file'] = STATIC_DOMAIN ."/". static::$image_folder ."/". $item_info['file_url'];
|
||||
}else if($item_info['file_external_url']) {
|
||||
$item_info['display_file'] = $item_info['file_external_url'];
|
||||
}
|
||||
|
||||
$item_info['html_code'] = "<a href=\"/ad.php?id=".$item_info['tracking_id']."\" target='_blank' rel='nofollow'><img border='0' src=\"".$item_info['display_file']."\" alt=\"".htmlspecialchars($item_info['title'])."\" /></a>";
|
||||
|
||||
return $item_info;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
30
inc/Hura8/Components/Banner/Model/BannerLocationModel.php
Normal file
30
inc/Hura8/Components/Banner/Model/BannerLocationModel.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Banner\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\System\Security\DataClean;
|
||||
use Hura8\System\Security\DataType;
|
||||
|
||||
|
||||
class BannerLocationModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::BANNER_LOCATION);
|
||||
}
|
||||
|
||||
protected function extendedFilterOptions(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
90
inc/Hura8/Components/Banner/Model/BannerModel.php
Normal file
90
inc/Hura8/Components/Banner/Model/BannerModel.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Banner\Model;
|
||||
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
|
||||
|
||||
class BannerModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
protected $tb_banner_location = "tb_banner_location";
|
||||
protected $tb_banner_per_category = "tb_banner_per_category";
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(
|
||||
EntityType::BANNER, "", new BannerSearchModel()
|
||||
);
|
||||
}
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
public function getInfoByTrackingId($tracking_id)
|
||||
{
|
||||
$query = $this->db->runQuery("SELECT * FROM `".$this->tb_entity."` WHERE `tracking_id` = ? LIMIT 1 ", ['s'], [$tracking_id]) ;
|
||||
if( $item_info = $this->db->fetchAssoc($query)){
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getBannerPerTemplate(array $template_list, $numberOfBannerPerTpl=100){
|
||||
|
||||
$all_bind_types = [];
|
||||
$all_bind_values = [];
|
||||
|
||||
$view_id = 0;
|
||||
|
||||
$build_query = [];
|
||||
foreach($template_list as $tpl) {
|
||||
|
||||
list($where_condition, $bind_types, $bind_values) = $this->buildQueryPerTpl($tpl, $view_id, $numberOfBannerPerTpl);
|
||||
|
||||
$build_query[] = " (".$where_condition.") ";
|
||||
$all_bind_types = array_merge($all_bind_types, $bind_types);
|
||||
$all_bind_values = array_merge($all_bind_values, $bind_values);
|
||||
}
|
||||
|
||||
if(!sizeof($build_query)) return [];
|
||||
|
||||
$query = $this->db->runQuery(join(" UNION ALL ", $build_query), $all_bind_types, $all_bind_values);
|
||||
|
||||
return $this->db->fetchAll($query);
|
||||
}
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
/*$condition = array(
|
||||
[location] => 2
|
||||
[category] => 0
|
||||
);*/
|
||||
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
if(isset($filter_condition['location']) && $filter_condition['location']) {
|
||||
$catCondition[] = " AND `location` = ? ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = $filter_condition['location'];
|
||||
}
|
||||
|
||||
if(isset($filter_condition['category']) && $filter_condition['category']) {
|
||||
$catCondition[] = " AND `id` IN ( SELECT `banner_id` FROM `".$this->tb_banner_per_category."` WHERE `category_id` = ? ) ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = $filter_condition['category'];
|
||||
}
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
33
inc/Hura8/Components/Banner/Model/BannerSearchModel.php
Normal file
33
inc/Hura8/Components/Banner/Model/BannerSearchModel.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Banner\Model;
|
||||
|
||||
use Hura8\Interfaces\iSearch;
|
||||
use Hura8\System\Model\aSearchBaseModel;
|
||||
|
||||
|
||||
class BannerSearchModel extends aSearchBaseModel implements iSearch
|
||||
{
|
||||
|
||||
private $filter_fields = [
|
||||
"location" => "tb_banner.location",
|
||||
"status" => "tb_banner.status",
|
||||
];
|
||||
|
||||
private $fulltext_fields = [
|
||||
"keywords" => ["tb_banner.title",],
|
||||
];
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
"tb_banner",
|
||||
$this->fulltext_fields,
|
||||
$this->filter_fields
|
||||
);
|
||||
|
||||
//$this->createTableSearch();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Brand\AdminController;
|
||||
|
||||
use Hura8\Components\Brand\Controller\bBrandController;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
class ABrandController extends bBrandController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
public function getGroupByFirstLetter() {
|
||||
return $this->objBrandModel->getGroupByFirstLetter();
|
||||
}
|
||||
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
// delete thumb files
|
||||
$item_info = $this->getInfo($item_id);
|
||||
if($item_info['thumbnail']) {
|
||||
foreach (static::$resized_sizes as $size => $value) {
|
||||
$file_local_path = PUBLIC_DIR . "/". static::$image_folder . "/". $size. IMAGE_FILE_SEPARATOR . $item_info['thumbnail'];
|
||||
unlink($file_local_path);
|
||||
}
|
||||
|
||||
// remove original file
|
||||
$file_local_path = PUBLIC_DIR . "/". static::$image_folder . "/". $item_info['thumbnail'];
|
||||
unlink($file_local_path);
|
||||
}
|
||||
|
||||
//delete media files?
|
||||
// todo:
|
||||
|
||||
// ok
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
73
inc/Hura8/Components/Brand/Controller/bBrandController.php
Normal file
73
inc/Hura8/Components/Brand/Controller/bBrandController.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Brand\Controller;
|
||||
|
||||
use Hura8\Components\Brand\Model\BrandLanguageModel;
|
||||
use Hura8\Components\Brand\Model\BrandModel;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
|
||||
class bBrandController extends aEntityBaseController
|
||||
{
|
||||
|
||||
static $image_folder = "media/brand";
|
||||
|
||||
static $resized_sizes = array(
|
||||
's' => ['width' => 200,] ,
|
||||
);
|
||||
|
||||
/* @var BrandModel $objBrandModel */
|
||||
protected $objBrandModel;
|
||||
/* @var BrandLanguageModel $objBrandLanguageModel */
|
||||
protected $objBrandLanguageModel;
|
||||
protected $view_language = '';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objBrandModel = new BrandModel();
|
||||
|
||||
if(!$this->isDefaultLanguage()) {
|
||||
$this->objBrandLanguageModel = new BrandLanguageModel();
|
||||
//$this->objVideoLanguageModel->createTableLang();
|
||||
parent::__construct($this->objBrandModel, $this->objBrandLanguageModel);
|
||||
|
||||
}else{
|
||||
parent::__construct($this->objBrandModel);
|
||||
}
|
||||
}
|
||||
|
||||
public function getInfoByUrl(string $band_index) : ?array
|
||||
{
|
||||
return $this->objBrandModel->getInfoByUrl($band_index);
|
||||
}
|
||||
|
||||
protected function formatItemInList(array $item_info) : array
|
||||
{
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInfo(array $item_info) : ?array
|
||||
{
|
||||
if(!$item_info) return null;
|
||||
|
||||
$info = static::formatItemImage($item_info);
|
||||
|
||||
$info['url'] = "/brand/".$info['brand_index'];
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
||||
public static function formatItemImage(array $item_info) {
|
||||
$info = $item_info;
|
||||
|
||||
foreach (static::$resized_sizes as $size => $value) {
|
||||
$info['image'][$size] = ($info['thumbnail']) ? STATIC_DOMAIN . "/". static::$image_folder . "/". $size. IMAGE_FILE_SEPARATOR . $info['thumbnail'] : '';
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
19
inc/Hura8/Components/Brand/Model/BrandLanguageModel.php
Normal file
19
inc/Hura8/Components/Brand/Model/BrandLanguageModel.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Brand\Model;
|
||||
|
||||
use Hura8\System\Model\EntityLanguageModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
|
||||
class BrandLanguageModel extends EntityLanguageModel
|
||||
{
|
||||
|
||||
protected $richtext_fields = [
|
||||
'description',
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::BRAND, '', $this->richtext_fields);
|
||||
}
|
||||
|
||||
}
|
||||
72
inc/Hura8/Components/Brand/Model/BrandModel.php
Normal file
72
inc/Hura8/Components/Brand/Model/BrandModel.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Brand\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\System\Config;
|
||||
use Hura8\System\Controller\UrlManagerController;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
use Hura8\Interfaces\TableName;
|
||||
|
||||
|
||||
class BrandModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
static $url_type = "brand:detail";
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::BRAND);
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getGroupByFirstLetter() {
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT `letter`, COUNT(*) AS item_count FROM `".$this->tb_entity."` GROUP BY `letter` ORDER BY `letter` ASC "
|
||||
);
|
||||
return $this->db->fetchAll($query);
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition): ?array
|
||||
{
|
||||
/*$condition = array(
|
||||
"letter" => "",
|
||||
);*/
|
||||
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
|
||||
if(isset($filter_condition["letter"]) && strlen($filter_condition["letter"]) == 1){
|
||||
$catCondition[] = " AND `letter` = ? ";
|
||||
$bind_types[] = 's';
|
||||
$bind_values[] = $filter_condition["letter"];
|
||||
}
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
public function getInfoByUrl($brand_index) : ?array
|
||||
{
|
||||
$brand_index = preg_replace("/[^a-z0-9\.\-\_]/i", '', $brand_index);
|
||||
|
||||
$query = $this->db->runQuery("SELECT * FROM `".$this->tb_entity."` WHERE `brand_index` = ? LIMIT 1 ", ['s'], [$brand_index]);
|
||||
if($item_info = $this->db->fetchAssoc($query)){
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\ComboSet\AdminController;
|
||||
|
||||
use Hura8\Components\ComboSet\Controller\bComboSetController;
|
||||
use Hura8\Components\Product\AdminController\AProductController;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
class AComboSetController extends bComboSetController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
}
|
||||
148
inc/Hura8/Components/ComboSet/Controller/bComboSetController.php
Normal file
148
inc/Hura8/Components/ComboSet/Controller/bComboSetController.php
Normal file
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\ComboSet\Controller;
|
||||
|
||||
use Hura8\Components\ComboSet\Model\ComboSetLanguageModel;
|
||||
use Hura8\Components\ComboSet\Model\ComboSetModel;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
class bComboSetController extends aEntityBaseController
|
||||
{
|
||||
/* @var ComboSetModel $objComboSetModel */
|
||||
protected $objComboSetModel;
|
||||
|
||||
/* @var ComboSetLanguageModel $objComboSetLanguageModel */
|
||||
protected $objComboSetLanguageModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objComboSetModel = new ComboSetModel();
|
||||
|
||||
if(!$this->isDefaultLanguage()) {
|
||||
$this->objComboSetLanguageModel = new ComboSetLanguageModel();
|
||||
//$this->objVideoLanguageModel->createTableLang();
|
||||
parent::__construct($this->objComboSetModel, $this->objComboSetLanguageModel);
|
||||
|
||||
}else{
|
||||
parent::__construct($this->objComboSetModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getAllSetIdsForAProduct($product_id)
|
||||
{
|
||||
return $this->objComboSetModel->getAllSetIdsForAProduct($product_id);
|
||||
}
|
||||
|
||||
|
||||
public function getTotalProductUseSet($set_id)
|
||||
{
|
||||
return $this->objComboSetModel->getTotalProductUseSet($set_id);
|
||||
}
|
||||
|
||||
|
||||
public function getListProductUseSet($set_id, $numPerPage)
|
||||
{
|
||||
return $this->objComboSetModel->getListProductUseSet($set_id, $numPerPage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public function getProductListInfoInConfig(array $category) {
|
||||
$product_list_ids = [];
|
||||
foreach ($category as $index => $_category_info) {
|
||||
foreach ($_category_info['suggest_list'] as $_proindex => $_pro_info) {
|
||||
$product_list_ids[] = $_pro_info['real_id'];
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique($product_list_ids);
|
||||
}
|
||||
|
||||
|
||||
public function buildConfig( $category, $product) {
|
||||
|
||||
$group_category = [];
|
||||
|
||||
foreach ($category as $category_index => $_category_info) {
|
||||
$category_product = [];
|
||||
foreach ($product[$category_index] as $product_index => $_product_info) {
|
||||
//$_product_info['price'] = clean_price($_product_info['price']);
|
||||
$category_product[] = $_product_info;
|
||||
}
|
||||
|
||||
$group_category[] = [
|
||||
"title" => $_category_info['title'],
|
||||
//"type" => "category",
|
||||
//"real_id" => $_category_info['real_id'],
|
||||
//"select_type" => $_category_info['select_type'],//checkbox|radio
|
||||
"suggest_list" => $category_product,
|
||||
];
|
||||
}
|
||||
|
||||
return $group_category;
|
||||
}
|
||||
|
||||
|
||||
public function decomposeConfig($config) {
|
||||
$tab = [];
|
||||
$group = [];
|
||||
$category = [];
|
||||
$product = [];
|
||||
|
||||
$group_index = 0;
|
||||
$category_index = 0;
|
||||
$product_index = 0;
|
||||
|
||||
foreach ($config as $tab_index => $tab_info) {
|
||||
//construct tab
|
||||
$tab[$tab_index] = [
|
||||
'title' => $tab_info['title'],
|
||||
];
|
||||
|
||||
//construct group
|
||||
foreach ($tab_info['child'] as $child_group) {
|
||||
$group_index += 1;
|
||||
|
||||
$group[$tab_index][$group_index] = [
|
||||
'title' => $child_group['title'],
|
||||
];
|
||||
|
||||
//construct category
|
||||
foreach ($child_group['child'] as $child_category) {
|
||||
$category_index += 1;
|
||||
|
||||
$category[$group_index][$category_index] = [
|
||||
'title' => $child_category['title'],
|
||||
'real_id' => $child_category['real_id'],
|
||||
'select_type' => $child_category['select_type'],
|
||||
];
|
||||
|
||||
//construct product
|
||||
foreach ($child_category['suggest_list'] as $child_product) {
|
||||
$product_index += 1;
|
||||
|
||||
$product[$category_index][$product_index] = [
|
||||
'title' => $child_product['title'],
|
||||
'real_id' => $child_product['real_id'],
|
||||
'is_default' => $child_product['is_default'],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
"tab" => $tab,
|
||||
"group" => $group,
|
||||
'category' => $category,
|
||||
'product' => $product,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\ComboSet\Model;
|
||||
|
||||
use Hura8\Interfaces\EntityType;
|
||||
use Hura8\System\Model\EntityLanguageModel;
|
||||
|
||||
|
||||
class ComboSetLanguageModel extends EntityLanguageModel
|
||||
{
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct('combo_set');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
165
inc/Hura8/Components/ComboSet/Model/ComboSetModel.php
Normal file
165
inc/Hura8/Components/ComboSet/Model/ComboSetModel.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\ComboSet\Model;
|
||||
|
||||
use Hura8\Components\Product\AdminController\AProductController;
|
||||
use Hura8\Components\Product\Model\ProductSearchModel;
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
|
||||
|
||||
class ComboSetModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
protected $tb_set_product = 'tb_combo_set_product';
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct('combo_set');
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getAllSetIdsForAProduct($product_id)
|
||||
{
|
||||
$query = $this->db->runQuery(
|
||||
" SELECT `set_id` FROM ".$this->tb_set_product." WHERE `product_id` = ? ",
|
||||
['d'], [$product_id]
|
||||
);
|
||||
|
||||
$item_list = array();
|
||||
foreach ( $this->db->fetchAll($query) as $info ) {
|
||||
$item_list[] = $info['set_id'];
|
||||
}
|
||||
|
||||
return $item_list;
|
||||
}
|
||||
|
||||
|
||||
public function getTotalProductUseSet($set_id)
|
||||
{
|
||||
// search
|
||||
$keyword = getRequest("q");
|
||||
if($keyword) {
|
||||
$search = new ProductSearchModel();
|
||||
$match_result = $search->find($keyword);
|
||||
$catCondition = (sizeof($match_result) > 0) ? " AND `product_id` IN (".join(",", $match_result).") " : " AND `product_id` = -1 ";
|
||||
|
||||
$query = $this->db->runQuery("
|
||||
SELECT COUNT(product_id) AS total_product
|
||||
FROM ".$this->tb_set_product."
|
||||
WHERE `set_id` = ? " . $catCondition ."
|
||||
", ['d'], [$set_id]);
|
||||
|
||||
if ($info = $this->db->fetchAssoc($query)) {
|
||||
return $info['total_product'];
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
$set_info = $this->getInfo($set_id);
|
||||
|
||||
return $set_info['product_count'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getListProductUseSet($set_id, $numPerPage)
|
||||
{
|
||||
$page = getPageId();
|
||||
|
||||
// search
|
||||
$catCondition = "";
|
||||
$keyword = getRequest("q");
|
||||
if($keyword) {
|
||||
$search = new ProductSearchModel();
|
||||
$match_result = $search->find($keyword);
|
||||
$catCondition = (sizeof($match_result) > 0) ? " AND `product_id` IN (".join(",", $match_result).") " : " AND `product_id` = -1 ";
|
||||
}
|
||||
|
||||
$query = $this->db->runQuery("
|
||||
SELECT `product_id`
|
||||
FROM ".$this->tb_set_product."
|
||||
WHERE `set_id` = ? " . $catCondition ."
|
||||
ORDER BY id desc
|
||||
LIMIT ".($page - 1) * $numPerPage .", ".$numPerPage."
|
||||
", ['d'], [$set_id]);
|
||||
|
||||
$item_list = array();
|
||||
foreach ( $this->db->fetchAll($query) as $info ) {
|
||||
$item_list[] = $info['product_id'];
|
||||
}
|
||||
|
||||
return $item_list;
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryOrderBy(string $sort_by = "new")
|
||||
{
|
||||
$order_condition = "";
|
||||
|
||||
switch ($sort_by) {
|
||||
case "ordering";
|
||||
$order_condition = " `ordering` desc ";
|
||||
break;
|
||||
case "old";
|
||||
$order_condition = " id asc ";
|
||||
break;
|
||||
case "last_show_time";
|
||||
$order_condition = " last_show_time ASC ";
|
||||
break;
|
||||
}
|
||||
|
||||
return $order_condition;
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInfo(array $item_info) : array
|
||||
{
|
||||
$from_time = $item_info['from_time'];
|
||||
$from_time_date = ($from_time > 0) ? date("d-m-Y", $from_time) : '';
|
||||
$from_time_minute = ($from_time > 0) ? date("H:i", $from_time) : "00:00";
|
||||
|
||||
$to_time = $item_info['to_time'];
|
||||
$to_time_date = ($to_time > 0) ? date("d-m-Y", $to_time) : '';
|
||||
$to_time_minute = ($to_time > 0) ? date("H:i", $to_time) : "00:00";
|
||||
|
||||
$item_info['from_time_date'] = $from_time_date;
|
||||
$item_info['from_time_minute'] = $from_time_minute;
|
||||
$item_info['to_time_date'] = $to_time_date;
|
||||
$item_info['to_time_minute'] = $to_time_minute;
|
||||
|
||||
return $item_info;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///---------
|
||||
///
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
|
||||
$catCondition = "";
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
if(isset($filter_condition["product_id"]) && $filter_condition["product_id"]){
|
||||
$catCondition .= " AND `id` IN ( SELECT `set_id` FROM ".$this->tb_set_product." WHERE `product_id` = ? ) ";
|
||||
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = $filter_condition['product_id'];
|
||||
}
|
||||
|
||||
return [$catCondition, $bind_types, $bind_values];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\ConfigGroup\AdminController;
|
||||
|
||||
use Hura8\Components\ConfigGroup\Controller\bConfigGroupController;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
class AConfigGroupController extends bConfigGroupController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
public function deleteAttribute($id, $group_id = 0) {
|
||||
$this->objConfigGroupModel->deleteAttribute($id, $group_id);
|
||||
}
|
||||
|
||||
|
||||
public function updateAttribute($id, $info) {
|
||||
$this->objConfigGroupModel->updateAttribute($id, $info) ;
|
||||
}
|
||||
|
||||
|
||||
public function createAttribute($info) {
|
||||
return $this->objConfigGroupModel->createAttribute($info) ;
|
||||
}
|
||||
|
||||
|
||||
public function createAttributeValue($info) {
|
||||
$this->objConfigGroupModel->createAttributeValue($info);
|
||||
}
|
||||
|
||||
|
||||
public function deleteAttributeValue($id) {
|
||||
$this->objConfigGroupModel->deleteAttributeValue($id);
|
||||
}
|
||||
|
||||
|
||||
public function updateAttributeValue($id, $info) {
|
||||
$this->objConfigGroupModel->updateAttributeValue($id, $info);
|
||||
}
|
||||
|
||||
|
||||
public function createProduct($product_id, $group_id, array $attribute_config) {
|
||||
$this->objConfigGroupModel->createProduct($product_id, $group_id, $attribute_config);
|
||||
}
|
||||
|
||||
|
||||
public function deleteProduct($product_id, $group_id) {
|
||||
$this->objConfigGroupModel->deleteProduct($product_id, $group_id);
|
||||
}
|
||||
|
||||
|
||||
public function updateProduct($product_id, $group_id, array $attribute_config, $product_name_in_group = '') {
|
||||
|
||||
return $this->objConfigGroupModel->updateProduct($product_id, $group_id, $attribute_config, $product_name_in_group);
|
||||
}
|
||||
|
||||
|
||||
public function getProductInGroup($group_id){
|
||||
return $this->objConfigGroupModel->getProductInGroup($group_id);
|
||||
}
|
||||
|
||||
|
||||
public function getGroupConfig($item_id) {
|
||||
return $this->objConfigGroupModel->getGroupConfig($item_id);
|
||||
}
|
||||
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\ConfigGroup\Controller;
|
||||
|
||||
use Hura8\Components\ConfigGroup\Model\ConfigGroupModel;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
|
||||
class bConfigGroupController extends aEntityBaseController
|
||||
{
|
||||
|
||||
/* @var ConfigGroupModel $objConfigGroupModel */
|
||||
protected $objConfigGroupModel;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objConfigGroupModel = new ConfigGroupModel();
|
||||
parent::__construct($this->objConfigGroupModel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
500
inc/Hura8/Components/ConfigGroup/Model/ConfigGroupModel.php
Normal file
500
inc/Hura8/Components/ConfigGroup/Model/ConfigGroupModel.php
Normal file
@@ -0,0 +1,500 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\ConfigGroup\Model;
|
||||
|
||||
|
||||
use Hura8\Components\Product\Model\ProductModel;
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
|
||||
|
||||
class ConfigGroupModel extends aEntityBaseModel
|
||||
{
|
||||
|
||||
protected $tb_config_group = "";
|
||||
protected $tb_config_group_product = "tb_config_group_product";
|
||||
protected $tb_config_group_product_cache = "tb_config_group_product_cache";
|
||||
protected $tb_config_group_attribute = "tb_config_group_attribute";
|
||||
protected $tb_config_group_attribute_value = "tb_config_group_attribute_value";
|
||||
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct('config_group');
|
||||
$this->tb_config_group = $this->tb_entity;
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function updateGroupAttributeCount($group_id) {
|
||||
$this->db->runQuery(
|
||||
"UPDATE `".$this->tb_config_group."` SET
|
||||
`attribute_count` = ( SELECT COUNT(*) FROM `".$this->tb_config_group_attribute."` WHERE `group_id` = ? )
|
||||
WHERE `id` = ? LIMIT 1 ",
|
||||
['d', 'd'], [ $group_id, $group_id ]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected function updateGroupProductCount($group_id) {
|
||||
$this->db->runQuery(
|
||||
"UPDATE `".$this->tb_config_group."` SET
|
||||
`item_count` = ( SELECT COUNT(*) FROM `".$this->tb_config_group_product."` WHERE `group_id` = ? )
|
||||
WHERE `id` = ? LIMIT 1 ",
|
||||
['d', 'd'], [ $group_id, $group_id ]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//attribute value
|
||||
public function deleteAttributeValue($att_value_id) {
|
||||
|
||||
$attr_id = 0;
|
||||
$query = $this->db->runQuery("SELECT `attr_id` FROM `".$this->tb_config_group_attribute_value."` WHERE `id` = ? LIMIT 1 ", ['d'], [ $att_value_id ]);
|
||||
if ($info = $this->db->fetchAssoc($query)) {
|
||||
$attr_id = $info['attr_id'];
|
||||
}
|
||||
|
||||
$group_id = $this->getGroupIdFromAttribute($attr_id);
|
||||
|
||||
$this->db->runQuery("DELETE FROM `".$this->tb_config_group_attribute_value."` WHERE `id` = ? LIMIT 1 ", ['d'], [ $att_value_id ]);
|
||||
|
||||
$this->resetProductConfigCache($group_id);
|
||||
|
||||
$this->updateAttributeValueCount($attr_id);
|
||||
}
|
||||
|
||||
|
||||
protected function updateAttributeValueCount($attr_id) {
|
||||
$this->db->runQuery(
|
||||
"UPDATE `".$this->tb_config_group_attribute."` SET
|
||||
`value_count` = ( SELECT COUNT(*) FROM `".$this->tb_config_group_attribute_value."` WHERE `attr_id` = ? )
|
||||
WHERE `id` = ? LIMIT 1 ",
|
||||
['d', 'd'],
|
||||
[$attr_id, $attr_id ]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function updateAttributeValue($id, $info) {
|
||||
|
||||
$updated_info = $info;
|
||||
|
||||
$updated_info['last_update'] = CURRENT_TIME;
|
||||
$updated_info['last_update_by'] = ADMIN_NAME;
|
||||
|
||||
$this->db->update(
|
||||
$this->tb_config_group_attribute_value,
|
||||
$updated_info,
|
||||
[
|
||||
"id" => $id,
|
||||
]
|
||||
);
|
||||
|
||||
$group_id = $this->getGroupIdFromAttributeValue($id);
|
||||
$this->resetProductConfigCache($group_id);
|
||||
}
|
||||
|
||||
|
||||
public function createAttributeValue($info) {
|
||||
$updated_info = $info;
|
||||
|
||||
$updated_info['create_time'] = CURRENT_TIME;
|
||||
$updated_info['create_by'] = ADMIN_NAME;
|
||||
$updated_info['last_update'] = CURRENT_TIME;
|
||||
$updated_info['last_update_by'] = ADMIN_NAME;
|
||||
|
||||
$this->db->insert($this->tb_config_group_attribute_value, $updated_info );
|
||||
|
||||
$group_id = $this->getGroupIdFromAttribute($info['attr_id']);
|
||||
$this->resetProductConfigCache($group_id);
|
||||
|
||||
$this->updateAttributeValueCount($info['attr_id']);
|
||||
}
|
||||
|
||||
//attribute
|
||||
public function deleteAttribute($id, $group_id = 0) {
|
||||
if(!$group_id) $group_id = $this->getGroupIdFromAttribute($id);
|
||||
$this->db->runQuery("DELETE FROM `".$this->tb_config_group_attribute."` WHERE `id` = ? LIMIT 1 ", ['d'], [ $id ]);
|
||||
$this->db->runQuery("DELETE FROM `".$this->tb_config_group_attribute_value."` WHERE `attr_id` = ? LIMIT 1 ", ['d'], [ $id ]);
|
||||
|
||||
$this->updateGroupAttributeCount($group_id);
|
||||
|
||||
//todo: update for product attribute_config ?
|
||||
$this->resetProductConfigCache($group_id);
|
||||
}
|
||||
|
||||
public function updateAttribute($id, $info) {
|
||||
|
||||
$updated_info = $info;
|
||||
|
||||
$updated_info['last_update'] = CURRENT_TIME;
|
||||
$updated_info['last_update_by'] = ADMIN_NAME;
|
||||
|
||||
$this->db->update(
|
||||
$this->tb_config_group_attribute,
|
||||
$updated_info,
|
||||
[
|
||||
'id' => $id,
|
||||
]
|
||||
);
|
||||
|
||||
$group_id = $this->getGroupIdFromAttribute($id);
|
||||
$this->resetProductConfigCache($group_id);
|
||||
}
|
||||
|
||||
public function createAttribute($info) {
|
||||
|
||||
$updated_info = $info;
|
||||
|
||||
$updated_info['create_time'] = CURRENT_TIME;
|
||||
$updated_info['create_by'] = ADMIN_NAME;
|
||||
$updated_info['last_update'] = CURRENT_TIME;
|
||||
$updated_info['last_update_by'] = ADMIN_NAME;
|
||||
|
||||
$this->db->insert($this->tb_config_group_attribute, $updated_info );
|
||||
|
||||
$this->resetProductConfigCache($info['group_id']);
|
||||
|
||||
$this->updateGroupAttributeCount($info['group_id']);
|
||||
|
||||
return $this->db->get_insert_id();
|
||||
}
|
||||
|
||||
private function getGroupIdFromAttributeValue($att_value_id) {
|
||||
$attr_id = 0;
|
||||
$query = $this->db->runQuery("SELECT `attr_id` FROM `".$this->tb_config_group_attribute_value."` WHERE `id` = ? LIMIT 1 ", ['d'], [ $att_value_id ]);
|
||||
if ($info = $this->db->fetchAssoc($query)) {
|
||||
$attr_id = $info['attr_id'];
|
||||
}
|
||||
|
||||
return $this->getGroupIdFromAttribute($attr_id);
|
||||
}
|
||||
|
||||
private function getGroupIdFromAttribute($attr_id) {
|
||||
$group_id = 0;
|
||||
$query = $this->db->runQuery("SELECT `group_id` FROM `".$this->tb_config_group_attribute."` WHERE `id` = ? LIMIT 1 ", ['d'], [ $attr_id ]);
|
||||
if ($info = $this->db->fetchAssoc($query)) {
|
||||
$group_id = $info['group_id'];
|
||||
}
|
||||
|
||||
return $group_id;
|
||||
}
|
||||
|
||||
//create or update product in a group
|
||||
public function createProduct($product_id, $group_id, array $attribute_config) {
|
||||
if($this->isProductInGroup($product_id, $group_id)) {
|
||||
|
||||
$this->updateProduct($product_id, $group_id, $attribute_config);
|
||||
|
||||
}else {
|
||||
|
||||
$updated_info = [
|
||||
"product_id" => $product_id,
|
||||
"group_id" => $group_id,
|
||||
"attribute_config" => json_encode($attribute_config),
|
||||
|
||||
"create_time" => CURRENT_TIME,
|
||||
"create_by" => ADMIN_NAME,
|
||||
"last_update" => CURRENT_TIME,
|
||||
"last_update_by" => ADMIN_NAME,
|
||||
];
|
||||
|
||||
$this->db->insert($this->tb_config_group_product, $updated_info );
|
||||
|
||||
$this->updateGroupProductCount($group_id);
|
||||
|
||||
}
|
||||
|
||||
$this->resetProductConfigCache($group_id);
|
||||
}
|
||||
|
||||
public function deleteProduct($product_id, $group_id) {
|
||||
$this->db->runQuery(
|
||||
"DELETE FROM `".$this->tb_config_group_product."` WHERE `product_id` = ? AND `group_id` = ? LIMIT 1 ",
|
||||
['d', 'd'], [ $product_id, $group_id ]
|
||||
);
|
||||
|
||||
$this->deleteProductConfigCache($product_id);
|
||||
|
||||
$this->updateGroupProductCount($group_id);
|
||||
}
|
||||
|
||||
public function updateProduct($product_id, $group_id, array $attribute_config, $product_name_in_group = '') {
|
||||
|
||||
$this->db->update(
|
||||
$this->tb_config_group_product,
|
||||
[
|
||||
"attribute_config" => json_encode($attribute_config),
|
||||
"product_name_in_group" => substr($product_name_in_group, 0, 140),
|
||||
"last_update" => CURRENT_TIME,
|
||||
"last_update_by" => ADMIN_NAME,
|
||||
],
|
||||
[
|
||||
"product_id" => $product_id,
|
||||
"group_id" => $group_id,
|
||||
]
|
||||
);
|
||||
|
||||
$this->resetProductConfigCache($group_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//we want to reset all caches for products in a group
|
||||
//we need to do this when we make changes to group's attributes, or create new products/ update product in group
|
||||
protected function resetProductConfigCache($group_id) {
|
||||
$query = $this->db->runQuery("SELECT `product_id` FROM `".$this->tb_config_group_product."` WHERE `group_id` = ? ", ['d'], [$group_id]) ;
|
||||
$product_list = array();
|
||||
foreach( $this->db->fetchAll($query) as $item ){
|
||||
$product_list[] = $item['product_id'];
|
||||
}
|
||||
|
||||
if(sizeof($product_list)) {
|
||||
$this->db->query("UPDATE `".$this->tb_config_group_product_cache."` SET
|
||||
`value` = NULL
|
||||
WHERE `product_id` IN (".join(",", $product_list).") ") ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function deleteProductConfigCache($product_id) {
|
||||
$this->db->runQuery("DELETE FROM `".$this->tb_config_group_product_cache."` WHERE `product_id` = ? LIMIT 1 ", ['d'], [$product_id]) ;
|
||||
}
|
||||
|
||||
|
||||
public function saveProductConfigCache($product_id, $value) {
|
||||
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT `product_id` FROM `".$this->tb_config_group_product_cache."` WHERE `product_id` = ? LIMIT 1 ",
|
||||
['d'], [$product_id]
|
||||
) ;
|
||||
|
||||
if($this->db->fetchAssoc($query)){
|
||||
$this->db->runQuery(
|
||||
"UPDATE `".$this->tb_config_group_product_cache."` SET
|
||||
`value` = '".$this->db->escape(json_encode($value))."'
|
||||
WHERE `product_id` = ? LIMIT 1 ",
|
||||
['d'], [$product_id]
|
||||
) ;
|
||||
}else{
|
||||
$this->db->runQuery("INSERT INTO `".$this->tb_config_group_product_cache."` (`product_id`, `value`)
|
||||
VALUES ('". (int) $product_id."', '".$this->db->escape(json_encode($value))."') ") ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getProductConfigCache($product_id) {
|
||||
$query = $this->db->runQuery("SELECT `value` FROM `".$this->tb_config_group_product_cache."` WHERE `product_id` = ? LIMIT 1 ", ['d'], [$product_id]) ;
|
||||
if($item_info = $this->db->fetchAssoc($query)){
|
||||
return ($item_info['value']) ? \json_decode($item_info['value'], true) : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//get all group config
|
||||
public function getGroupConfig($group_id) {
|
||||
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT
|
||||
a.id AS attribute_id ,
|
||||
a.name AS attribute_name ,
|
||||
a.ordering AS attr_ordering ,
|
||||
v.id AS value_id ,
|
||||
v.name AS value_name ,
|
||||
v.image AS image ,
|
||||
v.color_code AS color ,
|
||||
v.ordering ,
|
||||
v.description AS description
|
||||
FROM `".$this->tb_config_group_attribute."` a
|
||||
LEFT JOIN `".$this->tb_config_group_attribute_value."` v ON a.id = v.attr_id
|
||||
WHERE a.group_id = ?
|
||||
ORDER BY attr_ordering DESC, `ordering` DESC
|
||||
",
|
||||
['d'], [$group_id]
|
||||
);
|
||||
|
||||
$group_attribute = array();
|
||||
foreach ( $this->db->fetchAll($query) as $info ) {
|
||||
if(!isset($group_attribute[$info['attribute_id']])) {
|
||||
$group_attribute[$info['attribute_id']] = array(
|
||||
'id' => $info['attribute_id'],
|
||||
'name' => $info['attribute_name'],
|
||||
'ordering' => $info['attr_ordering'],
|
||||
'list' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
if($info['value_id']) {
|
||||
$group_attribute[$info['attribute_id']]['list'][] = array(
|
||||
'id' => $info['value_id'],
|
||||
'name' => $info['value_name'],
|
||||
'image' => $info['image'],
|
||||
'color' => $info['color'],
|
||||
'ordering' => $info['ordering'],
|
||||
'description' => $info['description'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $group_attribute;
|
||||
}
|
||||
|
||||
|
||||
public function getProductConfigGroupId($product_id) {
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT `group_id` FROM `".$this->tb_config_group_product."` WHERE `product_id` = ? LIMIT 1 ",
|
||||
['d'], [$product_id]
|
||||
) ;
|
||||
|
||||
if($item_info = $this->db->fetchAssoc($query)){
|
||||
return $item_info['group_id'];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public function getProductInGroup($group_id){
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT `product_id`, `product_name_in_group`, `attribute_config`
|
||||
FROM `".$this->tb_config_group_product."`
|
||||
WHERE `group_id` = ?
|
||||
",
|
||||
['d'], [$group_id]
|
||||
);
|
||||
|
||||
$product_list = array();
|
||||
$product_ids = array();
|
||||
|
||||
foreach ( $this->db->fetchAll($query) as $info ) {
|
||||
$product_ids[] = $info['product_id'];
|
||||
|
||||
$product_list[$info['product_id']] = array(
|
||||
"id" => $info['product_id'],
|
||||
"name" => "",
|
||||
"product_name_in_group" => $info['product_name_in_group'],
|
||||
"attribute" => \json_decode($info['attribute_config'], true),
|
||||
"url" => "",
|
||||
"sku" => "",
|
||||
"price" => 0,
|
||||
"image" => "",
|
||||
"status" => "",
|
||||
);
|
||||
}
|
||||
|
||||
//find product urls
|
||||
if(sizeof($product_ids)) {
|
||||
$objProductModel = new ProductModel();
|
||||
$product_list_info = $objProductModel->getListByIds($product_ids);
|
||||
|
||||
// debug_var($product_list_info);
|
||||
// update $product_list
|
||||
foreach ($product_list as $_pro_id => $_info) {
|
||||
$_pro_info = $product_list_info[$_pro_id] ?? null;
|
||||
if($_pro_info) {
|
||||
$product_list[$_pro_id]['name'] = $_pro_info['title'];
|
||||
$product_list[$_pro_id]['price'] = $_pro_info['price'];
|
||||
$product_list[$_pro_id]['sku'] = $_pro_info['sku'];
|
||||
$product_list[$_pro_id]['image'] = $_pro_info['thumbnail'];
|
||||
$product_list[$_pro_id]['url'] = $_pro_info['request_path'];
|
||||
$product_list[$_pro_id]['status'] = $_pro_info['status'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $product_list;
|
||||
}
|
||||
|
||||
|
||||
protected function isProductInGroup($product_id, $group_id) {
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT * FROM `".$this->tb_config_group_product."` WHERE `product_id` = ? AND `group_id` = ? LIMIT 1 ",
|
||||
['d', 'd'],
|
||||
[$product_id, $group_id]
|
||||
) ;
|
||||
|
||||
return ($this->db->fetchAssoc($query));
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
/*$condition = array(
|
||||
"q" => "",
|
||||
"numPerPage" => 20,
|
||||
"order_by" => '',
|
||||
);*/
|
||||
|
||||
$catCondition = "";
|
||||
|
||||
return [
|
||||
$catCondition,
|
||||
[],
|
||||
[]
|
||||
];
|
||||
}
|
||||
|
||||
protected function beforeCreateItem(array $input_info): AppResponse
|
||||
{
|
||||
$info = $input_info;
|
||||
|
||||
$info['create_time'] = CURRENT_TIME;
|
||||
$info['create_by'] = ADMIN_NAME;
|
||||
$info['last_update'] = CURRENT_TIME;
|
||||
$info['last_update_by'] = ADMIN_NAME;
|
||||
|
||||
return new AppResponse('ok', null, $info);
|
||||
}
|
||||
|
||||
protected function afterCreateItem($new_item_id, $new_item_info)
|
||||
{
|
||||
// TODO: Implement afterCreateItem() method.
|
||||
}
|
||||
|
||||
protected function beforeUpdateItem($item_id, $current_item_info, $new_input_info):AppResponse
|
||||
{
|
||||
$info = $new_input_info;
|
||||
|
||||
$info['last_update'] = CURRENT_TIME;
|
||||
$info['last_update_by'] = ADMIN_NAME;
|
||||
|
||||
return new AppResponse('ok', null, $info);
|
||||
}
|
||||
|
||||
protected function afterUpdateItem($item_id, $old_item_info, $new_item_info)
|
||||
{
|
||||
// TODO: Implement afterUpdateItem() method.
|
||||
}
|
||||
|
||||
protected function beforeDeleteItem($item_id, $item_info):AppResponse
|
||||
{
|
||||
return new AppResponse('ok' );
|
||||
}
|
||||
|
||||
protected function afterDeleteItem($item_id, $item_info)
|
||||
{
|
||||
|
||||
$query = $this->db->runQuery("SELECT `id` FROM `".$this->tb_config_group_attribute."` WHERE `group_id` = ? ", ['d'], [$item_id]);
|
||||
|
||||
foreach ( $this->db->fetchAll($query) as $info ) {
|
||||
$this->deleteAttribute($info['id'], $item_id);
|
||||
}
|
||||
|
||||
$this->db->runQuery(
|
||||
"DELETE FROM `".$this->tb_config_group_product_cache."` WHERE `product_id` IN (SELECT product_id FROM config_group_product WHERE `group_id` = ? ) ",
|
||||
['d'], [$item_id]
|
||||
) ;
|
||||
|
||||
$this->db->runQuery("DELETE FROM `".$this->tb_config_group_product."` WHERE `group_id` = ? ", ['d'], [$item_id]) ;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Customer\AdminController;
|
||||
|
||||
use Hura8\Components\Customer\Controller\bCustomerController;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
class ACustomerController extends bCustomerController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
// TODO: Implement deleteFileBeforeDeleteItem() method.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Customer\AdminController;
|
||||
|
||||
use Hura8\Components\Customer\Model\CustomerGroupModel;
|
||||
use Hura8\Components\Province\AdminController\AProvinceController;
|
||||
use Hura8\System\Controller\aAdminEntityBaseController;
|
||||
|
||||
|
||||
class ACustomerGroupController extends aAdminEntityBaseController
|
||||
{
|
||||
/* @var CustomerGroupModel $objCustomerGroupModel */
|
||||
protected $objCustomerGroupModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objCustomerGroupModel = new CustomerGroupModel();
|
||||
parent::__construct($this->objCustomerGroupModel);
|
||||
}
|
||||
|
||||
|
||||
public function getAllGroup() {
|
||||
return $this->objCustomerGroupModel->getList(["numPerPage" => 1000]);
|
||||
}
|
||||
|
||||
|
||||
public function removeCustomer($customer_id, $group_id)
|
||||
{
|
||||
return $this->objCustomerGroupModel->removeCustomer($customer_id, $group_id);
|
||||
}
|
||||
|
||||
|
||||
public function addCustomer($customer_id, $group_id)
|
||||
{
|
||||
return $this->objCustomerGroupModel->addCustomer($customer_id, $group_id);
|
||||
}
|
||||
|
||||
|
||||
public function getTotalCustomer($group_id, array $condition = [])
|
||||
{
|
||||
return $this->objCustomerGroupModel->getTotalCustomer($group_id, $condition);
|
||||
}
|
||||
|
||||
|
||||
public function getListCustomer($group_id, array $condition = []) {
|
||||
|
||||
$objProvinceController = new AProvinceController();
|
||||
|
||||
return array_map(function ($item) use ($objProvinceController){
|
||||
|
||||
$item['province_name'] = $objProvinceController->getProvinceName($item['province']);
|
||||
|
||||
return $item;
|
||||
|
||||
}, $this->objCustomerGroupModel->getListCustomer($group_id, $condition));
|
||||
}
|
||||
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
// TODO: Implement deleteFileBeforeDeleteItem() method.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Customer\AdminController;
|
||||
|
||||
use Hura8\Components\Customer\Controller\bCustomerLoyaltyController;
|
||||
|
||||
class ACustomerLoyaltyController extends bCustomerLoyaltyController {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Customer\Controller;
|
||||
|
||||
use Hura8\Components\Customer\Model\CustomerModel;
|
||||
use Hura8\Components\Province\AdminController\AProvinceController;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
class bCustomerController extends aEntityBaseController
|
||||
{
|
||||
|
||||
/* @var CustomerModel $objCustomerModel */
|
||||
protected $objCustomerModel;
|
||||
|
||||
/* @var AProvinceController $objProvinceController */
|
||||
protected $objProvinceController;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objCustomerModel = new CustomerModel();
|
||||
$this->objProvinceController = new AProvinceController();
|
||||
parent::__construct($this->objCustomerModel);
|
||||
}
|
||||
|
||||
|
||||
public function formatItemInList(array $item_info)
|
||||
{
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
|
||||
public function formatItemInfo(array $item_info)
|
||||
{
|
||||
$info = $item_info;
|
||||
$info['province_name'] = $this->objProvinceController->getProvinceName($item_info['province']);
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Customer\Controller;
|
||||
|
||||
use ClientExtend\UserLoyaltyPointCalculation;
|
||||
use Hura8\Components\Customer\Model\CustomerLoyaltyModel;
|
||||
|
||||
|
||||
class bCustomerLoyaltyController
|
||||
{
|
||||
|
||||
public static $POINT_NAME = 'điểm';
|
||||
|
||||
protected $point_setting = [];
|
||||
protected $point_setting_config_file = ROOT_DIR . "/config/build/customer_point.php";
|
||||
|
||||
protected $level_setting = [];
|
||||
protected $level_setting_config_file = ROOT_DIR . "/config/client/customer_level.php";
|
||||
|
||||
protected $level_by = '';// point|total_purchase_value as set by constant CHANGE_CUSTOMER_LEVEL_BY
|
||||
|
||||
/* @var $objUserLoyaltyPointCalculation UserLoyaltyPointCalculation */
|
||||
protected $objUserLoyaltyPointCalculation;
|
||||
|
||||
/* @var CustomerLoyaltyModel $objCustomerLoyaltyModel */
|
||||
protected $objCustomerLoyaltyModel;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objCustomerLoyaltyModel = new CustomerLoyaltyModel();
|
||||
|
||||
// import settings
|
||||
//$new_info_file = "../config/build/customer_point.php" ;
|
||||
//$config_file = ROOT_DIR . "/config/build/customer_point.php";
|
||||
if(@file_exists($this->point_setting_config_file)) {
|
||||
$this->point_setting = include $this->point_setting_config_file;
|
||||
}
|
||||
|
||||
// customer level based on point gain
|
||||
if( defined("ENABLE_CUSTOMER_POINT") && ENABLE_CUSTOMER_POINT ) {
|
||||
if(@file_exists($this->level_setting_config_file)) {
|
||||
$this->level_setting = include $this->level_setting_config_file;
|
||||
}
|
||||
}
|
||||
|
||||
// default is point
|
||||
$this->level_by = (defined('CHANGE_CUSTOMER_LEVEL_BY')) ? CHANGE_CUSTOMER_LEVEL_BY : 'point';
|
||||
|
||||
$this->objUserLoyaltyPointCalculation = new UserLoyaltyPointCalculation($this->point_setting);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function getPointSettingConfigFile() {
|
||||
return $this->point_setting_config_file;
|
||||
}
|
||||
|
||||
public function getPointSetting() {
|
||||
return $this->point_setting;
|
||||
}
|
||||
|
||||
public function getLevelSetting(){
|
||||
return $this->level_setting;
|
||||
}
|
||||
|
||||
// show estimate cart point
|
||||
public function getEstimateCartPoint($cart_value){
|
||||
$conversion_rate = (isset($this->point_setting['reward']['buy']['rate'])) ? $this->point_setting['reward']['buy']['rate'] : 0;
|
||||
return ($conversion_rate) ? round($cart_value / $conversion_rate) : 0;
|
||||
}
|
||||
|
||||
public function getUserPoint($user_id, array $condition, $return_type)
|
||||
{
|
||||
return $this->objCustomerLoyaltyModel->getUserPoint($user_id, $condition, $return_type);
|
||||
}
|
||||
|
||||
// remove rewarded point i.e. reward for successfull order and now order is marked canceled
|
||||
public function reclaimRewardedPoint($user_id, $activity_type_tracker){
|
||||
// todo:
|
||||
}
|
||||
|
||||
public function usePoint($user_id, $use_point, $activity_type, $activity_type_tracker, $reason = '', $point_args = ['order_value' => 0]){
|
||||
// no user or no config
|
||||
if(!$user_id || !ENABLE_CUSTOMER_POINT) return false;
|
||||
|
||||
$result = $this->objUserLoyaltyPointCalculation->calculateUsePoint($user_id, $use_point, $activity_type, $activity_type_tracker, $point_args);
|
||||
|
||||
$this->pointOp('use', $user_id, $result['use_point'], $activity_type, $activity_type_tracker, $reason);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function rewardPoint($user_id, $activity_type, $activity_type_tracker, $reason = '', $point_args = ['order_id' => 0]){
|
||||
// no user or no config
|
||||
if(!$user_id || !ENABLE_CUSTOMER_POINT) return false;
|
||||
|
||||
$point = $this->objUserLoyaltyPointCalculation->calculateRewardPoint($user_id, $activity_type, $activity_type_tracker, $point_args);
|
||||
|
||||
$this->pointOp('reward', $user_id, $point, $activity_type, $activity_type_tracker, $reason);
|
||||
|
||||
return $point;
|
||||
}
|
||||
|
||||
// $operation: reward|use
|
||||
// $change_point: positive (reward) or nagative (use)
|
||||
protected function pointOp($operation, $user_id, $change_point, $activity_type, $activity_type_tracker, $reason = '') {
|
||||
|
||||
if(!$change_point) return false;
|
||||
|
||||
$reason_prefix = ($operation == 'use') ? 'Sử dụng' : 'Thưởng';
|
||||
if($activity_type == 'return') $reason_prefix = 'Hoàn lại';
|
||||
$full_reason = join(" ", [$reason_prefix, $change_point, static::$POINT_NAME, ":", $reason]);
|
||||
|
||||
if($operation == 'use') $change_point = -1 * $change_point;
|
||||
|
||||
// security: hash the row to avoid editing point directly in the database
|
||||
$hash_value = sha1(join(".", [
|
||||
$operation,
|
||||
$user_id,
|
||||
$change_point,
|
||||
$activity_type,
|
||||
$activity_type_tracker,
|
||||
CURRENT_TIME,
|
||||
'ass@ss'
|
||||
]));
|
||||
|
||||
$new_id = $this->db->insert(
|
||||
$this->tb_point ,
|
||||
[
|
||||
'customer_id' => $user_id ,
|
||||
'activity_type' => $activity_type,
|
||||
'activity_type_tracker' => $activity_type_tracker ,
|
||||
'operation' => $operation,
|
||||
'point' => $change_point,
|
||||
'create_time' => CURRENT_TIME,
|
||||
'reason' => substr($full_reason, 0, 200),
|
||||
'referer_url' => substr(REFERER_URL, 0, 150) ,
|
||||
'hash_value' => $hash_value ,
|
||||
]
|
||||
);
|
||||
|
||||
//update user reward balance
|
||||
if($new_id) {
|
||||
$this->updateStat($user_id, $change_point);
|
||||
}
|
||||
|
||||
return $new_id;
|
||||
}
|
||||
|
||||
protected function updateStat($user_id, $changed_point, $changed_order_value=0) {
|
||||
return $this->objCustomerLoyaltyModel->updateStat($user_id, $changed_point, $changed_order_value);
|
||||
}
|
||||
|
||||
private function calculateLevelByPoint($point) {
|
||||
//if the point in between -> return the lowest level
|
||||
$all_level = array_keys($this->level_setting);
|
||||
|
||||
foreach ( $all_level as $level) {
|
||||
$next_level = $level + 1;
|
||||
if(!in_array($next_level, $all_level)) $next_level = 0;
|
||||
|
||||
if($next_level) {
|
||||
if( $point >= $this->level_setting[$level]["point_require"]
|
||||
&& $point < $this->level_setting[$next_level]["point_require"] ) {
|
||||
return $level;
|
||||
}
|
||||
}else{
|
||||
if($point >= $this->level_setting[$level]["point_require"]) {
|
||||
return $level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function calculateLevelByOrderValue($aggregate_purchase_value = 0) {
|
||||
|
||||
//if the point in between -> return the lowest level
|
||||
$all_level = array_keys($this->level_setting);
|
||||
|
||||
//tinh hang thanh vien theo so tien tich luy
|
||||
foreach ( $all_level as $level ) {
|
||||
$next_level = $level + 1;
|
||||
if(!in_array($next_level, $all_level)) $next_level = 0;
|
||||
|
||||
if($next_level) {
|
||||
if( $aggregate_purchase_value >= $this->level_setting[$level]["total_order_value"] &&
|
||||
$aggregate_purchase_value < $this->level_setting[$next_level]["total_order_value"]
|
||||
) {
|
||||
return $level;
|
||||
}
|
||||
}else{
|
||||
if( $aggregate_purchase_value >= $this->level_setting[$level]["total_order_value"]) {
|
||||
return $level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
79
inc/Hura8/Components/Customer/Model/CustomerAuthModel.php
Normal file
79
inc/Hura8/Components/Customer/Model/CustomerAuthModel.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Customer\Model;
|
||||
|
||||
use Hura8\System\Model\AuthModel;
|
||||
|
||||
|
||||
class CustomerAuthModel extends AuthModel
|
||||
{
|
||||
|
||||
private $tb_customer_login = "tb_customer_login";
|
||||
private $tb_customer_access_code = "tb_customer_access_code";
|
||||
private $tb_customer_login_log = "tb_customer_login_log";
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct($this->tb_customer_login, $this->tb_customer_access_code);
|
||||
}
|
||||
|
||||
|
||||
public function getLoginListByIds(array $staff_ids) {
|
||||
if(!sizeof($staff_ids)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
list($parameterized_ids, $bind_types) = create_bind_sql_parameter_from_value_list($staff_ids, 'int');
|
||||
|
||||
$bind_values = $staff_ids;
|
||||
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT `user_id`, `last_login_time`, `last_login_ip`, `last_login_device`, `last_login_browser`
|
||||
FROM ".$this->tb_customer_login."
|
||||
WHERE `user_id` IN (".$parameterized_ids.") ",
|
||||
$bind_types,
|
||||
$bind_values
|
||||
);
|
||||
|
||||
$item_list = [];
|
||||
foreach ($this->db->fetchAll($query) as $item) {
|
||||
$item_list[$item['user_id']] = $item;
|
||||
}
|
||||
|
||||
return $item_list;
|
||||
}
|
||||
|
||||
|
||||
public function getLoginLog(array $conditions = []) {
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT * FROM ".$this->tb_customer_login_log." WHERE 1 ORDER BY `id` DESC LIMIT 100 ",
|
||||
$bind_types,
|
||||
$bind_values
|
||||
);
|
||||
|
||||
return $this->db->fetchAll($query) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $email
|
||||
* @param string $login_status ok or error
|
||||
* @param string $login_msg
|
||||
*/
|
||||
public function logLogin($email, $login_status, $login_msg) {
|
||||
$this->db->insert(
|
||||
$this->tb_customer_login_log,
|
||||
[
|
||||
"email" => substr($email, 0, 45),
|
||||
"login_status" => $login_status,
|
||||
"login_msg" => substr($login_msg, 0, 45),
|
||||
"ip_address" => substr(USER_IP, 0, 45),
|
||||
"user_agent" => substr(USER_AGENT, 0, 99),
|
||||
"create_time" => CURRENT_TIME,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
213
inc/Hura8/Components/Customer/Model/CustomerGroupModel.php
Normal file
213
inc/Hura8/Components/Customer/Model/CustomerGroupModel.php
Normal file
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Customer\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\System\Controller\UrlManagerController;
|
||||
use Hura8\System\IDGenerator;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
|
||||
class CustomerGroupModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
protected $tb_customer_per_group = "tb_customer_per_group";
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct('customer_group');
|
||||
}
|
||||
|
||||
|
||||
public function updateItemCount($group_id) {
|
||||
$this->db->runQuery(
|
||||
"UPDATE `".$this->tb_entity."` SET
|
||||
`customer_count` = (SELECT COUNT(*) AS total FROM `".$this->tb_customer_per_group."` WHERE `group_id` = ? )
|
||||
WHERE `id` = ? LIMIT 1
|
||||
",
|
||||
['d', 'd'], [$group_id, $group_id]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function getTotalCustomer($group_id, array $condition = [])
|
||||
{
|
||||
$query = $this->db->runQuery(
|
||||
" SELECT COUNT(*) as total FROM `".$this->tb_customer_per_group."` WHERE `group_id` = ? ",
|
||||
['d'], [$group_id]
|
||||
);
|
||||
|
||||
$total = 0;
|
||||
if ($rs = $this->db->fetchAssoc($query)) {
|
||||
$total = $rs['total'];
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
|
||||
public function getListCustomer($group_id, array $condition = [])
|
||||
{
|
||||
$numPerPage = (isset($condition['numPerPage']) && $condition['numPerPage'] > 0 ) ? intval($condition['numPerPage']) : 20 ;
|
||||
$page = (isset($condition['page']) && $condition['page'] > 0 ) ? intval($condition['page']) : 1 ;
|
||||
$order_by = " `id` DESC";
|
||||
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT `customer_id` FROM ".$this->tb_customer_per_group." WHERE `group_id` = ?
|
||||
ORDER BY ".$order_by."
|
||||
LIMIT ".(($page-1) * $numPerPage).", ".$numPerPage ,
|
||||
['d'], [$group_id]
|
||||
) ;
|
||||
|
||||
$item_list_ids = array_map(function ($item){ return $item['customer_id'];}, $this->db->fetchAll($query));
|
||||
|
||||
$objCustomerModel = new CustomerModel();
|
||||
$list_info = $objCustomerModel->getListByIds($item_list_ids);
|
||||
|
||||
// final list
|
||||
$final_list = [];
|
||||
foreach ($item_list_ids as $_id) {
|
||||
$final_list[] = $list_info[$_id] ?? null;
|
||||
}
|
||||
|
||||
return $final_list;
|
||||
}
|
||||
|
||||
|
||||
public function removeCustomerFromAllGroup($customer_id)
|
||||
{
|
||||
$this->db->runQuery(
|
||||
"DELETE FROM `".$this->tb_customer_per_group."` WHERE `customer_id` = ?",
|
||||
['d'], [$customer_id]
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function removeCustomer($customer_id, $group_id)
|
||||
{
|
||||
$this->db->runQuery(
|
||||
"DELETE FROM `".$this->tb_customer_per_group."` WHERE `group_id` =? AND `customer_id` = ? LIMIT 1 ",
|
||||
['d', 'd'],
|
||||
[$group_id, $customer_id]
|
||||
);
|
||||
|
||||
$this->updateItemCount($group_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function addCustomer($customer_id, $group_id)
|
||||
{
|
||||
$query = $this->db->runQuery(
|
||||
" SELECT * FROM `".$this->tb_customer_per_group."` WHERE `group_id` = ? AND `customer_id` = ? LIMIT 1 ",
|
||||
['d', 'd'],
|
||||
[$group_id, $customer_id]
|
||||
);
|
||||
|
||||
if ($this->db->fetchAssoc($query)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->db->insert(
|
||||
$this->tb_customer_per_group,
|
||||
[
|
||||
"group_id" => $group_id,
|
||||
"customer_id" => $customer_id,
|
||||
]
|
||||
);
|
||||
|
||||
$this->updateItemCount($group_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition): ?array
|
||||
{
|
||||
/*$condition = array(
|
||||
"q" => "",
|
||||
"status" => 0,
|
||||
);*/
|
||||
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
protected function beforeCreateItem(array $input_info) : AppResponse
|
||||
{
|
||||
$info = $input_info;
|
||||
|
||||
if(!$info['group_code']) $info['group_code'] = $info['title'];
|
||||
$info['group_code'] = $this->createUniqueCode(0, $info['group_code']);
|
||||
|
||||
$info['create_time'] = CURRENT_TIME;
|
||||
$info['create_by'] = ADMIN_NAME;
|
||||
|
||||
return new AppResponse('ok', null, $info);
|
||||
}
|
||||
|
||||
|
||||
protected function afterCreateItem($new_item_id, $new_item_info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function beforeUpdateItem($item_id, $current_item_info, $new_input_info): AppResponse
|
||||
{
|
||||
$info = $new_input_info;
|
||||
|
||||
if(isset($info['group_code'])) {
|
||||
if(!$info['group_code']) $info['group_code'] = $info['title'];
|
||||
$info['group_code'] = $this->createUniqueCode($item_id, $info['group_code']);
|
||||
}
|
||||
|
||||
$info['last_update'] = CURRENT_TIME;
|
||||
$info['last_update_by'] = ADMIN_NAME;
|
||||
|
||||
return new AppResponse('ok', null, $info);
|
||||
}
|
||||
|
||||
|
||||
protected function createUniqueCode($current_item_id, $wanted_code){
|
||||
|
||||
$clean_code = UrlManagerController::create_url_index($wanted_code);
|
||||
|
||||
//if exist and belong other id, create a new one
|
||||
$query = $this->db->runQuery("SELECT `id` FROM `".$this->tb_entity."` WHERE `group_code` = ? LIMIT 1 ", ['s'], [$clean_code]) ;
|
||||
if($info = $this->db->fetchAssoc($query)){
|
||||
if($info['id'] != $current_item_id) {
|
||||
$new_code = $clean_code."-".IDGenerator::createStringId(3);
|
||||
return $this->createUniqueCode($current_item_id, $new_code);
|
||||
}
|
||||
}
|
||||
|
||||
return $clean_code;
|
||||
}
|
||||
|
||||
|
||||
protected function afterUpdateItem($item_id, $old_item_info, $new_item_info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function beforeDeleteItem($item_id, $item_info) : AppResponse
|
||||
{
|
||||
return new AppResponse('ok');
|
||||
}
|
||||
|
||||
protected function afterDeleteItem($item_id, $item_info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function extendedFilterOptions(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
268
inc/Hura8/Components/Customer/Model/CustomerLoyaltyModel.php
Normal file
268
inc/Hura8/Components/Customer/Model/CustomerLoyaltyModel.php
Normal file
@@ -0,0 +1,268 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Customer\Model;
|
||||
|
||||
use ClientExtend\UserLoyaltyPointCalculation;
|
||||
use Hura8\Database\iConnectDB;
|
||||
use Hura8\Interfaces\TableName;
|
||||
|
||||
class CustomerLoyaltyModel
|
||||
{
|
||||
|
||||
/* @var iConnectDB $db */
|
||||
protected $db;
|
||||
|
||||
protected $tb_point = TableName::CUSTOMER_POINT; // "idv_customer_point";
|
||||
protected $tb_customer = TableName::CUSTOMER; // "idv_customer";
|
||||
|
||||
public static $POINT_NAME = 'điểm';
|
||||
|
||||
protected $point_setting = [];
|
||||
protected $point_setting_config_file = ROOT_DIR . "/config/build/customer_point.php";
|
||||
|
||||
protected $level_setting = [];
|
||||
protected $level_setting_config_file = ROOT_DIR . "/config/client/customer_level.php";
|
||||
|
||||
protected $level_by = '';// point|total_purchase_value as set by constant CHANGE_CUSTOMER_LEVEL_BY
|
||||
|
||||
/* @var $objUserLoyaltyPointCalculation UserLoyaltyPointCalculation */
|
||||
protected $objUserLoyaltyPointCalculation;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = get_db("", ENABLE_DB_DEBUG);
|
||||
|
||||
// import settings
|
||||
//$new_info_file = "../config/build/customer_point.php" ;
|
||||
//$config_file = ROOT_DIR . "/config/build/customer_point.php";
|
||||
if(@file_exists($this->point_setting_config_file)) {
|
||||
$this->point_setting = include $this->point_setting_config_file;
|
||||
}
|
||||
|
||||
// customer level based on point gain
|
||||
if( defined("ENABLE_CUSTOMER_POINT") && ENABLE_CUSTOMER_POINT ) {
|
||||
if(@file_exists($this->level_setting_config_file)) {
|
||||
$this->level_setting = include $this->level_setting_config_file;
|
||||
}
|
||||
}
|
||||
|
||||
// default is point
|
||||
$this->level_by = (defined('CHANGE_CUSTOMER_LEVEL_BY')) ? CHANGE_CUSTOMER_LEVEL_BY : 'point';
|
||||
|
||||
$this->objUserLoyaltyPointCalculation = new UserLoyaltyPointCalculation($this->point_setting);
|
||||
}
|
||||
|
||||
|
||||
public function getPointSettingConfigFile() {
|
||||
return $this->point_setting_config_file;
|
||||
}
|
||||
|
||||
public function getPointSetting() {
|
||||
return $this->point_setting;
|
||||
}
|
||||
|
||||
public function getLevelSetting(){
|
||||
return $this->level_setting;
|
||||
}
|
||||
|
||||
// show estimate cart point
|
||||
public function getEstimateCartPoint($cart_value){
|
||||
$conversion_rate = (isset($this->point_setting['reward']['buy']['rate'])) ? $this->point_setting['reward']['buy']['rate'] : 0;
|
||||
return ($conversion_rate) ? round($cart_value / $conversion_rate) : 0;
|
||||
}
|
||||
|
||||
public function getUserPoint($user_id, array $condition, $return_type)
|
||||
{
|
||||
|
||||
if($return_type == "total") {
|
||||
//Lay tong so
|
||||
$query = $this->db->runQuery("SELECT COUNT(*) AS total FROM `". $this->tb_point ."` WHERE `customer_id` = ? " , ['d'], [$user_id]);
|
||||
if($resultTotal = $this->db->fetchAssoc($query)){
|
||||
return $resultTotal['total'];
|
||||
}
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
$numPerPage = (isset($condition['numPerPage'])) ? intval($condition['numPerPage']) : 50;
|
||||
$page = getPageId();
|
||||
|
||||
$query = $this->db->runQuery("
|
||||
SELECT * FROM `". $this->tb_point ."`
|
||||
WHERE `customer_id` = ?
|
||||
ORDER BY id DESC
|
||||
LIMIT ".($page - 1) * $numPerPage .", ".$numPerPage." " , ['d'], [$user_id]);
|
||||
|
||||
$result = array();
|
||||
$i = ($page - 1) * $numPerPage;
|
||||
foreach ( $this->db->fetchAll($query) as $rs){
|
||||
$i++;
|
||||
$rs['counter'] = $i;
|
||||
$rs['activity_type_name'] = (isset($this->point_setting[$rs['operation']][$rs['activity_type']])) ? $this->point_setting[$rs['operation']][$rs['activity_type']]['name'] : '--';
|
||||
$result[] = $rs;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function usePoint($user_id, $use_point, $activity_type, $activity_type_tracker, $reason = '', $point_args = ['order_value' => 0]){
|
||||
// no user or no config
|
||||
if(!$user_id || !ENABLE_CUSTOMER_POINT) return false;
|
||||
|
||||
$result = $this->objUserLoyaltyPointCalculation->calculateUsePoint($user_id, $use_point, $activity_type, $activity_type_tracker, $point_args);
|
||||
|
||||
$this->pointOp('use', $user_id, $result['use_point'], $activity_type, $activity_type_tracker, $reason);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function rewardPoint($user_id, $activity_type, $activity_type_tracker, $reason = '', $point_args = ['order_id' => 0]){
|
||||
// no user or no config
|
||||
if(!$user_id || !ENABLE_CUSTOMER_POINT) return false;
|
||||
|
||||
$point = $this->objUserLoyaltyPointCalculation->calculateRewardPoint($user_id, $activity_type, $activity_type_tracker, $point_args);
|
||||
|
||||
$this->pointOp('reward', $user_id, $point, $activity_type, $activity_type_tracker, $reason);
|
||||
|
||||
return $point;
|
||||
}
|
||||
|
||||
|
||||
// $operation: reward|use
|
||||
// $change_point: positive (reward) or nagative (use)
|
||||
protected function pointOp($operation, $user_id, $change_point, $activity_type, $activity_type_tracker, $reason = '') {
|
||||
|
||||
if(!$change_point) return false;
|
||||
|
||||
$reason_prefix = ($operation == 'use') ? 'Sử dụng' : 'Thưởng';
|
||||
if($activity_type == 'return') $reason_prefix = 'Hoàn lại';
|
||||
$full_reason = join(" ", [$reason_prefix, $change_point, static::$POINT_NAME, ":", $reason]);
|
||||
|
||||
if($operation == 'use') $change_point = -1 * $change_point;
|
||||
|
||||
// security: hash the row to avoid editing point directly in the database
|
||||
$hash_value = sha1(join(".", [
|
||||
$operation,
|
||||
$user_id,
|
||||
$change_point,
|
||||
$activity_type,
|
||||
$activity_type_tracker,
|
||||
CURRENT_TIME,
|
||||
'ass@ss'
|
||||
]));
|
||||
|
||||
$new_id = $this->db->insert(
|
||||
$this->tb_point ,
|
||||
[
|
||||
'customer_id' => $user_id ,
|
||||
'activity_type' => $activity_type,
|
||||
'activity_type_tracker' => $activity_type_tracker ,
|
||||
'operation' => $operation,
|
||||
'point' => $change_point,
|
||||
'create_time' => CURRENT_TIME,
|
||||
'reason' => substr($full_reason, 0, 200),
|
||||
'referer_url' => substr(REFERER_URL, 0, 150) ,
|
||||
'hash_value' => $hash_value ,
|
||||
]
|
||||
);
|
||||
|
||||
//update user reward balance
|
||||
if($new_id) {
|
||||
$this->updateStat($user_id, $change_point);
|
||||
}
|
||||
|
||||
return $new_id;
|
||||
}
|
||||
|
||||
|
||||
public function updateStat($user_id, $changed_point, $changed_order_value=0) {
|
||||
$user_id = intval($user_id);
|
||||
|
||||
$query = $this->db->runQuery("SELECT
|
||||
`loyalty_point`,
|
||||
`loyalty_level`,
|
||||
`total_value_success`
|
||||
FROM ".$this->tb_customer."
|
||||
WHERE `id` = ?
|
||||
LIMIT 1 " , ['d'], [$user_id]);
|
||||
|
||||
if($current = $this->db->fetchAssoc($query)){
|
||||
$new_point = $current['loyalty_point'] + $changed_point;
|
||||
$new_purchase_value = $current['total_value_success'] + $changed_order_value;
|
||||
|
||||
$level = $current['loyalty_level'];
|
||||
if($this->level_by == 'point' && $changed_point != 0) $level = $this->calculateLevelByPoint($new_point);
|
||||
else if($changed_order_value) $level = $this->calculateLevelByOrderValue($new_purchase_value);
|
||||
|
||||
$this->db->update(
|
||||
$this->tb_customer ,
|
||||
[
|
||||
'loyalty_point' => $new_point,
|
||||
'loyalty_level' => $level,
|
||||
'total_value_success' => $new_purchase_value,
|
||||
],
|
||||
[
|
||||
'id' => $user_id,
|
||||
],
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private function calculateLevelByPoint($point) {
|
||||
//if the point in between -> return the lowest level
|
||||
$all_level = array_keys($this->level_setting);
|
||||
|
||||
foreach ( $all_level as $level) {
|
||||
$next_level = $level + 1;
|
||||
if(!in_array($next_level, $all_level)) $next_level = 0;
|
||||
|
||||
if($next_level) {
|
||||
if( $point >= $this->level_setting[$level]["point_require"]
|
||||
&& $point < $this->level_setting[$next_level]["point_require"] ) {
|
||||
return $level;
|
||||
}
|
||||
}else{
|
||||
if($point >= $this->level_setting[$level]["point_require"]) {
|
||||
return $level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function calculateLevelByOrderValue($aggregate_purchase_value = 0) {
|
||||
|
||||
//if the point in between -> return the lowest level
|
||||
$all_level = array_keys($this->level_setting);
|
||||
|
||||
//tinh hang thanh vien theo so tien tich luy
|
||||
foreach ( $all_level as $level ) {
|
||||
$next_level = $level + 1;
|
||||
if(!in_array($next_level, $all_level)) $next_level = 0;
|
||||
|
||||
if($next_level) {
|
||||
if( $aggregate_purchase_value >= $this->level_setting[$level]["total_order_value"] &&
|
||||
$aggregate_purchase_value < $this->level_setting[$next_level]["total_order_value"]
|
||||
) {
|
||||
return $level;
|
||||
}
|
||||
}else{
|
||||
if( $aggregate_purchase_value >= $this->level_setting[$level]["total_order_value"]) {
|
||||
return $level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
128
inc/Hura8/Components/Customer/Model/CustomerModel.php
Normal file
128
inc/Hura8/Components/Customer/Model/CustomerModel.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Customer\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\Interfaces\iSearch;
|
||||
use Hura8\System\IDGenerator;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
use Hura8\System\Security\DataValidator;
|
||||
|
||||
|
||||
class CustomerModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
protected $user_types = [
|
||||
"auto" => "Chưa đăng ký",
|
||||
"register" => "Đăng ký thành viên",
|
||||
];
|
||||
|
||||
/* @var iSearch $objSearchModel */
|
||||
protected $objSearchModel;
|
||||
|
||||
public function __construct() {
|
||||
$this->objSearchModel = new CustomerSearchModel();
|
||||
|
||||
parent::__construct(
|
||||
EntityType::CUSTOMER,
|
||||
"",
|
||||
$this->objSearchModel
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
'province' => 0,
|
||||
'user_type' => '',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getInfoByCRMCode($code)
|
||||
{
|
||||
$query = $this->db->runQuery("SELECT * FROM `".$this->tb_entity."` WHERE `crm_code` = ? LIMIT 1 ", ['s'], [$code]) ;
|
||||
if( $item_info = $this->db->fetchAssoc($query)){
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function getInfoByEmail($email, $user_type='register')
|
||||
{
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT * FROM `".$this->tb_entity."` WHERE `email` = ? AND `type` = ? LIMIT 1 ",
|
||||
['s', 's'], [$email, $user_type]
|
||||
) ;
|
||||
|
||||
if( $item_info = $this->db->fetchAssoc($query)){
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function getInfoByVerifiedEmail($email)
|
||||
{
|
||||
$info = $this->getInfoByEmail($email);
|
||||
if($info && $info['is_email_verify']) {
|
||||
return $info;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition): ?array
|
||||
{
|
||||
/*$condition = array(
|
||||
"user_type" => ''
|
||||
"q" => "",
|
||||
"status" => 0,
|
||||
);*/
|
||||
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
|
||||
if(isset($filter_condition["province"]) && $filter_condition["province"]) {
|
||||
$catCondition[] = " AND `province` = ? ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = $filter_condition["province"];
|
||||
}
|
||||
|
||||
// user_type
|
||||
if(isset($filter_condition["user_type"]) && array_key_exists($filter_condition["user_type"], $this->user_types) ){
|
||||
$catCondition[] = " AND `type` = ? ";
|
||||
$bind_types[] = 's';
|
||||
$bind_values[] = $filter_condition["user_type"];
|
||||
}
|
||||
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInfo(array $item_info): array
|
||||
{
|
||||
if($item_info["birth_day"] && $item_info["birth_year"]) {
|
||||
$item_info["birth_day"] = $item_info["birth_day"]."-".$item_info["birth_year"];
|
||||
}
|
||||
|
||||
return $item_info;
|
||||
}
|
||||
|
||||
|
||||
protected function createWebCRMCode($input_code = '') {
|
||||
return $input_code ?: "Web-".IDGenerator::createStringId(8);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
34
inc/Hura8/Components/Customer/Model/CustomerSearchModel.php
Normal file
34
inc/Hura8/Components/Customer/Model/CustomerSearchModel.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Customer\Model;
|
||||
|
||||
|
||||
use Hura8\Interfaces\iSearch;
|
||||
use Hura8\System\Model\aSearchBaseModel;
|
||||
|
||||
|
||||
class CustomerSearchModel extends aSearchBaseModel implements iSearch
|
||||
{
|
||||
|
||||
private $filter_fields = [
|
||||
"type" => "tb_customer.type",
|
||||
"province" => "tb_customer.province",
|
||||
"is_email_verify" => "tb_customer.is_email_verify",
|
||||
"total_value" => "tb_customer.total_value",
|
||||
];
|
||||
|
||||
private $fulltext_fields = [
|
||||
"keywords" => ["tb_customer.name", "tb_customer.crm_code", "tb_customer.email","tb_customer.mobile",],
|
||||
];
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
"tb_customer",
|
||||
$this->fulltext_fields,
|
||||
$this->filter_fields
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Deal\AdminController;
|
||||
|
||||
use Hura8\Components\Deal\Model\DealCollectionModel;
|
||||
use Hura8\System\Controller\aAdminEntityBaseController;
|
||||
|
||||
class ADealCollectionController extends aAdminEntityBaseController
|
||||
{
|
||||
|
||||
/* @var DealCollectionModel $objDealCollectionModel */
|
||||
protected $objDealCollectionModel;
|
||||
|
||||
public function __construct() {
|
||||
$this->objDealCollectionModel = new DealCollectionModel();
|
||||
parent::__construct($this->objDealCollectionModel);
|
||||
}
|
||||
|
||||
public function getAllProductIdInCollection($collection_id) {
|
||||
return $this->objDealCollectionModel->getAllProductIdInCollection($collection_id);
|
||||
}
|
||||
|
||||
public function getAllDealIdInCollection($collection_id) {
|
||||
return $this->objDealCollectionModel->getAllDealIdInCollection($collection_id);
|
||||
}
|
||||
|
||||
public function updateAllDealInCollection($collection_id, $price, $time){
|
||||
return $this->objDealCollectionModel->updateAllDealInCollection($collection_id, $price, $time);
|
||||
}
|
||||
|
||||
public function addProductToCollection($product_id, $collection_id){
|
||||
return $this->objDealCollectionModel->addProductToCollection($product_id, $collection_id);
|
||||
}
|
||||
|
||||
public function removeFromCollection($deal_id, $collection_id){
|
||||
$this->objDealCollectionModel->removeFromCollection($deal_id, $collection_id);
|
||||
}
|
||||
|
||||
public function addToCollection($deal_id, $collection_id){
|
||||
$this->objDealCollectionModel->addToCollection($deal_id, $collection_id);
|
||||
}
|
||||
|
||||
public function updateCollectionView($id){
|
||||
$this->objDealCollectionModel->updateCollectionView($id);
|
||||
}
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Deal\AdminController;
|
||||
|
||||
use Hura8\Components\Deal\Controller\bDealController;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
class ADealController extends bDealController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
public function autoRenew() {
|
||||
$deal_list = $this->objDealModel->getAllAutoRenewableDeal();
|
||||
|
||||
//then renew & log history
|
||||
foreach ($deal_list as $info) {
|
||||
$this->renewDeal($info['id'], $info['from_time'], $info['to_time'], $info['auto_renew_history']);
|
||||
}
|
||||
}
|
||||
|
||||
protected function renewDeal($id, $from_time, $to_time, array $auto_renew_history) {
|
||||
/*$obj_from_date = new \DateTime(date("Y-m-d", $from_time));
|
||||
$obj_to_date = new \DateTime(date("Y-m-d", $to_time));
|
||||
$day_diff = $obj_to_date->diff($obj_from_date)->format('%a');
|
||||
|
||||
$obj_to_date->add(new \DateInterval('P'.$day_diff.'D'));
|
||||
$new_date = $obj_to_date->format('Y-m-d');
|
||||
|
||||
$current_date = date("Y-m-d");
|
||||
$from_time_minute = ($from_time > 0) ? date("H:i", $from_time) : "00:00";
|
||||
$to_time_minute = ($to_time > 0) ? date("H:i", $to_time) : "00:00";*/
|
||||
|
||||
$to_time_new = CURRENT_TIME + ($to_time - $from_time);
|
||||
|
||||
$auto_renew_history[] = [
|
||||
"renew_time" => show_datetime_from_unix(CURRENT_TIME),
|
||||
"from_time" => show_datetime_from_unix(CURRENT_TIME),
|
||||
"to_time" => show_datetime_from_unix($to_time_new),
|
||||
];
|
||||
|
||||
return $this->updateFields( $id,
|
||||
[
|
||||
'from_time' => CURRENT_TIME,
|
||||
'to_time' => $to_time_new,
|
||||
'auto_renew_history' => serialize($auto_renew_history),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
48
inc/Hura8/Components/Deal/Controller/bDealController.php
Normal file
48
inc/Hura8/Components/Deal/Controller/bDealController.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Deal\Controller;
|
||||
|
||||
use Hura8\Components\Deal\Model\DealModel;
|
||||
use Hura8\Components\Product\AdminController\AProductController;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
class bDealController extends aEntityBaseController
|
||||
{
|
||||
|
||||
protected $objDealModel;
|
||||
|
||||
|
||||
public function __construct() {
|
||||
$this->objDealModel = new DealModel();
|
||||
parent::__construct($this->objDealModel);
|
||||
}
|
||||
|
||||
|
||||
public function getList(array $condition) : array
|
||||
{
|
||||
$deal_list = parent::getList($condition);
|
||||
|
||||
$product_list_info = [];
|
||||
$product_list_ids = [];
|
||||
$final_list = [];
|
||||
foreach ($deal_list as $item) {
|
||||
if(!isset($product_list_info[$item['pro_id']])) {
|
||||
$product_list_info[$item['pro_id']]= null;
|
||||
$product_list_ids[] = $item['pro_id'];
|
||||
}
|
||||
|
||||
$copy = $item;
|
||||
$copy['product_info'] = &$product_list_info[$item['pro_id']];
|
||||
$final_list[] = $copy;
|
||||
}
|
||||
|
||||
$objAProductController = new AProductController();
|
||||
foreach ($objAProductController->getListByIds($product_list_ids) as $pro_id => $info) {
|
||||
$product_list_info[$pro_id] = $info;
|
||||
}
|
||||
|
||||
return $final_list;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
223
inc/Hura8/Components/Deal/Model/DealCollectionModel.php
Normal file
223
inc/Hura8/Components/Deal/Model/DealCollectionModel.php
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Deal\Model;
|
||||
|
||||
use Hura8\Components\Product\AdminController\AProductController;
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\Interfaces\TableName;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\System\TimeManager;
|
||||
|
||||
class DealCollectionModel extends aEntityBaseModel
|
||||
{
|
||||
|
||||
protected $tb_deal = "tb_deal";
|
||||
protected $tb_collection_item = "tb_deal_collection_item";
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('deal_collection');
|
||||
}
|
||||
|
||||
protected function extendedFilterOptions(): array
|
||||
{
|
||||
return [
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition): ?array
|
||||
{
|
||||
$where_clause = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
return [
|
||||
join(" ", $where_clause),
|
||||
$bind_types,
|
||||
$bind_values
|
||||
];
|
||||
}
|
||||
|
||||
public function getAllProductIdInCollection($collection_id) {
|
||||
$deal_id_list = $this->getAllDealIdInCollection($collection_id);
|
||||
|
||||
if(!sizeof($deal_id_list)) return array();
|
||||
|
||||
$query = $this->db->runQuery("SELECT `pro_id` FROM `".$this->tb_deal."` WHERE `id` IN (". join(',', $deal_id_list).") ");
|
||||
|
||||
return array_map(function ($item){
|
||||
return $item['pro_id'];
|
||||
}, $this->db->fetchAll($query));
|
||||
}
|
||||
|
||||
public function getAllDealIdInCollection($collection_id) {
|
||||
$query = $this->db->runQuery("SELECT `deal_id` FROM `".$this->tb_collection_item."` WHERE `collection_id` = ? ", ['d'], [$collection_id]);
|
||||
|
||||
return array_map(function ($item){
|
||||
return $item['deal_id'];
|
||||
}, $this->db->fetchAll($query));
|
||||
}
|
||||
|
||||
public function updateAllDealInCollection($collection_id, $price, $time){
|
||||
|
||||
$from_time = ($time['from_date'] != '') ? strtotime(TimeManager::convert_date_from_javascript($time['from_date'])." ".$time['from_time_minute'].":00") : 0;
|
||||
$to_time = ($time['to_date'] != '') ? strtotime(TimeManager::convert_date_from_javascript($time['to_date'])." ".$time['to_time_minute'].":00") : 0;
|
||||
|
||||
$deal_id_list = $this->getAllDealIdInCollection($collection_id);
|
||||
|
||||
if(!sizeof($deal_id_list)) return false;
|
||||
|
||||
$query = $this->db->runQuery("SELECT `id`, `pro_id` FROM `".$this->tb_deal."` WHERE `id` IN (". join(',', $deal_id_list).") ");
|
||||
$product_list_id = array();
|
||||
foreach ( $this->db->fetchAll($query) as $info ) {
|
||||
$product_list_id[$info['pro_id']] = $info['id'];
|
||||
}
|
||||
|
||||
//get product prices
|
||||
$query = $this->db->runQuery("
|
||||
SELECT `id`, price FROM ".TableName::PRODUCT."
|
||||
WHERE `id` IN (". join(',', array_keys($product_list_id)) .")
|
||||
");
|
||||
|
||||
$objDealModel = new DealModel();
|
||||
|
||||
foreach ( $this->db->fetchAll($query) as $_info ) {
|
||||
$product_id = $_info['id'];
|
||||
$product_price = $_info['price'];
|
||||
$deal_price = ($price['type'] == 'percent') ? round($product_price * (100 - $price['value']) / 100) : ($product_price - $price['value']);
|
||||
|
||||
//update
|
||||
$objDealModel->updatePriceAndTime(
|
||||
$product_list_id[$product_id],
|
||||
array(
|
||||
"price" => $deal_price,
|
||||
"from_time" => $from_time,
|
||||
"to_time" => $to_time,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function addProductToCollection($product_id, $collection_id){
|
||||
|
||||
$objAProductController = new AProductController();
|
||||
$product_info = $objAProductController->getInfo($product_id);
|
||||
|
||||
if($product_info){
|
||||
|
||||
$objDealModel = new DealModel();
|
||||
|
||||
$deal_id = $objDealModel->create(array(
|
||||
"pro_id" => $product_id,
|
||||
"title" => $product_info['title'],
|
||||
"price" => $product_info['price'],
|
||||
"quantity" => $product_info['quantity'],
|
||||
"min_purchase" => 1,
|
||||
"from_time" => 0,
|
||||
"to_time" => 0,
|
||||
"ordering" => $product_info[''],
|
||||
"description" => '',
|
||||
));
|
||||
|
||||
$this->addToCollection($deal_id, $collection_id);
|
||||
|
||||
return $deal_id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function removeFromCollection($deal_id, $collection_id){
|
||||
$this->db->runQuery(
|
||||
"DELETE FROM `".$this->tb_collection_item."` WHERE `deal_id` = ? AND `collection_id` = ? ",
|
||||
['d', 'd'],
|
||||
[$deal_id, $collection_id]
|
||||
);
|
||||
|
||||
$this->updateCollectionCount($collection_id);
|
||||
}
|
||||
|
||||
public function addToCollection($deal_id, $collection_id){
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT `deal_id` FROM `".$this->tb_collection_item."` WHERE `deal_id`= ? AND `collection_id` = ? LIMIT 1 ",
|
||||
['d', 'd'], [$deal_id, $collection_id]
|
||||
);
|
||||
|
||||
if( ! $this->db->fetchAssoc($query) ){
|
||||
$this->db->insert(
|
||||
$this->tb_collection_item ,
|
||||
[
|
||||
'collection_id' => $collection_id ,
|
||||
'deal_id' => $deal_id,
|
||||
'create_by' => ADMIN_ID,
|
||||
'create_time' => CURRENT_TIME,
|
||||
]
|
||||
);
|
||||
|
||||
$this->updateCollectionCount($collection_id);
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateCollectionCount($collection_id){
|
||||
$this->db->runQuery(
|
||||
"UPDATE `".$this->tb_entity."` SET
|
||||
`deal_count` = (SELECT COUNT(*) FROM `".$this->tb_collection_item."` WHERE `collection_id` = ? )
|
||||
WHERE `id` = ? LIMIT 1 ",
|
||||
['d', 'd'],
|
||||
[$collection_id, $collection_id]
|
||||
);
|
||||
}
|
||||
|
||||
public function updateCollectionView($id){
|
||||
$this->db->runQuery("UPDATE `".$this->tb_entity."` SET `visit` = `visit` + 1 WHERE `id` = ? LIMIT 1 ", ['d'], [ $id ]);
|
||||
}
|
||||
|
||||
|
||||
protected function beforeCreateItem(array $input_info) : AppResponse
|
||||
{
|
||||
$info = $input_info;
|
||||
|
||||
$info['create_time'] = CURRENT_TIME;
|
||||
$info['create_by'] = ADMIN_NAME;
|
||||
$info['last_update'] = CURRENT_TIME;
|
||||
$info['last_update_by'] = ADMIN_NAME;
|
||||
|
||||
return new AppResponse('ok', null, $info);
|
||||
}
|
||||
|
||||
protected function afterCreateItem($new_item_id, $new_item_info)
|
||||
{
|
||||
// TODO: Implement afterCreateItem() method.
|
||||
}
|
||||
|
||||
protected function beforeUpdateItem($item_id, $current_item_info, $new_input_info) : AppResponse
|
||||
{
|
||||
$info = $new_input_info;
|
||||
|
||||
$info['last_update'] = CURRENT_TIME;
|
||||
$info['last_update_by'] = ADMIN_NAME;
|
||||
|
||||
return new AppResponse('ok', null, $info);
|
||||
}
|
||||
|
||||
protected function afterUpdateItem($item_id, $old_item_info, $new_item_info)
|
||||
{
|
||||
// TODO: Implement afterUpdateItem() method.
|
||||
}
|
||||
|
||||
protected function beforeDeleteItem($item_id, $item_info) : AppResponse
|
||||
{
|
||||
return new AppResponse('ok');
|
||||
}
|
||||
|
||||
protected function afterDeleteItem($item_id, $item_info)
|
||||
{
|
||||
// TODO: Implement afterDeleteItem() method.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
196
inc/Hura8/Components/Deal/Model/DealModel.php
Normal file
196
inc/Hura8/Components/Deal/Model/DealModel.php
Normal file
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Deal\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\System\Security\DataValidator;
|
||||
use Hura8\System\TimeManager;
|
||||
|
||||
class DealModel extends aEntityBaseModel
|
||||
{
|
||||
|
||||
protected $tb_collection_item = "tb_deal_collection_item";
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('deal');
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getAllAutoRenewableDeal() {
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT `id`, `from_time`, `to_time` FROM `". $this->tb_entity ."`
|
||||
WHERE `to_time` < '".CURRENT_TIME."' AND `to_time` > 0 AND `auto_renew` = 1 "
|
||||
);
|
||||
|
||||
return $this->db->fetchAll($query);
|
||||
}
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
|
||||
$where_clause = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
$limit_by_time = false;
|
||||
$limit_by_time_condition = '';
|
||||
|
||||
// get deal by start time
|
||||
// require format: YY-mm-dd h:m:i or YY-mm-dd h:m or timestamp
|
||||
$datetime_pattern = '/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}\s[0-9]{1,2}:[0-9]{1,2}(:[0-9]{1,2})?$/i';
|
||||
|
||||
if(isset($filter_condition['start_time']) && $filter_condition['start_time'] ) {
|
||||
$limit_by_time = true;
|
||||
if(preg_match($datetime_pattern, trim($filter_condition['start_time']))) {
|
||||
$check_time = strtotime($filter_condition['start_time']);
|
||||
}else{
|
||||
$check_time = intval($filter_condition['start_time']);
|
||||
}
|
||||
|
||||
$limit_by_time_condition .= " AND `from_time` >= '".$check_time."' ";
|
||||
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = $check_time;
|
||||
}
|
||||
|
||||
// get deal by end time
|
||||
// require format: YY-mm-dd h:m:i or YY-mm-dd h:m or timestamp
|
||||
if(isset($filter_condition['end_time']) && $filter_condition['end_time'] ) {
|
||||
$limit_by_time = true;
|
||||
if(preg_match($datetime_pattern, trim($filter_condition['end_time']))) {
|
||||
$check_time = strtotime($filter_condition['end_time']);
|
||||
}else{
|
||||
$check_time = intval($filter_condition['end_time']);
|
||||
}
|
||||
|
||||
$limit_by_time_condition .= " AND `to_time` <= '".$check_time."' ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = $check_time;
|
||||
}
|
||||
|
||||
if($limit_by_time) {
|
||||
$where_clause[] = " AND `status`= 1 ".$limit_by_time_condition;
|
||||
}
|
||||
|
||||
//type expire
|
||||
if(isset($filter_condition['type']) && $filter_condition['type'] == 'expire' ) {
|
||||
$where_clause[] = "AND `status`= 1 AND `to_time` < ? ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = CURRENT_TIME;
|
||||
}
|
||||
|
||||
//type active: might not have begun yet
|
||||
if(isset($filter_condition['type']) && $filter_condition['type'] == 'active' && !$limit_by_time ) {
|
||||
$where_clause[] = " AND `status` = 1 AND `to_time` >= ? ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = CURRENT_TIME;
|
||||
}
|
||||
|
||||
// Đang bắt đầu
|
||||
if(isset($filter_condition['type']) && $filter_condition['type'] == 'started' && !$limit_by_time ) {
|
||||
$where_clause[] = " AND `status` = 1 AND `to_time` >= ? AND from_time < ? ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = CURRENT_TIME;
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = CURRENT_TIME;
|
||||
}
|
||||
|
||||
// Chưa bắt đầu
|
||||
if(isset($filter_condition['type']) && $filter_condition['type'] == 'coming' && !$limit_by_time ) {
|
||||
$where_clause[] = " AND `status` = 1 AND `from_time` >= ? ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = CURRENT_TIME;
|
||||
}
|
||||
|
||||
//deal collection
|
||||
if(isset($filter_condition['collection_id']) && $filter_condition['collection_id'] > 0) {
|
||||
$where_clause[] = " AND `id` IN ( SELECT `deal_id` FROM `".$this->tb_collection_item."` WHERE `collection_id` = ? ) ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = $filter_condition['collection_id'];
|
||||
}
|
||||
|
||||
// exclude from collection
|
||||
if(isset($filter_condition['add_to_collection']) && $filter_condition['add_to_collection'] > 0) {
|
||||
$where_clause[] = " AND `id` NOT IN ( SELECT `deal_id` FROM `".$this->tb_collection_item."` WHERE `collection_id` = ? ) ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = $filter_condition['add_to_collection'];
|
||||
}
|
||||
|
||||
// by word filter
|
||||
$filter = $filter_condition['filter'] ?? '';
|
||||
switch ($filter) {
|
||||
case "not-started": // Chưa bắt đầu
|
||||
$where_clause[] = " AND ( ? - `from_time` ) < 0 ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = CURRENT_TIME;
|
||||
break;
|
||||
|
||||
case "started": // Đang bắt đầu
|
||||
$where_clause[] = " AND ( ? - `from_time` ) > 0 AND ( `to_time` - ?) > 0 ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = CURRENT_TIME;
|
||||
$bind_values[] = CURRENT_TIME;
|
||||
break;
|
||||
|
||||
case "ended": // Hết thời gian
|
||||
$where_clause[] = " AND (`to_time` - ?) < 0 ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = CURRENT_TIME;
|
||||
break;
|
||||
|
||||
case "hidden": // Ẩn hiển thị
|
||||
$where_clause[] = " AND `status` = 0 ";
|
||||
break;
|
||||
|
||||
case "featured": // Đang nổi bật
|
||||
$where_clause[] = " AND `is_featured` = 1 ";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return [
|
||||
join(" ", $where_clause),
|
||||
$bind_types,
|
||||
$bind_values
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInList(array $item_info): array
|
||||
{
|
||||
$copy = $item_info;
|
||||
|
||||
$copy['deal_time_happen'] = CURRENT_TIME - $item_info['from_time'];
|
||||
$copy['deal_time_left'] = $item_info['to_time'] - CURRENT_TIME;
|
||||
$copy['is_start'] = (CURRENT_TIME - $item_info['from_time'] > 0) ? 1 : 0;
|
||||
$copy['is_end'] = ($item_info['to_time'] - CURRENT_TIME > 0) ? 0 : 1;
|
||||
|
||||
return $copy;
|
||||
}
|
||||
|
||||
protected function formatItemInfo(array $item_info): array
|
||||
{
|
||||
$copy = $item_info;
|
||||
|
||||
$copy['deal_time_happen'] = CURRENT_TIME - $item_info['from_time'];
|
||||
$copy['deal_time_left'] = $item_info['to_time'] - CURRENT_TIME;
|
||||
$copy['is_start'] = (CURRENT_TIME - $item_info['from_time'] > 0) ? 1 : 0;
|
||||
$copy['is_end'] = ($item_info['to_time'] - CURRENT_TIME > 0) ? 0 : 1;
|
||||
|
||||
return $copy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Marketing\AdminController;
|
||||
|
||||
use Hura8\Components\Marketing\Controller\bCouponController;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
class ACouponController extends bCouponController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
public function updateProduct($product_id, $coupon_id, array $info)
|
||||
{
|
||||
return $this->objCouponModel->updateProduct($product_id, $coupon_id, $info);
|
||||
}
|
||||
|
||||
|
||||
public function removeProduct($product_id, $coupon_id)
|
||||
{
|
||||
return $this->objCouponModel->removeProduct($product_id, $coupon_id);
|
||||
}
|
||||
|
||||
|
||||
public function addProduct($product_id, $coupon_id, $ordering=0)
|
||||
{
|
||||
return $this->objCouponModel->addProduct($product_id, $coupon_id, $ordering);
|
||||
}
|
||||
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
// TODO: Implement deleteFileBeforeDeleteItem() method.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Marketing\AdminController;
|
||||
|
||||
|
||||
use Hura8\Components\Marketing\Model\PosterModel;
|
||||
use Hura8\System\Controller\aAdminEntityBaseController;
|
||||
|
||||
class APosterController extends aAdminEntityBaseController
|
||||
{
|
||||
/* @var PosterModel $objPosterModel */
|
||||
protected $objPosterModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objPosterModel = new PosterModel();
|
||||
parent::__construct($this->objPosterModel);
|
||||
}
|
||||
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
// TODO: Implement deleteFileBeforeDeleteItem() method.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Marketing\AdminController;
|
||||
|
||||
use Hura8\Components\Marketing\Controller\bProductFeedController;
|
||||
use Hura8\Components\Marketing\Model\ProductFeedModel;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\System\Controller\aAdminEntityBaseController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
class AProductFeedController extends bProductFeedController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
public function getAllCategories() {
|
||||
return $this->objProductFeedModel->getAllCategories();
|
||||
}
|
||||
|
||||
public function getAllProductListIds( $list_id){
|
||||
return $this->objProductFeedModel->getAllProductListIds($list_id);
|
||||
}
|
||||
|
||||
public function getProductListTotal($list_id) {
|
||||
return $this->objProductFeedModel->getProductListTotal($list_id);
|
||||
}
|
||||
|
||||
public function getProductList($list_id, $page = 1, $numPerPage = 30) {
|
||||
return $this->objProductFeedModel->getProductList($list_id, $page, $numPerPage);
|
||||
}
|
||||
|
||||
public function deleteAllProductFromList($list_id) {
|
||||
$this->objProductFeedModel->deleteAllProductFromList($list_id);
|
||||
}
|
||||
|
||||
//remove product from a list
|
||||
public function deleteProductFromList($pro_list, $list_id){
|
||||
return $this->objProductFeedModel->deleteProductFromList($pro_list, $list_id);
|
||||
}
|
||||
|
||||
//add product to a list
|
||||
public function addProductToList($pro_list, $list_id){
|
||||
return $this->objProductFeedModel->addProductToList($pro_list, $list_id);
|
||||
}
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Marketing\Controller;
|
||||
|
||||
use Hura8\Components\Marketing\Model\CouponModel;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
|
||||
class bCouponController extends aEntityBaseController
|
||||
{
|
||||
|
||||
protected $type_list = array(
|
||||
'pro' => "Tặng sản phẩm",
|
||||
'cash' => "Tặng tiền mặt",
|
||||
'priceoff' => "Giảm giá %",
|
||||
'other' => "Khác"
|
||||
);
|
||||
|
||||
|
||||
/* @var CouponModel $objCouponModel */
|
||||
protected $objCouponModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objCouponModel = new CouponModel();
|
||||
parent::__construct($this->objCouponModel);
|
||||
}
|
||||
|
||||
|
||||
public function getTotalProduct($coupon_id, array $condition = [])
|
||||
{
|
||||
return $this->objCouponModel->getTotalProduct($coupon_id, $condition);
|
||||
}
|
||||
|
||||
|
||||
public function getListProduct($coupon_id, array $condition = []) {
|
||||
return $this->objCouponModel->getListProduct($coupon_id, $condition);
|
||||
}
|
||||
|
||||
|
||||
public function getTypeList() {
|
||||
return $this->type_list;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Marketing\Controller;
|
||||
|
||||
use Hura8\Components\Marketing\Model\ProductFeedModel;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
class bProductFeedController extends aEntityBaseController
|
||||
{
|
||||
|
||||
protected $objProductFeedModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objProductFeedModel = new ProductFeedModel();
|
||||
parent::__construct($this->objProductFeedModel);
|
||||
}
|
||||
|
||||
|
||||
public function getInfoByPublicId($public_id)
|
||||
{
|
||||
return $this->objProductFeedModel->getInfoByPublicId($public_id);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
130
inc/Hura8/Components/Marketing/Model/CouponModel.php
Normal file
130
inc/Hura8/Components/Marketing/Model/CouponModel.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Marketing\Model;
|
||||
|
||||
use Hura8\Components\Product\Model\ProductModel;
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
use Hura8\System\IDGenerator;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\System\Security\DataClean;
|
||||
use Hura8\System\Security\DataType;
|
||||
use Hura8\System\TimeManager;
|
||||
|
||||
|
||||
class CouponModel extends aEntityBaseModel
|
||||
{
|
||||
|
||||
protected $tb_coupon_product = "tb_coupon_product";
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::COUPON);
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getTotalProduct($coupon_id, array $condition = [])
|
||||
{
|
||||
$query = $this->db->runQuery(
|
||||
" SELECT COUNT(*) as total FROM `".$this->tb_coupon_product."` WHERE `coupon_id` = ? ",
|
||||
['d'], [$coupon_id]
|
||||
);
|
||||
|
||||
$total = 0;
|
||||
if ($rs = $this->db->fetchAssoc($query)) {
|
||||
$total = $rs['total'];
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
|
||||
public function getListProduct($coupon_id, array $condition = [])
|
||||
{
|
||||
$numPerPage = (isset($condition['numPerPage']) && $condition['numPerPage'] > 0 ) ? intval($condition['numPerPage']) : 20 ;
|
||||
$page = (isset($condition['page']) && $condition['page'] > 0 ) ? intval($condition['page']) : 1 ;
|
||||
$order_by = " `ordering` DESC, `id` DESC";
|
||||
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT `product_id` FROM ".$this->tb_coupon_product." WHERE `coupon_id` = ?
|
||||
ORDER BY ".$order_by."
|
||||
LIMIT ".(($page-1) * $numPerPage).", ".$numPerPage ,
|
||||
['d'], [$coupon_id]
|
||||
) ;
|
||||
|
||||
$item_list = array();
|
||||
$counter = ($page-1) * $numPerPage;
|
||||
foreach ( $this->db->fetchAll($query) as $item ) {
|
||||
$counter += 1;
|
||||
|
||||
$item_list[$item['product_id']] = [
|
||||
'counter' => $counter,
|
||||
];
|
||||
}
|
||||
|
||||
$objProductModel = new ProductModel();
|
||||
$product_list_info = $objProductModel->getListByIds(array_keys($item_list));
|
||||
|
||||
// final list
|
||||
$final_list = [];
|
||||
foreach ($item_list as $_pro_id => $_pro_info_in_collection) {
|
||||
$pro_basic = $product_list_info[$_pro_id] ?? null;
|
||||
if($pro_basic) {
|
||||
$final_list[] = array_merge($pro_basic, $_pro_info_in_collection);
|
||||
}
|
||||
}
|
||||
|
||||
return $final_list;
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
/*$condition = array(
|
||||
"q" => getRequest("q", ''),
|
||||
"featured" => (int) getRequest("featured"),
|
||||
"status" => (int) getRequest("status"),
|
||||
);*/
|
||||
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
|
||||
if(isset($filter_condition["letter"]) && strlen($filter_condition["letter"]) == 1){
|
||||
$catCondition[] = " AND `letter` = ? ";
|
||||
$bind_types[] = 's';
|
||||
$bind_values[] = $filter_condition["letter"];
|
||||
}
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
protected function createUniqueCode($current_item_id, $wanted_code = ''){
|
||||
if(!$wanted_code) $wanted_code = IDGenerator::createStringId(10);
|
||||
|
||||
$clean_code = DataClean::makeInputSafe($wanted_code, DataType::ID);
|
||||
$clean_code = strtoupper($clean_code);
|
||||
|
||||
//if exist and belong other id, create a new one
|
||||
$query = $this->db->runQuery("SELECT `id` FROM `".$this->tb_entity."` WHERE `code` = ? LIMIT 1 ", ['s'], [$clean_code]) ;
|
||||
if($info = $this->db->fetchAssoc($query)){
|
||||
if($info['id'] != $current_item_id) {
|
||||
$new_code = IDGenerator::createStringId(6);
|
||||
return $this->createUniqueCode($current_item_id, $new_code);
|
||||
}
|
||||
}
|
||||
|
||||
return $clean_code;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
33
inc/Hura8/Components/Marketing/Model/PosterModel.php
Normal file
33
inc/Hura8/Components/Marketing/Model/PosterModel.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Marketing\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
|
||||
class PosterModel extends aEntityBaseModel
|
||||
{
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct('poster');
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
}
|
||||
126
inc/Hura8/Components/Marketing/Model/ProductFeedModel.php
Normal file
126
inc/Hura8/Components/Marketing/Model/ProductFeedModel.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Marketing\Model;
|
||||
|
||||
use Hura8\Components\Product\AdminController\AProductController;
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\System\IDGenerator;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
|
||||
class ProductFeedModel extends aEntityBaseModel
|
||||
{
|
||||
|
||||
protected $tb_feed_product = "tb_feed_product";
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct('feed');
|
||||
|
||||
//$this->all_brands = $this->buildAllBrands();
|
||||
//$this->all_categories = $this->buildAllCategories();
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getInfoByPublicId($public_id)
|
||||
{
|
||||
$query = $this->db->runQuery("SELECT * FROM `".$this->tb_entity."` WHERE `public_id` = ? LIMIT 1 ", ['s'], [$public_id]) ;
|
||||
if( $item_info = $this->db->fetchAssoc($query)){
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getProductListTotal($list_id) {
|
||||
$query = $this->db->runQuery(
|
||||
" SELECT COUNT(*) AS total FROM `".$this->tb_feed_product."` WHERE `list_id` = ? ",
|
||||
['d'], [$list_id]
|
||||
);
|
||||
|
||||
$total = 0;
|
||||
if ($info = $this->db->fetchAssoc($query)) {
|
||||
$total = $info['total'];
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
public function getProductList($list_id, $page = 1, $numPerPage = 30) {
|
||||
|
||||
$query = $this->db->runQuery(
|
||||
" SELECT `pro_id` FROM `".$this->tb_feed_product."`
|
||||
WHERE `list_id` = ?
|
||||
ORDER BY `id` DESC
|
||||
LIMIT ".( ($page - 1) * $numPerPage ).", ".$numPerPage,
|
||||
['d'], [$list_id]
|
||||
);
|
||||
|
||||
$product_list_ids = array_map(function ($item) { return $item['pro_id'];}, $this->db->fetchAll($query));
|
||||
|
||||
$objAProductController = new AProductController();
|
||||
|
||||
$stt = ($page - 1) * $numPerPage;
|
||||
$item_list = [];
|
||||
foreach ($objAProductController->getListByIds($product_list_ids) as $_id => $info) {
|
||||
$stt++;
|
||||
$info["counter"] = $stt;
|
||||
$item_list[] = $info;
|
||||
}
|
||||
|
||||
return $item_list;
|
||||
}
|
||||
|
||||
//--------------------
|
||||
|
||||
public function getAllCategories() {
|
||||
return $this->all_categories;
|
||||
}
|
||||
|
||||
|
||||
public function getAllProductListIds( $list_id){
|
||||
if(!$list_id) return [];
|
||||
|
||||
$query = $this->db->runQuery("SELECT `pro_id` FROM `".$this->tb_feed_product."` WHERE `list_id` = ? ", ['d'], [ $list_id ]);
|
||||
|
||||
$item_list = array();
|
||||
foreach ( $this->db->fetchAll($query) as $rs ) {
|
||||
$item_list[] = $rs['pro_id'];
|
||||
}
|
||||
|
||||
return $item_list;
|
||||
}
|
||||
|
||||
|
||||
//--------------------
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
/*$condition = array(
|
||||
"letter" => "",
|
||||
);*/
|
||||
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
|
||||
if(isset($filter_condition["letter"]) && strlen($filter_condition["letter"]) == 1){
|
||||
$catCondition[] = " AND `letter` = ? ";
|
||||
$bind_types[] = 's';
|
||||
$bind_values[] = $filter_condition["letter"];
|
||||
}
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Marketing\Model;
|
||||
|
||||
class UProductFeedModel
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Media\AdminController;
|
||||
|
||||
use Hura8\Components\Media\Controller\bItemMediaController;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
class AItemMediaController extends bItemMediaController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
// delete thumb files
|
||||
$item_info = $this->getInfo($item_id);
|
||||
if(!$item_info['file_url']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$file_name = $item_info['file_url'];
|
||||
|
||||
foreach (static::$resized_sizes as $size => $value) {
|
||||
$file_local_path = PUBLIC_DIR . "/". static::$image_folder . "/". $size. IMAGE_FILE_SEPARATOR . $file_name;
|
||||
@unlink($file_local_path);
|
||||
}
|
||||
|
||||
// remove original file
|
||||
$file_local_path = PUBLIC_DIR . "/". static::$image_folder . "/". $file_name;
|
||||
@unlink($file_local_path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Media\AdminController;
|
||||
|
||||
use Hura8\Components\Media\Controller\bMediaCategoryController;
|
||||
use Hura8\Interfaces\iEntityAdminCategoryController;
|
||||
use Hura8\Traits\AdminEntityCategoryControllerTraits;
|
||||
|
||||
|
||||
class AMediaCategoryController extends bMediaCategoryController implements iEntityAdminCategoryController
|
||||
{
|
||||
use AdminEntityCategoryControllerTraits;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Media\AdminController;
|
||||
|
||||
use Hura8\Components\Media\Controller\bMediaController;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
class AMediaController extends bMediaController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
public static function createUploadSubFolder() {
|
||||
return date("Y-m-d");
|
||||
}
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
// delete thumb files
|
||||
$item_info = $this->getInfo($item_id);
|
||||
if(!$item_info['file_url']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
list($sub_folder, $file_name) = explode("/", $item_info['file_url']); // format: Y-m-d/file_name
|
||||
|
||||
foreach (static::$resized_sizes as $size => $value) {
|
||||
$file_local_path = PUBLIC_DIR . "/". static::$image_folder . "/" . $sub_folder . "/". $size. IMAGE_FILE_SEPARATOR . $file_name;
|
||||
@unlink($file_local_path);
|
||||
}
|
||||
|
||||
// remove original file
|
||||
$file_local_path = PUBLIC_DIR . "/". static::$image_folder . "/" . $sub_folder . "/". $file_name;
|
||||
@unlink($file_local_path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Media\Controller;
|
||||
|
||||
use Hura8\Components\Media\Model\ItemMediaModel;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
|
||||
class bItemMediaController extends aEntityBaseController
|
||||
{
|
||||
static $image_folder = "media/item";
|
||||
|
||||
static $resized_sizes = array(
|
||||
's' => ['width' => 300,]
|
||||
);
|
||||
|
||||
/* @var ItemMediaModel $objItemMediaModel */
|
||||
protected $objItemMediaModel;
|
||||
|
||||
protected $item_type;
|
||||
protected $item_id;
|
||||
|
||||
public function __construct(string $item_type = '', $item_id = 0)
|
||||
{
|
||||
$this->objItemMediaModel = new ItemMediaModel($item_type, $item_id);
|
||||
parent::__construct($this->objItemMediaModel);
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInList(array $item_info) : array
|
||||
{
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInfo(array $item_info) : ?array
|
||||
{
|
||||
if(!$item_info) return null;
|
||||
|
||||
$item_info['display_file'] = STATIC_DOMAIN . "/". static::$image_folder. "/". $item_info['file_url'];
|
||||
$item_info['image'] = self::getResizedImageCollection($item_info['file_url']);
|
||||
|
||||
return $item_info;
|
||||
}
|
||||
|
||||
|
||||
public static function getResizedImageCollection($image_name) {
|
||||
$image = [];
|
||||
|
||||
$size_in_full = [
|
||||
's' => 'small' ,
|
||||
];
|
||||
|
||||
foreach (static::$resized_sizes as $size => $value) {
|
||||
$image[$size_in_full[$size]] = ($image_name) ? STATIC_DOMAIN . "/". static::$image_folder . "/". $size. IMAGE_FILE_SEPARATOR . $image_name : '';
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Media\Controller;
|
||||
|
||||
use Hura8\System\Controller\aCategoryBaseController;
|
||||
use Hura8\Components\Media\Model\MediaCategoryModel;
|
||||
|
||||
|
||||
class bMediaCategoryController extends aCategoryBaseController
|
||||
{
|
||||
|
||||
protected $objMediaCategoryModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objMediaCategoryModel = new MediaCategoryModel();
|
||||
parent::__construct($this->objMediaCategoryModel);
|
||||
}
|
||||
|
||||
}
|
||||
59
inc/Hura8/Components/Media/Controller/bMediaController.php
Normal file
59
inc/Hura8/Components/Media/Controller/bMediaController.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Media\Controller;
|
||||
|
||||
use Hura8\System\Controller\aAdminEntityBaseController;
|
||||
use Hura8\Components\Media\Model\MediaModel;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
|
||||
class bMediaController extends aEntityBaseController
|
||||
{
|
||||
static $image_folder = "media/lib";
|
||||
|
||||
static $resized_sizes = array(
|
||||
's' => ['width' => 300,]
|
||||
);
|
||||
|
||||
protected $objMediaModel;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objMediaModel = new MediaModel();
|
||||
parent::__construct($this->objMediaModel);
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInList(array $item_info) : array
|
||||
{
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInfo(array $item_info) : ?array
|
||||
{
|
||||
if(!$item_info) return null;
|
||||
|
||||
$item_info['display_file'] = STATIC_DOMAIN . "/". static::$image_folder. "/". $item_info['file_url'];
|
||||
$item_info['image'] = ($item_info['file_type'] == 'image') ? self::getResizedImageCollection($item_info['file_url']) : null;
|
||||
|
||||
return $item_info;
|
||||
}
|
||||
|
||||
|
||||
public static function getResizedImageCollection($image_name) {
|
||||
$image = [];
|
||||
|
||||
$size_in_full = [
|
||||
's' => 'small' ,
|
||||
];
|
||||
|
||||
foreach (static::$resized_sizes as $size => $value) {
|
||||
$image[$size_in_full[$size]] = ($image_name) ? STATIC_DOMAIN . "/". static::$image_folder . "/". $size. IMAGE_FILE_SEPARATOR . $image_name : '';
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
}
|
||||
76
inc/Hura8/Components/Media/Model/ItemMediaModel.php
Normal file
76
inc/Hura8/Components/Media/Model/ItemMediaModel.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Media\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\System\Url;
|
||||
|
||||
|
||||
class ItemMediaModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
protected $item_type;
|
||||
protected $item_id;
|
||||
|
||||
public function __construct(string $item_type = '', $item_id = 0) {
|
||||
parent::__construct('item-media');
|
||||
|
||||
$this->item_type = $item_type;
|
||||
$this->item_id = $item_id;
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
if($this->item_type) {
|
||||
$catCondition[] = " AND `item_type` = ? ";
|
||||
$bind_types[] = 's';
|
||||
$bind_values[] = $this->item_type;
|
||||
}
|
||||
|
||||
if($this->item_id) {
|
||||
$catCondition[] = " AND `item_id` = ? ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = $this->item_id;
|
||||
}
|
||||
|
||||
if(isset($filter_condition["item_type"]) && $filter_condition["item_type"]){
|
||||
$catCondition[] = " AND `item_type` = ? ";
|
||||
$bind_types[] = 's';
|
||||
$bind_values[] = $filter_condition["item_type"];
|
||||
}
|
||||
|
||||
if(isset($filter_condition["item_id"]) && $filter_condition["item_id"]){
|
||||
$catCondition[] = " AND `item_id` = ? ";
|
||||
$bind_types[] = 's';
|
||||
$bind_values[] = $filter_condition["item_id"];
|
||||
}
|
||||
|
||||
if(isset($filter_condition["file_type"]) && $filter_condition["file_type"]){
|
||||
$catCondition[] = " AND `file_type` = ? ";
|
||||
$bind_types[] = 's';
|
||||
$bind_values[] = $filter_condition["file_type"];
|
||||
}
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
34
inc/Hura8/Components/Media/Model/ItemMediaSearchModel.php
Normal file
34
inc/Hura8/Components/Media/Model/ItemMediaSearchModel.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Media\Model;
|
||||
|
||||
use Hura8\Interfaces\iSearch;
|
||||
use Hura8\System\Model\aSearchBaseModel;
|
||||
|
||||
|
||||
class ItemMediaSearchModel extends aSearchBaseModel implements iSearch
|
||||
{
|
||||
|
||||
private $filter_fields = [
|
||||
'item_type' => "tb_item_media.item_type",
|
||||
'item_id' => "tb_item_media.item_id",
|
||||
'file_type' => "tb_item_media.file_type",
|
||||
];
|
||||
|
||||
private $fulltext_fields = [
|
||||
"keywords" => ["tb_item_media.title",],
|
||||
];
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
"tb_item_media",
|
||||
$this->fulltext_fields,
|
||||
$this->filter_fields
|
||||
);
|
||||
|
||||
//$this->createTableSearch();
|
||||
}
|
||||
|
||||
}
|
||||
20
inc/Hura8/Components/Media/Model/MediaCategoryModel.php
Normal file
20
inc/Hura8/Components/Media/Model/MediaCategoryModel.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Media\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\System\Model\aCategoryBaseModel;
|
||||
use Hura8\Interfaces\iEntityCategoryModel;
|
||||
|
||||
|
||||
class MediaCategoryModel extends aCategoryBaseModel implements iEntityCategoryModel
|
||||
{
|
||||
protected $tb_media_per_category = "tb_media_per_category";
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct('media-category');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
61
inc/Hura8/Components/Media/Model/MediaModel.php
Normal file
61
inc/Hura8/Components/Media/Model/MediaModel.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Media\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
use Hura8\System\Url;
|
||||
|
||||
|
||||
class MediaModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
protected $tb_media_per_category = "tb_media_per_category";
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::MEDIA, '', new MediaSearchModel());
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
/*$condition = array(
|
||||
"category" => getRequestInt("category"),
|
||||
"file_type" => '',
|
||||
);*/
|
||||
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
|
||||
//Tim danh muc
|
||||
if(isset($filter_condition["category"]) && $filter_condition["category"]){
|
||||
$catCondition[] = " AND `id` IN (SELECT `item_id` FROM `".$this->tb_media_per_category."` WHERE `category_id` = ?) ";
|
||||
$bind_types[] = 'd';
|
||||
$bind_values[] = $filter_condition["category"];
|
||||
}
|
||||
|
||||
if(isset($filter_condition["file_type"]) && $filter_condition["file_type"]){
|
||||
$catCondition[] = " AND `file_type` = ? ";
|
||||
$bind_types[] = 's';
|
||||
$bind_values[] = $filter_condition["file_type"];
|
||||
}
|
||||
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
32
inc/Hura8/Components/Media/Model/MediaSearchModel.php
Normal file
32
inc/Hura8/Components/Media/Model/MediaSearchModel.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Media\Model;
|
||||
|
||||
use Hura8\Interfaces\iSearch;
|
||||
use Hura8\System\Model\aSearchBaseModel;
|
||||
|
||||
|
||||
class MediaSearchModel extends aSearchBaseModel implements iSearch
|
||||
{
|
||||
|
||||
private $filter_fields = [
|
||||
'file_type' => "tb_media.file_type",
|
||||
];
|
||||
|
||||
private $fulltext_fields = [
|
||||
"keywords" => ["tb_media.title",],
|
||||
];
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
"tb_media",
|
||||
$this->fulltext_fields,
|
||||
$this->filter_fields
|
||||
);
|
||||
|
||||
//$this->createTableSearch();
|
||||
}
|
||||
|
||||
}
|
||||
235
inc/Hura8/Components/Order/AdminController/AOrderController.php
Normal file
235
inc/Hura8/Components/Order/AdminController/AOrderController.php
Normal file
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Order\AdminController;
|
||||
|
||||
|
||||
use Hura8\Components\Order\Controller\OrderStatus;
|
||||
use Hura8\Components\Order\Model\OrderModel;
|
||||
use Hura8\Events\EventName;
|
||||
use Hura8\Events\RealEvents\OrderEvent;
|
||||
use Hura8\System\Controller\aAdminEntityBaseController;
|
||||
|
||||
class AOrderController extends aAdminEntityBaseController
|
||||
{
|
||||
|
||||
/* @var OrderModel $objOrderModel */
|
||||
protected $objOrderModel;
|
||||
|
||||
/* @var AOrderStatusController $objAOrderStatusController */
|
||||
protected $objAOrderStatusController;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objAOrderStatusController = new AOrderStatusController();
|
||||
$this->objOrderModel = new OrderModel();
|
||||
parent::__construct($this->objOrderModel);
|
||||
}
|
||||
|
||||
public function updateOrderFulfillmentStatus($order_id, $new_status, $comment, $payment_data = []) {
|
||||
|
||||
if(!array_key_exists($new_status, OrderStatus::FULFILLMENT_STATUS)) {
|
||||
return [
|
||||
"status" => 'error',
|
||||
'message' => '',
|
||||
];
|
||||
}
|
||||
|
||||
$this->objAOrderStatusController->createHistory($order_id, 'fulfillment', $new_status, $comment, $payment_data );
|
||||
|
||||
//cap nhat don hang
|
||||
$this->objOrderModel->update( $order_id, [
|
||||
'fulfillment_status' => $new_status
|
||||
]);
|
||||
|
||||
$this->updateDerivedOrderStatus($order_id);
|
||||
|
||||
return [
|
||||
"status" => 'success',
|
||||
'message' => 'Cập nhật thành công',
|
||||
];
|
||||
}
|
||||
|
||||
public function updateOrderPaymentStatus($order_id, $new_status, $comment, $payment_data = []) {
|
||||
|
||||
if(!array_key_exists($new_status, OrderStatus::PAYMENT_STATUS)) {
|
||||
return [
|
||||
"status" => 'error',
|
||||
'message' => '',
|
||||
];
|
||||
}
|
||||
|
||||
$this->objAOrderStatusController->createHistory($order_id, 'payment', $new_status, $comment, $payment_data );
|
||||
|
||||
//cap nhat don hang
|
||||
$this->objOrderModel->update( $order_id, [
|
||||
'payment_status' => $new_status
|
||||
]);
|
||||
|
||||
$this->updateDerivedOrderStatus($order_id);
|
||||
|
||||
return [
|
||||
"status" => 'success',
|
||||
'message' => 'Cập nhật thành công',
|
||||
];
|
||||
}
|
||||
|
||||
protected function updateDerivedOrderStatus($order_id) {
|
||||
|
||||
$current_info = $this->getInfo($order_id);
|
||||
|
||||
// order must be success
|
||||
if(
|
||||
$current_info['payment_status'] == OrderStatus::PAYMENT_STATUS['paid']['id'] &&
|
||||
$current_info['fulfillment_status'] == OrderStatus::FULFILLMENT_STATUS['fulfilled']['id']
|
||||
) {
|
||||
|
||||
return $this->objOrderModel->update($order_id, [
|
||||
'order_status' => OrderStatus::ORDER_STATUS['success']['id']
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// update processing
|
||||
return $this->objOrderModel->update($order_id, [
|
||||
'order_status' => OrderStatus::ORDER_STATUS['processing']['id']
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function updateOrderStatus($order_id, $status, $comment) {
|
||||
|
||||
$current_info = $this->getInfo($order_id);
|
||||
|
||||
// cannot update if order has: success or cancel
|
||||
if(in_array($current_info['order_status'], [
|
||||
OrderStatus::ORDER_STATUS['success']['id'],
|
||||
OrderStatus::ORDER_STATUS['canceled']['id'],
|
||||
])) {
|
||||
return [
|
||||
"status" => 'error',
|
||||
'message' => '',
|
||||
];
|
||||
}
|
||||
|
||||
if(!array_key_exists($status, OrderStatus::ORDER_STATUS)) {
|
||||
return [
|
||||
"status" => 'error',
|
||||
'message' => '',
|
||||
];
|
||||
}
|
||||
|
||||
$this->objAOrderStatusController->createHistory($order_id, 'order', $status, $comment );
|
||||
|
||||
$this->objOrderModel->update($order_id, [
|
||||
'order_status' => $status
|
||||
]);
|
||||
|
||||
// dispatch
|
||||
$objOrderEvent = new OrderEvent();
|
||||
$objOrderEvent->setUpdateOrderInfo([
|
||||
'orderId' => $order_id,
|
||||
'order_status' => $status,
|
||||
'old_status' => $current_info['order_status']
|
||||
]);
|
||||
get_dispatcher()->dispatch(EventName::ORDER['updated_status'], $objOrderEvent);
|
||||
|
||||
return [
|
||||
"status" => 'success',
|
||||
'message' => 'Cập nhật thành công',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInList(array $order_info ) {
|
||||
|
||||
$rs = $order_info;
|
||||
|
||||
$rs["order_date"] = date("d-m-Y", $rs['order_time']);
|
||||
$rs["order_hour"] = date("h:i a", $rs['order_time']);
|
||||
|
||||
if($rs['order_discount']) $rs['order_discount'] = \json_decode($rs['order_discount'], true);
|
||||
|
||||
$rs["payment_status_name"] = (array_key_exists($rs["payment_status"], OrderStatus::PAYMENT_STATUS)) ? OrderStatus::PAYMENT_STATUS[$rs["payment_status"]]['title'] : '';
|
||||
|
||||
$rs["fulfillment_status_name"] = (array_key_exists($rs["fulfillment_status"], OrderStatus::FULFILLMENT_STATUS)) ? OrderStatus::FULFILLMENT_STATUS[$rs["fulfillment_status"]]['title'] : '';
|
||||
|
||||
$rs["order_status_name"] = (array_key_exists($rs["order_status"], OrderStatus::ORDER_STATUS)) ? OrderStatus::ORDER_STATUS[$rs["order_status"]]['title'] : '';
|
||||
|
||||
return $rs;
|
||||
}
|
||||
|
||||
protected function getListFilterCondition($list_id) {
|
||||
|
||||
if($list_id == 'mine') {
|
||||
return [
|
||||
'assign_to' => ADMIN_ID,
|
||||
];
|
||||
}
|
||||
|
||||
if($list_id == 'new') {
|
||||
return [
|
||||
'status' => 'new',
|
||||
];
|
||||
}
|
||||
|
||||
if($list_id == 'unpaid') {
|
||||
return [
|
||||
'payment' => 'unpaid',
|
||||
];
|
||||
}
|
||||
|
||||
if($list_id == 'partially-paid') {
|
||||
return [
|
||||
'payment' => 'partially-paid',
|
||||
];
|
||||
}
|
||||
|
||||
if($list_id == 'unfulfilled') {
|
||||
return [
|
||||
'fullfillment' => 'unfulfilled',
|
||||
];
|
||||
}
|
||||
|
||||
if($list_id == 'partially-fulfilled') {
|
||||
return [
|
||||
'fullfillment' => 'partially-fulfilled',
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getStatusHistory($orderId){
|
||||
|
||||
return $this->objAOrderStatusController->getStatusHistory($orderId);
|
||||
|
||||
}
|
||||
|
||||
public function getItemsForOrderList(array $list_ids, $fields = "*") {
|
||||
|
||||
return $this->objOrderModel->getItemsForOrderList($list_ids, $fields);
|
||||
|
||||
}
|
||||
|
||||
public static function createId($order_id){
|
||||
$key_length = strlen($order_id);
|
||||
|
||||
$order_keys = [];
|
||||
for($i=0; $i < 9 - $key_length; $i++){
|
||||
$order_keys[] = "0";
|
||||
}
|
||||
$order_keys[] = $order_id;
|
||||
|
||||
$order_eles = str_split(join("", $order_keys), 3);
|
||||
|
||||
return join("-", $order_eles);
|
||||
}
|
||||
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Order\AdminController;
|
||||
|
||||
use Hura8\Components\Order\Model\OrderStatusModel;
|
||||
|
||||
class AOrderStatusController
|
||||
{
|
||||
/* @var OrderStatusModel $objOrderStatusModel */
|
||||
protected $objOrderStatusModel;
|
||||
|
||||
public function __construct() {
|
||||
$this->objOrderStatusModel = new OrderStatusModel();
|
||||
}
|
||||
|
||||
public function getStatusHistory($orderId){
|
||||
return $this->objOrderStatusModel->getStatusHistory($orderId);
|
||||
}
|
||||
|
||||
public function createHistory($order_id, $status_type = 'order', $system_status = '', $comment = '', array $data= [], array $other_info = []) {
|
||||
return $this->objOrderStatusModel->createHistory($order_id, $status_type , $system_status , $comment, $data, $other_info);
|
||||
}
|
||||
|
||||
public function getInfo($status_id) {
|
||||
return $this->objOrderStatusModel->getInfo($status_id);
|
||||
}
|
||||
|
||||
public function getAll() {
|
||||
return $this->objOrderStatusModel->getAll();
|
||||
}
|
||||
|
||||
public function delete($id) {
|
||||
return $this->objOrderStatusModel->delete($id);
|
||||
}
|
||||
|
||||
public function update($id, array $info) {
|
||||
return $this->objOrderStatusModel->update($id, $info);
|
||||
}
|
||||
|
||||
public function create(array $info) {
|
||||
return $this->objOrderStatusModel->create($info);
|
||||
}
|
||||
}
|
||||
43
inc/Hura8/Components/Order/Controller/OrderStatus.php
Normal file
43
inc/Hura8/Components/Order/Controller/OrderStatus.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
// https://help.shopify.com/en/manual/orders/order-status
|
||||
|
||||
namespace Hura8\Components\Order\Controller;
|
||||
|
||||
|
||||
class OrderStatus
|
||||
{
|
||||
|
||||
const ORDER_STATUS = [
|
||||
'new' => ['id' => 'new', 'title' => 'Mới'],// 'Mới', //
|
||||
'processing' => ['id' => 'processing', 'title' => 'Đang xử lý'],// 'Đang xử lý', //
|
||||
'success' => ['id' => 'success', 'title' => 'Thành công'],// 'Thành công', //
|
||||
'closed' => ['id' => 'closed', 'title' => 'Đóng lại'],// 'Đóng lại', //
|
||||
//'archived' => 'Lưu kho', //
|
||||
'canceled' => ['id' => 'canceled', 'title' => 'Hủy'],// 'Hủy', //
|
||||
];
|
||||
|
||||
const PAYMENT_STATUS = [
|
||||
'pending' => ['id' => 'pending', 'title' => 'Chờ'],// 'Chờ', // Orders have the Payment pending status for one of the following reasons: During checkout, You create an order, Manual payment methods, such as Cash On Delivery
|
||||
'authorized' => ['id' => 'authorized', 'title' => 'Đã xác nhận'],// 'Đã xác nhận', // The payment provider validated your customer’s payment information. The order is created, customers can complete their checkout, and inventory is reserved.
|
||||
'overdue' => ['id' => 'overdue', 'title' => 'Quá hạn'],// 'Quá hạn', // Payment wasn't captured before the due date that was set in the payment terms on an order that had the Payment pending status.
|
||||
'expiring' => ['id' => 'expiring', 'title' => 'Sắp hết hạn'],// 'Sắp hết hạn', // Expiring isn't a payment status, but the Expiring badge is displayed two days before the deadline for capturing payment on orders that have the Authorized payment status.
|
||||
'expired' => ['id' => 'expired', 'title' => 'Hết hạn'],// 'Hết hạn', // Payment wasn't captured before the date that was set by the payment provider on an order that had the Authorized payment status.
|
||||
'paid' => ['id' => 'paid', 'title' => 'Đã thanh toán'],// 'Đã thanh toán', // Payment was automatically or manually captured, or the order was marked as paid.
|
||||
'refunded' => ['id' => 'refunded', 'title' => 'Đã hoàn lại'],// 'Đã hoàn lại', // The full amount that the customer paid for an order was returned to the customer.
|
||||
'partially-refunded' => ['id' => 'partially-refunded', 'title' => 'Hoàn lại 1 phần'],// 'Hoàn lại 1 phần', // The amount that was returned to a customer is less than the full amount that the customer paid for an order.
|
||||
'partially-paid' => ['id' => 'partially-paid', 'title' => 'Thanh toán 1 phần'],// 'Thanh toán 1 phần', // You manually captured payment for the order and specified less than the full order value as the payment amount.
|
||||
'voided' => ['id' => 'voided', 'title' => 'Hủy'],// 'Hủy', // An unpaid order was manually canceled.
|
||||
'unpaid' => ['id' => 'unpaid', 'title' => 'Chưa thanh toán'],// 'Chưa thanh toán', // Unpaid payment status includes orders that are in Authorized, Pending, Expired, and Partially paid payment status.
|
||||
];
|
||||
|
||||
const FULFILLMENT_STATUS = [
|
||||
'fulfilled' => ['id' => 'fulfilled', 'title' => 'Đã chuyển hết'],// 'Đã chuyển hết', // When you've shipped all the items in an order, it is Fulfilled.
|
||||
'unfulfilled' => ['id' => 'unfulfilled', 'title' => 'Chưa chuyển'],// 'Chưa chuyển', // When an order is placed, it has an Unfulfilled fulfillment status, unless you have selected to automatically capture the payment and automatically fulfill all of the order's line items in the checkout settings.
|
||||
'partially-fulfilled' => ['id' => 'partially-fulfilled', 'title' => 'Chuyển 1 phần'],// 'Chuyển 1 phần', // If you have shipped some, but not all, of the items in an order, then the order has a Partially fulfilled fulfillment status.
|
||||
'scheduled' => ['id' => 'scheduled', 'title' => 'Đã lên kế hoạch'],// 'Đã lên kế hoạch', // Prepaid subscription orders have a Scheduled status until the fulfillment date is reached
|
||||
'onhold ' => ['id' => 'onhold', 'title' => 'Giữ hàng'],// 'Giữ hàng', // When upsell offers are presented to customers at checkout, the order fulfillment status is set to On hold temporarily. When a fulfillment is On hold you can reserve inventory for the order, but you can't fulfill the order until the fulfillment hold is released, and the order fulfillment status changes to Unfulfilled.
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
557
inc/Hura8/Components/Order/Model/OrderModel.php
Normal file
557
inc/Hura8/Components/Order/Model/OrderModel.php
Normal file
@@ -0,0 +1,557 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Order\Model;
|
||||
|
||||
|
||||
use Hura8\Components\Order\Controller\OrderStatus;
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\Interfaces\iSearch;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\System\Security\DataClean;
|
||||
use Hura8\System\Security\DataType;
|
||||
use Hura8\System\TimeManager;
|
||||
use Hura8\System\Url;
|
||||
|
||||
class OrderModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
protected $tb_order_detail = "tb_order_detail";
|
||||
|
||||
/* @var iSearch $objSearchModel */
|
||||
protected $objSearchModel;
|
||||
|
||||
public function __construct() {
|
||||
|
||||
$this->objSearchModel = new OrderSearchModel();
|
||||
|
||||
parent::__construct(EntityType::ORDER, '', $this->objSearchModel);
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getItems($orderId, $fields = "*") {
|
||||
$query = $this->db->runQuery(
|
||||
" SELECT ".$fields." FROM `".$this->tb_order_detail."` WHERE `order_id` = ? ",
|
||||
['d'], [ $orderId ]);
|
||||
|
||||
$order_item = array();
|
||||
foreach ( $this->db->fetchAll($query) as $info ) {
|
||||
|
||||
$item_info = ($info["item_info"]) ? \json_decode($info["item_info"], true) : false;
|
||||
$in_cart = ($info["in_cart"]) ? \json_decode($info["in_cart"], true) : false;
|
||||
|
||||
|
||||
$info['item_info'] = $item_info;
|
||||
$info['in_cart'] = $in_cart;
|
||||
|
||||
$order_item[] = $info;
|
||||
}
|
||||
|
||||
return $order_item;
|
||||
}
|
||||
|
||||
//since we save the entire cart-structure for item_info, we need to re-construct it to make it easier to read and for various reporting/ email etc..
|
||||
protected function buildOrderItemInfo($item_type, array $item_info) {
|
||||
$new_info = [];
|
||||
|
||||
if($item_type == 'product') {
|
||||
|
||||
$new_info = System::stripProperty(array($item_info['info']), [
|
||||
"variant_option",
|
||||
'id',
|
||||
'productId',
|
||||
'priceUnit',
|
||||
'price',
|
||||
'currency',
|
||||
'lastUpdate',
|
||||
'warranty',
|
||||
'productName',
|
||||
'productUrl',
|
||||
'productModel',
|
||||
'productSummary',
|
||||
'marketPrice',
|
||||
'productImage',
|
||||
'brand',
|
||||
'visit',
|
||||
'rating',
|
||||
'reviewCount',
|
||||
'quantity',
|
||||
'productSKU',
|
||||
'hasVAT',
|
||||
'condition',
|
||||
'specialOffer',
|
||||
'specialOfferGroup',
|
||||
'productType',
|
||||
'thum_poster',
|
||||
'promotion_price',
|
||||
'addon'
|
||||
])[0];
|
||||
|
||||
//find variants bought
|
||||
if($new_info['config_count'] > 0) {
|
||||
|
||||
foreach ($item_info['in_cart'] as $_variant) {
|
||||
$new_info['variants'][] = array(
|
||||
"id" => $_variant['id'],
|
||||
"sku" => $_variant['sku'],
|
||||
"title" => $_variant['name'],
|
||||
"image" => ($_variant['image']) ? $_variant['image'] : $item_info['info']['productImage']["medium"],
|
||||
"url" => $item_info['info']['productUrl'],
|
||||
"attribute" => $_variant['attribute'],
|
||||
"price" => $_variant['price'],
|
||||
"addon_total" => 0,
|
||||
"currency" => $item_info['info']['currency'],
|
||||
"priceUnit" => $item_info['info']['priceUnit'],
|
||||
"quantity" => $_variant['quantity'],
|
||||
"buyer_note" => $_variant['buyer_note'],
|
||||
"addon" => [],
|
||||
"promotion" => [
|
||||
"list" => $item_info['info']['specialOffer'],
|
||||
"group" => (isset($_variant['promotion'])) ? $this->buildPromotionFromGroup( $item_info['info']['specialOfferGroup'], $_variant['promotion']) : $this->buildPromotionFromGroup( $item_info['info']['specialOfferGroup'], array() ),
|
||||
],
|
||||
//..any other
|
||||
);
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
//product does not have variant
|
||||
$build_addon = [];
|
||||
$total_addon_price = 0;
|
||||
if(isset($item_info['info']['addon']) && isset($item_info['in_cart'][0]['addon'])) {
|
||||
$build_addon = $this->getSelectedAddon($item_info['info']['addon'], $item_info['in_cart'][0]['addon']);
|
||||
foreach ($build_addon as $addon) {
|
||||
$total_addon_price += $addon['price'] * $addon['quantity'];
|
||||
}
|
||||
}
|
||||
|
||||
$variant_in_cart = (isset($item_info['in_cart'][0])) ? $item_info['in_cart'][0] : false;
|
||||
|
||||
$new_info['variants'][] = array(
|
||||
"id" => 0,
|
||||
"sku" => $item_info['info']['productSKU'],
|
||||
"title" => $item_info['info']['productName'],
|
||||
"image" => $item_info['info']['productImage']["medium"],
|
||||
"url" => $item_info['info']['productUrl'],
|
||||
"attribute" => [],
|
||||
"price" => $item_info['info']['price'],
|
||||
"addon_total" => $total_addon_price,
|
||||
"currency" => $item_info['info']['currency'],
|
||||
"priceUnit" => $item_info['info']['priceUnit'],
|
||||
"quantity" => $variant_in_cart['quantity'],
|
||||
"buyer_note" => $variant_in_cart['buyer_note'],
|
||||
"addon" => $build_addon,
|
||||
"promotion" => [
|
||||
"list" => $item_info['info']['specialOffer'],
|
||||
"group" => (isset($variant_in_cart['promotion'])) ? $this->buildPromotionFromGroup( $item_info['info']['specialOfferGroup'], $variant_in_cart['promotion']) : $this->buildPromotionFromGroup( $item_info['info']['specialOfferGroup'], array() ),
|
||||
],
|
||||
//..any other
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
return $new_info;
|
||||
}
|
||||
|
||||
if($item_type == 'combo') {
|
||||
|
||||
$new_info = [
|
||||
"price" => $item_info['info']['sale_price'],
|
||||
"quantity" => $item_info['in_cart']['quantity'],
|
||||
"buyer_note" => $item_info['in_cart']['buyer_note'],
|
||||
"url" => '',
|
||||
];
|
||||
|
||||
$new_info['product_list'] = System::stripProperty($item_info['info']['product_list'], [
|
||||
"variant_option",
|
||||
'id',
|
||||
'productId',
|
||||
'priceUnit',
|
||||
'price',
|
||||
'currency',
|
||||
'lastUpdate',
|
||||
'warranty',
|
||||
//'productName',
|
||||
//'productUrl',
|
||||
//'productModel',
|
||||
'productSummary',
|
||||
'marketPrice',
|
||||
'productImage',
|
||||
'brand',
|
||||
'visit',
|
||||
'rating',
|
||||
'reviewCount',
|
||||
'config_count',
|
||||
'quantity',
|
||||
//'productSKU',
|
||||
'hasVAT',
|
||||
'condition',
|
||||
'specialOffer',
|
||||
'specialOfferGroup',
|
||||
'productType',
|
||||
'thum_poster',
|
||||
'promotion_price',
|
||||
'addon',
|
||||
'imageCollection',
|
||||
'variants'
|
||||
]);
|
||||
|
||||
return $new_info;
|
||||
}
|
||||
|
||||
if($item_type == 'deal') {
|
||||
|
||||
$new_info = [
|
||||
"price" => $item_info['info']['price'],
|
||||
"quantity" => $item_info['in_cart']['quantity'],
|
||||
"buyer_note" => $item_info['in_cart']['buyer_note'],
|
||||
"url" => '/deal/'.$item_info['info']['id'],
|
||||
];
|
||||
|
||||
return $new_info;
|
||||
}
|
||||
|
||||
return $new_info;
|
||||
}
|
||||
|
||||
protected function getSelectedAddon($all_product_addons, $in_cart) {
|
||||
|
||||
if(!is_array($all_product_addons) || !is_array($in_cart)) return [];
|
||||
|
||||
$result = [];
|
||||
foreach ($all_product_addons as $item) {
|
||||
foreach ($in_cart as $selected) {
|
||||
if($item['addon_id'] == $selected['id']) {
|
||||
$result[] = [
|
||||
"id" => $selected['id'],
|
||||
"title" => $item['title'],
|
||||
"price" => $item['price'],
|
||||
"quantity" => (isset($selected['quantity'])) ? intval($selected['quantity']) : 1,
|
||||
"related_article_url" => $item['related_article_url'],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function buildPromotionFromGroup( $offer_group, $selected_one_promotion) {
|
||||
|
||||
if(!is_array($offer_group) && !is_array($selected_one_promotion)) return false;
|
||||
|
||||
$promotion = [];
|
||||
|
||||
foreach ($offer_group as $group) {
|
||||
if($group['type'] == 'one') {
|
||||
|
||||
$selected_promotion = [];
|
||||
foreach ($group['promotion'] as $promo) {
|
||||
foreach ($selected_one_promotion as $selected) {
|
||||
if($selected['promotion_id'] == $promo['id'] && $selected['group_id'] == $group['id']) {
|
||||
$selected_promotion[] = $promo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$promotion[] = [
|
||||
"id" => $group['id'],
|
||||
"title" => $group['title'],
|
||||
"note" => $group['note'],
|
||||
"promotion" => $selected_promotion,
|
||||
];
|
||||
|
||||
|
||||
}else{
|
||||
$promotion[] = [
|
||||
"id" => $group['id'],
|
||||
"title" => $group['title'],
|
||||
"note" => $group['note'],
|
||||
"promotion" => $group['promotion'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $promotion;
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected function getListFilterCondition($list_id) {
|
||||
|
||||
if($list_id == 'mine') {
|
||||
return [
|
||||
'assign_to' => ADMIN_ID,
|
||||
];
|
||||
}
|
||||
|
||||
if($list_id == 'new') {
|
||||
return [
|
||||
'status' => 'new',
|
||||
];
|
||||
}
|
||||
|
||||
if($list_id == 'unpaid') {
|
||||
return [
|
||||
'payment' => 'unpaid',
|
||||
];
|
||||
}
|
||||
|
||||
if($list_id == 'partially-paid') {
|
||||
return [
|
||||
'payment' => 'partially-paid',
|
||||
];
|
||||
}
|
||||
|
||||
if($list_id == 'unfulfilled') {
|
||||
return [
|
||||
'fullfillment' => 'unfulfilled',
|
||||
];
|
||||
}
|
||||
|
||||
if($list_id == 'partially-fulfilled') {
|
||||
return [
|
||||
'fullfillment' => 'partially-fulfilled',
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getStatusHistory($orderId){
|
||||
$query = $this->db->runQuery("
|
||||
select * from ".TB_ORDER_STATUS_HISTORY."
|
||||
WHERE order_id = ?
|
||||
order by id desc
|
||||
limit 100
|
||||
", ['d'], [ $orderId ] ) ;
|
||||
|
||||
return $this->db->fetchAll($query);
|
||||
}
|
||||
|
||||
public function getItemsForOrderList(array $list_ids, $fields = "*") {
|
||||
|
||||
if(!sizeof($list_ids)) return [];
|
||||
|
||||
list($parameterized_ids, $bind_types) = create_bind_sql_parameter_from_value_list($list_ids, 'int');
|
||||
|
||||
$query = $this->db->runQuery("
|
||||
SELECT ".$fields." FROM `".$this->tb_order_detail."`
|
||||
WHERE `order_id` IN (".$parameterized_ids.")
|
||||
", $bind_types, $list_ids);
|
||||
|
||||
$result = array();
|
||||
foreach ( $this->db->fetchAll($query) as $rs ) {
|
||||
|
||||
$item_info = unserialize($rs['item_info']);
|
||||
if( isset($item_info["info"]) && isset($item_info["in_cart"])) {
|
||||
$rs['item_info'] = $this->buildOrderItemInfo($rs['item_type'], $item_info );
|
||||
} else {
|
||||
$rs['item_info'] = null;
|
||||
}
|
||||
|
||||
$result[$rs['order_id']][] = $rs;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function _buildQueryConditionExtend(array $conditions) : ?array
|
||||
{
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
/*
|
||||
$conditions = array(
|
||||
'orderCode' => '',
|
||||
'query' => '',
|
||||
'coupon' => '',
|
||||
'cus_id' => '',
|
||||
'province' => '',
|
||||
'district' => '',
|
||||
'folder' => '',
|
||||
'view_status' => '',
|
||||
'update_by' => '',
|
||||
'shipping_status' => '',
|
||||
'assign_to' => '',
|
||||
'from_date' => '',
|
||||
'to_date' => '',
|
||||
'from_hour' => '',
|
||||
'to_hour' => '',
|
||||
'excluded_ids' => '',
|
||||
'included_ids' => '',
|
||||
'payment' => '',
|
||||
'fullfillment' => '',
|
||||
'list' => '',
|
||||
);*/
|
||||
|
||||
|
||||
// merge with special list
|
||||
if(isset($conditions['list']) && $conditions['list']) {
|
||||
$list_condition = $this->getListFilterCondition($conditions['list']);
|
||||
if($list_condition) {
|
||||
// update and over-write any key in $conditions if exist
|
||||
foreach ($list_condition as $key => $value) {
|
||||
$conditions[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($conditions['orderCode']) && $conditions['orderCode']) {
|
||||
$orderCode = DataClean::makeInputSafe($conditions['orderCode'],DataType::INTEGER);
|
||||
$catCondition[] = " AND `orderId` LIKE '".$orderCode."%' ";
|
||||
}
|
||||
|
||||
if(isset($conditions['coupon']) && $conditions['coupon']) {
|
||||
$coupon = preg_replace("/[^a-z0-9_\-\.]/i","", $conditions['coupon']);
|
||||
if($coupon) $catCondition[] = " AND ( LENGTH(`order_discount`) > 10 AND `order_discount` LIKE '%".$coupon."%' ) ";
|
||||
}
|
||||
|
||||
if(isset($conditions['cus_id']) && $conditions['cus_id']) {
|
||||
$catCondition[] = " AND buyerId = '".intval($conditions['cus_id'])."'";
|
||||
}
|
||||
|
||||
if(isset($conditions['province']) && $conditions['province']) {
|
||||
$catCondition[] = " AND province = '".intval($conditions['province'])."'";
|
||||
}
|
||||
|
||||
if(isset($conditions['district']) && $conditions['district']) {
|
||||
$catCondition[] = " AND district = '".intval($conditions['district'])."'";
|
||||
}
|
||||
|
||||
if(isset($conditions['folder']) && $conditions['folder']) {
|
||||
$catCondition[] = " AND `folder` = '". preg_replace("/[^a-z0-9_\-\.]/i", "", $conditions['folder'])."' ";
|
||||
}
|
||||
|
||||
if(isset($conditions['payment']) && array_key_exists($conditions['payment'], OrderStatus::PAYMENT_STATUS ) ) {
|
||||
$catCondition[] = " AND `payment_status` = '". $this->db->escape($conditions['payment'])."' ";
|
||||
}
|
||||
|
||||
if(isset($conditions['fullfillment']) && array_key_exists($conditions['fullfillment'], OrderStatus::FULFILLMENT_STATUS) ) {
|
||||
$catCondition[] = " AND `fulfillment_status` = '". $this->db->escape($conditions['fullfillment'])."' ";
|
||||
}
|
||||
|
||||
if(isset($conditions['status']) && array_key_exists($conditions['status'], OrderStatus::ORDER_STATUS) ) {
|
||||
$catCondition[] = " AND `order_status` = '". $this->db->escape($conditions['status'])."' ";
|
||||
}
|
||||
|
||||
if(isset($conditions['view_status']) && $conditions['view_status']) {
|
||||
if($conditions['view_status'] == 'no-status') {
|
||||
$catCondition[] = " AND `status_id` = 0 ";
|
||||
} else {
|
||||
$catCondition[] = " AND `status_id` = '". intval($conditions['view_status'])."' ";
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($conditions['update_by']) && $conditions['update_by']) {
|
||||
$catCondition[] = " AND `status_update_by` = '". $this->db->escape($conditions['update_by'])."' ";
|
||||
}
|
||||
|
||||
if(isset($conditions['shipping_status']) && $conditions['shipping_status']) {
|
||||
$catCondition[] = " AND `admin_shipping_status` = '". preg_replace("/[^a-z0-9_\-\.]/i", "", $conditions['shipping_status'])."' ";
|
||||
}
|
||||
|
||||
if(isset($conditions['assign_to']) && $conditions['assign_to']) {
|
||||
$catCondition[] = " AND `assign_to` = '". intval($conditions['assign_to'])."' ";
|
||||
}
|
||||
|
||||
//filter by date
|
||||
if(isset($conditions['from_date']) && $conditions['from_date']) {
|
||||
$catCondition[] = " AND order_time >= '". intval(strtotime(TimeManager::convert_date_from_javascript($conditions['from_date'])." 00:00"))."' ";
|
||||
}
|
||||
|
||||
if(isset($conditions['to_date']) && $conditions['to_date']) {
|
||||
$catCondition[] = " AND order_time <= '".strtotime(TimeManager::convert_date_from_javascript($conditions['to_date'])." 23:59")."' ";
|
||||
}
|
||||
|
||||
//filter by hour
|
||||
if(isset($conditions['from_hour']) && $conditions['from_hour']) {
|
||||
$catCondition[] = " AND `order_hour` >= '".intval($conditions['from_hour'])."' ";
|
||||
}
|
||||
if(isset($conditions['to_hour']) && $conditions['to_hour']) {
|
||||
$catCondition[] = " AND `order_hour` <= '".intval($conditions['to_hour'])."' ";
|
||||
}
|
||||
|
||||
if(isset($conditions["excluded_ids"]) && $conditions["excluded_ids"] ){
|
||||
$list_ids = filterNumber(explode(",", $conditions["excluded_ids"]));
|
||||
if(sizeof($list_ids)) $catCondition[] = " AND `orderId` NOT IN (".join(',', $list_ids ).") ";
|
||||
}
|
||||
|
||||
if(isset($conditions["included_ids"]) && $conditions["included_ids"] ){
|
||||
$list_ids = filterNumber(explode(",", $conditions["included_ids"]));
|
||||
if(sizeof($list_ids)) $catCondition[] = " AND `orderId` IN (".join(',', $list_ids ).") ";
|
||||
}
|
||||
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
protected function beforeCreateItem(array $input_info) : AppResponse
|
||||
{
|
||||
$info = $input_info;
|
||||
|
||||
if(isset($info['file_external_url'])) {
|
||||
if($info['file_external_url'] && !Url::isUrlValid($info['file_external_url'])) {
|
||||
$info['file_external_url'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$info['create_time'] = CURRENT_TIME;
|
||||
$info['create_by'] = ADMIN_NAME;
|
||||
$info['last_update'] = CURRENT_TIME;
|
||||
$info['last_update_by'] = ADMIN_NAME;
|
||||
|
||||
return new AppResponse('ok', null, $info);
|
||||
}
|
||||
|
||||
|
||||
protected function beforeUpdateItem($item_id, $current_item_info, $new_input_info) : AppResponse
|
||||
{
|
||||
$info = $new_input_info;
|
||||
|
||||
unset($info['id']);
|
||||
|
||||
if(isset($info['file_external_url']) && $info['file_external_url'] && !Url::isUrlValid($info['file_external_url'])) {
|
||||
$info['file_external_url'] = '';
|
||||
}
|
||||
|
||||
$info['last_update'] = CURRENT_TIME;
|
||||
$info['last_update_by'] = ADMIN_NAME;
|
||||
|
||||
return new AppResponse('ok', null, $info);
|
||||
}
|
||||
|
||||
protected function beforeDeleteItem($item_id, $item_info) : AppResponse
|
||||
{
|
||||
return new AppResponse('ok');
|
||||
}
|
||||
|
||||
protected function afterDeleteItem($item_id, $item_info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected function afterCreateItem($new_item_id, $new_item_info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function afterUpdateItem($item_id, $old_item_info, $new_item_info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
30
inc/Hura8/Components/Order/Model/OrderSearchModel.php
Normal file
30
inc/Hura8/Components/Order/Model/OrderSearchModel.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Order\Model;
|
||||
|
||||
use Hura8\Interfaces\iSearch;
|
||||
use Hura8\System\Model\aSearchBaseModel;
|
||||
|
||||
|
||||
class OrderSearchModel extends aSearchBaseModel implements iSearch
|
||||
{
|
||||
|
||||
private $filter_fields = [
|
||||
"folder" => "tb_order.price",
|
||||
];
|
||||
|
||||
private $fulltext_fields = [
|
||||
"keywords" => ["tb_order.buyerName", ],
|
||||
];
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
"tb_order",
|
||||
$this->fulltext_fields,
|
||||
$this->filter_fields
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
94
inc/Hura8/Components/Order/Model/OrderStatusModel.php
Normal file
94
inc/Hura8/Components/Order/Model/OrderStatusModel.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Order\Model;
|
||||
|
||||
use Hura8\Database\iConnectDB;
|
||||
|
||||
class OrderStatusModel
|
||||
{
|
||||
|
||||
/* @var iConnectDB $db */
|
||||
protected $db;
|
||||
|
||||
protected $tb_status = 'tb_order_status';
|
||||
protected $tb_status_history = 'tb_order_status_history';
|
||||
|
||||
public function __construct() {
|
||||
$this->db = get_db('', ENABLE_DB_DEBUG);
|
||||
}
|
||||
|
||||
public function getStatusHistory($orderId){
|
||||
$query = $this->db->runQuery("
|
||||
select * from ".$this->tb_status_history."
|
||||
WHERE order_id = ?
|
||||
order by id desc
|
||||
limit 100
|
||||
", ['d'], [ $orderId ] ) ;
|
||||
|
||||
return $this->db->fetchAll($query);
|
||||
}
|
||||
|
||||
public function createHistory($order_id, $status_type = 'order', $system_status = '', $comment = '', array $data= [], array $other_info = []) {
|
||||
|
||||
$info = $other_info;
|
||||
|
||||
$info['order_id'] = $order_id;
|
||||
$info['status_type'] = $status_type;
|
||||
$info['system_status'] = $system_status;
|
||||
$info['data'] = \json_encode($data);
|
||||
$info['comment'] = substr($comment, 0, 150);
|
||||
$info['create_time'] = CURRENT_TIME;
|
||||
$info['create_by'] = (defined('ADMIN_NAME')) ? ADMIN_NAME : '';
|
||||
|
||||
return $this->db->insert($this->tb_status_history, $info);
|
||||
}
|
||||
|
||||
public function getCustomerCancelStatusId() {
|
||||
$info = $this->db->select($this->tb_status, ['id'], [
|
||||
"system_status" => ["=", "cancel"],
|
||||
'message' => 'Khách hàng hủy',
|
||||
], '', 1);
|
||||
|
||||
if($info) {
|
||||
return $info['id'];
|
||||
}
|
||||
|
||||
// create and return
|
||||
return $this->create([
|
||||
'message' => 'Khách hàng hủy',
|
||||
'system_status' => "cancel",
|
||||
'create_time' => CURRENT_TIME,
|
||||
'create_by' => 'System',
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function getInfo($status_id) {
|
||||
return $this->db->getItemInfo($this->tb_status, $status_id, 'id');
|
||||
}
|
||||
|
||||
public function getAll() {
|
||||
$query = $this->db->runQuery(" select * from ".$this->tb_status." order by `id` desc ") ;
|
||||
$item_list = array();
|
||||
foreach ( $this->db->fetchAll($query) as $rs ) {
|
||||
if(!$rs['system_status']) $rs['system_status'] = 'new';
|
||||
//$rs['system_order_status'] = System::$ORDER_STATUS[$rs['system_status']];
|
||||
$item_list[] = $rs;
|
||||
}
|
||||
|
||||
return $item_list;
|
||||
}
|
||||
|
||||
public function delete($id) {
|
||||
return $this->db->runQuery("DELETE FROM ".$this->tb_status." WHERE `id` = ? limit 1 ", ['d'], [ $id ]) ;
|
||||
}
|
||||
|
||||
public function update($id, array $info) {
|
||||
return $this->db->update($this->tb_status, $info, ['id' => $id]);
|
||||
}
|
||||
|
||||
public function create(array $info) {
|
||||
return $this->db->insert($this->tb_status, $info);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Page\AdminController;
|
||||
|
||||
use Hura8\Components\Page\Controller\bPageController;
|
||||
use Hura8\Interfaces\iEntityAdminController;
|
||||
use Hura8\Traits\AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
class APageController extends bPageController implements iEntityAdminController
|
||||
{
|
||||
|
||||
use AdminEntityBaseControllerTraits;
|
||||
|
||||
|
||||
public function updateTableInfo($item_id, array $new_item_info) {
|
||||
return $this->objPageModel->updateTableInfo($item_id, $new_item_info);
|
||||
}
|
||||
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
// delete thumb files
|
||||
$item_info = $this->getInfo($item_id);
|
||||
$this->deleteThumbnailFile($item_info['thumbnail']);
|
||||
|
||||
//delete media files?
|
||||
// todo:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected function deleteThumbnailFile($file_name): bool
|
||||
{
|
||||
if(!$file_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (self::$resized_sizes as $size => $value) {
|
||||
$file_local_path = PUBLIC_DIR . "/". self::$image_folder . "/". $size. IMAGE_FILE_SEPARATOR . $file_name;
|
||||
unlink($file_local_path);
|
||||
}
|
||||
|
||||
// remove original file
|
||||
$file_local_path = PUBLIC_DIR . "/". self::$image_folder . "/". $file_name;
|
||||
return unlink($file_local_path);
|
||||
}
|
||||
|
||||
}
|
||||
92
inc/Hura8/Components/Page/Controller/bPageController.php
Normal file
92
inc/Hura8/Components/Page/Controller/bPageController.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Page\Controller;
|
||||
|
||||
|
||||
use Hura8\Components\Page\Model\PageLanguageModel;
|
||||
use Hura8\Components\Page\Model\PageModel;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
|
||||
class bPageController extends aEntityBaseController
|
||||
{
|
||||
|
||||
static $image_folder = "media/static";
|
||||
|
||||
static $resized_sizes = array(
|
||||
't' => ['width' => 200,] ,
|
||||
'l' => ['width' => 600,] ,
|
||||
);
|
||||
|
||||
|
||||
protected $objPageModel;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objPageModel = new PageModel();
|
||||
|
||||
if(!$this->isDefaultLanguage()) {
|
||||
//$this->objPageLanguageModel->createTableLang();
|
||||
parent::__construct($this->objPageModel, new PageLanguageModel());
|
||||
}else{
|
||||
parent::__construct($this->objPageModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// get full info- basic with description
|
||||
public function getFullInfo($id) : ?array
|
||||
{
|
||||
if(!$id) return null;
|
||||
|
||||
return self::getCache("getFullInfo-".$id."-".$this->view_language, function () use ($id){
|
||||
|
||||
$info = $this->objPageModel->getFullInfo($id);
|
||||
|
||||
if($this->iEntityLanguageModel && $info ) {
|
||||
$item_language_info = $this->iEntityLanguageModel->getInfo($id);
|
||||
if($item_language_info) {
|
||||
return $this->formatItemInfo(array_merge($info, $item_language_info));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->formatItemInfo($info);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInfo(array $item_info)
|
||||
{
|
||||
if(!$item_info) return null;
|
||||
|
||||
$info = $item_info;
|
||||
$info['image'] = self::getResizedImageCollection($info['thumbnail']);
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInList(array $item_info)
|
||||
{
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
|
||||
public static function getResizedImageCollection($image_name) {
|
||||
$image = [];
|
||||
|
||||
$size_in_full = [
|
||||
't' => 'thumb' ,
|
||||
's' => 'small' ,
|
||||
'l' => 'large' ,
|
||||
];
|
||||
|
||||
foreach (static::$resized_sizes as $size => $value) {
|
||||
$image[$size_in_full[$size]] = ($image_name) ? STATIC_DOMAIN . "/". static::$image_folder . "/". $size. IMAGE_FILE_SEPARATOR . $image_name : '';
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
}
|
||||
21
inc/Hura8/Components/Page/Model/PageLanguageModel.php
Normal file
21
inc/Hura8/Components/Page/Model/PageLanguageModel.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Page\Model;
|
||||
|
||||
use Hura8\System\Model\EntityLanguageModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
|
||||
class PageLanguageModel extends EntityLanguageModel
|
||||
{
|
||||
|
||||
protected $richtext_fields = [
|
||||
'content',
|
||||
'content_html',
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::PAGE, '', $this->richtext_fields);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
76
inc/Hura8/Components/Page/Model/PageModel.php
Normal file
76
inc/Hura8/Components/Page/Model/PageModel.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Page\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
use Hura8\System\Controller\UrlManagerController;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\System\ModuleManager;
|
||||
|
||||
class PageModel extends aEntityBaseModel implements iEntityModel
|
||||
{
|
||||
|
||||
protected $richtext_fields = [
|
||||
'content',
|
||||
'content_html',
|
||||
];
|
||||
|
||||
protected $tb_page_info = "tb_page_info";
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::PAGE, '', null, $this->richtext_fields);
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getFullInfo($id) : ?array
|
||||
{
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT * FROM `".$this->tb_entity."` basic, `".$this->tb_page_info."` info
|
||||
WHERE basic.`id` = info.`page_id` AND basic.id = ?
|
||||
LIMIT 1 ",
|
||||
['d'], [$id]
|
||||
);
|
||||
|
||||
if( $item_info = $this->db->fetchAssoc($query)){
|
||||
return $item_info;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition): ?array
|
||||
{
|
||||
/*$condition = array(
|
||||
"q" => "",
|
||||
"status" => 0,
|
||||
);*/
|
||||
|
||||
/*$condition = array(
|
||||
"letter" => "",
|
||||
);*/
|
||||
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
/*if(isset($filter_condition["letter"]) && strlen($filter_condition["letter"]) == 1){
|
||||
$catCondition[] = " AND `letter` = ? ";
|
||||
$bind_types[] = 's';
|
||||
$bind_values[] = $filter_condition["letter"];
|
||||
}*/
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\AdminController;
|
||||
|
||||
use Hura8\System\Controller\aAdminEntityBaseController;
|
||||
use Hura8\Components\Product\Model\ProductAttributeLanguageModel;
|
||||
use Hura8\Components\Product\Model\ProductAttributeModel;
|
||||
use Hura8\Components\Product\Model\ProductAttributeValueModel;
|
||||
use Hura8\System\Security\DataClean;
|
||||
use Hura8\System\Security\DataType;
|
||||
|
||||
|
||||
class AProductAttributeController extends aAdminEntityBaseController
|
||||
{
|
||||
/* @var ProductAttributeModel $objProductAttributeModel */
|
||||
protected $objProductAttributeModel;
|
||||
|
||||
/* @var ProductAttributeLanguageModel $objProductAttributeLanguageModel */
|
||||
protected $objProductAttributeLanguageModel;
|
||||
|
||||
protected $view_language = LANGUAGE;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objProductAttributeModel = new ProductAttributeModel();
|
||||
|
||||
if(!$this->isDefaultLanguage()) {
|
||||
$this->objProductAttributeLanguageModel = new ProductAttributeLanguageModel($this->view_language);
|
||||
//$this->objProductAttributeLanguageModel->createTableLang();
|
||||
|
||||
parent::__construct($this->objProductAttributeModel, $this->objProductAttributeLanguageModel);
|
||||
|
||||
}else{
|
||||
parent::__construct($this->objProductAttributeModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getProductAttributes($product_id) {
|
||||
$objProductAttributeValueModel = new ProductAttributeValueModel(0);
|
||||
|
||||
$result = [];
|
||||
foreach ($objProductAttributeValueModel->getProductAttributes($product_id) as $info) {
|
||||
$result[$info['attr_id']][] = $info['attr_value_id'];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function updateProductAttributes($product_id, array $current_value, array $new_value) {
|
||||
/*
|
||||
$current_value => Array
|
||||
(
|
||||
// attribute_id => [value1, value2]
|
||||
[2] => Array
|
||||
(
|
||||
[0] => 2
|
||||
[1] => 3
|
||||
)
|
||||
|
||||
[1] => Array
|
||||
(
|
||||
[0] => 1
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
$new_value => Array
|
||||
(
|
||||
// attribute_id => new_str_values by lines
|
||||
[2] => asdas
|
||||
[1] => asda
|
||||
)
|
||||
* */
|
||||
|
||||
// list of values for product
|
||||
$product_value_ids = [];
|
||||
|
||||
// use current values
|
||||
foreach ($current_value as $_attr_id => $_value_ids) {
|
||||
$product_value_ids = array_merge($product_value_ids, $_value_ids);
|
||||
}
|
||||
|
||||
// create new values for attributes
|
||||
foreach ($new_value as $_attr_id => $_value_text) {
|
||||
$new_value_texts = array_filter(explode("\n", $_value_text));
|
||||
foreach ($new_value_texts as $new_value) {
|
||||
// if exist
|
||||
$check_exist = $this->getValueByTitle($_attr_id, $new_value);
|
||||
if($check_exist) {
|
||||
$product_value_ids[] = $check_exist['id'];
|
||||
}else{
|
||||
$try_create_id = $this->addValue($_attr_id, ['title' => $new_value]);
|
||||
if($try_create_id) $product_value_ids[] = $try_create_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$objProductAttributeValueModel = new ProductAttributeValueModel(0);
|
||||
|
||||
return $objProductAttributeValueModel->updateProductAttributes($product_id, $product_value_ids);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function updateAttributeInSpecGroup($group_id, $attr_id, array $info) {
|
||||
$this->objProductAttributeModel->updateAttributeInSpecGroup($group_id, $attr_id, $info);
|
||||
}
|
||||
|
||||
public function removeAttributeFromSpecGroup($group_id, $attr_id) {
|
||||
$this->objProductAttributeModel->removeAttributeFromSpecGroup($group_id, $attr_id);
|
||||
}
|
||||
|
||||
public function addAttributeToSpecGroup($group_id, $attr_id, $ordering) {
|
||||
$this->objProductAttributeModel->addAttributeToSpecGroup($group_id, $attr_id, $ordering);
|
||||
}
|
||||
|
||||
public function updateAttributeInCategory($cat_id, $attr_id, array $info) {
|
||||
$this->objProductAttributeModel->updateAttributeInCategory($cat_id, $attr_id, $info);
|
||||
}
|
||||
|
||||
public function removeAttributeFromCategory($cat_id, $attr_id) {
|
||||
$this->objProductAttributeModel->removeAttributeFromCategory($cat_id, $attr_id);
|
||||
}
|
||||
|
||||
public function addAttributeToCategory($cat_id, $attr_id, $ordering) {
|
||||
$this->objProductAttributeModel->addAttributeToCategory($cat_id, $attr_id, $ordering);
|
||||
}
|
||||
|
||||
public function getAllAtributes() {
|
||||
return $this->objProductAttributeModel->getList(["numPerPage" => 2000]);
|
||||
}
|
||||
|
||||
public function deleteValue($attr_id, $value_id) {
|
||||
$objProductAttributeValueModel = new ProductAttributeValueModel($attr_id);
|
||||
return $objProductAttributeValueModel->delete($value_id);
|
||||
}
|
||||
|
||||
public function updateValue($attr_id, $value_id, array $info) {
|
||||
$objProductAttributeValueModel = new ProductAttributeValueModel($attr_id);
|
||||
return $objProductAttributeValueModel->updateFields($value_id, $info);
|
||||
}
|
||||
|
||||
public function getValueByTitle($attr_id, $value_title) {
|
||||
$objProductAttributeValueModel = new ProductAttributeValueModel($attr_id);
|
||||
$filter_code = DataClean::makeInputSafe($value_title, DataType::ID);
|
||||
return $objProductAttributeValueModel->getInfoByCode($filter_code);
|
||||
}
|
||||
|
||||
public function addValue($attr_id, array $info) {
|
||||
$objProductAttributeValueModel = new ProductAttributeValueModel($attr_id);
|
||||
return $objProductAttributeValueModel->create($info);
|
||||
}
|
||||
|
||||
public function getListAttributeValues($attr_id) {
|
||||
$objProductAttributeValueModel = new ProductAttributeValueModel($attr_id);
|
||||
return $objProductAttributeValueModel->getList(['numPerPage' => 200]);
|
||||
}
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\AdminController;
|
||||
|
||||
use Hura8\Components\Product\Controller\bProductCategoryController;
|
||||
use Hura8\Traits\AdminEntityCategoryControllerTraits;
|
||||
|
||||
|
||||
class AProductCategoryController extends bProductCategoryController
|
||||
{
|
||||
|
||||
use AdminEntityCategoryControllerTraits;
|
||||
|
||||
public function getAttributeList($catId) {
|
||||
return $this->objProductCategoryModel->getAttributeList($catId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\AdminController;
|
||||
|
||||
use Hura8\Components\Product\Controller\bProductCollectionController;
|
||||
use Hura8\Interfaces\iEntityAdminCategoryController;
|
||||
use Hura8\Traits\AdminEntityCategoryControllerTraits;
|
||||
|
||||
|
||||
class AProductCollectionController extends bProductCollectionController implements iEntityAdminCategoryController
|
||||
{
|
||||
|
||||
use AdminEntityCategoryControllerTraits;
|
||||
|
||||
public function updateProduct($product_id, $collection_id, array $info)
|
||||
{
|
||||
return $this->objProductCollectionModel->updateProduct($product_id, $collection_id, $info);
|
||||
}
|
||||
|
||||
|
||||
public function removeProduct($product_id, $collection_id)
|
||||
{
|
||||
return $this->objProductCollectionModel->removeProduct($product_id, $collection_id);
|
||||
}
|
||||
|
||||
|
||||
public function addProduct($product_id, $collection_id, $ordering=0)
|
||||
{
|
||||
return $this->objProductCollectionModel->addProduct($product_id, $collection_id, $ordering);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\AdminController;
|
||||
|
||||
use Hura8\Components\Product\Controller\bProductController;
|
||||
use Hura8\Components\Product\Model\ProductImageModel;
|
||||
use Hura8\Components\Product\Model\ProductInfoModel;
|
||||
|
||||
// Main class extend from base class implementing an interface
|
||||
// Main class use traits shared by other classes with same responsibilities
|
||||
|
||||
class AProductController extends bProductController {
|
||||
|
||||
|
||||
protected function extendFilterConditions(): array
|
||||
{
|
||||
return [
|
||||
"price" => array('max' => 0, 'min'=> 0),
|
||||
"brand" => array(), // array(1,2,3,)
|
||||
"collection" => array(), // array(1,2,3,)
|
||||
"supplier" => array(), // array(1,2,3,)
|
||||
"rating" => array(), // array(1,2,3,)
|
||||
"category" => array(), // array(1,2,3,)
|
||||
"status" => array(), // array(1,2,3,)
|
||||
"hotType" => array(),// array(saleoff | not | new)
|
||||
"attribute" => array(), // array(1,2,3,)
|
||||
"promotion" => "",
|
||||
"storeId" => array(), // array(1,2,3,)
|
||||
"other_filter" => array(), // array(in-stock, has-promotion etc...)
|
||||
"spec_group_id" => array(), // array(1,2,3,)
|
||||
];
|
||||
}
|
||||
|
||||
//get product image list
|
||||
public function productImageList($proId){
|
||||
$objProductImageModel = new ProductImageModel($proId);
|
||||
$result = array();
|
||||
foreach ( $objProductImageModel->getList(["numPerPage" => 100]) as $rs ) {
|
||||
|
||||
$rs['image'] = static::getResizedImageCollection($rs['img_name']);
|
||||
|
||||
$result[] = $rs;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// get only from tb_product_info
|
||||
public function getInfoMore($id)
|
||||
{
|
||||
$objProductInfoModel = new ProductInfoModel();
|
||||
$info = $objProductInfoModel->getInfo($id);
|
||||
|
||||
if(!$this->isDefaultLanguage() && $info) {
|
||||
$language_info = $this->iEntityLanguageModel->getInfo($id);
|
||||
$final_info = [];
|
||||
foreach ($info as $_k => $_v) {
|
||||
$final_info[$_k] = $language_info[$_k] ?? $_v;
|
||||
}
|
||||
|
||||
return $final_info;
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
public function getInfoMoreEmpty($addition_field_value = [])
|
||||
{
|
||||
$objProductInfoModel = new ProductInfoModel();
|
||||
return $objProductInfoModel->getEmptyInfo($addition_field_value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\AdminController;
|
||||
|
||||
use Hura8\System\Url;
|
||||
use Hura8\Components\Product\Controller\ProductFilterController;
|
||||
|
||||
|
||||
class AProductFilterController extends ProductFilterController
|
||||
{
|
||||
|
||||
|
||||
public static function getSortOptions($order) {
|
||||
return array(
|
||||
array(
|
||||
"selected" => '',
|
||||
"name" => "Sắp xếp sản phẩm",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("order"=>"")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($order == 'ordering') ? "selected" : "",
|
||||
"name" => "Thứ tự cửa hàng",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("order"=>"ordering")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($order == 'view') ? "selected" : "",
|
||||
"name" => "Xem nhiều nhất",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("order"=>"view")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($order == 'new') ? "selected" : "",
|
||||
"name" => "Mới nhất",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("order"=>"new")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($order == 'last-update') ? "selected" : "",
|
||||
"name" => "Thời gian cập nhật",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("order"=>"last-update")),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static function getFilterOptions($other_filter) {
|
||||
|
||||
return array(
|
||||
array(
|
||||
"selected" => ($other_filter == 'no-price') ? "selected" : "",
|
||||
"name" => "Giá bán = 0",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"no-price")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($other_filter == 'in-stock') ? "selected" : "",
|
||||
"name" => "Còn hàng",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"in-stock")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($other_filter == 'out-stock') ? "selected" : "",
|
||||
"name" => "Hết hàng",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"out-stock")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($other_filter == 'has-market-price') ? "selected" : "",
|
||||
"name" => "Có giá thị trường",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"has-market-price")),
|
||||
),
|
||||
|
||||
array(
|
||||
"selected" => ($other_filter == 'has-promotion') ? "selected" : "",
|
||||
"name" => "Có khuyến mại",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"has-promotion")),
|
||||
),
|
||||
|
||||
array(
|
||||
"selected" => ($other_filter == 'has-config') ? "selected" : "",
|
||||
"name" => "Có cấu hình",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"has-config")),
|
||||
),
|
||||
|
||||
array(
|
||||
"selected" => ($other_filter == 'no-sku') ? "selected" : "",
|
||||
"name" => "Chưa có mã kho",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"no-sku")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($other_filter == 'no-image') ? "selected" : "",
|
||||
"name" => "Chưa có ảnh",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"no-image")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($other_filter == 'display-off') ? "selected" : "",
|
||||
"name" => "Chưa hiển thị",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"display-off")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($other_filter == 'display-on') ? "selected" : "",
|
||||
"name" => "Đang hiển thị",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"display-on")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($other_filter == 'no-category') ? "selected" : "",
|
||||
"name" => "Chưa có danh mục",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"no-category")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($other_filter == 'no-brand') ? "selected" : "",
|
||||
"name" => "Chưa có thương hiệu",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"no-brand")),
|
||||
),
|
||||
|
||||
array(
|
||||
"selected" => ($other_filter == 'no-warranty') ? "selected" : "",
|
||||
"name" => "Chưa có bảo hành",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"no-warranty")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($other_filter == 'no-description') ? "selected" : "",
|
||||
"name" => "Chưa có mô tả",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"no-description")),
|
||||
),
|
||||
array(
|
||||
"selected" => ($other_filter == 'no-spec-text') ? "selected" : "",
|
||||
"name" => "Chưa có thông số nhập text",
|
||||
"url" => Url::buildUrl(CURRENT_URL, array("other_filter"=>"no-spec-text")),
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,948 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\AdminController;
|
||||
|
||||
|
||||
use Hura8\System\ProductFilterPrice;
|
||||
use Hura8\System\Registry;
|
||||
use Hura8\System\Security;
|
||||
use Hura8\System\Url;
|
||||
use Hura8\Components\Brand\Model\BrandModel;
|
||||
use Hura8\Components\Product\Model\ProductAttributeModel;
|
||||
use Hura8\Components\Product\Model\ProductCategoryModel;
|
||||
use Hura8\Components\Product\Model\ProductSearchModel;
|
||||
use Hura8\System\Security\DataType;
|
||||
use Hura8\Interfaces\TableName;
|
||||
|
||||
class AProductFilterOldController
|
||||
{
|
||||
|
||||
protected $filters = [
|
||||
"price" => false,
|
||||
"brand" => array(),
|
||||
"collection" => array(),
|
||||
"supplier" => array(),
|
||||
"rating" => array(),
|
||||
"category" => array(),
|
||||
"status" => "",
|
||||
"query" => "",
|
||||
"hotType" => "",//saleoff | not | new
|
||||
"attribute" => [],//,3793,3794,
|
||||
"ids" => array(),
|
||||
'excluded_ids' => array(),
|
||||
"promotion" => "",
|
||||
"storeId" => '',
|
||||
"other_filter" => array() //in-stock, has-promotion etc...
|
||||
];
|
||||
|
||||
|
||||
public function __construct() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function getDefaultFilter() {
|
||||
return [
|
||||
"price" => self::getPriceFilterRange(),
|
||||
"brand" => $this->getBrandFilter(),
|
||||
"collection" => array_filter(explode(FILTER_VALUE_SEPARATOR, getRequest('collection'))),
|
||||
"supplier" => array_filter(explode(FILTER_VALUE_SEPARATOR, getRequest('supplier'))),
|
||||
"rating" => array_filter(explode(FILTER_VALUE_SEPARATOR, getRequest('rating'))),
|
||||
"category" => array_filter(explode(FILTER_VALUE_SEPARATOR, getRequest('category'))),
|
||||
//"status" => "1",
|
||||
"query" => getRequest('q', ''),
|
||||
"hotType" => getRequest('hotType'),//saleoff | not | new
|
||||
"attribute" => $this->getAttributeFilter([]),//,3793,3794,
|
||||
"promotion" => getRequest('promo', ''),
|
||||
"ids" => array_filter(explode(',', str_replace(" ", "", getRequest('ids', '')))),
|
||||
'excluded_ids' => [],
|
||||
"storeId" => getRequest('storeId', ''),
|
||||
"other_filter" => array_filter(explode(",", getRequest('other_filter', ''))), //in-stock, has-promotion etc...
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
// build the user filters for product query
|
||||
// we can modify the code to accept various types of url customization
|
||||
public function getUserFilter(array $category_list_id) {
|
||||
return [
|
||||
"price" => self::getPriceFilterRange(),
|
||||
"brand" => $this->getBrandFilter(),
|
||||
"collection" => array_filter(explode(FILTER_VALUE_SEPARATOR, getRequest('collection'))),
|
||||
"supplier" => array_filter(explode(FILTER_VALUE_SEPARATOR, getRequest('supplier'))),
|
||||
"rating" => array_filter(explode(FILTER_VALUE_SEPARATOR, getRequest('rating'))),
|
||||
"category" => $category_list_id,
|
||||
//"status" => "1",
|
||||
"query" => getRequest('q', ''),
|
||||
"hotType" => getRequest('hotType'),//saleoff | not | new
|
||||
"attribute" => $this->getAttributeFilter( $category_list_id),//,3793,3794,
|
||||
"promotion" => getRequest('promo', ''),
|
||||
"ids" => array_filter(explode(',', str_replace(" ", "", getRequest('ids', '')))),
|
||||
"excluded_ids" => array_filter(explode(',', str_replace(" ", "", getRequest('excluded_ids', '')))),
|
||||
"storeId" => getRequest('storeId', ''),
|
||||
"other_filter" => array_filter(explode(",", getRequest('other_filter', ''))), //in-stock, has-promotion etc...
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
// allow to update filters
|
||||
public function setFilters(array $new_filters) {
|
||||
foreach ($new_filters as $key => $value) {
|
||||
if(isset($this->filters[$key])) {
|
||||
$this->filters[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// accept url format:
|
||||
// default: ?min=1000&max=20000
|
||||
// custom: ?p=15trieu-20-trieu
|
||||
public static function getPriceFilterRange(){
|
||||
// default format
|
||||
if(!defined('PRICE_FILTER_FORMAT') || PRICE_FILTER_FORMAT != 'p') {
|
||||
return array(
|
||||
"min" => getRequestInt("min", 0),
|
||||
"max" => getRequestInt("max", 0),
|
||||
);
|
||||
}
|
||||
|
||||
// custom price range query
|
||||
$price_range_format = getRequest("p"); // duoi-10trieu , 10ngan-2trieu, 3trieu-6trieu, tren-30trieu
|
||||
if(strpos($price_range_format, '-') === false) {
|
||||
return array(
|
||||
"min" => 0,
|
||||
"max" => 0,
|
||||
);
|
||||
}
|
||||
|
||||
$unit_translation = [
|
||||
'ngan' => 1000,
|
||||
'trieu' => 1000000,
|
||||
'ty' => 1000000000,
|
||||
];
|
||||
|
||||
// duoi-10trieu, duoi-10ngan
|
||||
if(strpos($price_range_format, 'duoi-') !== false) {
|
||||
$unit_match = self::findPriceUnitMatch(str_replace("duoi-", "", $price_range_format));
|
||||
return array(
|
||||
"min" => 0,
|
||||
"max" => $unit_match['number'] * $unit_translation[$unit_match['unit']],
|
||||
);
|
||||
}
|
||||
|
||||
// tren-10trieu, tren-10ngan
|
||||
if(strpos($price_range_format, 'tren-') !== false) {
|
||||
$unit_match = self::findPriceUnitMatch(str_replace("tren-", "", $price_range_format));
|
||||
return array(
|
||||
"min" => $unit_match['number'] * $unit_translation[$unit_match['unit']],
|
||||
"max" => 0,
|
||||
);
|
||||
}
|
||||
|
||||
// 10ngan-2trieu, 3trieu-6trieu
|
||||
$parts = explode('-', $price_range_format);
|
||||
$min_part = $parts[0];
|
||||
$max_part = $parts[1];
|
||||
$min_match = self::findPriceUnitMatch($min_part);
|
||||
$max_match = self::findPriceUnitMatch($max_part);
|
||||
|
||||
return [
|
||||
"min" => $min_match['number'] * $unit_translation[$min_match['unit']],
|
||||
"max" => $max_match['number'] * $unit_translation[$max_match['unit']],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
//get a list of products that match filtering conditions
|
||||
public function getProductList(
|
||||
$start_url,
|
||||
$sort_by = "new",
|
||||
$limit = 20,
|
||||
$page = 1
|
||||
) {
|
||||
//list of available filters
|
||||
/*
|
||||
* - price range
|
||||
* - brand id or ids
|
||||
* - collection id or ids
|
||||
* - supplier id
|
||||
* - rating: 1-> 5
|
||||
* - category id or ids
|
||||
* - status: 0|1|null
|
||||
* - detail_page_only: 0 | 1
|
||||
* - query: search keyword
|
||||
* - hotType: saleoff | not | new | or combination of types
|
||||
* - attribute values
|
||||
* ...
|
||||
* */
|
||||
|
||||
/*$filters = array(
|
||||
"price" => array("min"=> 1, "max" => 100),
|
||||
"brand" => array(12,3),
|
||||
"collection" => array(2,3),
|
||||
"supplier" => array(2,3),
|
||||
"rating" => array(2,3),
|
||||
"category" => array(1,2,),
|
||||
"status" => "1",
|
||||
"detail_page_only" => 0,
|
||||
"query" => "",
|
||||
"hotType" => "",//saleoff | not | new
|
||||
"attribute" => "",//,3793,3794,
|
||||
"ids" => array(12,3),
|
||||
'excluded_ids' => array(12,3),
|
||||
"other_filter" => array(in-stock, has-promotion)
|
||||
//...
|
||||
);*/
|
||||
|
||||
$filterPath = [];
|
||||
$filter_messages = [];
|
||||
$where_query = [];
|
||||
$paging_url = $start_url;
|
||||
$filters = $this->cleanFilter();
|
||||
// debug_var($filters);
|
||||
|
||||
//system controls
|
||||
if(ENABLE_PRODUCT_EXPIRE) {
|
||||
//$where_query[] = " AND (from_time =0 OR from_time < '".CURRENT_TIME."') AND (to_time > '".CURRENT_TIME."' OR to_time=0 ) ";
|
||||
}
|
||||
|
||||
//other filters
|
||||
if(isset($filters["other_filter"]) && sizeof($filters["other_filter"])) {
|
||||
foreach ($filters["other_filter"] as $_filter) {
|
||||
switch ($_filter) {
|
||||
case "in-stock";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Còn hàng',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND `quantity` > 0 ";
|
||||
break;
|
||||
case "has-vat";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Có thuế VAT',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND has_vat = 1 ";
|
||||
break;
|
||||
case "out-stock";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Hết hàng',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND quantity = 0 ";
|
||||
break;
|
||||
case "has-market-price";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Có giá thị trường',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND market_price > 0 ";
|
||||
break;
|
||||
case "no-price";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có giá',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND price = 0 ";
|
||||
break;
|
||||
case "no-warranty";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có bảo hành',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND LENGTH(`warranty`) < 2 ";
|
||||
break;
|
||||
case "no-sku";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không mã kho hàng',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND LENGTH(`sku`) < 2 ";
|
||||
break;
|
||||
case "has-sku";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Có mã kho hàng',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND LENGTH(`sku`) > 2 ";
|
||||
break;
|
||||
case "has-config";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có cấu hình',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND `config_count` > 0 ";
|
||||
break;
|
||||
case "no-image";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có ảnh',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND `image_count` = 0 ";
|
||||
break;
|
||||
case "no-category";
|
||||
$where_query[] = " AND `category_ids` = '' ";
|
||||
break;
|
||||
case "no-brand";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có thương hiệu',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['brand' => '']),
|
||||
];
|
||||
|
||||
$where_query[] = " AND `brand_id` = 0 ";
|
||||
break;
|
||||
case "display-off";
|
||||
$where_query[] = " AND `status`=0 ";
|
||||
break;
|
||||
case "display-on";
|
||||
$where_query[] = " AND `status`=1 ";
|
||||
break;
|
||||
case "has-promotion":
|
||||
$filter_messages[] = [
|
||||
'title' => 'Có khuyến mại',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
|
||||
$where_query[] = " AND LENGTH(`special_offer`) > 5 ";
|
||||
break;
|
||||
|
||||
case "no-description";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có mô tả',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
|
||||
$where_query["no-description"] = " AND `id` IN ( SELECT `id` FROM ".TableName::PRODUCT_INFO." WHERE LENGTH(`description`) < 5 ) ";
|
||||
break;
|
||||
|
||||
case "no-spec-text";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có thông số',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['other_filter' => '']),
|
||||
];
|
||||
|
||||
$where_query["no-spec-text"] = " AND `id` IN ( SELECT `id` FROM ".TableName::PRODUCT_INFO." WHERE LENGTH(`spec`) < 5 ) ";
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//- brand id or ids or brand_indexes
|
||||
if(isset($filters["brand"]) && sizeof($filters["brand"])) {
|
||||
global $admin_panel;
|
||||
|
||||
$brand_url_format = (defined('BRAND_FILTER_FORMAT')) ? BRAND_FILTER_FORMAT : '';
|
||||
if(isset($admin_panel) && $admin_panel) $brand_url_format = ''; // custom brand format cannot be used in admin panel
|
||||
|
||||
$objBrandModel = new BrandModel();
|
||||
$condition = array();
|
||||
foreach ($filters["brand"] as $_id) {
|
||||
if(!$_id) continue;
|
||||
|
||||
$brand_info = $objBrandModel->getInfo($_id);
|
||||
if(!$brand_info) continue;
|
||||
|
||||
$filterPath["brand"][] = array(
|
||||
"id" => $brand_info['id'],
|
||||
"name" => $brand_info["title"],
|
||||
);
|
||||
|
||||
$condition[] = " `brand_id` = '".intval($brand_info['id'])."' ";
|
||||
$filter_messages[] = [
|
||||
'title' => $brand_info['title'],
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['brand' => join(FILTER_VALUE_SEPARATOR, remove_item_from_array($filters["brand"], $_id))]),
|
||||
];
|
||||
}
|
||||
|
||||
if(sizeof($condition)) {
|
||||
$paging_url = Url::buildUrl($paging_url, array("brand" => join(FILTER_VALUE_SEPARATOR, $filters['brand'])));
|
||||
$where_query[] = " AND ( ".join(" OR ", $condition)." )";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//- collection id or ids
|
||||
if(isset($filters["collection"]) && sizeof($filters["collection"])) {
|
||||
$condition = array();
|
||||
foreach ($filters["collection"] as $_id) {
|
||||
$filterPath["collection"][] = array(
|
||||
"id" => $_id,
|
||||
//"name" => $brand_info["name"],
|
||||
);
|
||||
$condition[] = " `id` IN ( SELECT product_id FROM ".TB_CATEGORY_SPECIAL_PRODUCT." WHERE `special_cat_id`='".intval($_id)."' ) ";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Bộ sưu tập ',
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['collection' => join(',', remove_item_from_array($filters["collection"], $_id))]),
|
||||
];
|
||||
}
|
||||
|
||||
$paging_url = Url::buildUrl($paging_url, array("collection" => join(",", $filters['collection'])));
|
||||
$where_query[] = " AND ( ".join(" OR ", $condition)." )";
|
||||
}
|
||||
|
||||
|
||||
//- category id or ids
|
||||
if(isset($filters["category"]) && sizeof($filters["category"])) {
|
||||
|
||||
$objCategoryProductModel = new ProductCategoryModel();
|
||||
|
||||
$condition = array();
|
||||
|
||||
foreach ($filters["category"] as $cat_id) {
|
||||
$cat_id = intval($cat_id);
|
||||
|
||||
if(!$cat_id) continue;
|
||||
|
||||
$cat_info = $objCategoryProductModel->getInfo($cat_id);
|
||||
|
||||
if($cat_info["is_parent"]) {
|
||||
$childListId = ($cat_info["child_ids"]) ? $cat_info["child_ids"] : '0';
|
||||
$condition[] = " `category_id` IN (".$childListId .") ";
|
||||
}else{
|
||||
$condition[] = " `category_id` = '".$cat_id."' ";
|
||||
}
|
||||
|
||||
$filterPath["category"][] = array(
|
||||
"id" => $cat_id,
|
||||
"name" => $cat_info['title'],
|
||||
);
|
||||
|
||||
$filter_messages[] = [
|
||||
'title' => $cat_info['title'],
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['category' => join(',', remove_item_from_array($filters["category"], $cat_id))]),
|
||||
];
|
||||
}
|
||||
|
||||
if(sizeof($condition)) {
|
||||
$paging_url = Url::buildUrl($paging_url, array("category" => join(",", $filters['category'])));
|
||||
$where_query[] = " AND `id` IN ( SELECT DISTINCT `item_id` FROM ".TableName::PRODUCT_PER_CATEGORY." WHERE " . join(" OR ", $condition) . " )";
|
||||
}
|
||||
}
|
||||
|
||||
//- status: 0|1|null
|
||||
if(isset($filters["status"]) && $filters['status']) {
|
||||
$where_query[] = " AND `status` = 1 ";
|
||||
/*$filter_messages[] = [
|
||||
'title' => 'Trạng thái: '.($filters['status'] ? 'Đang hiển thị' : 'Đang ẩn'),
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['status' => '']),
|
||||
];*/
|
||||
}
|
||||
|
||||
|
||||
//- query: search keyword
|
||||
if(isset($filters["query"]) && $filters["query"]) {
|
||||
$keyword_search = $filters["query"];
|
||||
$search_by_product_id = intval(preg_replace('/[^0-9]/i', '', $keyword_search));
|
||||
|
||||
$objProductSearchModel = new ProductSearchModel();
|
||||
|
||||
$match_result = $objProductSearchModel->find($keyword_search);
|
||||
|
||||
$filterPath["search"] = array(
|
||||
"id" => $filters["query"],
|
||||
"name" => $filters["query"],
|
||||
);
|
||||
$filter_messages[] = [
|
||||
'title' => $filters["query"],
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['q' => '']),
|
||||
];
|
||||
|
||||
$paging_url = Url::buildUrl($paging_url, array("q" => $filters["query"]));
|
||||
|
||||
if(sizeof($match_result) > 0) {
|
||||
$where_query[] = " AND ( `id` IN (".join(",", $match_result ).") OR `id` = '".$search_by_product_id."' ) ";
|
||||
}else{
|
||||
$where_query[] = " AND `id` = '".$search_by_product_id."' ";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//- hotType: saleoff | not | new | or combination of types
|
||||
if(isset($filters["hotType"]) && $filters["hotType"]) {
|
||||
$hot_type = preg_replace("/[^a-z0-9_\-]/i","", $filters["hotType"]);
|
||||
$config_hottype = AProductFilterController::getProductHotTypeList();
|
||||
if(isset($config_hottype[$hot_type])) {
|
||||
$filterPath["hotType"] = array(
|
||||
"id" => $filters["hotType"],
|
||||
"name" => $filters["hotType"],
|
||||
);
|
||||
$paging_url = Url::buildUrl($paging_url, array("hotType" => $hot_type));
|
||||
$where_query[] = " AND `id` IN (SELECT `pro_id` FROM ".TB_PRODUCT_HOT." WHERE hot_type = '".$hot_type."' ) ";
|
||||
$filter_messages[] = [
|
||||
'title' => $filters["hotType"],
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['hotType' => '']),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
//- attribute values
|
||||
if(isset($filters["attribute"]) && sizeof($filters["attribute"])) {
|
||||
$filter_attr_value_list = $filters["attribute"];
|
||||
//filter = attr_value_1-attr_value_2-attr_value_3,
|
||||
$query_attr_id = [];
|
||||
$count_filter = 0;
|
||||
|
||||
if(ENABLE_FILTER_BY_APIKEY) {
|
||||
//filter = ,api_key_1,api_key_2,api_key_3,
|
||||
foreach($this->translate_api_filter($filter_attr_value_list) as $attr_id){
|
||||
$query_attr_id[] = $attr_id;
|
||||
$count_filter ++;
|
||||
}
|
||||
|
||||
} else {
|
||||
foreach($filter_attr_value_list as $attr_id){
|
||||
$attr_id = (int) $attr_id;
|
||||
if($attr_id) {
|
||||
$query_attr_id[] = $attr_id;
|
||||
$count_filter ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$objProductAttributeModel = new ProductAttributeModel();
|
||||
|
||||
$product_filter_id_match = $objProductAttributeModel->getProductMatchAttributeValue($query_attr_id);
|
||||
|
||||
|
||||
$paging_url = Url::buildUrl($paging_url, array("filter" => join(FILTER_VALUE_SEPARATOR, $filter_attr_value_list)));
|
||||
$where_query[] = (sizeof($product_filter_id_match)) ? " AND `id` IN (".join(', ', $product_filter_id_match).") " : " AND `id` = 0 " ;
|
||||
|
||||
//xay lai url de back
|
||||
foreach($filter_attr_value_list as $value_id ){
|
||||
$att_name = 'att_name'; //$objCategoryProduct->atrValueName($value_id);
|
||||
$filterPath["attribute"][] = array(
|
||||
"id" => $value_id,
|
||||
"name" => $att_name,
|
||||
);
|
||||
$filter_messages[] = [
|
||||
'title' => $att_name,
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['attribute' => join(FILTER_VALUE_SEPARATOR, remove_item_from_array($filters["category"], $value_id))]),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
//given products' ids
|
||||
if(isset($filters["ids"]) && is_array($filters["ids"]) && sizeof($filters["ids"])) {
|
||||
$where_query[] = " AND `id` IN (". join(",", $filters["ids"]) .") ";
|
||||
}
|
||||
|
||||
//exclude products' ids
|
||||
if(isset($filters["excluded_ids"]) && is_array($filters["excluded_ids"]) && sizeof($filters["excluded_ids"])) {
|
||||
$where_query[] = " AND `id` NOT IN (". join(",", $filters["excluded_ids"]) .") ";
|
||||
}
|
||||
|
||||
$price_range_query_limit = join(" ",$where_query);
|
||||
|
||||
//- price range
|
||||
if(isset($filters["price"]) && is_array($filters["price"]) && sizeof($filters["price"]) && ($filters["price"]['min'] > 0 || $filters["price"]['max'] > 0)) {
|
||||
//limit by price range
|
||||
$maxPrice = clean_price($filters["price"]['max']);
|
||||
$minPrice = clean_price($filters["price"]['min']);
|
||||
$paging_url = Url::buildUrl($paging_url, array("max"=>$maxPrice, "min"=>$minPrice));
|
||||
|
||||
$price_range_query = '';
|
||||
if($maxPrice > 0 && $minPrice > 0){
|
||||
$price_range_query = " ( `price` BETWEEN '".$minPrice."' AND '".$maxPrice."' ) ";
|
||||
|
||||
}else if($maxPrice > 0){
|
||||
$price_range_query = " `price` < '".$maxPrice."' ";
|
||||
|
||||
}else if($minPrice > 0){
|
||||
$price_range_query = " `price` >='".$minPrice."' ";
|
||||
}
|
||||
|
||||
$where_query[] = " AND ". $price_range_query;
|
||||
|
||||
$filterPath["price"] = array(
|
||||
"min" => $minPrice,
|
||||
"max" => $maxPrice,
|
||||
);
|
||||
|
||||
$price_format = ProductFilterPrice::buildPriceRangeFormat($minPrice, $maxPrice);
|
||||
|
||||
$filter_messages[] = [
|
||||
'title' => $price_format['title'],
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['price' => '']),
|
||||
];
|
||||
}
|
||||
|
||||
// use location price sorting
|
||||
$ordering_clause = $this->getOrderingClause($sort_by, $db_condition, 0);
|
||||
|
||||
$db_condition = join(" ", $where_query);
|
||||
|
||||
$total_number = 0;
|
||||
$list_ids = [];
|
||||
|
||||
/* $query = $this->db->runQuery("SELECT COUNT(`id`) AS total FROM ".TB_PRODUCT_LIGHT." WHERE 1 ".$db_condition." ");
|
||||
if($rs = $this->db->fetchAssoc($query)) {
|
||||
$total_number = $rs['total'];
|
||||
}
|
||||
|
||||
$category_query = " AND idv_product_category.`pro_id` IN (SELECT `id` FROM ".TB_PRODUCT_LIGHT." WHERE 1 ".$db_condition.") ";
|
||||
|
||||
if($location_sorting) {
|
||||
|
||||
$list_ids = array_slice($location_product_ids, ($page-1) * $limit, $limit);
|
||||
|
||||
} else {
|
||||
|
||||
if(in_array($sort_by, ['view', 'name'])) {
|
||||
$query = $this->db->runQuery("
|
||||
SELECT `id`, ".TB_PRODUCT.".proName
|
||||
FROM ".TB_PRODUCT_LIGHT.", ".TB_PRODUCT."
|
||||
WHERE `id` = ".TB_PRODUCT.".`id`
|
||||
".$db_condition."
|
||||
".$ordering_clause."
|
||||
LIMIT ".($page-1) * $limit.", ".$limit."
|
||||
");
|
||||
}else{
|
||||
$query = $this->db->runQuery("
|
||||
SELECT `id` FROM ".TB_PRODUCT_LIGHT."
|
||||
WHERE 1 ".$db_condition."
|
||||
".$ordering_clause."
|
||||
LIMIT ".($page-1) * $limit.", ".$limit."
|
||||
");
|
||||
}
|
||||
|
||||
$list_ids = array_map(function ($rs){
|
||||
return $rs['id'];
|
||||
}, $this->db->fetchAll($query));
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
return [
|
||||
"full_query" => $db_condition,
|
||||
"price_query" => $price_range_query_limit,
|
||||
//"category_query" => $category_query,
|
||||
"filter" => $filterPath,
|
||||
"filter_messages" => $filter_messages,
|
||||
"total" => $total_number,
|
||||
"list_ids" => $list_ids,
|
||||
"url" => $paging_url,
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected function cleanFilter() {
|
||||
$clean_filter = [];
|
||||
foreach ($this->filters as $key => $value) {
|
||||
$clean_filter[$key] = $this->clearFilterValue($key, $value);
|
||||
}
|
||||
return $clean_filter;
|
||||
}
|
||||
|
||||
|
||||
protected function clearFilterValue($key, $value) {
|
||||
if($key == 'price') {
|
||||
if(!is_array($value)) return false;
|
||||
$min = isset($value['min']) ? intval($value['min']) : 0;
|
||||
$max = isset($value['max']) ? intval($value['max']) : 0;
|
||||
|
||||
return ['min' => $min, 'max' => $max]; // array("min" => getRequestInt("min", 0), "max" => getRequestInt("max", 0)),
|
||||
}
|
||||
|
||||
if(in_array($key, ['collection', 'supplier', 'rating', 'category', 'ids', 'excluded_ids'])) {
|
||||
return Security::makeListOfInputSafe($value, 'int'); // int1-int2 => array(int1, int2, ...)
|
||||
}
|
||||
|
||||
// accept a-z0-9-
|
||||
if(in_array($key, ['attribute', 'brand'])) {
|
||||
return Security::makeListOfInputSafe($value, 'string');
|
||||
}
|
||||
|
||||
if($key == 'status') {
|
||||
return (in_array($value, [0, 1])) ? $value : 0;
|
||||
}
|
||||
|
||||
if($key == 'query') {
|
||||
return substr(trim(str_replace(['\'', '"'], '', strip_tags($value))), 0, 100); // string
|
||||
}
|
||||
|
||||
if($key == 'hotType') {
|
||||
$config_hottype = AProductFilterController::getProductHotTypeList();
|
||||
return (isset($config_hottype[$value])) ? $value : ''; //saleoff | not | new
|
||||
}
|
||||
|
||||
if($key == 'promotion') {
|
||||
return intval($value);
|
||||
}
|
||||
|
||||
if($key == 'storeId') {
|
||||
return intval($value);
|
||||
}
|
||||
|
||||
if($key == 'detail_page_only') {
|
||||
return intval($value); // 1|0|''
|
||||
}
|
||||
|
||||
if($key == 'other_filter') {
|
||||
return array_filter(
|
||||
array_map(function ($item){
|
||||
return preg_replace('/[^a-z0-9_\.\-\,]/i', '', $item);
|
||||
}, $value )
|
||||
); // array() //in-stock, has-promotion
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected function filterLocationProductByPrice(array $product_list, $max_price, $min_price) {
|
||||
if($max_price > 0 && $min_price > 0){
|
||||
return array_filter($product_list, function ($pro) use ($max_price, $min_price) {
|
||||
return ($pro['price'] >= $min_price && $pro['price'] < $max_price);
|
||||
});
|
||||
}
|
||||
|
||||
if($max_price > 0){
|
||||
return array_filter($product_list, function ($pro) use ($max_price, $min_price) {
|
||||
return ($pro['price'] < $max_price);
|
||||
});
|
||||
}
|
||||
|
||||
if($min_price > 0){
|
||||
return array_filter($product_list, function ($pro) use ($max_price, $min_price) {
|
||||
return ($pro['price'] >= $min_price);
|
||||
});
|
||||
}
|
||||
|
||||
return $product_list;
|
||||
}
|
||||
|
||||
protected function getProductIds($price_range_query_limit) {
|
||||
/*$query = $this->db->query("
|
||||
SELECT `id` FROM ".TB_PRODUCT_LIGHT."
|
||||
WHERE 1 ".$price_range_query_limit."
|
||||
LIMIT 10000
|
||||
");
|
||||
|
||||
return array_map(function ($rs){
|
||||
return $rs['id'];
|
||||
}, $this->db->fetchAll($query));*/
|
||||
}
|
||||
|
||||
//10-04-2017 allow ?filter=api_key1,api_key2, ... and translate to id
|
||||
protected function translate_api_filter($filter_api) {
|
||||
/*$filter_attr_value_list = array_filter(explode(",", $filter_api));
|
||||
|
||||
$build_query = array();
|
||||
foreach($filter_attr_value_list as $api_key){
|
||||
$api_key = \preg_replace('/[^a-z0-9\_\-\.]/i', '', $api_key);
|
||||
if($api_key) $build_query[] = " `api_key` = '".$this->db->escape($api_key)."' ";
|
||||
}
|
||||
|
||||
$result = array();
|
||||
if(sizeof($build_query)) {
|
||||
$query = $this->db->runQuery("SELECT id FROM ".TB_ATTRIBUTE_VALUE." WHERE ". join(" OR ", $build_query)) ;
|
||||
foreach ( $this->db->fetchAll($query) as $info ) {
|
||||
$result[] = $info['id'];
|
||||
}
|
||||
}
|
||||
|
||||
return $result;*/
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
// accept url format:
|
||||
// default: ?brand=1
|
||||
// brand_index: ?brand=apple
|
||||
protected function getBrandFilter() {
|
||||
$brand_url_format = (defined('BRAND_FILTER_FORMAT')) ? BRAND_FILTER_FORMAT : '';
|
||||
|
||||
$module = (Registry::getVariable('global')) ? Registry::getVariable('global')['module'] : null;
|
||||
|
||||
if(!$module) {
|
||||
// possible admin panel
|
||||
return array_filter(explode(FILTER_VALUE_SEPARATOR, getRequest('brand', '')));
|
||||
}
|
||||
|
||||
$current_brand_queries = (isset($module['query']['brand'])) ? array_filter(explode(FILTER_VALUE_SEPARATOR, $module['query']['brand'])) : [];
|
||||
|
||||
// fix for brand-detail page
|
||||
// example: domain.com/brand/sony
|
||||
if(isset($module['query']['brandName']) && $module['query']['brandName']) {
|
||||
$objBrandModel = new BrandModel();
|
||||
$brand_info = $objBrandModel->getInfoByUrl($module['query']['brandName']);
|
||||
|
||||
if($brand_url_format == 'brand_index') {
|
||||
$current_brand_queries = array($brand_info['brand_index']);
|
||||
}else{
|
||||
$current_brand_queries = array($brand_info['id']);
|
||||
}
|
||||
}
|
||||
|
||||
if($brand_url_format == 'brand_index') {
|
||||
//i.e ?brand=apple-canon
|
||||
return $current_brand_queries;
|
||||
}
|
||||
|
||||
$selected_brand = $current_brand_queries;
|
||||
if(isset($module['query']['brand_id']) && $module['query']['brand_id']) {
|
||||
$selected_brand[] = intval($module['query']['brand_id']);
|
||||
}
|
||||
|
||||
return $selected_brand;
|
||||
}
|
||||
|
||||
// accept url format:
|
||||
// default: ?filter=3793-3794,
|
||||
// custom: ?ram=8gb&hdd=500GB
|
||||
protected function getAttributeFilter(array $category_list_id){
|
||||
|
||||
$request_filter_list = getRequest('filter', '');
|
||||
|
||||
// custom1
|
||||
if( !$request_filter_list && defined('ATTRIBUTE_FILTER_FORMAT') && ATTRIBUTE_FILTER_FORMAT == 'custom1' ) {
|
||||
// iUCategoryProduct $objCategoryProduct, array $category_list_id
|
||||
return $this->getAttributeFilterPara($category_list_id); //join(FILTER_VALUE_SEPARATOR, $this->getAttributeFilterPara($category_list_id));
|
||||
}
|
||||
|
||||
if(!$request_filter_list) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// default
|
||||
$clean_list = Security::makeListOfInputSafe(
|
||||
explode(FILTER_VALUE_SEPARATOR, str_replace([',', '-', '_'], FILTER_VALUE_SEPARATOR, $request_filter_list) ),
|
||||
DataType::INTEGER
|
||||
) ; //preg_replace("/[^0-9,_\-]/", "", getRequest('filter', ''));//3793-3794,
|
||||
|
||||
return array_filter($clean_list);
|
||||
}
|
||||
|
||||
|
||||
protected function getAttributeFilterPara( array $category_list_id){
|
||||
|
||||
$excluded_keys = ['p', 'min', 'max', 'brand', 'page', 'request_path'];
|
||||
$attr_filter_params = [];
|
||||
|
||||
$query_parameters = Url::parse(CURRENT_URL)['query'];
|
||||
|
||||
|
||||
foreach ( $query_parameters as $key => $value) {
|
||||
if(in_array($key, $excluded_keys) || !$value) continue;
|
||||
|
||||
$attr_filter_params[$key] = $value;
|
||||
}
|
||||
|
||||
|
||||
if(sizeof($attr_filter_params)) {
|
||||
/*$objCategoryProduct = new UCategoryProduct();
|
||||
$category_attributes = $objCategoryProduct->getAttributesForCategory($category_list_id);
|
||||
|
||||
$match_attr_value_ids = [];
|
||||
foreach ($attr_filter_params as $attr_filter_code => $attr_value_api_key) {
|
||||
foreach ($category_attributes as $attribute) {
|
||||
if($attribute['filter_code'] != $attr_filter_code) continue;
|
||||
|
||||
foreach ($attribute['value_list'] as $_value_id => $_value_info) {
|
||||
if($_value_info['info']['api_key'] == $attr_value_api_key) {
|
||||
$match_attr_value_ids[] = $_value_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $match_attr_value_ids;*/
|
||||
return [];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
public static function findPriceUnitMatch($str){
|
||||
$match = [];
|
||||
$pattern = "/^([\d]+)(ngan|trieu|ty)/i";
|
||||
if(preg_match($pattern, $str, $match)){
|
||||
return [
|
||||
"number" => $match[1],
|
||||
"unit" => $match[2],
|
||||
];
|
||||
}
|
||||
return [
|
||||
"number" => 0,
|
||||
"unit" => 'trieu',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
// accept url format:
|
||||
// default: ?min=1000&max=20000
|
||||
// custom: ?p=tu-15-20-trieu
|
||||
protected static function getPriceRange(){
|
||||
// default
|
||||
$min_price = getRequest("min");
|
||||
$max_price = getRequest("max");
|
||||
|
||||
// custom price range query
|
||||
$price_range = getRequest("p"); // duoi-10-trieu , tu-15-20-trieu, tren-30-trieu
|
||||
|
||||
// duoi-10-trieu
|
||||
$match = [];
|
||||
if(preg_match("/^duoi-([0-9]+)-trieu$/i", $price_range, $match)) {
|
||||
$min_price = '';
|
||||
$max_price = $match[1] * 1000000;
|
||||
}
|
||||
elseif (preg_match("/^tu-([0-9]+)-([0-9]+)-trieu$/i", $price_range, $match)) {
|
||||
$min_price = $match[1] * 1000000;
|
||||
$max_price = $match[2] * 1000000;
|
||||
}
|
||||
elseif (preg_match("/^tren-([0-9]+)-trieu$/i", $price_range, $match)) {
|
||||
$min_price = $match[1] * 1000000;
|
||||
$max_price = '';
|
||||
}
|
||||
|
||||
return [
|
||||
"min" => intval($min_price),
|
||||
"max" => intval($max_price),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function getOrderingClause($sort_by, &$where_query, $current_viewed_category = 0) {
|
||||
|
||||
// show by global order
|
||||
$ordering = "ORDER BY ordering DESC, id DESC";
|
||||
|
||||
switch($sort_by) {
|
||||
case "order-new";
|
||||
$ordering = "ORDER BY `ordering` DESC, `id` DESC";
|
||||
break;
|
||||
case "order-last-update";
|
||||
$ordering = "ORDER BY `ordering` DESC, last_update DESC";
|
||||
break;
|
||||
case "last-update";
|
||||
$ordering = "ORDER BY last_update DESC";
|
||||
break;
|
||||
case "order";
|
||||
$ordering = "ORDER BY `ordering` DESC";
|
||||
break;
|
||||
case "new";
|
||||
$ordering = "ORDER BY `id` DESC";
|
||||
break;
|
||||
case "price-asc";
|
||||
$where_query .= " AND `price` > 100 ";
|
||||
$ordering = "ORDER BY `price` ASC";
|
||||
break;
|
||||
case "price-desc";
|
||||
$ordering = " ORDER BY `price` DESC ";
|
||||
break;
|
||||
case "view";
|
||||
$ordering = "ORDER BY `visit` desc";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return $ordering;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\AdminController;
|
||||
|
||||
use Hura8\Components\Product\Model\ProductHotModel;
|
||||
use Hura8\Traits\ClassCacheTrait;
|
||||
|
||||
class AProductHotController
|
||||
{
|
||||
use ClassCacheTrait;
|
||||
|
||||
/* @var ProductHotModel $objProductHotModel */
|
||||
protected $objProductHotModel;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objProductHotModel = new ProductHotModel();
|
||||
}
|
||||
|
||||
|
||||
public function getProductHot(array $product_id_array) {
|
||||
$hot_script = $this->objProductHotModel->getProductHot($product_id_array);
|
||||
|
||||
//add empty for other products
|
||||
foreach ($product_id_array as $pro_id) {
|
||||
if(!isset($hot_script[$pro_id])) $hot_script[$pro_id] = [];
|
||||
}
|
||||
|
||||
return $hot_script;
|
||||
}
|
||||
|
||||
|
||||
public function updateProductHot($pro_id, array $new_types) {
|
||||
return $this->objProductHotModel->updateProductHot($pro_id, $new_types);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\AdminController;
|
||||
|
||||
use Hura8\Components\Product\Model\ProductSpecGroupAttributeModel;
|
||||
use Hura8\System\Controller\aAdminEntityBaseController;
|
||||
|
||||
class AProductSpecGroupAttributeController extends aAdminEntityBaseController
|
||||
{
|
||||
/* @var ProductSpecGroupAttributeModel $objProductSpecGroupAttributeModel */
|
||||
protected $objProductSpecGroupAttributeModel;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objProductSpecGroupAttributeModel = new ProductSpecGroupAttributeModel();
|
||||
parent::__construct($this->objProductSpecGroupAttributeModel);
|
||||
}
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\AdminController;
|
||||
|
||||
use Hura8\Components\Product\Model\ProductAttributeModel;
|
||||
use Hura8\Components\Product\Model\ProductSpecGroupModel;
|
||||
use Hura8\System\Controller\aAdminEntityBaseController;
|
||||
|
||||
class AProductSpecGroupController extends aAdminEntityBaseController
|
||||
{
|
||||
/* @var ProductSpecGroupModel $objProductSpecGroupModel */
|
||||
protected $objProductSpecGroupModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objProductSpecGroupModel = new ProductSpecGroupModel();
|
||||
parent::__construct($this->objProductSpecGroupModel);
|
||||
}
|
||||
|
||||
public function getSpecGroupAttributeWithValues($group_id)
|
||||
{
|
||||
$objProductAttributeModel = new ProductAttributeModel();
|
||||
return $objProductAttributeModel->getSpecGroupAttributeWithValues($group_id);
|
||||
}
|
||||
|
||||
public function getSpecGroupAttribute($group_id)
|
||||
{
|
||||
$objProductAttributeModel = new ProductAttributeModel();
|
||||
return $objProductAttributeModel->getSpecGroupAttribute($group_id);
|
||||
}
|
||||
|
||||
|
||||
public function clearProductSpecGroup($product_id)
|
||||
{
|
||||
return $this->objProductSpecGroupModel->clearProductSpecGroup($product_id);
|
||||
}
|
||||
|
||||
|
||||
public function setProductSpecGroup($product_id, $group_id)
|
||||
{
|
||||
return $this->objProductSpecGroupModel->setProductSpecGroup($product_id, $group_id);
|
||||
}
|
||||
|
||||
|
||||
public function getProductSpec($product_id)
|
||||
{
|
||||
return $this->objProductSpecGroupModel->getProductSpec($product_id);
|
||||
}
|
||||
|
||||
|
||||
public function getProductSpecGroupInfo($product_id)
|
||||
{
|
||||
return $this->objProductSpecGroupModel->getProductSpecGroupInfo($product_id);
|
||||
}
|
||||
|
||||
|
||||
public function getProductSpecGroupId($product_id)
|
||||
{
|
||||
return $this->objProductSpecGroupModel->getProductSpecGroupId($product_id);
|
||||
}
|
||||
|
||||
|
||||
public function getSpecGroupInfo($group_id)
|
||||
{
|
||||
return $this->objProductSpecGroupModel->getSpecGroupInfo($group_id);
|
||||
}
|
||||
|
||||
|
||||
protected function deleteFileBeforeDeleteItem($item_id): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\AdminController;
|
||||
|
||||
use Hura8\Components\Product\Model\ProductVariantModel;
|
||||
|
||||
class AProductVariantController
|
||||
{
|
||||
/* @var ProductVariantModel $objProductVariantModel */
|
||||
protected $objProductVariantModel;
|
||||
|
||||
|
||||
public function __construct($product_id)
|
||||
{
|
||||
$this->objProductVariantModel = new ProductVariantModel($product_id);
|
||||
}
|
||||
|
||||
|
||||
public function delete($id) {
|
||||
return $this->objProductVariantModel->delete($id);
|
||||
}
|
||||
|
||||
|
||||
public function updateImage($variant_id, $image_name) {
|
||||
return $this->objProductVariantModel->updateFields($variant_id, [
|
||||
"thumbnail" => $image_name
|
||||
]);
|
||||
}
|
||||
|
||||
public function removeImage($variant_id) {
|
||||
return $this->objProductVariantModel->updateFields($variant_id, [
|
||||
"thumbnail" => ''
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function getInfo($id) {
|
||||
return $this->objProductVariantModel->getInfo($id);
|
||||
}
|
||||
|
||||
public function getProductVariantOption($product_id){
|
||||
return $this->objProductVariantModel->getProductVariantOption($product_id);
|
||||
}
|
||||
|
||||
|
||||
//update product's variant options
|
||||
public function updateVariantOption($attribute) {
|
||||
return $this->objProductVariantModel->updateVariantOption($attribute);
|
||||
}
|
||||
|
||||
public function useVariantOptionSample($select_id) {
|
||||
$sample = $this->objProductVariantModel->useVariantOptionSample($select_id);
|
||||
|
||||
return ($sample) ? \json_decode($sample,true) : [];
|
||||
}
|
||||
|
||||
|
||||
//use a product's variant-option to create a choice, so next product can select without recreate from beginning
|
||||
public function createVariantOptionSample($use_from_pro_id, $sample_title) {
|
||||
return $this->objProductVariantModel->createVariantOptionSample($use_from_pro_id, $sample_title);
|
||||
}
|
||||
|
||||
|
||||
public function getVariantOptionSample() {
|
||||
return $this->objProductVariantModel->getVariantOptionSample();
|
||||
}
|
||||
|
||||
public function updateVariant($variant_id, array $variant_info) {
|
||||
if($variant_id) {
|
||||
return $this->objProductVariantModel->update($variant_id, $variant_info);
|
||||
}else{
|
||||
return $this->objProductVariantModel->create($variant_info);
|
||||
}
|
||||
}
|
||||
|
||||
public function getProductVariantPriceRange(){
|
||||
return $this->objProductVariantModel->getProductVariantPriceRange();
|
||||
}
|
||||
|
||||
public function getProductVariantList(){
|
||||
return $this->objProductVariantModel->getList([]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Controller;
|
||||
|
||||
use Hura8\System\Url;
|
||||
use Hura8\Components\Brand\Model\BrandModel;
|
||||
|
||||
|
||||
class ProductFilterBuilderController {
|
||||
|
||||
protected $_request_url = '';
|
||||
|
||||
protected $_url_elements = [
|
||||
'scheme' => '',
|
||||
'host' => '',
|
||||
'port' => '',
|
||||
'user' => '',
|
||||
'pass' => '',
|
||||
'path' => '',
|
||||
'query' => [],
|
||||
'fragment' => '',
|
||||
];
|
||||
|
||||
protected $_price_format = '';
|
||||
protected $_brand_format = '';
|
||||
protected $_filter_format = '';
|
||||
|
||||
|
||||
public function __construct($request_url) {
|
||||
|
||||
if(defined('PRICE_FILTER_FORMAT') && PRICE_FILTER_FORMAT) {
|
||||
$this->_price_format = PRICE_FILTER_FORMAT;
|
||||
}
|
||||
|
||||
if(defined('BRAND_FILTER_FORMAT') && BRAND_FILTER_FORMAT) {
|
||||
$this->_brand_format = BRAND_FILTER_FORMAT;
|
||||
}
|
||||
|
||||
if(defined('ATTRIBUTE_FILTER_FORMAT') && ATTRIBUTE_FILTER_FORMAT ) {
|
||||
$this->_filter_format = ATTRIBUTE_FILTER_FORMAT;
|
||||
}
|
||||
|
||||
$this->_request_url = $request_url;
|
||||
$this->_url_elements = Url::parse($request_url);
|
||||
}
|
||||
|
||||
|
||||
public function buildProductFilterFromUrl(array $existing_filters = []) {
|
||||
$filters = [
|
||||
"price" => $this->getPriceFilterRange(),
|
||||
"brand" => $this->getBrandFilter(), // array(1,2,3,)
|
||||
"collection" => $this->getGenericFilter('collection'), // array(1,2,3,)
|
||||
"supplier" => $this->getGenericFilter('supplier'), // array(1,2,3,)
|
||||
"rating" => $this->getGenericFilter('rating'), // array(1,2,3,)
|
||||
"category" => $this->getGenericFilter('category'), // array(1,2,3,)
|
||||
"status" => array(), // array(1,2,3,)
|
||||
"query" => (isset($this->_url_elements['query']['q'])) ? $this->_url_elements['query']['q'] : '', // string search keyword
|
||||
"hotType" => $this->getGenericFilter('hotType', 'string'),// array(saleoff | not | new)
|
||||
"attribute" => $this->getAttributeFilter(), // array(1,2,3,)
|
||||
"ids" => $this->getGenericFilter('ids'), // array(1,2,3,)
|
||||
"promotion" => "",
|
||||
"storeId" => $this->getGenericFilter('store'), // array(1,2,3,)
|
||||
"other_filter" => $this->getGenericFilter('other_filter', 'string'), // array(in-stock, has-promotion etc...)
|
||||
"spec_group_id" => $this->getGenericFilter('spec_group_id'),
|
||||
];
|
||||
|
||||
|
||||
// debug_var(array_merge($filters, $existing_filters));
|
||||
if(sizeof($existing_filters)) {
|
||||
foreach ($existing_filters as $key => $values) {
|
||||
if(!isset($filters[$key])) continue;
|
||||
if(!$values) continue;
|
||||
|
||||
if(is_array($values) && is_array($filters[$key])) {
|
||||
$filters[$key] = array_merge($filters[$key], $values);
|
||||
}else{
|
||||
$filters[$key] = $values;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $filters ;
|
||||
}
|
||||
|
||||
|
||||
protected function getGenericFilter($url_para, $data_type='int') {
|
||||
$value = (isset($this->_url_elements['query'][$url_para])) ? $this->_url_elements['query'][$url_para] : '';
|
||||
|
||||
if($data_type == 'int') {
|
||||
$safe_value = trim(preg_replace("/[^0-9_\-\,]/i", '', $value));
|
||||
}else{
|
||||
$safe_value = trim(preg_replace("/[^a-z0-9_\-\.\,]/i", '', $value));
|
||||
}
|
||||
|
||||
if(!$safe_value) return [];
|
||||
|
||||
$safe_value_list = explode(FILTER_VALUE_SEPARATOR, $safe_value);
|
||||
|
||||
return array_values(array_filter($safe_value_list));
|
||||
}
|
||||
|
||||
|
||||
protected function getBrandFilter()
|
||||
{
|
||||
if($this->_brand_format == 'brand_index'){
|
||||
|
||||
$objBrandModel = new BrandModel();
|
||||
|
||||
$result = [];
|
||||
$brand_filters = $this->getGenericFilter('brand', 'string');
|
||||
|
||||
foreach ($brand_filters as $_brand) {
|
||||
if(is_int($_brand)) {
|
||||
$result[] = $_brand;
|
||||
}
|
||||
|
||||
$brand_info = $objBrandModel->getInfoByUrl( $_brand);
|
||||
if(!$brand_info) continue;
|
||||
|
||||
$result[] = $brand_info['id'];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
// default
|
||||
return $this->getGenericFilter('brand');
|
||||
}
|
||||
|
||||
|
||||
protected function getAttributeFilter(array $category_list_id = []) {
|
||||
|
||||
if($this->_filter_format == 'filter_code') {
|
||||
|
||||
$excluded_keys = [
|
||||
'q',
|
||||
'p',
|
||||
'min', 'max',
|
||||
'brand',
|
||||
'page',
|
||||
'request_path',
|
||||
'category',
|
||||
'supplier', 'collection',
|
||||
'ids',
|
||||
'filter',' hotType',
|
||||
'other_filter',
|
||||
'rating', 'price',
|
||||
// special ajax key
|
||||
'action','action_type', '_auto'
|
||||
];
|
||||
$attr_filter_params = [];
|
||||
|
||||
foreach ( $this->_url_elements['query'] as $key => $value) {
|
||||
if(in_array($key, $excluded_keys) || !$value) continue;
|
||||
|
||||
$attr_filter_params[$key] = explode(',', urldecode(urldecode($value)));
|
||||
}
|
||||
|
||||
if(sizeof($attr_filter_params)) {
|
||||
|
||||
$category_attributes = $this->getAttributesForCategory($category_list_id);
|
||||
//debug_var($category_attributes);
|
||||
|
||||
$match_attr_value_ids = [];
|
||||
foreach ($attr_filter_params as $attr_filter_code => $attr_value_api_key_list) {
|
||||
|
||||
foreach ($category_attributes as $attribute) {
|
||||
if($attribute['filter_code'] != $attr_filter_code) continue;
|
||||
|
||||
foreach ($attribute['value_list'] as $_index => $_value_info) {
|
||||
|
||||
foreach ($attr_value_api_key_list as $attr_value_api_key) {
|
||||
if($_value_info['api_key'] == $attr_value_api_key) {
|
||||
$match_attr_value_ids[] = $_value_info['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $match_attr_value_ids;
|
||||
}
|
||||
}
|
||||
|
||||
// default
|
||||
return $this->getGenericFilter('filter');
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected function getAttributesForCategory(array $category_ids){
|
||||
|
||||
$category_att_id_list = array();
|
||||
$attr_query_cond = (sizeof($category_ids)) ? " AND category_id IN (".join(',', $category_ids).") " : "";
|
||||
|
||||
$query = $this->db->runQuery(" SELECT `attr_id` FROM `idv_attribute_category` WHERE 1 ". $attr_query_cond);
|
||||
foreach ($this->db->fetchAll($query) as $rs ){
|
||||
$category_att_id_list[] = $rs['attr_id'];
|
||||
}
|
||||
|
||||
if(!sizeof($category_att_id_list)) return array();
|
||||
|
||||
$query = $this->db->query("
|
||||
SELECT
|
||||
attval.id ,
|
||||
attval.attributeId ,
|
||||
attval.value ,
|
||||
attval.api_key ,
|
||||
att.attribute_code ,
|
||||
att.filter_code
|
||||
FROM ".TB_ATTRIBUTE_VALUE." attval
|
||||
LEFT JOIN ".TB_ATTRIBUTE." att ON attval.attributeId = att.id
|
||||
WHERE att.id IN (".join(',', $category_att_id_list).") AND att.isSearch=1
|
||||
ORDER BY attval.ordering DESC ");
|
||||
|
||||
$attribute_list = [];
|
||||
|
||||
foreach ($this->db->fetchAll($query) as $rs ){
|
||||
$att_value_id = $rs['id'];
|
||||
$att_id = $rs['attributeId'];
|
||||
|
||||
$value_info = array(
|
||||
"id" => $att_value_id,
|
||||
"api_key" => $rs['api_key'],
|
||||
);
|
||||
|
||||
if(!array_key_exists($att_id, $attribute_list)) {
|
||||
$attribute_list[$att_id] = [
|
||||
"id" => $att_id,
|
||||
"code" => $rs['attribute_code'],
|
||||
"filter_code" => $rs['filter_code'],
|
||||
'value_list' => [$value_info],
|
||||
];
|
||||
}else{
|
||||
$attribute_list[$att_id]['value_list'][] = $value_info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return array_values($attribute_list);
|
||||
}
|
||||
|
||||
|
||||
// accept url format:
|
||||
// default: ?min=1000&max=20000
|
||||
// custom: ?p=15trieu-20-trieu
|
||||
protected function getPriceFilterRange(){
|
||||
// default format
|
||||
if($this->_price_format != 'p') {
|
||||
return array(
|
||||
"min" => isset($this->_url_elements['query']['min']) ? intval($this->_url_elements['query']['min']) : 0 ,
|
||||
"max" => isset($this->_url_elements['query']['max']) ? intval($this->_url_elements['query']['max']) : 0 ,
|
||||
);
|
||||
}
|
||||
|
||||
// custom price range query
|
||||
$price_range_format = (isset($this->_url_elements['query']['p'])) ? $this->_url_elements['query']['p'] : ''; // duoi-10trieu , 10ngan-2trieu, 3trieu-6trieu, tren-30trieu
|
||||
|
||||
if(strpos($price_range_format, '-') === false) {
|
||||
return array(
|
||||
"min" => 0,
|
||||
"max" => 0,
|
||||
);
|
||||
}
|
||||
|
||||
$unit_translation = [
|
||||
'ngan' => 1000,
|
||||
'trieu' => 1000000,
|
||||
'ty' => 1000000000,
|
||||
];
|
||||
|
||||
// duoi-10trieu, duoi-10ngan
|
||||
if(strpos($price_range_format, 'duoi-') !== false) {
|
||||
$unit_match = $this->findPriceUnitMatch(str_replace("duoi-", "", $price_range_format));
|
||||
return array(
|
||||
"min" => 0,
|
||||
"max" => $unit_match['number'] * $unit_translation[$unit_match['unit']],
|
||||
);
|
||||
}
|
||||
|
||||
// tren-10trieu, tren-10ngan
|
||||
if(strpos($price_range_format, 'tren-') !== false) {
|
||||
$unit_match = $this->findPriceUnitMatch(str_replace("tren-", "", $price_range_format));
|
||||
return array(
|
||||
"min" => $unit_match['number'] * $unit_translation[$unit_match['unit']],
|
||||
"max" => 0,
|
||||
);
|
||||
}
|
||||
|
||||
// 10ngan-2trieu, 3trieu-6trieu
|
||||
$parts = explode('-', $price_range_format);
|
||||
$min_part = $parts[0];
|
||||
$max_part = $parts[1];
|
||||
$min_match = $this->findPriceUnitMatch($min_part);
|
||||
$max_match = $this->findPriceUnitMatch($max_part);
|
||||
|
||||
return [
|
||||
"min" => $min_match['number'] * $unit_translation[$min_match['unit']],
|
||||
"max" => $max_match['number'] * $unit_translation[$max_match['unit']],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function findPriceUnitMatch($str){
|
||||
$match = [];
|
||||
$pattern = "/^([\d]+)(ngan|trieu|ty)/i";
|
||||
if(preg_match($pattern, $str, $match)){
|
||||
return [
|
||||
"number" => $match[1],
|
||||
"unit" => $match[2],
|
||||
];
|
||||
}
|
||||
return [
|
||||
"number" => 0,
|
||||
"unit" => 'trieu',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,797 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Controller;
|
||||
|
||||
use Hura8\Components\Product\Model\ProductCollectionModel;
|
||||
use Hura8\System\Url;
|
||||
use Hura8\Components\Brand\Model\BrandModel;
|
||||
use Hura8\Components\Product\AdminController\AProductHotController;
|
||||
use Hura8\Components\Product\Model\ProductAttributeModel;
|
||||
use Hura8\Components\Product\Model\ProductAttributeValueModel;
|
||||
use Hura8\Components\Product\Model\ProductCategoryModel;
|
||||
use Hura8\Components\Product\Model\ProductFilterModel;
|
||||
use Hura8\Components\Product\Model\ProductSearchModel;
|
||||
use Hura8\Interfaces\TableName;
|
||||
use Hura8\Traits\ClassCacheTrait;
|
||||
|
||||
|
||||
class ProductFilterController
|
||||
{
|
||||
|
||||
use ClassCacheTrait;
|
||||
|
||||
protected $_request_url = '';
|
||||
|
||||
/* @var ProductFilterModel $objProductFilterModel */
|
||||
protected $objProductFilterModel;
|
||||
|
||||
/*
|
||||
all types of filtering representation must be finally translated to this format
|
||||
For example:
|
||||
- ?brand=sony => translated to brand=>array(2,),
|
||||
- ?monitor_size=12inch&color=red => translated to attribute=> array(123, 23121,)
|
||||
*/
|
||||
protected $filters = [
|
||||
"price" => array('max' => 0, 'min'=> 0),
|
||||
"brand" => array(), // array(1,2,3,)
|
||||
"collection" => array(), // array(1,2,3,)
|
||||
"supplier" => array(), // array(1,2,3,)
|
||||
"rating" => array(), // array(1,2,3,)
|
||||
"category" => array(), // array(1,2,3,)
|
||||
"status" => array(), // array(1,2,3,)
|
||||
"query" => "", // string search keyword
|
||||
"hotType" => array(),// array(saleoff | not | new)
|
||||
"attribute" => array(), // array(1,2,3,)
|
||||
"ids" => array(), // array(1,2,3,)
|
||||
"excluded_ids" => array(), // array(1,2,3,)
|
||||
"promotion" => "",
|
||||
"storeId" => array(), // array(1,2,3,)
|
||||
"other_filter" => array(), // array(in-stock, has-promotion etc...)
|
||||
"spec_group_id" => array(), // array(1,2,3,)
|
||||
];
|
||||
|
||||
|
||||
public function __construct($request_url = '') {
|
||||
$this->_request_url = $request_url;
|
||||
}
|
||||
|
||||
|
||||
public function getResult(
|
||||
$current_page_id =1,
|
||||
$number_per_page=10,
|
||||
$sort_by = 'new',
|
||||
array $existing_filters=[],
|
||||
$current_category_ids = [],
|
||||
$price_range = []
|
||||
) {
|
||||
|
||||
$objProductFilterBuilder = new ProductFilterBuilderController($this->_request_url);
|
||||
$built_filters = $objProductFilterBuilder->buildProductFilterFromUrl($existing_filters);
|
||||
$this->setFilters($built_filters);
|
||||
|
||||
$product_result = $this->findProductListIdMatchFilters($current_page_id, $number_per_page, $sort_by);
|
||||
//debug_var($product_result);
|
||||
|
||||
$objProductFilterOptions = new ProductFilterOptionsController(
|
||||
$this->getFilters(),
|
||||
$current_category_ids,
|
||||
$product_result['item_list'],
|
||||
$price_range
|
||||
);
|
||||
$objProductFilterOptionsTranslation = new ProductFilterOptionsTranslationController($this->_request_url);
|
||||
|
||||
list ( $filter_options, $filter_messages ) = $objProductFilterOptionsTranslation->getAllFilterOptions(
|
||||
$objProductFilterOptions->categoryList(),
|
||||
$objProductFilterOptions->attributeList(),
|
||||
$objProductFilterOptions->brandList(),
|
||||
$objProductFilterOptions->priceList()
|
||||
);
|
||||
|
||||
return [
|
||||
'total' => $product_result['total'],
|
||||
'paged_product_list' => $product_result['item_list'],
|
||||
'filter_options' => $filter_options,
|
||||
'filter_messages' => $filter_messages,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getFilters() {
|
||||
return $this->filters;
|
||||
}
|
||||
|
||||
|
||||
// allow to update filters
|
||||
public function setFilters(array $new_filters) {
|
||||
foreach ($new_filters as $key => $value) {
|
||||
if(isset($this->filters[$key])) {
|
||||
$this->filters[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function createFilterCacheKey($sort_by) {
|
||||
return md5(\json_encode($this->filters) . $sort_by);
|
||||
}
|
||||
|
||||
|
||||
// find a list of products that match filtering conditions
|
||||
protected function findProductListIdMatchFilters($current_page_id, $number_per_page, $sort_by = "new" ) {
|
||||
|
||||
$cache_key = $this->createFilterCacheKey($sort_by);
|
||||
|
||||
return self::getCache($cache_key, function () use ($current_page_id, $number_per_page, $sort_by) {
|
||||
return $this->findProductListIdMatchFilters_raw($current_page_id, $number_per_page, $sort_by );
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected function findProductListIdMatchFilters_raw($current_page_id=1, $number_per_page=10, $sort_by = "new" ) {
|
||||
|
||||
list( , , , $where_query ) = $this->buildSQLConditionFromFilters($sort_by);
|
||||
|
||||
$ordering_clause = $this->getOrderingClause($sort_by);
|
||||
|
||||
$objProductFilterModel = new ProductFilterModel();
|
||||
|
||||
list($total_number, $item_list) = $objProductFilterModel->findProductListIdMatchFilters([
|
||||
$where_query,
|
||||
$current_page_id,
|
||||
$number_per_page,
|
||||
$ordering_clause
|
||||
]);
|
||||
|
||||
|
||||
$final_result = [
|
||||
"total" => $total_number,
|
||||
"item_list" => $item_list,
|
||||
];
|
||||
|
||||
return $final_result;
|
||||
}
|
||||
|
||||
|
||||
protected function buildSQLConditionFromFilters( $sort_by = "new" ) {
|
||||
//list of available filters
|
||||
$filterPath = [];
|
||||
$filter_messages = [];
|
||||
$where_query = [];
|
||||
|
||||
// system controls
|
||||
if( ENABLE_PRODUCT_EXPIRE ) {
|
||||
$where_query[] = " AND (from_time =0 OR from_time < '".CURRENT_TIME."')
|
||||
AND (to_time > '".CURRENT_TIME."' OR to_time=0 ) ";
|
||||
}
|
||||
|
||||
//other filters
|
||||
if( array_key_exists("other_filter", $this->filters) && sizeof($this->filters["other_filter"])) {
|
||||
foreach ($this->filters["other_filter"] as $_filter) {
|
||||
switch ($_filter) {
|
||||
case "in-stock";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Còn hàng',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND quantity > 0 ";
|
||||
break;
|
||||
case "has-vat";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Có thuế VAT',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND `has_vat` = 1 ";
|
||||
break;
|
||||
case "out-stock";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Hết hàng',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND `quantity` = 0 ";
|
||||
break;
|
||||
case "has-market-price";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Có giá thị trường',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND market_price > 0 ";
|
||||
break;
|
||||
case "no-price";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có giá',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND `price` = 0 ";
|
||||
break;
|
||||
case "no-warranty";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có bảo hành',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND LENGTH(warranty) < 2 ";
|
||||
break;
|
||||
case "no-sku";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không mã kho hàng',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND LENGTH(sku) < 2 ";
|
||||
break;
|
||||
case "has-config";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có cấu hình',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND `config_count` > 0 ";
|
||||
break;
|
||||
case "no-image";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có ảnh',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND image_count = 0 ";
|
||||
break;
|
||||
case "no-category";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Không có danh mục',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND `category` = '0' ";
|
||||
break;
|
||||
case "display-off";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Đang ẩn',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND `status`=0 ";
|
||||
break;
|
||||
case "display-on";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Đang hiển thị',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND `status`=1 ";
|
||||
break;
|
||||
case "has-promotion":
|
||||
$filter_messages[] = [
|
||||
'title' => 'Có khuyến mại',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['other_filter' => '']),
|
||||
];
|
||||
$where_query[] = " AND LENGTH(`special_offer`) < 5 ";
|
||||
break;
|
||||
//...add more
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*// limit by admin permission
|
||||
//1-1-2014 gioi han theo san pham danh muc ma quan tri nay quan ly
|
||||
global $admin_permission;
|
||||
$restricted_category_per_admin = (isset($admin_permission['permit'])) ? $admin_permission['permit']['product:category']['ids'] : [];
|
||||
if(sizeof($restricted_category_per_admin)) {
|
||||
$cat_query = $this->db->runQuery("
|
||||
SELECT DISTINCT pro_id
|
||||
FROM ".TB_PRODUCT_CATEGORY."
|
||||
WHERE `category_id` IN (".join(",", $restricted_category_per_admin).")
|
||||
LIMIT 5000
|
||||
");
|
||||
|
||||
//lay danh sach danh muc cua san pham
|
||||
$product_in_category = [];
|
||||
foreach( $this->db->fetchAll($cat_query) as $cat_info ){
|
||||
$product_in_category[] = $cat_info["pro_id"];
|
||||
}
|
||||
|
||||
$where_query[] = (sizeof($product_in_category)) ? " AND id IN (". join(',', $product_in_category) .") " : " AND id = 0 ";
|
||||
}*/
|
||||
|
||||
|
||||
//- brand id or ids or brand_indexes
|
||||
if( array_key_exists("brand", $this->filters) && sizeof($this->filters["brand"])) {
|
||||
|
||||
$objBrandModel = new BrandModel();
|
||||
|
||||
$condition = array();
|
||||
foreach ($this->filters["brand"] as $brand_id) {
|
||||
if(!$brand_id) continue;
|
||||
|
||||
$brand_info = $objBrandModel->getInfo( $brand_id);
|
||||
if(!$brand_info) continue;
|
||||
|
||||
$filterPath["brand"][] = array(
|
||||
"id" => $brand_info['id'],
|
||||
"name" => $brand_info["title"],
|
||||
);
|
||||
|
||||
$condition[] = " brandId = '".intval($brand_info['id'])."' ";
|
||||
$filter_messages[] = [
|
||||
'title' => $brand_info['title'],
|
||||
'reset' => Url::buildUrl($this->_request_url, ['brand' => join(FILTER_VALUE_SEPARATOR, remove_item_from_array($this->filters["brand"], $brand_id ))] ),
|
||||
];
|
||||
}
|
||||
|
||||
if(sizeof($condition)) {
|
||||
$where_query[] = " AND ( ".join(" OR ", $condition)." )";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//- collection id or ids
|
||||
if( array_key_exists("collection", $this->filters) && sizeof($this->filters["collection"])) {
|
||||
$condition = array();
|
||||
|
||||
$objProductCollectionModel = new ProductCollectionModel();
|
||||
|
||||
foreach ($this->filters["collection"] as $_id) {
|
||||
|
||||
$collection_info = $objProductCollectionModel->getInfo($_id);
|
||||
if(!$collection_info) continue;
|
||||
|
||||
$filterPath["collection"][] = array(
|
||||
"id" => $_id,
|
||||
"name" => $collection_info["title"],
|
||||
);
|
||||
$condition[] = " `id` IN ( SELECT product_id FROM ".TableName::PRODUCT_PER_COLLECTION." WHERE `collection_id`='".intval($collection_info['id'])."' ) ";
|
||||
$filter_messages[] = [
|
||||
'title' => 'Bộ sưu tập ',
|
||||
'reset' => Url::buildUrl($this->_request_url, ['collection' => join(',', remove_item_from_array($this->filters["collection"], $_id))] ),
|
||||
];
|
||||
}
|
||||
|
||||
$where_query[] = " AND ( ".join(" OR ", $condition)." )";
|
||||
}
|
||||
|
||||
//- supplier id
|
||||
if( array_key_exists("supplier", $this->filters) && sizeof($this->filters["supplier"])) {
|
||||
/*$condition = array();
|
||||
|
||||
if(!$this->objSupplier) $this->objSupplier = new Supplier();
|
||||
|
||||
foreach ($this->filters["supplier"] as $_id) {
|
||||
$_id = intval($_id);
|
||||
|
||||
$supplier_info = $this->objSupplier->getInfo($_id);
|
||||
|
||||
$filterPath["supplier"][] = array(
|
||||
"id" => $_id,
|
||||
"name" => $supplier_info["name"],
|
||||
);
|
||||
$condition[] = " supplier_id = '".$_id."' ";
|
||||
$filter_messages[] = [
|
||||
'title' => $supplier_info["name"],
|
||||
'reset' => Url::buildUrl($this->_request_url, ['supplier' => join(',', remove_item_from_array($this->filters["supplier"], $_id))] ),
|
||||
];
|
||||
}
|
||||
|
||||
$where_query[] = " AND ( ".join(" OR ", $condition)." )";*/
|
||||
}
|
||||
|
||||
//- rating: 1-> 5
|
||||
if( array_key_exists("rating", $this->filters) && sizeof($this->filters["rating"])) {
|
||||
$condition = array();
|
||||
foreach ($this->filters["rating"] as $_id) {
|
||||
|
||||
$condition[] = " `rating` = '".intval($_id)."' ";
|
||||
$filterPath["rating"][] = array(
|
||||
"id" => $_id,
|
||||
"name" => $_id,
|
||||
);
|
||||
$filter_messages[] = [
|
||||
'title' => 'Đánh giá '.$_id,
|
||||
'reset' => Url::buildUrl($this->_request_url, ['rating' => join(',', remove_item_from_array($this->filters["rating"], $_id))] ),
|
||||
];
|
||||
}
|
||||
|
||||
$where_query[] = " AND ( ".join(" OR ", $condition)." )";
|
||||
}
|
||||
|
||||
//- category id or ids
|
||||
if( array_key_exists("category", $this->filters) && sizeof($this->filters["category"])) {
|
||||
|
||||
$objProductCategoryModel = new ProductCategoryModel();
|
||||
|
||||
$condition = array();
|
||||
foreach ($this->filters["category"] as $cat_id) {
|
||||
|
||||
$cat_info = $objProductCategoryModel->getInfo($cat_id);
|
||||
if(!$cat_info) continue;
|
||||
|
||||
if($cat_info["is_parent"]) {
|
||||
$childListId = ($cat_info["child_ids"]) ?: '0';
|
||||
$condition[] = " `category_id` IN (".$childListId .") ";
|
||||
}else{
|
||||
$condition[] = " `category_id` = '".$cat_id."' ";
|
||||
}
|
||||
|
||||
$filterPath["category"][] = array(
|
||||
"id" => $cat_id,
|
||||
"name" => $cat_info['title'],
|
||||
);
|
||||
|
||||
$filter_messages[] = [
|
||||
'title' => $cat_info['title'],
|
||||
'reset' => Url::buildUrl($this->_request_url, ['category' => join(FILTER_VALUE_SEPARATOR, remove_item_from_array($this->filters["category"], $cat_id))] ),
|
||||
];
|
||||
}
|
||||
|
||||
if(sizeof($condition)) {
|
||||
$where_query[] = " AND `id` IN ( SELECT DISTINCT `item_id` FROM ".TableName::PRODUCT_PER_CATEGORY." WHERE " . join(" OR ", $condition) . " )";
|
||||
}
|
||||
}
|
||||
|
||||
//- status: 0|1|null
|
||||
if( array_key_exists("status", $this->filters) && sizeof($this->filters["status"])) {
|
||||
$where_query[] = " AND `status` IN (".join(',', $this->filters["status"]).") ";
|
||||
}
|
||||
|
||||
// spec_group_id
|
||||
if( array_key_exists("spec_group_id", $this->filters) && sizeof($this->filters["spec_group_id"])) {
|
||||
$where_query[] = " AND `spec_group_id` IN (".join(',', $this->filters["spec_group_id"]).") ";
|
||||
}
|
||||
|
||||
// detail_page_only: 0 | 1
|
||||
if( array_key_exists("detail_page_only", $this->filters) && $this->filters["detail_page_only"]) {
|
||||
$where_query[] = " AND `detail_page_only` = '".intval($this->filters['detail_page_only'])."' ";
|
||||
}
|
||||
|
||||
|
||||
//- query: search keyword
|
||||
if( array_key_exists("query", $this->filters) && $this->filters["query"]) {
|
||||
$keyword_search = $this->filters["query"];
|
||||
$search_by_product_id = intval(preg_replace('/[^0-9]/i', '', $keyword_search));
|
||||
|
||||
// todo: add more
|
||||
$filter_search = [];
|
||||
if(isset($this->filters["brand"]) && $this->filters["brand"]) {
|
||||
$filter_search['brand'] = ["IN", $this->filters["brand"]];
|
||||
}
|
||||
|
||||
if(isset($this->filters["status"]) && $this->filters["status"]) {
|
||||
$filter_search['status'] = ["IN", $this->filters["status"]];
|
||||
}
|
||||
|
||||
$objProductSearchModel = new ProductSearchModel();
|
||||
$match_result = $objProductSearchModel->find($keyword_search, $filter_search);
|
||||
|
||||
//debug_var($match_result);
|
||||
|
||||
$filterPath["search"] = array(
|
||||
"id" => $keyword_search,
|
||||
"name" => $keyword_search,
|
||||
);
|
||||
$filter_messages[] = [
|
||||
'title' => $keyword_search,
|
||||
'reset' => Url::buildUrl($this->_request_url, ['q' => ''] ),
|
||||
];
|
||||
|
||||
if($search_by_product_id > 0) {
|
||||
$where_query[] = (sizeof($match_result) > 0) ? " AND ( `id` IN (".join(',', $match_result).") OR `id` = '".$search_by_product_id."' ) " : " AND `id` = '".$search_by_product_id."' ";
|
||||
}else{
|
||||
$where_query[] = (sizeof($match_result) > 0) ? " AND `id` IN (".join(',', $match_result).") " : " AND `id` = -1 ";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//- hotType: saleoff | not | new | or combination of types
|
||||
if( array_key_exists("hotType", $this->filters) && sizeof($this->filters["hotType"])) {
|
||||
$config_hottype = AProductHotController::getProductHotTypeList();
|
||||
$condition = array();
|
||||
foreach ($this->filters["hotType"] as $_id) {
|
||||
if(!array_key_exists($_id, $config_hottype)) continue;
|
||||
|
||||
$condition[] = " `hot_type` = '".$_id."' ";
|
||||
|
||||
$filter_messages[] = [
|
||||
'title' => $config_hottype[$_id],
|
||||
'reset' => Url::buildUrl($this->_request_url, ['hotType' => '']),
|
||||
];
|
||||
}
|
||||
|
||||
if(sizeof($condition)) {
|
||||
$where_query[] = " AND `id` IN (SELECT pro_id FROM ".TB_PRODUCT_HOT." WHERE 1 AND ( ".join(" OR ", $condition)." ) ) ";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//- attribute values
|
||||
/*
|
||||
if( array_key_exists("attribute", $this->filters) && sizeof($this->filters["attribute"])) {
|
||||
$filter_attr_value_list = $this->filters["attribute"];
|
||||
//filter = attr_value_1-attr_value_2-attr_value_3,
|
||||
$query_attr_id = [];
|
||||
$count_filter = 0;
|
||||
|
||||
foreach($filter_attr_value_list as $attr_id){
|
||||
$attr_id = (int) $attr_id;
|
||||
if($attr_id) {
|
||||
$query_attr_id[] = $attr_id;
|
||||
$count_filter ++;
|
||||
}
|
||||
}
|
||||
|
||||
$product_filter_id_match = array();
|
||||
if(sizeof($query_attr_id)) {
|
||||
$query = $this->db->runQuery("
|
||||
SELECT DISTINCT pro_id , COUNT(*) as num_pro
|
||||
FROM ".TB_PRODUCT_ATTRIBUTE."
|
||||
WHERE attr_value_id IN (".join(',', $query_attr_id).")
|
||||
GROUP BY pro_id
|
||||
HAVING num_pro = ".$count_filter."
|
||||
LIMIT 10000
|
||||
");
|
||||
foreach ( $this->db->fetchAll($query) as $rs ) {
|
||||
$product_filter_id_match[] = $rs["pro_id"];
|
||||
}
|
||||
}
|
||||
|
||||
$where_query[] = (sizeof($product_filter_id_match)) ? " AND `id` IN (".join(', ', $product_filter_id_match).") " : " AND `id` = 0 " ;
|
||||
|
||||
//xay lai url de back
|
||||
if(!$this->objCategoryProduct) $this->objCategoryProduct = new CategoryProduct();
|
||||
|
||||
foreach($filter_attr_value_list as $value_id ){
|
||||
$att_name = $this->objCategoryProduct->atrValueName($value_id);
|
||||
|
||||
$filterPath["attribute"][] = array(
|
||||
"id" => $value_id,
|
||||
"name" => $att_name,
|
||||
);
|
||||
$filter_messages[] = [
|
||||
'title' => $att_name,
|
||||
'reset' => Url::buildUrl($this->_request_url, ['filter' => join(FILTER_VALUE_SEPARATOR, remove_item_from_array($this->filters["attribute"], $value_id))] ),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//- attribute values
|
||||
if( array_key_exists("attribute", $this->filters) && sizeof($this->filters["attribute"])) {
|
||||
|
||||
$filter_attr_value_list = $this->filters["attribute"];
|
||||
|
||||
$attr_values_per_attribute = $this->groupAttributeValuesByAttributeId($filter_attr_value_list);
|
||||
|
||||
$having_match_count = sizeof(array_keys($attr_values_per_attribute));
|
||||
|
||||
$attribute_info_list = $this->groupAttributeListInfo(array_keys($attr_values_per_attribute));
|
||||
|
||||
$attr_where_query = [];
|
||||
foreach ($attr_values_per_attribute as $_att_id => $_att_value_list) {
|
||||
// if same attribute : find products that match either ONE of these values (not match ALL values)
|
||||
$_att_info = $attribute_info_list[$_att_id];
|
||||
if (!$_att_info) continue;
|
||||
|
||||
// this attribute requires all products must have ALL selected values
|
||||
if ($_att_info['value_match_all'] && sizeof($_att_value_list) > 1) {
|
||||
|
||||
$_product_id_match_all = $this->getProductMatchAllAttributeValueIds($_att_value_list);
|
||||
|
||||
if (sizeof($_product_id_match_all) > 0) {
|
||||
$attr_where_query[] = " ( `id` IN (" . join(",", $_product_id_match_all) . ") ) ";
|
||||
} else {
|
||||
$attr_where_query[] = " ( `id` = -1 ) ";
|
||||
}
|
||||
|
||||
} else {
|
||||
$attr_where_query[] = " ( SELECT DISTINCT `pro_id` FROM " . TB_PRODUCT_ATTRIBUTE . " WHERE (" .
|
||||
join(" OR ", array_map(function ($_item) { return " `attr_value_id` = '" . intval($_item['id']) . "' "; }, $_att_value_list))
|
||||
. " ) ) ";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$product_filter_id_match = array();
|
||||
|
||||
if (sizeof($attr_where_query)) {
|
||||
$query = $this->db->runQuery("
|
||||
SELECT `pro_id` , COUNT(*) AS num_pro
|
||||
FROM ( " . join(" UNION ALL ", $attr_where_query) . " ) AS tpm_tb
|
||||
GROUP BY pro_id
|
||||
HAVING num_pro = " . $having_match_count . "
|
||||
LIMIT 10000
|
||||
");
|
||||
foreach ($this->db->fetchAll($query) as $rs) {
|
||||
$product_filter_id_match[] = $rs["pro_id"];
|
||||
}
|
||||
}
|
||||
|
||||
$where_query[] = (sizeof($product_filter_id_match)) ? " AND " . TB_PRODUCT_LIGHT . ".`id` IN (" . join(', ', $product_filter_id_match) . ") " : " AND " . TB_PRODUCT_LIGHT . ".`id` = 0 ";
|
||||
|
||||
//xay lai url de back
|
||||
$objProductAttributeModel = new ProductAttributeModel();
|
||||
|
||||
foreach($filter_attr_value_list as $value_id ){
|
||||
$att_name = $objProductAttributeModel->getInfo($value_id)['title'];
|
||||
|
||||
$filterPath["attribute"][] = array(
|
||||
"id" => $value_id,
|
||||
"name" => $att_name,
|
||||
);
|
||||
$filter_messages[] = [
|
||||
'title' => $att_name,
|
||||
'reset' => Url::buildUrl($this->_request_url, ['filter' => join(FILTER_VALUE_SEPARATOR, remove_item_from_array($this->filters["attribute"], $value_id))] ),
|
||||
];
|
||||
}
|
||||
|
||||
/*//xay lai url de back
|
||||
$filterPath["attribute"] = $filter_attr_value_list;
|
||||
|
||||
foreach ($attr_values_per_attribute as $_att_id => $_att_value_list) {
|
||||
foreach ($_att_value_list as $_item) {
|
||||
$filter_messages[] = [
|
||||
'title' => $_item['title'],
|
||||
'reset' => Url::buildUrl(CURRENT_URL, ['filter' => join('-', remove_item_from_array($filter_attr_value_list, $_item['id']))]),
|
||||
];
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
//given products' ids
|
||||
if( array_key_exists("ids", $this->filters) && sizeof($this->filters["ids"])) {
|
||||
|
||||
$filter_messages[] = [
|
||||
'title' => "IDs",
|
||||
'reset' => Url::buildUrl($this->_request_url, ['ids' => '']),
|
||||
];
|
||||
|
||||
$where_query[] = " AND `id` IN (". join(",", $this->filters["ids"]) .") ";
|
||||
}
|
||||
|
||||
// exclude some ids
|
||||
if( array_key_exists("excluded_ids", $this->filters) && sizeof($this->filters["excluded_ids"])) {
|
||||
|
||||
$filter_messages[] = [
|
||||
'title' => "Excluded IDs",
|
||||
'reset' => Url::buildUrl($this->_request_url, ['excluded_ids' => '']),
|
||||
];
|
||||
|
||||
$where_query[] = " AND `id` NOT IN (". join(",", $this->filters["excluded_ids"]) .") ";
|
||||
}
|
||||
|
||||
$price_range_query_limit = join(" ",$where_query);
|
||||
|
||||
//- price range
|
||||
if(isset($this->filters["price"]) && sizeof($this->filters["price"]) && ($this->filters["price"]['min'] > 0 || $this->filters["price"]['max'] > 0)) {
|
||||
//limit by price range
|
||||
$maxPrice = clean_price($this->filters["price"]['max']);
|
||||
$minPrice = clean_price($this->filters["price"]['min']);
|
||||
|
||||
$price_range_query = '';
|
||||
if($maxPrice > 0 && $minPrice > 0){
|
||||
$price_range_query = " ( `price` BETWEEN '".$minPrice."' AND '".$maxPrice."' ) ";
|
||||
|
||||
}else if($maxPrice > 0){
|
||||
$price_range_query = " `price` < '".$maxPrice."' ";
|
||||
|
||||
}else if($minPrice > 0){
|
||||
$price_range_query = " `price` >='".$minPrice."' ";
|
||||
}
|
||||
|
||||
/*if(ENABLE_INVENTORY_PER_STORE && USER_LOCATION) {
|
||||
|
||||
$list_ids = $this->getProductIds($price_range_query_limit);
|
||||
$this->objCache->set("all_product_ids_location", $list_ids);
|
||||
|
||||
$objUStoreLocation = new UStoreLocation();
|
||||
$location_products = $objUStoreLocation->getAllProductForLocation(USER_LOCATION, $list_ids, $sort_by);
|
||||
$location_products = $this->filterLocationProductByPrice($location_products, $maxPrice, $minPrice);
|
||||
|
||||
$this->objCache->set("location_products", $location_products);
|
||||
|
||||
$location_product_ids = array_keys($location_products);
|
||||
$where_query[] = (sizeof($location_product_ids)) ? " AND `id` IN (".join(',', $location_product_ids).") " : " AND `id` = 0";
|
||||
|
||||
} else {
|
||||
$where_query[] = " AND ". $price_range_query;
|
||||
}*/
|
||||
|
||||
$where_query[] = " AND ". $price_range_query;
|
||||
|
||||
$filterPath["price"] = array(
|
||||
"min" => $minPrice,
|
||||
"max" => $maxPrice,
|
||||
);
|
||||
|
||||
$price_format = ProductFilterPrice::buildPriceRangeFormat($minPrice, $maxPrice);
|
||||
|
||||
$filter_messages[] = [
|
||||
'title' => $price_format['title'],
|
||||
'reset' => Url::buildUrl($this->_request_url, ['p' => '', 'min' => '', 'max' => ''])
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
$price_range_query_limit,
|
||||
$filterPath,
|
||||
$filter_messages,
|
||||
$where_query
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function getProductMatchAllAttributeValueIds(array $_att_value_list) {
|
||||
$objProductAttributeModel = new ProductAttributeModel();
|
||||
return $objProductAttributeModel->getProductMatchAllAttributeValueIds($_att_value_list);
|
||||
}
|
||||
|
||||
|
||||
protected function groupAttributeListInfo(array $attr_ids) {
|
||||
|
||||
$objProductAttributeModel = new ProductAttributeModel();
|
||||
$attr_list_info = $objProductAttributeModel->getListByIds($attr_ids);
|
||||
|
||||
$final_list = [];
|
||||
foreach ($attr_ids as $_id) {
|
||||
$final_list[$_id] = (isset($attr_list_info[$_id])) ? $attr_list_info[$_id] : null;
|
||||
}
|
||||
|
||||
return $final_list;
|
||||
}
|
||||
|
||||
|
||||
protected function groupAttributeValuesByAttributeId(array $attr_value_ids) {
|
||||
|
||||
$objProductAttributeValueModel = new ProductAttributeValueModel(0);
|
||||
|
||||
$result = array();
|
||||
foreach ( $objProductAttributeValueModel->getListByIds($attr_value_ids) as $info ) {
|
||||
$result[$info['attributeId']][] = [
|
||||
'id' => $info['id'],
|
||||
'title' => $info['value'],
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
protected function filterLocationProductByPrice(array $product_list, $max_price, $min_price) {
|
||||
if($max_price > 0 && $min_price > 0){
|
||||
return array_filter($product_list, function ($pro) use ($max_price, $min_price) {
|
||||
return ($pro['price'] >= $min_price && $pro['price'] < $max_price);
|
||||
});
|
||||
}
|
||||
|
||||
if($max_price > 0){
|
||||
return array_filter($product_list, function ($pro) use ($max_price, $min_price) {
|
||||
return ($pro['price'] < $max_price);
|
||||
});
|
||||
}
|
||||
|
||||
if($min_price > 0){
|
||||
return array_filter($product_list, function ($pro) use ($max_price, $min_price) {
|
||||
return ($pro['price'] >= $min_price);
|
||||
});
|
||||
}
|
||||
|
||||
return $product_list;
|
||||
}
|
||||
|
||||
|
||||
protected function getOrderingClause($sort_by) {
|
||||
$mappings = [
|
||||
'order-new' => "ORDER BY `ordering` DESC, `id` DESC",
|
||||
'order-last-update' => "ORDER BY `ordering` DESC, last_update DESC",
|
||||
'last-update' => "ORDER BY `last_update` DESC",
|
||||
'order' => "ORDER BY `ordering` DESC",
|
||||
'new' => "ORDER BY `id` DESC",
|
||||
'price-asc' => "ORDER BY `price` asc",
|
||||
'price-desc' => "ORDER BY `price` DESC ",
|
||||
'view' => "ORDER BY `visit` desc",
|
||||
'ranking' => "ORDER BY `ranking` DESC",
|
||||
'name' => "ORDER BY `title` asc",
|
||||
];
|
||||
|
||||
if(array_key_exists($sort_by, $mappings)) {
|
||||
return $mappings[$sort_by];
|
||||
}
|
||||
|
||||
return "ORDER BY `ordering` DESC, `id` DESC";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Controller;
|
||||
|
||||
use Hura8\Components\Product\Model\ProductFilterModel;
|
||||
|
||||
|
||||
class ProductFilterOptionsController {
|
||||
|
||||
protected $_current_category_ids = [];
|
||||
|
||||
protected $_list_product_ids = [];
|
||||
|
||||
protected $_price_range = [];// [1000000, 5000000, 15000000, 25000000, 50000000];
|
||||
|
||||
protected $_filters = [
|
||||
"price" => array('max' => 0, 'min'=> 0),
|
||||
"brand" => array(), // array(1,2,3,)
|
||||
"collection" => array(), // array(1,2,3,)
|
||||
"supplier" => array(), // array(1,2,3,)
|
||||
"rating" => array(), // array(1,2,3,)
|
||||
"category" => array(), // array(1,2,3,)
|
||||
"status" => array(), // array(1,2,3,)
|
||||
"query" => "", // string search keyword
|
||||
"hotType" => array(),// array(saleoff | not | new)
|
||||
"attribute" => array(), // array(1,2,3,)
|
||||
"ids" => array(), // array(1,2,3,)
|
||||
"promotion" => "",
|
||||
"storeId" => array(), // array(1,2,3,)
|
||||
"other_filter" => array() // array(in-stock, has-promotion etc...)
|
||||
];
|
||||
|
||||
protected $objProductFilterModel;
|
||||
|
||||
public function __construct($filters, $current_category_ids = [], $list_product_ids = [], $price_range = []) {
|
||||
|
||||
$this->objProductFilterModel = new ProductFilterModel();
|
||||
|
||||
$this->_filters = $filters;
|
||||
$this->_current_category_ids = $current_category_ids;
|
||||
$this->_list_product_ids = $list_product_ids;
|
||||
$this->_price_range = $price_range;
|
||||
}
|
||||
|
||||
|
||||
public function ratingList() {
|
||||
|
||||
$neededList = array();
|
||||
|
||||
foreach ( $this->objProductFilterModel->ratingList($this->_list_product_ids) as $result ) {
|
||||
$neededList[] = array(
|
||||
"rating" => $result['review_rate'] ,
|
||||
"count" => $result['num'] ,
|
||||
'is_selected' => in_array($result['review_rate'], $this->_filters['rating']),
|
||||
);
|
||||
}
|
||||
|
||||
return $neededList;
|
||||
}
|
||||
|
||||
|
||||
public function categoryList() {
|
||||
|
||||
if(!sizeof($this->_list_product_ids)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->objProductFilterModel->categoryList($this->_filters['category'], $this->_list_product_ids);
|
||||
}
|
||||
|
||||
|
||||
public function brandList() {
|
||||
|
||||
if(!sizeof($this->_list_product_ids)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->objProductFilterModel->brandList($this->_filters['brand'], $this->_list_product_ids);
|
||||
}
|
||||
|
||||
|
||||
public function attributeList() {
|
||||
|
||||
return $this->objProductFilterModel->attributeList(
|
||||
$this->_filters['attribute'],
|
||||
$this->_current_category_ids,
|
||||
$this->_list_product_ids
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function priceList() {
|
||||
|
||||
return $this->objProductFilterModel->priceList(
|
||||
$this->_filters['price']['max'] ,
|
||||
$this->_filters['price']['min'],
|
||||
$this->_list_product_ids,
|
||||
$this->_price_range
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Controller;
|
||||
|
||||
use Hura8\System\Url;
|
||||
|
||||
|
||||
class ProductFilterOptionsTranslationController {
|
||||
|
||||
protected $_request_url = '';
|
||||
protected $_url_elements = [
|
||||
'scheme' => '',
|
||||
'host' => '',
|
||||
'port' => '',
|
||||
'user' => '',
|
||||
'pass' => '',
|
||||
'path' => '',
|
||||
'query' => [],
|
||||
'fragment' => '',
|
||||
];
|
||||
|
||||
protected $_price_format = '';
|
||||
protected $_brand_format = '';
|
||||
protected $_filter_format = '';
|
||||
|
||||
|
||||
public function __construct($request_url) {
|
||||
if(defined('PRICE_FILTER_FORMAT') && PRICE_FILTER_FORMAT) {
|
||||
$this->_price_format = PRICE_FILTER_FORMAT;
|
||||
}
|
||||
|
||||
if(defined('BRAND_FILTER_FORMAT') && BRAND_FILTER_FORMAT) {
|
||||
$this->_brand_format = BRAND_FILTER_FORMAT;
|
||||
}
|
||||
|
||||
if(defined('ATTRIBUTE_FILTER_FORMAT') && ATTRIBUTE_FILTER_FORMAT ) {
|
||||
$this->_filter_format = ATTRIBUTE_FILTER_FORMAT;
|
||||
}
|
||||
|
||||
$this->_request_url = $request_url;
|
||||
$this->_url_elements = Url::parse($request_url);
|
||||
}
|
||||
|
||||
|
||||
public function getAllFilterOptions(array $category_list = [], array $attribute_list = [], array $brand_list = [], array $price_list_options = []) {
|
||||
|
||||
$result = [
|
||||
'category' => $category_list,
|
||||
'price' => $this->translatePriceList($price_list_options),
|
||||
'brand' => $this->translateBrandList($brand_list),
|
||||
'attribute' => $this->translateAttributeList($attribute_list),
|
||||
];
|
||||
|
||||
$selected_categories = array_filter($category_list, function ($item){ return $item['is_selected'];});
|
||||
$selected_prices = array_filter($result['price'], function ($item){ return $item['is_selected'];});
|
||||
$selected_brands = array_filter($result['brand'], function ($item){ return $item['is_selected'];});
|
||||
$selected_attributes = array_filter($result['attribute'], function ($item){ return $item['is_selected'];});
|
||||
|
||||
$filter_messages = [];
|
||||
|
||||
foreach ($selected_categories as $selected_category) {
|
||||
$filter_messages[] = [
|
||||
'name' => $selected_category['name'], // 'Danh mục: '.
|
||||
'reset_url' => Url::buildUrl($this->_request_url, ['category' => ''] ),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($selected_prices as $selected_price) {
|
||||
$filter_messages[] = [
|
||||
'name' => $selected_price['name'], // 'Giá: '.
|
||||
'reset_url' => $selected_price['url'],
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($selected_brands as $selected_brand) {
|
||||
$filter_messages[] = [
|
||||
'name' => $selected_brand['name'], // 'Thương hiệu: '.
|
||||
'reset_url' => $selected_brand['url'],
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($selected_attributes as $selected_attribute) {
|
||||
|
||||
$selected_attribute_values = array_filter($selected_attribute['value_list'], function ($item){ return $item['is_selected'];});
|
||||
|
||||
foreach ($selected_attribute_values as $selected_attribute_value) {
|
||||
$filter_messages[] = [
|
||||
'name' => $selected_attribute_value['name'], //$selected_attribute['name'].': '.$selected_attribute_value['name'],
|
||||
'reset_url' => $selected_attribute_value['url'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return [$result, $filter_messages];
|
||||
}
|
||||
|
||||
|
||||
public function translateAttributeList(array $attribute_list = []) {
|
||||
$result = [];
|
||||
|
||||
foreach ($attribute_list as $attr_info) {
|
||||
$copy = $attr_info;
|
||||
$copy['value_list'] = array_map(function ($value_info) use ($attr_info) {
|
||||
return $this->translateAttributeValue($attr_info['filter_code'], $value_info);
|
||||
}, $attr_info['value_list']);
|
||||
|
||||
$result[] = $copy;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
protected function translateAttributeValue($attribute_filter_code, array $value_info = []) {
|
||||
$copy = $value_info;
|
||||
|
||||
if($copy['is_selected']) {
|
||||
$copy['url'] = Url::buildUrl($this->_request_url, $this->buildAttributeValueUrlResetParameters($attribute_filter_code, $value_info['id'], $value_info['api_key']) );
|
||||
}else{
|
||||
$copy['url'] = Url::buildUrl($this->_request_url, $this->buildAttributeValueUrlParameters($attribute_filter_code, $value_info['id'], $value_info['api_key']) );
|
||||
}
|
||||
|
||||
//$copy['reset_url'] = Url::buildUrl($this->_request_url, $this->buildAttributeValueUrlResetParameters($attribute_filter_code, $value_info['id'], $value_info['api_key']) );
|
||||
|
||||
return $copy;
|
||||
}
|
||||
|
||||
|
||||
protected function buildAttributeValueUrlParameters($attribute_filter_code, $value_id, $value_api_key) {
|
||||
if($this->_filter_format == 'filter_code') {
|
||||
$filter_query = (isset($this->_url_elements['query'][$attribute_filter_code])) ? $this->_url_elements['query'][$attribute_filter_code] : '';
|
||||
$filter_value_list = ($filter_query) ? explode(FILTER_VALUE_SEPARATOR, $filter_query) : [];
|
||||
|
||||
$filter_value_list[] = $value_api_key;
|
||||
|
||||
$result = [];
|
||||
$result[$attribute_filter_code] = join(FILTER_VALUE_SEPARATOR, $filter_value_list );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// default
|
||||
$filter_query = (isset($this->_url_elements['query']['filter'])) ? $this->_url_elements['query']['filter'] : '';
|
||||
$filter_value_list = ($filter_query) ? explode(FILTER_VALUE_SEPARATOR, $filter_query) : [];
|
||||
|
||||
$filter_value_list[] = $value_id;
|
||||
sort($filter_value_list);
|
||||
|
||||
return [
|
||||
'filter' => join(FILTER_VALUE_SEPARATOR, $filter_value_list ),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function buildAttributeValueUrlResetParameters($attribute_filter_code, $value_id, $value_api_key) {
|
||||
if($this->_filter_format == 'filter_code') {
|
||||
$filter_query = (isset($this->_url_elements['query'][$attribute_filter_code])) ? $this->_url_elements['query'][$attribute_filter_code] : '';
|
||||
$filter_value_list = ($filter_query) ? explode(FILTER_VALUE_SEPARATOR, $filter_query) : [];
|
||||
|
||||
$filter_value_list = remove_item_from_array($filter_value_list, $value_api_key);
|
||||
|
||||
$result = [];
|
||||
$result[$attribute_filter_code] = join(FILTER_VALUE_SEPARATOR, $filter_value_list );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
// default
|
||||
$filter_query = (isset($this->_url_elements['query']['filter'])) ? $this->_url_elements['query']['filter'] : '';
|
||||
$filter_value_list = ($filter_query) ? explode(FILTER_VALUE_SEPARATOR, $filter_query) : [];
|
||||
|
||||
$filter_value_list = remove_item_from_array($filter_value_list, $value_id);
|
||||
|
||||
return [
|
||||
'filter' => join(FILTER_VALUE_SEPARATOR, $filter_value_list ),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function translateBrandList(array $brand_list = []) {
|
||||
|
||||
return array_map(function ($item){
|
||||
$copy = $item;
|
||||
|
||||
if(($copy['is_selected'])) {
|
||||
$copy['url'] = Url::buildUrl($this->_request_url, $this->buildBrandUrlResetParameters($item['id'], $item['brand_index']) ) ;
|
||||
}else{
|
||||
$copy['url'] = Url::buildUrl($this->_request_url, $this->buildBrandUrlParameters($item['id'], $item['brand_index']) );
|
||||
}
|
||||
|
||||
//$copy['reset_url'] = Url::buildUrl($this->_request_url, $this->buildBrandUrlResetParameters($item['id'], $item['brand_index']) );
|
||||
//unset($copy['brand_index']);
|
||||
|
||||
return $copy;
|
||||
|
||||
}, $brand_list);
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected function buildBrandUrlResetParameters($brand_id, $brand_index){
|
||||
$brand_query = (isset($this->_url_elements['query']['brand'])) ? $this->_url_elements['query']['brand'] : '';
|
||||
$brand_list = ($brand_query) ? explode(FILTER_VALUE_SEPARATOR, $brand_query) : [];
|
||||
|
||||
if($this->_brand_format == 'brand_index') {
|
||||
$brand_list = remove_item_from_array($brand_list, $brand_index);
|
||||
}else{
|
||||
$brand_list = remove_item_from_array($brand_list, $brand_id);
|
||||
}
|
||||
|
||||
return [
|
||||
'brand' => join(FILTER_VALUE_SEPARATOR, $brand_list ),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function buildBrandUrlParameters($brand_id, $brand_index){
|
||||
$brand_query = (isset($this->_url_elements['query']['brand'])) ? $this->_url_elements['query']['brand'] : '';
|
||||
$brand_list = ($brand_query) ? explode(FILTER_VALUE_SEPARATOR, $brand_query) : [];
|
||||
|
||||
if($this->_brand_format == 'brand_index') {
|
||||
if(!in_array($brand_index, $brand_list)) $brand_list[] = $brand_index;
|
||||
}else{
|
||||
if(!in_array($brand_id, $brand_list)) $brand_list[] = $brand_id;
|
||||
}
|
||||
|
||||
return [
|
||||
'brand' => join(FILTER_VALUE_SEPARATOR, $brand_list ),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function translatePriceList(array $price_list_options = []) {
|
||||
|
||||
return array_map(function ($item){
|
||||
$copy = $item;
|
||||
|
||||
$format = $this->buildPriceRangeFormat($item['min'], $item['max']);
|
||||
|
||||
$copy['name'] = $format['name'];
|
||||
$copy['url'] = ($copy['is_selected']) ? Url::buildUrl($this->_request_url, $this->buildPriceUrlResetParameters()) : Url::buildUrl($this->_request_url, $format['url_para']);
|
||||
|
||||
//$copy['reset_url'] = Url::buildUrl($this->_request_url, $this->buildPriceUrlResetParameters());
|
||||
//unset($copy['min'], $copy['max']);
|
||||
|
||||
return $copy;
|
||||
|
||||
}, $price_list_options);
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected function buildPriceRangeFormat($min_price, $max_price) {
|
||||
if($min_price > 0 && !$max_price) {
|
||||
$title = "Trên ".$this->format_search_price($min_price);
|
||||
}elseif(!$min_price && $max_price > 0) {
|
||||
$title = "Dưới ".$this->format_search_price($max_price);
|
||||
}else{
|
||||
$title = $this->format_search_price($min_price)." - ".$this->format_search_price($max_price);
|
||||
}
|
||||
|
||||
return [
|
||||
'url_para' => $this->buildPriceUrlParameters($min_price, $max_price),
|
||||
'name' => $title,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function format_search_price($p_price){
|
||||
|
||||
$price_len = strlen($p_price);
|
||||
|
||||
if($price_len < 7) {
|
||||
return round($p_price/1000,1)." ngàn";
|
||||
}
|
||||
else if($price_len < 10) {
|
||||
return round($p_price/1000000,1)." triệu";
|
||||
}
|
||||
|
||||
return round($p_price/1000000000,1)." tỷ";
|
||||
}
|
||||
|
||||
|
||||
protected function buildPriceUrlResetParameters() {
|
||||
if( $this->_price_format == 'p') {
|
||||
return [
|
||||
"p" => '',
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
"min" => '' ,
|
||||
"max" => '' ,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function buildPriceUrlParameters($min_price = 0, $max_price = 0) {
|
||||
|
||||
if($min_price > 0 && !$max_price) {
|
||||
if( $this->_price_format == 'p') {
|
||||
return [
|
||||
"p" => "tren-".self::convertPriceFormatToFilter($this->format_search_price($min_price)),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
"min" => $min_price ,
|
||||
];
|
||||
}
|
||||
|
||||
if(!$min_price && $max_price > 0) {
|
||||
|
||||
if( $this->_price_format == 'p') {
|
||||
return [
|
||||
"p" => "duoi-" . self::convertPriceFormatToFilter($this->format_search_price($max_price)),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
"max" => $max_price,
|
||||
];
|
||||
}
|
||||
|
||||
if( $this->_price_format == 'p') {
|
||||
return [
|
||||
"p" => self::convertPriceFormatToFilter($this->format_search_price($min_price)) . "-" . self::convertPriceFormatToFilter($this->format_search_price($max_price)),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
"max" => $max_price ,
|
||||
"min" => $min_price,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
// convert: 10 ngàn -> 10ngan, 10 triệu => 10trieu
|
||||
protected static function convertPriceFormatToFilter($price_format){
|
||||
$price_format = str_replace(['ngàn', 'triệu'], ['ngan', 'trieu'], $price_format);
|
||||
// remove whitespace
|
||||
return str_replace(" ",'', $price_format);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Controller;
|
||||
|
||||
use Hura8\Components\Product\Model\ProductCategoryLanguageModel;
|
||||
use Hura8\Components\Product\Model\ProductCategoryModel;
|
||||
use Hura8\System\Controller\aCategoryBaseController;
|
||||
|
||||
class bProductCategoryController extends aCategoryBaseController
|
||||
{
|
||||
|
||||
static $image_folder = "media/category";
|
||||
|
||||
protected $objProductCategoryModel;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objProductCategoryModel = new ProductCategoryModel();
|
||||
|
||||
if(!$this->isDefaultLanguage()) {
|
||||
//$this->objProductCategoryLanguageModel->createTableLang();
|
||||
parent::__construct(
|
||||
$this->objProductCategoryModel,
|
||||
new ProductCategoryLanguageModel()
|
||||
);
|
||||
|
||||
}else{
|
||||
parent::__construct(
|
||||
$this->objProductCategoryModel
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInfo(?array $info) : ?array
|
||||
{
|
||||
if(!$info) return null;
|
||||
|
||||
if($info['icon']) $info['icon'] = STATIC_DOMAIN . "/" . static::$image_folder . "/" . $info['icon'];
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
// get full info- basic with description
|
||||
public function getFullInfo($id): ?array
|
||||
{
|
||||
$info = $this->objProductCategoryModel->getFullInfo($id);
|
||||
|
||||
if(!$info) return null;
|
||||
|
||||
if($this->iEntityLanguageModel) {
|
||||
$item_language_info = $this->iEntityLanguageModel->getInfo($id);
|
||||
if($item_language_info) {
|
||||
return $this->formatItemInfo(array_merge($info, $item_language_info));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->formatItemInfo($info);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Controller;
|
||||
|
||||
|
||||
use Hura8\Components\Product\Model\ProductCollectionLanguageModel;
|
||||
use Hura8\Components\Product\Model\ProductCollectionModel;
|
||||
use Hura8\System\Controller\aCategoryBaseController;
|
||||
|
||||
|
||||
class bProductCollectionController extends aCategoryBaseController
|
||||
{
|
||||
|
||||
static $image_folder = "media/category";
|
||||
|
||||
protected $objProductCollectionModel;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objProductCollectionModel = new ProductCollectionModel();
|
||||
|
||||
if(!$this->isDefaultLanguage()) {
|
||||
//$this->objProductCategoryLanguageModel->createTableLang();
|
||||
parent::__construct(
|
||||
$this->objProductCollectionModel,
|
||||
new ProductCollectionLanguageModel()
|
||||
);
|
||||
|
||||
}else{
|
||||
parent::__construct(
|
||||
$this->objProductCollectionModel
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getTotalProduct($collection_id, array $condition = [])
|
||||
{
|
||||
return $this->objProductCollectionModel->getTotalProduct($collection_id, $condition);
|
||||
}
|
||||
|
||||
|
||||
public function getListProduct($collection_id, array $condition = []) {
|
||||
return $this->objProductCollectionModel->getListProduct($collection_id, $condition);
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInList(array $info) : array
|
||||
{
|
||||
return $this->formatItemInfo($info);
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInfo(?array $info) : ?array
|
||||
{
|
||||
$info['url'] = "/collection/".$info['url_index'];
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
210
inc/Hura8/Components/Product/Controller/bProductController.php
Normal file
210
inc/Hura8/Components/Product/Controller/bProductController.php
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Controller;
|
||||
|
||||
|
||||
use Hura8\Components\Product\Model\ProductImageModel;
|
||||
use Hura8\Components\Product\Model\ProductLanguageModel;
|
||||
use Hura8\Components\Product\Model\ProductModel;
|
||||
use Hura8\System\Controller\aEntityBaseController;
|
||||
use Hura8\System\Security\DataClean;
|
||||
use Hura8\System\Security\DataType;
|
||||
use Hura8\System\Url;
|
||||
|
||||
|
||||
abstract class bProductController extends aEntityBaseController
|
||||
{
|
||||
|
||||
static $image_folder = "media/product";
|
||||
|
||||
static $resized_sizes = array(
|
||||
't' => ['width' => 100,] ,
|
||||
's' => ['width' => 300,] ,
|
||||
'l' => ['width' => 650,]
|
||||
);
|
||||
|
||||
protected $objProductModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->objProductModel = new ProductModel();
|
||||
|
||||
if(!$this->isDefaultLanguage()) {
|
||||
$objProductLanguageModel = new ProductLanguageModel();
|
||||
// $this->objProductLanguageModel->createTableLang();
|
||||
parent::__construct($this->objProductModel, $objProductLanguageModel);
|
||||
}else{
|
||||
parent::__construct($this->objProductModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//get product image list
|
||||
public function productImageList($proId){
|
||||
$objProductImageModel = new ProductImageModel($proId);
|
||||
$result = array();
|
||||
foreach ( $objProductImageModel->getList(["numPerPage" => 100]) as $rs ) {
|
||||
$result[] = [
|
||||
"size" => static::getResizedImageCollection($rs['img_name']),
|
||||
"alt" => $rs['alt'],
|
||||
"folder" => $rs['folder'],
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function getProductDisplayOptions($current_url) {
|
||||
$allowed_options = array(
|
||||
"list" => "Danh sách",
|
||||
"grid" => "Xem nhóm",
|
||||
"detail" => "Chi tiết"
|
||||
) ;
|
||||
|
||||
$collection = array();
|
||||
foreach($allowed_options as $option => $name){
|
||||
$url = Url::buildUrl($current_url, array("display" => ""));
|
||||
$collection[] = array(
|
||||
"url" => Url::buildUrl($url, array("display" => $option)) ,
|
||||
"key" => $option ,
|
||||
"name" => $name ,
|
||||
);
|
||||
}
|
||||
return $collection;
|
||||
}
|
||||
|
||||
|
||||
public function getProductOtherFilterOptions($current_url) {
|
||||
$allowed_options = array(
|
||||
//"order" => $global_language['sort_by_order'] ,
|
||||
"in-stock" => 'Còn hàng' ,
|
||||
) ;
|
||||
|
||||
$_collection = array();
|
||||
foreach($allowed_options as $option => $_name){
|
||||
$_collection[] = array(
|
||||
"url" => Url::buildUrl($current_url, array("other_filter" => $option, 'page' => '')) ,
|
||||
"key" => $option ,
|
||||
"name" => $_name ,
|
||||
);
|
||||
}
|
||||
return $_collection;
|
||||
}
|
||||
|
||||
|
||||
public function getProductSortOptions($current_url, array $options = []) {
|
||||
//global $global_language;
|
||||
|
||||
if(!sizeof($options)) $options = array(
|
||||
//"order" => $global_language['sort_by_order'] ,
|
||||
"new" => "Mới nhất" ,
|
||||
"price-asc" => "Giá tăng dần", //$global_language['sort_by_price_asc'] ,
|
||||
"price-desc" => "Giá giảm dần", //$global_language['sort_by_price_desc'] ,
|
||||
"view" => "Lượt xem", //$global_language['sort_by_view'],
|
||||
"comment" => "Trao đổi", //$global_language['sort_by_comment'] ,
|
||||
"rating" => "Đánh giá", //$global_language['sort_by_rating'] ,
|
||||
"name" => "Tên A->Z" ,
|
||||
) ;
|
||||
|
||||
$sort_by_collection = array();
|
||||
foreach($options as $sort_option=>$sort_name){
|
||||
// $url = build_url($current_url, array("sort" => ""));
|
||||
$sort_by_collection[] = array(
|
||||
"url" => Url::buildUrl($current_url, array("sort" => $sort_option)) ,
|
||||
"key" => $sort_option ,
|
||||
"name" => $sort_name ,
|
||||
);
|
||||
}
|
||||
return $sort_by_collection;
|
||||
}
|
||||
|
||||
|
||||
public function getProductInfoBySKU($sku) {
|
||||
|
||||
return self::getCache(md5("getFullInfo-".$sku), function () use ($sku) {
|
||||
|
||||
$info = $this->objProductModel->getProductInfoBySKU($sku);
|
||||
|
||||
return ($info) ? $this->formatItemInfo($info) : null;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// get full info- basic with description
|
||||
public function getFullInfo($id)
|
||||
{
|
||||
return self::getCache("getFullInfo-".$id, function () use ($id) {
|
||||
|
||||
$info = $this->objProductModel->getFullInfo($id);
|
||||
|
||||
if($this->iEntityLanguageModel && $info) {
|
||||
$item_language_info = $this->iEntityLanguageModel->getInfo($id);
|
||||
if($item_language_info) {
|
||||
return $this->formatItemInfo(array_merge($info, $item_language_info));
|
||||
}
|
||||
}
|
||||
|
||||
return ($info) ? $this->formatItemInfo($info) : null;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected function validateAndCleanFilterCondition(array $raw_filter_condition): array
|
||||
{
|
||||
$clean_values = parent::validateAndCleanFilterCondition($raw_filter_condition);
|
||||
|
||||
// special cases for 'price' which is in range
|
||||
if(array_key_exists('price', $raw_filter_condition)) {
|
||||
$value = $raw_filter_condition['price'];
|
||||
// expect $value = array('max' => 0, 'min'=> 0)
|
||||
if(isset($value['max']) && isset($value['min'])) {
|
||||
$clean_values['price'] = array(
|
||||
'max' => DataClean::makeInputSafe($value['max'], DataType::INTEGER),
|
||||
'min' => DataClean::makeInputSafe($value['min'], DataType::INTEGER),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $clean_values;
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInList(array $item_info) : array
|
||||
{
|
||||
return $this->formatItemInfo($item_info);
|
||||
}
|
||||
|
||||
|
||||
protected function formatItemInfo(?array $item_info): ?array
|
||||
{
|
||||
if(!$item_info) return null;
|
||||
|
||||
$info = $item_info;
|
||||
|
||||
$info['image'] = static::getResizedImageCollection($info['thumbnail']);
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
||||
public static function getResizedImageCollection($image_name) {
|
||||
|
||||
$image = [];
|
||||
|
||||
$size_in_full = [
|
||||
't' => 'thumb' ,
|
||||
's' => 'small' ,
|
||||
'l' => 'large' ,
|
||||
];
|
||||
|
||||
foreach (static::$resized_sizes as $size => $value) {
|
||||
$image[$size_in_full[$size]] = ($image_name) ? STATIC_DOMAIN . "/". static::$image_folder . "/". $size. IMAGE_FILE_SEPARATOR . $image_name : '';
|
||||
}
|
||||
|
||||
$image['original'] = ($image_name) ? STATIC_DOMAIN . "/". static::$image_folder . "/". $image_name : '';
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Model;
|
||||
|
||||
use Hura8\System\Model\EntityLanguageModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
|
||||
|
||||
class ProductAttributeLanguageModel extends EntityLanguageModel
|
||||
{
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::PRODUCT_ATTRIBUTE);
|
||||
}
|
||||
|
||||
}
|
||||
175
inc/Hura8/Components/Product/Model/ProductAttributeModel.php
Normal file
175
inc/Hura8/Components/Product/Model/ProductAttributeModel.php
Normal file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\System\Language;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\Interfaces\iEntityModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
use Hura8\System\Security\DataClean;
|
||||
use Hura8\System\Security\DataType;
|
||||
|
||||
class ProductAttributeModel extends aEntityBaseModel {
|
||||
|
||||
protected $tb_product_category = "tb_product_category";
|
||||
protected $tb_attribute_value = "tb_attribute_value";
|
||||
|
||||
protected $tb_product_spec_group = "tb_product_spec_group";
|
||||
protected $tb_attribute_per_spec_group = "tb_attribute_per_spec_group";
|
||||
protected $tb_attribute_per_category = "tb_attribute_per_category";
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::PRODUCT_ATTRIBUTE);
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
// SPEC-GROUP
|
||||
|
||||
public function getSpecGroupAttributeWithValues($group_id) {
|
||||
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT
|
||||
a.title,
|
||||
a.summary,
|
||||
a.is_filter,
|
||||
a.value_match_all,
|
||||
a.filter_code,
|
||||
a.is_display,
|
||||
a.is_header,
|
||||
a.is_multi, a.in_summary,
|
||||
a.value_count,
|
||||
g.attr_id,
|
||||
g.ordering,
|
||||
g.status
|
||||
FROM ".$this->tb_attribute_per_spec_group." g, ".$this->tb_entity." a
|
||||
WHERE g.`group_id`= ? AND g.`attr_id`= a.`id`
|
||||
ORDER BY g.`ordering` DESC, a.`ordering` DESC ",
|
||||
['d'],
|
||||
[$group_id]
|
||||
) ;
|
||||
|
||||
$attribute_ids = [];
|
||||
$value_per_attribute_ids = [];
|
||||
$result = [];
|
||||
foreach ($this->db->fetchAll($query) as $item) {
|
||||
$attribute_ids[] = $item['attr_id'];
|
||||
$value_per_attribute_ids[$item['attr_id']] = [];
|
||||
|
||||
$result[$item['attr_id']] = [
|
||||
"attribute_info" => $item,
|
||||
"attribute_values" => &$value_per_attribute_ids[$item['attr_id']],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
if(!sizeof($attribute_ids)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// now get all values for each attribute
|
||||
list($parameterized_ids, $bind_types) = create_bind_sql_parameter_from_value_list($attribute_ids, "int");
|
||||
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT * FROM ".$this->tb_attribute_value."
|
||||
WHERE `attribute_id` IN (".$parameterized_ids.")
|
||||
ORDER BY `ordering` DESC, `title` ASC ",
|
||||
$bind_types,
|
||||
$attribute_ids
|
||||
) ;
|
||||
|
||||
foreach ($this->db->fetchAll($query) as $item) {
|
||||
$value_per_attribute_ids[$item['attribute_id']][] = $item;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function getSpecGroupAttribute($group_id) {
|
||||
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT
|
||||
a.title,
|
||||
a.summary,
|
||||
a.is_filter,
|
||||
a.value_match_all,
|
||||
a.filter_code,
|
||||
a.is_display,
|
||||
a.is_header, a.is_multi, a.value_count,
|
||||
g.attr_id,
|
||||
g.ordering,
|
||||
g.status
|
||||
FROM ".$this->tb_attribute_per_spec_group." g, ".$this->tb_entity." a
|
||||
WHERE g.`group_id`= ? AND g.`attr_id`= a.`id`
|
||||
ORDER BY g.`ordering` DESC, a.`ordering` DESC ",
|
||||
['d'],
|
||||
[$group_id]
|
||||
) ;
|
||||
|
||||
return $this->db->fetchAll($query);
|
||||
}
|
||||
|
||||
|
||||
public function getProductMatchAllAttributeValueIds(array $_att_value_list) {
|
||||
/*$query = $this->db->runQuery("
|
||||
SELECT `pro_id` , COUNT(*) AS num_pro
|
||||
FROM ".TB_PRODUCT_ATTRIBUTE."
|
||||
WHERE " . join(" OR ", array_map(function ($_item){ return " `attr_value_id` = '".intval($_item['id'])."' "; }, $_att_value_list )) ."
|
||||
GROUP BY pro_id
|
||||
HAVING num_pro = ".sizeof($_att_value_list)."
|
||||
LIMIT 10000
|
||||
");
|
||||
|
||||
return array_map(function ($item){
|
||||
return $item["pro_id"];
|
||||
}, $this->db->fetchAll($query));*/
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getProductMatchAttributeValue(array $value_ids) {
|
||||
$product_filter_id_match = array();
|
||||
// todo:
|
||||
/*if(sizeof($query_attr_id)) {
|
||||
$query = $this->db->runQuery("
|
||||
SELECT DISTINCT pro_id , COUNT(*) as num_pro
|
||||
FROM ".TB_PRODUCT_ATTRIBUTE."
|
||||
WHERE attr_value_id IN (".join(',', $query_attr_id).")
|
||||
GROUP BY pro_id
|
||||
HAVING num_pro = ".$count_filter."
|
||||
LIMIT 10000
|
||||
");
|
||||
foreach ( $this->db->fetchAll($query) as $rs ) {
|
||||
$product_filter_id_match[] = $rs["pro_id"];
|
||||
}
|
||||
}*/
|
||||
|
||||
return $product_filter_id_match;
|
||||
}
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
/*$condition = array(
|
||||
"q" => "",
|
||||
"letter" => "",
|
||||
"status" => 0,
|
||||
);*/
|
||||
|
||||
$catCondition = [];
|
||||
$bind_types = [];
|
||||
$bind_values = [];
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Model;
|
||||
|
||||
use Hura8\Interfaces\AppResponse;
|
||||
use Hura8\System\Model\aEntityBaseModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
use Hura8\System\Security\DataClean;
|
||||
use Hura8\System\Security\DataType;
|
||||
|
||||
|
||||
class ProductAttributeValueModel extends aEntityBaseModel
|
||||
{
|
||||
|
||||
const MAX_VALUE_PER_ATTRIBUTE = 100; // one attribute should not have more that this number of values
|
||||
|
||||
protected $attribute_id = 0;
|
||||
|
||||
protected $tb_attribute = 'tb_attribute';
|
||||
protected $tb_product_attribute = 'tb_product_attribute';
|
||||
|
||||
public function __construct($attribute_id) {
|
||||
parent::__construct(EntityType::PRODUCT_ATTRIBUTE_VALUE);
|
||||
$this->attribute_id = $attribute_id;
|
||||
}
|
||||
|
||||
|
||||
protected function extendedFilterOptions() : array
|
||||
{
|
||||
return [
|
||||
// empty for now
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getProductAttributes($product_id) {
|
||||
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT `attr_id`, `attr_value_id` FROM `".$this->tb_product_attribute."` WHERE `pro_id` = ? ",
|
||||
['d'], [ $product_id]
|
||||
);
|
||||
|
||||
return $this->db->fetchAll($query);
|
||||
}
|
||||
|
||||
|
||||
protected function getAttributeValueCount() {
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT `value_count` FROM `".$this->tb_attribute."` WHERE `id` = ? LIMIT 1 ",
|
||||
['d'], [$this->attribute_id]
|
||||
);
|
||||
|
||||
if($info = $this->db->fetchAssoc($query)) {
|
||||
return $info['value_count'];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function _buildQueryConditionExtend(array $filter_condition) : ?array
|
||||
{
|
||||
|
||||
$catCondition = [" AND `attribute_id` = ? "];
|
||||
$bind_types = ["d"];
|
||||
$bind_values = [$this->attribute_id];
|
||||
|
||||
|
||||
return array( join(" ", $catCondition), $bind_types, $bind_values);
|
||||
}
|
||||
|
||||
|
||||
public function getInfoByCode($filter_code)
|
||||
{
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT * FROM `".$this->tb_entity."` WHERE `attribute_id` = ? AND `filter_code` = ? LIMIT 1",
|
||||
['d', 's'], [$this->attribute_id, $filter_code ]
|
||||
);
|
||||
|
||||
return $this->db->fetchAssoc($query);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Model;
|
||||
|
||||
use Hura8\Database\iConnectDB;
|
||||
|
||||
class ProductCategoryInfoModel
|
||||
{
|
||||
/* @var $db iConnectDB */
|
||||
protected $db;
|
||||
|
||||
protected $tb_category_info = "tb_product_category_info";
|
||||
|
||||
public function __construct() {
|
||||
$this->db = get_db();
|
||||
}
|
||||
|
||||
public function getInfo($id) {
|
||||
return $this->db->select(
|
||||
$this->tb_category_info,
|
||||
[],
|
||||
[
|
||||
'id' => ['=', $id],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Model;
|
||||
|
||||
|
||||
use Hura8\System\Model\EntityLanguageModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
|
||||
|
||||
class ProductCategoryLanguageModel extends EntityLanguageModel
|
||||
{
|
||||
|
||||
protected $richtext_fields = [
|
||||
'description',
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::PRODUCT_CATEGORY, '', $this->richtext_fields);
|
||||
}
|
||||
|
||||
}
|
||||
83
inc/Hura8/Components/Product/Model/ProductCategoryModel.php
Normal file
83
inc/Hura8/Components/Product/Model/ProductCategoryModel.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Hura8\Components\Product\Model;
|
||||
|
||||
|
||||
use Hura8\Interfaces\iEntityCategoryModel;
|
||||
use Hura8\System\Model\aCategoryBaseModel;
|
||||
use Hura8\Interfaces\EntityType;
|
||||
|
||||
|
||||
class ProductCategoryModel extends aCategoryBaseModel implements iEntityCategoryModel
|
||||
{
|
||||
static $url_module = "product";
|
||||
static $url_view = "category";
|
||||
static $url_type = "product:category";
|
||||
|
||||
protected $tb_category_info = "tb_product_category_info";
|
||||
protected $tb_product_per_category = "tb_product_per_category";
|
||||
protected $tb_attribute_per_category = "tb_attribute_per_category";
|
||||
protected $tb_attribute_value = "tb_attribute_value";
|
||||
protected $tb_attribute = "tb_attribute";
|
||||
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(EntityType::PRODUCT_CATEGORY);
|
||||
}
|
||||
|
||||
|
||||
public function getAttributeList($catId) {
|
||||
$query = $this->db->runQuery("SELECT
|
||||
a.id ,
|
||||
a.filter_code ,
|
||||
a.title ,
|
||||
a.value_count ,
|
||||
a.is_filter ,
|
||||
c.ordering ,
|
||||
c.status ,
|
||||
a.is_header
|
||||
FROM ".$this->tb_attribute." a
|
||||
LEFT JOIN ".$this->tb_attribute_per_category." c ON a.id = c.attr_id
|
||||
WHERE c.category_id = ?
|
||||
ORDER BY c.ordering desc
|
||||
", ['d'], [ $catId ]) ; // AND isSearch = 1
|
||||
|
||||
return $this->db->fetchAll($query);
|
||||
}
|
||||
|
||||
|
||||
public function getFullInfo($id) : ?array {
|
||||
$query = $this->db->runQuery(
|
||||
"SELECT * FROM `".$this->tb_entity."` basic, `".$this->tb_category_info."` info
|
||||
WHERE basic.`id` = info.`id` AND basic.id = ?
|
||||
LIMIT 1 ",
|
||||
['d'], [$id]
|
||||
);
|
||||
|
||||
if( $item_info = $this->db->fetchAssoc($query)){
|
||||
$item_info['settings'] = ($item_info['settings']) ? \json_decode($item_info['settings'], true) : [];
|
||||
return $item_info;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function getEmptyInfo($addition_field_value = []) : array
|
||||
{
|
||||
// basic table
|
||||
$basic_empty = parent::getEmptyInfo($addition_field_value);
|
||||
|
||||
// info table
|
||||
foreach ($this->db->getTableInfo($this->tb_category_info) as $field => $field_info) {
|
||||
$basic_empty[$field] = ( in_array($field_info['DATA_TYPE'], ['int', 'float']) ) ? 0 : '' ;
|
||||
}
|
||||
|
||||
if(sizeof($addition_field_value)) {
|
||||
return array_merge($basic_empty, $addition_field_value);
|
||||
}
|
||||
|
||||
return $basic_empty;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user