This commit is contained in:
2024-01-29 10:39:53 +07:00
parent 545c404fdf
commit 72170f373a
143 changed files with 20188 additions and 3 deletions

View File

@@ -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;
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace Hura8\Components\Product\AdminController;
use Hura8\Components\Product\Controller\bProductCategoryController;
use Hura8\Interfaces\AppResponse;
use Hura8\Components\Product\Model\ProductCategoryInfoModel;
use Hura8\Interfaces\iEntityAdminCategoryController;
use Hura8\Traits\AdminEntityCategoryControllerTraits;
class AProductCategoryController extends bProductCategoryController implements iEntityAdminCategoryController
{
use AdminEntityCategoryControllerTraits;
public function updateItemCount($id) {
$this->objProductCategoryModel->updateItemCount($id);
}
public function getAttributeList($catId) {
return $this->objProductCategoryModel->getAttributeList($catId);
}
public function create(array $info) : AppResponse
{
$res = parent::create($info);
if($res->getStatus() == 'ok') {
$objProductCategoryInfoModel = new ProductCategoryInfoModel();
$objProductCategoryInfoModel->createInfo($res->getData(), $info);
}
return $res;
}
public function update($id, array $info) : AppResponse
{
if(!$this->isDefaultLanguage()) {
return parent::update($id, $info);
}
// update info
$objProductCategoryInfoModel = new ProductCategoryInfoModel();
$objProductCategoryInfoModel->updateInfo($id, $info);
return parent::update($id, $info);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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")),
),
);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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([]);
}
}