This commit is contained in:
2025-05-27 14:28:47 +07:00
parent 170122ad32
commit 4fb79660b2
144 changed files with 5973 additions and 0 deletions

211
src/Hura/App.php Normal file
View File

@@ -0,0 +1,211 @@
<?php
namespace Hura;
use Liquid\Liquid;
use Liquid\Template as LiquidTemplate;
class App
{
protected $tpl_path = ROOT_DIR . "/template";
protected $current_route_info = [
"module" => 'home',
"view" => 'home',
"url" => '/admin/product'
];
protected $data = [];
public function __construct()
{
}
// start the app
public function start() {
$this->getRouter();
$this->getData();
echo $this->renderModule();
}
protected function getRouter() {
/*$route = [
"module" => (isset($_REQUEST['module'])) ? $_REQUEST['module'] : 'home',
"view" => (isset($_REQUEST['view'])) ? $_REQUEST['view'] : 'home',
];*/
$objRouter = new Router();
$this->current_route_info = $objRouter->getRouting();
}
protected function getData() {
$module_file = $this->getModuleFile();
if(!file_exists($module_file)) {
// print_r($this->current_route_info);
die('Page '. $module_file .' not found!');
}
$data = include_once $module_file;
$global_data = [
"module" => $this->current_route_info['module'],
"view" => $this->current_route_info['view'],
"url" => $this->current_route_info['url'],
];
$this->data = array(
'global' => $global_data,
// module-specific data, just print {{ page }} to see all available data for the current page!!!
'page' => (is_array($data)) ? $data : [],
);
}
protected function getModuleFile(): string
{
return SRC_DIR . DIRECTORY_SEPARATOR . join(DIRECTORY_SEPARATOR, [
"pages",
$this->current_route_info["module"],
str_replace("-", "_", $this->current_route_info["view"]).".php"
]) ;
}
protected function renderModule() {
if(!$this->current_route_info['module'] || !$this->current_route_info['view']) {
die("Module not exist");
}
$template_file_path = $this->tpl_path ."/". $this->current_route_info['module'];
$template_file_name = str_replace("-", '_', $this->current_route_info['view']).".html";
$template_file_full_path = $template_file_path."/".$template_file_name;
//check exist
if(!@file_exists( $template_file_full_path)) {
// attempt to auto create first
// todo: this MUST BE TURNED OFF IN PRODUCTION, else many files will be created unintentionally
$module_file = $this->getModuleFile();
// only create if module file exist
if(file_exists($module_file) && !$this->autoCreateTplFile( $template_file_path, $template_file_name )) {
die("Please manually create template file at: ". $template_file_full_path);
}
}
$theme_file_path = $this->tpl_path ."/theme.html";
if( ! @file_exists( $theme_file_path)) {
die("Theme not exist (please create): " . $theme_file_path);
}
$theme_content = @file_get_contents( $theme_file_path );
$module_content = @file_get_contents( $template_file_full_path );
$page_content_to_parse = preg_replace([
"/{{(\s+)?page_content(\s+)?}}/"
], [
$module_content,
] , $theme_content );
return $this->parse(
$page_content_to_parse,
$template_file_path
);
}
protected function autoCreateTplFile($file_path, $file_name) : bool {
// create dir if not exist
if(!file_exists($file_path)) {
if(!mkdir($file_path, 0755, true)) {
return false;
}
if(!file_exists($file_path)) {
return false;
}
}
//create file
$file_full_path = $file_path . "/". $file_name;
@file_put_contents($file_full_path, $file_full_path);
return file_exists($file_full_path);
}
/*
* 2 ways to render a html template
* 1. Use $html_to_parse, which requires no dependencies
* Example:
* Template::parse(null, 'Age = {{age}}', ['age' => 21], '');
*
* 2. Use $template_file_path, which requires dependency $path
* Template::parse(Template::$setting_template_path, null, ['age' => 21], 'email/test');
* */
protected function parse($html_to_parse = null, $template_file_path = '') {
if(!$html_to_parse && !$template_file_path) {
return 'Nothing to parse';
}
//output to html
Liquid::set('INCLUDE_SUFFIX', 'html');
Liquid::set('INCLUDE_PREFIX', '');
//Liquid::set('INCLUDE_ALLOW_EXT', true);
Liquid::set('ESCAPE_BY_DEFAULT', false);
$enable_cache = false; // default = true, turn this on-off to disable cache while working on local mode
//$enable_cache = true;
//catch exception and print friendly notice
try {
$objLiquidTemplate = new LiquidTemplate( $this->tpl_path );
$objLiquidTemplate->registerFilter( TemplateFilter::class );
if($enable_cache) {
/*$objLiquidTemplate->setCache(new File([
'cache_dir' => self::$cache_dir
]));*/
}
if($html_to_parse) {
$objLiquidTemplate->parse($html_to_parse);
}elseif ($template_file_path) {
$objLiquidTemplate->parseFile($template_file_path);
}
return $objLiquidTemplate->render($this->data);
} catch (\Exception $e) {
$result = [];
do {
//printf("%s:%d %s (%d) [%s]\n", $e->getFile(), $e->getLine(), $e->getMessage(), $e->getCode(), get_class($e));
//echo $e->getTraceAsString();
//$code = $e->getTrace()[0]['args'][0];
//if(is_array($code)) $code = serialize($code);
$result[] = sprintf(
"
Lỗi code trong file template html: <br />
- Chi tiết lỗi: %s<br />
- File template: %s<br />
- Hướng dẫn xử lý: Tách từng phần html để kiểm tra và nhấn F5 mỗi lần. Nếu không xuất hiện thông báo này nghĩa là phần đó không tạo lỗi
",
$e->getMessage(),
substr($template_file_path, strrpos($template_file_path, DIRECTORY_SEPARATOR) + 1 ),
//static::$cache_dir
);
} while($e = $e->getPrevious());
return join(" - ", $result);
}
}
}

78
src/Hura/Router.php Normal file
View File

@@ -0,0 +1,78 @@
<?php
namespace Hura;
class Router {
private array $path_config = [];
public function __construct() {
$path_config_file = CONFIG_DIR . '/routing.php';
$this->path_config = require $path_config_file;
}
// url: asdas.php?para1=value1
public function getRouting(): array
{
$parsed = Url::parse($_SERVER['REQUEST_URI']); //abc/product?param1=12&param2=value2
//print_r($parsed);
// home
if($parsed['path'] == '/') {
return [
'module' => preg_replace("/[^a-z0-9_\-]/i","", getRequest('module', 'home')),
'view' => preg_replace("/[^a-z0-9_\-]/i","", getRequest('view', 'home')),
'view_id'=> 0,
'query' => $parsed['query'],
'url' => $_SERVER['REQUEST_URI'],
];
}
// check match pattern in $this->path_config
foreach ($this->path_config as $_config => $_route ) {
if(preg_match("{^".$_config."$}", $parsed['path'], $match )) {
if(isset($_route['query']) && is_array($_route['query'])) {
$_route['query'] = array_merge($_route['query'], $parsed['query']);
}else{
$_route['query'] = $parsed['query'];
}
return array_merge([
'path' => $parsed['path'],
'match' => $match,
], $_route);
}
}
// check database
// else error
return [
'module' => "error" ,
'view' => "error" ,
'view_id' => "not_found",
'query' => $parsed['query'],
'url' => $_SERVER['REQUEST_URI'],
];
// auto parse path base on convention: admin/module/view/view_id
/* $ele = explode("/", $parsed['path']);
$module = $ele[2] ?? 'home';
$view = isset($ele[3]) ? $ele[3] : getRequest('view', 'home');
$view_id = isset($ele[4]) ? $ele[4] : getRequest('id', 'view_id');
// else error
return [
'module' => preg_replace("/[^a-z0-9_\-]/i","", $module ) ,
'view' => preg_replace("/[^a-z0-9_\-]/i","", $view ) ,
'view_id' => preg_replace("/[^a-z0-9_]/i","", $view_id ),
'query' => $parsed['query'],
'url' => $_SERVER['REQUEST_URI'],
];*/
}
}

256
src/Hura/TemplateFilter.php Normal file
View File

@@ -0,0 +1,256 @@
<?php
namespace Hura;
/**
* Before attempting to make new filter, see built-in filters: https://shopify.github.io/liquid/
*/
class TemplateFilter
{
/**
*
* @param array $array
*
* @return string
*/
public static function to_json(array $array) {
return \json_encode($array);
}
/**
* create array of ['key' => '', 'value' => ] from [key1 => value1, key2=>value2, ...]
*
* @param array $key_values [key1 => value1, key2=>value2]
*
* @return array [['key' => 'key1', 'value' => value1], ['key' => 'key2', 'value' => value2]]
*/
public static function to_array(array $key_values) {
$result = [];
foreach ($key_values as $key => $value) {
$result[] = [
'key' => $key,
'value' => $value,
];
}
return $result;
}
/**
* split a s by line to create array
*
* @param string $txt
*
* @return array
*/
public static function get_line($txt) {
if(is_array($txt)) {
return $txt;
}
$txt = trim($txt);
if( ! $txt ) return [];
return preg_split("/\n/", $txt);
}
/**
* Implement strlen
*
* @param string $str
*
* @return int
*/
public static function length($str) {
return strlen(trim($str));
}
/**
* Make number easier to read: 1000 -> 1.000
*
* @param string $number
*
* @return string
*/
public static function format_number($number) {
if(!$number) return '';
$number = floatval($number);
$number = number_format($number, 0, ",", "."); //Vietnamese format with decimals by a coma
return $number;
}
public static function format_price($p_price, $currency = ''){
if(!$p_price) return '';
if(!$currency) $currency = (defined("DEFAULT_CURRENCY")) ? DEFAULT_CURRENCY : "vnd";
//if(is_string($p_price)) return 0;
if($currency == 'usd') {
return number_format($p_price,2,".",",");
}else {
return number_format($p_price,0,",",".");
}
}
/**
*
* Description: get the shop's full asset url for template's images/js/css
*
* //Returns the URL of a file in the "assets" folder of a theme.
// {{ 'shop.css' | asset_url : 'arg1', 'arg2' ...}} -> //cdn.shopify.com/s/files/1/0087/0462/t/394/assets/shop.css?28253
*
* @param string $file_name
*
* @return string
*/
public static function asset_url($file_name = '')
{
if( !$file_name ) return '';
$file_ext = strtolower(strrchr($file_name, "."));
// script tags
if(in_array($file_ext, ['.js', '.css'])) return TEMPLATE_ASSET . "/script/" . $file_name;
// default image
return TEMPLATE_ASSET . "/images/" . $file_name;
}
/**
*
* Description: construct a full html tag for images/js/css file
*
* @param string $file_path domain.com/static/style.css?v=3.1.1
*
* @return string
*/
public static function script_tag($file_path) {
if( ! $file_path ) return '';
//check for ?
if(strpos($file_path, "?") !== false) {
$file_ext = str_replace(strrchr($file_path, "?"), "", $file_path);
$file_ext = strtolower(strrchr($file_ext, "."));
} else {
$file_ext = strtolower(strrchr($file_path, "."));
}
$tag_config = [
".css" => "<link rel=\"stylesheet\" href=\"".$file_path."\" type=\"text/css\" />",
".js" => "<script src=\"".$file_path."\"></script>",
".jpg" => "<img src=\"".$file_path."\" alt=\"n\"/>",
".jpeg" => "<img src=\"".$file_path."\" alt=\"\"/>",
".gif" => "<img src=\"".$file_path."\" alt=\"\"/>",
".png" => "<img src=\"".$file_path."\" alt=\"\"/>",
];
return (isset($tag_config[$file_ext])) ? $tag_config[$file_ext] : '';
}
/**
* {{ product_info.main_image | img_url: '300x300' }} => https://cdn.shopify.com/s/files/1/1183/1048/products/boat-shoes_300x300.jpeg?1459175177
* @param string $full_path
* @param string $modifier
* $modifier:
* - must be in format: NumberxNumber or Numberx where Number must within 10 -> 9999
* - or be one of these: small | medium | large
* @return string
*/
public static function img_url($full_path, $modifier)
{
$clean_modifier = ($modifier) ? trim($modifier) : "";
// verify $modifier
// must be in format: NumberxNumber or Numberx where Number must within 10 -> 9999
if($clean_modifier
&& !preg_match("/^[0-9]{2,4}x([0-9]{2,4})?$/i", $clean_modifier)
&& !in_array($clean_modifier, ["small", "medium", "large"])
) {
$clean_modifier = "";
}
// return if no valid modifier
if( ! $clean_modifier ) {
return $full_path;
}
$last_dot_position = strrpos($full_path, ".");
if( ! $last_dot_position ) return $full_path . $clean_modifier;
return join("", [
substr($full_path, 0, $last_dot_position),
"_",
$clean_modifier,
substr($full_path, $last_dot_position)
]);
}
/**
* //Returns the URL of a file in the Files page of the admin.
//{{ 'size-chart.pdf' | file_url }} -> //cdn.shopify.com/s/files/1/0087/0462/files/size-chart.pdf?28261
*
* @param string $input
* @param string $string
*
* @return string
*/
public static function file_url($input, $string)
{
return strtoupper($input) . " = " . $string;
}
/**
* //Returns the asset URL of an image in the Files page of the admin. file_img_url accepts an image size parameter.
//{{ 'logo.png' | file_img_url: '1024x768' }} -> //cdn.shopify.com/s/files/1/0246/0527/files/logo_1024x768.png?42
*
* @param string $input
* @param string $string
*
* @return string
*/
public static function file_img_url($input, $string)
{
return '';
}
/**
* Show all content of a variable, useful for template development
*
* @param string
*
* @return string
*/
public static function print_r($input)
{
@ob_start();
print_r($input);
$content = ob_get_contents();
@ob_end_clean();
return join("\r", ['<!-- print_r debug content: ', $content, '-->']) ;
}
/**
* Show all content of a variable, useful for template development
*
* @param string
*
* @return string
*/
public static function show_var($input)
{
@ob_start();
print_r($input);
$content = ob_get_contents();
@ob_end_clean();
return join("\r", ['<textarea cols="80" rows="20">', $content, '</textarea>']) ;
}
}

47
src/Hura/Url.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
namespace Hura;
class Url
{
public static function parse($url) {
$data = parse_url($url);
$default = [
'scheme' => '',
'host' => '',
'port' => '',
'user' => '',
'pass' => '',
'path' => '',
'query' => [],
'fragment' => '',
];
foreach ($data as $key => $value) {
if(isset($default[$key])) {
$default[$key] = ($key == 'query') ? self::parsedQuery($value) : $value;
}
}
return $default;
}
public static function parsedQuery($query = '') {
if(!$query) return [];
$result = [];
$parts = explode("&", $query);
foreach ($parts as $part) {
$el = explode("=", $part);
if(sizeof($el) != 2) continue;
$cleaned_key = preg_replace("/[^a-z0-9_\-\.]/i", '', $el[0]);
$cleaned_value = preg_replace("/[^a-z0-9_\.\-;&]/i", '', $el[1]);
$result[$cleaned_key] = $cleaned_value;
}
return $result;
}
}

45
src/inc/common.php Normal file
View File

@@ -0,0 +1,45 @@
<?php
function debug_var($input) {
@ob_start();
print_r($input);
$content = ob_get_contents();
@ob_end_clean();
echo join("\r", ['<textarea cols="80" rows="20">', $content, '</textarea>']) ;
}
function init_autoload(){
$classLoader = require_once ROOT_DIR . '/package/vendor/autoload.php';
$classLoader->add("Hura", ROOT_DIR . '/src' );
return $classLoader;
}
//get current paging id
function getPageId(){
return getRequestInt('page', 1);
}
function getPageSize($default=10){
return getRequestInt('pageSize', $default);
}
//Function to get the post value in submit
function getPost($var, $default="", $encode = false, $keep_tag=""){
return isset($_POST[$var]) ? $_POST[$var] : $default;
}
//Function to get the INTERGER request value of a variable
function getRequestInt($var, $min_value = 0){
$request = isset($_REQUEST[$var]) ? (int) $_REQUEST[$var] : (int) $min_value;
$request = ($request >= $min_value ) ? $request : $min_value; //if user tampers request parameter
return $request;
}
//Function to get the request value of a variable
function getRequest($var, $default=""){
return $_REQUEST[$var] ?? $default;
}

16
src/inc/fun.db.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
use Hura\Database\ConnectDB;
use Hura\Database\iConnectDB;
function create_bind_sql_parameter_from_value_list(array $value_list = [], $data_type = 'int') {
$parameterized_ids = join(",", array_map(function (){ return '?'; }, $value_list));
$bind_types = array_map(function () use ($data_type){ return ($data_type == 'int') ? 'd' : 's'; }, $value_list);
return [$parameterized_ids, $bind_types];
}
function get_db($db_id ='', $debug=false) : iConnectDB {
return ConnectDB::getInstance($db_id, $debug);
}

View File

@@ -0,0 +1,5 @@
<?php
return [
];

13
src/pages/home/home.php Normal file
View File

@@ -0,0 +1,13 @@
<?php
return [
"tom_tat" => [
[
'id' => 1,
'title' => 'ĐƠN HÀNG MỚI',
'main_stat' => '1000000',
'time' => ' 24/11/2023 ',
],
],
];

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1,108 @@
<?php
use Hura\Components\Product\AdminController\AProductCategoryController;
$objAProductCategoryController = new AProductCategoryController();
$category_collection = $objAProductCategoryController->getAllParent();
return [
'category_list' => get_category_list(0, getRequest("id"), $level=1, $prefix="", $category_collection )
];
function get_category_list($parentId=0, $currentCat="",$level=1, $prefix="", $category_collection = array()){
$categoryTree = "";
$extra_space = "";
for($i = 1; $i < $level; $i++){
$extra_space .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
}
$stt = 0;
if(isset($category_collection[$parentId])) {
foreach($category_collection[$parentId] as $index => $cat_info){
$cat_id = $cat_info['id'];
$stt ++;
$imgUrl = (strlen($cat_info["thumbnail"]) > 2) ? " <img src=\"".$cat_info["thumbnail"]."\" style=\"max-width:30px; max-height:30px;\" />" : "";
if($cat_info["status"]) $status = "<a href=\"javascript:update_status(".$cat_id.",'off')\" class='w-[30px] h-[30px] border-[1px] border-[#9E9E9E] rounded-[4px] text-center leading-[30px] flex items-center justify-center mr-[5px]'><i class='fa-regular fa-eye-slash text-[#9E9E9E]'></i></a>";
else $status = "<a href=\"javascript:update_status(".$cat_id.",'on')\" class='w-[30px] h-[30px] border-[1px] border-[#0041E8] rounded-[4px] text-center leading-[30px] flex items-center justify-center mr-[5px]'><i class='fa-regular fa-eye text-[#0041E8]'></i></a>";
$edit_link ="/admin/product/category-form?id=".$cat_id;
$hide_this = ($parentId > 0) ? "style='display: none;'" : '';
$show_category_name = $cat_info["title"];
if(!IS_DEFAULT_LANGUAGE && isset($cat_info["not_translated"]) && $cat_info["not_translated"]) {
$show_category_name = "<span style='color: red'>[Chưa dịch]</span> ".$cat_info["title"];
}
if($cat_info['is_parent']) {
$show_category_name = "<a href=\"javascript:;\" onclick=\"RowExpand.open_child('parent_".$cat_id."')\">".$show_category_name."</a>";
}
$categoryTree .= "
<tr id='row_".$cat_id."' class='parent_".$parentId." row' ". $hide_this ."
onmouseover=\"this.className='row-hover parent_".$parentId."'\" onmouseout=\"this.className='parent_".$parentId."'\">
<td>
<a name='cat_".$cat_id."'></a>
". $extra_space . $prefix . $stt.". ". $show_category_name . $imgUrl."
</td>
<td>
<a href='".$cat_info['request_path']."' title='Mở tại website' target='_blank'>Xem trang</a>
</td>
<td>".$cat_id."</td>
<td class='whitespace-nowrap'>413787</td>
<td><a href='/admin/product?category=".$cat_id."'>1292</a></td>
<td>
<input type=text id=order_".$cat_id." value='".$cat_info["ordering"]."' size=2 onchange=\"update_order(".$cat_id.",this.value)\" />
<span class='status-ordering-".$cat_id."'></span>
</td>
<td class='whitespace-nowrap'>
SP + Danh mục con
</td>
";
if(IS_DEFAULT_LANGUAGE) {
$categoryTree .= "
<td>
<a href='/admin/product/category-attribute?id=".$cat_id."&popup=1' class='pop-up'>Tổng</a> (".$cat_info['attribute_count'].")
</td>
<td>
<div class='list-btn flex items-center'>
<a href=\"".$edit_link."\" class='w-[32px] h-[32px] border-[1px] border-[#0041E8] rounded-[4px] text-center leading-[30px] flex items-center justify-center mr-[5px]'><i class='icons icon-edit'></i></a>
<a class='w-[32px] h-[32px] border-[1px] border-[#0041E8] rounded-[4px] text-center leading-[30px] flex items-center justify-center mr-[5px]' href='javascript:set_category_feature(.$cat_id.,'off')'><i class='icons icon-feature'></i></a>
<span id=status-".$cat_id.">".$status."</span>
<span class='status-delete-".$cat_id."'><a href=\"javascript:deleteThis(".$cat_id.")\" class='w-[32px] h-[32px] border-[1px] border-[#9E9E9E] rounded-[4px] text-center leading-[30px] flex items-center justify-center mr-[5px]'><i class='icons icon-delete'></i></a></span>
</div>
</td>
";
}else{
$categoryTree .= "
<td>
<a href=\"".$edit_link."\"><i class='icons icon-edit'></i></a>
</td>
";
}
$categoryTree .= "
</tr>
";
if($cat_info["is_parent"]) $categoryTree .= get_category_list($cat_id, $currentCat, $level + 1, $prefix . $stt.".", $category_collection);
}
}
return $categoryTree;
}

View File

@@ -0,0 +1,18 @@
<?php
use Hura\Components\Product\AdminController\AProductCategoryController;
$objAProductCategoryController = new AProductCategoryController();
$id = (int) getRequest("id");
$item_info = ($id > 0) ? $objAProductCategoryController->getFullInfo($id) : null;
if(!$item_info) $item_info = $objAProductCategoryController->getEmptyInfo([]);
return [
'item_info' => $item_info,
'categoryDropBox' => $objAProductCategoryController->getDropBox( $item_info['parent_id'], 0, 1),
'update_status' => getRequest("us"),
];

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

174
src/pages/product/form.php Normal file
View File

@@ -0,0 +1,174 @@
<?php
use Hura\Components\Product\AdminController\AProductController;
$objAProductController = new AProductController();
$product_id = getRequestInt('id', 0);
$product_info = $objAProductController->getFullInfo($product_id);
$view_part = getRequest("part", "basic");
$view_part_file = str_replace("-", "_", $view_part);
$part_file = __DIR__."/form_components/". $view_part_file .".php";
if(@file_exists($part_file)) {
include $part_file;
}else{
die("File: /form_components/". $view_part_file .".php does not exist!");
}
return [
"product_info" => $product_info,
"product_menu" => _get_product_menu(),
"view_part" => $view_part,
];
// helpers
function _get_product_menu() {
$current_selected = getRequest('part', 'basic');
$product_menu = array(
array(
'id' => 'basic',
"name" => "Cơ bản",
),
array(
'id' => 'store',
"name" => "Cửa hàng",
),
array(
'id' => 'category',
"name" => "Danh mục",
),
array(
'id' => 'seo',
"name" => "SEO",
),
array(
'id' => 'description',
"name" => "Mô tả",
),
array(
'id' => 'spec-group',
"name" => "Thông số kỹ thuật",//"Thông số",
),
/*"spec" => array(
"name" => "Thông số kỹ thuật nhập text", //"Bộ lọc thuộc tính", //"Thông số",
"must_have_id" => true,
"change_language" => true,
),*/
/*"image-spec" => array(
"name" => "Ảnh thông số",
"must_have_id" => true,
"change_language" => true,
),*/
array(
'id' => 'instruction',
"name" => "Hướng dẫn sử dụng",
),
array(
'id' => 'image',
"name" => "Ảnh",
),
array(
'id' => 'variant',
"name" => "Cấu hình",
),
array(
'id' => 'accessory',
"name" => "Phụ kiện",
),
array(
'id' => 'addon',
"name" => "Dịch vụ/SP đi kèm",
),
array(
'id' => 'video',
"name" => "Youtube",
),
/* "video-list" => array(
"name" => "Thư viện Youtube",
"must_have_id" => true,
"change_language" => false,
),*/
/*"relate-article" => array(
"name" => "Nội dung liên quan",
"must_have_id" => true,
"change_language" => false,
),*/
/*"web-link" => array(
"name" => "So sánh giá",
"must_have_id" => true,
"change_language" => false,
),*/
array(
'id' => 'tag',
"name" => "Tags",
),
array(
'id' => 'relation',
"name" => "Nội dung liên quan",
),
array(
'id' => 'customer-group',
"name" => "Giá theo nhóm khách hàng",
),
array(
'id' => 'component',
"name" => "Thành phần",
),
array(
'id' => 'configurable',
"name" => "Tùy chọn thành phần",
),
array(
'id' => 'compatible',
"name" => "Sp tương thích",
),
array(
'id' => 'similar',
"name" => "Sp tương tự",
),
array(
'id' => 'combo-set',
"name" => "Combo Set",
),
);
return array_map(function ($item) use ($current_selected){
$copy = $item;
$copy['is_current'] = $item['id'] == $current_selected ? 1 : 0;
return $copy;
}, $product_menu);
}

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

228
src/pages/product/home.php Normal file
View File

@@ -0,0 +1,228 @@
<?php
use Hura\Components\Product\AdminController\AProductController;
use Hura\System\Paging;
$objAProductController = new AProductController();
//Paging setting
$numPerPage = getPageSize(15);
$conditions = [
"category" => explode("-", getRequest("category", '')),
"brand" => explode("-", getRequest("brand", '')),
"hotType" => explode("-", getRequest("hotType", '')),
"other_filter" => [getRequest("other_filter", '')],
"q" => getRequest("q", ''),
'numPerPage' => $numPerPage,
'page' => getPageId(),
'translated' => getRequestInt('translated', 0),
//... more extended filters
];
//debug_var($objAProductController->getFilterConditions());
$totalResults = $objAProductController->getTotal($conditions);
$item_list = $objAProductController->getList($conditions);
list($page_collection, $tb_page, $total_pages) = Paging::paging_template($totalResults, $numPerPage);
return [
"total" => $totalResults,
"item_list" => $item_list,
"pagination" => [
'collection' => $page_collection,
'html' => $tb_page,
'total_pages' => $total_pages,
],
"list_category" => [
[
'id' => 1,
'title' => 'Màn hình máy tính',
'url' => '/admin/product?category=9',
'parentId' => 0,
'isParent' => 1,
'children' => [
[
'id' => 10,
'title' => 'Màn hình theo khoảng giá',
'url' => '/admin/product?category=148',
'parentId' => 1,
'isParent' => 0,
'totalProduct' => 0,
'children' => [
]
],
[
'id' => 11,
'title' => 'Màn Hình Theo Kích Thước',
'url' => '/admin/product?category=54',
'parentId' => 1,
'isParent' => 0,
'totalProduct' => 0,
'children' => [
[
'id' => 148,
'title' => '17 inch - 21.5 inch',
'url' => '/admin/product?category=148',
'parentId' => 11,
'isParent' => 0,
'totalProduct' => 5,
],
[
'id' => 66,
'title' => '22 inch - 24 inch',
'url' => '/admin/product?category=66',
'parentId' => 11,
'isParent' => 0,
'totalProduct' => 41,
],
[
'id' => 67,
'title' => '25 inch - 27 inch',
'url' => '/admin/product?category=67',
'parentId' => 11,
'isParent' => 0,
'totalProduct' => 42,
],
[
'id' => 68,
'title' => '28 inch - 32 inch',
'url' => '/admin/product?category=68',
'parentId' => 11,
'isParent' => 0,
'totalProduct' => 11,
]
]
]
]
],
[
'id' => 65,
'title' => 'PC, Workstation',
'url' => '/admin/product?category=65',
'parentId' => 0,
'isParent' => 1,
'children' => []
],
[
'id' => 3,
'title' => 'Gaming Gear',
'url' => '/admin/product?category=3',
'parentId' => 0,
'isParent' => 1,
'children' => []
],[
'id' => 4,
'title' => 'CPU - Bộ Vi Xử Lý',
'url' => '/admin/product?category=4',
'parentId' => 0,
'isParent' => 1,
'children' => []
]
],
"brand_letters" => [
[
'key' => 'A',
'url' => '/ajax/brand.php?action=show-brand-list&letter=A&popup=1',
'total' => 13,
],
[
'key' => 'B',
'url' => '/ajax/brand.php?action=show-brand-list&letter=B&popup=1',
'total' => 2,
],
[
'key' => 'C',
'url' => '/ajax/brand.php?action=show-brand-list&letter=C&popup=1',
'total' => 5,
]
],
"list_brands" => [
'A' => [
[
'id' => 1,
'name' => 'ABS',
'letter' => 'A',
'url' => '/admin/?brand=83&opt=product',
'product' => 1,
],
[
'id' => 2,
'name' => 'ACE GAMING',
'letter' => 'A',
'url' => '/admin/?brand=83&opt=product',
'product' => 6,
],
[
'id' => 3,
'name' => 'ADATA',
'letter' => 'A',
'url' => '/admin/?brand=83&opt=product',
'product' => 15,
]
],
'B' => [
[
'id' => 3,
'name' => 'BE QUIET ',
'letter' => 'B',
'url' => '/admin/?brand=83&opt=product',
'product' => 2,
],
[
'id' => 3,
'name' => 'BENQ',
'letter' => 'B',
'url' => '/admin/?brand=83&opt=product',
'product' => 6,
],
],
'C' => [
[
'id' => 3,
'name' => 'CISCO',
'letter' => 'C',
'url' => '/admin/?brand=83&opt=product',
'product' => 2,
],
[
'id' => 3,
'name' => 'Colorful',
'letter' => 'C',
'url' => '/admin/?brand=83&opt=product',
'product' => 6,
],
[
'id' => 3,
'name' => 'COOLER MASTER',
'letter' => 'C',
'url' => '/admin/?brand=83&opt=product',
'product' => 6,
],
[
'id' => 3,
'name' => 'COOLMOON',
'letter' => 'C',
'url' => '/admin/?brand=83&opt=product',
'product' => 6,
],
[
'id' => 3,
'name' => 'CORSAIR',
'letter' => 'C',
'url' => '/admin/?brand=83&opt=product',
'product' => 6,
],
]
]
];

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1 @@
<?php