cfmgrv4 init...1

This commit is contained in:
최준흠 2024-10-04 19:15:57 +09:00
parent 6ac8f794ce
commit 42f638e019
27 changed files with 255 additions and 288 deletions

View File

@ -139,22 +139,22 @@ define('AUTH_FIELDS', [
//메신저 관련
define("MESSENGERS", [
"skype" => [
"url" => "https://join.skype.com/invite/uKUgXfZThSQC",
"url" => "//join.skype.com/invite/uKUgXfZThSQC",
"icon" => '<img src="/images/common/top_skype.png" alt="스카이프">',
"id" => '',
],
"discord" => [
"url" => "https://discord.gg/k6nQg84N",
"url" => "//discord.gg/k6nQg84N",
"icon" => '<img src="/images/common/discord.png" alt="디스코드">',
"id" => '',
],
"telegram" => [
"url" => "https://t.me/daemonidc",
"url" => "//t.me/daemonidc",
"icon" => '<img src="/images/common/telegram.png" alt="텔레그램">',
"id" => '@daemonidc',
],
"kakaotalk" => [
"url" => "https://t.me/daemonidc",
"url" => "//t.me/daemonidc",
"icon" => '<img src="/images/common/kakaotalk.png" alt="카카오톡">',
"id" => '',
],
@ -241,21 +241,21 @@ define('LAYOUTS', [
'<meta property="og:description" content="' . KEYWORD . '">',
],
'stylesheets' => [
'<link rel="canonical" href="https://daemonidc.com/" />',
'<link rel="canonical" href="//daemonidc.com/" />',
'<link rel="icon" href="/favicon.ico">',
'<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">',
'<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">',
'<link href="//cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">',
'<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">',
'<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.min.css" />',
'<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css" />',
'<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">',
'<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.min.css" />',
'<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css" />',
'<link rel="stylesheet" href="/css/style.css" />',
],
'javascripts' => [
'<script src="//cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js"></script>',
'<script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>',
'<script src="//cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>',
'<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>',
'<script src="//cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>',
'<script src="/vendors/tinymce/tinymce/tinymce.js" referrerpolicy="origin"></script>',
],
],
@ -267,16 +267,17 @@ define('LAYOUTS', [
'<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">',
'<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">',
'<link href="//cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">',
'<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">',
'<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.min.css" />',
'<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css" />',
'<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">',
'<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.min.css" />',
'<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css" />',
'<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css" />',
'<link rel="stylesheet" href="/css/style.css" />',
],
'javascripts' => [
'<script src="//cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js"></script>',
'<script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>',
'<script src="//cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>',
'<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>',
'<script src="//cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>',
'<script src="/vendors/tinymce/tinymce/tinymce.js" referrerpolicy="origin"></script>',
],
],

View File

@ -25,7 +25,6 @@ $routes->group('admin', ['namespace' => 'App\Controllers\Admin'], function ($rou
$routes->get('toggle/(:num)/(:alpha)', 'UserController::toggle/$1/$2');
$routes->post('batchjob', 'UserController::batcjob');
$routes->get('download/(:alpha)', 'UserController::download/$1');
$routes->get('download/(:alpha)/(:any)', 'UserController::download/$1/$2');
});
$routes->group('mapurl', function ($routes) {
$routes->get('/', 'MapurlController::index');
@ -37,7 +36,6 @@ $routes->group('admin', ['namespace' => 'App\Controllers\Admin'], function ($rou
$routes->get('toggle/(:num)/(:alpha)', 'MapurlController::toggle/$1/$2');
$routes->post('batchjob', 'MapurlController::batcjob');
$routes->get('download/(:alpha)', 'MapurlController::download/$1');
$routes->get('download/(:alpha)/(:any)', 'MapurlController::download/$1/$2');
});
$routes->group('cloudflare', ['namespace' => 'App\Controllers\Admin\Cloudflare'], function ($routes) {
$routes->group('auth', function ($routes) {
@ -46,49 +44,44 @@ $routes->group('admin', ['namespace' => 'App\Controllers\Admin'], function ($rou
$routes->post('create', 'AuthController::create');
$routes->get('modify/(:num)', 'AuthController::modify_form/$1');
$routes->get('delete/(:num)', 'AuthController::delete/$1');
$routes->post('modify/(:num)', 'AuthController::modify/$1');
$routes->get('toggle/(:num)/(:alpha)', 'AuthController::toggle/$1/$2');
$routes->post('batchjob', 'AuthController::batcjob');
$routes->get('download/(:alpha)', 'AuthController::download/$1');
$routes->get('download/(:alpha)/(:any)', 'AuthController::download/$1/$2');
$routes->get('reload/(:num)', 'AuthController::reload/$1');
$routes->get('reload', 'AuthController::reload');
$routes->cli('reload/(:num)', 'AuthController::reload/$1');
$routes->cli('reload', 'AuthController::reload');
$routes->get('download/(:alpha)', 'AccountController::download/$1');
});
$routes->group('account', function ($routes) {
$routes->get('/', 'AccountController::index');
$routes->post('create/(:uuid)', 'AccountController::create');
$routes->get('download/(:alpha)', 'AccountController::download/$1');
$routes->get('download/(:alpha)/(:any)', 'AccountController::download/$1/$2');
$routes->get('reload/(:alphanum)', 'AccountController::reload/$1');
$routes->get('reload', 'AccountController::reload');
$routes->cli('reload/(:alphanum)', 'AccountController::reload/$1');
$routes->cli('reload', 'AccountController::reload');
$routes->get('download/(:alpha)', 'AccountController::download/$1');
});
$routes->group('zone', function ($routes) {
$routes->get('/', 'ZoneController::index');
$routes->get('create', 'ZoneController::create_form');
$routes->post('create', 'ZoneController::create');
$routes->get('delete/(:uuid)', 'ZoneController::delete/$1');
$routes->get('toggle/(:uuid)/(:alpha)', 'ZoneController::toggle/$1/$2');
$routes->get('delete/(:alphanum)', 'ZoneController::delete/$1');
$routes->get('toggle/(:alphanum)/(:alpha)', 'ZoneController::toggle/$1/$2');
$routes->post('batchjob', 'ZoneController::batcjob');
$routes->get('download/(:alpha)', 'ZoneController::download/$1');
$routes->get('download/(:alpha)/(:any)', 'ZoneController::download/$1/$2');
$routes->get('reload/(:alphanum)', 'ZoneController::reload/$1');
$routes->get('reload', 'ZoneController::reload');
$routes->cli('reload/(:alphanum)', 'ZoneController::reload/$1');
$routes->cli('reload', 'ZoneController::reload');
$routes->get('download/(:alpha)', 'ZoneController::download/$1');
});
$routes->group('record', function ($routes) {
$routes->get('/', 'RecordController::index');
$routes->get('create', 'RecordController::create_form');
$routes->post('create)', 'RecordController::create');
$routes->get('delete/(:uuid)', 'RecordController::delete/$1');
$routes->get('toggle/(:uuid)/(:alpha)', 'RecordController::toggle/$1/$2');
$routes->get('delete/(:alphanum)', 'RecordController::delete/$1');
$routes->get('toggle/(:alphanum)/(:alpha)', 'RecordController::toggle/$1/$2');
$routes->post('batchjob', 'RecordController::batcjob');
$routes->get('download/(:alpha)', 'RecordController::download/$1');
$routes->get('download/(:alpha)/(:any)', 'RecordController::download/$1/$2');
});
});
});

View File

@ -78,6 +78,8 @@ class RecordController extends CloudflareController
public function create_form(): RedirectResponse|string
{
$this->init('create');
$parent_field = $this->getModel()::PARENT;
$this->$parent_field = $this->request->getVar($parent_field) ?: DEFAULTS["EMPTY"];
return $this->create_form_procedure();
}
protected function create_validate(string $action, array $fields): void
@ -88,40 +90,44 @@ class RecordController extends CloudflareController
protected function create_process(): void
{
//DB작업도 Socket에서 다 처리하므로 parent::create_process()하면 않됨
//부모데이터정의
$this->_zone_entity = $this->getZoneModel()->getEntityByPK($this->formDatas[$this->getModel()::PARENT]);
foreach ($this->formDatas['hosts'] as $host) {
//Cloudflare 생성
$entity = $this->getMySocket()->create($host, $this->formDatas['type'], $this->formDatas['content'], $this->formDatas['proxied']);
log_message("debug", "Record:{$entity->getTitle()} 생성 작업을 완료하였습니다.");
}
}
public function create(): RedirectResponse|string
{
$this->init(__FUNCTION__);
$this->create_validate($this->action, $this->fields);
$this->formDatas = $this->getFormDatas();
//부모데이터정의
$this->_zone_entity = $this->getZoneModel()->getEntityByPK($this->formDatas[$this->getModel()::PARENT]);
//데이터 검증
$cnt = 1;
foreach ($this->formDatas['hosts'] as $host) {
//호스트명 형식확인
if (!isHost_CommonHelper($host)) {
throw new \Exception("{$this->_account_entity->getTitle()}{$cnt}번째 {$host} 호스트명 형식 오류");
throw new \Exception("{$this->_zone_entity->getTitle()}{$cnt}번째 {$host} 호스트명 형식 오류");
}
$cnt++;
}
//Socket처리
foreach ($this->formDatas['hosts'] as $host) {
$entity = $this->getMySocket()->create($host, $this->formDatas['type'], $this->formDatas['content'], $this->formDatas['proxied']);
log_message("debug", "Record:{$entity->getTitle()} 생성 작업을 완료하였습니다.");
}
}
public function create(mixed $zone_uid = false): RedirectResponse|string
{
$this->init(__FUNCTION__);
return $this->create_procedure($this->action_form);
}
//수정 (modify,toggle,batchjob사용)
protected function modify_process(string $uid): void
{
//DB작업도 Socket에서 다 처리하므로 parent::modify_process($uid)하면 않됨
$this->entity = $this->getModel()->getEntityByPK(intval($uid));
$this->modify_validate($this->action, $this->fields);
$this->formDatas = $this->getFormDatas();
//자신정보정의
$this->entity = $this->getModel()->getEntityByPK($uid);
if ($this->entity === null) {
throw new \Exception("{$uid} 정보를 찾을수 없습니다.");
}
//부모데이터정의
$this->_zone_entity = $this->getZoneModel()->getEntityByPK($this->formDatas[$this->getModel()::PARENT]);
//Cloudflare 수정
$this->_zone_entity = $this->getZoneModel()->getEntityByPK($this->entity->getParent());
//Socket처리
$entity = $this->getMySocket()->modify($this->entity, $this->formDatas);
log_message("debug", "Record:{$entity->getTitle()} 수정 작업을 완료하였습니다.");
}
@ -131,14 +137,13 @@ class RecordController extends CloudflareController
$this->action = __FUNCTION__;
$this->fields = ['proxied'];
$this->field_rules = $this->getModel()->getFieldRules($this->action, $this->fields);
$this->modify_validate($this->action, $this->fields);
$this->formDatas = $this->getFormDatas();
return $this->batcjob_procedure();
}
//삭제
protected function delete_process(string $uid): void
{
//DB작업도 Socket에서 다 처리하므로 parent::delete_process($uid)하면 않됨
//자신정보정의
$this->entity = $this->getModel()->getEntityByPK(intval($uid));
if ($this->entity === null) {
throw new \Exception("{$uid} 정보를 찾을수 없습니다.");

View File

@ -91,6 +91,8 @@ class ZoneController extends CloudflareController
public function create_form(): RedirectResponse|string
{
$this->init('create');
$parent_field = $this->getModel()::PARENT;
$this->$parent_field = $this->request->getVar($parent_field) ?: DEFAULTS["EMPTY"];
return $this->create_form_procedure();
}
protected function create_validate(string $action, array $fields): void
@ -101,31 +103,11 @@ class ZoneController extends CloudflareController
protected function create_process(): void
{
//DB작업도 Socket에서 다 처리하므로 parent::create_process()하면 않됨
//Zone생성
$cnt = 1;
$zone_entitys = [];
foreach ($this->formDatas['domains'] as $domain) {
$entity = $this->getMySocket()->create($domain);
log_message("debug", "Zone:{$entity->getTitle()} 작업을 완료하였습니다.");
$zone_entitys[] = $entity;
$cnt++;
}
//Record생성
foreach ($zone_entitys as $zone_entity) {
$record_socket = new RecordSocket($entity);
foreach ($this->formDatas['hosts'] as $host) {
$entity = $record_socket->create($host, $this->formDatas['type'], $this->formDatas['content'], $this->formDatas['proxied']);
log_message("debug", "Record:{$entity->getTitle()} 작업을 완료하였습니다.");
}
}
}
public function create(): RedirectResponse|string
{
$this->init(__FUNCTION__);
$this->create_validate($this->action, $this->fields);
$this->formDatas = $this->getFormDatas();
//부모데이터 정의
$this->_account_entity = $this->getAccountModel()->getEntityByPK($this->formDatas[$this->getModel()::PARENT]);
//데이터검증
//Type이 A형식일경우 IP형태인지 확인
if ($this->formDatas['type'] === 'A') {
if (!isIPAddress_CommonHelper($this->formDatas['content'], $this->formDatas['type'])) {
@ -152,19 +134,44 @@ class ZoneController extends CloudflareController
}
$cnt++;
}
//Socket처리
//Zone생성
$cnt = 1;
$zone_entitys = [];
foreach ($this->formDatas['domains'] as $domain) {
$entity = $this->getMySocket()->create($domain);
log_message("debug", "Zone:{$entity->getTitle()} 작업을 완료하였습니다.");
$zone_entitys[] = $entity;
$cnt++;
}
//Record생성
foreach ($zone_entitys as $zone_entity) {
$record_socket = new RecordSocket($entity);
foreach ($this->formDatas['hosts'] as $host) {
$entity = $record_socket->create($host, $this->formDatas['type'], $this->formDatas['content'], $this->formDatas['proxied']);
log_message("debug", "Record:{$entity->getTitle()} 작업을 완료하였습니다.");
}
}
}
public function create(): RedirectResponse|string
{
$this->init(__FUNCTION__);
return $this->create_procedure($this->action_form);
}
//수정 (modify,toggle,batchjob사용)
protected function modify_process(string $uid): void
{
//DB작업도 Socket에서 다 처리하므로 parent::modify_process($uid)하면 않됨
$this->modify_validate($this->action, $this->fields);
$this->formDatas = $this->getFormDatas();
//자신정보정의
$this->entity = $this->getModel()->getEntityByPK(intval($uid));
if ($this->entity === null) {
throw new \Exception("{$uid} 정보를 찾을수 없습니다.");
}
//부모데이터정의
$this->_account_entity = $this->getAccountModel()->getEntityByPK($this->formDatas[$this->getModel()::PARENT]);
//Cloudflare 수정
$this->_account_entity = $this->getAccountModel()->getEntityByPK($this->entity->getParent());
//Socket처리
$entity = $this->getMySocket()->modify($this->entity, $this->formDatas);
log_message("debug", "Record:{$entity->getTitle()} 수정 작업을 완료하였습니다.");
}
@ -174,14 +181,13 @@ class ZoneController extends CloudflareController
$this->action = __FUNCTION__;
$this->fields = ['development_mode', 'ipv6', 'security_level'];
$this->field_rules = $this->getModel()->getFieldRules($this->action, $this->fields);
$this->modify_validate($this->action, $this->fields);
$this->formDatas = $this->getFormDatas();
return $this->batcjob_procedure();
}
//삭제
protected function delete_process(string $uid): void
{
//DB작업도 Socket에서 다 처리하므로 parent::delete_process($uid)하면 않됨
//자신정보정의
$this->entity = $this->getModel()->getEntityByPK(intval($uid));
if ($this->entity === null) {
throw new \Exception("{$uid} 정보를 찾을수 없습니다.");

View File

@ -179,12 +179,12 @@ abstract class MVController extends CommonController
}
protected function modify_process(string $uid): void
{
// dd($this->fields);
$this->modify_validate($this->action, $this->fields);
$this->formDatas = $this->getFormDatas();
$this->entity = $this->getModel()->getEntityByPK(intval($uid));
//자신정보정의
$this->entity = $this->getModel()->getEntityByPK($uid);
if ($this->entity === null) {
throw new \Exception("{$uid} 정보를 찾을수 없습니다.");
throw new \Exception(__FUNCTION__, " => {$uid} 정보를 찾을수 없습니다.");
}
$this->entity = $this->getModel()->modify($this->entity, $this->formDatas);
}
@ -258,6 +258,7 @@ abstract class MVController extends CommonController
//삭제
protected function delete_process(string $uid): void
{
//자신정보정의
$this->entity = $this->getModel()->getEntityByPK(intval($uid));
if ($this->entity === null) {
throw new \Exception("{$uid} 정보를 찾을수 없습니다.");
@ -372,7 +373,7 @@ abstract class MVController extends CommonController
//모델 처리
$this->entitys = $this->list_entitys_process();
//setting return_url to session flashdata
$this->session->setFlashdata(SESSION_NAMES['RETURN_URL'], current_url() . '?' . $this->request->getUri()->getQuery() ?: "");
$this->session->setFlashdata(SESSION_NAMES['RETURN_URL'], current_url() . '?' . $this->uri->getQuery() ?: "");
return view(
strtolower($this->class_path) . "/index",
['viewDatas' => $this->getViewDatas()]

View File

@ -25,7 +25,7 @@ function getFieldForm_AccountHelper(string $field, mixed $value, array $viewData
$form = form_dropdown($field, [
"" => lang($viewDatas['class_path'] . '.label.' . $field) . ' 선택',
...$viewDatas['field_options'][$field]
], $value, [...$extras, 'class' => "select-field"]);
], isset($viewDatas[AccountModel::PARENT]) ? $viewDatas[AccountModel::PARENT] : $value, [...$extras, 'class' => "select-field"]);
// // return form_multiselect($field, $field_options[$field], is_array($value) ? [...$value] : [$value], [$extras]);
// foreach ($viewDatas['field_options'][$field] as $key => $label) {
// $checkboxs[] = form_checkbox("{$field}[]", $key, in_array($key, explode(DEFAULTS["DELIMITER_ROLE"], $value))) . $label;
@ -170,7 +170,7 @@ function getListButton_AccountHelper(string $action, array $viewDatas, array $ex
{
switch ($action) {
case 'create':
$viewDatas['list_action_url'] = $url = current_url() . '/' . $action;
$viewDatas['list_action_url'] = current_url() . '/' . $action . '?' . $viewDatas['uri']->getQuery(['only' => AccountModel::PARENT]);
$extras = ["class" => "btn btn-outline btn-primary btn-circle", "target" => "_self", ...$extras];
$action = getListButtonLabel_AccountHelper($action, '입력', $viewDatas, $extras);
break;

View File

@ -138,7 +138,7 @@ function getListButton_AuthHelper(string $action, array $viewDatas, array $extra
{
switch ($action) {
case 'create':
$viewDatas['list_action_url'] = $url = current_url() . '/' . $action;
$viewDatas['list_action_url'] = current_url() . '/' . $action;
$extras = ["class" => "btn btn-outline btn-primary btn-circle", "target" => "_self", ...$extras];
$action = getListButtonLabel_AuthHelper($action, '입력', $viewDatas, $extras);
break;

View File

@ -1,6 +1,7 @@
<?php
use App\Models\Cloudflare\RecordModel;
use App\Models\Cloudflare\ZoneModel;
function getFieldLabel_RecordHelper(string $field, array $viewDatas, array $extras = []): string
{
@ -22,10 +23,15 @@ function getFieldForm_RecordHelper(string $field, mixed $value, array $viewDatas
$value = $value ?: DEFAULTS['EMPTY'];
switch ($field) {
case RecordModel::PARENT:
$form = form_dropdown($field, [
"" => lang($viewDatas['class_path'] . '.label.' . $field) . ' 선택',
...$viewDatas['field_options'][$field]
], $value, [...$extras, 'class' => "select-field"]);
$form = form_dropdown(
$field,
[
"" => lang($viewDatas['class_path'] . '.label.' . $field) . ' 선택',
...$viewDatas['field_options'][$field]
],
isset($viewDatas[RecordModel::PARENT]) ? $viewDatas[RecordModel::PARENT] : $value,
[...$extras, 'class' => "select-field"]
);
// // return form_multiselect($field, $field_options[$field], is_array($value) ? [...$value] : [$value], [$extras]);
// foreach ($viewDatas['field_options'][$field] as $key => $label) {
// $checkboxs[] = form_checkbox("{$field}[]", $key, in_array($key, explode(DEFAULTS["DELIMITER_ROLE"], $value))) . $label;
@ -84,19 +90,12 @@ function getFieldView_RecordHelper(string $field, array $viewDatas, array $extra
$value = sprintf("%s%s", $viewDatas['entity']->fixed == 'on' ? ICONS['LOCK'] : "", $value);
$value = anchor($url, $value, ["target" => "_self"]);
break;
case 'category_uid':
foreach (array_values($viewDatas['field_options'][$field]) as $category_2depths) {
foreach ($category_2depths as $key => $depth) {
if ($key == $depth) {
$value = $depth;
}
}
}
break;
case 'cost':
case 'price':
case 'sale':
$value = number_format(!$value ? 0 : $value) . "";
case 'content':
$value = sprintf(
"<span class=\"short-text\" data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"%s\">%s</span>",
$value,
mb_strlen($value) > 40 ? mb_substr($value, 0, 40) . '...' : $value
);
break;
case 'updated_at':
case 'created_at':
@ -197,7 +196,7 @@ function getListButton_RecordHelper(string $action, array $viewDatas, array $ext
{
switch ($action) {
case 'create':
$viewDatas['list_action_url'] = $url = current_url() . '/' . $action;
$viewDatas['list_action_url'] = current_url() . '/' . $action . '?' . $viewDatas['uri']->getQuery(['only' => RecordModel::PARENT]);
$extras = ["class" => "btn btn-outline btn-primary btn-circle", "target" => "_self", ...$extras];
$action = getListButtonLabel_RecordHelper($action, '입력', $viewDatas, $extras);
break;

View File

@ -25,7 +25,7 @@ function getFieldForm_ZoneHelper(string $field, mixed $value, array $viewDatas,
$form = form_dropdown($field, [
"" => lang($viewDatas['class_path'] . '.label.' . $field) . ' 선택',
...$viewDatas['field_options'][$field]
], $value, [...$extras, 'class' => "select-field"]);
], isset($viewDatas[ZoneModel::PARENT]) ? $viewDatas[ZoneModel::PARENT] : $value, [...$extras, 'class' => "select-field"]);
// // return form_multiselect($field, $field_options[$field], is_array($value) ? [...$value] : [$value], [$extras]);
// foreach ($viewDatas['field_options'][$field] as $key => $label) {
// $checkboxs[] = form_checkbox("{$field}[]", $key, in_array($key, explode(DEFAULTS["DELIMITER_ROLE"], $value))) . $label;
@ -223,7 +223,7 @@ function getListButton_ZoneHelper(string $action, array $viewDatas, array $extra
{
switch ($action) {
case 'create':
$viewDatas['list_action_url'] = $url = current_url() . '/' . $action;
$viewDatas['list_action_url'] = current_url() . '/' . $action . '?' . $viewDatas['uri']->getQuery(['only' => ZoneModel::PARENT]);
$extras = ["class" => "btn btn-outline btn-primary btn-circle", "target" => "_self", ...$extras];
$action = getListButtonLabel_ZoneHelper($action, '입력', $viewDatas, $extras);
break;

View File

@ -132,7 +132,7 @@ function getListButton_MapurlHelper(string $action, array $viewDatas, array $ext
{
switch ($action) {
case 'create':
$viewDatas['list_action_url'] = $url = current_url() . '/' . $action;
$viewDatas['list_action_url'] = current_url() . '/' . $action;
$extras = ["class" => "btn btn-outline btn-primary btn-circle", "target" => "_self", ...$extras];
$action = getListButtonLabel_MapurlHelper($action, '입력', $viewDatas, $extras);
break;

View File

@ -151,7 +151,7 @@ function getListButton_UserHelper(string $action, array $viewDatas, array $extra
{
switch ($action) {
case 'create':
$viewDatas['list_action_url'] = $url = current_url() . '/' . $action;
$viewDatas['list_action_url'] = current_url() . '/' . $action;
$extras = ["class" => "btn btn-outline btn-primary btn-circle", "target" => "_self", ...$extras];
$action = getListButtonLabel_UserHelper($action, '입력', $viewDatas, $extras);
break;

View File

@ -52,16 +52,19 @@ class RecordSocket extends CloudflareSocket
public function create(string $host, string $type, string $content, string $proxied): RecordEntity
{
//Socket용
//도메인생성을 위해 Cloudflare에 전송
$cf = $this->getClient()->post('zones/' . $this->_zone_entity->getPK() . '/dns_records', [
//호스트생성을 위해 Cloudflare에 전송
$datas = [
'name' => $host,
'type' => $type,
'content' => $content,
'proxied' => $proxied === 'on' ? true : false
]);
];
$cf = $this->getRequest('post', "zones/{$this->_zone_entity->getPK()}/dns_records", $datas);
$cf = json_decode($cf->getBody());
if (!$cf->success) {
throw new \Exception("Record:" . __FUNCTION__ . "에서 실패:\n" . var_export($cf, true));
$message = "Record:" . __FUNCTION__ . "에서 실패:\nrequest:" . var_export($datas, true) . "\nresponse:" . var_export($cf, true);
log_message("error", $message);
throw new \Exception($message);
}
//DB생성
$formDatas = $this->getArrayByResult($cf->result);
@ -77,17 +80,23 @@ class RecordSocket extends CloudflareSocket
'proxied' => $entity->proxied == 'on' ? true : false,
'ttl' => intval($entity->ttl),
];
if (isset($formDatas['proxied']) && $formDatas['proxied'] === 'on') {
$datas['proxied'] = true;
$datas['ttl'] = 1;
} elseif (isset($formDatas['proxied']) && $formDatas['proxied'] === 'off') {
$datas['proxied'] = false;
$datas['ttl'] = 120;
if (isset($formDatas['proxied'])) {
if ($formDatas['proxied'] === 'on') {
$datas['proxied'] = true;
$datas['ttl'] = 1;
} else {
$datas['proxied'] = false;
$datas['ttl'] = 120;
}
}
$cf = $this->getClient()->put('zones/' . $this->_zone_entity->getPK() . '/dns_records', $datas);
// 인코딩된 JSON을 확인
// throw new \Exception("Record:" . __FUNCTION__ . "\n" . json_encode($datas, JSON_PRETTY_PRINT) . "\n" . var_export($datas, true));
$cf = $this->getRequest('put', "zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}", $datas);
$cf = json_decode($cf->getBody());
if (!$cf->success) {
throw new \Exception("Record:" . __FUNCTION__ . "에서 실패:\n" . var_export($cf, true));
$message = "Record:" . __FUNCTION__ . "에서 실패:\nrequest:" . var_export($datas, true) . "\nresponse:" . var_export($cf, true);
log_message("error", $message);
throw new \Exception($message);
}
//DB수정
$formDatas = $this->getArrayByResult($cf->result);
@ -95,10 +104,12 @@ class RecordSocket extends CloudflareSocket
}
public function delete(RecordEntity $entity): void
{
$cf = $this->getClient()->delete('zones/' . $this->_zone_entity->getPK() . '/dns_records/' . $entity->getPK());
$cf = $this->getRequest('delete', "zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}");
$cf = json_decode($cf->getBody());
if (!$cf->success) {
throw new \Exception("Record:" . __FUNCTION__ . "에서 실패:\n" . var_export($cf, true));
$message = "Record:" . __FUNCTION__ . "에서 실패:\nresponse:" . var_export($cf, true);
log_message("error", $message);
throw new \Exception($message);
}
//DB삭제
$this->getModel()->where(RecordModel::PK, $entity->getPK());
@ -107,14 +118,14 @@ class RecordSocket extends CloudflareSocket
public function sync(RecordEntity $entity): void
{
//기존 Sync형태
// $cf = $this->getClient()->get("zones/{$this->_zone_entity->getPK()}/dns_records/" . $entity->getPK());
// $cf = $this->getRequest('get',"zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}");
// $cf = json_decode($cf->getBody());
// if (!$cf->success) {
// throw new \Exception(__FUNCTION__ . "에서 실패:\n" . var_export($cf, true));
// }
// return new RecordEntity($this->getArrayByResult($cf->result));
//Async형태
$promise = $this->getClient()->getAsync("zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}");
$promise = $this->getRequest('getAsync', "zones/{$this->_zone_entity->getPK()}/dns_records/{$entity->getPK()}");
$promise->then(
onFulfilled: function ($response) use ($entity): RecordEntity {
$record = json_decode($response->getBody(), true)['result'];

View File

@ -59,10 +59,12 @@ class ZoneSocket extends CloudflareSocket
//Cfzone에서 가져온 값을 zone에 setting
protected function getCFSetting(ZoneEntity $entity): ZoneEntity
{
$cf = $this->getClient()->patch('zones/' . $entity->getPK() . '/settings/');
$cf = $this->getRequest('patch', 'zones/' . $entity->getPK() . '/settings/');
$cf = json_decode($cf->getBody());
if (!$cf->success) {
throw new \Exception("Zone:" . __FUNCTION__ . "에서 실패:\n" . var_export($cf, true));
$message = "Zone:" . __FUNCTION__ . "에서 실패:\nresponse:" . var_export($cf, true);
log_message("error", $message);
throw new \Exception($message);
}
foreach ($cf->result as $cf) {
switch ($cf->id) {
@ -81,10 +83,13 @@ class ZoneSocket extends CloudflareSocket
}
protected function setCFSetting(ZoneEntity $entity, string $field, string $value): ZoneEntity
{
$cf = $this->getClient()->patch('zones/' . $entity->getPK() . '/settings/' . $field, array('value' => $value));
$datas = ['value' => $value];
$cf = $this->getRequest('patch', 'zones/' . $entity->getPK() . '/settings/' . $field, $datas);
$cf = json_decode($cf->getBody());
if (!$cf->success || $cf->result->id !== $field) {
throw new \Exception("Zone:" . __FUNCTION__ . "에서 {$field}->{$value} 변경실패:\n" . var_export($cf, true));
$message = "Zone:" . __FUNCTION__ . "에서 실패:\nrequest:" . var_export($datas, true) . "\nresponse:" . var_export($cf, true);
log_message("error", $message);
throw new \Exception($message);
}
//최종 결과값은 body->result->id='필드명',body->result->value='on/off'이런식으로 받음
return $cf->result->value;
@ -93,14 +98,17 @@ class ZoneSocket extends CloudflareSocket
{
//Socket용
//도메인생성을 위해 Cloudflare에 전송
$cf = $this->getClient()->post('zones/', [
$datas = [
'accountId' => $this->_account_entity->getPK(),
'name' => $domain,
'jump_start' => $jump_start,
]);
];
$cf = $this->getRequest('post', 'zones/', $datas);
$cf = json_decode($cf->getBody());
if (!$cf->success) {
throw new \Exception("Zone:" . __FUNCTION__ . "에서 실패:\n" . var_export($cf, true));
$message = "Zone:" . __FUNCTION__ . "에서 실패:\nrequest:" . var_export($datas, true) . "\nresponse:" . var_export($cf, true);
log_message("error", $message);
throw new \Exception($message);
}
//DB생성
$formDatas = $this->getArrayByResult($cf->result);
@ -126,10 +134,12 @@ class ZoneSocket extends CloudflareSocket
}
public function delete(ZoneEntity $entity): void
{
$cf = $this->getClient()->delete('zones/' . $entity->getPK());
$cf = $this->getRequest('delete', "zones/{$entity->getPK()}");
$cf = json_decode($cf->getBody());
if (!$cf->success) {
throw new \Exception("Zone:" . __FUNCTION__ . "에서 실패:\n" . var_export($cf, true));
$message = "Zone:" . __FUNCTION__ . "에서 실패:\nresponse:" . var_export($cf, true);
log_message("error", $message);
throw new \Exception($message);
}
//DB삭제
$this->getModel()->where(ZoneModel::PK, $entity->getPK());
@ -138,7 +148,7 @@ class ZoneSocket extends CloudflareSocket
public function sync(ZoneEntity $entity): void
{
//기존 Sync형태
// $cf = $this->getClient()->get('zones/' . $entity->getPK());
// $cf = $this->getRequest('get',"zones/{$entity->getPK()}");
// $cf = json_decode($cf->getBody());
// if (!$cf->success) {
// throw new \Exception("Zone:" . __FUNCTION__ . "에서 실패:\n" . var_export($cf, true));
@ -146,7 +156,7 @@ class ZoneSocket extends CloudflareSocket
// log_message("notice", "Zone:" . __FUNCTION__ . "=> 작업을 완료하였습니다.");
// return new ZoneEntity($this->getArrayByResult($cf->result));
//Async형태
$promise = $this->getClient()->getAsync("zones/{$entity->getPK()}");
$promise = $this->getRequest('getAsync', "zones/{$entity->getPK()}");
$promise->then(
onFulfilled: function ($response) use ($entity): ZoneEntity {
$record = json_decode($response->getBody(), true)['result'];

View File

@ -3,11 +3,13 @@
namespace App\Libraries\MySocket;
use GuzzleHttp\Client;
use App\Models\Cloudflare\AuthModel;
use App\Models\Cloudflare\AccountModel;
use App\Libraries\CommonLibrary;
use App\Entities\Cloudflare\AuthEntity;
use App\Libraries\CommonLibrary;
use App\Models\Cloudflare\AccountModel;
use App\Models\Cloudflare\AuthModel;
use Cloudflare\API\Adapter\ResponseException;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
abstract class CloudflareSocket extends CommonLibrary
{
@ -29,6 +31,22 @@ abstract class CloudflareSocket extends CommonLibrary
self::$_request_timewait = getenv("cfmgr.request.timewait") ?: 60;
}
abstract protected function getArrayByResult($result, array $formDatas = []): array;
private function getClient(): Client
{
if ($this->_client === null) {
// Guzzle HTTP 클라이언트를 설정하면서 Cloudflare API 토큰 사용
$this->_client = new Client([
'base_uri' => 'https://api.cloudflare.com/client/v4/',
'headers' => [
'X-Auth-Email' => $this->_auth_entity->getID(), // 인증 토큰 사용
'X-Auth-Key' => $this->_auth_entity->getAuthKey(), // 인증 토큰 사용
'Content-Type' => 'application/json',
],
'verify' => false // SSL 인증서 검증을 비활성화
]);
}
return $this->_client;
}
final protected function getAuthModel(): AuthModel
{
if ($this->_authModel === null) {
@ -43,28 +61,26 @@ abstract class CloudflareSocket extends CommonLibrary
}
return $this->_accountModel;
}
final protected function getClient(): Client
final protected function getRequest(string $method, string $uri, array $datas = [])
{
if ($this->_client === null) {
// Guzzle HTTP 클라이언트를 설정하면서 Cloudflare API 토큰 사용
$this->_client = new Client([
'base_uri' => 'https://api.cloudflare.com/client/v4/',
'headers' => [
'X-Auth-Email' => $this->_auth_entity->getID(), // 인증 토큰 사용
'X-Auth-Key' => $this->_auth_entity->getAuthKey(), // 인증 토큰 사용
'Content-Type' => 'application/json',
],
'verify' => false // SSL 인증서 검증을 비활성화
if (!in_array($method, ['get', 'post', 'put', 'patch', 'delete'])) {
throw new \InvalidArgumentException('Request method must be get, post, put, patch, or delete');
}
try {
$response = $this->getClient()->$method($uri, [
$method == 'get' ? 'query' : 'json' => $datas,
]);
if (self::$_request >= self::$_request_max) {
log_message('warning', sprintf("--Cloudflare API Call %s초 대기 시작--", self::$_request_timewait));
sleep(intval(self::$_request_timewait));
self::$_request = 0;
log_message('warning', sprintf("--Cloudflare API Call %s초 대기 종료--", self::$_request_timewait));
}
self::$_request++;
} catch (RequestException $err) {
throw ResponseException::fromRequestException($err);
}
if (self::$_request >= self::$_request_max) {
log_message('warning', sprintf("--Cloudflare API Call %s초 대기 시작--", self::$_request_timewait));
sleep(intval(self::$_request_timewait));
self::$_request = 0;
log_message('warning', sprintf("--Cloudflare API Call %s초 대기 종료--", self::$_request_timewait));
}
self::$_request++;
return $this->_client;
return $response;
}
final protected function reload_procedure($uri): array

View File

@ -54,9 +54,9 @@ class AuthModel extends CommonModel
}
return $options;
}
public function getEntityByPK(int $uid): null|AuthEntity
public function getEntityByPK(string $uid): null|AuthEntity
{
$this->where($this->getPKField(), $uid);
$this->where($this->getPKField(), intval($uid));
return $this->getEntity();
}
public function getEntityByID(string $id): null|AuthEntity

View File

@ -45,9 +45,9 @@ class MapurlModel extends CommonModel
}
return $rule;
}
public function getEntityByPK(int $uid): null|MapurlEntity
public function getEntityByPK(string $uid): null|MapurlEntity
{
$this->where($this->getPKField(), $uid);
$this->where($this->getPKField(), intval($uid));
return $this->getEntity();
}
//create용

View File

@ -46,9 +46,9 @@ class SNSUserModel extends CommonModel
}
return $rule;
}
public function getEntityByPK(int $uid): null|SNSUSerEntity
public function getEntityByPK(string $uid): null|SNSUSerEntity
{
$this->where($this->getPKField(), $uid);
$this->where($this->getPKField(), intval($uid));
return $this->getEntity();
}
public function getEntityByID(string $id): null|SNSUSerEntity

View File

@ -54,9 +54,9 @@ class UserModel extends CommonModel
return $rule;
}
public function getEntityByPK(int $uid): null|UserEntity
public function getEntityByPK(string $uid): null|UserEntity
{
$this->where($this->getPKField(), $uid);
$this->where($this->getPKField(), intval($uid));
return $this->getEntity();
}
public function getEntityByID(string $id): null|UserEntity

View File

@ -29,9 +29,9 @@
<div class="middle">
<div class="left"><?= $this->include(LAYOUTS[$viewDatas['layout']]['path'] . '/left_menu'); ?></div>
<div class="center">
<div class="header"><?= $this->include('templates/admin/header'); ?></div>
<div class="header"><?= $this->include("templates/{$viewDatas['layout']}/header"); ?></div>
<div class="content"><?= $this->renderSection('content') ?></div>
<div class="footer"><?= $this->include('templates/admin/footer'); ?></div>
<div class="footer"><?= $this->include("templates/{$viewDatas['layout']}/footer"); ?></div>
</div>
</div>
<div class="bottom">

View File

@ -29,9 +29,9 @@
<div class="middle">
<div class="left"><?= $this->include(LAYOUTS[$viewDatas['layout']]['path'] . '/left_menu'); ?></div>
<div class="center">
<div class="header"><?= $this->include('templates/admin/header'); ?></div>
<div class="header"><?= $this->include("templates/{$viewDatas['layout']}/header"); ?></div>
<div class="content"><?= $this->renderSection('content') ?></div>
<div class="footer"><?= $this->include('templates/admin/footer'); ?></div>
<div class="footer"><?= $this->include("templates/{$viewDatas['layout']}/footer"); ?></div>
</div>
</div>
<div class="bottom">

View File

@ -24,6 +24,7 @@
<body>
<div class="content"><?= $this->renderSection('content') ?></div>
<div class="footer"><?= $this->include("templates/{$viewDatas['layout']}/footer"); ?></div>
</body>
</html>

View File

@ -24,6 +24,7 @@
<body>
<div class="content"><?= $this->renderSection('content') ?></div>
<div class="footer"><?= $this->include("templates/{$viewDatas['layout']}/footer"); ?></div>
</body>
</html>

View File

@ -2,40 +2,41 @@
<html lang="ko">
<head>
<?php foreach ($viewDatas['layout']['metas'] as $meta) : ?><?= $meta ?><?php endforeach; ?>
<?php foreach ($viewDatas['layout']['stylesheets'] as $stylesheet) : ?><?= $stylesheet ?><?php endforeach; ?>
<?php foreach ($viewDatas['layout']['javascripts'] as $javascript) : ?><?= $javascript ?><?php endforeach; ?>
<link href="/css/front.css" media="screen" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/js/front.js"></script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title><?= $viewDatas['title'] ?></title>
<?php foreach (LAYOUTS[$viewDatas['layout']]['stylesheets'] as $stylesheet): ?>
<?= $stylesheet ?>
<?php endforeach; ?>
<?php foreach (LAYOUTS[$viewDatas['layout']]['javascripts'] as $javascript): ?>
<?= $javascript ?>
<?php endforeach; ?>
<link href="/css/<?= $viewDatas['layout'] ?>.css" media="screen" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/js/<?= $viewDatas['layout'] ?>.js"></script>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn' t work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div id="head">
<?= $this->include($viewDatas['layout']['path'] . '/top_navigator'); ?>
<?= $this->include($viewDatas['layout']['path'] . '/top_menu'); ?>
<?= TOP_BANNER[array_key_exists('currentCategory', $viewDatas) ? $viewDatas['currentCategory']->parent : 'default'] ?>
<div class="top">
<?= $this->include(LAYOUTS[$viewDatas['layout']]['path'] . '/top'); ?>
</div>
<div class="container-fluid">
<nav class="nav"></nav>
<nav class="nav justify-content-center">
<table id="layout">
<tr>
<td id="left" valign="top" width="200">
<?= $this->include($viewDatas['layout']['path'] . '/left_menu'); ?>
</td>
<td id="body" valign="top" width="*">
<?= $this->include('templates/front/header'); ?>
<?= $this->renderSection('content') ?>
<?= $this->include('templates/front/footer'); ?>
</td>
</tr>
</table>
<nav class="nav justify-content-end"></nav>
<div class="middle">
<div class="left"><?= $this->include(LAYOUTS[$viewDatas['layout']]['path'] . '/left_menu'); ?></div>
<div class="center">
<div class="header"><?= $this->include("templates/{$viewDatas['layout']}/header"); ?></div>
<div class="content"><?= $this->renderSection('content') ?></div>
<div class="footer"><?= $this->include("templates/{$viewDatas['layout']}/footer"); ?></div>
</div>
</div>
<div class="bottom">
<?= $this->include(LAYOUTS[$viewDatas['layout']]['path'] . '/bottom'); ?>
</div>
<nav id="tail" class="navbar navbar-expand-lg" style="background-color:white">
<?= $this->include($viewDatas['layout']['path'] . '/../common/copyright'); ?>
</nav>
</body>
</html>

View File

@ -1,49 +0,0 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" id="viewport" content="width=1280">
<meta name="subject" content="IT Solution">
<meta name="description" content="일본IDC 일본서버 일본 서버 일본호스팅 서버호스팅 디도스 공격 해외 호스팅 DDOS 방어 ddos 의뢰 디도스 보안 일본 단독서버">
<meta name="keywords" content="일본IDC 일본서버 일본 서버 일본호스팅 서버호스팅 디도스 공격 해외 호스팅 DDOS 방어 ddos 의뢰 디도스 보안 일본 단독서버">
<meta property="og:type" content="website">
<meta property="og:title" content="IT Solution">
<meta property="og:description" content="일본IDC 일본서버 일본 서버 일본호스팅 서버호스팅 디도스 공격 해외 호스팅 DDOS 방어 ddos 의뢰 디도스 보안 일본 단독서버">
<?php foreach ($viewDatas['layout']['stylesheets'] as $stylesheet) : ?>
<?= $stylesheet ?>
<?php endforeach; ?>
<?php foreach ($viewDatas['layout']['javascripts'] as $javascript) : ?>
<?= $javascript ?>
<?php endforeach; ?>
<link href="/css/front.css" media="screen" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/js/front.js"></script>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<title><?= $viewDatas['title'] ?></title>
</head>
<body>
<div id="head">
<?= $this->include($viewDatas['layout']['path'] . '/top_navigator'); ?>
<?= $this->include($viewDatas['layout']['path'] . '/top_menu'); ?>
</div>
<div class="container-fluid">
<nav class="nav"></nav>
<nav class="nav justify-content-center">
<?= $this->renderSection('content') ?>
</nav>
<nav class="nav justify-content-end"></nav>
</div>
<nav id="tail" class="navbar navbar-expand-lg" style="background-color:white">
<?= $this->include($viewDatas['layout']['path'] . '/../common/copyright'); ?>
</nav>
</body>
</html>

View File

@ -2,70 +2,41 @@
<html lang="ko">
<head>
<meta charset="utf-8">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" id="viewport" content="width=1280">
<meta name="subject" content="IT Solution">
<meta name="description" content="일본IDC 일본서버 일본 서버 일본호스팅 서버호스팅 디도스 공격 해외 호스팅 DDOS 방어 ddos 의뢰 디도스 보안 일본 단독서버">
<meta name="keywords" content="일본IDC 일본서버 일본 서버 일본호스팅 서버호스팅 디도스 공격 해외 호스팅 DDOS 방어 ddos 의뢰 디도스 보안 일본 단독서버">
<meta property="og:type" content="website">
<meta property="og:title" content="IT Solution">
<meta property="og:description" content="일본IDC 일본서버 일본 서버 일본호스팅 서버호스팅 디도스 공격 해외 호스팅 DDOS 방어 ddos 의뢰 디도스 보안 일본 단독서버">
<?php foreach ($viewDatas['layout']['stylesheets'] as $stylesheet) : ?>
<title><?= $viewDatas['title'] ?></title>
<?php foreach (LAYOUTS[$viewDatas['layout']]['stylesheets'] as $stylesheet): ?>
<?= $stylesheet ?>
<?php endforeach; ?>
<?php foreach ($viewDatas['layout']['javascripts'] as $javascript) : ?>
<?php foreach (LAYOUTS[$viewDatas['layout']]['javascripts'] as $javascript): ?>
<?= $javascript ?>
<?php endforeach; ?>
<link href="/css/main.css" media="screen" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/js/main.js"></script>
<link href="/css/<?= $viewDatas['layout'] ?>.css" media="screen" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/js/<?= $viewDatas['layout'] ?>.js"></script>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!-- WARNING: Respond.js doesn' t work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<title><?= $viewDatas['title'] ?></title>
</head>
<body>
<div id="head">
<?= $this->include($viewDatas['layout']['path'] . '/top_navigator'); ?>
<?= $this->include($viewDatas['layout']['path'] . '/top_menu'); ?>
<div class="top">
<?= $this->include(LAYOUTS[$viewDatas['layout']]['path'] . '/top'); ?>
</div>
<div id="carouselExampleAutoplaying" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="/images/main/visual1.jpg" class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="/images/main/visual2.jpg" class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="/images/main/visual3.jpg" class="d-block w-100" alt="...">
</div>
<div class="middle">
<div class="left"><?= $this->include(LAYOUTS[$viewDatas['layout']]['path'] . '/left_menu'); ?></div>
<div class="center">
<div class="header"><?= $this->include("templates/{$viewDatas['layout']}/header"); ?></div>
<div class="content"><?= $this->renderSection('content') ?></div>
<div class="footer"><?= $this->include("templates/{$viewDatas['layout']}/footer"); ?></div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleAutoplaying" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselExampleAutoplaying" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
<div class="container-fluid">
<nav class="nav"></nav>
<nav class="nav justify-content-center">
<?= $this->renderSection('content') ?>
</nav>
<nav class="nav justify-content-end"></nav>
<div class="bottom">
<?= $this->include(LAYOUTS[$viewDatas['layout']]['path'] . '/bottom'); ?>
</div>
<nav id="tail" class="navbar navbar-expand-lg" style="background-color:white">
<?= $this->include($viewDatas['layout']['path'] . '/../common/copyright'); ?>
</nav>
</body>
</html>

View File

@ -30,7 +30,7 @@
//참고: https://phppot.com/menu/php/learn-php/
// class가 editor인 textarea용
tinymce.init({
selector: 'textarea.editor',
selector: 'textarea.tinymce',
plugins: ['code', 'image', 'preview', 'table', 'emoticons', 'autoresize'],
height: 600,
// content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'

View File

@ -11,13 +11,13 @@
},
"require": {
"php": "^8.3",
"cloudflare/sdk": "^1.3",
"codeigniter4/framework": "^4.5",
"guzzlehttp/guzzle": "^7.9",
"phpoffice/phpspreadsheet": "^1.27",
"symfony/css-selector": "^7.1",
"symfony/dom-crawler": "^7.1",
"tinymce/tinymce": "^7.3",
"phpoffice/phpspreadsheet": "^1.27",
"cloudflare/sdk": "^1.3"
"tinymce/tinymce": "^7.3"
},
"require-dev": {
"fakerphp/faker": "^1.9",