d
67
README.md
Normal file
@@ -0,0 +1,67 @@
|
||||
<h1>Hướng dẫn</h1>
|
||||
|
||||
<p>Link thiết kế: <a href="https://www.figma.com/file/5Km584w3tlnwxOltV5KAjh/281123_HURA8?node-id=328%3A1204&mode=dev" target="_blank"> <strong>Giao diện Admin</strong> </a></p>
|
||||
|
||||
<p>Repo: <a href="https://repo.hurasoft.com/tieptk/bestpc_vn" target="_blank">https://repo.hurasoft.com/tieptk/bestpc_vn</a></p>
|
||||
|
||||
<p>Theo dõi tiến độ: <a href="https://docs.google.com/spreadsheets/d/1Po3ANsG00pm_Y3dnrwuV81cidTCCqepYmR3yPDlIq6c/edit#gid=0" target="_blank">https://docs.google.com/spreadsheets/d/1Po3ANsG00pm_Y3dnrwuV81cidTCCqepYmR3yPDlIq6c/edit#gid=0</a></p>
|
||||
|
||||
<h2>Cài đặt hệ thống</h2>
|
||||
|
||||
<p>Test và làm việc chính tại web: <a href="http://local.bestpc_vn/"> http://local.bestpc_vn/</a> </p>
|
||||
|
||||
<ul>
|
||||
<li>Tải phần mềm XAMPP tại <a href="https://www.apachefriends.org/download.html" target="_blank">https://www.apachefriends.org/download.html</a> để chạy PHP</li>
|
||||
<li>Chỉnh file hosts trong máy tính C:\Windows\System32\drivers\etc\hosts:
|
||||
<pre><code>
|
||||
127.0.0.1 local.bestpc_vn
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
Cài đặt ../xampp/apache/conf/extra/httpd-vhosts.conf của apache trong XAMPP
|
||||
<pre><code>
|
||||
<VirtualHost *:80>
|
||||
DocumentRoot "/thuc-muc-check-out/bestpc_vn"
|
||||
ServerName local.bestpc_vn
|
||||
<Directory "/thuc-muc-check-out/bestpc_vn/">
|
||||
Require all granted
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
Cài đặt ../xampp/apache/conf/httpd.conf của apache trong XAMPP
|
||||
<pre><code>
|
||||
# AllowOverride controls what directives may be placed in .htaccess files.
|
||||
# It can be "All", "None", or any combination of the keywords:
|
||||
# AllowOverride FileInfo AuthConfig Limit
|
||||
AllowOverride All
|
||||
</code></pre>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<h2>Cấu trúc thư mục</h2>
|
||||
|
||||
<ul>
|
||||
<li>/template: các file template html chia theo module/view</li>
|
||||
<li>/pages: cung cấp dữ liệu cho template và hiển thị dữ liệu trên template qua code Liquid <a href="https://shopify.github.io/liquid/" target="_blank">https://shopify.github.io/liquid/</a></li>
|
||||
<li>/public_html: Code public</li>
|
||||
<li>/public_html/assets: lưu các file ảnh/css/js dùng cho giao diện</li>
|
||||
<li>/package: thư viện code PHP hỗ trợ</li>
|
||||
<li>/src: các code PHP hỗ trợ</li>
|
||||
</ul>
|
||||
|
||||
<h2>Cài đặt Composer (dùng tải package của PHP)</h2>
|
||||
|
||||
<p>Xem hướng dẫn: <a href="https://getcomposer.org/doc/00-intro.md#installation-windows" target="_blank">https://getcomposer.org/doc/00-intro.md#installation-windows</a> </p>
|
||||
|
||||
<p>Sau khi cài đặt xong. Mở cmd của Windows và thao tác lệnh sau để cài các thư viện code PHP cần cho dự án này.</p>
|
||||
|
||||
<pre><code>
|
||||
> cd /thuc-muc-check-out/bestpc_vn/package
|
||||
> composer i
|
||||
</code></pre>
|
||||
|
||||
|
||||
9
config/constant.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
const IMAGE_FILE_SEPARATOR = "-";
|
||||
define("CURRENT_TIME", time());
|
||||
const STATIC_DOMAIN = "";
|
||||
const ENABLE_DB_DEBUG = true;
|
||||
const LANGUAGE = 'vi';
|
||||
const IS_DEFAULT_LANGUAGE = true;
|
||||
|
||||
11
config/routing.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
"/buildpc" => [
|
||||
'module' => 'buildpc',
|
||||
'view' => 'home',
|
||||
'view_id'=> 0,
|
||||
'query' => [],
|
||||
'url' => '/buildpc',
|
||||
],
|
||||
];
|
||||
8
package/composer.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"require": {
|
||||
"liquid/liquid": "1.4.32",
|
||||
"ext-json": "*",
|
||||
"ext-mysqli": "*",
|
||||
"ext-zip": "*"
|
||||
}
|
||||
}
|
||||
7
public_html/.htaccess
Normal file
@@ -0,0 +1,7 @@
|
||||
RewriteEngine on
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} !^/index.php
|
||||
# prevent rewrite non-existent files
|
||||
RewriteCond %{REQUEST_URI} !\.(jpg|png|gif|css|js|php|tiff|webp|jpeg|ico)$
|
||||
RewriteRule ^(.*)$ /index.php [QSA,L]
|
||||
13
public_html/_shared.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
define("ROOT_DIR", dirname(__DIR__));
|
||||
|
||||
const SRC_DIR = ROOT_DIR . '/src';
|
||||
const CONFIG_DIR = ROOT_DIR . '/config';
|
||||
|
||||
include CONFIG_DIR."/constant.php";
|
||||
include SRC_DIR."/inc/common.php";
|
||||
include SRC_DIR."/inc/fun.db.php";
|
||||
|
||||
// start autoload
|
||||
init_autoload();
|
||||
7
public_html/ajax.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
include __DIR__."/_shared.php";
|
||||
BIN
public_html/assets/font/FVHShopeeText-Bold.otf
Normal file
BIN
public_html/assets/font/ShopeeDisplay-Black.ttf
Normal file
BIN
public_html/assets/font/ShopeeDisplay-Bold.ttf
Normal file
BIN
public_html/assets/font/ShopeeDisplay-ExtraBold.ttf
Normal file
BIN
public_html/assets/font/ShopeeDisplay-Light.ttf
Normal file
BIN
public_html/assets/font/ShopeeDisplay-Medium.ttf
Normal file
BIN
public_html/assets/font/ShopeeDisplay-Regular.ttf
Normal file
BIN
public_html/assets/images/avartar-review-1.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
public_html/assets/images/avartar-review-2.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
public_html/assets/images/avartar-review-3.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public_html/assets/images/avartar.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
public_html/assets/images/avartar_acc.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public_html/assets/images/banner-list-product-save.png
Normal file
|
After Width: | Height: | Size: 620 KiB |
BIN
public_html/assets/images/banner-right-slider-1.png
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
public_html/assets/images/banner-right-slider-2.png
Normal file
|
After Width: | Height: | Size: 454 KiB |
BIN
public_html/assets/images/banner-right-slider-3.png
Normal file
|
After Width: | Height: | Size: 464 KiB |
BIN
public_html/assets/images/banner-right-slider-4.png
Normal file
|
After Width: | Height: | Size: 415 KiB |
BIN
public_html/assets/images/banner-sale-1.png
Normal file
|
After Width: | Height: | Size: 488 KiB |
BIN
public_html/assets/images/banner-sale-2.png
Normal file
|
After Width: | Height: | Size: 397 KiB |
BIN
public_html/assets/images/banner-sale-3.png
Normal file
|
After Width: | Height: | Size: 386 KiB |
BIN
public_html/assets/images/banner-sale-4.png
Normal file
|
After Width: | Height: | Size: 268 KiB |
BIN
public_html/assets/images/banner-slider.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
public_html/assets/images/banner_canhbao.png
Normal file
|
After Width: | Height: | Size: 262 KiB |
BIN
public_html/assets/images/big-image-rao-vat.png
Normal file
|
After Width: | Height: | Size: 477 KiB |
BIN
public_html/assets/images/big-product-detail-1.jpg
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
public_html/assets/images/big-product-detail-2.jpg
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
public_html/assets/images/big-product-detail-3.jpg
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
public_html/assets/images/big-product-detail-4.jpg
Normal file
|
After Width: | Height: | Size: 275 KiB |
BIN
public_html/assets/images/big-product-detail.jpg
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
public_html/assets/images/big-product-detail.png
Normal file
|
After Width: | Height: | Size: 357 KiB |
BIN
public_html/assets/images/box-image.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
public_html/assets/images/category-avatar.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
public_html/assets/images/icon-cate-1.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
public_html/assets/images/icon-cate-10.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public_html/assets/images/icon-cate-11.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
public_html/assets/images/icon-cate-12.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
public_html/assets/images/icon-cate-13.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public_html/assets/images/icon-cate-14.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public_html/assets/images/icon-cate-15.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
public_html/assets/images/icon-cate-16.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
public_html/assets/images/icon-cate-2.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public_html/assets/images/icon-cate-3.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public_html/assets/images/icon-cate-4.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public_html/assets/images/icon-cate-5.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
public_html/assets/images/icon-cate-6.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public_html/assets/images/icon-cate-7.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
public_html/assets/images/icon-cate-8.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public_html/assets/images/icon-cate-9.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
public_html/assets/images/icon-file-save.png
Normal file
|
After Width: | Height: | Size: 516 B |
BIN
public_html/assets/images/icon-play.png
Normal file
|
After Width: | Height: | Size: 786 B |
BIN
public_html/assets/images/icon-star-active.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public_html/assets/images/icon-star-gray.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
public_html/assets/images/icon_2025.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
public_html/assets/images/icon_star.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public_html/assets/images/icon_upload_image.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public_html/assets/images/icon_upload_video.png
Normal file
|
After Width: | Height: | Size: 1006 B |
BIN
public_html/assets/images/image-article.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public_html/assets/images/lienkien-ram.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
public_html/assets/images/logo-anphat.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
public_html/assets/images/logo-footer.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
public_html/assets/images/logo-gearvn.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public_html/assets/images/logo-hacom.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public_html/assets/images/logo.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
public_html/assets/images/promotions-1.png
Normal file
|
After Width: | Height: | Size: 543 KiB |
BIN
public_html/assets/images/promotions-2.png
Normal file
|
After Width: | Height: | Size: 352 KiB |
BIN
public_html/assets/images/promotions-3.png
Normal file
|
After Width: | Height: | Size: 452 KiB |
BIN
public_html/assets/images/promotions-4.png
Normal file
|
After Width: | Height: | Size: 464 KiB |
BIN
public_html/assets/images/promotions-big.png
Normal file
|
After Width: | Height: | Size: 452 KiB |
BIN
public_html/assets/images/small-product-detail.png
Normal file
|
After Width: | Height: | Size: 536 KiB |
BIN
public_html/assets/images/star_min.png
Normal file
|
After Width: | Height: | Size: 942 B |
BIN
public_html/assets/images/thumb-image-rao-vat.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
41
public_html/assets/script/font.css
Normal file
@@ -0,0 +1,41 @@
|
||||
@font-face {
|
||||
font-family: "Shopee";
|
||||
font-display: swap;
|
||||
src: url(../font//FVHShopeeText-Bold.otf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Shopee Bold";
|
||||
font-display: swap;
|
||||
src: url(../font/ShopeeDisplay-Bold.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Shopee Regular";
|
||||
font-display: swap;
|
||||
src: url(../font/ShopeeDisplay-Regular.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Shopee Medium";
|
||||
font-display: swap;
|
||||
src: url(../font/ShopeeDisplay-Medium.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Shopee Light";
|
||||
font-display: swap;
|
||||
src: url(../font/ShopeeDisplay-Light.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Shopee ExtraBold";
|
||||
font-display: swap;
|
||||
src: url(../font/ShopeeDisplay-ExtraBold.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Shopee Black";
|
||||
font-display: swap;
|
||||
src: url(../font/ShopeeDisplay-Black.ttf);
|
||||
}
|
||||
1297
public_html/assets/script/style.css
Normal file
1
public_html/assets/script/style.css.map
Normal file
1367
public_html/assets/script/style.scss
Normal file
15
public_html/index.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
use Hura\App;
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
const TEMPLATE_ASSET = '/assets';
|
||||
|
||||
include __DIR__."/_shared.php";
|
||||
|
||||
$objApp = new App();
|
||||
|
||||
$objApp->start();
|
||||
211
src/Hura/App.php
Normal 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
@@ -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¶m2=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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
5
src/pages/buildpc/home.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
];
|
||||
13
src/pages/home/home.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
"tom_tat" => [
|
||||
[
|
||||
'id' => 1,
|
||||
'title' => 'ĐƠN HÀNG MỚI',
|
||||
'main_stat' => '1000000',
|
||||
'time' => ' 24/11/2023 ',
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
1
src/pages/product/addon.php
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||
1
src/pages/product/addon_add.php
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||
1
src/pages/product/attribute.php
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||
1
src/pages/product/attribute_add.php
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||
1
src/pages/product/brand.php
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||
1
src/pages/product/brand_add.php
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||
108
src/pages/product/category.php
Normal 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 .= " ";
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
18
src/pages/product/category_form.php
Normal 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"),
|
||||
];
|
||||
1
src/pages/product/collection.php
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||