init
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
#-------------------------
|
||||
# Operating Specific Junk Files
|
||||
#-------------------------
|
||||
|
||||
# OS X
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# OS X Thumbnails
|
||||
._*
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# Linux
|
||||
*~
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
#-------------------------
|
||||
# Environment Files
|
||||
#-------------------------
|
||||
# These should never be under version control,
|
||||
# as it poses a security risk.
|
||||
.env
|
||||
.vagrant
|
||||
Vagrantfile
|
||||
|
||||
#-------------------------
|
||||
# Temporary Files
|
||||
#-------------------------
|
||||
writable/cache/*
|
||||
!writable/cache/index.html
|
||||
|
||||
writable/logs/*
|
||||
!writable/logs/index.html
|
||||
|
||||
writable/session/*
|
||||
!writable/session/index.html
|
||||
|
||||
writable/uploads/*
|
||||
!writable/uploads/index.html
|
||||
|
||||
writable/debugbar/*
|
||||
|
||||
php_errors.log
|
||||
|
||||
#-------------------------
|
||||
# User Guide Temp Files
|
||||
#-------------------------
|
||||
user_guide_src/build/*
|
||||
user_guide_src/cilexer/build/*
|
||||
user_guide_src/cilexer/dist/*
|
||||
user_guide_src/cilexer/pycilexer.egg-info/*
|
||||
|
||||
#-------------------------
|
||||
# Test Files
|
||||
#-------------------------
|
||||
tests/coverage*
|
||||
|
||||
# Don't save phpunit under version control.
|
||||
phpunit
|
||||
|
||||
#-------------------------
|
||||
# Composer
|
||||
#-------------------------
|
||||
vendor/
|
||||
|
||||
#-------------------------
|
||||
# IDE / Development Files
|
||||
#-------------------------
|
||||
|
||||
# Modules Testing
|
||||
_modules/*
|
||||
|
||||
# phpenv local config
|
||||
.php-version
|
||||
|
||||
# Jetbrains editors (PHPStorm, etc)
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
# Netbeans
|
||||
nbproject/
|
||||
build/
|
||||
nbbuild/
|
||||
#dist/
|
||||
nbdist/
|
||||
nbactions.xml
|
||||
nb-configuration.xml
|
||||
.nb-gradle/
|
||||
|
||||
# Sublime Text
|
||||
*.tmlanguage.cache
|
||||
*.tmPreferences.cache
|
||||
*.stTheme.cache
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
.phpintel
|
||||
/api/
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/
|
||||
|
||||
/results/
|
||||
/phpunit*.xml
|
||||
/.phpunit.*.cache
|
||||
|
||||
|
||||
/public/static/node_modules
|
||||
node_modules/
|
||||
|
||||
ThirdParty/*
|
||||
ThirdParty/*/config.php
|
||||
*DB.php
|
||||
*.ini
|
||||
examples
|
||||
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2019 British Columbia Institute of Technology
|
||||
Copyright (c) 2019-2023 CodeIgniter Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1,62 @@
|
||||
# CodeIgniter 4 Application Starter
|
||||
|
||||
## What is CodeIgniter?
|
||||
|
||||
CodeIgniter is a PHP full-stack web framework that is light, fast, flexible and secure.
|
||||
More information can be found at the [official site](https://codeigniter.com).
|
||||
|
||||
This repository holds a composer-installable app starter.
|
||||
It has been built from the
|
||||
[development repository](https://github.com/codeigniter4/CodeIgniter4).
|
||||
|
||||
More information about the plans for version 4 can be found in [CodeIgniter 4](https://forum.codeigniter.com/forumdisplay.php?fid=28) on the forums.
|
||||
|
||||
The user guide corresponding to the latest version of the framework can be found
|
||||
[here](https://codeigniter4.github.io/userguide/).
|
||||
|
||||
## Installation & updates
|
||||
|
||||
`composer create-project codeigniter4/appstarter` then `composer update` whenever
|
||||
there is a new release of the framework.
|
||||
|
||||
When updating, check the release notes to see if there are any changes you might need to apply
|
||||
to your `app` folder. The affected files can be copied or merged from
|
||||
`vendor/codeigniter4/framework/app`.
|
||||
|
||||
## Setup
|
||||
|
||||
Copy `env` to `.env` and tailor for your app, specifically the baseURL
|
||||
and any database settings.
|
||||
|
||||
## Important Change with index.php
|
||||
|
||||
`index.php` is no longer in the root of the project! It has been moved inside the *public* folder,
|
||||
for better security and separation of components.
|
||||
|
||||
This means that you should configure your web server to "point" to your project's *public* folder, and
|
||||
not to the project root. A better practice would be to configure a virtual host to point there. A poor practice would be to point your web server to the project root and expect to enter *public/...*, as the rest of your logic and the
|
||||
framework are exposed.
|
||||
|
||||
**Please** read the user guide for a better explanation of how CI4 works!
|
||||
|
||||
## Repository Management
|
||||
|
||||
We use GitHub issues, in our main repository, to track **BUGS** and to track approved **DEVELOPMENT** work packages.
|
||||
We use our [forum](http://forum.codeigniter.com) to provide SUPPORT and to discuss
|
||||
FEATURE REQUESTS.
|
||||
|
||||
This repository is a "distribution" one, built by our release preparation script.
|
||||
Problems with it can be raised on our forum, or as issues in the main repository.
|
||||
|
||||
## Server Requirements
|
||||
|
||||
PHP version 7.4 or higher is required, with the following extensions installed:
|
||||
|
||||
- [intl](http://php.net/manual/en/intl.requirements.php)
|
||||
- [mbstring](http://php.net/manual/en/mbstring.installation.php)
|
||||
|
||||
Additionally, make sure that the following extensions are enabled in your PHP:
|
||||
|
||||
- json (enabled by default - don't turn it off)
|
||||
- [mysqlnd](http://php.net/manual/en/mysqlnd.install.php) if you plan to use MySQL
|
||||
- [libcurl](http://php.net/manual/en/curl.requirements.php) if you plan to use the HTTP\CURLRequest library
|
||||
@@ -0,0 +1,6 @@
|
||||
<IfModule authz_core_module>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
<IfModule !authz_core_module>
|
||||
Deny from all
|
||||
</IfModule>
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
use App\Controllers\AdvertisementManager\Automation\AutomationController;
|
||||
use App\Services\LoggerService;
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use DateTime;
|
||||
|
||||
class Automation extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The Command's Group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $group = 'CodeIgniter';
|
||||
|
||||
/**
|
||||
* The Command's Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'Automation';
|
||||
|
||||
/**
|
||||
* The Command's Description
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* The Command's Usage
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $usage = 'command:Automation [arguments] [options]';
|
||||
|
||||
/**
|
||||
* The Command's Arguments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [];
|
||||
|
||||
/**
|
||||
* The Command's Options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
/**
|
||||
* Actually execute a command.
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
$automation = new AutomationController;
|
||||
$automation->automation();
|
||||
|
||||
//로그 기록
|
||||
$data = [
|
||||
'type' => 'tasks',
|
||||
'command' => $this->name
|
||||
];
|
||||
|
||||
$logger = new LoggerService();
|
||||
$logger->insertLog($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use App\Controllers\HumanResource\HumanResourceController;
|
||||
use App\Libraries\slack_api\SlackChat;
|
||||
use App\Services\LoggerService;
|
||||
use App\ThirdParty\googleclient\GoogleCalendar; // GoogleCalendar 클래스 추가
|
||||
|
||||
|
||||
class CheckDayOff extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The Command's Group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $group = 'Slack';
|
||||
|
||||
/**
|
||||
* The Command's Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'todayDayOff';
|
||||
|
||||
/**
|
||||
* The Command's Description
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '당일 연차/시차 슬랙 전송';
|
||||
|
||||
/**
|
||||
* The Command's Usage
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $usage = 'command:dayoff [arguments] [options]';
|
||||
|
||||
/**
|
||||
* The Command's Arguments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [];
|
||||
|
||||
/**
|
||||
* The Command's Options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
private $sendList = ['개발팀', '디자인실', '운영실'];
|
||||
|
||||
/**
|
||||
* Actually execute a command.
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
$sendType = "";
|
||||
if(isset($params[0]))
|
||||
$sendType = $params[0];
|
||||
$Tdate = date('Ymd'); //기본값은 오늘
|
||||
if(isset($params[1]) && preg_match('/^\d{8}$/', $params[1])) $Tdate = $params[1];
|
||||
$dayOff = new HumanResourceController();
|
||||
$lists = $dayOff->getTodayDayOff($Tdate);
|
||||
$slack = new SlackChat();
|
||||
$googleCalendar = new GoogleCalendar(); // GoogleCalendar 인스턴스 생성
|
||||
$msg = [];
|
||||
$now = date('H');
|
||||
foreach($lists as $row) {
|
||||
if($now == "10" || $sendType == 'today') { //업무시작시간에 당일 연/시차 전체 전송
|
||||
if(date('Ymd', strtotime($row['start'])) != $Tdate) continue;
|
||||
} else { //그 외 매시간 새로 등록된 당일 연/시차 전송
|
||||
if(date('Ymd', strtotime($row['start'])) != $Tdate || strtotime($row['datetime']) <= strtotime('-1 hour')) continue;
|
||||
}
|
||||
if($row['type'] == '시차') {
|
||||
$start = date('Y년m월d일 H시부터', strtotime($row['start']));
|
||||
$end = date('H시까지', strtotime($row['end']));
|
||||
$term = "{$start} {$end}({$row['term']}시간)";
|
||||
$remain = "잔여:{$row['total_remain']}시간";
|
||||
if(date('H', strtotime($row['start'])) == 10)
|
||||
$term = date('Y년m월d일 H시', strtotime($row['end']))." 출근({$row['term']}시간 사용)";
|
||||
if(date('H', strtotime($row['end'])) == 19)
|
||||
$term = date('Y년m월d일 H시', strtotime($row['start']))." 퇴근({$row['term']}시간 사용)";
|
||||
if($row['total_remain'] <= 0) {
|
||||
$data = [
|
||||
'channel' => $row['name'],
|
||||
'text' => "{$row['name']}님, 시차 잔여량이 부족합니다. [{$remain}]",
|
||||
];
|
||||
$slack->sendMessage($data);
|
||||
}
|
||||
} else {
|
||||
$start = date('Y년m월d일부터', strtotime($row['start']));
|
||||
$end = date('Y년m월d일까지', strtotime($row['end']));
|
||||
$remain = "사용:{$row['total_used']}일/잔여:{$row['total_remain']}일";
|
||||
$term = "{$start} {$end}({$row['term']}일)";
|
||||
if($row['start'] == $row['end'])
|
||||
$term = date('Y년m월d일', strtotime($row['start']));
|
||||
}
|
||||
// Google Calendar 이벤트 생성
|
||||
$eventData = [
|
||||
'summary' => "[{$row['type']}]{$row['name']}({$row['team']})",
|
||||
'description' => "{$term}",
|
||||
];
|
||||
if ($row['type'] == '연차' || $row['type'] == '출산휴가' || $row['type'] == '예비군훈련') {
|
||||
$eventData['start'] = [
|
||||
'date' => date('Y-m-d', strtotime($row['start'])),
|
||||
];
|
||||
$eventData['end'] = [
|
||||
'date' => date('Y-m-d', strtotime($row['end'] . ' +1 day')),
|
||||
];
|
||||
$eventData['colorId'] = '11';
|
||||
} else {
|
||||
$eventData['start'] = [
|
||||
'dateTime' => date('Y-m-d\TH:00:00P', strtotime($row['start'])),
|
||||
];
|
||||
$eventData['end'] = [
|
||||
'dateTime' => date('Y-m-d\TH:00:00P', strtotime($row['end'])),
|
||||
];
|
||||
//type에 생일휴가 또는 오후가 포함되어 있을 경우 start, end를 각각 당일 15시, 19시로 강제로 조정
|
||||
if(strpos($row['type'], '생일휴가') !== false || strpos($row['type'], '오후') !== false) {
|
||||
$eventData['start']['dateTime'] = date('Y-m-d\T15:00:00P', strtotime($row['start']));
|
||||
$eventData['end']['dateTime'] = date('Y-m-d\T19:00:00P', strtotime($row['end']));
|
||||
}
|
||||
//type에 오전 포함되어 있을 경우 start, end를 각각 당일 10시, 15시로 강제로 조정
|
||||
if(strpos($row['type'], '오전') !== false) {
|
||||
$eventData['start']['dateTime'] = date('Y-m-d\T10:00:00P', strtotime($row['start']));
|
||||
$eventData['end']['dateTime'] = date('Y-m-d\T15:00:00P', strtotime($row['end']));
|
||||
}
|
||||
$eventData['colorId'] = '5';
|
||||
}
|
||||
$googleCalendar->createEvent($eventData); // 이벤트 생성 메서드 호출
|
||||
$slackMsg = [
|
||||
"type" => "section",
|
||||
"text" => [
|
||||
"type" => "mrkdwn",
|
||||
"text" => "*{$row['name']}* _({$row['team']})_ [{$remain}]\n`[{$row['type']}]` {$term}"
|
||||
]
|
||||
];
|
||||
$msg['연차공유'][] = ["type"=>"divider"];
|
||||
$msg['연차공유'][] = $slackMsg;
|
||||
$msg['연차알림'][] = ["type"=>"divider"];
|
||||
$msg['연차알림'][] = $slackMsg;
|
||||
foreach($this->sendList as $list) {
|
||||
if($list != $row['team'] && $list != $row['division']) continue;
|
||||
$msg[$list][] = ["type"=>"divider"];
|
||||
$msg[$list][] = $slackMsg;
|
||||
}
|
||||
}
|
||||
if(!count($msg)) return;
|
||||
if($sendType == 'debug') dd($msg);
|
||||
foreach($msg as $channel => $row) {
|
||||
if(preg_match('/.+(팀|실)/', $channel))
|
||||
$channel = $channel."_연차공유";
|
||||
$data = [
|
||||
'channel' => $channel,
|
||||
'text' => '',
|
||||
'blocks' => json_encode($row,JSON_UNESCAPED_UNICODE)
|
||||
];
|
||||
// d($data);
|
||||
$response = $slack->sendMessage($data);
|
||||
}
|
||||
|
||||
//로그 기록
|
||||
$data = [
|
||||
'type' => 'tasks',
|
||||
'command' => $this->name
|
||||
];
|
||||
|
||||
$logger = new LoggerService();
|
||||
$logger->insertLog($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
|
||||
class Encryption extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The Command's Group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $group = 'Encryption';
|
||||
|
||||
/**
|
||||
* The Command's Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'encryption';
|
||||
|
||||
/**
|
||||
* The Command's Description
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '데이터 암호화/복호화';
|
||||
|
||||
/**
|
||||
* The Command's Usage
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $usage = 'command:name [arguments] [options]';
|
||||
|
||||
/**
|
||||
* The Command's Arguments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [
|
||||
'type' => 'Set encrypt/decrypt',
|
||||
'text' => 'Encrypt(Decrypt) for Text',
|
||||
'key' => 'Encrypt(Decrypt) for Key'
|
||||
];
|
||||
|
||||
/**
|
||||
* The Command's Options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
protected $encrypter;
|
||||
protected $key = 'f907464a49e95e8d778cf87374cc59ccd7669f5924e25776320ec69479206a22';
|
||||
|
||||
/**
|
||||
* Actually execute a command.
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
if(!isset($params[0]))
|
||||
throw new \Exception('"encrypt"또는"decrypt"를 지정해주세요.');
|
||||
if(!isset($params[1]))
|
||||
throw new \Exception('암호화(복호화) 할 문자를 입력해주세요.');
|
||||
|
||||
$type = $params[0];
|
||||
$this->encrypter = \Config\Services::encrypter();
|
||||
switch($type) {
|
||||
case 'encrypt' :
|
||||
$result = $this->encrypt($params[1]);
|
||||
break;
|
||||
case 'decrypt' :
|
||||
$result = $this->decrypt($params[1]);
|
||||
break;
|
||||
case 'sodium_encrypt' :
|
||||
$result = $this->sodium_encrypt($params[1]);
|
||||
break;
|
||||
case 'sodium_decrypt' :
|
||||
$result = $this->sodium_decrypt($params[1]);
|
||||
break;
|
||||
default :
|
||||
throw new \RuntimeException('"encrypt"또는"decrypt"를 지정해주세요.');
|
||||
break;
|
||||
}
|
||||
var_dump($result);
|
||||
}
|
||||
|
||||
private function encrypt($text) {
|
||||
$result = $this->encrypter->encrypt($text);
|
||||
return sodium_bin2hex($result);
|
||||
}
|
||||
|
||||
private function decrypt($text) {
|
||||
$text = sodium_hex2bin($text);
|
||||
return $this->encrypter->decrypt($text);
|
||||
}
|
||||
|
||||
private function sodium_encrypt($text) {
|
||||
// create a nonce for this operation
|
||||
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); // 24 bytes
|
||||
|
||||
$data = sodium_pad($text, 16);
|
||||
|
||||
// encrypt message and combine with nonce
|
||||
$ciphertext = $nonce . sodium_crypto_secretbox($data, $nonce, sodium_hex2bin($this->key));
|
||||
|
||||
// cleanup buffers
|
||||
sodium_memzero($data);
|
||||
sodium_memzero($this->key);
|
||||
|
||||
return sodium_bin2hex($ciphertext);
|
||||
}
|
||||
|
||||
private function sodium_decrypt($text) {
|
||||
$text = sodium_hex2bin($text);
|
||||
// Extract info from encrypted data
|
||||
$nonce = mb_substr($text, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
|
||||
$ciphertext = mb_substr($text, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
|
||||
|
||||
// decrypt data
|
||||
$data = sodium_crypto_secretbox_open($ciphertext, $nonce, sodium_hex2bin($this->key));
|
||||
$data = sodium_unpad($data,16);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
use App\Services\LoggerService;
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
|
||||
class EventCron extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The Command's Group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $group = 'cron';
|
||||
|
||||
/**
|
||||
* The Command's Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'EventCron';
|
||||
|
||||
/**
|
||||
* The Command's Description
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* Actually execute a command.
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
CLI::write('DB수 업데이트 작업을 시작합니다.', 'green');
|
||||
try {
|
||||
$zenith = \Config\Database::connect();
|
||||
$sql = "SELECT event_seq, site, count(*) AS db_count, DATE(reg_date) AS date FROM event_leads WHERE status = 1 GROUP BY event_seq, site, DATE(reg_date)";
|
||||
$result = $zenith->query($sql)->getResultArray();
|
||||
$data = [];
|
||||
|
||||
foreach($result as $row) {
|
||||
$data[] = "('{$row['event_seq']}', '{$row['site']}', '{$row['date']}', '{$row['db_count']}', NOW())";
|
||||
}
|
||||
|
||||
$sql = "INSERT INTO event_leads_count(seq, site, date, db_count, update_time) VALUES ".implode(',', $data)." ON DUPLICATE KEY
|
||||
UPDATE db_count = VALUES(db_count), update_time = VALUES(update_time)";
|
||||
$result = $zenith->query($sql);
|
||||
CLI::write('DB수 업데이트 작업 완료', 'green');
|
||||
} catch (\Exception $e) {
|
||||
$this->showError($e);
|
||||
}
|
||||
|
||||
//로그 기록
|
||||
$data = [
|
||||
'type' => 'tasks',
|
||||
'command' => $this->name
|
||||
];
|
||||
|
||||
$logger = new LoggerService();
|
||||
$logger->insertLog($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
use App\Controllers\Api\JiraController;
|
||||
use App\Services\LoggerService;
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
|
||||
class EventDataUpdateCron extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The Command's Group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $group = 'CodeIgniter';
|
||||
|
||||
/**
|
||||
* The Command's Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'EventDataUpdateCron';
|
||||
|
||||
/**
|
||||
* The Command's Description
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* The Command's Usage
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $usage = 'command:EventDataUpdateCron [arguments] [options]';
|
||||
|
||||
/**
|
||||
* The Command's Arguments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [];
|
||||
|
||||
/**
|
||||
* The Command's Options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
/**
|
||||
* Actually execute a command.
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
$jira = new JiraController;
|
||||
$jira->getIssueEventData();
|
||||
|
||||
//로그 기록
|
||||
$data = [
|
||||
'type' => 'tasks',
|
||||
'command' => $this->name
|
||||
];
|
||||
|
||||
$logger = new LoggerService();
|
||||
$logger->insertLog($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use App\Controllers\EventManage\AdvertiserController;
|
||||
use App\Services\LoggerService;
|
||||
|
||||
class EvtOverwatch extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The Command's Group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $group = 'cron';
|
||||
|
||||
/**
|
||||
* The Command's Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'EvtOverwatch';
|
||||
|
||||
/**
|
||||
* The Command's Description
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* Actually execute a command.
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
CLI::write('그룹웨어 데이터 연동 작업을 시작합니다.', 'green');
|
||||
try{
|
||||
$advertiser = new AdvertiserController();
|
||||
$advertiser->evtOverwatch();
|
||||
CLI::write('오버워치 실행 완료', 'green');
|
||||
} catch (\Exception $e) {
|
||||
$this->showError($e);
|
||||
}
|
||||
|
||||
//로그 기록
|
||||
$data = [
|
||||
'type' => 'tasks',
|
||||
'command' => $this->name
|
||||
];
|
||||
|
||||
$logger = new LoggerService();
|
||||
$logger->insertLog($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use App\Controllers\HumanResource\HumanResourceController;
|
||||
use App\Services\LoggerService;
|
||||
|
||||
class GwCron extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The Command's Group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $group = 'cron';
|
||||
|
||||
/**
|
||||
* The Command's Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'GwCron';
|
||||
|
||||
/**
|
||||
* The Command's Description
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* Actually execute a command.
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
CLI::write('그룹웨어 데이터 연동 작업을 시작합니다.', 'green');
|
||||
try{
|
||||
$hr = new HumanResourceController();
|
||||
$hr->updateUsersByDouzone();
|
||||
CLI::write('그룹웨어 데이터 연동 작업 완료', 'green');
|
||||
} catch (\Exception $e) {
|
||||
$this->showError($e);
|
||||
}
|
||||
|
||||
//로그 기록
|
||||
$data = [
|
||||
'type' => 'tasks',
|
||||
'command' => $this->name
|
||||
];
|
||||
|
||||
$logger = new LoggerService();
|
||||
$logger->insertLog($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use App\Controllers\HumanResource\HumanResourceController;
|
||||
use App\Services\LoggerService;
|
||||
|
||||
class HumanResource extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The Command's Group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $group = 'cron';
|
||||
|
||||
/**
|
||||
* The Command's Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'HumanResource';
|
||||
|
||||
/**
|
||||
* The Command's Description
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* Actually execute a command.
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
CLI::write('그룹웨어 데이터 연동 작업을 시작합니다.', 'green');
|
||||
try{
|
||||
$hr = new HumanResourceController();
|
||||
$hr->gwData();
|
||||
CLI::write('그룹웨어 데이터 연동 작업 완료', 'green');
|
||||
} catch (\Exception $e) {
|
||||
$this->showError($e);
|
||||
}
|
||||
|
||||
//로그 기록
|
||||
$data = [
|
||||
'type' => 'tasks',
|
||||
'command' => $this->name
|
||||
];
|
||||
|
||||
$logger = new LoggerService();
|
||||
$logger->insertLog($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
use App\Controllers\Api\JiraController;
|
||||
use App\Services\LoggerService;
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
|
||||
class PreparingIssueMessageCron extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The Command's Group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $group = 'CodeIgniter';
|
||||
|
||||
/**
|
||||
* The Command's Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'PreparingIssueMessage';
|
||||
|
||||
/**
|
||||
* The Command's Description
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* The Command's Usage
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $usage = 'command:PreparingIssueMessage [arguments] [options]';
|
||||
|
||||
/**
|
||||
* The Command's Arguments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [];
|
||||
|
||||
/**
|
||||
* The Command's Options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
/**
|
||||
* Actually execute a command.
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
$hour = date('G');
|
||||
$week = date('w');
|
||||
if($hour < "10" || $hour >= "19" || $week == "0" || $week == "6") return;
|
||||
$jira = new JiraController;
|
||||
$jira->getIssuePreparing();
|
||||
|
||||
//로그 기록
|
||||
$data = [
|
||||
'type' => 'tasks',
|
||||
'command' => $this->name
|
||||
];
|
||||
|
||||
$logger = new LoggerService();
|
||||
$logger->insertLog($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
use CodeIgniter\CLI\BaseCommand;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use DateTime;
|
||||
|
||||
class ZenithLogTable extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The Command's Group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $group = 'CodeIgniter';
|
||||
|
||||
/**
|
||||
* The Command's Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'ZenithLogTable';
|
||||
|
||||
/**
|
||||
* The Command's Description
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* The Command's Usage
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $usage = 'command:name [arguments] [options]';
|
||||
|
||||
/**
|
||||
* The Command's Arguments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [];
|
||||
|
||||
/**
|
||||
* The Command's Options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
/**
|
||||
* Actually execute a command.
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function run(array $params)
|
||||
{
|
||||
$db = \Config\Database::connect();
|
||||
$nextMonth = date('Ym', strtotime('+1 month'));
|
||||
$tableName = 'zenith_logs_'.$nextMonth;
|
||||
$sql = "CREATE TABLE `$tableName` (
|
||||
`seq` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`type` VARCHAR(100),
|
||||
`scheme` VARCHAR(100),
|
||||
`host` VARCHAR(255),
|
||||
`path` VARCHAR(255),
|
||||
`method` VARCHAR(100),
|
||||
`command` VARCHAR(255),
|
||||
`query_string` TEXT,
|
||||
`data` TEXT,
|
||||
`content_type` VARCHAR(100),
|
||||
`remote_addr` VARCHAR(100),
|
||||
`server_addr` VARCHAR(100),
|
||||
`nickname` VARCHAR(100),
|
||||
`datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`seq`),
|
||||
KEY `zenith_logs_type_IDX` (`type`) USING BTREE,
|
||||
KEY `zenith_logs_path_IDX` (`path`) USING BTREE,
|
||||
KEY `zenith_logs_method_IDX` (`method`) USING BTREE,
|
||||
KEY `zenith_logs_nickname_IDX` (`nickname`) USING BTREE,
|
||||
KEY `zenith_logs_datetime_IDX` (`datetime`) USING BTREE
|
||||
)";
|
||||
$db->query($sql);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The goal of this file is to allow developers a location
|
||||
* where they can overwrite core procedural functions and
|
||||
* replace them with their own. This file is loaded during
|
||||
* the bootstrap process and is called during the framework's
|
||||
* execution.
|
||||
*
|
||||
* This can be looked at as a `master helper` file that is
|
||||
* loaded early on, and may also contain additional functions
|
||||
* that you'd like to use throughout your entire application
|
||||
*
|
||||
* @see: https://codeigniter4.github.io/CodeIgniter4/
|
||||
*/
|
||||
@@ -0,0 +1,360 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Session\Handlers\FileHandler;
|
||||
|
||||
class App extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Base Site URL
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* URL to your CodeIgniter root. Typically this will be your base URL,
|
||||
* WITH a trailing slash:
|
||||
*
|
||||
* http://example.com/
|
||||
*
|
||||
* If this is not set then CodeIgniter will try guess the protocol, domain
|
||||
* and path to your installation. However, you should always configure this
|
||||
* explicitly and never rely on auto-guessing, especially in production
|
||||
* environments.
|
||||
*/
|
||||
public string $baseURL = 'http://localhost:8080/';
|
||||
|
||||
/**
|
||||
* Allowed Hostnames in the Site URL other than the hostname in the baseURL.
|
||||
* If you want to accept multiple Hostnames, set this.
|
||||
*
|
||||
* E.g. When your site URL ($baseURL) is 'http://example.com/', and your site
|
||||
* also accepts 'http://media.example.com/' and
|
||||
* 'http://accounts.example.com/':
|
||||
* ['media.example.com', 'accounts.example.com']
|
||||
*
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
public array $allowedHostnames = [];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Index File
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Typically this will be your index.php file, unless you've renamed it to
|
||||
* something else. If you are using mod_rewrite to remove the page set this
|
||||
* variable so that it is blank.
|
||||
*/
|
||||
// public string $indexPage = 'index.php';
|
||||
public string $indexPage = '';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* URI PROTOCOL
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* This item determines which server global should be used to retrieve the
|
||||
* URI string. The default setting of 'REQUEST_URI' works for most servers.
|
||||
* If your links do not seem to work, try one of the other delicious flavors:
|
||||
*
|
||||
* 'REQUEST_URI' Uses $_SERVER['REQUEST_URI']
|
||||
* 'QUERY_STRING' Uses $_SERVER['QUERY_STRING']
|
||||
* 'PATH_INFO' Uses $_SERVER['PATH_INFO']
|
||||
*
|
||||
* WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded!
|
||||
*/
|
||||
public string $uriProtocol = 'PATH_INFO';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Default Locale
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The Locale roughly represents the language and location that your visitor
|
||||
* is viewing the site from. It affects the language strings and other
|
||||
* strings (like currency markers, numbers, etc), that your program
|
||||
* should run under for this request.
|
||||
*/
|
||||
public string $defaultLocale = 'ko';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Negotiate Locale
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If true, the current Request object will automatically determine the
|
||||
* language to use based on the value of the Accept-Language header.
|
||||
*
|
||||
* If false, no automatic detection will be performed.
|
||||
*/
|
||||
public bool $negotiateLocale = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Supported Locales
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If $negotiateLocale is true, this array lists the locales supported
|
||||
* by the application in descending order of priority. If no match is
|
||||
* found, the first locale will be used.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public array $supportedLocales = ['ko'];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Application Timezone
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The default timezone that will be used in your application to display
|
||||
* dates with the date helper, and can be retrieved through app_timezone()
|
||||
*/
|
||||
public string $appTimezone = 'Asia/Seoul';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Default Character Set
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* This determines which character set is used by default in various methods
|
||||
* that require a character set to be provided.
|
||||
*
|
||||
* @see http://php.net/htmlspecialchars for a list of supported charsets.
|
||||
*/
|
||||
public string $charset = 'UTF-8';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* URI PROTOCOL
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If true, this will force every request made to this application to be
|
||||
* made via a secure connection (HTTPS). If the incoming request is not
|
||||
* secure, the user will be redirected to a secure version of the page
|
||||
* and the HTTP Strict Transport Security header will be set.
|
||||
*/
|
||||
public bool $forceGlobalSecureRequests = false;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Cookie Name
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The session cookie name, must contain only [0-9a-z_-] characters
|
||||
*
|
||||
* @deprecated use Config\Session::$cookieName instead.
|
||||
*/
|
||||
public string $sessionCookieName = 'ci_session';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Expiration
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The number of SECONDS you want the session to last.
|
||||
* Setting to 0 (zero) means expire when the browser is closed.
|
||||
*
|
||||
* @deprecated use Config\Session::$expiration instead.
|
||||
*/
|
||||
public int $sessionExpiration = 7200;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Save Path
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The location to save sessions to and is driver dependent.
|
||||
*
|
||||
* For the 'files' driver, it's a path to a writable directory.
|
||||
* WARNING: Only absolute paths are supported!
|
||||
*
|
||||
* For the 'database' driver, it's a table name.
|
||||
* Please read up the manual for the format with other session drivers.
|
||||
*
|
||||
* IMPORTANT: You are REQUIRED to set a valid save path!
|
||||
*
|
||||
* @deprecated use Config\Session::$savePath instead.
|
||||
*/
|
||||
public string $sessionSavePath = WRITEPATH . 'session';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Match IP
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Whether to match the user's IP address when reading the session data.
|
||||
*
|
||||
* WARNING: If you're using the database driver, don't forget to update
|
||||
* your session table's PRIMARY KEY when changing this setting.
|
||||
*
|
||||
* @deprecated use Config\Session::$matchIP instead.
|
||||
*/
|
||||
public bool $sessionMatchIP = false;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Time to Update
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* How many seconds between CI regenerating the session ID.
|
||||
*
|
||||
* @deprecated use Config\Session::$timeToUpdate instead.
|
||||
*/
|
||||
public int $sessionTimeToUpdate = 300;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Regenerate Destroy
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Whether to destroy session data associated with the old session ID
|
||||
* when auto-regenerating the session ID. When set to FALSE, the data
|
||||
* will be later deleted by the garbage collector.
|
||||
*
|
||||
* @deprecated use Config\Session::$regenerateDestroy instead.
|
||||
*/
|
||||
public bool $sessionRegenerateDestroy = false;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie Domain
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Set to `.your-domain.com` for site-wide cookies.
|
||||
*
|
||||
* @deprecated use Config\Cookie::$domain property instead.
|
||||
*/
|
||||
public string $cookieDomain = '';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie Path
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Typically will be a forward slash.
|
||||
*
|
||||
* @deprecated use Config\Cookie::$path property instead.
|
||||
*/
|
||||
public string $cookiePath = '/';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie Secure
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Cookie will only be set if a secure HTTPS connection exists.
|
||||
*
|
||||
* @deprecated use Config\Cookie::$secure property instead.
|
||||
*/
|
||||
public bool $cookieSecure = false;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie HttpOnly
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Cookie will only be accessible via HTTP(S) (no JavaScript).
|
||||
*
|
||||
* @deprecated use Config\Cookie::$httponly property instead.
|
||||
*/
|
||||
public bool $cookieHTTPOnly = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Reverse Proxy IPs
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If your server is behind a reverse proxy, you must whitelist the proxy
|
||||
* IP addresses from which CodeIgniter should trust headers such as
|
||||
* X-Forwarded-For or Client-IP in order to properly identify
|
||||
* the visitor's IP address.
|
||||
*
|
||||
* You need to set a proxy IP address or IP address with subnets and
|
||||
* the HTTP header for the client IP address.
|
||||
*
|
||||
* Here are some examples:
|
||||
* [
|
||||
* '10.0.1.200' => 'X-Forwarded-For',
|
||||
* '192.168.5.0/24' => 'X-Real-IP',
|
||||
* ]
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $proxyIPs = [];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Header Name
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The header name.
|
||||
*
|
||||
* @deprecated Use `Config\Security` $headerName property instead of using this property.
|
||||
*/
|
||||
public string $CSRFHeaderName = 'X-CSRF-TOKEN';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Cookie Name
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The cookie name.
|
||||
*
|
||||
* @deprecated Use `Config\Security` $cookieName property instead of using this property.
|
||||
*/
|
||||
public string $CSRFCookieName = 'csrf_cookie_name';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Expire
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The number in seconds the token should expire.
|
||||
*
|
||||
* @deprecated Use `Config\Security` $expire property instead of using this property.
|
||||
*/
|
||||
public int $CSRFExpire = 7200;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Regenerate
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Regenerate token on every submission?
|
||||
*
|
||||
* @deprecated Use `Config\Security` $regenerate property instead of using this property.
|
||||
*/
|
||||
public bool $CSRFRegenerate = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Redirect
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Redirect to previous page with error on failure?
|
||||
*
|
||||
* @deprecated Use `Config\Security` $redirect property instead of using this property.
|
||||
*/
|
||||
public bool $CSRFRedirect = false;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Content Security Policy
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Enables the Response's Content Secure Policy to restrict the sources that
|
||||
* can be used for images, scripts, CSS files, audio, video, etc. If enabled,
|
||||
* the Response object will populate default values for the policy from the
|
||||
* `ContentSecurityPolicy.php` file. Controllers can always add to those
|
||||
* restrictions at run time.
|
||||
*
|
||||
* For a better understanding of CSP, see these documents:
|
||||
*
|
||||
* @see http://www.html5rocks.com/en/tutorials/security/content-security-policy/
|
||||
* @see http://www.w3.org/TR/CSP/
|
||||
*/
|
||||
public bool $CSPEnabled = false;
|
||||
}
|
||||
@@ -0,0 +1,474 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Shield\Config\Auth as ShieldAuth;
|
||||
use CodeIgniter\Shield\Authentication\Actions\ActionInterface;
|
||||
use CodeIgniter\Shield\Authentication\AuthenticatorInterface;
|
||||
use CodeIgniter\Shield\Authentication\Authenticators\AccessTokens;
|
||||
use CodeIgniter\Shield\Authentication\Authenticators\Session;
|
||||
use CodeIgniter\Shield\Authentication\Passwords\CompositionValidator;
|
||||
use CodeIgniter\Shield\Authentication\Passwords\DictionaryValidator;
|
||||
use CodeIgniter\Shield\Authentication\Passwords\NothingPersonalValidator;
|
||||
use CodeIgniter\Shield\Authentication\Passwords\PwnedValidator;
|
||||
use CodeIgniter\Shield\Authentication\Passwords\ValidatorInterface;
|
||||
use CodeIgniter\Shield\Models\UserModel;
|
||||
|
||||
class Auth extends ShieldAuth
|
||||
{
|
||||
/**
|
||||
* ////////////////////////////////////////////////////////////////////
|
||||
* AUTHENTICATION
|
||||
* ////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
public array $views = [
|
||||
'login' => '\App\Views\auth\login',
|
||||
'register' => '\App\Views\auth\register',
|
||||
'layout' => '\App\Views\templates\header',
|
||||
'action_email_2fa' => '\App\Views\auth\email_2fa_show',
|
||||
'action_email_2fa_verify' => '\App\Views\auth\email_2fa_verify',
|
||||
'action_email_2fa_email' => '\App\Views\auth\email\email_2fa_email',
|
||||
'action_email_activate_show' => '\App\Views\auth\email_activate_show',
|
||||
'action_email_activate_email' => '\App\Views\auth\email\email_activate_email',
|
||||
'magic-link-login' => '\App\Views\auth\magic_link_form',
|
||||
'magic-link-message' => '\App\Views\auth\magic_link_message',
|
||||
'magic-link-email' => '\App\Views\auth\email\magic_link_email',
|
||||
'set-password' => '\App\Views\auth\set_password',
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Redirect URLs
|
||||
* --------------------------------------------------------------------
|
||||
* The default URL that a user will be redirected to after various auth
|
||||
* auth actions. This can be either of the following:
|
||||
*
|
||||
* 1. An absolute URL. E.g. http://example.com OR https://example.com
|
||||
* 2. A named route that can be accessed using `route_to()` or `url_to()`
|
||||
* 3. A URI path within the application. e.g 'admin', 'login', 'expath'
|
||||
*
|
||||
* If you need more flexibility you can override the `getUrl()` method
|
||||
* to apply any logic you may need.
|
||||
*/
|
||||
public array $redirects = [
|
||||
'register' => '/',
|
||||
'login' => '/',
|
||||
'logout' => 'login',
|
||||
'force_reset' => '/set-password',
|
||||
'permission_denied' => '/',
|
||||
'group_denied' => '/',
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Authentication Actions
|
||||
* --------------------------------------------------------------------
|
||||
* Specifies the class that represents an action to take after
|
||||
* the user logs in or registers a new account at the site.
|
||||
*
|
||||
* You must register actions in the order of the actions to be performed.
|
||||
*
|
||||
* Available actions with Shield:
|
||||
* - register: \CodeIgniter\Shield\Authentication\Actions\EmailActivator::class
|
||||
* - login: \CodeIgniter\Shield\Authentication\Actions\Email2FA::class
|
||||
*
|
||||
* @var array<string, class-string<ActionInterface>|null>
|
||||
*/
|
||||
public array $actions = [
|
||||
'register' => null,//\CodeIgniter\Shield\Authentication\Actions\EmailActivator::class
|
||||
'login' => null,
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Authenticators
|
||||
* --------------------------------------------------------------------
|
||||
* The available authentication systems, listed
|
||||
* with alias and class name. These can be referenced
|
||||
* by alias in the auth helper:
|
||||
* auth('tokens')->attempt($credentials);
|
||||
*
|
||||
* @var array<string, class-string<AuthenticatorInterface>>
|
||||
*/
|
||||
public array $authenticators = [
|
||||
'tokens' => AccessTokens::class,
|
||||
'session' => Session::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Name of Authenticator Header
|
||||
* --------------------------------------------------------------------
|
||||
* The name of Header that the Authorization token should be found.
|
||||
* According to the specs, this should be `Authorization`, but rare
|
||||
* circumstances might need a different header.
|
||||
*/
|
||||
public array $authenticatorHeader = [
|
||||
'tokens' => 'Authorization',
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Unused Token Lifetime
|
||||
* --------------------------------------------------------------------
|
||||
* Determines the amount of time, in seconds, that an unused
|
||||
* access token can be used.
|
||||
*/
|
||||
public int $unusedTokenLifetime = YEAR;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Default Authenticator
|
||||
* --------------------------------------------------------------------
|
||||
* The Authenticator to use when none is specified.
|
||||
* Uses the $key from the $authenticators array above.
|
||||
*/
|
||||
public string $defaultAuthenticator = 'session';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Authentication Chain
|
||||
* --------------------------------------------------------------------
|
||||
* The Authenticators to test logged in status against
|
||||
* when using the 'chain' filter. Each Authenticator listed will be checked.
|
||||
* If no match is found, then the next in the chain will be checked.
|
||||
*
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
public array $authenticationChain = [
|
||||
'session',
|
||||
'tokens',
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Allow Registration
|
||||
* --------------------------------------------------------------------
|
||||
* Determines whether users can register for the site.
|
||||
*/
|
||||
public bool $allowRegistration = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Record Last Active Date
|
||||
* --------------------------------------------------------------------
|
||||
* If true, will always update the `last_active` datetime for the
|
||||
* logged in user on every page request.
|
||||
*/
|
||||
public bool $recordActiveDate = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Allow Magic Link Logins
|
||||
* --------------------------------------------------------------------
|
||||
* If true, will allow the use of "magic links" sent via the email
|
||||
* as a way to log a user in without the need for a password.
|
||||
* By default, this is used in place of a password reset flow, but
|
||||
* could be modified as the only method of login once an account
|
||||
* has been set up.
|
||||
*/
|
||||
public bool $allowMagicLinkLogins = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Magic Link Lifetime
|
||||
* --------------------------------------------------------------------
|
||||
* Specifies the amount of time, in seconds, that a magic link is valid.
|
||||
* You can use Time Constants or any desired number.
|
||||
*/
|
||||
public int $magicLinkLifetime = HOUR;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Session Authenticator Configuration
|
||||
* --------------------------------------------------------------------
|
||||
* These settings only apply if you are using the Session Authenticator
|
||||
* for authentication.
|
||||
*
|
||||
* - field The name of the key the current user info is stored in session
|
||||
* - allowRemembering Does the system allow use of "remember-me"
|
||||
* - rememberCookieName The name of the cookie to use for "remember-me"
|
||||
* - rememberLength The length of time, in seconds, to remember a user.
|
||||
*
|
||||
* @var array<string, bool|int|string>
|
||||
*/
|
||||
public array $sessionConfig = [
|
||||
'field' => 'user',
|
||||
'allowRemembering' => true,
|
||||
'rememberCookieName' => 'remember',
|
||||
'rememberLength' => 30 * DAY,
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Minimum Password Length
|
||||
* --------------------------------------------------------------------
|
||||
* The minimum length that a password must be to be accepted.
|
||||
* Recommended minimum value by NIST = 8 characters.
|
||||
*/
|
||||
public int $minimumPasswordLength = 8;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Password Check Helpers
|
||||
* --------------------------------------------------------------------
|
||||
* The PasswordValidator class runs the password through all of these
|
||||
* classes, each getting the opportunity to pass/fail the password.
|
||||
* You can add custom classes as long as they adhere to the
|
||||
* CodeIgniter\Shield\Authentication\Passwords\ValidatorInterface.
|
||||
*
|
||||
* @var class-string<ValidatorInterface>[]
|
||||
*/
|
||||
public array $passwordValidators = [
|
||||
CompositionValidator::class, // 비밀번호가 8자리 이상
|
||||
NothingPersonalValidator::class, // 비밀번호에 개인 정보(예: 이메일, 사용자 이름)가 포함되지 않았는지 확인합니다.
|
||||
DictionaryValidator::class, // 비밀번호가 사전에 있는 단어와 일치하지 않는지 확인합니다.
|
||||
// PwnedValidator::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Valid login fields
|
||||
* --------------------------------------------------------------------
|
||||
* Fields that are available to be used as credentials for login.
|
||||
*/
|
||||
public array $validFields = [
|
||||
'email',
|
||||
'username',
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Additional Fields for "Nothing Personal"
|
||||
* --------------------------------------------------------------------
|
||||
* The NothingPersonalValidator prevents personal information from
|
||||
* being used in passwords. The email and username fields are always
|
||||
* considered by the validator. Do not enter those field names here.
|
||||
*
|
||||
* An extended User Entity might include other personal info such as
|
||||
* first and/or last names. $personalFields is where you can add
|
||||
* fields to be considered as "personal" by the NothingPersonalValidator.
|
||||
* For example:
|
||||
* $personalFields = ['firstname', 'lastname'];
|
||||
*/
|
||||
public array $personalFields = [];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Password / Username Similarity
|
||||
* --------------------------------------------------------------------
|
||||
* Among other things, the NothingPersonalValidator checks the
|
||||
* amount of sameness between the password and username.
|
||||
* Passwords that are too much like the username are invalid.
|
||||
*
|
||||
* The value set for $maxSimilarity represents the maximum percentage
|
||||
* of similarity at which the password will be accepted. In other words, any
|
||||
* calculated similarity equal to, or greater than $maxSimilarity
|
||||
* is rejected.
|
||||
*
|
||||
* The accepted range is 0-100, with 0 (zero) meaning don't check similarity.
|
||||
* Using values at either extreme of the *working range* (1-100) is
|
||||
* not advised. The low end is too restrictive and the high end is too permissive.
|
||||
* The suggested value for $maxSimilarity is 50.
|
||||
*
|
||||
* You may be thinking that a value of 100 should have the effect of accepting
|
||||
* everything like a value of 0 does. That's logical and probably true,
|
||||
* but is unproven and untested. Besides, 0 skips the work involved
|
||||
* making the calculation unlike when using 100.
|
||||
*
|
||||
* The (admittedly limited) testing that's been done suggests a useful working range
|
||||
* of 50 to 60. You can set it lower than 50, but site users will probably start
|
||||
* to complain about the large number of proposed passwords getting rejected.
|
||||
* At around 60 or more it starts to see pairs like 'captain joe' and 'joe*captain' as
|
||||
* perfectly acceptable which clearly they are not.
|
||||
*
|
||||
* To disable similarity checking set the value to 0.
|
||||
* public $maxSimilarity = 0;
|
||||
*/
|
||||
public int $maxSimilarity = 50;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Hashing Algorithm to use
|
||||
* --------------------------------------------------------------------
|
||||
* Valid values are
|
||||
* - PASSWORD_DEFAULT (default)
|
||||
* - PASSWORD_BCRYPT
|
||||
* - PASSWORD_ARGON2I - As of PHP 7.2 only if compiled with support for it
|
||||
* - PASSWORD_ARGON2ID - As of PHP 7.3 only if compiled with support for it
|
||||
*/
|
||||
public string $hashAlgorithm = PASSWORD_DEFAULT;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* ARGON2I/ARGON2ID Algorithm options
|
||||
* --------------------------------------------------------------------
|
||||
* The ARGON2I method of hashing allows you to define the "memory_cost",
|
||||
* the "time_cost" and the number of "threads", whenever a password hash is
|
||||
* created.
|
||||
*/
|
||||
public int $hashMemoryCost = 65536; // PASSWORD_ARGON2_DEFAULT_MEMORY_COST;
|
||||
|
||||
public int $hashTimeCost = 4; // PASSWORD_ARGON2_DEFAULT_TIME_COST;
|
||||
public int $hashThreads = 1; // PASSWORD_ARGON2_DEFAULT_THREADS;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* BCRYPT Algorithm options
|
||||
* --------------------------------------------------------------------
|
||||
* The BCRYPT method of hashing allows you to define the "cost"
|
||||
* or number of iterations made, whenever a password hash is created.
|
||||
* This defaults to a value of 10 which is an acceptable number.
|
||||
* However, depending on the security needs of your application
|
||||
* and the power of your hardware, you might want to increase the
|
||||
* cost. This makes the hashing process takes longer.
|
||||
*
|
||||
* Valid range is between 4 - 31.
|
||||
*/
|
||||
public int $hashCost = 10;
|
||||
|
||||
/**
|
||||
* ////////////////////////////////////////////////////////////////////
|
||||
* OTHER SETTINGS
|
||||
* ////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* User Provider
|
||||
* --------------------------------------------------------------------
|
||||
* The name of the class that handles user persistence.
|
||||
* By default, this is the included UserModel, which
|
||||
* works with any of the database engines supported by CodeIgniter.
|
||||
* You can change it as long as they adhere to the
|
||||
* CodeIgniter\Shield\Models\UserModel.
|
||||
*
|
||||
* @var class-string<UserModel>
|
||||
*/
|
||||
public string $userProvider = UserModel::class;
|
||||
|
||||
/**
|
||||
* Returns the URL that a user should be redirected
|
||||
* to after a successful login.
|
||||
*/
|
||||
public function loginRedirect(): string
|
||||
{
|
||||
if(auth()->user()->inGroup('guest')){
|
||||
return $this->getUrl('/guest');
|
||||
}
|
||||
|
||||
if(auth()->user()->inGroup('advertiser', 'agency')){
|
||||
return $this->getUrl('/integrate');
|
||||
}
|
||||
|
||||
$url = setting('Auth.redirects')['login'];
|
||||
|
||||
return $this->getUrl($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL that a user should be redirected
|
||||
* to after they are logged out.
|
||||
*/
|
||||
public function logoutRedirect(): string
|
||||
{
|
||||
$url = setting('Auth.redirects')['logout'];
|
||||
|
||||
return $this->getUrl($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL the user should be redirected to
|
||||
* after a successful registration.
|
||||
*/
|
||||
public function registerRedirect(): string
|
||||
{
|
||||
if(auth()->user()->inGroup('guest')){
|
||||
return $this->getUrl('/guest');
|
||||
}
|
||||
$url = setting('Auth.redirects')['register'];
|
||||
|
||||
return $this->getUrl($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL the user should be redirected to
|
||||
* if force_reset identity is set to true.
|
||||
*/
|
||||
public function forcePasswordResetRedirect(): string
|
||||
{
|
||||
$url = setting('Auth.redirects')['force_reset'];
|
||||
|
||||
return $this->getUrl($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL the user should be redirected to
|
||||
* if permission denied.
|
||||
*/
|
||||
public function permissionDeniedRedirect(): string
|
||||
{
|
||||
if(auth()->user()->inGroup('guest')){
|
||||
return $this->getUrl('/guest');
|
||||
}
|
||||
|
||||
if(auth()->user()->inGroup('advertiser', 'agency')){
|
||||
return $this->getUrl('/integrate');
|
||||
}
|
||||
|
||||
$url = setting('Auth.redirects')['permission_denied'];
|
||||
|
||||
return $this->getUrl($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL the user should be redirected to
|
||||
* if group denied.
|
||||
*/
|
||||
public function groupDeniedRedirect(): string
|
||||
{
|
||||
if(auth()->user()->inGroup('guest')){
|
||||
return $this->getUrl('/guest');
|
||||
}
|
||||
|
||||
if(auth()->user()->inGroup('advertiser', 'agency')){
|
||||
return $this->getUrl('/integrate');
|
||||
}
|
||||
|
||||
$url = setting('Auth.redirects')['group_denied'];
|
||||
|
||||
return $this->getUrl($url);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Accepts a string which can be an absolute URL or
|
||||
* a named route or just a URI path, and returns the
|
||||
* full path.
|
||||
*
|
||||
* @param string $url an absolute URL or a named route or just URI path
|
||||
*/
|
||||
protected function getUrl(string $url): string
|
||||
{
|
||||
// To accommodate all url patterns
|
||||
$final_url = '';
|
||||
|
||||
switch (true) {
|
||||
case strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0: // URL begins with 'http' or 'https'. E.g. http://example.com
|
||||
$final_url = $url;
|
||||
break;
|
||||
|
||||
case route_to($url) !== false: // URL is a named-route
|
||||
$final_url = rtrim(url_to($url), '/ ');
|
||||
break;
|
||||
|
||||
default: // URL is a route (URI path)
|
||||
$final_url = rtrim(site_url($url), '/ ');
|
||||
break;
|
||||
}
|
||||
|
||||
return $final_url;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Shield\Config\AuthGroups as ShieldAuthGroups;
|
||||
|
||||
class AuthGroups extends ShieldAuthGroups
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Default Group
|
||||
* --------------------------------------------------------------------
|
||||
* The group that a newly registered user is added to.
|
||||
*/
|
||||
public string $defaultGroup = 'guest';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Groups
|
||||
* --------------------------------------------------------------------
|
||||
* An associative array of the available groups in the system, where the keys are
|
||||
* the group names and the values are arrays of the group info.
|
||||
*
|
||||
* Whatever value you assign as the key will be used to refer to the group when using functions such as:
|
||||
* $user->addGroup('superadmin');
|
||||
*
|
||||
* @var array<string, array<string, string>>
|
||||
*
|
||||
* @see https://github.com/codeigniter4/shield/blob/develop/docs/quickstart.md#change-available-groups for more info
|
||||
*/
|
||||
public array $groups = [
|
||||
'superadmin' => [
|
||||
'title' => '최고관리자',
|
||||
'description' => '제니스 최고관리자',
|
||||
],
|
||||
'admin' => [
|
||||
'title' => '관리자',
|
||||
'description' => '제니스 일반관리자',
|
||||
],
|
||||
'developer' => [
|
||||
'title' => '제니스 개발자',
|
||||
'description' => '제니스 개발자',
|
||||
],
|
||||
'user' => [
|
||||
'title' => '제니스 사용자',
|
||||
'description' => '제니스 사용자',
|
||||
],
|
||||
'agency' => [
|
||||
'title' => '광고대행사',
|
||||
'description' => '광고대행사 사용자',
|
||||
],
|
||||
'advertiser' => [
|
||||
'title' => '광고주',
|
||||
'description' => '광고주 사용자',
|
||||
],
|
||||
'guest' => [
|
||||
'title' => '게스트',
|
||||
'description' => '게스트 권한'
|
||||
],
|
||||
'test' => [
|
||||
'title' => '테스트',
|
||||
'description' => '테스트 권한'
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Permissions
|
||||
* --------------------------------------------------------------------
|
||||
* The available permissions in the system. Each system is defined
|
||||
* where the key is the
|
||||
*
|
||||
* If a permission is not listed here it cannot be used.
|
||||
*/
|
||||
//일부 그룹에 특정 관리에 대한 명시적 권한을 부여
|
||||
public array $permissions = [
|
||||
'admin.access' => '관리자만 가능한 페이지 접근 가능',
|
||||
'admin.settings' => '관리자만 가능한 설정 접근 가능',
|
||||
'users.create' => '회원 생성',
|
||||
'users.edit' => '회원 수정',
|
||||
'users.delete' => '회원 삭제',
|
||||
|
||||
'agency.access' => '대행사 목록 페이지',
|
||||
'agency.advertisers' => '대행사 하위 광고주 관리',
|
||||
'agency.create' => '대행사 생성',
|
||||
'agency.edit' => '대행사 수정',
|
||||
'agency.delete' => '대행사 삭제',
|
||||
|
||||
'advertiser.access' => '광고주 목록 페이지',
|
||||
'advertiser.create' => '광고주 생성',
|
||||
'advertiser.edit' => '광고주 수정',
|
||||
'advertiser.delete' => '광고주 삭제',
|
||||
|
||||
'integrate.status' => '인정기준 변경 권한',
|
||||
'integrate.advertiser' => '광고주 노출 권한',
|
||||
'integrate.media' => '매체 노출 권한',
|
||||
'integrate.description' => '구분 노출 권한',
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Permissions Matrix
|
||||
* --------------------------------------------------------------------
|
||||
* Maps permissions to groups.
|
||||
*/
|
||||
//그룹과 권한 맵핑
|
||||
public array $matrix = [
|
||||
'superadmin' => [
|
||||
'admin.access',
|
||||
'users.*',
|
||||
'agency.*',
|
||||
'advertiser.*',
|
||||
'integrate.*',
|
||||
],
|
||||
'admin' => [
|
||||
'admin.access',
|
||||
'users.create',
|
||||
'users.edit',
|
||||
'users.delete',
|
||||
'agency.*',
|
||||
'advertiser.*',
|
||||
'integrate.*',
|
||||
],
|
||||
'developer' => [
|
||||
'admin.access',
|
||||
'admin.settings',
|
||||
'users.create',
|
||||
'users.edit',
|
||||
'integrate.*',
|
||||
],
|
||||
'agency' => [
|
||||
'agency.advertisers',
|
||||
],
|
||||
'advertiser' => [],
|
||||
'user' => [
|
||||
'agency.*',
|
||||
'advertiser.*',
|
||||
],
|
||||
'guest' => [
|
||||
'guest.access'
|
||||
],
|
||||
'test' => [
|
||||
'admin.access',
|
||||
'users.create',
|
||||
'users.edit',
|
||||
'users.delete',
|
||||
'agency.*',
|
||||
'advertiser.*',
|
||||
'integrate.*',
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter Shield.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Shield\Config\AuthToken as ShieldAuthToken;
|
||||
|
||||
/**
|
||||
* Configuration for Token Auth and HMAC Auth
|
||||
*/
|
||||
class AuthToken extends ShieldAuthToken
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Record Login Attempts for Token Auth and HMAC Auth
|
||||
* --------------------------------------------------------------------
|
||||
* Specify which login attempts are recorded in the database.
|
||||
*
|
||||
* Valid values are:
|
||||
* - Auth::RECORD_LOGIN_ATTEMPT_NONE
|
||||
* - Auth::RECORD_LOGIN_ATTEMPT_FAILURE
|
||||
* - Auth::RECORD_LOGIN_ATTEMPT_ALL
|
||||
*/
|
||||
public int $recordLoginAttempt = Auth::RECORD_LOGIN_ATTEMPT_FAILURE;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Name of Authenticator Header
|
||||
* --------------------------------------------------------------------
|
||||
* The name of Header that the Authorization token should be found.
|
||||
* According to the specs, this should be `Authorization`, but rare
|
||||
* circumstances might need a different header.
|
||||
*/
|
||||
public array $authenticatorHeader = [
|
||||
'tokens' => 'Authorization',
|
||||
'hmac' => 'Authorization',
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Unused Token Lifetime for Token Auth and HMAC Auth
|
||||
* --------------------------------------------------------------------
|
||||
* Determines the amount of time, in seconds, that an unused token can
|
||||
* be used.
|
||||
*/
|
||||
public int $unusedTokenLifetime = YEAR;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Secret2 storage character limit
|
||||
* --------------------------------------------------------------------
|
||||
* Database size limit for the identities 'secret2' field.
|
||||
*/
|
||||
public int $secret2StorageLimit = 255;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* HMAC secret key byte size
|
||||
* --------------------------------------------------------------------
|
||||
* Specify in integer the desired byte size of the
|
||||
* HMAC SHA256 byte size
|
||||
*/
|
||||
public int $hmacSecretKeyByteSize = 32;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* HMAC encryption Keys
|
||||
* --------------------------------------------------------------------
|
||||
* This sets the key to be used when encrypting a user's HMAC Secret Key.
|
||||
*
|
||||
* 'keys' is an array of keys which will facilitate key rotation. Valid
|
||||
* keyTitles must include only [a-zA-Z0-9_] and should be kept to a
|
||||
* max of 8 characters.
|
||||
*
|
||||
* Each keyTitle is an associative array containing the required 'key'
|
||||
* value, and the optional 'driver' and 'digest' values. If the
|
||||
* 'driver' and 'digest' values are not specified, the default 'driver'
|
||||
* and 'digest' values will be used.
|
||||
*
|
||||
* Old keys will are used to decrypt existing Secret Keys. It is encouraged
|
||||
* to run 'php spark shield:hmac reencrypt' to update existing Secret
|
||||
* Key encryptions.
|
||||
*
|
||||
* @see https://codeigniter.com/user_guide/libraries/encryption.html
|
||||
*
|
||||
* @var array<string, array{key: string, driver?: string, digest?: string}>|string
|
||||
*
|
||||
* NOTE: The value becomes temporarily a string when setting value as JSON
|
||||
* from environment variable.
|
||||
*
|
||||
* [key_name => ['key' => key_value]]
|
||||
* or [key_name => ['key' => key_value, 'driver' => driver, 'digest' => digest]]
|
||||
*/
|
||||
public $hmacEncryptionKeys = [
|
||||
'k1' => [
|
||||
'key' => '',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* HMAC Current Encryption Key Selector
|
||||
* --------------------------------------------------------------------
|
||||
* This specifies which of the encryption keys should be used.
|
||||
*/
|
||||
public string $hmacEncryptionCurrentKey = 'k1';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* HMAC Encryption Key Driver
|
||||
* --------------------------------------------------------------------
|
||||
* This specifies which of the encryption drivers should be used.
|
||||
*
|
||||
* Available drivers:
|
||||
* - OpenSSL
|
||||
* - Sodium
|
||||
*/
|
||||
public string $hmacEncryptionDefaultDriver = 'OpenSSL';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* HMAC Encryption Key Driver
|
||||
* --------------------------------------------------------------------
|
||||
* THis specifies the type of encryption to be used.
|
||||
* e.g. 'SHA512' or 'SHA256'.
|
||||
*/
|
||||
public string $hmacEncryptionDefaultDigest = 'SHA512';
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\AutoloadConfig;
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* AUTOLOADER CONFIGURATION
|
||||
* -------------------------------------------------------------------
|
||||
*
|
||||
* This file defines the namespaces and class maps so the Autoloader
|
||||
* can find the files as needed.
|
||||
*
|
||||
* NOTE: If you use an identical key in $psr4 or $classmap, then
|
||||
* the values in this file will overwrite the framework's values.
|
||||
*/
|
||||
class Autoload extends AutoloadConfig
|
||||
{
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Namespaces
|
||||
* -------------------------------------------------------------------
|
||||
* This maps the locations of any namespaces in your application to
|
||||
* their location on the file system. These are used by the autoloader
|
||||
* to locate files the first time they have been instantiated.
|
||||
*
|
||||
* The '/app' and '/system' directories are already mapped for you.
|
||||
* you may change the name of the 'App' namespace if you wish,
|
||||
* but this should be done prior to creating any namespaced classes,
|
||||
* else you will need to modify all of those classes for this to work.
|
||||
*
|
||||
* Prototype:
|
||||
* $psr4 = [
|
||||
* 'CodeIgniter' => SYSTEMPATH,
|
||||
* 'App' => APPPATH
|
||||
* ];
|
||||
*
|
||||
* @var array<string, array<int, string>|string>
|
||||
* @phpstan-var array<string, string|list<string>>
|
||||
*/
|
||||
public $psr4 = [
|
||||
APP_NAMESPACE => APPPATH, // For custom app namespace
|
||||
'Config' => APPPATH . 'Config',
|
||||
];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Class Map
|
||||
* -------------------------------------------------------------------
|
||||
* The class map provides a map of class names and their exact
|
||||
* location on the drive. Classes loaded in this manner will have
|
||||
* slightly faster performance because they will not have to be
|
||||
* searched for within one or more directories as they would if they
|
||||
* were being autoloaded through a namespace.
|
||||
*
|
||||
* Prototype:
|
||||
* $classmap = [
|
||||
* 'MyClass' => '/path/to/class/file.php'
|
||||
* ];
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public $classmap = [
|
||||
];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Files
|
||||
* -------------------------------------------------------------------
|
||||
* The files array provides a list of paths to __non-class__ files
|
||||
* that will be autoloaded. This can be useful for bootstrap operations
|
||||
* or for loading functions.
|
||||
*
|
||||
* Prototype:
|
||||
* $files = [
|
||||
* '/path/to/my/file.php',
|
||||
* ];
|
||||
*
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
public $files = [];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Helpers
|
||||
* -------------------------------------------------------------------
|
||||
* Prototype:
|
||||
* $helpers = [
|
||||
* 'form',
|
||||
* ];
|
||||
*
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
public $helpers = ['auth', 'setting', 'common'];
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| ERROR DISPLAY
|
||||
|--------------------------------------------------------------------------
|
||||
| In development, we want to show as many errors as possible to help
|
||||
| make sure they don't make it to production. And save us hours of
|
||||
| painful debugging.
|
||||
*/
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', '1');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| DEBUG BACKTRACES
|
||||
|--------------------------------------------------------------------------
|
||||
| If true, this constant will tell the error screens to display debug
|
||||
| backtraces along with the other error information. If you would
|
||||
| prefer to not see this, set this value to false.
|
||||
*/
|
||||
defined('SHOW_DEBUG_BACKTRACE') || define('SHOW_DEBUG_BACKTRACE', true);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| DEBUG MODE
|
||||
|--------------------------------------------------------------------------
|
||||
| Debug mode is an experimental flag that can allow changes throughout
|
||||
| the system. This will control whether Kint is loaded, and a few other
|
||||
| items. It can always be used within your own application too.
|
||||
*/
|
||||
defined('CI_DEBUG') || define('CI_DEBUG', true);
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| ERROR DISPLAY
|
||||
|--------------------------------------------------------------------------
|
||||
| Don't show ANY in production environments. Instead, let the system catch
|
||||
| it and display a generic error message.
|
||||
*/
|
||||
ini_set('display_errors', '0');
|
||||
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| DEBUG MODE
|
||||
|--------------------------------------------------------------------------
|
||||
| Debug mode is an experimental flag that can allow changes throughout
|
||||
| the system. It's not widely used currently, and may not survive
|
||||
| release of the framework.
|
||||
*/
|
||||
defined('CI_DEBUG') || define('CI_DEBUG', false);
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| ERROR DISPLAY
|
||||
|--------------------------------------------------------------------------
|
||||
| In development, we want to show as many errors as possible to help
|
||||
| make sure they don't make it to production. And save us hours of
|
||||
| painful debugging.
|
||||
*/
|
||||
error_reporting(E_ALL & ~E_NOTICE);
|
||||
ini_set('display_errors', '1');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| DEBUG BACKTRACES
|
||||
|--------------------------------------------------------------------------
|
||||
| If true, this constant will tell the error screens to display debug
|
||||
| backtraces along with the other error information. If you would
|
||||
| prefer to not see this, set this value to false.
|
||||
*/
|
||||
defined('SHOW_DEBUG_BACKTRACE') || define('SHOW_DEBUG_BACKTRACE', true);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| DEBUG MODE
|
||||
|--------------------------------------------------------------------------
|
||||
| Debug mode is an experimental flag that can allow changes throughout
|
||||
| the system. It's not widely used currently, and may not survive
|
||||
| release of the framework.
|
||||
*/
|
||||
defined('CI_DEBUG') || define('CI_DEBUG', true);
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
class CURLRequest extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CURLRequest Share Options
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Whether share options between requests or not.
|
||||
*
|
||||
* If true, all the options won't be reset between requests.
|
||||
* It may cause an error request with unnecessary headers.
|
||||
*/
|
||||
public bool $shareOptions = true;
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Cache\Handlers\DummyHandler;
|
||||
use CodeIgniter\Cache\Handlers\FileHandler;
|
||||
use CodeIgniter\Cache\Handlers\MemcachedHandler;
|
||||
use CodeIgniter\Cache\Handlers\PredisHandler;
|
||||
use CodeIgniter\Cache\Handlers\RedisHandler;
|
||||
use CodeIgniter\Cache\Handlers\WincacheHandler;
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
class Cache extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Primary Handler
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The name of the preferred handler that should be used. If for some reason
|
||||
* it is not available, the $backupHandler will be used in its place.
|
||||
*/
|
||||
public string $handler = 'file';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Backup Handler
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The name of the handler that will be used in case the first one is
|
||||
* unreachable. Often, 'file' is used here since the filesystem is
|
||||
* always available, though that's not always practical for the app.
|
||||
*/
|
||||
public string $backupHandler = 'dummy';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cache Directory Path
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The path to where cache files should be stored, if using a file-based
|
||||
* system.
|
||||
*
|
||||
* @deprecated Use the driver-specific variant under $file
|
||||
*/
|
||||
public string $storePath = WRITEPATH . 'cache/';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cache Include Query String
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Whether to take the URL query string into consideration when generating
|
||||
* output cache files. Valid options are:
|
||||
*
|
||||
* false = Disabled
|
||||
* true = Enabled, take all query parameters into account.
|
||||
* Please be aware that this may result in numerous cache
|
||||
* files generated for the same page over and over again.
|
||||
* array('q') = Enabled, but only take into account the specified list
|
||||
* of query parameters.
|
||||
*
|
||||
* @var bool|string[]
|
||||
*/
|
||||
public $cacheQueryString = false;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Key Prefix
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* This string is added to all cache item names to help avoid collisions
|
||||
* if you run multiple applications with the same cache engine.
|
||||
*/
|
||||
public string $prefix = '';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Default TTL
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The default number of seconds to save items when none is specified.
|
||||
*
|
||||
* WARNING: This is not used by framework handlers where 60 seconds is
|
||||
* hard-coded, but may be useful to projects and modules. This will replace
|
||||
* the hard-coded value in a future release.
|
||||
*/
|
||||
public int $ttl = 60;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Reserved Characters
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* A string of reserved characters that will not be allowed in keys or tags.
|
||||
* Strings that violate this restriction will cause handlers to throw.
|
||||
* Default: {}()/\@:
|
||||
* Note: The default set is required for PSR-6 compliance.
|
||||
*/
|
||||
public string $reservedCharacters = '{}()/\@:';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* File settings
|
||||
* --------------------------------------------------------------------------
|
||||
* Your file storage preferences can be specified below, if you are using
|
||||
* the File driver.
|
||||
*
|
||||
* @var array<string, int|string|null>
|
||||
*/
|
||||
public array $file = [
|
||||
'storePath' => WRITEPATH . 'cache/',
|
||||
'mode' => 0640,
|
||||
];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------------
|
||||
* Memcached settings
|
||||
* -------------------------------------------------------------------------
|
||||
* Your Memcached servers can be specified below, if you are using
|
||||
* the Memcached drivers.
|
||||
*
|
||||
* @see https://codeigniter.com/user_guide/libraries/caching.html#memcached
|
||||
*
|
||||
* @var array<string, bool|int|string>
|
||||
*/
|
||||
public array $memcached = [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 11211,
|
||||
'weight' => 1,
|
||||
'raw' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------------
|
||||
* Redis settings
|
||||
* -------------------------------------------------------------------------
|
||||
* Your Redis server can be specified below, if you are using
|
||||
* the Redis or Predis drivers.
|
||||
*
|
||||
* @var array<string, int|string|null>
|
||||
*/
|
||||
public array $redis = [
|
||||
'host' => '127.0.0.1',
|
||||
'password' => null,
|
||||
'port' => 6379,
|
||||
'timeout' => 0,
|
||||
'database' => 0,
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Available Cache Handlers
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* This is an array of cache engine alias' and class names. Only engines
|
||||
* that are listed here are allowed to be used.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $validHandlers = [
|
||||
'dummy' => DummyHandler::class,
|
||||
'file' => FileHandler::class,
|
||||
'memcached' => MemcachedHandler::class,
|
||||
'predis' => PredisHandler::class,
|
||||
'redis' => RedisHandler::class,
|
||||
'wincache' => WincacheHandler::class,
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
| --------------------------------------------------------------------
|
||||
| App Namespace
|
||||
| --------------------------------------------------------------------
|
||||
|
|
||||
| This defines the default Namespace that is used throughout
|
||||
| CodeIgniter to refer to the Application directory. Change
|
||||
| this constant to change the namespace that all application
|
||||
| classes should use.
|
||||
|
|
||||
| NOTE: changing this will require manually modifying the
|
||||
| existing namespaces of App\* namespaced-classes.
|
||||
*/
|
||||
defined('APP_NAMESPACE') || define('APP_NAMESPACE', 'App');
|
||||
|
||||
/*
|
||||
| --------------------------------------------------------------------------
|
||||
| Composer Path
|
||||
| --------------------------------------------------------------------------
|
||||
|
|
||||
| The path that Composer's autoload file is expected to live. By default,
|
||||
| the vendor folder is in the Root directory, but you can customize that here.
|
||||
*/
|
||||
defined('COMPOSER_PATH') || define('COMPOSER_PATH', ROOTPATH . 'vendor/autoload.php');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Timing Constants
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Provide simple ways to work with the myriad of PHP functions that
|
||||
| require information to be in seconds.
|
||||
*/
|
||||
defined('SECOND') || define('SECOND', 1);
|
||||
defined('MINUTE') || define('MINUTE', 60);
|
||||
defined('HOUR') || define('HOUR', 3600);
|
||||
defined('DAY') || define('DAY', 86400);
|
||||
defined('WEEK') || define('WEEK', 604800);
|
||||
defined('MONTH') || define('MONTH', 2_592_000);
|
||||
defined('YEAR') || define('YEAR', 31_536_000);
|
||||
defined('DECADE') || define('DECADE', 315_360_000);
|
||||
|
||||
/*
|
||||
| --------------------------------------------------------------------------
|
||||
| Exit Status Codes
|
||||
| --------------------------------------------------------------------------
|
||||
|
|
||||
| Used to indicate the conditions under which the script is exit()ing.
|
||||
| While there is no universal standard for error codes, there are some
|
||||
| broad conventions. Three such conventions are mentioned below, for
|
||||
| those who wish to make use of them. The CodeIgniter defaults were
|
||||
| chosen for the least overlap with these conventions, while still
|
||||
| leaving room for others to be defined in future versions and user
|
||||
| applications.
|
||||
|
|
||||
| The three main conventions used for determining exit status codes
|
||||
| are as follows:
|
||||
|
|
||||
| Standard C/C++ Library (stdlibc):
|
||||
| http://www.gnu.org/software/libc/manual/html_node/Exit-Status.html
|
||||
| (This link also contains other GNU-specific conventions)
|
||||
| BSD sysexits.h:
|
||||
| http://www.gsp.com/cgi-bin/man.cgi?section=3&topic=sysexits
|
||||
| Bash scripting:
|
||||
| http://tldp.org/LDP/abs/html/exitcodes.html
|
||||
|
|
||||
*/
|
||||
defined('EXIT_SUCCESS') || define('EXIT_SUCCESS', 0); // no errors
|
||||
defined('EXIT_ERROR') || define('EXIT_ERROR', 1); // generic error
|
||||
defined('EXIT_CONFIG') || define('EXIT_CONFIG', 3); // configuration error
|
||||
defined('EXIT_UNKNOWN_FILE') || define('EXIT_UNKNOWN_FILE', 4); // file not found
|
||||
defined('EXIT_UNKNOWN_CLASS') || define('EXIT_UNKNOWN_CLASS', 5); // unknown class
|
||||
defined('EXIT_UNKNOWN_METHOD') || define('EXIT_UNKNOWN_METHOD', 6); // unknown class member
|
||||
defined('EXIT_USER_INPUT') || define('EXIT_USER_INPUT', 7); // invalid user input
|
||||
defined('EXIT_DATABASE') || define('EXIT_DATABASE', 8); // database error
|
||||
defined('EXIT__AUTO_MIN') || define('EXIT__AUTO_MIN', 9); // lowest automatically-assigned error code
|
||||
defined('EXIT__AUTO_MAX') || define('EXIT__AUTO_MAX', 125); // highest automatically-assigned error code
|
||||
|
||||
/**
|
||||
* @deprecated Use \CodeIgniter\Events\Events::PRIORITY_LOW instead.
|
||||
*/
|
||||
define('EVENT_PRIORITY_LOW', 200);
|
||||
|
||||
/**
|
||||
* @deprecated Use \CodeIgniter\Events\Events::PRIORITY_NORMAL instead.
|
||||
*/
|
||||
define('EVENT_PRIORITY_NORMAL', 100);
|
||||
|
||||
/**
|
||||
* @deprecated Use \CodeIgniter\Events\Events::PRIORITY_HIGH instead.
|
||||
*/
|
||||
define('EVENT_PRIORITY_HIGH', 10);
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
/**
|
||||
* Stores the default settings for the ContentSecurityPolicy, if you
|
||||
* choose to use it. The values here will be read in and set as defaults
|
||||
* for the site. If needed, they can be overridden on a page-by-page basis.
|
||||
*
|
||||
* Suggested reference for explanations:
|
||||
*
|
||||
* @see https://www.html5rocks.com/en/tutorials/security/content-security-policy/
|
||||
*/
|
||||
class ContentSecurityPolicy extends BaseConfig
|
||||
{
|
||||
// -------------------------------------------------------------------------
|
||||
// Broadbrush CSP management
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Default CSP report context
|
||||
*/
|
||||
public bool $reportOnly = false;
|
||||
|
||||
/**
|
||||
* Specifies a URL where a browser will send reports
|
||||
* when a content security policy is violated.
|
||||
*/
|
||||
public ?string $reportURI = null;
|
||||
|
||||
/**
|
||||
* Instructs user agents to rewrite URL schemes, changing
|
||||
* HTTP to HTTPS. This directive is for websites with
|
||||
* large numbers of old URLs that need to be rewritten.
|
||||
*/
|
||||
public bool $upgradeInsecureRequests = false;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Sources allowed
|
||||
// Note: once you set a policy to 'none', it cannot be further restricted
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Will default to self if not overridden
|
||||
*
|
||||
* @var string|string[]|null
|
||||
*/
|
||||
public $defaultSrc;
|
||||
|
||||
/**
|
||||
* Lists allowed scripts' URLs.
|
||||
*
|
||||
* @var string|string[]
|
||||
*/
|
||||
public $scriptSrc = 'self';
|
||||
|
||||
/**
|
||||
* Lists allowed stylesheets' URLs.
|
||||
*
|
||||
* @var string|string[]
|
||||
*/
|
||||
public $styleSrc = 'self';
|
||||
|
||||
/**
|
||||
* Defines the origins from which images can be loaded.
|
||||
*
|
||||
* @var string|string[]
|
||||
*/
|
||||
public $imageSrc = 'self';
|
||||
|
||||
/**
|
||||
* Restricts the URLs that can appear in a page's `<base>` element.
|
||||
*
|
||||
* Will default to self if not overridden
|
||||
*
|
||||
* @var string|string[]|null
|
||||
*/
|
||||
public $baseURI;
|
||||
|
||||
/**
|
||||
* Lists the URLs for workers and embedded frame contents
|
||||
*
|
||||
* @var string|string[]
|
||||
*/
|
||||
public $childSrc = 'self';
|
||||
|
||||
/**
|
||||
* Limits the origins that you can connect to (via XHR,
|
||||
* WebSockets, and EventSource).
|
||||
*
|
||||
* @var string|string[]
|
||||
*/
|
||||
public $connectSrc = 'self';
|
||||
|
||||
/**
|
||||
* Specifies the origins that can serve web fonts.
|
||||
*
|
||||
* @var string|string[]
|
||||
*/
|
||||
public $fontSrc;
|
||||
|
||||
/**
|
||||
* Lists valid endpoints for submission from `<form>` tags.
|
||||
*
|
||||
* @var string|string[]
|
||||
*/
|
||||
public $formAction = 'self';
|
||||
|
||||
/**
|
||||
* Specifies the sources that can embed the current page.
|
||||
* This directive applies to `<frame>`, `<iframe>`, `<embed>`,
|
||||
* and `<applet>` tags. This directive can't be used in
|
||||
* `<meta>` tags and applies only to non-HTML resources.
|
||||
*
|
||||
* @var string|string[]|null
|
||||
*/
|
||||
public $frameAncestors;
|
||||
|
||||
/**
|
||||
* The frame-src directive restricts the URLs which may
|
||||
* be loaded into nested browsing contexts.
|
||||
*
|
||||
* @var array|string|null
|
||||
*/
|
||||
public $frameSrc;
|
||||
|
||||
/**
|
||||
* Restricts the origins allowed to deliver video and audio.
|
||||
*
|
||||
* @var string|string[]|null
|
||||
*/
|
||||
public $mediaSrc;
|
||||
|
||||
/**
|
||||
* Allows control over Flash and other plugins.
|
||||
*
|
||||
* @var string|string[]
|
||||
*/
|
||||
public $objectSrc = 'self';
|
||||
|
||||
/**
|
||||
* @var string|string[]|null
|
||||
*/
|
||||
public $manifestSrc;
|
||||
|
||||
/**
|
||||
* Limits the kinds of plugins a page may invoke.
|
||||
*
|
||||
* @var string|string[]|null
|
||||
*/
|
||||
public $pluginTypes;
|
||||
|
||||
/**
|
||||
* List of actions allowed.
|
||||
*
|
||||
* @var string|string[]|null
|
||||
*/
|
||||
public $sandbox;
|
||||
|
||||
/**
|
||||
* Nonce tag for style
|
||||
*/
|
||||
public string $styleNonceTag = '{csp-style-nonce}';
|
||||
|
||||
/**
|
||||
* Nonce tag for script
|
||||
*/
|
||||
public string $scriptNonceTag = '{csp-script-nonce}';
|
||||
|
||||
/**
|
||||
* Replace nonce tag automatically
|
||||
*/
|
||||
public bool $autoNonce = true;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use DateTimeInterface;
|
||||
|
||||
class Cookie extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie Prefix
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Set a cookie name prefix if you need to avoid collisions.
|
||||
*/
|
||||
public string $prefix = '';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie Expires Timestamp
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Default expires timestamp for cookies. Setting this to `0` will mean the
|
||||
* cookie will not have the `Expires` attribute and will behave as a session
|
||||
* cookie.
|
||||
*
|
||||
* @var DateTimeInterface|int|string
|
||||
*/
|
||||
public $expires = 0;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie Path
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Typically will be a forward slash.
|
||||
*/
|
||||
public string $path = '/';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie Domain
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Set to `.your-domain.com` for site-wide cookies.
|
||||
*/
|
||||
public string $domain = '';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie Secure
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Cookie will only be set if a secure HTTPS connection exists.
|
||||
*/
|
||||
public bool $secure = false;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie HTTPOnly
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Cookie will only be accessible via HTTP(S) (no JavaScript).
|
||||
*/
|
||||
public bool $httponly = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie SameSite
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Configure cookie SameSite setting. Allowed values are:
|
||||
* - None
|
||||
* - Lax
|
||||
* - Strict
|
||||
* - ''
|
||||
*
|
||||
* Alternatively, you can use the constant names:
|
||||
* - `Cookie::SAMESITE_NONE`
|
||||
* - `Cookie::SAMESITE_LAX`
|
||||
* - `Cookie::SAMESITE_STRICT`
|
||||
*
|
||||
* Defaults to `Lax` for compatibility with modern browsers. Setting `''`
|
||||
* (empty string) means default SameSite attribute set by browsers (`Lax`)
|
||||
* will be set on cookies. If set to `None`, `$secure` must also be set.
|
||||
*
|
||||
* @phpstan-var 'None'|'Lax'|'Strict'|''
|
||||
*/
|
||||
public string $samesite = 'Lax';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Cookie Raw
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* This flag allows setting a "raw" cookie, i.e., its name and value are
|
||||
* not URL encoded using `rawurlencode()`.
|
||||
*
|
||||
* If this is set to `true`, cookie names should be compliant of RFC 2616's
|
||||
* list of allowed characters.
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#attributes
|
||||
* @see https://tools.ietf.org/html/rfc2616#section-2.2
|
||||
*/
|
||||
public bool $raw = false;
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Database\Config;
|
||||
|
||||
/**
|
||||
* Database Configuration
|
||||
*/
|
||||
class Database extends Config
|
||||
{
|
||||
/**
|
||||
* The directory that holds the Migrations
|
||||
* and Seeds directories.
|
||||
*/
|
||||
public string $filesPath = APPPATH . 'Database' . DIRECTORY_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Lets you choose which connection group to
|
||||
* use if no other is specified.
|
||||
*/
|
||||
public string $defaultGroup = 'default';
|
||||
|
||||
/**
|
||||
* The default database connection.
|
||||
*/
|
||||
public array $default = [
|
||||
'DSN' => '',
|
||||
'hostname' => 'localhost',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'database' => '',
|
||||
'DBDriver' => 'MySQLi',
|
||||
'DBPrefix' => '',
|
||||
'pConnect' => false,
|
||||
'DBDebug' => (ENVIRONMENT !== 'production'),
|
||||
'charset' => 'utf8mb4',
|
||||
'DBCollat' => 'utf8mb4_unicode_ci',
|
||||
'swapPre' => '',
|
||||
'encrypt' => false,
|
||||
'compress' => false,
|
||||
'strictOn' => false,
|
||||
'failover' => [],
|
||||
'port' => 3306,
|
||||
'read' => ['hostname' => '','username' => '','password' => '','database' => ''],
|
||||
'write' => ['hostname' => '','username' => '','password' => '','database' => ''],
|
||||
];
|
||||
|
||||
/**
|
||||
* This database connection is used when
|
||||
* running PHPUnit database tests.
|
||||
*/
|
||||
public array $tests = [
|
||||
'DSN' => '',
|
||||
'hostname' => '127.0.0.1',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'database' => ':memory:',
|
||||
'DBDriver' => 'SQLite3',
|
||||
'DBPrefix' => 'db_', // Needed to ensure we're working correctly with prefixes live. DO NOT REMOVE FOR CI DEVS
|
||||
'pConnect' => false,
|
||||
'DBDebug' => (ENVIRONMENT !== 'production'),
|
||||
'charset' => 'utf8mb4',
|
||||
'DBCollat' => 'utf8mb4_unicode_ci',
|
||||
'swapPre' => '',
|
||||
'encrypt' => false,
|
||||
'compress' => false,
|
||||
'strictOn' => false,
|
||||
'failover' => [],
|
||||
'port' => 3306,
|
||||
'foreignKeys' => true,
|
||||
'busyTimeout' => 1000,
|
||||
];
|
||||
|
||||
public array $facebook = [
|
||||
'DSN' => '',
|
||||
'hostname' => 'localhost',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'database' => '',
|
||||
'DBDriver' => 'MySQLi',
|
||||
'DBPrefix' => '',
|
||||
'pConnect' => false,
|
||||
'DBDebug' => (ENVIRONMENT !== 'production'),
|
||||
'charset' => 'utf8mb4',
|
||||
'DBCollat' => 'utf8mb4_unicode_ci',
|
||||
'swapPre' => '',
|
||||
'encrypt' => false,
|
||||
'compress' => false,
|
||||
'strictOn' => false,
|
||||
'failover' => [],
|
||||
'port' => 3306,
|
||||
'read' => ['hostname' => '','username' => '','password' => '','database' => ''],
|
||||
'write' => ['hostname' => '','username' => '','password' => '','database' => ''],
|
||||
];
|
||||
|
||||
public array $kakao = [
|
||||
'DSN' => '',
|
||||
'hostname' => 'localhost',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'database' => '',
|
||||
'DBDriver' => 'MySQLi',
|
||||
'DBPrefix' => '',
|
||||
'pConnect' => false,
|
||||
'DBDebug' => (ENVIRONMENT !== 'production'),
|
||||
'charset' => 'utf8mb4',
|
||||
'DBCollat' => 'utf8mb4_unicode_ci',
|
||||
'swapPre' => '',
|
||||
'encrypt' => false,
|
||||
'compress' => false,
|
||||
'strictOn' => false,
|
||||
'failover' => [],
|
||||
'port' => 3306,
|
||||
'read' => ['hostname' => '','username' => '','password' => '','database' => ''],
|
||||
'write' => ['hostname' => '','username' => '','password' => '','database' => ''],
|
||||
];
|
||||
|
||||
public array $google = [
|
||||
'DSN' => '',
|
||||
'hostname' => 'localhost',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'database' => '',
|
||||
'DBDriver' => 'MySQLi',
|
||||
'DBPrefix' => '',
|
||||
'pConnect' => false,
|
||||
'DBDebug' => (ENVIRONMENT !== 'production'),
|
||||
'charset' => 'utf8mb4',
|
||||
'DBCollat' => 'utf8mb4_unicode_ci',
|
||||
'swapPre' => '',
|
||||
'encrypt' => false,
|
||||
'compress' => false,
|
||||
'strictOn' => false,
|
||||
'failover' => [],
|
||||
'port' => 3306,
|
||||
'read' => ['hostname' => '','username' => '','password' => '','database' => ''],
|
||||
'write' => ['hostname' => '','username' => '','password' => '','database' => ''],
|
||||
];
|
||||
|
||||
public array $jira = [
|
||||
'DSN' => '',
|
||||
'hostname' => 'localhost',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'database' => '',
|
||||
'DBDriver' => 'MySQLi',
|
||||
'DBPrefix' => '',
|
||||
'pConnect' => false,
|
||||
'DBDebug' => (ENVIRONMENT !== 'production'),
|
||||
'charset' => 'utf8mb4',
|
||||
'DBCollat' => 'utf8mb4_unicode_ci',
|
||||
'swapPre' => '',
|
||||
'encrypt' => false,
|
||||
'compress' => false,
|
||||
'strictOn' => false,
|
||||
'failover' => [],
|
||||
'port' => 3306,
|
||||
];
|
||||
|
||||
public array $chainsaw = [
|
||||
'DSN' => '',
|
||||
'hostname' => 'localhost',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'database' => '',
|
||||
'DBDriver' => 'MySQLi',
|
||||
'DBPrefix' => '',
|
||||
'pConnect' => false,
|
||||
'DBDebug' => (ENVIRONMENT !== 'production'),
|
||||
'charset' => 'utf8mb4',
|
||||
'DBCollat' => 'utf8mb4_unicode_ci',
|
||||
'swapPre' => '',
|
||||
'encrypt' => false,
|
||||
'compress' => false,
|
||||
'strictOn' => false,
|
||||
'failover' => [],
|
||||
'port' => 3306,
|
||||
'read' => ['hostname' => '','username' => '','password' => '','database' => ''],
|
||||
'write' => ['hostname' => '','username' => '','password' => '','database' => ''],
|
||||
];
|
||||
|
||||
public array $gwdb = [
|
||||
'DSN' => '',
|
||||
'hostname' => 'localhost',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'database' => '',
|
||||
'DBDriver' => 'MySQLi',
|
||||
'DBPrefix' => '',
|
||||
'pConnect' => false,
|
||||
'DBDebug' => (ENVIRONMENT !== 'production'),
|
||||
'charset' => 'utf8mb4',
|
||||
'DBCollat' => 'utf8mb4_unicode_ci',
|
||||
'swapPre' => '',
|
||||
'encrypt' => false,
|
||||
'compress' => false,
|
||||
'strictOn' => false,
|
||||
'failover' => [],
|
||||
'port' => 13306,
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Ensure that we always set the database group to 'tests' if
|
||||
// we are currently running an automated test suite, so that
|
||||
// we don't overwrite live data on accident.
|
||||
if (ENVIRONMENT === 'testing') {
|
||||
$this->defaultGroup = 'tests';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
class DocTypes
|
||||
{
|
||||
/**
|
||||
* List of valid document types.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $list = [
|
||||
'xhtml11' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
|
||||
'xhtml1-strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
|
||||
'xhtml1-trans' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
|
||||
'xhtml1-frame' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
|
||||
'xhtml-basic11' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
|
||||
'html5' => '<!DOCTYPE html>',
|
||||
'html4-strict' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
|
||||
'html4-trans' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
|
||||
'html4-frame' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
|
||||
'mathml1' => '<!DOCTYPE math SYSTEM "http://www.w3.org/Math/DTD/mathml1/mathml.dtd">',
|
||||
'mathml2' => '<!DOCTYPE math PUBLIC "-//W3C//DTD MathML 2.0//EN" "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">',
|
||||
'svg10' => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">',
|
||||
'svg11' => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">',
|
||||
'svg11-basic' => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Basic//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd">',
|
||||
'svg11-tiny' => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">',
|
||||
'xhtml-math-svg-xh' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">',
|
||||
'xhtml-math-svg-sh' => '<!DOCTYPE svg:svg PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">',
|
||||
'xhtml-rdfa-1' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">',
|
||||
'xhtml-rdfa-2' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.1//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd">',
|
||||
];
|
||||
|
||||
/**
|
||||
* Whether to remove the solidus (`/`) character for void HTML elements (e.g. `<input>`)
|
||||
* for HTML5 compatibility.
|
||||
*
|
||||
* Set to:
|
||||
* `true` - to be HTML5 compatible
|
||||
* `false` - to be XHTML compatible
|
||||
*/
|
||||
public bool $html5 = true;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
class Email extends BaseConfig
|
||||
{
|
||||
public string $fromEmail;
|
||||
public string $fromName = 'Zenith';
|
||||
public string $recipients = '';
|
||||
|
||||
/**
|
||||
* The "user agent"
|
||||
*/
|
||||
public string $userAgent = 'CodeIgniter';
|
||||
|
||||
/**
|
||||
* The mail sending protocol: mail, sendmail, smtp
|
||||
*/
|
||||
public string $protocol = 'mail';
|
||||
|
||||
/**
|
||||
* The server path to Sendmail.
|
||||
*/
|
||||
public string $mailPath = '/usr/sbin/sendmail';
|
||||
|
||||
/**
|
||||
* SMTP Server Address
|
||||
*/
|
||||
public string $SMTPHost = '';
|
||||
|
||||
/**
|
||||
* SMTP Username
|
||||
*/
|
||||
public string $SMTPUser = '';
|
||||
|
||||
/**
|
||||
* SMTP Password
|
||||
*/
|
||||
public string $SMTPPass = '';
|
||||
|
||||
/**
|
||||
* SMTP Port
|
||||
*/
|
||||
public int $SMTPPort = 25;
|
||||
|
||||
/**
|
||||
* SMTP Timeout (in seconds)
|
||||
*/
|
||||
public int $SMTPTimeout = 5;
|
||||
|
||||
/**
|
||||
* Enable persistent SMTP connections
|
||||
*/
|
||||
public bool $SMTPKeepAlive = false;
|
||||
|
||||
/**
|
||||
* SMTP Encryption. Either tls or ssl
|
||||
*/
|
||||
public string $SMTPCrypto = 'tls';
|
||||
|
||||
/**
|
||||
* Enable word-wrap
|
||||
*/
|
||||
public bool $wordWrap = true;
|
||||
|
||||
/**
|
||||
* Character count to wrap at
|
||||
*/
|
||||
public int $wrapChars = 76;
|
||||
|
||||
/**
|
||||
* Type of mail, either 'text' or 'html'
|
||||
*/
|
||||
public string $mailType = 'html';
|
||||
|
||||
/**
|
||||
* Character set (utf-8, iso-8859-1, etc.)
|
||||
*/
|
||||
public string $charset = 'UTF-8';
|
||||
|
||||
/**
|
||||
* Whether to validate the email address
|
||||
*/
|
||||
public bool $validate = false;
|
||||
|
||||
/**
|
||||
* Email Priority. 1 = highest. 5 = lowest. 3 = normal
|
||||
*/
|
||||
public int $priority = 3;
|
||||
|
||||
/**
|
||||
* Newline character. (Use “\r\n” to comply with RFC 822)
|
||||
*/
|
||||
public string $CRLF = "\r\n";
|
||||
|
||||
/**
|
||||
* Newline character. (Use “\r\n” to comply with RFC 822)
|
||||
*/
|
||||
public string $newline = "\r\n";
|
||||
|
||||
/**
|
||||
* Enable BCC Batch Mode.
|
||||
*/
|
||||
public bool $BCCBatchMode = false;
|
||||
|
||||
/**
|
||||
* Number of emails in each BCC batch
|
||||
*/
|
||||
public int $BCCBatchSize = 200;
|
||||
|
||||
/**
|
||||
* Enable notify message from server
|
||||
*/
|
||||
public bool $DSN = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->fromEmail = getenv('EMAIL');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
/**
|
||||
* Encryption configuration.
|
||||
*
|
||||
* These are the settings used for encryption, if you don't pass a parameter
|
||||
* array to the encrypter for creation/initialization.
|
||||
*/
|
||||
class Encryption extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Encryption Key Starter
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If you use the Encryption class you must set an encryption key (seed).
|
||||
* You need to ensure it is long enough for the cipher and mode you plan to use.
|
||||
* See the user guide for more info.
|
||||
*/
|
||||
public string $key = '';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Encryption Driver to Use
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* One of the supported encryption drivers.
|
||||
*
|
||||
* Available drivers:
|
||||
* - OpenSSL
|
||||
* - Sodium
|
||||
*/
|
||||
public string $driver = 'OpenSSL';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* SodiumHandler's Padding Length in Bytes
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* This is the number of bytes that will be padded to the plaintext message
|
||||
* before it is encrypted. This value should be greater than zero.
|
||||
*
|
||||
* See the user guide for more information on padding.
|
||||
*/
|
||||
public int $blockSize = 16;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Encryption digest
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* HMAC digest to use, e.g. 'SHA512' or 'SHA256'. Default value is 'SHA512'.
|
||||
*/
|
||||
public string $digest = 'SHA512';
|
||||
|
||||
/**
|
||||
* Whether the cipher-text should be raw. If set to false, then it will be base64 encoded.
|
||||
* This setting is only used by OpenSSLHandler.
|
||||
*
|
||||
* Set to false for CI3 Encryption compatibility.
|
||||
*/
|
||||
public bool $rawData = true;
|
||||
|
||||
/**
|
||||
* Encryption key info.
|
||||
* This setting is only used by OpenSSLHandler.
|
||||
*
|
||||
* Set to 'encryption' for CI3 Encryption compatibility.
|
||||
*/
|
||||
public string $encryptKeyInfo = '';
|
||||
|
||||
/**
|
||||
* Authentication key info.
|
||||
* This setting is only used by OpenSSLHandler.
|
||||
*
|
||||
* Set to 'authentication' for CI3 Encryption compatibility.
|
||||
*/
|
||||
public string $authKeyInfo = '';
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Events\Events;
|
||||
use CodeIgniter\Exceptions\FrameworkException;
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* Application Events
|
||||
* --------------------------------------------------------------------
|
||||
* Events allow you to tap into the execution of the program without
|
||||
* modifying or extending core files. This file provides a central
|
||||
* location to define your events, though they can always be added
|
||||
* at run-time, also, if needed.
|
||||
*
|
||||
* You create code that can execute by subscribing to events with
|
||||
* the 'on()' method. This accepts any form of callable, including
|
||||
* Closures, that will be executed when the event is triggered.
|
||||
*
|
||||
* Example:
|
||||
* Events::on('create', [$myInstance, 'myMethod']);
|
||||
*/
|
||||
|
||||
Events::on('pre_system', static function () {
|
||||
if (ENVIRONMENT !== 'testing') {
|
||||
if (ini_get('zlib.output_compression')) {
|
||||
throw FrameworkException::forEnabledZlibOutputCompression();
|
||||
}
|
||||
|
||||
while (ob_get_level() > 0) {
|
||||
ob_end_flush();
|
||||
}
|
||||
|
||||
ob_start(static fn ($buffer) => $buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* Debug Toolbar Listeners.
|
||||
* --------------------------------------------------------------------
|
||||
* If you delete, they will no longer be collected.
|
||||
*/
|
||||
if (CI_DEBUG && ! is_cli()) {
|
||||
Events::on('DBQuery', 'CodeIgniter\Debug\Toolbar\Collectors\Database::collect');
|
||||
Services::toolbar()->respond();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Setup how the exception handler works.
|
||||
*/
|
||||
class Exceptions extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* LOG EXCEPTIONS?
|
||||
* --------------------------------------------------------------------------
|
||||
* If true, then exceptions will be logged
|
||||
* through Services::Log.
|
||||
*
|
||||
* Default: true
|
||||
*/
|
||||
public bool $log = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* DO NOT LOG STATUS CODES
|
||||
* --------------------------------------------------------------------------
|
||||
* Any status codes here will NOT be logged if logging is turned on.
|
||||
* By default, only 404 (Page Not Found) exceptions are ignored.
|
||||
*/
|
||||
public array $ignoreCodes = [404];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Error Views Path
|
||||
* --------------------------------------------------------------------------
|
||||
* This is the path to the directory that contains the 'cli' and 'html'
|
||||
* directories that hold the views used to generate errors.
|
||||
*
|
||||
* Default: APPPATH.'Views/errors'
|
||||
*/
|
||||
public string $errorViewPath = APPPATH . 'Views/errors';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* HIDE FROM DEBUG TRACE
|
||||
* --------------------------------------------------------------------------
|
||||
* Any data that you would like to hide from the debug trace.
|
||||
* In order to specify 2 levels, use "/" to separate.
|
||||
* ex. ['server', 'setup/password', 'secret_token']
|
||||
*/
|
||||
public array $sensitiveDataInTrace = [];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* LOG DEPRECATIONS INSTEAD OF THROWING?
|
||||
* --------------------------------------------------------------------------
|
||||
* By default, CodeIgniter converts deprecations into exceptions. Also,
|
||||
* starting in PHP 8.1 will cause a lot of deprecated usage warnings.
|
||||
* Use this option to temporarily cease the warnings and instead log those.
|
||||
* This option also works for user deprecations.
|
||||
*/
|
||||
public bool $logDeprecations = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* LOG LEVEL THRESHOLD FOR DEPRECATIONS
|
||||
* --------------------------------------------------------------------------
|
||||
* If `$logDeprecations` is set to `true`, this sets the log level
|
||||
* to which the deprecation will be logged. This should be one of the log
|
||||
* levels recognized by PSR-3.
|
||||
*
|
||||
* The related `Config\Logger::$threshold` should be adjusted, if needed,
|
||||
* to capture logging the deprecations.
|
||||
*/
|
||||
public string $deprecationLogLevel = LogLevel::WARNING;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
/**
|
||||
* Enable/disable backward compatibility breaking features.
|
||||
*/
|
||||
class Feature extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* Enable multiple filters for a route or not.
|
||||
*
|
||||
* If you enable this:
|
||||
* - CodeIgniter\CodeIgniter::handleRequest() uses:
|
||||
* - CodeIgniter\Filters\Filters::enableFilters(), instead of enableFilter()
|
||||
* - CodeIgniter\CodeIgniter::tryToRouteIt() uses:
|
||||
* - CodeIgniter\Router\Router::getFilters(), instead of getFilter()
|
||||
* - CodeIgniter\Router\Router::handle() uses:
|
||||
* - property $filtersInfo, instead of $filterInfo
|
||||
* - CodeIgniter\Router\RouteCollection::getFiltersForRoute(), instead of getFilterForRoute()
|
||||
*/
|
||||
public bool $multipleFilters = false;
|
||||
|
||||
/**
|
||||
* Use improved new auto routing instead of the default legacy version.
|
||||
*/
|
||||
public bool $autoRoutesImproved = false;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Filters\CSRF;
|
||||
use CodeIgniter\Filters\DebugToolbar;
|
||||
use CodeIgniter\Filters\Honeypot;
|
||||
use CodeIgniter\Filters\InvalidChars;
|
||||
use CodeIgniter\Filters\SecureHeaders;
|
||||
use CodeIgniter\Shield\Filters\ForcePasswordResetFilter;
|
||||
|
||||
class Filters extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* Configures aliases for Filter classes to
|
||||
* make reading things nicer and simpler.
|
||||
*/
|
||||
public array $aliases = [
|
||||
'auth' => \App\Filters\AuthFilter::class,
|
||||
'forcehttps' => \CodeIgniter\Filters\ForceHTTPS::class,
|
||||
'pagecache' => \CodeIgniter\Filters\PageCache::class,
|
||||
'performance' => \CodeIgniter\Filters\PerformanceMetrics::class,
|
||||
'csrf' => CSRF::class,
|
||||
'toolbar' => DebugToolbar::class,
|
||||
'honeypot' => Honeypot::class,
|
||||
'invalidchars' => InvalidChars::class,
|
||||
'secureheaders' => SecureHeaders::class,
|
||||
'forcePasswordReset' => ForcePasswordResetFilter::class,
|
||||
'logFilter' => \App\Filters\LogFilter::class,
|
||||
];
|
||||
|
||||
public array $required = [
|
||||
'before' => [
|
||||
'forcehttps', // Force Global Secure Requests
|
||||
'pagecache', // Web Page Caching
|
||||
],
|
||||
'after' => [
|
||||
'pagecache', // Web Page Caching
|
||||
'performance', // Performance Metrics
|
||||
'toolbar', // Debug Toolbar
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* List of filter aliases that are always
|
||||
* applied before and after every request.
|
||||
*/
|
||||
public array $globals = [
|
||||
'before' => [
|
||||
'auth' => ['except' => [
|
||||
'login',
|
||||
'login/*',
|
||||
'register',
|
||||
'register/*',
|
||||
'password-reset',
|
||||
'password-reset/*',
|
||||
'*api/*',
|
||||
'*slack*',
|
||||
'*jira*',
|
||||
'*interlock*',
|
||||
'*resta*'
|
||||
]], // 로그인 및 회원가입 관련 URI 예외 처리
|
||||
// 'honeypot',
|
||||
// 'csrf',
|
||||
// 'invalidchars',
|
||||
'session' => ['except' => ['login*', 'register', 'auth/a/*', 'slack/*', 'jira/*', 'interlock', 'resta/*']],
|
||||
'forcePasswordReset' => ['except' => ['login*', 'set-password*', 'logout']],
|
||||
'logFilter'
|
||||
],
|
||||
'after' => [
|
||||
'toolbar',
|
||||
// 'honeypot',
|
||||
// 'secureheaders',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* List of filter aliases that works on a
|
||||
* particular HTTP method (GET, POST, etc.).
|
||||
*
|
||||
* Example:
|
||||
* 'post' => ['foo', 'bar']
|
||||
*
|
||||
* If you use this, you should disable auto-routing because auto-routing
|
||||
* permits any HTTP method to access a controller. Accessing the controller
|
||||
* with a method you don’t expect could bypass the filter.
|
||||
*/
|
||||
public array $methods = [];
|
||||
|
||||
/**
|
||||
* List of filter aliases that should run on any
|
||||
* before or after URI patterns.
|
||||
*
|
||||
* Example:
|
||||
* 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
|
||||
*/
|
||||
public array $filters = [
|
||||
'auth-rates' => [
|
||||
'before' => [
|
||||
'login*', 'register', 'auth/*'
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\ForeignCharacters as BaseForeignCharacters;
|
||||
|
||||
class ForeignCharacters extends BaseForeignCharacters
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Format\FormatterInterface;
|
||||
use CodeIgniter\Format\JSONFormatter;
|
||||
use CodeIgniter\Format\XMLFormatter;
|
||||
|
||||
class Format extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Available Response Formats
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* When you perform content negotiation with the request, these are the
|
||||
* available formats that your application supports. This is currently
|
||||
* only used with the API\ResponseTrait. A valid Formatter must exist
|
||||
* for the specified format.
|
||||
*
|
||||
* These formats are only checked when the data passed to the respond()
|
||||
* method is an array.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public array $supportedResponseFormats = [
|
||||
'application/json',
|
||||
'application/xml', // machine-readable XML
|
||||
'text/xml', // human-readable XML
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Formatters
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Lists the class to use to format responses with of a particular type.
|
||||
* For each mime type, list the class that should be used. Formatters
|
||||
* can be retrieved through the getFormatter() method.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $formatters = [
|
||||
'application/json' => JSONFormatter::class,
|
||||
'application/xml' => XMLFormatter::class,
|
||||
'text/xml' => XMLFormatter::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Formatters Options
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Additional Options to adjust default formatters behaviour.
|
||||
* For each mime type, list the additional options that should be used.
|
||||
*
|
||||
* @var array<string, int>
|
||||
*/
|
||||
public array $formatterOptions = [
|
||||
'application/json' => JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
|
||||
'application/xml' => 0,
|
||||
'text/xml' => 0,
|
||||
];
|
||||
|
||||
/**
|
||||
* A Factory method to return the appropriate formatter for the given mime type.
|
||||
*
|
||||
* @return FormatterInterface
|
||||
*
|
||||
* @deprecated This is an alias of `\CodeIgniter\Format\Format::getFormatter`. Use that instead.
|
||||
*/
|
||||
public function getFormatter(string $mime)
|
||||
{
|
||||
return Services::format()->getFormatter($mime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
class Generators extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Generator Commands' Views
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* This array defines the mapping of generator commands to the view files
|
||||
* they are using. If you need to customize them for your own, copy these
|
||||
* view files in your own folder and indicate the location here.
|
||||
*
|
||||
* You will notice that the views have special placeholders enclosed in
|
||||
* curly braces `{...}`. These placeholders are used internally by the
|
||||
* generator commands in processing replacements, thus you are warned
|
||||
* not to delete them or modify the names. If you will do so, you may
|
||||
* end up disrupting the scaffolding process and throw errors.
|
||||
*
|
||||
* YOU HAVE BEEN WARNED!
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $views = [
|
||||
'make:command' => 'CodeIgniter\Commands\Generators\Views\command.tpl.php',
|
||||
'make:config' => 'CodeIgniter\Commands\Generators\Views\config.tpl.php',
|
||||
'make:controller' => 'CodeIgniter\Commands\Generators\Views\controller.tpl.php',
|
||||
'make:entity' => 'CodeIgniter\Commands\Generators\Views\entity.tpl.php',
|
||||
'make:filter' => 'CodeIgniter\Commands\Generators\Views\filter.tpl.php',
|
||||
'make:migration' => 'CodeIgniter\Commands\Generators\Views\migration.tpl.php',
|
||||
'make:model' => 'CodeIgniter\Commands\Generators\Views\model.tpl.php',
|
||||
'make:seeder' => 'CodeIgniter\Commands\Generators\Views\seeder.tpl.php',
|
||||
'make:validation' => 'CodeIgniter\Commands\Generators\Views\validation.tpl.php',
|
||||
'session:migration' => 'CodeIgniter\Commands\Generators\Views\migration.tpl.php',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
class Honeypot extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* Makes Honeypot visible or not to human
|
||||
*/
|
||||
public bool $hidden = true;
|
||||
|
||||
/**
|
||||
* Honeypot Label Content
|
||||
*/
|
||||
public string $label = 'Fill This Field';
|
||||
|
||||
/**
|
||||
* Honeypot Field Name
|
||||
*/
|
||||
public string $name = 'honeypot';
|
||||
|
||||
/**
|
||||
* Honeypot HTML Template
|
||||
*/
|
||||
public string $template = '<label>{label}</label><input type="text" name="{name}" value="">';
|
||||
|
||||
/**
|
||||
* Honeypot container
|
||||
*
|
||||
* If you enabled CSP, you can remove `style="display:none"`.
|
||||
*/
|
||||
public string $container = '<div style="display:none">{template}</div>';
|
||||
|
||||
/**
|
||||
* The id attribute for Honeypot container tag
|
||||
*
|
||||
* Used when CSP is enabled.
|
||||
*/
|
||||
public string $containerId = 'hpc';
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Images\Handlers\GDHandler;
|
||||
use CodeIgniter\Images\Handlers\ImageMagickHandler;
|
||||
|
||||
class Images extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* Default handler used if no other handler is specified.
|
||||
*/
|
||||
public string $defaultHandler = 'gd';
|
||||
|
||||
/**
|
||||
* The path to the image library.
|
||||
* Required for ImageMagick, GraphicsMagick, or NetPBM.
|
||||
*/
|
||||
public string $libraryPath = '/usr/local/bin/convert';
|
||||
|
||||
/**
|
||||
* The available handler classes.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $handlers = [
|
||||
'gd' => GDHandler::class,
|
||||
'imagick' => ImageMagickHandler::class,
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use Kint\Renderer\AbstractRenderer;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Kint
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* We use Kint's `RichRenderer` and `CLIRenderer`. This area contains options
|
||||
* that you can set to customize how Kint works for you.
|
||||
*
|
||||
* @see https://kint-php.github.io/kint/ for details on these settings.
|
||||
*/
|
||||
class Kint extends BaseConfig
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Global Settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public $plugins;
|
||||
public int $maxDepth = 6;
|
||||
public bool $displayCalledFrom = true;
|
||||
public bool $expanded = false;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| RichRenderer Settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
public string $richTheme = 'aante-light.css';
|
||||
public bool $richFolder = false;
|
||||
public int $richSort = AbstractRenderer::SORT_FULL;
|
||||
public $richObjectPlugins;
|
||||
public $richTabPlugins;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| CLI Settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
public bool $cliColors = true;
|
||||
public bool $cliForceUTF8 = false;
|
||||
public bool $cliDetectWidth = true;
|
||||
public int $cliMinWidth = 40;
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Log\Handlers\FileHandler;
|
||||
|
||||
class Logger extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Error Logging Threshold
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* You can enable error logging by setting a threshold over zero. The
|
||||
* threshold determines what gets logged. Any values below or equal to the
|
||||
* threshold will be logged.
|
||||
*
|
||||
* Threshold options are:
|
||||
*
|
||||
* - 0 = Disables logging, Error logging TURNED OFF
|
||||
* - 1 = Emergency Messages - System is unusable
|
||||
* - 2 = Alert Messages - Action Must Be Taken Immediately
|
||||
* - 3 = Critical Messages - Application component unavailable, unexpected exception.
|
||||
* - 4 = Runtime Errors - Don't need immediate action, but should be monitored.
|
||||
* - 5 = Warnings - Exceptional occurrences that are not errors.
|
||||
* - 6 = Notices - Normal but significant events.
|
||||
* - 7 = Info - Interesting events, like user logging in, etc.
|
||||
* - 8 = Debug - Detailed debug information.
|
||||
* - 9 = All Messages
|
||||
*
|
||||
* You can also pass an array with threshold levels to show individual error types
|
||||
*
|
||||
* array(1, 2, 3, 8) = Emergency, Alert, Critical, and Debug messages
|
||||
*
|
||||
* For a live site you'll usually enable Critical or higher (3) to be logged otherwise
|
||||
* your log files will fill up very fast.
|
||||
*
|
||||
* @var array|int
|
||||
*/
|
||||
public $threshold = (ENVIRONMENT === 'production') ? 4 : 9;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Date Format for Logs
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Each item that is logged has an associated date. You can use PHP date
|
||||
* codes to set your own date formatting
|
||||
*/
|
||||
public string $dateFormat = 'Y-m-d H:i:s';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Log Handlers
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The logging system supports multiple actions to be taken when something
|
||||
* is logged. This is done by allowing for multiple Handlers, special classes
|
||||
* designed to write the log to their chosen destinations, whether that is
|
||||
* a file on the getServer, a cloud-based service, or even taking actions such
|
||||
* as emailing the dev team.
|
||||
*
|
||||
* Each handler is defined by the class name used for that handler, and it
|
||||
* MUST implement the `CodeIgniter\Log\Handlers\HandlerInterface` interface.
|
||||
*
|
||||
* The value of each key is an array of configuration items that are sent
|
||||
* to the constructor of each handler. The only required configuration item
|
||||
* is the 'handles' element, which must be an array of integer log levels.
|
||||
* This is most easily handled by using the constants defined in the
|
||||
* `Psr\Log\LogLevel` class.
|
||||
*
|
||||
* Handlers are executed in the order defined in this array, starting with
|
||||
* the handler on top and continuing down.
|
||||
*/
|
||||
public array $handlers = [
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* File Handler
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
FileHandler::class => [
|
||||
|
||||
// The log levels that this handler will handle.
|
||||
'handles' => [
|
||||
'critical',
|
||||
'alert',
|
||||
'emergency',
|
||||
'debug',
|
||||
'error',
|
||||
'info',
|
||||
'notice',
|
||||
'warning',
|
||||
],
|
||||
|
||||
/*
|
||||
* The default filename extension for log files.
|
||||
* An extension of 'php' allows for protecting the log files via basic
|
||||
* scripting, when they are to be stored under a publicly accessible directory.
|
||||
*
|
||||
* Note: Leaving it blank will default to 'log'.
|
||||
*/
|
||||
'fileExtension' => '',
|
||||
|
||||
/*
|
||||
* The file system permissions to be applied on newly created log files.
|
||||
*
|
||||
* IMPORTANT: This MUST be an integer (no quotes) and you MUST use octal
|
||||
* integer notation (i.e. 0700, 0644, etc.)
|
||||
*/
|
||||
'filePermissions' => 0644,
|
||||
|
||||
/*
|
||||
* Logging Directory Path
|
||||
*
|
||||
* By default, logs are written to WRITEPATH . 'logs/'
|
||||
* Specify a different destination here, if desired.
|
||||
*/
|
||||
'path' => '',
|
||||
],
|
||||
|
||||
/*
|
||||
* The ChromeLoggerHandler requires the use of the Chrome web browser
|
||||
* and the ChromeLogger extension. Uncomment this block to use it.
|
||||
*/
|
||||
// 'CodeIgniter\Log\Handlers\ChromeLoggerHandler' => [
|
||||
// /*
|
||||
// * The log levels that this handler will handle.
|
||||
// */
|
||||
// 'handles' => ['critical', 'alert', 'emergency', 'debug',
|
||||
// 'error', 'info', 'notice', 'warning'],
|
||||
// ],
|
||||
|
||||
/*
|
||||
* The ErrorlogHandler writes the logs to PHP's native `error_log()` function.
|
||||
* Uncomment this block to use it.
|
||||
*/
|
||||
// 'CodeIgniter\Log\Handlers\ErrorlogHandler' => [
|
||||
// /* The log levels this handler can handle. */
|
||||
// 'handles' => ['critical', 'alert', 'emergency', 'debug', 'error', 'info', 'notice', 'warning'],
|
||||
//
|
||||
// /*
|
||||
// * The message type where the error should go. Can be 0 or 4, or use the
|
||||
// * class constants: `ErrorlogHandler::TYPE_OS` (0) or `ErrorlogHandler::TYPE_SAPI` (4)
|
||||
// */
|
||||
// 'messageType' => 0,
|
||||
// ],
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
class Migrations extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Enable/Disable Migrations
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Migrations are enabled by default.
|
||||
*
|
||||
* You should enable migrations whenever you intend to do a schema migration
|
||||
* and disable it back when you're done.
|
||||
*/
|
||||
public bool $enabled = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Migrations Table
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* This is the name of the table that will store the current migrations state.
|
||||
* When migrations runs it will store in a database table which migration
|
||||
* level the system is at. It then compares the migration level in this
|
||||
* table to the $config['migration_version'] if they are not the same it
|
||||
* will migrate up. This must be set.
|
||||
*/
|
||||
public string $table = 'migrations';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Timestamp Format
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* This is the format that will be used when creating new migrations
|
||||
* using the CLI command:
|
||||
* > php spark make:migration
|
||||
*
|
||||
* Note: if you set an unsupported format, migration runner will not find
|
||||
* your migration files.
|
||||
*
|
||||
* Supported formats:
|
||||
* - YmdHis_
|
||||
* - Y-m-d-His_
|
||||
* - Y_m_d_His_
|
||||
*/
|
||||
public string $timestampFormat = 'Y-m-d-His_';
|
||||
}
|
||||
@@ -0,0 +1,530 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
/**
|
||||
* Mimes
|
||||
*
|
||||
* This file contains an array of mime types. It is used by the
|
||||
* Upload class to help identify allowed file types.
|
||||
*
|
||||
* When more than one variation for an extension exist (like jpg, jpeg, etc)
|
||||
* the most common one should be first in the array to aid the guess*
|
||||
* methods. The same applies when more than one mime-type exists for a
|
||||
* single extension.
|
||||
*
|
||||
* When working with mime types, please make sure you have the ´fileinfo´
|
||||
* extension enabled to reliably detect the media types.
|
||||
*/
|
||||
class Mimes
|
||||
{
|
||||
/**
|
||||
* Map of extensions to mime types.
|
||||
*/
|
||||
public static array $mimes = [
|
||||
'hqx' => [
|
||||
'application/mac-binhex40',
|
||||
'application/mac-binhex',
|
||||
'application/x-binhex40',
|
||||
'application/x-mac-binhex40',
|
||||
],
|
||||
'cpt' => 'application/mac-compactpro',
|
||||
'csv' => [
|
||||
'text/csv',
|
||||
'text/x-comma-separated-values',
|
||||
'text/comma-separated-values',
|
||||
'application/vnd.ms-excel',
|
||||
'application/x-csv',
|
||||
'text/x-csv',
|
||||
'application/csv',
|
||||
'application/excel',
|
||||
'application/vnd.msexcel',
|
||||
'text/plain',
|
||||
],
|
||||
'bin' => [
|
||||
'application/macbinary',
|
||||
'application/mac-binary',
|
||||
'application/octet-stream',
|
||||
'application/x-binary',
|
||||
'application/x-macbinary',
|
||||
],
|
||||
'dms' => 'application/octet-stream',
|
||||
'lha' => 'application/octet-stream',
|
||||
'lzh' => 'application/octet-stream',
|
||||
'exe' => [
|
||||
'application/octet-stream',
|
||||
'application/x-msdownload',
|
||||
],
|
||||
'class' => 'application/octet-stream',
|
||||
'psd' => [
|
||||
'application/x-photoshop',
|
||||
'image/vnd.adobe.photoshop',
|
||||
],
|
||||
'so' => 'application/octet-stream',
|
||||
'sea' => 'application/octet-stream',
|
||||
'dll' => 'application/octet-stream',
|
||||
'oda' => 'application/oda',
|
||||
'pdf' => [
|
||||
'application/pdf',
|
||||
'application/force-download',
|
||||
'application/x-download',
|
||||
],
|
||||
'ai' => [
|
||||
'application/pdf',
|
||||
'application/postscript',
|
||||
],
|
||||
'eps' => 'application/postscript',
|
||||
'ps' => 'application/postscript',
|
||||
'smi' => 'application/smil',
|
||||
'smil' => 'application/smil',
|
||||
'mif' => 'application/vnd.mif',
|
||||
'xls' => [
|
||||
'application/vnd.ms-excel',
|
||||
'application/msexcel',
|
||||
'application/x-msexcel',
|
||||
'application/x-ms-excel',
|
||||
'application/x-excel',
|
||||
'application/x-dos_ms_excel',
|
||||
'application/xls',
|
||||
'application/x-xls',
|
||||
'application/excel',
|
||||
'application/download',
|
||||
'application/vnd.ms-office',
|
||||
'application/msword',
|
||||
],
|
||||
'ppt' => [
|
||||
'application/vnd.ms-powerpoint',
|
||||
'application/powerpoint',
|
||||
'application/vnd.ms-office',
|
||||
'application/msword',
|
||||
],
|
||||
'pptx' => [
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
],
|
||||
'wbxml' => 'application/wbxml',
|
||||
'wmlc' => 'application/wmlc',
|
||||
'dcr' => 'application/x-director',
|
||||
'dir' => 'application/x-director',
|
||||
'dxr' => 'application/x-director',
|
||||
'dvi' => 'application/x-dvi',
|
||||
'gtar' => 'application/x-gtar',
|
||||
'gz' => 'application/x-gzip',
|
||||
'gzip' => 'application/x-gzip',
|
||||
'php' => [
|
||||
'application/x-php',
|
||||
'application/x-httpd-php',
|
||||
'application/php',
|
||||
'text/php',
|
||||
'text/x-php',
|
||||
'application/x-httpd-php-source',
|
||||
],
|
||||
'php4' => 'application/x-httpd-php',
|
||||
'php3' => 'application/x-httpd-php',
|
||||
'phtml' => 'application/x-httpd-php',
|
||||
'phps' => 'application/x-httpd-php-source',
|
||||
'js' => [
|
||||
'application/x-javascript',
|
||||
'text/plain',
|
||||
],
|
||||
'swf' => 'application/x-shockwave-flash',
|
||||
'sit' => 'application/x-stuffit',
|
||||
'tar' => 'application/x-tar',
|
||||
'tgz' => [
|
||||
'application/x-tar',
|
||||
'application/x-gzip-compressed',
|
||||
],
|
||||
'z' => 'application/x-compress',
|
||||
'xhtml' => 'application/xhtml+xml',
|
||||
'xht' => 'application/xhtml+xml',
|
||||
'zip' => [
|
||||
'application/x-zip',
|
||||
'application/zip',
|
||||
'application/x-zip-compressed',
|
||||
'application/s-compressed',
|
||||
'multipart/x-zip',
|
||||
],
|
||||
'rar' => [
|
||||
'application/vnd.rar',
|
||||
'application/x-rar',
|
||||
'application/rar',
|
||||
'application/x-rar-compressed',
|
||||
],
|
||||
'mid' => 'audio/midi',
|
||||
'midi' => 'audio/midi',
|
||||
'mpga' => 'audio/mpeg',
|
||||
'mp2' => 'audio/mpeg',
|
||||
'mp3' => [
|
||||
'audio/mpeg',
|
||||
'audio/mpg',
|
||||
'audio/mpeg3',
|
||||
'audio/mp3',
|
||||
],
|
||||
'aif' => [
|
||||
'audio/x-aiff',
|
||||
'audio/aiff',
|
||||
],
|
||||
'aiff' => [
|
||||
'audio/x-aiff',
|
||||
'audio/aiff',
|
||||
],
|
||||
'aifc' => 'audio/x-aiff',
|
||||
'ram' => 'audio/x-pn-realaudio',
|
||||
'rm' => 'audio/x-pn-realaudio',
|
||||
'rpm' => 'audio/x-pn-realaudio-plugin',
|
||||
'ra' => 'audio/x-realaudio',
|
||||
'rv' => 'video/vnd.rn-realvideo',
|
||||
'wav' => [
|
||||
'audio/x-wav',
|
||||
'audio/wave',
|
||||
'audio/wav',
|
||||
],
|
||||
'bmp' => [
|
||||
'image/bmp',
|
||||
'image/x-bmp',
|
||||
'image/x-bitmap',
|
||||
'image/x-xbitmap',
|
||||
'image/x-win-bitmap',
|
||||
'image/x-windows-bmp',
|
||||
'image/ms-bmp',
|
||||
'image/x-ms-bmp',
|
||||
'application/bmp',
|
||||
'application/x-bmp',
|
||||
'application/x-win-bitmap',
|
||||
],
|
||||
'gif' => 'image/gif',
|
||||
'jpg' => [
|
||||
'image/jpeg',
|
||||
'image/pjpeg',
|
||||
],
|
||||
'jpeg' => [
|
||||
'image/jpeg',
|
||||
'image/pjpeg',
|
||||
],
|
||||
'jpe' => [
|
||||
'image/jpeg',
|
||||
'image/pjpeg',
|
||||
],
|
||||
'jp2' => [
|
||||
'image/jp2',
|
||||
'video/mj2',
|
||||
'image/jpx',
|
||||
'image/jpm',
|
||||
],
|
||||
'j2k' => [
|
||||
'image/jp2',
|
||||
'video/mj2',
|
||||
'image/jpx',
|
||||
'image/jpm',
|
||||
],
|
||||
'jpf' => [
|
||||
'image/jp2',
|
||||
'video/mj2',
|
||||
'image/jpx',
|
||||
'image/jpm',
|
||||
],
|
||||
'jpg2' => [
|
||||
'image/jp2',
|
||||
'video/mj2',
|
||||
'image/jpx',
|
||||
'image/jpm',
|
||||
],
|
||||
'jpx' => [
|
||||
'image/jp2',
|
||||
'video/mj2',
|
||||
'image/jpx',
|
||||
'image/jpm',
|
||||
],
|
||||
'jpm' => [
|
||||
'image/jp2',
|
||||
'video/mj2',
|
||||
'image/jpx',
|
||||
'image/jpm',
|
||||
],
|
||||
'mj2' => [
|
||||
'image/jp2',
|
||||
'video/mj2',
|
||||
'image/jpx',
|
||||
'image/jpm',
|
||||
],
|
||||
'mjp2' => [
|
||||
'image/jp2',
|
||||
'video/mj2',
|
||||
'image/jpx',
|
||||
'image/jpm',
|
||||
],
|
||||
'png' => [
|
||||
'image/png',
|
||||
'image/x-png',
|
||||
],
|
||||
'webp' => 'image/webp',
|
||||
'tif' => 'image/tiff',
|
||||
'tiff' => 'image/tiff',
|
||||
'css' => [
|
||||
'text/css',
|
||||
'text/plain',
|
||||
],
|
||||
'html' => [
|
||||
'text/html',
|
||||
'text/plain',
|
||||
],
|
||||
'htm' => [
|
||||
'text/html',
|
||||
'text/plain',
|
||||
],
|
||||
'shtml' => [
|
||||
'text/html',
|
||||
'text/plain',
|
||||
],
|
||||
'txt' => 'text/plain',
|
||||
'text' => 'text/plain',
|
||||
'log' => [
|
||||
'text/plain',
|
||||
'text/x-log',
|
||||
],
|
||||
'rtx' => 'text/richtext',
|
||||
'rtf' => 'text/rtf',
|
||||
'xml' => [
|
||||
'application/xml',
|
||||
'text/xml',
|
||||
'text/plain',
|
||||
],
|
||||
'xsl' => [
|
||||
'application/xml',
|
||||
'text/xsl',
|
||||
'text/xml',
|
||||
],
|
||||
'mpeg' => 'video/mpeg',
|
||||
'mpg' => 'video/mpeg',
|
||||
'mpe' => 'video/mpeg',
|
||||
'qt' => 'video/quicktime',
|
||||
'mov' => 'video/quicktime',
|
||||
'avi' => [
|
||||
'video/x-msvideo',
|
||||
'video/msvideo',
|
||||
'video/avi',
|
||||
'application/x-troff-msvideo',
|
||||
],
|
||||
'movie' => 'video/x-sgi-movie',
|
||||
'doc' => [
|
||||
'application/msword',
|
||||
'application/vnd.ms-office',
|
||||
],
|
||||
'docx' => [
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'application/zip',
|
||||
'application/msword',
|
||||
'application/x-zip',
|
||||
],
|
||||
'dot' => [
|
||||
'application/msword',
|
||||
'application/vnd.ms-office',
|
||||
],
|
||||
'dotx' => [
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'application/zip',
|
||||
'application/msword',
|
||||
],
|
||||
'xlsx' => [
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'application/zip',
|
||||
'application/vnd.ms-excel',
|
||||
'application/msword',
|
||||
'application/x-zip',
|
||||
],
|
||||
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
|
||||
'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
|
||||
'word' => [
|
||||
'application/msword',
|
||||
'application/octet-stream',
|
||||
],
|
||||
'xl' => 'application/excel',
|
||||
'eml' => 'message/rfc822',
|
||||
'json' => [
|
||||
'application/json',
|
||||
'text/json',
|
||||
],
|
||||
'pem' => [
|
||||
'application/x-x509-user-cert',
|
||||
'application/x-pem-file',
|
||||
'application/octet-stream',
|
||||
],
|
||||
'p10' => [
|
||||
'application/x-pkcs10',
|
||||
'application/pkcs10',
|
||||
],
|
||||
'p12' => 'application/x-pkcs12',
|
||||
'p7a' => 'application/x-pkcs7-signature',
|
||||
'p7c' => [
|
||||
'application/pkcs7-mime',
|
||||
'application/x-pkcs7-mime',
|
||||
],
|
||||
'p7m' => [
|
||||
'application/pkcs7-mime',
|
||||
'application/x-pkcs7-mime',
|
||||
],
|
||||
'p7r' => 'application/x-pkcs7-certreqresp',
|
||||
'p7s' => 'application/pkcs7-signature',
|
||||
'crt' => [
|
||||
'application/x-x509-ca-cert',
|
||||
'application/x-x509-user-cert',
|
||||
'application/pkix-cert',
|
||||
],
|
||||
'crl' => [
|
||||
'application/pkix-crl',
|
||||
'application/pkcs-crl',
|
||||
],
|
||||
'der' => 'application/x-x509-ca-cert',
|
||||
'kdb' => 'application/octet-stream',
|
||||
'pgp' => 'application/pgp',
|
||||
'gpg' => 'application/gpg-keys',
|
||||
'sst' => 'application/octet-stream',
|
||||
'csr' => 'application/octet-stream',
|
||||
'rsa' => 'application/x-pkcs7',
|
||||
'cer' => [
|
||||
'application/pkix-cert',
|
||||
'application/x-x509-ca-cert',
|
||||
],
|
||||
'3g2' => 'video/3gpp2',
|
||||
'3gp' => [
|
||||
'video/3gp',
|
||||
'video/3gpp',
|
||||
],
|
||||
'mp4' => 'video/mp4',
|
||||
'm4a' => 'audio/x-m4a',
|
||||
'f4v' => [
|
||||
'video/mp4',
|
||||
'video/x-f4v',
|
||||
],
|
||||
'flv' => 'video/x-flv',
|
||||
'webm' => 'video/webm',
|
||||
'aac' => 'audio/x-acc',
|
||||
'm4u' => 'application/vnd.mpegurl',
|
||||
'm3u' => 'text/plain',
|
||||
'xspf' => 'application/xspf+xml',
|
||||
'vlc' => 'application/videolan',
|
||||
'wmv' => [
|
||||
'video/x-ms-wmv',
|
||||
'video/x-ms-asf',
|
||||
],
|
||||
'au' => 'audio/x-au',
|
||||
'ac3' => 'audio/ac3',
|
||||
'flac' => 'audio/x-flac',
|
||||
'ogg' => [
|
||||
'audio/ogg',
|
||||
'video/ogg',
|
||||
'application/ogg',
|
||||
],
|
||||
'kmz' => [
|
||||
'application/vnd.google-earth.kmz',
|
||||
'application/zip',
|
||||
'application/x-zip',
|
||||
],
|
||||
'kml' => [
|
||||
'application/vnd.google-earth.kml+xml',
|
||||
'application/xml',
|
||||
'text/xml',
|
||||
],
|
||||
'ics' => 'text/calendar',
|
||||
'ical' => 'text/calendar',
|
||||
'zsh' => 'text/x-scriptzsh',
|
||||
'7zip' => [
|
||||
'application/x-compressed',
|
||||
'application/x-zip-compressed',
|
||||
'application/zip',
|
||||
'multipart/x-zip',
|
||||
],
|
||||
'cdr' => [
|
||||
'application/cdr',
|
||||
'application/coreldraw',
|
||||
'application/x-cdr',
|
||||
'application/x-coreldraw',
|
||||
'image/cdr',
|
||||
'image/x-cdr',
|
||||
'zz-application/zz-winassoc-cdr',
|
||||
],
|
||||
'wma' => [
|
||||
'audio/x-ms-wma',
|
||||
'video/x-ms-asf',
|
||||
],
|
||||
'jar' => [
|
||||
'application/java-archive',
|
||||
'application/x-java-application',
|
||||
'application/x-jar',
|
||||
'application/x-compressed',
|
||||
],
|
||||
'svg' => [
|
||||
'image/svg+xml',
|
||||
'image/svg',
|
||||
'application/xml',
|
||||
'text/xml',
|
||||
],
|
||||
'vcf' => 'text/x-vcard',
|
||||
'srt' => [
|
||||
'text/srt',
|
||||
'text/plain',
|
||||
],
|
||||
'vtt' => [
|
||||
'text/vtt',
|
||||
'text/plain',
|
||||
],
|
||||
'ico' => [
|
||||
'image/x-icon',
|
||||
'image/x-ico',
|
||||
'image/vnd.microsoft.icon',
|
||||
],
|
||||
'stl' => [
|
||||
'application/sla',
|
||||
'application/vnd.ms-pki.stl',
|
||||
'application/x-navistyle',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Attempts to determine the best mime type for the given file extension.
|
||||
*
|
||||
* @return string|null The mime type found, or none if unable to determine.
|
||||
*/
|
||||
public static function guessTypeFromExtension(string $extension)
|
||||
{
|
||||
$extension = trim(strtolower($extension), '. ');
|
||||
|
||||
if (! array_key_exists($extension, static::$mimes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return is_array(static::$mimes[$extension]) ? static::$mimes[$extension][0] : static::$mimes[$extension];
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to determine the best file extension for a given mime type.
|
||||
*
|
||||
* @param string|null $proposedExtension - default extension (in case there is more than one with the same mime type)
|
||||
*
|
||||
* @return string|null The extension determined, or null if unable to match.
|
||||
*/
|
||||
public static function guessExtensionFromType(string $type, ?string $proposedExtension = null)
|
||||
{
|
||||
$type = trim(strtolower($type), '. ');
|
||||
|
||||
$proposedExtension = trim(strtolower($proposedExtension ?? ''));
|
||||
|
||||
if (
|
||||
$proposedExtension !== ''
|
||||
&& array_key_exists($proposedExtension, static::$mimes)
|
||||
&& in_array($type, (array) static::$mimes[$proposedExtension], true)
|
||||
) {
|
||||
// The detected mime type matches with the proposed extension.
|
||||
return $proposedExtension;
|
||||
}
|
||||
|
||||
// Reverse check the mime type list if no extension was proposed.
|
||||
// This search is order sensitive!
|
||||
foreach (static::$mimes as $ext => $types) {
|
||||
if (in_array($type, (array) $types, true)) {
|
||||
return $ext;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Modules\Modules as BaseModules;
|
||||
|
||||
class Modules extends BaseModules
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Enable Auto-Discovery?
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If true, then auto-discovery will happen across all elements listed in
|
||||
* $aliases below. If false, no auto-discovery will happen at all,
|
||||
* giving a slight performance boost.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $enabled = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Enable Auto-Discovery Within Composer Packages?
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If true, then auto-discovery will happen across all namespaces loaded
|
||||
* by Composer, as well as the namespaces configured locally.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $discoverInComposer = true;
|
||||
|
||||
/**
|
||||
* The Composer package list for Auto-Discovery
|
||||
* This setting is optional.
|
||||
*
|
||||
* E.g.:
|
||||
* [
|
||||
* 'only' => [
|
||||
* // List up all packages to auto-discover
|
||||
* 'codeigniter4/shield',
|
||||
* ],
|
||||
* ]
|
||||
* or
|
||||
* [
|
||||
* 'exclude' => [
|
||||
* // List up packages to exclude.
|
||||
* 'pestphp/pest',
|
||||
* ],
|
||||
* ]
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $composerPackages = [];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Auto-Discovery Rules
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Aliases list of all discovery classes that will be active and used during
|
||||
* the current application request.
|
||||
*
|
||||
* If it is not listed, only the base application elements will be used.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public $aliases = [
|
||||
'events',
|
||||
'filters',
|
||||
'registrars',
|
||||
'routes',
|
||||
'services',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
class Pager extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Templates
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Pagination links are rendered out using views to configure their
|
||||
* appearance. This array contains aliases and the view names to
|
||||
* use when rendering the links.
|
||||
*
|
||||
* Within each view, the Pager object will be available as $pager,
|
||||
* and the desired group as $pagerGroup;
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $templates = [
|
||||
'default_full' => 'CodeIgniter\Pager\Views\default_full',
|
||||
'default_simple' => 'CodeIgniter\Pager\Views\default_simple',
|
||||
'default_head' => 'CodeIgniter\Pager\Views\default_head',
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Items Per Page
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The default number of results shown in a single page.
|
||||
*/
|
||||
public int $perPage = 20;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
/**
|
||||
* Paths
|
||||
*
|
||||
* Holds the paths that are used by the system to
|
||||
* locate the main directories, app, system, etc.
|
||||
*
|
||||
* Modifying these allows you to restructure your application,
|
||||
* share a system folder between multiple applications, and more.
|
||||
*
|
||||
* All paths are relative to the project's root folder.
|
||||
*/
|
||||
class Paths
|
||||
{
|
||||
/**
|
||||
* ---------------------------------------------------------------
|
||||
* SYSTEM FOLDER NAME
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* This must contain the name of your "system" folder. Include
|
||||
* the path if the folder is not in the same directory as this file.
|
||||
*/
|
||||
public string $systemDirectory = __DIR__ . '/../../vendor/codeigniter4/framework/system';
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------
|
||||
* APPLICATION FOLDER NAME
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* If you want this front controller to use a different "app"
|
||||
* folder than the default one you can set its name here. The folder
|
||||
* can also be renamed or relocated anywhere on your server. If
|
||||
* you do, use a full server path.
|
||||
*
|
||||
* @see http://codeigniter.com/user_guide/general/managing_apps.html
|
||||
*/
|
||||
public string $appDirectory = __DIR__ . '/..';
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------
|
||||
* WRITABLE DIRECTORY NAME
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* This variable must contain the name of your "writable" directory.
|
||||
* The writable directory allows you to group all directories that
|
||||
* need write permission to a single place that can be tucked away
|
||||
* for maximum security, keeping it out of the app and/or
|
||||
* system directories.
|
||||
*/
|
||||
public string $writableDirectory = __DIR__ . '/../../writable';
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------
|
||||
* TESTS DIRECTORY NAME
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* This variable must contain the name of your "tests" directory.
|
||||
*/
|
||||
public string $testsDirectory = __DIR__ . '/../../tests';
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------
|
||||
* VIEW DIRECTORY NAME
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* This variable must contain the name of the directory that
|
||||
* contains the view files used by your application. By
|
||||
* default this is in `app/Views`. This value
|
||||
* is used when no value is provided to `Services::renderer()`.
|
||||
*/
|
||||
public string $viewDirectory = __DIR__ . '/../Views';
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\Publisher as BasePublisher;
|
||||
|
||||
/**
|
||||
* Publisher Configuration
|
||||
*
|
||||
* Defines basic security restrictions for the Publisher class
|
||||
* to prevent abuse by injecting malicious files into a project.
|
||||
*/
|
||||
class Publisher extends BasePublisher
|
||||
{
|
||||
/**
|
||||
* A list of allowed destinations with a (pseudo-)regex
|
||||
* of allowed files for each destination.
|
||||
* Attempts to publish to directories not in this list will
|
||||
* result in a PublisherException. Files that do no fit the
|
||||
* pattern will cause copy/merge to fail.
|
||||
*
|
||||
* @var array<string,string>
|
||||
*/
|
||||
public $restrictions = [
|
||||
ROOTPATH => '*',
|
||||
FCPATH => '#\.(s?css|js|map|html?|xml|json|webmanifest|ttf|eot|woff2?|gif|jpe?g|tiff?|png|webp|bmp|ico|svg)$#i',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
// Create a new instance of our RouteCollection class.
|
||||
$routes = Services::routes();
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* Router Setup
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
$routes->setDefaultNamespace('App\Controllers');
|
||||
$routes->setDefaultController('Home');
|
||||
$routes->setDefaultMethod('index');
|
||||
$routes->setTranslateURIDashes(false);
|
||||
$routes->set404Override();
|
||||
// The Auto Routing (Legacy) is very dangerous. It is easy to create vulnerable apps
|
||||
// where controller filters or CSRF protection are bypassed.
|
||||
// If you don't want to define all routes, please use the Auto Routing (Improved).
|
||||
// Set `$autoRoutesImproved` to true in `app/Config/Feature.php` and set the following to true.
|
||||
$routes->setAutoRoute(false);
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* Route Definitions
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
service('auth')->routes($routes, ['except' => ['magic-link']]);
|
||||
$routes->get('login/magic-link', '\App\Controllers\Auth\MagicLinkController::loginView', ['as' => 'magic-link']);
|
||||
$routes->post('login/magic-link', '\App\Controllers\Auth\MagicLinkController::loginAction');
|
||||
$routes->get('login/verify-magic-link', '\App\Controllers\Auth\MagicLinkController::verify', ['as' => 'verify-magic-link']);
|
||||
$routes->get('set-password', '\App\Controllers\Auth\PasswordChangeController::changePasswordView', ['as' => 'set_password']);
|
||||
$routes->post('set-password', '\App\Controllers\Auth\PasswordChangeController::changePasswordAction', ['as' => 'set_password_action']);
|
||||
// We get a performance increase by specifying the default
|
||||
// route since we don't have to scan directories.
|
||||
|
||||
//게스트 - 승인대기중 페이지
|
||||
$routes->group('', ['filter' => 'group:admin,superadmin,developer,guest,test'], static function($routes){
|
||||
$routes->get('guest', 'GuestController::index', ['as' => 'guest']);
|
||||
});
|
||||
|
||||
//관리자, 최고관리자, 개발자, 일반사용자, 광고주, 광고대행사, 테스트
|
||||
$routes->group('', ['filter' => 'auth', 'group' => 'admin,superadmin,developer,user,agency,advertiser,test'], static function($routes){
|
||||
$routes->get('mypage', 'User\UserController::myPage');
|
||||
$routes->post('mypage/update', 'User\UserController::myPageUpdate');
|
||||
$routes->get('password-changed-at', 'User\UserController::setPasswordChangedAtAjax');
|
||||
|
||||
$routes->group('', ['filter' => 'group:superadmin,admin,developer,user,test'], static function($routes){
|
||||
$routes->get('/', 'HomeController::index');
|
||||
$routes->get('/home', 'HomeController::index');
|
||||
$routes->get('/home/report', 'HomeController::getReports');
|
||||
$routes->get('pages/(:any)', 'PageController::view/$1');
|
||||
});
|
||||
|
||||
//광고주, 광고대행사 관리
|
||||
$routes->group('', ['filter' => 'group:superadmin,admin,developer,user,test', 'permission:admin.access,admin.settings,agency.access'], static function($routes){
|
||||
$routes->get('company', 'Company\CompanyController::index');
|
||||
$routes->get('company/get-companies', 'Company\CompanyController::getCompanies');
|
||||
$routes->get('company/get-company', 'Company\CompanyController::getCompany');
|
||||
$routes->get('company/get-search-agencies', 'Company\CompanyController::getSearchAgencies');
|
||||
$routes->post('company/create-company', 'Company\CompanyController::createCompany');
|
||||
$routes->put('company/set-company', 'Company\CompanyController::setCompany');
|
||||
$routes->delete('company/delete-company', 'Company\CompanyController::deleteCompany');
|
||||
|
||||
$routes->get('company/get-search-users', 'User\UserController::getSearchUsers');
|
||||
$routes->get('company/get-belong-users', 'User\UserController::getBelongUsers');
|
||||
$routes->put('company/set-belong-user', 'User\UserController::setBelongUser');
|
||||
$routes->delete('company/except-belong-user', 'User\UserController::exceptBelongUser');
|
||||
|
||||
$routes->get('company/get-search-adaccounts', 'Company\CompanyController::getSearchAdAccounts');
|
||||
$routes->get('company/get-company-adaccounts', 'Company\CompanyController::getCompanyAdAccounts');
|
||||
$routes->put('company/set-adaccounts', 'Company\CompanyController::setCompanyAdAccount');
|
||||
$routes->delete('company/except-company-adaccount', 'Company\CompanyController::exceptCompanyAdAccount');
|
||||
});
|
||||
|
||||
// 회원 관리
|
||||
$routes->group('', ['filter' => 'group:admin,superadmin,developer,user', 'permission:admin.access,admin.settings'], static function($routes){
|
||||
$routes->get('user', 'User\UserController::index');
|
||||
$routes->get('user/get-users', 'User\UserController::getUsers');
|
||||
$routes->get('user/get-user', 'User\UserController::getUser');
|
||||
$routes->get('company/get-search-companies', 'Company\CompanyController::getSearchCompanies');
|
||||
$routes->put('company/set-user', 'User\UserController::setUser');
|
||||
});
|
||||
|
||||
// 광고관리
|
||||
$routes->group('advertisements', ['filter' => 'group:superadmin,admin,developer,user,test'], static function($routes){
|
||||
$routes->get('', 'AdvertisementManager\AdvManagerController::index');
|
||||
$routes->get('data', 'AdvertisementManager\AdvManagerController::getData');
|
||||
$routes->get('report', 'AdvertisementManager\AdvManagerController::getReportData');
|
||||
$routes->get('accounts', 'AdvertisementManager\AdvManagerController::getAccountsData');
|
||||
$routes->get('account-stat', 'AdvertisementManager\AdvManagerController::getAccountStat');
|
||||
$routes->get('mediaAccounts', 'AdvertisementManager\AdvManagerController::getMediaAccountsData');
|
||||
$routes->get('check-data', 'AdvertisementManager\AdvManagerController::getCheckData');
|
||||
$routes->get('diff-report', 'AdvertisementManager\AdvManagerController::getDiffReport');
|
||||
$routes->get('get-adv', 'AdvertisementManager\AdvManagerController::getAdvs');
|
||||
$routes->get('adaccounts', 'AdvertisementManager\AdvManagerController::getOnlyAdAccount');
|
||||
$routes->put('set-dbcount', 'AdvertisementManager\AdvManagerController::setDbCount');
|
||||
$routes->put('set-exposed', 'AdvertisementManager\AdvManagerController::setExposed');
|
||||
$routes->put('set-status', 'AdvertisementManager\AdvManagerController::updateStatus');
|
||||
$routes->put('set-name', 'AdvertisementManager\AdvManagerController::updateName');
|
||||
$routes->put('set-budget', 'AdvertisementManager\AdvManagerController::updateBudget');
|
||||
$routes->put('set-bidamount', 'AdvertisementManager\AdvManagerController::updateBidAmount');
|
||||
$routes->put('set-adv', 'AdvertisementManager\AdvManagerController::updateAdv');
|
||||
$routes->put('set-code', 'AdvertisementManager\AdvManagerController::updateCode');
|
||||
$routes->get('getmemo', 'AdvertisementManager\AdvManagerController::getMemo');
|
||||
$routes->post('addmemo', 'AdvertisementManager\AdvManagerController::addMemo');
|
||||
$routes->post('checkmemo', 'AdvertisementManager\AdvManagerController::checkMemo');
|
||||
$routes->get('change-log', 'AdvertisementManager\AdvManagerController::getChangeLogs');
|
||||
|
||||
$routes->group('facebook', static function($routes){
|
||||
$routes->get('report', 'AdvertisementManager\AdvFacebookManagerController::getReport');
|
||||
});
|
||||
|
||||
$routes->group('kakao', static function($routes){
|
||||
$routes->get('report', 'AdvertisementManager\AdvKakaoManagerController::getReport');
|
||||
});
|
||||
|
||||
$routes->group('google', static function($routes){
|
||||
$routes->get('report', 'AdvertisementManager\AdvGoogleManagerController::getReport');
|
||||
});
|
||||
});
|
||||
|
||||
$routes->group('etcmanager', ['filter' => 'group:superadmin,admin,developer,user,test'], static function($routes){
|
||||
$routes->get('', 'AdvertisementManager\AdvEtcManagerController::index');
|
||||
$routes->post('get-list', 'AdvertisementManager\AdvEtcManagerController::getList');
|
||||
$routes->post('update-data', 'AdvertisementManager\AdvEtcManagerController::updateData');
|
||||
});
|
||||
|
||||
//자동화
|
||||
$routes->group('automation', ['filter' => 'group:superadmin,admin,developer,user,test'], static function($routes){
|
||||
$routes->get('', 'AdvertisementManager\Automation\AutomationController::index');
|
||||
$routes->get('list', 'AdvertisementManager\Automation\AutomationController::getList');
|
||||
$routes->get('adv', 'AdvertisementManager\Automation\AutomationController::getAdv');
|
||||
$routes->put('set-status', 'AdvertisementManager\Automation\AutomationController::setStatus');
|
||||
$routes->get('get-automation', 'AdvertisementManager\Automation\AutomationController::getAutomation');
|
||||
$routes->get('logs', 'AdvertisementManager\Automation\AutomationController::getLogs');
|
||||
$routes->get('log', 'AdvertisementManager\Automation\AutomationController::getLogByAdv');
|
||||
$routes->post('create', 'AdvertisementManager\Automation\AutomationController::createAutomation');
|
||||
$routes->post('copy', 'AdvertisementManager\Automation\AutomationController::copyAutomation');
|
||||
$routes->put('update', 'AdvertisementManager\Automation\AutomationController::updateAutomation');
|
||||
$routes->delete('delete', 'AdvertisementManager\Automation\AutomationController::deleteAutomation');
|
||||
});
|
||||
|
||||
// 통합 DB관리
|
||||
$routes->group('integrate', static function($routes){
|
||||
$routes->get('', 'Integrate\IntegrateController::index');
|
||||
$routes->get('download', 'Integrate\IntegrateController::download');
|
||||
$routes->post('download-send', 'Integrate\IntegrateController::downloadData');
|
||||
$routes->post('list', 'Integrate\IntegrateController::getList');
|
||||
$routes->post('buttons', 'Integrate\IntegrateController::getButtons');
|
||||
$routes->get('lead', 'Integrate\IntegrateController::getLead');
|
||||
$routes->get('leadcount', 'Integrate\IntegrateController::getEventLeadCount');
|
||||
$routes->get('statuscount', 'Integrate\IntegrateController::getStatusCount');
|
||||
$routes->get('getmemo', 'Integrate\IntegrateController::getMemo');
|
||||
$routes->post('addmemo', 'Integrate\IntegrateController::addMemo');
|
||||
$routes->post('setstatus', 'Integrate\IntegrateController::setStatus');
|
||||
});
|
||||
|
||||
// 회계 관리
|
||||
$routes->group('accounting', ['filter' => 'group:superadmin,admin,developer,user,test'], static function($routes){
|
||||
$routes->get('tax', 'Accounting\TaxController::tax');
|
||||
$routes->get('taxList', 'Accounting\TaxController::taxList');
|
||||
$routes->get('unpaid', 'Accounting\UnpaidController::unpaid');
|
||||
|
||||
$routes->group('withdrawList', ['filter' => 'group:superadmin,admin,developer,user,test'], static function($routes) {
|
||||
$routes->get('', 'Accounting\WithdrawController::withdrawList');
|
||||
$routes->post('accountlist', 'Accounting\WithdrawController::accountList');
|
||||
});
|
||||
|
||||
$routes->group('withdraw', ['filter' => 'group:superadmin,admin,developer,user,test'], static function($routes){
|
||||
$routes->get('', 'Accounting\WithdrawController::withdraw');
|
||||
$routes->post('getlist','Accounting\WithdrawController::getList');
|
||||
$routes->get('userlist','Accounting\WithdrawController::userList');
|
||||
$routes->get('typelist','Accounting\WithdrawController::typeList');
|
||||
$routes->post('excel','Accounting\WithdrawController::excelDownload');
|
||||
$routes->get('withdraw_write','Accounting\WithdrawController::withdrawWrite');
|
||||
});
|
||||
});
|
||||
|
||||
// 인사 관리
|
||||
$routes->group('humanresource', ['filter' => 'group:superadmin,admin,developer,user,test'], static function($routes){
|
||||
$routes->get('management', 'HumanResource\HumanResourceController::humanResource');
|
||||
$routes->post('hourticketissue', 'HumanResource\HumanResourceController::getHourTicketIssue');
|
||||
$routes->post('hourticketuse', 'HumanResource\HumanResourceController::getHourTicketUseNew');
|
||||
$routes->post('hourticketall', 'HumanResource\HumanResourceController::getHourTicketAll');
|
||||
$routes->post('hourticketreg', 'HumanResource\HumanResourceController::hourTicketReg');
|
||||
$routes->post('hourticketconfirm', 'HumanResource\HumanResourceController::hourTicketConfirm');
|
||||
$routes->post('issueproc', 'HumanResource\HumanResourceController::issueProc');
|
||||
$routes->post('getgwdata', 'HumanResource\HumanResourceController::getGwData');
|
||||
$routes->post('gwdata', 'HumanResource\HumanResourceController::gwData');
|
||||
});
|
||||
|
||||
// 이벤트
|
||||
$routes->group('eventmanage', ['filter' => 'group:superadmin,admin,developer,user,test'], static function($routes){
|
||||
$routes->group('event', static function($routes){
|
||||
$routes->get('', 'EventManage\EventController::index');
|
||||
$routes->get('list', 'EventManage\EventController::getList');
|
||||
$routes->get('adv', 'EventManage\EventController::getAdv');
|
||||
$routes->get('media', 'EventManage\EventController::getMedia');
|
||||
$routes->post('create', 'EventManage\EventController::createEvent');
|
||||
$routes->post('copy', 'EventManage\EventController::copyEvent');
|
||||
$routes->put('update', 'EventManage\EventController::updateEvent');
|
||||
$routes->get('view', 'EventManage\EventController::getEvent');
|
||||
$routes->delete('delete', 'EventManage\EventController::deleteEvent');
|
||||
$routes->get('impressions', 'EventManage\EventController::getEventImpressions');
|
||||
});
|
||||
|
||||
$routes->group('advertiser', static function($routes){
|
||||
$routes->get('', 'EventManage\AdvertiserController::index');
|
||||
$routes->get('list', 'EventManage\AdvertiserController::getList');
|
||||
$routes->get('view', 'EventManage\AdvertiserController::getAdvertiser');
|
||||
$routes->get('company', 'EventManage\AdvertiserController::getCompanies');
|
||||
$routes->post('create', 'EventManage\AdvertiserController::createAdv');
|
||||
$routes->put('update', 'EventManage\AdvertiserController::updateAdv');
|
||||
});
|
||||
|
||||
$routes->group('media', static function($routes){
|
||||
$routes->get('', 'EventManage\MediaController::index');
|
||||
$routes->get('list', 'EventManage\MediaController::getList');
|
||||
$routes->get('view', 'EventManage\MediaController::getMedia');
|
||||
$routes->post('create', 'EventManage\MediaController::createMedia');
|
||||
$routes->put('update', 'EventManage\MediaController::updateMedia');
|
||||
});
|
||||
|
||||
$routes->group('change', static function($routes){
|
||||
$routes->get('', 'EventManage\ChangeController::index');
|
||||
$routes->get('list', 'EventManage\ChangeController::getList');
|
||||
$routes->get('view', 'EventManage\ChangeController::getChange');
|
||||
$routes->post('create', 'EventManage\ChangeController::createChange');
|
||||
$routes->put('update', 'EventManage\ChangeController::updateChange');
|
||||
});
|
||||
|
||||
$routes->group('blacklist', static function($routes){
|
||||
$routes->get('', 'EventManage\BlackListController::index');
|
||||
$routes->get('list', 'EventManage\BlackListController::getList');
|
||||
$routes->get('view', 'EventManage\BlackListController::getBlackList');
|
||||
$routes->post('create', 'EventManage\BlackListController::createBlackList');
|
||||
$routes->delete('delete', 'EventManage\BlackListController::deleteBlackList');
|
||||
});
|
||||
|
||||
$routes->group('excel', static function($routes){
|
||||
$routes->get('', 'EventManage\ExcelController::index');
|
||||
$routes->post('upload', 'EventManage\ExcelController::upload');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$routes->group('eventmanage', ['filter' => 'group:superadmin,admin,developer,user,test'], static function($routes){
|
||||
$routes->get('/advertisement/(:any)', 'Advertisement\ApiController::$1');
|
||||
$routes->get('fbapi/(:any)', 'Advertisement\Facebook::$1');
|
||||
$routes->get('ggapi/(:any)', 'Advertisement\GoogleAds::$1');
|
||||
$routes->get('calendar', 'Calendar\CalendarController::index');
|
||||
});
|
||||
});
|
||||
$routes->get('example/(:any)', 'ExampleController::view/$1');
|
||||
$routes->get('advertisement/moment/oauth', 'Advertisement\KakaoMoment::oauth');
|
||||
|
||||
$routes->cli('fbapi/(:any)', 'Advertisement\Facebook::$1');
|
||||
$routes->cli('kmapi/(:any)', 'Advertisement\KakaoMoment::$1');
|
||||
$routes->cli('ggapi/(:any)', 'Advertisement\GoogleAds::$1');
|
||||
|
||||
//잠재고객 가져오기
|
||||
$routes->cli('sendToEventLead', 'Advertisement\AdLeadController::sendToEventLead');
|
||||
|
||||
//자동화 실행
|
||||
$routes->cli('automation/exec', 'AdvertisementManager\Automation\AutomationController::automation');
|
||||
$routes->get('automation/exec', 'AdvertisementManager\Automation\AutomationController::automation');
|
||||
$routes->get('auth/slack/callback', '\App\ThirdParty\botman\ChatBot::getToken');
|
||||
|
||||
/* $routes->get('slack/code', '\App\ThirdParty\botman\ChatBot::getCode');
|
||||
$routes->get('auth/slack/callback', '\App\ThirdParty\botman\ChatBot::getToken');
|
||||
$routes->match(['get', 'post'], 'slack/test', '\App\ThirdParty\botman\ChatBot::test'); */
|
||||
$routes->match(['get', 'post'], 'slack/(:any)', '\App\Libraries\slack_api\SlackChat::$1');
|
||||
$routes->cli('slack/(:any)', '\App\Libraries\slack_api\SlackChat::$1');
|
||||
$routes->get('dz/(:any)', '\App\Libraries\Douzone\Douzone::$1');
|
||||
$routes->cli('dz/(:any)', '\App\Libraries\Douzone\Douzone::$1');
|
||||
|
||||
$routes->cli('hr/(:any)', 'HumanResource\HumanResourceController::$1');
|
||||
$routes->get('hr/(:any)', 'HumanResource\HumanResourceController::$1');
|
||||
|
||||
$routes->match(['get', 'post'], 'jira/(:any)', 'Api\JiraController::$1');
|
||||
$routes->match(['get', 'post'], 'interlock/(:any)', 'Api\TestController::$1');
|
||||
|
||||
$routes->get('resta/get-adv', 'Api\RestaController::getList');
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\Routing as BaseRouting;
|
||||
|
||||
/**
|
||||
* Routing configuration
|
||||
*/
|
||||
class Routing extends BaseRouting
|
||||
{
|
||||
/**
|
||||
* An array of files that contain route definitions.
|
||||
* Route files are read in order, with the first match
|
||||
* found taking precedence.
|
||||
*
|
||||
* Default: APPPATH . 'Config/Routes.php'
|
||||
*/
|
||||
public array $routeFiles = [
|
||||
APPPATH . 'Config/Routes.php',
|
||||
];
|
||||
|
||||
/**
|
||||
* The default namespace to use for Controllers when no other
|
||||
* namespace has been specified.
|
||||
*
|
||||
* Default: 'App\Controllers'
|
||||
*/
|
||||
public string $defaultNamespace = 'App\Controllers';
|
||||
|
||||
/**
|
||||
* The default controller to use when no other controller has been
|
||||
* specified.
|
||||
*
|
||||
* Default: 'Home'
|
||||
*/
|
||||
public string $defaultController = 'Home';
|
||||
|
||||
/**
|
||||
* The default method to call on the controller when no other
|
||||
* method has been set in the route.
|
||||
*
|
||||
* Default: 'index'
|
||||
*/
|
||||
public string $defaultMethod = 'index';
|
||||
|
||||
/**
|
||||
* Whether to translate dashes in URIs to underscores.
|
||||
* Primarily useful when using the auto-routing.
|
||||
*
|
||||
* Default: false
|
||||
*/
|
||||
public bool $translateURIDashes = false;
|
||||
|
||||
/**
|
||||
* Sets the class/method that should be called if routing doesn't
|
||||
* find a match. It can be either a closure or the controller/method
|
||||
* name exactly like a route is defined: Users::index
|
||||
*
|
||||
* This setting is passed to the Router class and handled there.
|
||||
*
|
||||
* If you want to use a closure, you will have to set it in the
|
||||
* class constructor or the routes file by calling:
|
||||
*
|
||||
* $routes->set404Override(function() {
|
||||
* // Do something here
|
||||
* });
|
||||
*
|
||||
* Example:
|
||||
* public $override404 = 'App\Errors::show404';
|
||||
*/
|
||||
public ?string $override404 = null;
|
||||
|
||||
/**
|
||||
* If TRUE, the system will attempt to match the URI against
|
||||
* Controllers by matching each segment against folders/files
|
||||
* in APPPATH/Controllers, when a match wasn't found against
|
||||
* defined routes.
|
||||
*
|
||||
* If FALSE, will stop searching and do NO automatic routing.
|
||||
*/
|
||||
public bool $autoRoute = false;
|
||||
|
||||
/**
|
||||
* If TRUE, will enable the use of the 'prioritize' option
|
||||
* when defining routes.
|
||||
*
|
||||
* Default: false
|
||||
*/
|
||||
public bool $prioritize = false;
|
||||
|
||||
/**
|
||||
* Map of URI segments and namespaces. For Auto Routing (Improved).
|
||||
*
|
||||
* The key is the first URI segment. The value is the controller namespace.
|
||||
* E.g.,
|
||||
* [
|
||||
* 'blog' => 'Acme\Blog\Controllers',
|
||||
* ]
|
||||
*
|
||||
* @var array [ uri_segment => namespace ]
|
||||
*/
|
||||
public array $moduleRoutes = [];
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
class Security extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Protection Method
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Protection Method for Cross Site Request Forgery protection.
|
||||
*
|
||||
* @var string 'cookie' or 'session'
|
||||
*/
|
||||
public string $csrfProtection = 'session';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Token Randomization
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Randomize the CSRF Token for added security.
|
||||
*/
|
||||
public bool $tokenRandomize = false;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Token Name
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Token name for Cross Site Request Forgery protection.
|
||||
*/
|
||||
public string $tokenName = 'csrf_test_name';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Header Name
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Header name for Cross Site Request Forgery protection.
|
||||
*/
|
||||
public string $headerName = 'X-CSRF-TOKEN';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Cookie Name
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Cookie name for Cross Site Request Forgery protection.
|
||||
*/
|
||||
public string $cookieName = 'csrf_cookie_name';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Expires
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Expiration time for Cross Site Request Forgery protection cookie.
|
||||
*
|
||||
* Defaults to two hours (in seconds).
|
||||
*/
|
||||
public int $expires = 7200;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Regenerate
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Regenerate CSRF Token on every submission.
|
||||
*/
|
||||
public bool $regenerate = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF Redirect
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Redirect to previous page with error on failure.
|
||||
*/
|
||||
public bool $redirect = false;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* CSRF SameSite
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Setting for CSRF SameSite cookie token.
|
||||
*
|
||||
* Allowed values are: None - Lax - Strict - ''.
|
||||
*
|
||||
* Defaults to `Lax` as recommended in this link:
|
||||
*
|
||||
* @see https://portswigger.net/web-security/csrf/samesite-cookies
|
||||
*
|
||||
* @deprecated `Config\Cookie` $samesite property is used.
|
||||
*/
|
||||
public string $samesite = 'Lax';
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseService;
|
||||
|
||||
/**
|
||||
* Services Configuration file.
|
||||
*
|
||||
* Services are simply other classes/libraries that the system uses
|
||||
* to do its job. This is used by CodeIgniter to allow the core of the
|
||||
* framework to be swapped out easily without affecting the usage within
|
||||
* the rest of your application.
|
||||
*
|
||||
* This file holds any application-specific services, or service overrides
|
||||
* that you might need. An example has been included with the general
|
||||
* method format you should use for your service methods. For more examples,
|
||||
* see the core Services file at system/Config/Services.php.
|
||||
*/
|
||||
class Services extends BaseService
|
||||
{
|
||||
/*
|
||||
* public static function example($getShared = true)
|
||||
* {
|
||||
* if ($getShared) {
|
||||
* return static::getSharedInstance('example');
|
||||
* }
|
||||
*
|
||||
* return new \CodeIgniter\Example();
|
||||
* }
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Session\Handlers\BaseHandler;
|
||||
use CodeIgniter\Session\Handlers\FileHandler;
|
||||
|
||||
class Session extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Driver
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The session storage driver to use:
|
||||
* - `CodeIgniter\Session\Handlers\FileHandler`
|
||||
* - `CodeIgniter\Session\Handlers\DatabaseHandler`
|
||||
* - `CodeIgniter\Session\Handlers\MemcachedHandler`
|
||||
* - `CodeIgniter\Session\Handlers\RedisHandler`
|
||||
*
|
||||
* @phpstan-var class-string<BaseHandler>
|
||||
*/
|
||||
public string $driver = FileHandler::class;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Cookie Name
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The session cookie name, must contain only [0-9a-z_-] characters
|
||||
*/
|
||||
public string $cookieName = 'ci_session';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Expiration
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The number of SECONDS you want the session to last.
|
||||
* Setting to 0 (zero) means expire when the browser is closed.
|
||||
*/
|
||||
public int $expiration = 7200;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Save Path
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The location to save sessions to and is driver dependent.
|
||||
*
|
||||
* For the 'files' driver, it's a path to a writable directory.
|
||||
* WARNING: Only absolute paths are supported!
|
||||
*
|
||||
* For the 'database' driver, it's a table name.
|
||||
* Please read up the manual for the format with other session drivers.
|
||||
*
|
||||
* IMPORTANT: You are REQUIRED to set a valid save path!
|
||||
*/
|
||||
public string $savePath = WRITEPATH . 'session';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Match IP
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Whether to match the user's IP address when reading the session data.
|
||||
*
|
||||
* WARNING: If you're using the database driver, don't forget to update
|
||||
* your session table's PRIMARY KEY when changing this setting.
|
||||
*/
|
||||
public bool $matchIP = false;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Time to Update
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* How many seconds between CI regenerating the session ID.
|
||||
*/
|
||||
public int $timeToUpdate = 300;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Regenerate Destroy
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Whether to destroy session data associated with the old session ID
|
||||
* when auto-regenerating the session ID. When set to FALSE, the data
|
||||
* will be later deleted by the garbage collector.
|
||||
*/
|
||||
public bool $regenerateDestroy = false;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Session Database Group
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* DB Group for the database session.
|
||||
*/
|
||||
public ?string $DBGroup = null;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Tasks\Scheduler;
|
||||
|
||||
class Tasks extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Should performance metrics be logged
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If true, will log the time it takes for each task to run.
|
||||
* Requires the settings table to have been created previously.
|
||||
*/
|
||||
public bool $logPerformance = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Maximum performance logs
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The maximum number of logs that should be saved per Task.
|
||||
* Lower numbers reduced the amount of database required to
|
||||
* store the logs.
|
||||
*/
|
||||
public int $maxLogsPerTask = 10;
|
||||
|
||||
/**
|
||||
* Register any tasks within this method for the application.
|
||||
* Called by the TaskRunner.
|
||||
*/
|
||||
public function init(Scheduler $schedule)
|
||||
{
|
||||
$schedule->command('EventCron')->everyMinute(5)->named('event');
|
||||
|
||||
if(getenv('MY_SERVER_NAME') === 'carelabs'){
|
||||
$schedule->command('GwCron')->cron('0 11-19 * * *')->named('gw');
|
||||
|
||||
$schedule->command('todayDayOff')->cron('0 9-19 * * *')->named('sendSlackForDayOff');
|
||||
|
||||
$schedule->command('HumanResource')->cron('0 11-19 * * *')->named('hr');
|
||||
|
||||
$schedule->command('EvtOverwatch')->everyMinute(10)->named('ow');
|
||||
}
|
||||
|
||||
$schedule->command('Automation')->everyMinute(5)->named('aaCheck');
|
||||
|
||||
$schedule->command('EventDataUpdateCron')->everyMinute(60)->named('eventUpdate');
|
||||
$schedule->command('PreparingIssueMessage')->everyMinute(30)->named('preparingIssue');
|
||||
|
||||
//매달 말일 zenith_logs테이블 생성
|
||||
$schedule->command('ZenithLogTable')->cron('59 23 28 * *')->named('zenithLogTable');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Debug\Toolbar\Collectors\Database;
|
||||
use CodeIgniter\Debug\Toolbar\Collectors\Events;
|
||||
use CodeIgniter\Debug\Toolbar\Collectors\Files;
|
||||
use CodeIgniter\Debug\Toolbar\Collectors\Logs;
|
||||
use CodeIgniter\Debug\Toolbar\Collectors\Routes;
|
||||
use CodeIgniter\Debug\Toolbar\Collectors\Timers;
|
||||
use CodeIgniter\Debug\Toolbar\Collectors\Views;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Debug Toolbar
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The Debug Toolbar provides a way to see information about the performance
|
||||
* and state of your application during that page display. By default it will
|
||||
* NOT be displayed under production environments, and will only display if
|
||||
* `CI_DEBUG` is true, since if it's not, there's not much to display anyway.
|
||||
*/
|
||||
class Toolbar extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Toolbar Collectors
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* List of toolbar collectors that will be called when Debug Toolbar
|
||||
* fires up and collects data from.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public array $collectors = [
|
||||
Timers::class,
|
||||
Database::class,
|
||||
Logs::class,
|
||||
Views::class,
|
||||
// \CodeIgniter\Debug\Toolbar\Collectors\Cache::class,
|
||||
Files::class,
|
||||
Routes::class,
|
||||
Events::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Collect Var Data
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If set to false var data from the views will not be colleted. Useful to
|
||||
* avoid high memory usage when there are lots of data passed to the view.
|
||||
*/
|
||||
public bool $collectVarData = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Max History
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* `$maxHistory` sets a limit on the number of past requests that are stored,
|
||||
* helping to conserve file space used to store them. You can set it to
|
||||
* 0 (zero) to not have any history stored, or -1 for unlimited history.
|
||||
*/
|
||||
public int $maxHistory = 20;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Toolbar Views Path
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The full path to the the views that are used by the toolbar.
|
||||
* This MUST have a trailing slash.
|
||||
*/
|
||||
public string $viewsPath = SYSTEMPATH . 'Debug/Toolbar/Views/';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Max Queries
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If the Database Collector is enabled, it will log every query that the
|
||||
* the system generates so they can be displayed on the toolbar's timeline
|
||||
* and in the query log. This can lead to memory issues in some instances
|
||||
* with hundreds of queries.
|
||||
*
|
||||
* `$maxQueries` defines the maximum amount of queries that will be stored.
|
||||
*/
|
||||
public int $maxQueries = 100;
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* User Agents
|
||||
* -------------------------------------------------------------------
|
||||
*
|
||||
* This file contains four arrays of user agent data. It is used by the
|
||||
* User Agent Class to help identify browser, platform, robot, and
|
||||
* mobile device data. The array keys are used to identify the device
|
||||
* and the array values are used to set the actual name of the item.
|
||||
*/
|
||||
class UserAgents extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* OS Platforms
|
||||
* -------------------------------------------------------------------
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $platforms = [
|
||||
'windows nt 10.0' => 'Windows 10',
|
||||
'windows nt 6.3' => 'Windows 8.1',
|
||||
'windows nt 6.2' => 'Windows 8',
|
||||
'windows nt 6.1' => 'Windows 7',
|
||||
'windows nt 6.0' => 'Windows Vista',
|
||||
'windows nt 5.2' => 'Windows 2003',
|
||||
'windows nt 5.1' => 'Windows XP',
|
||||
'windows nt 5.0' => 'Windows 2000',
|
||||
'windows nt 4.0' => 'Windows NT 4.0',
|
||||
'winnt4.0' => 'Windows NT 4.0',
|
||||
'winnt 4.0' => 'Windows NT',
|
||||
'winnt' => 'Windows NT',
|
||||
'windows 98' => 'Windows 98',
|
||||
'win98' => 'Windows 98',
|
||||
'windows 95' => 'Windows 95',
|
||||
'win95' => 'Windows 95',
|
||||
'windows phone' => 'Windows Phone',
|
||||
'windows' => 'Unknown Windows OS',
|
||||
'android' => 'Android',
|
||||
'blackberry' => 'BlackBerry',
|
||||
'iphone' => 'iOS',
|
||||
'ipad' => 'iOS',
|
||||
'ipod' => 'iOS',
|
||||
'os x' => 'Mac OS X',
|
||||
'ppc mac' => 'Power PC Mac',
|
||||
'freebsd' => 'FreeBSD',
|
||||
'ppc' => 'Macintosh',
|
||||
'linux' => 'Linux',
|
||||
'debian' => 'Debian',
|
||||
'sunos' => 'Sun Solaris',
|
||||
'beos' => 'BeOS',
|
||||
'apachebench' => 'ApacheBench',
|
||||
'aix' => 'AIX',
|
||||
'irix' => 'Irix',
|
||||
'osf' => 'DEC OSF',
|
||||
'hp-ux' => 'HP-UX',
|
||||
'netbsd' => 'NetBSD',
|
||||
'bsdi' => 'BSDi',
|
||||
'openbsd' => 'OpenBSD',
|
||||
'gnu' => 'GNU/Linux',
|
||||
'unix' => 'Unknown Unix OS',
|
||||
'symbian' => 'Symbian OS',
|
||||
];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Browsers
|
||||
* -------------------------------------------------------------------
|
||||
*
|
||||
* The order of this array should NOT be changed. Many browsers return
|
||||
* multiple browser types so we want to identify the subtype first.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $browsers = [
|
||||
'OPR' => 'Opera',
|
||||
'Flock' => 'Flock',
|
||||
'Edge' => 'Spartan',
|
||||
'Edg' => 'Edge',
|
||||
'Chrome' => 'Chrome',
|
||||
// Opera 10+ always reports Opera/9.80 and appends Version/<real version> to the user agent string
|
||||
'Opera.*?Version' => 'Opera',
|
||||
'Opera' => 'Opera',
|
||||
'MSIE' => 'Internet Explorer',
|
||||
'Internet Explorer' => 'Internet Explorer',
|
||||
'Trident.* rv' => 'Internet Explorer',
|
||||
'Shiira' => 'Shiira',
|
||||
'Firefox' => 'Firefox',
|
||||
'Chimera' => 'Chimera',
|
||||
'Phoenix' => 'Phoenix',
|
||||
'Firebird' => 'Firebird',
|
||||
'Camino' => 'Camino',
|
||||
'Netscape' => 'Netscape',
|
||||
'OmniWeb' => 'OmniWeb',
|
||||
'Safari' => 'Safari',
|
||||
'Mozilla' => 'Mozilla',
|
||||
'Konqueror' => 'Konqueror',
|
||||
'icab' => 'iCab',
|
||||
'Lynx' => 'Lynx',
|
||||
'Links' => 'Links',
|
||||
'hotjava' => 'HotJava',
|
||||
'amaya' => 'Amaya',
|
||||
'IBrowse' => 'IBrowse',
|
||||
'Maxthon' => 'Maxthon',
|
||||
'Ubuntu' => 'Ubuntu Web Browser',
|
||||
'Vivaldi' => 'Vivaldi',
|
||||
];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Mobiles
|
||||
* -------------------------------------------------------------------
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $mobiles = [
|
||||
// legacy array, old values commented out
|
||||
'mobileexplorer' => 'Mobile Explorer',
|
||||
// 'openwave' => 'Open Wave',
|
||||
// 'opera mini' => 'Opera Mini',
|
||||
// 'operamini' => 'Opera Mini',
|
||||
// 'elaine' => 'Palm',
|
||||
'palmsource' => 'Palm',
|
||||
// 'digital paths' => 'Palm',
|
||||
// 'avantgo' => 'Avantgo',
|
||||
// 'xiino' => 'Xiino',
|
||||
'palmscape' => 'Palmscape',
|
||||
// 'nokia' => 'Nokia',
|
||||
// 'ericsson' => 'Ericsson',
|
||||
// 'blackberry' => 'BlackBerry',
|
||||
// 'motorola' => 'Motorola'
|
||||
|
||||
// Phones and Manufacturers
|
||||
'motorola' => 'Motorola',
|
||||
'nokia' => 'Nokia',
|
||||
'palm' => 'Palm',
|
||||
'iphone' => 'Apple iPhone',
|
||||
'ipad' => 'iPad',
|
||||
'ipod' => 'Apple iPod Touch',
|
||||
'sony' => 'Sony Ericsson',
|
||||
'ericsson' => 'Sony Ericsson',
|
||||
'blackberry' => 'BlackBerry',
|
||||
'cocoon' => 'O2 Cocoon',
|
||||
'blazer' => 'Treo',
|
||||
'lg' => 'LG',
|
||||
'amoi' => 'Amoi',
|
||||
'xda' => 'XDA',
|
||||
'mda' => 'MDA',
|
||||
'vario' => 'Vario',
|
||||
'htc' => 'HTC',
|
||||
'samsung' => 'Samsung',
|
||||
'sharp' => 'Sharp',
|
||||
'sie-' => 'Siemens',
|
||||
'alcatel' => 'Alcatel',
|
||||
'benq' => 'BenQ',
|
||||
'ipaq' => 'HP iPaq',
|
||||
'mot-' => 'Motorola',
|
||||
'playstation portable' => 'PlayStation Portable',
|
||||
'playstation 3' => 'PlayStation 3',
|
||||
'playstation vita' => 'PlayStation Vita',
|
||||
'hiptop' => 'Danger Hiptop',
|
||||
'nec-' => 'NEC',
|
||||
'panasonic' => 'Panasonic',
|
||||
'philips' => 'Philips',
|
||||
'sagem' => 'Sagem',
|
||||
'sanyo' => 'Sanyo',
|
||||
'spv' => 'SPV',
|
||||
'zte' => 'ZTE',
|
||||
'sendo' => 'Sendo',
|
||||
'nintendo dsi' => 'Nintendo DSi',
|
||||
'nintendo ds' => 'Nintendo DS',
|
||||
'nintendo 3ds' => 'Nintendo 3DS',
|
||||
'wii' => 'Nintendo Wii',
|
||||
'open web' => 'Open Web',
|
||||
'openweb' => 'OpenWeb',
|
||||
|
||||
// Operating Systems
|
||||
'android' => 'Android',
|
||||
'symbian' => 'Symbian',
|
||||
'SymbianOS' => 'SymbianOS',
|
||||
'elaine' => 'Palm',
|
||||
'series60' => 'Symbian S60',
|
||||
'windows ce' => 'Windows CE',
|
||||
|
||||
// Browsers
|
||||
'obigo' => 'Obigo',
|
||||
'netfront' => 'Netfront Browser',
|
||||
'openwave' => 'Openwave Browser',
|
||||
'mobilexplorer' => 'Mobile Explorer',
|
||||
'operamini' => 'Opera Mini',
|
||||
'opera mini' => 'Opera Mini',
|
||||
'opera mobi' => 'Opera Mobile',
|
||||
'fennec' => 'Firefox Mobile',
|
||||
|
||||
// Other
|
||||
'digital paths' => 'Digital Paths',
|
||||
'avantgo' => 'AvantGo',
|
||||
'xiino' => 'Xiino',
|
||||
'novarra' => 'Novarra Transcoder',
|
||||
'vodafone' => 'Vodafone',
|
||||
'docomo' => 'NTT DoCoMo',
|
||||
'o2' => 'O2',
|
||||
|
||||
// Fallback
|
||||
'mobile' => 'Generic Mobile',
|
||||
'wireless' => 'Generic Mobile',
|
||||
'j2me' => 'Generic Mobile',
|
||||
'midp' => 'Generic Mobile',
|
||||
'cldc' => 'Generic Mobile',
|
||||
'up.link' => 'Generic Mobile',
|
||||
'up.browser' => 'Generic Mobile',
|
||||
'smartphone' => 'Generic Mobile',
|
||||
'cellphone' => 'Generic Mobile',
|
||||
];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Robots
|
||||
* -------------------------------------------------------------------
|
||||
*
|
||||
* There are hundred of bots but these are the most common.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $robots = [
|
||||
'googlebot' => 'Googlebot',
|
||||
'msnbot' => 'MSNBot',
|
||||
'baiduspider' => 'Baiduspider',
|
||||
'bingbot' => 'Bing',
|
||||
'slurp' => 'Inktomi Slurp',
|
||||
'yahoo' => 'Yahoo',
|
||||
'ask jeeves' => 'Ask Jeeves',
|
||||
'fastcrawler' => 'FastCrawler',
|
||||
'infoseek' => 'InfoSeek Robot 1.0',
|
||||
'lycos' => 'Lycos',
|
||||
'yandex' => 'YandexBot',
|
||||
'mediapartners-google' => 'MediaPartners Google',
|
||||
'CRAZYWEBCRAWLER' => 'Crazy Webcrawler',
|
||||
'adsbot-google' => 'AdsBot Google',
|
||||
'feedfetcher-google' => 'Feedfetcher Google',
|
||||
'curious george' => 'Curious George',
|
||||
'ia_archiver' => 'Alexa Crawler',
|
||||
'MJ12bot' => 'Majestic-12',
|
||||
'Uptimebot' => 'Uptimebot',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Validation\StrictRules\CreditCardRules;
|
||||
use CodeIgniter\Validation\StrictRules\FileRules;
|
||||
use CodeIgniter\Validation\StrictRules\FormatRules;
|
||||
use CodeIgniter\Validation\StrictRules\Rules;
|
||||
|
||||
class Validation extends BaseConfig
|
||||
{
|
||||
// --------------------------------------------------------------------
|
||||
// Setup
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Stores the classes that contain the
|
||||
* rules that are available.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public array $ruleSets = [
|
||||
Rules::class,
|
||||
FormatRules::class,
|
||||
FileRules::class,
|
||||
CreditCardRules::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Specifies the views that are used to display the
|
||||
* errors.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $templates = [
|
||||
'list' => 'CodeIgniter\Validation\Views\list',
|
||||
'single' => 'CodeIgniter\Validation\Views\single',
|
||||
];
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Rules
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
public $login = [
|
||||
'username' => [
|
||||
'label' => 'Auth.username',
|
||||
'rules' => 'required|max_length[30]|min_length[3]|regex_match[/\A[a-zA-Z0-9\.]+\z/]',
|
||||
],
|
||||
//'email' => [
|
||||
//'label' => 'Auth.email',
|
||||
//'rules' => 'required|max_length[254]|valid_email',
|
||||
//],
|
||||
'password' => [
|
||||
'label' => 'Auth.password',
|
||||
'rules' => 'required',
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\View as BaseView;
|
||||
use CodeIgniter\View\ViewDecoratorInterface;
|
||||
|
||||
class View extends BaseView
|
||||
{
|
||||
/**
|
||||
* When false, the view method will clear the data between each
|
||||
* call. This keeps your data safe and ensures there is no accidental
|
||||
* leaking between calls, so you would need to explicitly pass the data
|
||||
* to each view. You might prefer to have the data stick around between
|
||||
* calls so that it is available to all views. If that is the case,
|
||||
* set $saveData to true.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $saveData = true;
|
||||
|
||||
/**
|
||||
* Parser Filters map a filter name with any PHP callable. When the
|
||||
* Parser prepares a variable for display, it will chain it
|
||||
* through the filters in the order defined, inserting any parameters.
|
||||
* To prevent potential abuse, all filters MUST be defined here
|
||||
* in order for them to be available for use within the Parser.
|
||||
*
|
||||
* Examples:
|
||||
* { title|esc(js) }
|
||||
* { created_on|date(Y-m-d)|esc(attr) }
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $filters = [];
|
||||
|
||||
/**
|
||||
* Parser Plugins provide a way to extend the functionality provided
|
||||
* by the core Parser by creating aliases that will be replaced with
|
||||
* any callable. Can be single or tag pair.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $plugins = [];
|
||||
|
||||
/**
|
||||
* View Decorators are class methods that will be run in sequence to
|
||||
* have a chance to alter the generated output just prior to caching
|
||||
* the results.
|
||||
*
|
||||
* All classes must implement CodeIgniter\View\ViewDecoratorInterface
|
||||
*
|
||||
* @var class-string<ViewDecoratorInterface>[]
|
||||
*/
|
||||
public array $decorators = [];
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Accounting;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
|
||||
class TaxController extends BaseController
|
||||
{
|
||||
public function tax()
|
||||
{
|
||||
return view('accounting/tax/tax');
|
||||
}
|
||||
|
||||
public function taxList()
|
||||
{
|
||||
return view('accounting/tax/tax_list');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Accounting;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
|
||||
class UnpaidController extends BaseController
|
||||
{
|
||||
public function unpaid()
|
||||
{
|
||||
return view('accounting/unpaid/unpaid');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Accounting;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\Accounting\WithdrawModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
class WithdrawController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $wd;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->wd = model(WithdrawModel::class);
|
||||
}
|
||||
public function withdraw()
|
||||
{
|
||||
return view('accounting/withdraw/withdraw');
|
||||
}
|
||||
|
||||
public function withdrawList()
|
||||
{
|
||||
return view('accounting/withdraw/withdraw_list');
|
||||
}
|
||||
|
||||
public function withdrawWrite(){
|
||||
return view('accounting/withdraw/withdraw_write');
|
||||
}
|
||||
|
||||
public function accountList(){
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post') {
|
||||
$data = $this->request->getRawInput();
|
||||
$result = $this->wd->accountList($data);
|
||||
|
||||
return $result;
|
||||
} else {
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function typeList(){
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get') {
|
||||
$result = $this->wd->typeList();
|
||||
|
||||
return $result;
|
||||
} else {
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function userList(){
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get') {
|
||||
$result = $this->wd->userList();
|
||||
|
||||
return $result;
|
||||
} else {
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getList(){
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post') {
|
||||
$data = $this->request->getRawInput();
|
||||
$result = $this->wd->getList($data);
|
||||
|
||||
return $result;
|
||||
} else {
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function excelDownload(){
|
||||
$data = $this->request->getRawInput();
|
||||
$transformedData = json_decode($this->wd->getList($data),true);
|
||||
$columns = $this->getColumns();
|
||||
|
||||
$fileData = $this->createExcelFile($transformedData, $columns);
|
||||
$contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
||||
$fileExtension = 'xlsx';
|
||||
|
||||
return $this->response
|
||||
->setHeader('Content-Type', $contentType)
|
||||
->setHeader('Content-Disposition', 'attachment; filename="event_lead_' . date('YmdHis') . '.' . $fileExtension . '"')
|
||||
->setBody($fileData);
|
||||
}
|
||||
|
||||
private function createExcelFile($data, $columns)
|
||||
{
|
||||
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
// 헤더 설정
|
||||
$columnIndex = 'A';
|
||||
$sheet->setCellValue($columnIndex . '1', '#');
|
||||
$columnIndex++;
|
||||
foreach ($columns as $key => $header) {
|
||||
$sheet->setCellValue($columnIndex . '1', $header);
|
||||
// if (in_array($key, ['addr', 'email', 'add1', 'add2', 'add3', 'add4', 'add5', 'add6'])) {
|
||||
// $sheet->getColumnDimension($columnIndex)->setAutoSize(true);
|
||||
// $sheet->getColumnDimension($columnIndex)->setWidth(200 / 7); // 최대 200픽셀로 제한
|
||||
// } else if ($key === 'name') {
|
||||
// $sheet->getColumnDimension($columnIndex)->setWidth(100 / 7); // 100픽셀로 설정 (엑셀의 너비 단위는 약 1/7인치)
|
||||
// } else {
|
||||
$sheet->getColumnDimension($columnIndex)->setAutoSize(true); // 자동 너비 조정
|
||||
// }
|
||||
$columnIndex++;
|
||||
}
|
||||
|
||||
// 필터 설정
|
||||
$sheet->setAutoFilter($sheet->calculateWorksheetDimension());
|
||||
|
||||
// 데이터 삽입
|
||||
$rowIndex = 2; // 데이터는 2번째 행부터 시작
|
||||
$totalRows = count($data);
|
||||
|
||||
foreach ($data as $row) {
|
||||
|
||||
$columnIndex = 'A';
|
||||
$sheet->setCellValue($columnIndex . $rowIndex, $totalRows); // 역순 카운트
|
||||
$columnIndex++;
|
||||
|
||||
foreach ($columns as $key => $header) {
|
||||
$value = $row[$key];
|
||||
|
||||
if(!isset($row["gwstatus"])){
|
||||
$row["gwstatus"]="";
|
||||
}else if(strpos($row["gwstatus"],"http") > -1){
|
||||
$row["gwstatus"]="완료";
|
||||
}
|
||||
|
||||
// if ($key === 'phone') {
|
||||
// $value = preg_replace("/([0-9]{3})([0-9]{4})([0-9]{4})/", "$1-$2-$3", $value);
|
||||
// $sheet->setCellValue($columnIndex . $rowIndex, $value);
|
||||
// } elseif($key === 'age') {
|
||||
// $value = $value == 0 ? "" : $value;
|
||||
// $sheet->setCellValue($columnIndex . $rowIndex, $value);
|
||||
// } elseif ($key === 'site') {
|
||||
// $sheet->getCell($columnIndex . $rowIndex)->setValueExplicit($value, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
|
||||
// } else {
|
||||
$sheet->setCellValue($columnIndex . $rowIndex, $value);
|
||||
// }
|
||||
$columnIndex++;
|
||||
}
|
||||
|
||||
$rowIndex++;
|
||||
$totalRows--;
|
||||
}
|
||||
|
||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
|
||||
ob_start();
|
||||
$writer->save('php://output');
|
||||
$excelData = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $excelData;
|
||||
}
|
||||
|
||||
private function getColumns()
|
||||
{
|
||||
$columns = [
|
||||
'reg_date' => '등록일시',
|
||||
'nickname' => '이름',
|
||||
'type' => '구분',
|
||||
'company_name' => '거래처명(입금주명)',
|
||||
'bank' => '은행',
|
||||
'account' => '계좌번호',
|
||||
'detail' => '내역(자세히)',
|
||||
'total_price' => '총금액(VAT 포함)',
|
||||
'memo' => '비고',
|
||||
'status' => '결과',
|
||||
'gwstatus'=>'결제현황',
|
||||
'date' => '출금완료일',
|
||||
];
|
||||
|
||||
// if(auth()->user()->hasPermission('integrate.description')
|
||||
// || auth()->user()->inGroup('superadmin', 'admin', 'developer', 'user')){
|
||||
// $columns = array_merge(
|
||||
// array_slice($columns, 0, 2, true),
|
||||
// ['description' => '구분'],
|
||||
// array_slice($columns, 2, null, true)
|
||||
// );
|
||||
// }
|
||||
// if(auth()->user()->hasPermission('integrate.media')
|
||||
// || auth()->user()->inGroup('superadmin', 'admin', 'developer', 'user')){
|
||||
// $columns = array_merge(
|
||||
// array_slice($columns, 0, 2, true),
|
||||
// ['media' => '매체'],
|
||||
// array_slice($columns, 2, null, true)
|
||||
// );
|
||||
// }
|
||||
// if(auth()->user()->hasPermission('integrate.advertiser')
|
||||
// || auth()->user()->inGroup('superadmin', 'admin', 'developer', 'user')){
|
||||
// $columns = array_merge(
|
||||
// array_slice($columns, 0, 2, true),
|
||||
// ['advertiser' => '광고주'],
|
||||
// array_slice($columns, 2, null, true)
|
||||
// );
|
||||
// }
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Advertisement;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\Api\AdLeadModel;
|
||||
use App\ThirdParty\facebook_api\ZenithFB;
|
||||
use App\ThirdParty\googleads_api\ZenithGG;
|
||||
use App\ThirdParty\moment_api\ZenithKM;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
|
||||
class AdLeadController extends BaseController
|
||||
{
|
||||
protected $adlead, $facebook, $google, $kakao;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->adlead = model(AdLeadModel::class);
|
||||
$this->facebook = new ZenithFB();
|
||||
$this->google = new ZenithGG();
|
||||
$this->kakao = new ZenithKM();
|
||||
}
|
||||
|
||||
public function sendToEventLead()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("잠재고객 업데이트를 시작합니다.", "yellow");
|
||||
$this->sendToEventLeadFromKakao();
|
||||
$this->sendToEventLeadFromFacebook();
|
||||
//$this->sendToEventLeadFromGoogle();
|
||||
CLI::write("잠재고객 업데이트가 완료되었습니다.", "yellow");
|
||||
}
|
||||
|
||||
private function sendToEventLeadFromKakao()
|
||||
{
|
||||
$moment_ads = $this->adlead->getBizFormUserResponse();
|
||||
$step = 1;
|
||||
$total = $moment_ads->getNumRows();
|
||||
if(!$total){
|
||||
return null;
|
||||
}
|
||||
CLI::write("카카오 모먼트 잠재고객 업데이트를 시작합니다.", "yellow");
|
||||
foreach($moment_ads->getResultArray() as $row){
|
||||
CLI::showProgress($step++, $total);
|
||||
if (!empty($row['code'])) {
|
||||
$title = trim($row['code']);
|
||||
}else{
|
||||
$title = $row['name'];
|
||||
}
|
||||
$landing = $this->kakao->landingGroup($title, $row['landingUrl'] ?? '');
|
||||
if(is_null($landing)) {
|
||||
CLI::print('비즈폼 매칭 오류 발생 : ' . $row . '');
|
||||
continue;
|
||||
}
|
||||
|
||||
//전화번호
|
||||
$phone = str_replace("+82010", "010", $row['phoneNumber']);
|
||||
$phone = str_replace("+8210", "010", $phone);
|
||||
$phone = preg_replace("/^8210(.+)$/", "010$1", $phone);
|
||||
$phone = str_replace("+82 10", "010", $phone);
|
||||
$phone = str_replace("-", "", $phone);
|
||||
if ($row['email'] == '없음') $row['email'] = '';
|
||||
|
||||
//추가질문
|
||||
$questions = [];
|
||||
$add = [];
|
||||
$responses = json_decode($row['responses'], 1);
|
||||
$acnt = 1;
|
||||
|
||||
$addr = $add1 = $add2 = $add3 = $add4 = $add5 = null;
|
||||
foreach ($responses as $response) {
|
||||
$qs = $this->adlead->getBizformQuestion($row['bizFormId'], $response['bizformItemId']);
|
||||
if(is_null($qs)) continue;
|
||||
if (!key_exists($qs['id'], $questions))
|
||||
$questions[$qs['id']] = $qs['title'];
|
||||
$add[] = ${'add' . $acnt} = $questions[$response['bizformItemId']] . '::' . $response['response'];
|
||||
$acnt++;
|
||||
}
|
||||
|
||||
$result = [];
|
||||
if ($landing['event_seq']) {
|
||||
$result['event_seq'] = $landing['event_seq'];
|
||||
$result['site'] = $landing['site']??null;
|
||||
$result['name'] = $row['nickname'];
|
||||
$result['email'] = $row['email']??'';
|
||||
$result['gender'] = $row['gender']??null;
|
||||
$result['age'] = $row['age'] ?? 0;
|
||||
$result['phone'] = $phone;
|
||||
$result['add1'] = $add1;
|
||||
$result['add2'] = $add2;
|
||||
$result['add3'] = $add3;
|
||||
$result['add4'] = $add4;
|
||||
$result['add5'] = $add5;
|
||||
$result['addr'] = $addr;
|
||||
$result['reg_timestamp'] = strtotime($row['submitAt']);
|
||||
$result['lead_id'] = $row['id']??null;
|
||||
$result['encUserId'] = $row['encUserId'];
|
||||
$result['bizFormId'] = $row['bizFormId'];
|
||||
}
|
||||
|
||||
if (is_array($result) && count($result)) {
|
||||
$this->adlead->insertEventLeadKakao($result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function sendToEventLeadFromFacebook()
|
||||
{
|
||||
$facebook_ads = $this->adlead->getFBAdLead();
|
||||
$step = 1;
|
||||
$total = count($facebook_ads);
|
||||
if(!$total){
|
||||
return null;
|
||||
}
|
||||
CLI::write("페이스북 잠재고객 업데이트를 시작합니다.", "yellow");
|
||||
foreach($facebook_ads as $row){
|
||||
CLI::showProgress($step++, $total);
|
||||
if (!empty($row['code'])) {
|
||||
$title = trim($row['code']);
|
||||
}else{
|
||||
$title = $row['ad_name'];
|
||||
}
|
||||
$landing = $this->facebook->landingGroup($title);
|
||||
//이름
|
||||
$full_name = $row['full_name'];
|
||||
if (!$full_name || $full_name == null) {
|
||||
$full_name = trim($row['first_name'] . ' ' . $row['last_name']);
|
||||
}
|
||||
|
||||
//성별
|
||||
if ($row['gender'] == "female") {
|
||||
$gender = "여자";
|
||||
} elseif ($row['gender'] == "male") {
|
||||
$gender = "남자";
|
||||
} else {
|
||||
$gender = $row['gender'];
|
||||
}
|
||||
|
||||
//나이
|
||||
if ($row['date_of_birth']) {
|
||||
$birthyear = date("Y", strtotime($row['date_of_birth']));
|
||||
$nowyear = date("Y");
|
||||
$age = $nowyear - $birthyear + 1;
|
||||
} else {
|
||||
$age = "";
|
||||
}
|
||||
|
||||
//전화번호
|
||||
$phone = str_replace("+82010", "010", $row['phone_number']);
|
||||
$phone = str_replace("+8210", "010", $phone);
|
||||
$phone = str_replace("-", "", $phone);
|
||||
|
||||
|
||||
//주소
|
||||
if ($row['street_address']) {
|
||||
$addr = $row['street_address'];
|
||||
} else {
|
||||
$addr = "";
|
||||
}
|
||||
|
||||
//추가질문
|
||||
preg_match_all("/0 => \'(.*)\',/iU", $row['field_data'], $match);
|
||||
if (isset($match[1][0])) {
|
||||
$add1 = $match[1][0];
|
||||
} else {
|
||||
$add1 = "";
|
||||
}
|
||||
if (isset($match[1][1])) {
|
||||
$add2 = $match[1][1];
|
||||
} else {
|
||||
$add2 = "";
|
||||
}
|
||||
if (isset($match[1][2])) {
|
||||
$add3 = $match[1][2];
|
||||
} else {
|
||||
$add3 = "";
|
||||
}
|
||||
if (isset($match[1][3])) {
|
||||
$add4 = $match[1][3];
|
||||
} else {
|
||||
$add4 = "";
|
||||
}
|
||||
if (isset($match[1][4])) {
|
||||
$add5 = $match[1][4];
|
||||
} else {
|
||||
$add5 = "";
|
||||
}
|
||||
|
||||
if ($landing['event_seq']) {
|
||||
$result['event_seq'] = $landing['event_seq'];
|
||||
$result['site'] = $landing['site'];
|
||||
$result['name'] = addslashes($full_name);
|
||||
$result['gender'] = $gender;
|
||||
$result['age'] = $age ?? 0;
|
||||
$result['phone'] = $phone;
|
||||
$result['add1'] = addslashes($add1);
|
||||
$result['add2'] = addslashes($add2);
|
||||
$result['add3'] = addslashes($add3);
|
||||
$result['add4'] = addslashes($add4);
|
||||
$result['add5'] = addslashes($add5);
|
||||
$result['addr'] = $addr;
|
||||
$result['reg_date'] = $row['created_time'];
|
||||
$result['id'] = $row['id'];
|
||||
|
||||
if (is_array($result)) {
|
||||
$this->adlead->insertEventLeadFacebook($result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function sendToEventLeadFromGoogle()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace App\Controllers\Advertisement;
|
||||
use App\Controllers\BaseController;
|
||||
use App\ThirdParty\facebook_api\ZenithFB;
|
||||
use App\ThirdParty\moment_api\ZenithKM;
|
||||
use App\ThirdParty\googleads_api\ZenithGG;
|
||||
|
||||
class ApiController extends BaseController
|
||||
{
|
||||
protected $chainsaw;
|
||||
/*
|
||||
public function __construct(...$params) {
|
||||
print_r($params); exit;
|
||||
include APPPATH."/ThirdParty/facebook_api/facebook-api.php";
|
||||
$this->chainsaw = new \ChainsawFB();
|
||||
}
|
||||
*/
|
||||
public function _remap($method, ...$params) {
|
||||
if (method_exists($this, $method)) {
|
||||
return $this->{$method}(...$params);
|
||||
}
|
||||
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
protected function facebook(...$params) {
|
||||
$this->chainsaw = new ZenithFB();
|
||||
$this->fb_func(...$params);
|
||||
}
|
||||
protected function moment(...$params) {
|
||||
$this->chainsaw = new ZenithKM();
|
||||
$this->fb_func(...$params);
|
||||
}
|
||||
protected function google(...$params) {
|
||||
$this->chainsaw = new ZenithGG();
|
||||
$this->fb_func(...$params);
|
||||
}
|
||||
|
||||
protected function fb_func(...$params) {
|
||||
if (method_exists($this->chainsaw, $params[0])) {
|
||||
$result = $this->chainsaw->{$params[0]}();
|
||||
if(in_array('grid', $params)) $this->chainsaw->grid($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
//안쓰는거
|
||||
/*
|
||||
protected function kakaoMoment(...$params) {
|
||||
include APPPATH."/ThirdParty/moment_api/kmapi.php";
|
||||
$this->chainsaw = new \ChainsawKM();
|
||||
$this->km_func(...$params);
|
||||
}
|
||||
|
||||
protected function km_func(...$params) {
|
||||
if (method_exists($this->chainsaw, $params[0])) {
|
||||
$result = $this->chainsaw->{$params[0]}();
|
||||
if(in_array('grid', $params)) $this->chainsaw->grid($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
namespace App\Controllers\Advertisement;
|
||||
|
||||
use App\ThirdParty\facebook_api\ZenithFB;
|
||||
use App\Libraries\slack_api\SlackChat;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use CodeIgniter\Controller;
|
||||
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use DateInterval;
|
||||
use DatePeriod;
|
||||
|
||||
class Facebook extends Controller
|
||||
{
|
||||
private $zenith;
|
||||
private $slack;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->zenith = new ZenithFB();
|
||||
$this->slack = new SlackChat();
|
||||
}
|
||||
|
||||
public function initController(
|
||||
RequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$date = "";
|
||||
$today = date('Y-m-d');
|
||||
$argv = @$request->getServer()['argv'];
|
||||
if(!is_null($argv)) {
|
||||
$method = $argv[2];
|
||||
$params = @array_slice($argv, 3);
|
||||
if(!@count($params)) return;
|
||||
foreach($params as $v) {
|
||||
$value = preg_replace('/[^0-9\-]+/', '', $v);
|
||||
if(preg_match('/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$/', $value)) { //request argument에 날짜형식이 있는지 체크
|
||||
$date = $v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
$hour = date("G"); //24-hour format of an hour without leading zeros
|
||||
if($date == $today && ($hour >= 0 && $hour <= 7)) {
|
||||
CLI::write("당일 0시~8시는 자동업데이트를 사용할 수 없습니다.", "light_purple");
|
||||
exit;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
public function getAccounts() {
|
||||
$this->zenith->updateAdAccounts();
|
||||
}
|
||||
|
||||
public function getLongLivedAccessToken() {
|
||||
$this->zenith->getLongLivedAccessToken();
|
||||
}
|
||||
|
||||
public function getInsight($all=null, $date=null, $edate=null) {
|
||||
CLI::clearScreen();
|
||||
if($all == null)
|
||||
$all = CLI::prompt("인사이트가 수신된 캠페인,광고그룹,광고 데이터를 함께 수신하시겠습니까?\n(시간이 오래 걸릴 수 있습니다.)", ["true","false"]);
|
||||
if($date == null)
|
||||
$date = CLI::prompt("인사이트를 수신할 기간 중 시작날짜를 입력해주세요.", date('Y-m-d'));
|
||||
if($edate == null)
|
||||
$edate = CLI::prompt("인사이트를 수신할 기간 중 종료날짜를 입력해주세요.", $date);
|
||||
// $run = CLI::prompt("광고데이터를 ".($all=="true"?"포함":"미포함")."하여 {$date} ~ {$edate} 기간의 인사이트를 수신합니다.",["y","n"]);
|
||||
// if($run != 'y') return false;
|
||||
$this->zenith->getAsyncInsights($all, $date, $edate);
|
||||
CLI::write("데이터 수신이 완료되었습니다.", "yellow");
|
||||
}
|
||||
|
||||
public function adLeadByAd($ad_id = null, $from = null, $to = null) {
|
||||
CLI::clearScreen();
|
||||
if($ad_id == null)
|
||||
$ad_id = CLI::prompt("잠재고객 업데이트 할 광고ID를 입력해주세요.");
|
||||
if($from == null)
|
||||
$from = CLI::prompt("잠재고객 업데이트 할 시작날짜를 입력해주세요.", date('Y-m-d'));
|
||||
if($to == null)
|
||||
$to = CLI::prompt("잠재고객 업데이트 할 종료날짜를 입력해주세요.", $from);
|
||||
$result = $this->zenith->adLeadByAd($ad_id, $from, $to);
|
||||
CLI::write("잠재고객 업데이트 완료되었습니다.", "yellow");
|
||||
}
|
||||
|
||||
public function getAdLead($from = null, $to = null) {
|
||||
CLI::clearScreen();
|
||||
if($from == null)
|
||||
$from = CLI::prompt("잠재고객 업데이트 할 시작날짜를 입력해주세요.", date('Y-m-d'));
|
||||
if($to == null)
|
||||
$to = CLI::prompt("잠재고객 업데이트 할 종료날짜를 입력해주세요.", date('Y-m-d'));
|
||||
// $run = CLI::prompt("{$from}~{$to}일자의 잠재고객을 업데이트 합니다.",["y","n"]);
|
||||
// if($run != 'y') return false;
|
||||
$this->zenith->getAdLead($from, $to);
|
||||
}
|
||||
|
||||
public function updateAll() {
|
||||
CLI::clearScreen();
|
||||
// $run = CLI::prompt("캠페인/광고그룹/광고를 업데이트 합니다.",["y","n"]);
|
||||
// if($run != 'y') return false;
|
||||
CLI::write("캠페인/광고그룹/광고를 업데이트 합니다.", "light_red");
|
||||
$this->zenith->updateAllByAccounts();
|
||||
/*
|
||||
$getAds = $this->zenith->getAds();
|
||||
$updateAdsets = $this->zenith->updateAdsets($getAds);
|
||||
$updateCampaigns = $this->zenith->updateCampaigns($updateAdsets);
|
||||
*/
|
||||
}
|
||||
|
||||
public function updateDB($sdate = null, $edate = null) {
|
||||
CLI::clearScreen();
|
||||
if($sdate == null)
|
||||
$sdate = CLI::prompt("유효DB 업데이트 할 시작날짜를 입력해주세요.", date('Y-m-d'));
|
||||
if($edate == null)
|
||||
$edate = CLI::prompt("유효DB 업데이트 할 종료날짜를 입력해주세요.", $sdate);
|
||||
$sdate = date_create($sdate);
|
||||
$edate = date_create(date('Y-m-d', strtotime($edate.'+1 days')));
|
||||
$interval = DateInterval::createFromDateString('1 day');
|
||||
$date_range = new DatePeriod($sdate, $interval, $edate);
|
||||
foreach($date_range as $date) {
|
||||
$date = $date->format('Y-m-d');
|
||||
CLI::write("{$date} 유효DB를 업데이트 합니다.", "light_red");
|
||||
$this->zenith->getAdsUseLanding($date);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateCampaign() {
|
||||
$campaign_id = CLI::prompt("업데이트 할 캠페인 ID를 입력해주세요.", null);
|
||||
if(is_null($campaign_id)) return;
|
||||
$data = [
|
||||
['campaign_id'=>$campaign_id]
|
||||
];
|
||||
$campaign = $this->zenith->updateCampaigns($data);
|
||||
print_r($campaign);
|
||||
}
|
||||
|
||||
public function updateAds() {
|
||||
CLI::clearScreen();
|
||||
// $run = CLI::prompt("광고를 업데이트 합니다.",["y","n"]);
|
||||
// if($run != 'y') return false;
|
||||
CLI::write("광고를 업데이트 합니다.", "light_red");
|
||||
|
||||
$this->zenith->updateAds();
|
||||
}
|
||||
public function updateAdCreatives() {
|
||||
CLI::clearScreen();
|
||||
$ad_id = CLI::prompt("업데이트 할 광고 ID를 입력해주세요.", null);
|
||||
if(is_null($ad_id)) return;
|
||||
$data = [
|
||||
['id'=>$ad_id]
|
||||
];
|
||||
// $run = CLI::prompt("광고를 업데이트 합니다.",["y","n"]);
|
||||
// if($run != 'y') return false;
|
||||
CLI::write("광고소재를 업데이트 합니다.", "light_red");
|
||||
|
||||
$adcreative = $this->zenith->updateAdCreatives($data);
|
||||
print_r($adcreative);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
namespace App\Controllers\Advertisement;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\ThirdParty\googleads_api\ZenithGG;
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use Config\Paths;
|
||||
use DateInterval;
|
||||
use DatePeriod;
|
||||
|
||||
class GoogleAds extends BaseController
|
||||
{
|
||||
private $chainsaw;
|
||||
|
||||
public function __construct(...$param)
|
||||
{
|
||||
$this->chainsaw = new ZenithGG();
|
||||
}
|
||||
|
||||
public function getAccounts()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("광고계정 수신을 진행합니다.", "light_red");
|
||||
$this->chainsaw->getAccounts();
|
||||
CLI::write("광고계정 업데이트 완료", "yellow");
|
||||
}
|
||||
|
||||
public function getReports($date=null, $edate=null) {
|
||||
CLI::clearScreen();
|
||||
if($date == null)
|
||||
$date = CLI::prompt("리포트를 수신할 기간 중 시작날짜를 입력해주세요.", date('Y-m-d'));
|
||||
if($edate == null)
|
||||
$edate = CLI::prompt("리포트를 수신할 기간 중 종료날짜를 입력해주세요.", $date);
|
||||
// $run = CLI::prompt("광고데이터를 ".($all=="true"?"포함":"미포함")."하여 {$date} ~ {$edate} 기간의 인사이트를 수신합니다.",["y","n"]);
|
||||
// if($run != 'y') return false;
|
||||
$this->chainsaw->getReports($date, $edate);
|
||||
CLI::write("데이터 수신이 완료되었습니다.", "yellow");
|
||||
$this->chainsaw->getAdsUseLanding($date);
|
||||
}
|
||||
|
||||
public function getAll()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("계정/계정예산/에셋/캠페인/그룹/소재/보고서 업데이트를 진행합니다.", "light_red");
|
||||
$result = $this->chainsaw->getAll();
|
||||
CLI::write("계정/계정예산/에셋/캠페인/그룹/소재/보고서 업데이트 완료", "yellow");
|
||||
// $paths = new Paths();
|
||||
// $log_file = fopen($paths->writableDirectory . '/logs/GoogleAdsGetAll.txt', 'a');
|
||||
// fwrite($log_file, $result . "\r\n\r\n");
|
||||
// fclose($log_file);
|
||||
}
|
||||
public function getAdSchedules() {
|
||||
$result = $this->chainsaw->getAdSchedules();
|
||||
}
|
||||
|
||||
public function updateDB($sdate = null, $edate = null) {
|
||||
CLI::clearScreen();
|
||||
$cliArgs = CLI::getOptions();
|
||||
$is_result = false;
|
||||
$ids = [];
|
||||
if (isset($cliArgs['result'])) {
|
||||
$is_result = $cliArgs['result'];
|
||||
}
|
||||
if (isset($cliArgs['ids'])) {
|
||||
$ids = $cliArgs['ids'];
|
||||
}
|
||||
if($sdate == null) {
|
||||
$sdate = CLI::prompt("유효DB 업데이트 할 시작날짜를 입력해주세요.", date('Y-m-d'));
|
||||
}
|
||||
if($edate == null) {
|
||||
$edate = CLI::prompt("유효DB 업데이트 할 종료날짜를 입력해주세요.", $sdate);
|
||||
}
|
||||
if(!empty($ids)) {
|
||||
$ids = explode(',', $ids);
|
||||
}
|
||||
$sdate = date_create($sdate);
|
||||
$edate = date_create(date('Y-m-d', strtotime($edate.'+1 days')));
|
||||
$interval = DateInterval::createFromDateString('1 day');
|
||||
$date_range = new DatePeriod($sdate, $interval, $edate);
|
||||
foreach($date_range as $date) {
|
||||
$date = $date->format('Y-m-d');
|
||||
CLI::write("{$date} 유효DB를 업데이트 합니다.", "light_red");
|
||||
$result = $this->chainsaw->getAdsUseLanding($date, $ids);
|
||||
if($is_result) print_r($result);
|
||||
}
|
||||
}
|
||||
|
||||
public function getReport() {
|
||||
$accounts = [
|
||||
['manageCustomer'=> 7792262348,'customerId'=>4658512480]
|
||||
];
|
||||
$this->chainsaw->getReports('2024-05-31', '2024-05-31', $accounts);
|
||||
}
|
||||
|
||||
public function getCampaign() {
|
||||
$campaigns = $this->chainsaw->getCampaigns('7792262348', '1705230747', '20870581914');
|
||||
dd($campaigns);
|
||||
}
|
||||
|
||||
public function getCriterion() {
|
||||
// $campaigns = $this->chainsaw->getCriterions('7792262348', '1705230747', '20870581914');
|
||||
// $campaigns = $this->chainsaw->getCriterions('7792262348', '8023466215', '20999659346');
|
||||
$campaigns = $this->chainsaw->getCriterions('7792262348', '9049844350', '20979863645');
|
||||
dd($campaigns);
|
||||
}
|
||||
|
||||
public function getAdGroups() {
|
||||
$adgroups = $this->chainsaw->getAdGroups('5980790227', '3931611101', '20581900068');
|
||||
dd($adgroups);
|
||||
}
|
||||
|
||||
public function getAds() {
|
||||
$ads = $this->chainsaw->getAds('5980790227', '3288458378', '130392657290', '2023-12-22');
|
||||
dd($ads);
|
||||
}
|
||||
|
||||
public function getData() {
|
||||
$getAll = $this->chainsaw->getAll(null, [['manageCustomer'=>7177486093, 'customerId'=>9604111811]]);
|
||||
dd($getAll);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Advertisement;
|
||||
|
||||
use CodeIgniter\CLI\CLI;
|
||||
use App\ThirdParty\moment_api\ZenithKM;
|
||||
use CodeIgniter\Controller;
|
||||
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use DateInterval;
|
||||
use DatePeriod;
|
||||
|
||||
class KakaoMoment extends Controller
|
||||
{
|
||||
private $chainsaw;
|
||||
private $run_proc = [];
|
||||
|
||||
public function __construct(...$param)
|
||||
{
|
||||
$this->chainsaw = new ZenithKM();
|
||||
}
|
||||
|
||||
public function initController(
|
||||
RequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$uname = php_uname();
|
||||
if(stripos($uname, 'windows') === false) {
|
||||
@exec("ps ax | grep -i kmapi | grep -v grep", $exec);
|
||||
if($exec) {
|
||||
foreach($exec as $v) $proc[] = preg_replace('/^.+php\skmapi\s(.+)$/', '$1', $v);
|
||||
foreach($proc as $v) {
|
||||
$method = preg_replace('/^([a-z]+)\s.+$/i', '$1', $v);
|
||||
$_params = preg_replace('/^([a-z]+)\s(.+)$/i', '$2', str_replace('\\', '', $v));
|
||||
$params = explode(' ', $_params);
|
||||
$this->run_proc = [
|
||||
'method' => $method,
|
||||
'params' => $params
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public function oauth() {
|
||||
return $this->chainsaw->oauth();
|
||||
}
|
||||
//토큰 업데이트
|
||||
public function refresh_token()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("토큰 업데이트를 진행합니다.", "light_red");
|
||||
$this->chainsaw->refresh_token();
|
||||
CLI::write("토큰 업데이트 완료", "yellow");
|
||||
}
|
||||
|
||||
//전체 광고계정 업데이트
|
||||
public function updateAdAccounts()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("전체 광고계정 업데이트를 진행합니다.", "light_red");
|
||||
$this->chainsaw->updateAdAccounts();
|
||||
CLI::write("전체 광고계정 업데이트 완료", "yellow");
|
||||
}
|
||||
|
||||
//캠페인 데이터 업데이트
|
||||
public function updateCampaigns()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("캠페인 업데이트를 진행합니다.", "light_red");
|
||||
$this->chainsaw->updateCampaigns();
|
||||
CLI::write("캠페인 업데이트 완료", "yellow");
|
||||
}
|
||||
|
||||
//광고그룹 데이터 업데이트
|
||||
public function updateAdGroups()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("광고그룹 업데이트를 진행합니다.", "light_red");
|
||||
$this->chainsaw->updateAdGroups();
|
||||
CLI::write("광고그룹 업데이트 완료", "yellow");
|
||||
}
|
||||
|
||||
//소재 데이터 업데이트
|
||||
public function updateCreatives()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("소재 데이터 업데이트를 진행합니다.", "light_red");
|
||||
$this->chainsaw->updateCreatives();
|
||||
CLI::write("소재 데이터 업데이트 완료", "yellow");
|
||||
}
|
||||
|
||||
//전체 소재 보고서 BASIC 업데이트
|
||||
/*
|
||||
public function updateReportByAdgroup($date = null)
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("소재 보고서 업데이트를 진행합니다.", "light_red");
|
||||
if(is_null($date))
|
||||
$date = CLI::prompt("전체 소재 보고서 BASIC 수신할 날짜를 입력해주세요.(ex. ".date('Y-m-d', strtotime('-1 day')).")", 'TODAY');
|
||||
$this->chainsaw->updateCreativesReportBasic($date);
|
||||
CLI::write("소재 보고서 업데이트 완료", "yellow");
|
||||
}
|
||||
*/
|
||||
public function updateReportByHour($date = null)
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("소재 보고서 업데이트를 진행합니다.", "light_red");
|
||||
if(is_null($date))
|
||||
$date = CLI::prompt("전체 소재 보고서 BASIC 수신할 날짜를 입력해주세요.(ex. ".date('Y-m-d', strtotime('-1 day')).")", 'TODAY');
|
||||
$this->chainsaw->updateHourReportBasic($date);
|
||||
CLI::write("소재 보고서 업데이트 완료", "yellow");
|
||||
}
|
||||
|
||||
public function getAll() {
|
||||
$this->chainsaw->updateAdAccounts();
|
||||
$this->chainsaw->updateCampaigns();
|
||||
$this->chainsaw->updateAdGroups();
|
||||
$this->chainsaw->updateCreatives();
|
||||
$this->chainsaw->updateBizform();
|
||||
}
|
||||
|
||||
|
||||
//비즈폼 데이터 업데이트
|
||||
public function updateBizform()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("비즈폼 데이터 업데이트를 진행합니다.", "light_red");
|
||||
$this->chainsaw->updateBizform();
|
||||
CLI::write("비즈폼 데이터 업데이트 완료", "yellow");
|
||||
}
|
||||
|
||||
//app_subscribe 데이터 업데이트
|
||||
/* public function moveToAppsubscribe()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("app_subscribe 데이터 업데이트를 진행합니다.", "light_red");
|
||||
$this->chainsaw->moveToLeads();
|
||||
CLI::write("app_subscribe 데이터 업데이트 완료", "yellow");
|
||||
} */
|
||||
|
||||
//유효DB 개수 업데이트
|
||||
public function updateDB($sdate = null, $edate = null) {
|
||||
CLI::clearScreen();
|
||||
if($sdate == null)
|
||||
$sdate = CLI::prompt("유효DB 업데이트 할 시작날짜를 입력해주세요.", date('Y-m-d'));
|
||||
if($edate == null)
|
||||
$edate = CLI::prompt("유효DB 업데이트 할 종료날짜를 입력해주세요.", $sdate);
|
||||
$sdate = date_create($sdate);
|
||||
$edate = date_create(date('Y-m-d', strtotime($edate.'+1 days')));
|
||||
$interval = DateInterval::createFromDateString('1 day');
|
||||
$date_range = new DatePeriod($sdate, $interval, $edate);
|
||||
foreach($date_range as $date) {
|
||||
$date = $date->format('Y-m-d');
|
||||
CLI::write("{$date} 유효DB를 업데이트 합니다.", "light_red");
|
||||
$result = $this->chainsaw->getCreativesUseLanding($date);
|
||||
}
|
||||
}
|
||||
|
||||
//리포트데이터를 업데이트
|
||||
public function updateReportByDate($sdate=null, $edate=null)
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("리포트데이터를 업데이트를 진행합니다.", "light_red");
|
||||
if($sdate == null)
|
||||
$sdate = CLI::prompt("리포트데이터를 수신할 기간 중 시작날짜를 입력해주세요.", date('Y-m-d'));
|
||||
if($edate == null)
|
||||
$edate = CLI::prompt("리포트데이터를 수신할 기간 중 종료날짜를 입력해주세요.", $sdate);
|
||||
$this->chainsaw->updateReportByDate($sdate, $edate);
|
||||
CLI::write("리포트데이터 업데이트 완료", "yellow");
|
||||
}
|
||||
|
||||
//소재 자동 변경
|
||||
public function autoCreativeOnOff()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("소재 자동 변경을 진행합니다.", "light_red");
|
||||
$check = CLI::prompt("전체 소재 보고서 BASIC 수신할 날짜를 입력해주세요.", ['on', 'off']);
|
||||
$this->chainsaw->autoCreativeOnOff();
|
||||
CLI::write("소재 자동 변경 완료", "yellow");
|
||||
}
|
||||
|
||||
//자동 입찰가한도 리셋
|
||||
public function autoLimitBidAmountReset()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("자동 입찰가한도 리셋을 진행합니다.", "light_red");
|
||||
$date = CLI::prompt("자동 입찰가한도 리셋할 날짜를 입력해주세요.", date('Y-m-d'));
|
||||
$this->chainsaw->autoLimitBidAmountReset($date);
|
||||
CLI::write("자동 입찰가한도 리셋 완료", "yellow");
|
||||
}
|
||||
|
||||
//자동 입찰가 설정
|
||||
public function autoLimitBidAmount()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("자동 입찰가한도 설정을 진행합니다.", "light_red");
|
||||
$date = CLI::prompt("자동 입찰가한도 설정할 날짜를 입력해주세요.", date('Y-m-d'));
|
||||
$this->chainsaw->autoLimitBidAmount($date);
|
||||
CLI::write("자동 입찰가한도 설정 완료", "yellow");
|
||||
}
|
||||
|
||||
//자동 예산한도 리셋
|
||||
public function autoLimitBudgetReset()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("자동 예산한도 리셋을 진행합니다.", "light_red");
|
||||
$date = CLI::prompt("자동 예산한도 리셋할 날짜를 입력해주세요.", date('Y-m-d'));
|
||||
$this->chainsaw->autoLimitBudgetReset($date);
|
||||
CLI::write("자동 예산한도 리셋 완료", "yellow");
|
||||
}
|
||||
|
||||
//자동 예산한도 설정
|
||||
public function autoLimitBudget()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("자동 예산한도 설정을 진행합니다.", "light_red");
|
||||
$date = CLI::prompt("자동 예산한도 설정할 날짜를 입력해주세요.", date('Y-m-d'));
|
||||
$this->chainsaw->autoLimitBudget();
|
||||
CLI::write("자동 예산한도 설정 완료", "yellow");
|
||||
}
|
||||
|
||||
//광고그룹 AI 업데이트
|
||||
public function setAdGroupsAiRun()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("광고그룹 AI 업데이트를 진행합니다.", "light_red");
|
||||
$this->chainsaw->setAdGroupsAiRun();
|
||||
CLI::write("광고그룹 AI 업데이트 완료", "yellow");
|
||||
}
|
||||
|
||||
//AI 자동켜기
|
||||
public function autoAiOn()
|
||||
{
|
||||
CLI::clearScreen();
|
||||
CLI::write("AI를 시작합니다.", "light_red");
|
||||
$this->chainsaw->autoAiOn();
|
||||
CLI::write("AI 시작", "yellow");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\AdvertisementManager;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\Advertiser\AdvEtcManagerModel;
|
||||
|
||||
class AdvEtcManagerController extends BaseController
|
||||
{
|
||||
protected $advEtcManagerModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->advEtcManagerModel = model(AdvEtcManagerModel::class);
|
||||
}
|
||||
|
||||
// 기본 페이지 로드
|
||||
public function index()
|
||||
{
|
||||
return view('advertisements/etc/etc');
|
||||
}
|
||||
|
||||
public function getList() {
|
||||
if ($this->request->isAJAX()) {
|
||||
$date = $this->request->getPost('date') ?? ['sdate' => date('Y-m-d'), 'edate' => date('Y-m-d')];
|
||||
$sdate = (new \DateTime($date['sdate']))->format('Y-m-d') . ' 00:00:00';
|
||||
$edate = (new \DateTime($date['edate']))->format('Y-m-d') . ' 23:59:59';
|
||||
|
||||
$data = $this->advEtcManagerModel->getList(['sdate' => $sdate, 'edate' => $edate]);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'data' => $data // dataTables에 맞게 'data' 키 사용
|
||||
]);
|
||||
} else {
|
||||
return $this->response->setStatusCode(403)->setBody('Access denied');
|
||||
}
|
||||
}
|
||||
|
||||
public function updateData()
|
||||
{
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$result = $this->advEtcManagerModel->updateOrInsertEventData($data);
|
||||
|
||||
if ($result) {
|
||||
return $this->response->setJSON(['status' => 'success', 'message' => 'Data updated successfully']);
|
||||
} else {
|
||||
return $this->response->setJSON(['status' => 'error', 'message' => 'Failed to update data']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\AdvertisementManager;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\Advertiser\AdvFacebookManagerModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class AdvFacebookManagerController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $facebook;
|
||||
public function __construct()
|
||||
{
|
||||
$this->facebook = model(AdvFacebookManagerModel::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('advertisements/facebook/facebook');
|
||||
}
|
||||
|
||||
public function getAccounts()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = [
|
||||
'dates' => [
|
||||
'sdate' => $this->request->getGet('sdate') ? $this->request->getGet('sdate') : date('Y-m-d'),
|
||||
'edate' => $this->request->getGet('edate') ? $this->request->getGet('edate') : date('Y-m-d'),
|
||||
],
|
||||
'businesses' => $this->request->getGet('businesses'),
|
||||
];
|
||||
|
||||
$accounts = $this->facebook->getAccounts($arg);
|
||||
$getDisapprovalByAccount = $this->getDisapprovalByAccount();
|
||||
foreach ($accounts as &$account) {
|
||||
|
||||
$account['class'] = [];
|
||||
$account['db_ratio'] = 0;
|
||||
|
||||
if ($account['status'] != 1)
|
||||
array_push($account['class'], 'tag-inactive');
|
||||
if (in_array($account['id'], $getDisapprovalByAccount))
|
||||
array_push($account['class'], 'disapproval');
|
||||
|
||||
$account['db_count'] = $account['db_count'] * $account['date_count'];
|
||||
|
||||
if($account['db_sum'] && $account['db_count'])
|
||||
$account['db_ratio'] = round($account['db_sum'] / $account['db_count'] * 100,1);
|
||||
|
||||
if($account['db_ratio'] >= 100) {
|
||||
$account['db_ratio'] = 100;
|
||||
array_push($account['class'], 'over');
|
||||
}
|
||||
|
||||
if(!$account['db_sum']) $account['db_sum'] = 0;
|
||||
}
|
||||
|
||||
return $this->respond($accounts);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getData(){
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = [
|
||||
'dates' => [
|
||||
'sdate' => $this->request->getGet('sdate') ? $this->request->getGet('sdate') : date('Y-m-d'),
|
||||
'edate' => $this->request->getGet('edate') ? $this->request->getGet('edate') : date('Y-m-d'),
|
||||
],
|
||||
'type' => $this->request->getGet('type'),
|
||||
'businesses' => $this->request->getGet('businesses'),
|
||||
'accounts' => $this->request->getGet('accounts'),
|
||||
'stx' => $this->request->getGet('stx'),
|
||||
];
|
||||
|
||||
if($arg['type'] == 'ads'){
|
||||
$result = $this->getAds($arg);
|
||||
}else if($arg['type'] == 'adsets'){
|
||||
$result = $this->getAdSets($arg);
|
||||
}else{
|
||||
$result = $this->getCampaigns($arg);
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getReport()
|
||||
{
|
||||
if(isset($this->request) && $this->request->isAJAX()){
|
||||
$arg = [
|
||||
'sdate' => $this->request->getGet('sdate'),
|
||||
'edate' => $this->request->getGet('edate'),
|
||||
];
|
||||
}else{
|
||||
$arg = [
|
||||
'sdate' => date("Y-m-d"),
|
||||
'edate' => date("Y-m-d"),
|
||||
];
|
||||
}
|
||||
|
||||
$res = $this->facebook->getReport($arg)->get()->getResultArray();
|
||||
$columnIndex = 0;
|
||||
$data = [];
|
||||
foreach($res as $row) {
|
||||
$data[] = $row;
|
||||
foreach ($row as $col => $val) {
|
||||
if ($val == NULL) $val = "0";
|
||||
$total[$col][$columnIndex] = $val;
|
||||
}
|
||||
$columnIndex++;
|
||||
}
|
||||
|
||||
$report['impressions_sum'] = $report['clicks_sum'] = $report['click_ratio_sum'] = $report['spend_sum'] = $report['unique_total_sum'] = $report['unique_one_price_sum'] = $report['conversion_ratio_sum'] = $report['profit_sum'] = $report['per_sum'] = $report['price_sum'] = 0;
|
||||
|
||||
if(!empty($res)){
|
||||
$report['impressions_sum'] = array_sum($total['impressions']); //총 노출수
|
||||
$report['clicks_sum'] = array_sum($total['click']); //총 클릭수
|
||||
if ($report['clicks_sum'] != 0 && $report['impressions_sum'] != 0) {
|
||||
$report['click_ratio_sum'] = round(($report['clicks_sum'] / $report['impressions_sum']) * 100, 2); //총 클릭률
|
||||
}
|
||||
$report['spend_sum'] = array_sum($total['spend']); //총 지출액
|
||||
$report['unique_total_sum'] = array_sum($total['unique_total']); //총 유효db수
|
||||
if ($report['spend_sum'] != 0 && $report['unique_total_sum'] != 0) {
|
||||
$report['unique_one_price_sum'] = round($report['spend_sum'] / $report['unique_total_sum'], 0); //총 db당 단가
|
||||
}
|
||||
if ($report['unique_total_sum'] != 0 && $report['clicks_sum'] != 0) {
|
||||
$report['conversion_ratio_sum'] = round(($report['unique_total_sum'] / $report['clicks_sum']) * 100, 2); //총 전환율
|
||||
}
|
||||
$report['price_sum'] = array_sum($total['price']); //총 매출액
|
||||
$report['profit_sum'] = array_sum($total['profit']); //총 수익
|
||||
if ($report['profit_sum'] != 0 && $report['price_sum'] != 0) {
|
||||
$report['per_sum'] = round(($report['profit_sum'] / $report['price_sum']) * 100, 2); //총 수익률
|
||||
}
|
||||
|
||||
$report['impressions_sum'] = number_format($report['impressions_sum']);
|
||||
$report['clicks_sum'] = number_format($report['clicks_sum']);
|
||||
$report['spend_sum'] = number_format($report['spend_sum']);
|
||||
$report['unique_one_price_sum'] = number_format($report['unique_one_price_sum']);
|
||||
$report['price_sum'] = number_format($report['price_sum']);
|
||||
$report['profit_sum'] = number_format($report['profit_sum']);
|
||||
}
|
||||
|
||||
if(isset($this->request) && $this->request->isAJAX()){
|
||||
return $this->respond($report);
|
||||
}else{
|
||||
return $report;
|
||||
}
|
||||
}
|
||||
|
||||
private function getCampaigns($arg)
|
||||
{
|
||||
$campaigns = $this->facebook->getCampaigns($arg);
|
||||
$campaigns = $this->facebook->getStatuses("campaigns", $campaigns, $arg['dates']);
|
||||
$total = $this->getTotal($campaigns);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $campaigns,
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getAdSets($arg)
|
||||
{
|
||||
$adsets = $this->facebook->getAdSets($arg);
|
||||
$adsets = $this->facebook->getStatuses("adsets", $adsets, $arg['dates']);
|
||||
$total = $this->getTotal($adsets);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $adsets
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getAds($arg)
|
||||
{
|
||||
$ads = $this->facebook->getAds($arg);
|
||||
$ads = $this->facebook->getStatuses("ads", $ads, $arg['dates']);
|
||||
$total = $this->getTotal($ads);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $ads
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getDisapprovalByAccount()
|
||||
{
|
||||
$disapprovals = $this->facebook->getDisapproval();
|
||||
$data = [];
|
||||
foreach ($disapprovals as $row) {
|
||||
$data[] = $row['ad_account_id'];
|
||||
}
|
||||
$data = array_unique($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function getTotal($datas)
|
||||
{
|
||||
$total = [];
|
||||
$total['impressions'] = 0;
|
||||
$total['click'] = 0;
|
||||
$total['spend'] = 0;
|
||||
$total['margin'] = 0;
|
||||
$total['unique_total'] = 0;
|
||||
$total['sales'] = 0;
|
||||
$total['budget'] = 0;
|
||||
$total['cpc'] = 0;
|
||||
$total['ctr'] = 0;
|
||||
$total['cpa'] = 0;
|
||||
$total['cvr'] = 0;
|
||||
$total['margin_ratio'] = 0;
|
||||
$total['expect_db'] = 0;
|
||||
foreach($datas as $data){
|
||||
$total['impressions'] +=$data['impressions'];
|
||||
$total['click'] +=$data['click'];
|
||||
$total['spend'] +=$data['spend'];
|
||||
$total['margin'] +=$data['margin'];
|
||||
$total['unique_total'] +=$data['unique_total'];
|
||||
$total['sales'] +=$data['sales'];
|
||||
$total['budget'] +=$data['budget'];
|
||||
$total['cpc'] +=$data['cpc'];
|
||||
$total['ctr'] +=$data['ctr'];
|
||||
$total['cpa'] +=$data['cpa'];
|
||||
$total['cvr'] +=$data['cvr'];
|
||||
$total['margin_ratio'] +=$data['margin_ratio'];
|
||||
|
||||
//CPC(Cost Per Click: 클릭당단가 (1회 클릭당 비용)) = 지출액/링크클릭
|
||||
if($total['click'] > 0){
|
||||
$total['avg_cpc'] = $total['spend'] / $total['click'];
|
||||
}else{
|
||||
$total['avg_cpc'] = 0;
|
||||
}
|
||||
|
||||
//CTR(Click Through Rate: 클릭율 (노출 대비 클릭한 비율)) = (링크클릭/노출수)*100
|
||||
$total['avg_ctr'] = ($total['click'] / $total['impressions']) * 100;
|
||||
|
||||
//CPA(Cost Per Action: 현재 DB단가(전환당 비용)) = 지출액/유효db
|
||||
if($total['unique_total'] > 0){
|
||||
$total['avg_cpa'] = $total['spend'] / $total['unique_total'];
|
||||
}else{
|
||||
$total['avg_cpa'] = 0;
|
||||
}
|
||||
|
||||
//CVR(Conversion Rate:전환율 = (유효db / 링크클릭)*100
|
||||
if ($total['click'] > 0) {
|
||||
$total['avg_cvr'] = ($total['unique_total'] / $total['click']) * 100;
|
||||
} else {
|
||||
$total['avg_cvr'] = 0;
|
||||
}
|
||||
|
||||
//수익률 = (수익/매출액)*100
|
||||
if ($total['sales'] > 0) {
|
||||
$total['avg_margin_ratio'] = ($total['margin'] / $total['sales']) * 100;
|
||||
} else {
|
||||
$total['avg_margin_ratio'] = 0;
|
||||
}
|
||||
|
||||
if ($data['status'] == 'ACTIVE' && $data['unique_total']){
|
||||
$total['expect_db'] += round($data['budget'] / $data['cpa']);
|
||||
}
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\AdvertisementManager;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\Advertiser\AdvGoogleManagerModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class AdvGoogleManagerController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $google;
|
||||
public function __construct()
|
||||
{
|
||||
$this->google = model(AdvGoogleManagerModel::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('advertisements/google/google');
|
||||
}
|
||||
|
||||
public function getManageAccounts()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$accounts = $this->google->getManageAccounts();
|
||||
return $this->respond($accounts);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getAccounts()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = [
|
||||
'dates' => [
|
||||
'sdate' => $this->request->getGet('sdate') ? $this->request->getGet('sdate') : date('Y-m-d'),
|
||||
'edate' => $this->request->getGet('edate') ? $this->request->getGet('edate') : date('Y-m-d'),
|
||||
],
|
||||
'businesses' => $this->request->getGet('businesses'),
|
||||
];
|
||||
|
||||
$accounts = $this->google->getAccounts($arg);
|
||||
$getDisapprovalByAccount = $this->getDisapprovalByAccount();
|
||||
foreach ($accounts as &$account) {
|
||||
|
||||
$account['class'] = [];
|
||||
$account['db_ratio'] = '';
|
||||
|
||||
if($account['is_exposed'] === 0)
|
||||
array_push($account['class'], 'tag-inactive');
|
||||
if(in_array($account['id'], $getDisapprovalByAccount))
|
||||
array_push($account['class'], 'disapproval');
|
||||
|
||||
$account['db_count'] = $account['db_count'] * $account['date_count'];
|
||||
|
||||
if($account['db_sum'] && $account['db_count'])
|
||||
$account['db_ratio'] = round($account['db_sum'] / $account['db_count'] * 100,1);
|
||||
|
||||
if($account['db_ratio'] >= 100) {
|
||||
$account['db_ratio'] = 100;
|
||||
array_push($account['class'], 'over');
|
||||
}
|
||||
|
||||
if(!$account['db_sum']) $account['db_sum'] = 0;
|
||||
}
|
||||
|
||||
return $this->respond($accounts);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getData(){
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = [
|
||||
'dates' => [
|
||||
'sdate' => $this->request->getGet('sdate') ? $this->request->getGet('sdate') : date('Y-m-d'),
|
||||
'edate' => $this->request->getGet('edate') ? $this->request->getGet('edate') : date('Y-m-d'),
|
||||
],
|
||||
'type' => $this->request->getGet('type'),
|
||||
'businesses' => $this->request->getGet('businesses'),
|
||||
'accounts' => $this->request->getGet('accounts'),
|
||||
'stx' => $this->request->getGet('stx'),
|
||||
];
|
||||
|
||||
if($arg['type'] == 'ads'){
|
||||
$result = $this->getAds($arg);
|
||||
}else if($arg['type'] == 'adsets'){
|
||||
$result = $this->getAdSets($arg);
|
||||
}else{
|
||||
$result = $this->getCampaigns($arg);
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getReport()
|
||||
{
|
||||
if(isset($this->request) && $this->request->isAJAX()){
|
||||
$arg = [
|
||||
'sdate' => $this->request->getGet('sdate'),
|
||||
'edate' => $this->request->getGet('edate'),
|
||||
];
|
||||
}else{
|
||||
$arg = [
|
||||
'sdate' => date("Y-m-d"),
|
||||
'edate' => date("Y-m-d"),
|
||||
];
|
||||
}
|
||||
|
||||
$res = $this->google->getReport($arg)->get()->getResultArray();
|
||||
$columnIndex = 0;
|
||||
$data = [];
|
||||
foreach($res as $row) {
|
||||
$data[] = $row;
|
||||
foreach ($row as $col => $val) {
|
||||
if ($val == NULL) $val = "0";
|
||||
$total[$col][$columnIndex] = $val;
|
||||
}
|
||||
$columnIndex++;
|
||||
}
|
||||
|
||||
$report['impressions_sum'] = $report['clicks_sum'] = $report['click_ratio_sum'] = $report['spend_sum'] = $report['unique_total_sum'] = $report['unique_one_price_sum'] = $report['conversion_ratio_sum'] = $report['profit_sum'] = $report['per_sum'] = $report['price_sum'] = 0;
|
||||
|
||||
if(!empty($res)){
|
||||
$report['impressions_sum'] = array_sum($total['impressions']); //총 노출수
|
||||
$report['clicks_sum'] = array_sum($total['click']); //총 클릭수
|
||||
if ($report['clicks_sum'] != 0 && $report['impressions_sum'] != 0) {
|
||||
$report['click_ratio_sum'] = round(($report['clicks_sum'] / $report['impressions_sum']) * 100, 2); //총 클릭률
|
||||
}
|
||||
$report['spend_sum'] = array_sum($total['spend']); //총 지출액
|
||||
$report['unique_total_sum'] = array_sum($total['unique_total']); //총 유효db수
|
||||
if ($report['spend_sum'] != 0 && $report['unique_total_sum'] != 0) {
|
||||
$report['unique_one_price_sum'] = round($report['spend_sum'] / $report['unique_total_sum'], 0); //총 db당 단가
|
||||
}
|
||||
if ($report['unique_total_sum'] != 0 && $report['clicks_sum'] != 0) {
|
||||
$report['conversion_ratio_sum'] = round(($report['unique_total_sum'] / $report['clicks_sum']) * 100, 2); //총 전환율
|
||||
}
|
||||
$report['price_sum'] = array_sum($total['price']); //총 매출액
|
||||
$report['profit_sum'] = array_sum($total['profit']); //총 수익
|
||||
if ($report['profit_sum'] != 0 && $report['price_sum'] != 0) {
|
||||
$report['per_sum'] = round(($report['profit_sum'] / $report['price_sum']) * 100, 2); //총 수익률
|
||||
}
|
||||
|
||||
$report['impressions_sum'] = number_format($report['impressions_sum']);
|
||||
$report['clicks_sum'] = number_format($report['clicks_sum']);
|
||||
$report['spend_sum'] = number_format($report['spend_sum']);
|
||||
$report['unique_one_price_sum'] = number_format($report['unique_one_price_sum']);
|
||||
$report['price_sum'] = number_format($report['price_sum']);
|
||||
$report['profit_sum'] = number_format($report['profit_sum']);
|
||||
}
|
||||
|
||||
if(isset($this->request) && $this->request->isAJAX()){
|
||||
return $this->respond($report);
|
||||
}else{
|
||||
return $report;
|
||||
}
|
||||
}
|
||||
|
||||
private function getCampaigns($arg)
|
||||
{
|
||||
$campaigns = $this->google->getCampaigns($arg);
|
||||
$campaigns = $this->google->getStatuses("campaigns", $campaigns, $arg['dates']);
|
||||
$total = $this->getTotal($campaigns);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $campaigns,
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getAdSets($arg)
|
||||
{
|
||||
$adsets = $this->google->getAdSets($arg);
|
||||
$adsets = $this->google->getStatuses("adsets", $adsets, $arg['dates']);
|
||||
$total = $this->getTotal($adsets);
|
||||
|
||||
foreach ($adsets as &$adset) {
|
||||
$adset['bidAmount'] = max([$adset['cpcBidAmount'],$adset['cpmBidAmount']]);
|
||||
if($adset['biddingStrategyType'] == '타겟 CPA')
|
||||
$adset['bidAmount'] = $adset['cpaBidAmount'];
|
||||
}
|
||||
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $adsets
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getAds($arg)
|
||||
{
|
||||
$ads = $this->google->getAds($arg);
|
||||
$ads = $this->google->getStatuses("ads", $ads, $arg['dates']);
|
||||
$total = $this->getTotal($ads);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $ads
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getDisapprovalByAccount()
|
||||
{
|
||||
$disapprovals = $this->google->getDisapproval();
|
||||
$data = [];
|
||||
foreach ($disapprovals as $row) {
|
||||
$data[] = $row['customerId'];
|
||||
}
|
||||
$data = array_unique($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function getTotal($datas)
|
||||
{
|
||||
$total = [];
|
||||
$total['impressions'] = 0;
|
||||
$total['click'] = 0;
|
||||
$total['spend'] = 0;
|
||||
$total['margin'] = 0;
|
||||
$total['unique_total'] = 0;
|
||||
$total['sales'] = 0;
|
||||
$total['budget'] = 0;
|
||||
$total['cpc'] = 0;
|
||||
$total['ctr'] = 0;
|
||||
$total['cpa'] = 0;
|
||||
$total['cvr'] = 0;
|
||||
$total['margin_ratio'] = 0;
|
||||
$total['expect_db'] = 0;
|
||||
foreach($datas as $data){
|
||||
$total['impressions'] +=$data['impressions'];
|
||||
$total['click'] +=$data['click'];
|
||||
$total['spend'] +=$data['spend'];
|
||||
$total['margin'] +=$data['margin'];
|
||||
$total['unique_total'] +=$data['unique_total'];
|
||||
$total['sales'] +=$data['sales'];
|
||||
$total['budget'] +=$data['budget'];
|
||||
$total['cpc'] +=$data['cpc'];
|
||||
$total['ctr'] +=$data['ctr'];
|
||||
$total['cpa'] +=$data['cpa'];
|
||||
$total['cvr'] +=$data['cvr'];
|
||||
$total['margin_ratio'] +=$data['margin_ratio'];
|
||||
|
||||
//CPC(Cost Per Click: 클릭당단가 (1회 클릭당 비용)) = 지출액/링크클릭
|
||||
if($total['click'] > 0){
|
||||
$total['avg_cpc'] = $total['spend'] / $total['click'];
|
||||
}else{
|
||||
$total['avg_cpc'] = 0;
|
||||
}
|
||||
|
||||
//CTR(Click Through Rate: 클릭율 (노출 대비 클릭한 비율)) = (링크클릭/노출수)*100
|
||||
$total['avg_ctr'] = ($total['click'] / $total['impressions']) * 100;
|
||||
|
||||
//CPA(Cost Per Action: 현재 DB단가(전환당 비용)) = 지출액/유효db
|
||||
if($total['unique_total'] > 0){
|
||||
$total['avg_cpa'] = $total['spend'] / $total['unique_total'];
|
||||
}else{
|
||||
$total['avg_cpa'] = 0;
|
||||
}
|
||||
|
||||
//CVR(Conversion Rate:전환율 = (유효db / 링크클릭)*100
|
||||
if ($total['click'] > 0) {
|
||||
$total['avg_cvr'] = ($total['unique_total'] / $total['click']) * 100;
|
||||
} else {
|
||||
$total['avg_cvr'] = 0;
|
||||
}
|
||||
|
||||
//수익률 = (수익/매출액)*100
|
||||
if ($total['sales'] > 0) {
|
||||
$total['avg_margin_ratio'] = ($total['margin'] / $total['sales']) * 100;
|
||||
} else {
|
||||
$total['avg_margin_ratio'] = 0;
|
||||
}
|
||||
|
||||
if ($data['status'] == 'ACTIVE' && $data['unique_total']){
|
||||
$total['expect_db'] += round($data['budget'] / $data['cpa']);
|
||||
}
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\AdvertisementManager;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\Advertiser\AdvKakaoManagerModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class AdvKakaoManagerController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $kakao;
|
||||
public function __construct()
|
||||
{
|
||||
$this->kakao = model(AdvKakaoManagerModel::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('advertisements/kakao/kakao');
|
||||
}
|
||||
|
||||
public function getAccounts()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = [
|
||||
'dates' => [
|
||||
'sdate' => $this->request->getGet('sdate') ? $this->request->getGet('sdate') : date('Y-m-d'),
|
||||
'edate' => $this->request->getGet('edate') ? $this->request->getGet('edate') : date('Y-m-d'),
|
||||
],
|
||||
'businesses' => $this->request->getGet('businesses'),
|
||||
];
|
||||
|
||||
$accounts = $this->kakao->getAccounts($arg);
|
||||
$getDisapprovalByAccount = $this->getDisapprovalByAccount();
|
||||
foreach ($accounts as &$account) {
|
||||
$account['class'] = [];
|
||||
if($account['config'] == 'OFF' || $account['isAdminStop'] == 1)
|
||||
array_push($account['class'], 'tag-inactive');
|
||||
if(is_array($getDisapprovalByAccount) && in_array($account['id'], $getDisapprovalByAccount))
|
||||
array_push($account['class'], 'disapproval');
|
||||
}
|
||||
|
||||
return $this->respond($accounts);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getData(){
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = [
|
||||
'dates' => [
|
||||
'sdate' => $this->request->getGet('sdate') ? $this->request->getGet('sdate') : date('Y-m-d'),
|
||||
'edate' => $this->request->getGet('edate') ? $this->request->getGet('edate') : date('Y-m-d'),
|
||||
],
|
||||
'type' => $this->request->getGet('type'),
|
||||
'accounts' => $this->request->getGet('accounts'),
|
||||
'stx' => $this->request->getGet('stx'),
|
||||
];
|
||||
|
||||
if($arg['type'] == 'ads'){
|
||||
$result = $this->getAds($arg);
|
||||
}else if($arg['type'] == 'adsets'){
|
||||
$result = $this->getAdSets($arg);
|
||||
}else{
|
||||
$result = $this->getCampaigns($arg);
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getReport()
|
||||
{
|
||||
if(isset($this->request) && $this->request->isAJAX()){
|
||||
$arg = [
|
||||
'sdate' => $this->request->getGet('sdate'),
|
||||
'edate' => $this->request->getGet('edate'),
|
||||
];
|
||||
}else{
|
||||
$arg = [
|
||||
'sdate' => date("Y-m-d"),
|
||||
'edate' => date("Y-m-d"),
|
||||
];
|
||||
}
|
||||
|
||||
$res = $this->kakao->getReport($arg)->get()->getResultArray();
|
||||
$columnIndex = 0;
|
||||
$data = [];
|
||||
foreach($res as $row) {
|
||||
$data[] = $row;
|
||||
foreach ($row as $col => $val) {
|
||||
if ($val == NULL) $val = "0";
|
||||
$total[$col][$columnIndex] = $val;
|
||||
}
|
||||
$columnIndex++;
|
||||
}
|
||||
|
||||
$report['impressions_sum'] = $report['clicks_sum'] = $report['click_ratio_sum'] = $report['spend_sum'] = $report['unique_total_sum'] = $report['unique_one_price_sum'] = $report['conversion_ratio_sum'] = $report['profit_sum'] = $report['per_sum'] = 0;
|
||||
|
||||
if(!empty($res)){
|
||||
$report['impressions_sum'] = array_sum($total['impressions']); //총 노출수
|
||||
$report['clicks_sum'] = array_sum($total['click']); //총 클릭수
|
||||
if($report['clicks_sum'] != 0 && $report['impressions_sum'] != 0) {
|
||||
$report['click_ratio_sum'] = round(($report['clicks_sum'] / $report['impressions_sum']) * 100,2); //총 클릭률
|
||||
}
|
||||
$report['spend_sum'] = array_sum($total['spend']); //총 지출액
|
||||
$report['unique_total_sum'] = array_sum($total['unique_total']); //총 유효db수
|
||||
if($report['spend_sum'] != 0 && $report['unique_total_sum'] != 0) {
|
||||
$report['unique_one_price_sum'] = round($report['spend_sum'] / $report['unique_total_sum'],0); //총 db당 단가
|
||||
}
|
||||
if($report['unique_total_sum'] != 0 && $report['clicks_sum'] != 0) {
|
||||
$report['conversion_ratio_sum'] = round(($report['unique_total_sum'] / $report['clicks_sum']) * 100,2); //총 전환율
|
||||
}
|
||||
$report['price_sum'] = array_sum($total['price']); //총 매출액
|
||||
$report['profit_sum'] = array_sum($total['profit']); //총 수익
|
||||
if($report['profit_sum'] != 0 && $report['price_sum'] != 0) {
|
||||
$report['per_sum'] = round(($report['profit_sum'] / $report['price_sum']) * 100,2); //총 수익률
|
||||
}
|
||||
|
||||
$report['impressions_sum'] = number_format($report['impressions_sum']);
|
||||
$report['clicks_sum'] = number_format($report['clicks_sum']);
|
||||
$report['spend_sum'] = number_format($report['spend_sum']);
|
||||
$report['unique_one_price_sum'] = number_format($report['unique_one_price_sum']);
|
||||
$report['price_sum'] = number_format($report['price_sum']);
|
||||
$report['profit_sum'] = number_format($report['profit_sum']);
|
||||
}
|
||||
|
||||
if(isset($this->request) && $this->request->isAJAX()){
|
||||
return $this->respond($report);
|
||||
}else{
|
||||
return $report;
|
||||
}
|
||||
}
|
||||
|
||||
private function getCampaigns($arg)
|
||||
{
|
||||
$campaigns = $this->kakao->getCampaigns($arg);
|
||||
$campaigns = $this->kakao->getStatuses("campaigns", $campaigns, $arg['dates']);
|
||||
$total = $this->getTotal($campaigns);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $campaigns,
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getAdSets($arg)
|
||||
{
|
||||
$adsets = $this->kakao->getAdSets($arg);
|
||||
$adsets = $this->kakao->getStatuses("adsets", $adsets, $arg['dates']);
|
||||
$total = $this->getTotal($adsets);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $adsets
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getAds($arg)
|
||||
{
|
||||
$ads = $this->kakao->getAds($arg);
|
||||
$ads = $this->kakao->getStatuses("ads", $ads, $arg['dates']);
|
||||
$total = $this->getTotal($ads);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $ads
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getDisapprovalByAccount()
|
||||
{
|
||||
$disapprovals = $this->kakao->getDisapproval();
|
||||
$data = [];
|
||||
foreach ($disapprovals as $row) {
|
||||
$data[] = $row['account_id'];
|
||||
}
|
||||
$data = array_unique($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function getTotal($datas)
|
||||
{
|
||||
$total = [];
|
||||
$total['impressions'] = 0;
|
||||
$total['click'] = 0;
|
||||
$total['spend'] = 0;
|
||||
$total['margin'] = 0;
|
||||
$total['unique_total'] = 0;
|
||||
$total['sales'] = 0;
|
||||
$total['budget'] = 0;
|
||||
$total['cpc'] = 0;
|
||||
$total['ctr'] = 0;
|
||||
$total['cpa'] = 0;
|
||||
$total['cvr'] = 0;
|
||||
$total['margin_ratio'] = 0;
|
||||
$total['expect_db'] = 0;
|
||||
foreach($datas as $data){
|
||||
$total['impressions'] +=$data['impressions'];
|
||||
$total['click'] +=$data['click'];
|
||||
$total['spend'] +=$data['spend'];
|
||||
$total['margin'] +=$data['margin'];
|
||||
$total['unique_total'] +=$data['unique_total'];
|
||||
$total['sales'] +=$data['sales'];
|
||||
$total['budget'] +=$data['budget'];
|
||||
$total['cpc'] +=$data['cpc'];
|
||||
$total['ctr'] +=$data['ctr'];
|
||||
$total['cpa'] +=$data['cpa'];
|
||||
$total['cvr'] +=$data['cvr'];
|
||||
$total['margin_ratio'] +=$data['margin_ratio'];
|
||||
|
||||
//CPC(Cost Per Click: 클릭당단가 (1회 클릭당 비용)) = 지출액/링크클릭
|
||||
if($total['click'] > 0){
|
||||
$total['avg_cpc'] = $total['spend'] / $total['click'];
|
||||
}else{
|
||||
$total['avg_cpc'] = 0;
|
||||
}
|
||||
|
||||
//CTR(Click Through Rate: 클릭율 (노출 대비 클릭한 비율)) = (링크클릭/노출수)*100
|
||||
$total['avg_ctr'] = ($total['click'] / $total['impressions']) * 100;
|
||||
|
||||
//CPA(Cost Per Action: 현재 DB단가(전환당 비용)) = 지출액/유효db
|
||||
if($total['unique_total'] > 0){
|
||||
$total['avg_cpa'] = $total['spend'] / $total['unique_total'];
|
||||
}else{
|
||||
$total['avg_cpa'] = 0;
|
||||
}
|
||||
|
||||
//CVR(Conversion Rate:전환율 = (유효db / 링크클릭)*100
|
||||
if ($total['click'] > 0) {
|
||||
$total['avg_cvr'] = ($total['unique_total'] / $total['click']) * 100;
|
||||
} else {
|
||||
$total['avg_cvr'] = 0;
|
||||
}
|
||||
|
||||
//수익률 = (수익/매출액)*100
|
||||
if ($total['sales'] > 0) {
|
||||
$total['avg_margin_ratio'] = ($total['margin'] / $total['sales']) * 100;
|
||||
} else {
|
||||
$total['avg_margin_ratio'] = 0;
|
||||
}
|
||||
|
||||
|
||||
if ($data['status'] == 'ON' && $data['unique_total']){
|
||||
$total['expect_db'] += round($data['budget'] / $data['cpa']);
|
||||
}
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
private function array_remove_keys($array, $keys)
|
||||
{
|
||||
$assocKeys = array();
|
||||
foreach ($keys as $key) {
|
||||
$assocKeys[$key] = true;
|
||||
}
|
||||
|
||||
return array_diff_key($array, $assocKeys);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\AdvertisementManager;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\Advertiser\AdvNaverManagerModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class AdvNaverManagerController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $naver;
|
||||
public function __construct()
|
||||
{
|
||||
$this->naver = model(AdvNaverManagerModel::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('advertisements/naver/naver');
|
||||
}
|
||||
|
||||
public function getAccounts()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = [
|
||||
'dates' => [
|
||||
'sdate' => $this->request->getGet('sdate') ? $this->request->getGet('sdate') : date('Y-m-d'),
|
||||
'edate' => $this->request->getGet('edate') ? $this->request->getGet('edate') : date('Y-m-d'),
|
||||
],
|
||||
];
|
||||
|
||||
$accounts = $this->naver->getAccounts($arg);
|
||||
|
||||
return $this->respond($accounts);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getData(){
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = [
|
||||
'dates' => [
|
||||
'sdate' => $this->request->getGet('sdate') ? $this->request->getGet('sdate') : date('Y-m-d'),
|
||||
'edate' => $this->request->getGet('edate') ? $this->request->getGet('edate') : date('Y-m-d'),
|
||||
],
|
||||
'type' => $this->request->getGet('type'),
|
||||
'accounts' => $this->request->getGet('accounts'),
|
||||
'stx' => $this->request->getGet('stx'),
|
||||
];
|
||||
|
||||
if($arg['type'] == 'ads'){
|
||||
$result = $this->getAds($arg);
|
||||
}else if($arg['type'] == 'adsets'){
|
||||
$result = $this->getAdSets($arg);
|
||||
}else{
|
||||
$result = $this->getCampaigns($arg);
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getReport()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = [
|
||||
'dates' => [
|
||||
'sdate' => $this->request->getGet('sdate') ? $this->request->getGet('sdate') : date('Y-m-d'),
|
||||
'edate' => $this->request->getGet('edate') ? $this->request->getGet('edate') : date('Y-m-d'),
|
||||
],
|
||||
'accounts' => $this->request->getGet('accounts'),
|
||||
];
|
||||
|
||||
$res = $this->naver->getReport($arg);
|
||||
$columnIndex = 0;
|
||||
$data = [];
|
||||
foreach($res as $row) {
|
||||
$data[] = $row;
|
||||
foreach ($row as $col => $val) {
|
||||
if ($val == NULL) $val = "0";
|
||||
$total[$col][$columnIndex] = $val;
|
||||
}
|
||||
$columnIndex++;
|
||||
}
|
||||
|
||||
$report['impressions_sum'] = $report['clicks_sum'] = $report['click_ratio_sum'] = $report['spend_sum'] = $report['unique_total_sum'] = $report['unique_one_price_sum'] = $report['conversion_ratio_sum'] = $report['profit_sum'] = $report['per_sum'] = 0;
|
||||
|
||||
if(!empty($res)){
|
||||
$report['impressions_sum'] = array_sum($total['impressions']); //총 노출수
|
||||
$report['clicks_sum'] = array_sum($total['click']); //총 클릭수
|
||||
if($report['clicks_sum'] != 0 && $report['impressions_sum'] != 0) {
|
||||
$report['click_ratio_sum'] = round(($report['clicks_sum'] / $report['impressions_sum']) * 100,2); //총 클릭률
|
||||
}
|
||||
$report['spend_sum'] = array_sum($total['spend']); //총 지출액
|
||||
$report['unique_total_sum'] = array_sum($total['unique_total']); //총 유효db수
|
||||
if($report['spend_sum'] != 0 && $report['unique_total_sum'] != 0) {
|
||||
$report['unique_one_price_sum'] = round($report['spend_sum'] / $report['unique_total_sum'],0); //총 db당 단가
|
||||
}
|
||||
if($report['unique_total_sum'] != 0 && $report['clicks_sum'] != 0) {
|
||||
$report['conversion_ratio_sum'] = round(($report['unique_total_sum'] / $report['clicks_sum']) * 100,2); //총 전환율
|
||||
}
|
||||
$report['price_sum'] = array_sum($total['price']); //총 매출액
|
||||
$report['profit_sum'] = array_sum($total['profit']); //총 수익
|
||||
if($report['profit_sum'] != 0 && $report['price_sum'] != 0) {
|
||||
$report['per_sum'] = round(($report['profit_sum'] / $report['price_sum']) * 100,2); //총 수익률
|
||||
}
|
||||
}
|
||||
return $this->respond($report);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
private function getCampaigns($arg)
|
||||
{
|
||||
$campaigns = $this->naver->getCampaigns($arg);
|
||||
$campaigns = $this->naver->getStatuses("campaigns", $campaigns, $arg['dates']);
|
||||
$total = $this->getTotal($campaigns);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $campaigns,
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getAdSets($arg)
|
||||
{
|
||||
$adsets = $this->naver->getAdSets($arg);
|
||||
$adsets = $this->naver->getStatuses("adsets", $adsets, $arg['dates']);
|
||||
$total = $this->getTotal($adsets);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $adsets
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getAds($arg)
|
||||
{
|
||||
$ads = $this->naver->getAds($arg);
|
||||
$ads = $this->naver->getStatuses("ads", $ads, $arg['dates']);
|
||||
$total = $this->getTotal($ads);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $ads
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getTotal($datas)
|
||||
{
|
||||
$total = [];
|
||||
$total['impressions'] = 0;
|
||||
$total['click'] = 0;
|
||||
$total['spend'] = 0;
|
||||
$total['margin'] = 0;
|
||||
$total['unique_total'] = 0;
|
||||
$total['sales'] = 0;
|
||||
$total['dailyBudgetAmount'] = 0;
|
||||
$total['cpc'] = 0;
|
||||
$total['ctr'] = 0;
|
||||
$total['cpa'] = 0;
|
||||
$total['cvr'] = 0;
|
||||
$total['margin_ratio'] = 0;
|
||||
$total['expect_db'] = 0;
|
||||
foreach($datas as $data){
|
||||
$total['margin'] = $data['sales'] - $data['cost'];
|
||||
$total['impressions'] +=$data['impressions'];
|
||||
$total['click'] +=$data['click'];
|
||||
$total['spend'] +=$data['spend'];
|
||||
$total['margin'] +=$data['margin'];
|
||||
$total['unique_total'] +=$data['unique_total'];
|
||||
$total['sales'] +=$data['sales'];
|
||||
$total['cpc'] +=$data['cpc'];
|
||||
$total['ctr'] +=$data['ctr'];
|
||||
$total['cpa'] +=$data['cpa'];
|
||||
$total['cvr'] +=$data['cvr'];
|
||||
$total['margin_ratio'] +=$data['margin_ratio'];
|
||||
|
||||
//CPC(Cost Per Click: 클릭당단가 (1회 클릭당 비용)) = 지출액/링크클릭
|
||||
if($total['click'] > 0){
|
||||
$total['avg_cpc'] = $total['spend'] / $total['click'];
|
||||
}else{
|
||||
$total['avg_cpc'] = 0;
|
||||
}
|
||||
|
||||
//CTR(Click Through Rate: 클릭율 (노출 대비 클릭한 비율)) = (링크클릭/노출수)*100
|
||||
$total['avg_ctr'] = ($total['click'] / $total['impressions']) * 100;
|
||||
|
||||
//CPA(Cost Per Action: 현재 DB단가(전환당 비용)) = 지출액/유효db
|
||||
if($total['unique_total'] > 0){
|
||||
$total['avg_cpa'] = $total['spend'] / $total['unique_total'];
|
||||
}else{
|
||||
$total['avg_cpa'] = 0;
|
||||
}
|
||||
|
||||
//CVR(Conversion Rate:전환율 = (유효db / 링크클릭)*100
|
||||
if ($total['click'] > 0) {
|
||||
$total['avg_cvr'] = ($total['unique_total'] / $total['click']) * 100;
|
||||
} else {
|
||||
$total['avg_cvr'] = 0;
|
||||
}
|
||||
|
||||
//수익률 = (수익/매출액)*100
|
||||
if ($total['sales'] > 0) {
|
||||
$total['avg_margin_ratio'] = ($total['margin'] / $total['sales']) * 100;
|
||||
} else {
|
||||
$total['avg_margin_ratio'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,424 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Api;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Libraries\Calc;
|
||||
use App\Models\Advertiser\AdvFacebookManagerModel;
|
||||
use App\Models\Advertiser\AdvGoogleManagerModel;
|
||||
use App\Models\Advertiser\AdvKakaoManagerModel;
|
||||
use App\Models\Advertiser\AdvManagerModel;
|
||||
use App\Models\Api\CompanyModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class RestaController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $admanager, $facebook, $google, $kakao;
|
||||
private $advertiser = [
|
||||
'더스퀘어치과의원',
|
||||
'메이드영성형외과의원',
|
||||
'리프톤피부과의원',
|
||||
'모아만의원',
|
||||
'모우림의원',
|
||||
'열정치과의원',
|
||||
'우리들40플란트치과병원',
|
||||
'하루플란트치과의원광고주',
|
||||
'한나이브성형외과의원',
|
||||
'강남애프터치과의원',
|
||||
'참좋은치과의원',
|
||||
'보가치과의원'
|
||||
];
|
||||
public function __construct()
|
||||
{
|
||||
$this->admanager = model(AdvManagerModel::class);
|
||||
$this->facebook = model(AdvFacebookManagerModel::class);
|
||||
$this->google = model(AdvGoogleManagerModel::class);
|
||||
$this->kakao = model(AdvKakaoManagerModel::class);
|
||||
}
|
||||
|
||||
public function getList()
|
||||
{
|
||||
if(strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
if(empty($arg['external']) || $arg['external'] != 'resta'){
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
|
||||
$company = model(CompanyModel::class);
|
||||
$companySeq = $company->getCompaniesByName($this->advertiser);
|
||||
$ids = array_column($companySeq, 'id');
|
||||
$ids = implode("|", $ids);
|
||||
$arg['searchData']['resta'] = $ids;
|
||||
switch ($arg['searchData']['type']) {
|
||||
case 'ads':
|
||||
$result = $this->getAds($arg);
|
||||
break;
|
||||
case 'adsets':
|
||||
$result = $this->getAdSets($arg);
|
||||
break;
|
||||
case 'campaigns':
|
||||
$result = $this->getCampaigns($arg);
|
||||
break;
|
||||
default:
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
|
||||
$orderBy = [];
|
||||
if(!empty($arg['order'])) {
|
||||
foreach($arg['order'] as $row) {
|
||||
if($row['dir'] == 'desc'){
|
||||
$sort = SORT_DESC;
|
||||
}else{
|
||||
$sort = SORT_ASC;
|
||||
}
|
||||
$col = $arg['columns'][$row['column']]['data'];
|
||||
if($col) $orderBy[$col] = $sort;
|
||||
}
|
||||
array_sort_by_multiple_keys($result['data'], $orderBy);
|
||||
}
|
||||
|
||||
foreach ($result['data'] as &$value) {
|
||||
$value['bidamount'] = number_format($value['bidamount']);
|
||||
$value['budget'] = number_format($value['budget']);
|
||||
$value['impressions'] = number_format($value['impressions']);
|
||||
$value['click'] = number_format($value['click']);
|
||||
$value['spend'] = number_format($value['spend']);
|
||||
$value['sales'] = number_format($value['sales']);
|
||||
$value['unique_total'] = number_format($value['unique_total']);
|
||||
$value['margin'] = number_format($value['margin']);
|
||||
$value['margin_ratio'] = number_format($value['margin_ratio']);
|
||||
$value['cpa'] = number_format($value['cpa']);
|
||||
$value['cpc'] = number_format($value['cpc']);
|
||||
}
|
||||
if(isset($arg['noLimit'])) {
|
||||
return $this->respond($result['data']);
|
||||
}
|
||||
$result['accounts'] = $this->getAccounts($arg);
|
||||
$result['media_accounts'] = $this->getMediaAccounts($arg);
|
||||
$result['report'] = $this->getReport($arg);
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
private function getAccounts($arg)
|
||||
{
|
||||
$result = [];
|
||||
$accounts = $this->admanager->getAccounts($arg);
|
||||
//$accounts = $this->setAccountData($accounts);
|
||||
$result = array_merge($result, $accounts);
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getMediaAccounts($arg)
|
||||
{
|
||||
$result = $this->admanager->getMediaAccounts($arg);
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getReport($arg)
|
||||
{
|
||||
$result = $this->admanager->getReport($arg);
|
||||
$columnIndex = 0;
|
||||
$data = [];
|
||||
|
||||
foreach($result as $row) {
|
||||
$data[] = $row;
|
||||
foreach ($row as $col => $val) {
|
||||
if ($val == NULL) $val = "0";
|
||||
$total[$col][$columnIndex] = $val;
|
||||
}
|
||||
$columnIndex++;
|
||||
}
|
||||
|
||||
$report['impressions_sum'] = $report['clicks_sum'] = $report['click_ratio_sum'] = $report['spend_sum'] = $report['unique_total_sum'] = $report['unique_one_price_sum'] = $report['conversion_ratio_sum'] = $report['profit_sum'] = $report['per_sum'] = $report['price_sum'] = $report['spend_ratio_sum'] =$report['cpc'] = 0;
|
||||
|
||||
if(!empty($result)){
|
||||
|
||||
$report['impressions_sum'] = array_sum($total['impressions']); //총 노출수
|
||||
$report['clicks_sum'] = array_sum($total['click']); //총 클릭수
|
||||
if ($report['clicks_sum'] != 0 && $report['impressions_sum'] != 0) {
|
||||
$report['click_ratio_sum'] = round(($report['clicks_sum'] / $report['impressions_sum']) * 100, 2); //총 클릭률
|
||||
}
|
||||
$report['spend_sum'] = array_sum($total['spend']); //총 지출액
|
||||
$report['spend_ratio_sum'] = floor(array_sum($total['spend']) * 0.85); //총 매체비
|
||||
if ($report['clicks_sum'] != 0) {
|
||||
$report['cpc'] = round($report['spend_sum'] / $report['clicks_sum'], 2);
|
||||
} else {
|
||||
$report['cpc'] = 0;
|
||||
}
|
||||
$report['unique_total_sum'] = array_sum($total['unique_total']); //총 유효db수
|
||||
if ($report['spend_sum'] != 0 && $report['unique_total_sum'] != 0) {
|
||||
$report['unique_one_price_sum'] = round($report['spend_sum'] / $report['unique_total_sum'], 0); //총 db당 단가
|
||||
}
|
||||
if ($report['unique_total_sum'] != 0 && $report['clicks_sum'] != 0) {
|
||||
$report['conversion_ratio_sum'] = round(($report['unique_total_sum'] / $report['clicks_sum']) * 100, 2); //총 전환율
|
||||
}
|
||||
$report['price_sum'] = array_sum($total['price']); //총 매출액
|
||||
$report['profit_sum'] = array_sum($total['profit']); //총 수익
|
||||
if ($report['profit_sum'] != 0 && $report['price_sum'] != 0) {
|
||||
$report['per_sum'] = round(($report['profit_sum'] / $report['price_sum']) * 100, 2); //총 수익률
|
||||
}
|
||||
|
||||
$report['impressions_sum'] = number_format($report['impressions_sum']);
|
||||
$report['clicks_sum'] = number_format($report['clicks_sum']);
|
||||
$report['spend_sum'] = number_format($report['spend_sum']);
|
||||
$report['unique_one_price_sum'] = number_format($report['unique_one_price_sum']);
|
||||
$report['spend_ratio_sum'] = number_format($report['spend_ratio_sum']);
|
||||
$report['price_sum'] = number_format($report['price_sum']);
|
||||
$report['profit_sum'] = number_format($report['profit_sum']);
|
||||
}
|
||||
|
||||
return $report;
|
||||
}
|
||||
|
||||
private function getCampaigns($arg)
|
||||
{
|
||||
$campaigns = $this->admanager->getCampaigns($arg);
|
||||
$campaigns = $this->setData($campaigns);
|
||||
|
||||
$total = $this->getTotal($campaigns);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $campaigns,
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getAdSets($arg)
|
||||
{
|
||||
$result = [];
|
||||
$campaigns = $this->admanager->getAdSets($arg);
|
||||
$campaigns = $this->setData($campaigns);
|
||||
$result = array_merge($result, $campaigns);
|
||||
|
||||
$total = $this->getTotal($result);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $result,
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getAds($arg)
|
||||
{
|
||||
$result = [];
|
||||
$campaigns = $this->admanager->getAds($arg);
|
||||
$campaigns = $this->setData($campaigns);
|
||||
$result = array_merge($result, $campaigns);
|
||||
|
||||
$total = $this->getTotal($result);
|
||||
|
||||
$result = [
|
||||
'total' => $total,
|
||||
'data' => $result,
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function setData($result)
|
||||
{
|
||||
foreach ($result as &$row) {
|
||||
$row['status'] = $this->setStatus($row['status']);
|
||||
|
||||
$row['margin_ratio'] = Calc::margin_ratio($row['margin'], $row['sales']); // 수익률
|
||||
|
||||
$row['cpc'] = Calc::cpc($row['spend'], $row['click']); // 클릭당단가 (1회 클릭당 비용)
|
||||
$row['ctr'] = Calc::ctr($row['click'], $row['impressions']); // 클릭율 (노출 대비 클릭한 비율)
|
||||
$row['cpa'] = Calc::cpa($row['unique_total'], $row['spend']); //DB단가(전환당 비용)
|
||||
$row['cvr'] = Calc::cvr($row['unique_total'], $row['click']); //전환율
|
||||
|
||||
if($row['bidamount_type'] == 'cpm' && $row['bidamount'] <= 1){
|
||||
$row['bidamount_type'] = '';
|
||||
$row['bidamount'] = 0;
|
||||
}
|
||||
|
||||
if(!empty($row['biddingStrategyType'])){
|
||||
switch($row['biddingStrategyType']) {
|
||||
case 'TARGET_CPA' :
|
||||
$row['biddingStrategyType'] = '타겟 CPA';
|
||||
break;
|
||||
case 'TARGET_ROAS' :
|
||||
$row['biddingStrategyType'] = '타겟 광고 투자수익(ROAS)';
|
||||
break;
|
||||
case 'TARGET_SPEND' :
|
||||
$row['biddingStrategyType'] = '클릭수 최대화';
|
||||
break;
|
||||
case 'MAXIMIZE_CONVERSIONS' :
|
||||
$row['biddingStrategyType'] = '전환수 최대화';
|
||||
break;
|
||||
/* //값이 뭔지 모름ㅠㅠ
|
||||
case '' :
|
||||
$row['biddingStrategyType'] = '검색 결과 위치 타겟';
|
||||
break;
|
||||
case '' :
|
||||
$row['biddingStrategyType'] = '경쟁 광고보다 내 광고가 높은 순위에 게재되는 비율 타겟';
|
||||
break;
|
||||
case '' :
|
||||
$row['biddingStrategyType'] = '타겟 노출 점유율';
|
||||
break;
|
||||
*/
|
||||
case 'PAGE_ONE_PROMOTED' :
|
||||
$row['biddingStrategyType'] = '향상된 CPC 입찰기능';
|
||||
break;
|
||||
case 'MANUAL_CPM' :
|
||||
$row['biddingStrategyType'] = '수동 입찰 전략';
|
||||
break;
|
||||
case 'MANUAL_CPC' :
|
||||
$row['biddingStrategyType'] = '수동 CPC';
|
||||
break;
|
||||
case 'UNKNOWN' :
|
||||
$row['biddingStrategyType'] = '알수없음';
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function setStatus($status)
|
||||
{
|
||||
/*
|
||||
ON = 인정,
|
||||
READY = 집행 예정,
|
||||
FINISHED = 집행 완료,
|
||||
STOPPED = 정지,
|
||||
ARCHIVED = 보관,
|
||||
DELETED = 삭제
|
||||
UNKNOWN = 알수 없음
|
||||
UNSPECIFIED = 명시되지 않음
|
||||
EXCEED_DAILY_BUDGET = 일 예산 초과
|
||||
NO_AVAILABLE_CREATIVE = 집행 가능한 소재가 없음
|
||||
CANCELED = 계약 해지
|
||||
SYSTEM_CONFIG_EXTERNAL_SERVICE_STOP = 연결 서비스 제한으로 운영불가인 상태
|
||||
ADACCOUNT_UNAVAILABLE = 광고계정 운영불가
|
||||
CAMPAIGN_UNAVAILABLE = 캠페인 운영불가
|
||||
ADGROUP_UNAVAILABLE = 광고 상위단위인 광고그룹이 운영불가인 상태
|
||||
SYSTEM_CONFIG_ADMIN_STOP = 관리자 정지
|
||||
OPERATING = 운영가능 상태
|
||||
UNAPPROVED = 심사승인이 아닌 상태(심사중, 심사보류를 모두 포함)
|
||||
INVALID_DATE = 집행기간이 도래하지 않았거나 이미 지난 상태
|
||||
MONITORING_REJECTED = 관리자정지 상태
|
||||
SYSTEM_CONFIG_VOID = 소재 콘텐츠 오류로 소재 운영불가인 상태
|
||||
*/
|
||||
if(!empty($status)){
|
||||
if(in_array($status, ['ENABLED', 'ACTIVE', 'LIVE', 'ON'])){$status = 'ON';}
|
||||
else if(in_array($status, ['READY'])){$status = 'READY';}
|
||||
else if(in_array($status, ['FINISHED'])){$status = 'FINISHED';}
|
||||
else if(in_array($status, ['OFF', 'PAUSED'])){$status = 'OFF';}
|
||||
else if(in_array($status, ['ARCHIVED'])){$status = 'ARCHIVED';}
|
||||
else if(in_array($status, ['DELETED', 'REMOVED'])){$status = 'DELETED';}
|
||||
else if(in_array($status, ['UNKNOWN'])){$status = 'UNKNOWN';}
|
||||
else if(in_array($status, ['UNSPECIFIED'])){$status = 'UNSPECIFIED';}
|
||||
else if(in_array($status, ['EXCEED_DAILY_BUDGET'])){$status = 'EXCEED_DAILY_BUDGET';}
|
||||
else if(in_array($status, ['NO_AVAILABLE_CREATIVE'])){$status = 'NO_AVAILABLE_CREATIVE';}
|
||||
else if(in_array($status, ['CANCELED'])){$status = 'CANCELED';}
|
||||
else if(in_array($status, ['SYSTEM_CONFIG_EXTERNAL_SERVICE_STOP'])){$status = 'SYSTEM_CONFIG_EXTERNAL_SERVICE_STOP';}
|
||||
else if(in_array($status, ['ADACCOUNT_UNAVAILABLE'])){$status = 'ADACCOUNT_UNAVAILABLE';}
|
||||
else if(in_array($status, ['CAMPAIGN_UNAVAILABLE'])){$status = 'CAMPAIGN_UNAVAILABLE';}
|
||||
else if(in_array($status, ['SYSTEM_CONFIG_ADMIN_STOP'])){$status = 'SYSTEM_CONFIG_ADMIN_STOP';}
|
||||
else if(in_array($status, ['OPERATING'])){$status = 'OPERATING';}
|
||||
else if(in_array($status, ['UNAPPROVED'])){$status = 'UNAPPROVED';}
|
||||
else if(in_array($status, ['INVALID_DATE'])){$status = 'INVALID_DATE';}
|
||||
else if(in_array($status, ['MONITORING_REJECTED'])){$status = 'MONITORING_REJECTED';}
|
||||
else if(in_array($status, ['ADGROUP_UNAVAILABLE'])){$status = 'ADGROUP_UNAVAILABLE';}
|
||||
else if(in_array($status, ['SYSTEM_CONFIG_VOID'])){$status = 'SYSTEM_CONFIG_VOID';}
|
||||
else{$status = 'ETC';};
|
||||
}else{
|
||||
$status = NULL;
|
||||
};
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
private function getTotal($datas)
|
||||
{
|
||||
$total = [];
|
||||
$total['impressions'] = 0;
|
||||
$total['click'] = 0;
|
||||
$total['spend'] = 0;
|
||||
$total['margin'] = 0;
|
||||
$total['unique_total'] = 0;
|
||||
$total['sales'] = 0;
|
||||
$total['budget'] = 0;
|
||||
$total['bidamount'] = 0;
|
||||
$total['cpc'] = 0;
|
||||
$total['ctr'] = 0;
|
||||
$total['cpa'] = 0;
|
||||
$total['cvr'] = 0;
|
||||
$total['margin_ratio'] = 0;
|
||||
$total['expect_db'] = 0;
|
||||
$total['avg_cpc'] = 0;
|
||||
$total['avg_cpa'] = 0;
|
||||
$total['avg_cvr'] = 0;
|
||||
$total['avg_ctr'] = 0;
|
||||
foreach($datas as $data){
|
||||
$total['impressions'] +=$data['impressions'];
|
||||
$total['click'] +=$data['click'];
|
||||
$total['spend'] +=$data['spend'];
|
||||
$total['margin'] +=$data['margin'];
|
||||
$total['unique_total'] +=$data['unique_total'];
|
||||
$total['sales'] +=$data['sales'];
|
||||
$total['bidamount'] +=$data['bidamount'];
|
||||
$total['budget'] +=$data['budget'];
|
||||
$total['cpc'] +=$data['cpc'];
|
||||
$total['ctr'] +=$data['ctr'];
|
||||
$total['cpa'] +=$data['cpa'];
|
||||
$total['cvr'] +=$data['cvr'];
|
||||
$total['margin_ratio'] +=$data['margin_ratio'];
|
||||
|
||||
//CPC(Cost Per Click: 클릭당단가 (1회 클릭당 비용)) = 지출액/링크클릭
|
||||
if($total['click'] > 0){
|
||||
$total['avg_cpc'] = $total['spend'] / $total['click'];
|
||||
}
|
||||
|
||||
//CTR(Click Through Rate: 클릭율 (노출 대비 클릭한 비율)) = (링크클릭/노출수)*100
|
||||
if($total['impressions'] > 0){
|
||||
$total['avg_ctr'] = ($total['click'] / $total['impressions']) * 100;
|
||||
}
|
||||
|
||||
//CPA(Cost Per Action: 현재 DB단가(전환당 비용)) = 지출액/유효db
|
||||
if($total['unique_total'] > 0){
|
||||
$total['avg_cpa'] = $total['spend'] / $total['unique_total'];
|
||||
}
|
||||
|
||||
//CVR(Conversion Rate:전환율 = (유효db / 링크클릭)*100
|
||||
if ($total['click'] > 0) {
|
||||
$total['avg_cvr'] = ($total['unique_total'] / $total['click']) * 100;
|
||||
}
|
||||
|
||||
//수익률 = (수익/매출액)*100
|
||||
if ($total['sales'] > 0) {
|
||||
$total['avg_margin_ratio'] = ($total['margin'] / $total['sales']) * 100;
|
||||
} else {
|
||||
$total['avg_margin_ratio'] = 0;
|
||||
}
|
||||
|
||||
if ($data['status'] == 'ON' && $data['unique_total'] && $data['cpa'] != 0){
|
||||
$total['expect_db'] += round($data['budget'] / $data['cpa']);
|
||||
}
|
||||
}
|
||||
|
||||
$total['impressions'] = number_format($total['impressions']);
|
||||
$total['bidamount'] = number_format($total['bidamount']);
|
||||
$total['budget'] = number_format($total['budget']);
|
||||
$total['click'] = number_format($total['click']);
|
||||
$total['spend'] = number_format($total['spend']);
|
||||
$total['avg_cpa'] = number_format($total['avg_cpa']);
|
||||
$total['margin'] = number_format($total['margin']);
|
||||
$total['sales'] = number_format($total['sales']);
|
||||
$total['avg_cpc'] = number_format($total['avg_cpc']);
|
||||
|
||||
return $total;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Api;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class TestController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
public function getInterlockData()
|
||||
{
|
||||
$data = $this->request->getVar();
|
||||
return $this->respond(['result'=> 200, 'msg' => 'success']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Auth;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Controllers\User\UserController;
|
||||
use CodeIgniter\Shield\Controllers\MagicLinkController as ShieldMagicLinkController;
|
||||
use CodeIgniter\Events\Events;
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use CodeIgniter\I18n\Time;
|
||||
use CodeIgniter\Shield\Authentication\Authenticators\Session;
|
||||
use CodeIgniter\Shield\Config\Auth;
|
||||
use CodeIgniter\Shield\Models\LoginModel;
|
||||
use CodeIgniter\Shield\Models\UserIdentityModel;
|
||||
|
||||
class MagicLinkController extends ShieldMagicLinkController
|
||||
{
|
||||
public function verify(): RedirectResponse
|
||||
{
|
||||
$token = $this->request->getGet('token');
|
||||
|
||||
/** @var UserIdentityModel $identityModel */
|
||||
$identityModel = model(UserIdentityModel::class);
|
||||
|
||||
$identity = $identityModel->getIdentityBySecret(Session::ID_TYPE_MAGIC_LINK, $token);
|
||||
|
||||
$identifier = $token ?? '';
|
||||
|
||||
// No token found?
|
||||
if ($identity === null) {
|
||||
$this->recordLoginAttempt($identifier, false);
|
||||
|
||||
$credentials = ['magicLinkToken' => $token];
|
||||
Events::trigger('failedLogin', $credentials);
|
||||
|
||||
return redirect()->route('magic-link')->with('error', lang('Auth.magicTokenNotFound'));
|
||||
}
|
||||
|
||||
// Delete the db entry so it cannot be used again.
|
||||
$identityModel->delete($identity->id);
|
||||
|
||||
// Token expired?
|
||||
if (Time::now()->isAfter($identity->expires)) {
|
||||
$this->recordLoginAttempt($identifier, false);
|
||||
|
||||
$credentials = ['magicLinkToken' => $token];
|
||||
Events::trigger('failedLogin', $credentials);
|
||||
|
||||
return redirect()->route('magic-link')->with('error', lang('Auth.magicLinkExpired'));
|
||||
}
|
||||
|
||||
/** @var Session $authenticator */
|
||||
$authenticator = auth('session')->getAuthenticator();
|
||||
|
||||
// If an action has been defined
|
||||
if ($authenticator->hasAction($identity->user_id)) {
|
||||
return redirect()->route('auth-action-show')->with('error', lang('Auth.forcePasswordChange'));
|
||||
}
|
||||
|
||||
// Log the user in
|
||||
$authenticator->loginById($identity->user_id);
|
||||
|
||||
$user = $authenticator->getUser();
|
||||
|
||||
$this->recordLoginAttempt($identifier, true, $user->id);
|
||||
|
||||
// Give the developer a way to know the user
|
||||
// logged in via a magic link.
|
||||
session()->setTempdata('magicLogin', true);
|
||||
|
||||
Events::trigger('magicLogin');
|
||||
$user->forcePasswordReset();
|
||||
// Get our login redirect url
|
||||
return redirect()->to('/set-password');
|
||||
}
|
||||
|
||||
private function recordLoginAttempt(
|
||||
string $identifier,
|
||||
bool $success,
|
||||
$userId = null
|
||||
): void {
|
||||
/** @var LoginModel $loginModel */
|
||||
$loginModel = model(LoginModel::class);
|
||||
|
||||
$loginModel->recordLoginAttempt(
|
||||
Session::ID_TYPE_MAGIC_LINK,
|
||||
$identifier,
|
||||
$success,
|
||||
$this->request->getIPAddress(),
|
||||
(string) $this->request->getUserAgent(),
|
||||
$userId
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Auth;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Controllers\User\UserController;
|
||||
use App\Models\Api\UserModel;
|
||||
use CodeIgniter\Shield\Authentication\Passwords;
|
||||
|
||||
class PasswordChangeController extends BaseController
|
||||
{
|
||||
private $user, $userModel;
|
||||
protected $helpers = ['setting'];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (!auth()->loggedIn()) {
|
||||
return redirect()->to('/login');
|
||||
}
|
||||
$this->user = auth()->user();
|
||||
$this->userModel = model(UserModel::class);
|
||||
}
|
||||
|
||||
public function changePasswordView()
|
||||
{
|
||||
/* if (!session('magicLogin')) {
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
|
||||
} */
|
||||
|
||||
return view(setting('Auth.views')['set-password']);
|
||||
}
|
||||
|
||||
public function changePasswordAction(){
|
||||
$data = $this->request->getPost();
|
||||
$rules = [
|
||||
'password' => [
|
||||
'label' => 'Auth.password',
|
||||
'rules' => 'required|' . Passwords::getMaxLengthRule() . '|strong_password[]',
|
||||
'errors' => [
|
||||
'max_byte' => 'Auth.errorPasswordTooLongBytes',
|
||||
],
|
||||
],
|
||||
'password_confirm' => [
|
||||
'label' => 'Auth.passwordConfirm',
|
||||
'rules' => 'required|matches[password]',
|
||||
],
|
||||
];
|
||||
|
||||
if (! $this->validateData($data, $rules, [], config('Auth')->DBGroup)) {
|
||||
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
|
||||
$this->user->fill($data);
|
||||
$result = $this->userModel->save($this->user);
|
||||
if($result == true){
|
||||
$this->user->undoForcePasswordReset();
|
||||
|
||||
$userController = new UserController;
|
||||
$userController->setPasswordChangedAt(true);
|
||||
session()->removeTempdata('magicLogin');
|
||||
}
|
||||
|
||||
return redirect()->to("/");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use CodeIgniter\Controller;
|
||||
use CodeIgniter\HTTP\CLIRequest;
|
||||
use CodeIgniter\HTTP\IncomingRequest;
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Class BaseController
|
||||
*
|
||||
* BaseController provides a convenient place for loading components
|
||||
* and performing functions that are needed by all your controllers.
|
||||
* Extend this class in any new controllers:
|
||||
* class Home extends BaseController
|
||||
*
|
||||
* For security be sure to declare any new methods as protected or private.
|
||||
*/
|
||||
abstract class BaseController extends Controller
|
||||
{
|
||||
/**
|
||||
* Instance of the main Request object.
|
||||
*
|
||||
* @var CLIRequest|IncomingRequest
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* An array of helpers to be loaded automatically upon
|
||||
* class instantiation. These helpers will be available
|
||||
* to all other controllers that extend BaseController.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $helpers = [];
|
||||
|
||||
/**
|
||||
* Be sure to declare properties for any property fetch you initialized.
|
||||
* The creation of dynamic property is deprecated in PHP 8.2.
|
||||
*/
|
||||
// protected $session;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
|
||||
{
|
||||
// Do Not Edit This Line
|
||||
parent::initController($request, $response, $logger);
|
||||
|
||||
// Preload any models, libraries, etc, here.
|
||||
|
||||
// E.g.: $this->session = \Config\Services::session();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Calendar;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\ThirdParty\googleclient\GoogleCalendar;
|
||||
|
||||
class CalendarController extends BaseController
|
||||
{
|
||||
protected $googleCalender;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->googleCalender = new GoogleCalendar();
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
//$list = $this->googleCalender->eventList();
|
||||
|
||||
/* $data['startDate'] = '2023-06-24';
|
||||
$data['endDate'] = '2023-06-30';
|
||||
$data['summary'] = 'test6';
|
||||
$this->googleCalender->createEvent($data); */
|
||||
|
||||
/* $data['startDate'] = '2023-06-20';
|
||||
$data['endDate'] = '2023-06-30';
|
||||
$data['summary'] = '테스트2';
|
||||
$event_id = '0iaudoh97jkqnp8vg1mbg5d4fg';
|
||||
$this->googleCalender->updateEvent($data, $event_id); */
|
||||
|
||||
/* $event_id = '3pp2lt2r5iuc9k4r13ampehhvt';
|
||||
$this->googleCalender->deleteEvent($event_id); */
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Company;
|
||||
|
||||
use App\Models\Api\CompanyModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class CompanyController extends \CodeIgniter\Controller
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $data, $zenith, $company, $validation;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
/* if(!auth()->user()->ingroup('superadmin', 'admin', 'developer')){
|
||||
return $this->failUnauthorized("권한이 없습니다.");
|
||||
} */
|
||||
$this->zenith = \Config\Database::connect();
|
||||
$this->company = model(CompanyModel::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('companies/company');
|
||||
}
|
||||
|
||||
public function getCompanies()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get') {
|
||||
$param = $this->request->getGet();
|
||||
$result = $this->company->getCompanies($param);
|
||||
$result = [
|
||||
'data' => $result['data'],
|
||||
'recordsTotal' => $result['allCount'],
|
||||
'recordsFiltered' => $result['allCount'],
|
||||
'draw' => intval($param['draw']),
|
||||
];
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getCompany()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get') {
|
||||
$param = $this->request->getGet();
|
||||
$result = $this->company->getCompany($param['id']);
|
||||
$result['username'] = explode(',', $result['username']);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function createCompany()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post') {
|
||||
$param = $this->request->getRawInput();
|
||||
if (!empty($param)) {
|
||||
$validation = \Config\Services::validation();
|
||||
if(!empty($param['p_name'])){
|
||||
$agency = $this->company->getAgencyByName($param['p_name']);
|
||||
if(empty($agency)) {
|
||||
return $this->failValidationErrors(["p_name" => "존재하지 않는 대행사입니다."]);
|
||||
}
|
||||
}else{
|
||||
$agency = '';
|
||||
}
|
||||
|
||||
$validation->setRules($this->company->validationRules, $this->company->validationMessages);
|
||||
if (!$validation->run($param)) {
|
||||
$errors = $validation->getErrors();
|
||||
return $this->failValidationErrors($errors);
|
||||
}
|
||||
|
||||
$result = $this->company->createCompany($param, $agency);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function setCompany()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'put') {
|
||||
$param = $this->request->getRawInput();
|
||||
if (!empty($param)) {
|
||||
$validation = \Config\Services::validation();
|
||||
if(!empty($param['p_name'])){
|
||||
$agency = $this->company->getAgencyByName($param['p_name']);
|
||||
if(empty($agency)) {
|
||||
return $this->failValidationErrors(["p_name" => "존재하지 않는 대행사입니다."]);
|
||||
}
|
||||
}else{
|
||||
$agency = '';
|
||||
}
|
||||
$validation->setRules($this->company->validationRules, $this->company->validationMessages);
|
||||
if (!$validation->run($param)) {
|
||||
$errors = $validation->getErrors();
|
||||
return $this->failValidationErrors($errors);
|
||||
}
|
||||
|
||||
$result = $this->company->setCompany($param, $agency);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getSearchCompanies()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get') {
|
||||
$param = $this->request->getGet();
|
||||
$result = $this->company->getSearchCompanies($param['stx']);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getSearchAgencies()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get') {
|
||||
$param = $this->request->getGet();
|
||||
$result = $this->company->getSearchAgencies($param['stx']);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteCompany()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'delete') {
|
||||
$param = $this->request->getRawInput();
|
||||
$result = $this->company->deleteCompany($param);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getSearchAdAccounts()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get') {
|
||||
$param = $this->request->getGet();
|
||||
$result = $this->company->getSearchAdAccounts($param['stx']);
|
||||
if(!empty($result)){
|
||||
foreach($result as &$row){
|
||||
if($row['status'] == 'ENABLED' || $row['status'] == 1 || $row['status'] == 'ON'){
|
||||
$row['status'] = '활성';
|
||||
}else{
|
||||
$row['status'] = '비활성';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getCompanyAdAccounts()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get') {
|
||||
$param = $this->request->getGet();
|
||||
$result = $this->company->getCompanyAdAccounts($param);
|
||||
if(!empty($result)){
|
||||
foreach($result as &$row){
|
||||
if($row['status'] == 'ENABLED' || $row['status'] == 1 || $row['status'] == 'ON'){
|
||||
$row['status'] = '활성';
|
||||
}else{
|
||||
$row['status'] = '비활성';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function setCompanyAdAccount()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'put') {
|
||||
$param = $this->request->getRawInput();
|
||||
$sliceId = explode("_", $param['ad_account_id']);
|
||||
$param['ad_account_id'] = $sliceId[1];
|
||||
$param['media'] = $sliceId[0];
|
||||
$adAccount = $this->company->getCompanyAdAccount($param);
|
||||
if(!empty($adAccount)){
|
||||
return $this->failValidationErrors(["username" => "이미 소속되어 있습니다."]);
|
||||
}
|
||||
$result = $this->company->setCompanyAdAccount($param);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function exceptCompanyAdAccount()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'delete') {
|
||||
$param = $this->request->getRawInput();
|
||||
$sliceId = explode("_", $param['ad_account_id']);
|
||||
$param['ad_account_id'] = $sliceId[1];
|
||||
$param['media'] = $sliceId[0];
|
||||
if (!empty($param)) {
|
||||
$result = $this->company->exceptCompanyAdAccount($param);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\EventManage;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\EventManage\AdvertiserModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class AdvertiserController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $advertiser;
|
||||
public function __construct()
|
||||
{
|
||||
$this->advertiser = model(AdvertiserModel::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('/events/advertiser/advertiser');
|
||||
}
|
||||
|
||||
public function getList()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
$result = $this->advertiser->getAdvertisers($arg);
|
||||
$list = $result['data'];
|
||||
for ($i = 0; $i < count($list); $i++) {
|
||||
if($list[$i]['is_stop']){
|
||||
$list[$i]['is_stop'] = '사용중지';
|
||||
}else{
|
||||
$list[$i]['is_stop'] = '사용중';
|
||||
}
|
||||
|
||||
if($list[$i]['interlock_url']){
|
||||
$list[$i]['interlock_url'] = 'O';
|
||||
}
|
||||
|
||||
if($list[$i]['agreement_url']){
|
||||
$list[$i]['agreement_url_exist'] = 'O';
|
||||
}
|
||||
|
||||
$list[$i]['remain_balance'] = ($list[$i]['sum_price'] == ($list[$i]['remain_balance'] * -1)) ? "" : $list[$i]['remain_balance'];
|
||||
|
||||
if($list[$i]['sum_price']){
|
||||
$list[$i]['sum_price'] = number_format($list[$i]['sum_price']);
|
||||
}
|
||||
|
||||
if($list[$i]['remain_balance']){
|
||||
$list[$i]['remain_balance'] = number_format($list[$i]['remain_balance']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$result = [
|
||||
'data' => $list,
|
||||
'recordsTotal' => $result['allCount'],
|
||||
'recordsFiltered' => $result['allCount'],
|
||||
'draw' => intval($arg['draw']),
|
||||
];
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getAdvertiser()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
$adv = $this->advertiser->getAdvertiser($arg);
|
||||
$ow = $this->advertiser->getOverwatchByAdvertiser($arg);
|
||||
$wl = $this->advertiser->getMedia($arg);
|
||||
|
||||
$result = [
|
||||
'advertiser' => $adv,
|
||||
'ow' => $ow,
|
||||
'wl' => $wl
|
||||
];
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getCompanies()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$stx = $this->request->getGet('stx');
|
||||
$result = $this->advertiser->getCompanies($stx);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function createAdv()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post'){
|
||||
$arg = $this->request->getRawInput();
|
||||
$data = [
|
||||
'name' => $arg['name'],
|
||||
'agent' => $arg['agent'],
|
||||
'username' => auth()->user()->username,
|
||||
'homepage_url' => $arg['homepage_url'],
|
||||
'interlock_url' => $arg['interlock_url'],
|
||||
'agreement_url' => $arg['agreement_url'],
|
||||
'account_balance' => empty($arg['account_balance'])?0:$arg['account_balance'],
|
||||
'is_stop' => $arg['is_stop']
|
||||
];
|
||||
if(!empty($arg['company_id'])) {
|
||||
$data['company_seq'] = $arg['company_id'];
|
||||
}
|
||||
$data['ea_datetime'] = date('Y-m-d H:i:s');
|
||||
$validation = \Config\Services::validation();
|
||||
$validationRules = [
|
||||
'name' => 'required|is_unique[event_advertiser.name]',
|
||||
// 'company_seq' => 'required|is_unique[event_advertiser.company_seq]',
|
||||
];
|
||||
$validationMessages = [
|
||||
/*
|
||||
'company_seq' => [
|
||||
'required' => '광고주 연결은 필수 입력 사항입니다.',
|
||||
'is_unique' => '이미 등록된 소속 광고주입니다.'
|
||||
],
|
||||
*/
|
||||
'name' => [
|
||||
'required' => '광고주명은 필수 입력 사항입니다.',
|
||||
'is_unique' => '이미 등록된 광고주입니다.'
|
||||
],
|
||||
];
|
||||
$validation->setRules($validationRules, $validationMessages);
|
||||
if (!$validation->run($data)) {
|
||||
$errors = $validation->getErrors();
|
||||
return $this->failValidationErrors($errors);
|
||||
}
|
||||
/*
|
||||
$company = $this->advertiser->getCompanies($arg['name'])[0];
|
||||
if(empty($company['id']) || $company['id'] != $arg['company_id']) {
|
||||
$error = ['advertiser' => '소속 광고주와 입력한 광고주가 일치하지 않습니다.'];
|
||||
return $this->failValidationErrors($error);
|
||||
}
|
||||
|
||||
if(empty($arg['company_id'])){
|
||||
$advertiser = $this->advertiser->getAdvertiserByName($data);
|
||||
if(empty($advertiser)){
|
||||
$error = ['advertiser' => '광고주명에 해당하는 소속 광고주가 존재하지 않습니다.'];
|
||||
return $this->failValidationErrors($error);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
$result = $this->advertiser->createAdv($data);
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function updateAdv()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'put'){
|
||||
$arg = $this->request->getRawInput();
|
||||
$validation = \Config\Services::validation();
|
||||
$validationRules = [
|
||||
// 'name' => 'required',
|
||||
];
|
||||
|
||||
if($arg['sms_alert']){
|
||||
$validationRules['contact.0'] = 'required';
|
||||
}
|
||||
|
||||
$validationMessages = [
|
||||
'contact.0' => [
|
||||
'required' => '연락처는 필수 입력 사항입니다.'
|
||||
],
|
||||
];
|
||||
if(count($validationRules)) {
|
||||
$validation->setRules($validationRules, $validationMessages);
|
||||
if (!$validation->run($arg)) {
|
||||
$errors = $validation->getErrors();
|
||||
return $this->failValidationErrors($errors);
|
||||
}
|
||||
}
|
||||
|
||||
$data = [
|
||||
'agent' => $arg['agent'],
|
||||
'username' => auth()->user()->username,
|
||||
'homepage_url' => $arg['homepage_url'],
|
||||
'interlock_url' => $arg['interlock_url'],
|
||||
'agreement_url' => $arg['agreement_url'],
|
||||
'account_balance' => $arg['account_balance'],
|
||||
'is_stop' => $arg['is_stop'],
|
||||
];
|
||||
if(!empty($arg['company_id'])) {
|
||||
$data['company_seq'] = $arg['company_id'];
|
||||
}
|
||||
if(isset($arg['name'])) $data['name'] = $arg['name'];
|
||||
$data['ea_datetime'] = date('Y-m-d H:i:s');
|
||||
$result = $this->advertiser->updateAdv($data, $arg['seq']);
|
||||
|
||||
// OVERWATCH
|
||||
$db = \Config\Database::connect();
|
||||
$builder = $db->table('event_overwatch');
|
||||
$ow = $this->advertiser->getOverwatchByAdvertiser($arg['seq']);
|
||||
$contact = implode(';',$arg['contact']);
|
||||
// INSERT / UPDATE / DELETE
|
||||
if($arg['sms_alert'] && !$ow){
|
||||
$overwatch = [
|
||||
'advertiser' => $arg['seq'],
|
||||
'contact' => $contact,
|
||||
'watch_list' => $arg['watch_list'],
|
||||
'username' => auth()->user()->username
|
||||
];
|
||||
$overwatch['eo_datetime'] = date('Y-m-d H:i:s');
|
||||
$builder->insert($overwatch);
|
||||
}else if($arg['sms_alert'] && $ow){
|
||||
$builder->set('contact', $contact);
|
||||
$builder->set('watch_list', $arg['watch_list']);
|
||||
$builder->set('watch_all', $arg['watch_all']);
|
||||
$builder->where('seq', $ow['seq']);
|
||||
$builder->update();
|
||||
}else if(!$arg['sms_alert'] && $ow){
|
||||
$builder->where('seq', $ow['seq']);
|
||||
$builder->delete();
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function evtOverwatch(){
|
||||
$result = $this->advertiser->evtOverwatch();
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\EventManage;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\EventManage\BlackListModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
use DateTime;
|
||||
|
||||
class BlackListController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $blacklist;
|
||||
public function __construct()
|
||||
{
|
||||
$this->blacklist = model(BlackListModel::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('/events/blacklist/blacklist');
|
||||
}
|
||||
|
||||
public function getList()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
$result = $this->blacklist->getBlackLists($arg);
|
||||
$list = $result['data'];
|
||||
|
||||
$result = [
|
||||
'data' => $list,
|
||||
'recordsTotal' => $result['allCount'],
|
||||
'recordsFiltered' => $result['allCount'],
|
||||
'draw' => intval($arg['draw']),
|
||||
];
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlackList()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$data = $this->request->getGet();
|
||||
$result = $this->blacklist->getBlacklist($data['seq']);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function createBlackList()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post'){
|
||||
$arg = $this->request->getRawInput();
|
||||
|
||||
//유효성 검사 start
|
||||
$validation = \Config\Services::validation();
|
||||
$validationRules = [
|
||||
'data' => 'required|is_unique[event_blacklist.data]',
|
||||
];
|
||||
$validationMessages = [
|
||||
'data' => [
|
||||
'required' => '전화번호/아이피를 입력해주세요.',
|
||||
'is_unique' => '이미 존재하는 전화번호/아이피입니다.'
|
||||
],
|
||||
];
|
||||
$validation->setRules($validationRules, $validationMessages);
|
||||
if (!$validation->run($arg)) {
|
||||
$errors = $validation->getErrors();
|
||||
return $this->failValidationErrors($errors);
|
||||
}
|
||||
//유효성 검사 end
|
||||
|
||||
$data = [
|
||||
'data' => preg_replace("/[^0-9.]/", "", $arg['data']),
|
||||
'memo' => $arg['memo'],
|
||||
];
|
||||
|
||||
$result = $this->blacklist->createBlackList($data);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteBlackList()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'delete'){
|
||||
$data = $this->request->getRawInput();
|
||||
$result = $this->blacklist->deleteBlackList($data['seq']);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\EventManage;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\EventManage\ChangeModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class ChangeController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $change;
|
||||
public function __construct()
|
||||
{
|
||||
$this->change = model(ChangeModel::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('/events/change/change');
|
||||
}
|
||||
|
||||
public function getList()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
$result = $this->change->getChanges($arg);
|
||||
$list = $result['data'];
|
||||
|
||||
$result = [
|
||||
'data' => $list,
|
||||
'recordsTotal' => $result['allCount'],
|
||||
'recordsFiltered' => $result['allCount'],
|
||||
'draw' => intval($arg['draw']),
|
||||
];
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getChange()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
$result = $this->change->getChange($arg['id']);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function createChange()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post'){
|
||||
$arg = $this->request->getRawInput();
|
||||
$data = [
|
||||
'id' => $arg['id'],
|
||||
'name' => $arg['name'],
|
||||
'token' => $arg['token'],
|
||||
];
|
||||
$data['ec_datetime'] = date('Y-m-d H:i:s');
|
||||
$validation = \Config\Services::validation();
|
||||
$validationRules = [
|
||||
'id' => 'required|is_unique[event_conversion.id]',
|
||||
'token' => 'required'
|
||||
];
|
||||
$validationMessages = [
|
||||
'id' => [
|
||||
'required' => '전환ID는 필수 입력 사항입니다.',
|
||||
'is_unique' => '이미 등록된 아이디입니다.'
|
||||
],
|
||||
'token' => [
|
||||
'required' => 'Access Token은 필수 입력 사항입니다.',
|
||||
],
|
||||
];
|
||||
$validation->setRules($validationRules, $validationMessages);
|
||||
if (!$validation->run($data)) {
|
||||
$errors = $validation->getErrors();
|
||||
return $this->failValidationErrors($errors);
|
||||
}
|
||||
|
||||
$result = $this->change->createChange($data);
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function updateChange()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'put'){
|
||||
$arg = $this->request->getRawInput();
|
||||
$data = [
|
||||
'old_id' => $arg['old_id'],
|
||||
'id' => $arg['id'],
|
||||
'name' => $arg['name'],
|
||||
'token' => $arg['token'],
|
||||
];
|
||||
$data['ec_datetime'] = date('Y-m-d H:i:s');
|
||||
$validation = \Config\Services::validation();
|
||||
$validationRules = [
|
||||
'id' => 'required',
|
||||
'token' => 'required'
|
||||
];
|
||||
if($data['old_id'] != $data['id']){
|
||||
$validationRules['id'] = 'required|is_unique[event_conversion.id]';
|
||||
}
|
||||
$validationMessages = [
|
||||
'id' => [
|
||||
'required' => '전환ID는 필수 입력 사항입니다.',
|
||||
'is_unique' => '이미 등록된 아이디입니다.'
|
||||
],
|
||||
'token' => [
|
||||
'required' => 'Access Token은 필수 입력 사항입니다.',
|
||||
],
|
||||
];
|
||||
$validation->setRules($validationRules, $validationMessages);
|
||||
if (!$validation->run($data)) {
|
||||
$errors = $validation->getErrors();
|
||||
return $this->failValidationErrors($errors);
|
||||
}
|
||||
|
||||
$result = $this->change->updateChange($data);
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\EventManage;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\EventManage\AdvertiserModel;
|
||||
use App\Models\EventManage\EventModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class EventController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $event, $advertiser;
|
||||
public function __construct()
|
||||
{
|
||||
$this->event = model(EventModel::class);
|
||||
$this->advertiser = model(AdvertiserModel::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('events/event/event');
|
||||
}
|
||||
|
||||
public function getList()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
$result = $this->event->getInformation($arg);
|
||||
$ads = $this->event->getEnabledAds();
|
||||
if(empty($ads)){$ads = [];}
|
||||
foreach ($result['data'] as &$data) {
|
||||
if($data['is_stop']){
|
||||
$data['is_stop'] = 'X';
|
||||
}else{
|
||||
$data['is_stop'] = 'O';
|
||||
}
|
||||
|
||||
if($data['interlock']){
|
||||
$data['interlock'] = 'O';
|
||||
}else{
|
||||
$data['interlock'] = '';
|
||||
}
|
||||
|
||||
if($data['lead']){
|
||||
$lead_array = array("0" => $data['title'], "1" => "잠재고객", "2" => "엑셀업로드", "3" => "API 수신", "4" => "카카오 비즈폼");
|
||||
$data['title'] = $lead_array[$data['lead']];
|
||||
if($data['lead'] == 3)
|
||||
$data['title'] .= "<p class='desc'>[{$data['partner_event_seq']}]</p>";
|
||||
}
|
||||
|
||||
if(preg_match('/(카카오|GDN|페이스북|잠재|유튜브)/', $data['media_name'])) {
|
||||
$is_enabledAds = false;
|
||||
$data['config'] = 'disabled';
|
||||
if(in_array($data['seq'], $ads)){
|
||||
$is_enabledAds = true;
|
||||
}
|
||||
if($is_enabledAds) {
|
||||
$data['config'] = 'enabled';
|
||||
}
|
||||
}
|
||||
|
||||
if(!$data['impressions']){
|
||||
$data['impressions'] = 0;
|
||||
}
|
||||
|
||||
$data['hash_no'] = $this->makeHash($data['seq']);
|
||||
$url = env('app.eventURL');
|
||||
if($data['another_url'])
|
||||
$url = env('app.newEventURL');
|
||||
$data['event_url'] = $url.$data['hash_no'];
|
||||
$data['db_price'] = number_format($data['db_price']);
|
||||
}
|
||||
|
||||
$result = [
|
||||
'data' => $result['data'],
|
||||
'recordsTotal' => $result['allCount'],
|
||||
'recordsFiltered' => $result['allCount'],
|
||||
'draw' => intval($arg['draw']),
|
||||
];
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getAdv()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
$result = $this->event->getAdv($arg['stx']);
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getMedia()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
$result = $this->event->getMedia($arg['stx']);
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function createEvent()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post'){
|
||||
$arg = $this->request->getRawInput();
|
||||
$data = $this->setArg($arg);
|
||||
|
||||
$data['advertiser'] = $arg['advertiser'];
|
||||
$data['keyword'] = $arg['keyword'];
|
||||
$data['ei_datetime'] = date('Y-m-d H:i:s');
|
||||
$validation = \Config\Services::validation();
|
||||
$validationRules = [
|
||||
'advertiser' => 'required',
|
||||
'media' => 'required',
|
||||
];
|
||||
$validationMessages = [
|
||||
'advertiser' => [
|
||||
'required' => '광고주가 입력되지 않았습니다.',
|
||||
],
|
||||
'media' => [
|
||||
'required' => '매체가 입력되지 않았습니다.',
|
||||
],
|
||||
];
|
||||
$validation->setRules($validationRules, $validationMessages);
|
||||
if (!$validation->run($data)) {
|
||||
$errors = $validation->getErrors();
|
||||
return $this->failValidationErrors($errors);
|
||||
}
|
||||
|
||||
$adData = [
|
||||
'seq' => $arg['advertiser']
|
||||
];
|
||||
$advertiser = $this->advertiser->getAdvertiser($adData);
|
||||
if(empty($advertiser['company_seq']) || $advertiser['company_seq'] == 0){
|
||||
$error = ['advertiser' => '소속이 지정되지 않은 광고주입니다.'];
|
||||
return $this->failValidationErrors($error);
|
||||
}
|
||||
|
||||
$result = $this->event->createEvent($data);
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function updateEvent()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'put'){
|
||||
$arg = $this->request->getRawInput();
|
||||
$data = $this->setArg($arg);
|
||||
$data['keyword'] = $arg['keyword'];
|
||||
$data['ei_updatetime'] = date('Y-m-d H:i:s');
|
||||
|
||||
$validation = \Config\Services::validation();
|
||||
$validationRules = [
|
||||
'media' => 'required',
|
||||
];
|
||||
$validationMessages = [
|
||||
'media' => [
|
||||
'required' => '매체가 입력되지 않았습니다.',
|
||||
],
|
||||
];
|
||||
$validation->setRules($validationRules, $validationMessages);
|
||||
if (!$validation->run($data)) {
|
||||
$errors = $validation->getErrors();
|
||||
return $this->failValidationErrors($errors);
|
||||
}
|
||||
|
||||
$result = $this->event->updateEvent($data, $arg['seq']);
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function copyEvent()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post'){
|
||||
$data = $this->request->getRawInput();
|
||||
if(empty($data['seq'])){
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
$result = $this->event->copyEvent($data['seq']);
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteEvent()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'delete'){
|
||||
$data = $this->request->getRawInput();
|
||||
if(empty($data['seq'])){
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
$url = "https://event.hotblood.co.kr/filecheck/".$data['seq'];
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if (!$response) {
|
||||
$result = $this->event->deleteEvent($data['seq']);
|
||||
return $this->respond($result);
|
||||
} else {
|
||||
$result = $this->event->deleteEvent($data['seq']);
|
||||
return $this->respond($result);
|
||||
return $this->fail("삭제할 수 없는 이벤트입니다.");
|
||||
}
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getEvent()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$seq = $this->request->getGet('seq');
|
||||
$result = $this->event->getEvent($seq);
|
||||
$result['keywords'] = explode(',', $result['keywords']);
|
||||
$result['hash_no'] = $this->makeHash($result['seq']);
|
||||
$url = env('app.eventURL');
|
||||
if($result['another_url'])
|
||||
$url = env('app.newEventURL');
|
||||
$result['event_url'] = $url.$result['hash_no'];
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getEventImpressions()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$seq = $this->request->getGet('seq');
|
||||
$result = $this->event->getEventImpressions($seq);
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
private function setArg($arg){
|
||||
$data = [
|
||||
'media' => $arg['media'],
|
||||
'description' => $arg['description'],
|
||||
'db_price' => (integer)$arg['db_price'] ?? 0,
|
||||
'interlock' => (integer)$arg['interlock'] ?? 0,
|
||||
'partner_id' => $arg['partner_id'],
|
||||
'partner_name' => $arg['partner_name'],
|
||||
'paper_code' => $arg['paper_code'],
|
||||
'paper_name' => $arg['paper_name'],
|
||||
'lead' => (integer)$arg['lead'],
|
||||
'creative_id' => (integer)$arg['creative_id'] ?? 0,
|
||||
'bizform_apikey' => $arg['bizform_apikey'],
|
||||
'is_stop' => (integer)$arg['is_stop'] ?? 0,
|
||||
'custom' => $arg['custom'],
|
||||
'title' => $arg['title'],
|
||||
'subtitle' => $arg['subtitle'],
|
||||
'object' => $arg['object'],
|
||||
'object_items' => $arg['object_items'],
|
||||
'pixel_id' => trim($arg['pixel_id']),
|
||||
'view_script' => $arg['view_script'],
|
||||
'done_script' => $arg['done_script'],
|
||||
'check_gender' => $arg['check_gender'],
|
||||
'check_age_min' => (integer)$arg['check_age_min'] ?? 0,
|
||||
'check_age_max' => (integer)$arg['check_age_max'] ?? 0,
|
||||
'duplicate_term' => (integer)$arg['duplicate_term'] ?? 0,
|
||||
'check_phone' => $arg['check_phone'],
|
||||
'check_name' => $arg['check_name'],
|
||||
'duplicate_precheck' => (integer)$arg['duplicate_precheck'] ?? 0,
|
||||
'no_hash' => isset($arg['no_hash']) ? (integer)$arg['no_hash'] : 0,
|
||||
'another_url' => isset($arg['another_url']) ? (integer)$arg['another_url'] : 0,
|
||||
'username' => auth()->user()->nickname ?? '',
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function makeHash($uid) {
|
||||
$ab = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
$s_id = str_split($uid);
|
||||
$make_hash = [0,0];
|
||||
for($i=0; $i<count($s_id); $i++) $make_hash[0] += $s_id[$i]*($i+$s_id[count($s_id)-1]);
|
||||
for($i=0; $i<count($s_id); $i++) $make_hash[1] += $s_id[$i]*($i+$s_id[0]);
|
||||
$make_hash = array_map(function($v) use($ab){$chksum = ($v % 26); return $ab[$chksum];}, $make_hash);
|
||||
$hash = implode("", $make_hash);
|
||||
$result = $hash.$uid;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\EventManage;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\EventManage\ExcelModel;
|
||||
use Config\Services;
|
||||
|
||||
class ExcelController extends BaseController
|
||||
{
|
||||
protected $excel;
|
||||
public function __construct()
|
||||
{
|
||||
$this->excel = model(ExcelModel::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('events/excelUpload/excel', [
|
||||
'validation' => Services::validation(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function upload()
|
||||
{
|
||||
if(strtolower($this->request->getMethod()) === 'post'){
|
||||
$validated = $this->validate([
|
||||
'upload_file' => [
|
||||
'uploaded[upload_file]',
|
||||
'ext_in[upload_file,csv]',
|
||||
'max_size[upload_file, 4096]',
|
||||
],
|
||||
],
|
||||
[
|
||||
'upload_file' => [
|
||||
'uploaded' => '업로드 오류가 발생하였습니다.',
|
||||
'ext_in' => 'csv 파일만 업로드 가능합니다.',
|
||||
'max_size' => '파일 크기는 4MB를 초과할 수 없습니다.'
|
||||
]
|
||||
|
||||
]);
|
||||
|
||||
if (!$validated) {
|
||||
return view('events/excelUpload/excel', [
|
||||
'validation' => $this->validator
|
||||
]);
|
||||
}
|
||||
|
||||
$file = $this->request->getFile('upload_file');
|
||||
$filePath = $file->getPathname();
|
||||
$row = 1; //줄수 초기화
|
||||
$idx = 0; //배열 인덱스
|
||||
$fp = fopen($filePath, "r");
|
||||
while (($data = fgetcsv($fp, 1000, ",")) !== false) { //csv파일열기
|
||||
if ($row == 1) {
|
||||
$row += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
$excel[$idx]['reg_date'] = iconv("EUC-KR", "UTF-8", $data[1]);
|
||||
$excel[$idx]['name'] = preg_replace("/[#\&\+%@=\/\\\:;,\.'\"\^`~\_|\!\?\*$#<>\[\]\{\}]/i", "", iconv("EUC-KR", "UTF-8", $data[2]));
|
||||
$excel[$idx]['phone'] = strtr(iconv("EUC-KR", "UTF-8", $data[3]), array("+82 " => "0", "-" => "")); // 전화번호에서 국제번호 및 하이픈 제거
|
||||
$excel[$idx]['add1'] = iconv("EUC-KR", "UTF-8", $data[4]); //나이 또는 생년월일
|
||||
$excel[$idx]['add2'] = iconv("EUC-KR", "UTF-8", $data[5]);
|
||||
$excel[$idx]['add3'] = iconv("EUC-KR", "UTF-8", $data[6]);
|
||||
$excel[$idx]['add4'] = iconv("EUC-KR", "UTF-8", $data[7]);
|
||||
$excel[$idx]['add5'] = iconv("EUC-KR", "UTF-8", $data[8]);
|
||||
$excel[$idx]['branch'] = iconv("EUC-KR", "UTF-8", $data[9]);
|
||||
$excel[$idx]['age'] = iconv("EUC-KR", "UTF-8", $data[10]);
|
||||
$excel[$idx]['partner_name'] = iconv("EUC-KR", "UTF-8", $data[11]); //파트너명
|
||||
$excel[$idx]['partner_id'] = iconv("EUC-KR", "UTF-8", $data[12]); //파트너아이디
|
||||
$excel[$idx]['hospital_name'] = iconv("EUC-KR", "UTF-8", $data[13]); //코드명
|
||||
$excel[$idx]['counsel_memo'] = iconv("EUC-KR", "UTF-8", $data[14]); //지면명
|
||||
$excel[$idx]['paper_code'] = iconv("EUC-KR", "UTF-8", $data[13]); //코드명
|
||||
$excel[$idx]['paper_name'] = iconv("EUC-KR", "UTF-8", $data[14]); //지면명
|
||||
$excel[$idx]['event_seq'] = iconv("EUC-KR", "UTF-8", $data[15]); //랜딩번호
|
||||
$excel[$idx]['site'] = iconv("EUC-KR", "UTF-8", $data[16]); //사이트
|
||||
|
||||
if ($excel[$idx]['name'] && $excel[$idx]['phone']) {
|
||||
$status_check = $this->excel->status_check($excel[$idx]['name'], $excel[$idx]['phone'], $excel[$idx]['event_seq']);
|
||||
$excel[$idx]['status'] = $status_check['status'];
|
||||
$excel[$idx]['status_memo'] = $status_check['status_memo'];
|
||||
}
|
||||
|
||||
$idx++;
|
||||
}
|
||||
session()->setFlashdata('success', 'Success! image uploaded.');
|
||||
return redirect()->to(site_url('/events/exelUpload/exel'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\EventManage;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\EventManage\MediaModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class MediaController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $media;
|
||||
public function __construct()
|
||||
{
|
||||
$this->media = model(MediaModel::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('/events/media/media');
|
||||
}
|
||||
|
||||
public function getList()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
$result = $this->media->getMedias($arg);
|
||||
$list = $result['data'];
|
||||
|
||||
$result = [
|
||||
'data' => $list,
|
||||
'recordsTotal' => $result['allCount'],
|
||||
'recordsFiltered' => $result['allCount'],
|
||||
'draw' => intval($arg['draw']),
|
||||
];
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getMedia()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
$result = $this->media->getMedia($arg);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function createMedia()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post'){
|
||||
$arg = $this->request->getRawInput();
|
||||
$data = [
|
||||
'media' => $arg['media'],
|
||||
'target' => $arg['target'],
|
||||
];
|
||||
|
||||
$validation = \Config\Services::validation();
|
||||
$validationRules = [
|
||||
'media' => 'required|is_unique[event_media.media]',
|
||||
];
|
||||
$validationMessages = [
|
||||
'media' => [
|
||||
'required' => '매체명은 필수 입력 사항입니다.',
|
||||
'is_unique' => '이미 등록된 매체입니다.'
|
||||
],
|
||||
];
|
||||
$validation->setRules($validationRules, $validationMessages);
|
||||
if (!$validation->run($data)) {
|
||||
$errors = $validation->getErrors();
|
||||
return $this->failValidationErrors($errors);
|
||||
}
|
||||
|
||||
$result = $this->media->createMedia($data);
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function updateMedia()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'put'){
|
||||
$arg = $this->request->getRawInput();
|
||||
$data = [
|
||||
'media' => $arg['media'],
|
||||
'target' => $arg['target'],
|
||||
];
|
||||
|
||||
$validation = \Config\Services::validation();
|
||||
$validationRules = [
|
||||
'media' => 'required',
|
||||
];
|
||||
$validationMessages = [
|
||||
'media' => [
|
||||
'required' => '매체명은 필수 입력 사항입니다.',
|
||||
],
|
||||
];
|
||||
$validation->setRules($validationRules, $validationMessages);
|
||||
if (!$validation->run($data)) {
|
||||
$errors = $validation->getErrors();
|
||||
return $this->failValidationErrors($errors);
|
||||
}
|
||||
|
||||
$result = $this->media->updateMedia($data, $arg['seq']);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
|
||||
class ExampleController extends BaseController
|
||||
{
|
||||
public function view($page = 'test')
|
||||
{
|
||||
if(!is_file(APPPATH . 'Views/example/' . $page . '.php')) {
|
||||
throw new \CodeIgniter\Exceptions\PageNotFoundException($page);
|
||||
}
|
||||
|
||||
return view('example/'.$page);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
|
||||
class GuestController extends BaseController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('guest/guest');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Controllers\AdvertisementManager\AdvFacebookManagerController;
|
||||
use App\Controllers\AdvertisementManager\AdvGoogleManagerController;
|
||||
use App\Controllers\AdvertisementManager\AdvKakaoManagerController;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
|
||||
class HomeController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
public function index()
|
||||
{
|
||||
$data = [];
|
||||
$data['password_check'] = false;
|
||||
$password_check = auth()->user()->getEmailIdentity()->password_changed_at;
|
||||
|
||||
if(!empty($password_check) && (strtotime($password_check) < strtotime('-90 days'))){
|
||||
$data['password_check'] = true;
|
||||
}
|
||||
|
||||
return view('pages/home', $data);
|
||||
}
|
||||
|
||||
public function getReports()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$facebookDB = \Config\Database::connect('facebook');
|
||||
$googleDB = \Config\Database::connect('google');
|
||||
$kakaoDB = \Config\Database::connect('kakao');
|
||||
|
||||
$result = [];
|
||||
$facebook = new AdvFacebookManagerController;
|
||||
$result['facebookReport'] = $facebook->getReport();
|
||||
|
||||
$google = new AdvGoogleManagerController;
|
||||
$result['googleReport'] = $google->getReport();
|
||||
|
||||
$kakao = new AdvKakaoManagerController;
|
||||
$result['kakaoReport'] = $kakao->getReport();
|
||||
|
||||
return $this->respond($result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\HumanResource;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\HumanResource\HumanResourceModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
use App\Libraries\Douzone\Douzone;
|
||||
use App\Libraries\Douzone\DouzoneModel;
|
||||
|
||||
class HumanResourceController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $hr;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->hr = model(HumanResourceModel::class);
|
||||
}
|
||||
|
||||
public function humanResource()
|
||||
{
|
||||
return view('humanResource/humanresource');
|
||||
}
|
||||
|
||||
private function getDayOff()
|
||||
{ //연차
|
||||
$douzone = new Douzone();
|
||||
$list = $douzone->getDayOff();
|
||||
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function getMemberList()
|
||||
{
|
||||
$lists = $this->hr->getMemberList();
|
||||
foreach($lists as $row) $data[] = [$row['nickname'],$row['division'],$row['secret']];
|
||||
foreach ($lists as $row) $data[] = [$row['nickname'], $row['division'], $row['secret']];
|
||||
dd($data);
|
||||
return $lists;
|
||||
}
|
||||
|
||||
public function updateUsersByDouzone()
|
||||
{
|
||||
$douzone = new Douzone();
|
||||
$list = $douzone->getMemberList();
|
||||
$total = count($list);
|
||||
if (!$total) return null;
|
||||
if (!$total) return null;
|
||||
$i = 1;
|
||||
foreach ($list as $row) {
|
||||
foreach ($list as $row) {
|
||||
$result = $this->hr->updateUserByEmail($row);
|
||||
if ($result) $i++;
|
||||
if ($result) $i++;
|
||||
}
|
||||
if ($result == $i) return true;
|
||||
if ($result == $i) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function getHourTicketUse()
|
||||
{
|
||||
$hourticket = $this->hr->getHourTicketUse();
|
||||
|
||||
return $hourticket;
|
||||
}
|
||||
|
||||
public function getTodayDayOff($date = null)
|
||||
{
|
||||
$date = $date ? date('Y-m-d', strtotime($date)) : date('Y-m-d');
|
||||
$list = $this->getDayOff();
|
||||
$data = [];
|
||||
foreach ($list as $row) {
|
||||
if (isset($row['start']) && date('Y-m-d', strtotime($row['start'])) >= $date) {
|
||||
$data['day'][] = $row;
|
||||
}
|
||||
}
|
||||
$list = $this->getHourTicketUse($date);
|
||||
foreach ($list as $row) {
|
||||
if (isset($row['date']) && date('Y-m-d', strtotime($row['date'])) >= $date) {
|
||||
$data['hour'][] = $row;
|
||||
}
|
||||
}
|
||||
$result = $this->setMessageData($data);
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function gwData(){
|
||||
$result = $this->hr->gwData();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getGwData(){
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post') {
|
||||
$input = $this->request->getBody();
|
||||
$data = json_decode($input, true);
|
||||
$result = $this->hr->getGwData($data);
|
||||
|
||||
return json_encode($result);
|
||||
} else {
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function issueProc()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post') {
|
||||
$data = $this->request->getRawInput();
|
||||
$result = $this->hr->issueProc($data);
|
||||
|
||||
return json_encode($result);
|
||||
} else {
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function hourTicketConfirm()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post') {
|
||||
$input = $this->request->getBody();
|
||||
$data = json_decode($input, true);
|
||||
$result = $this->hr->hourTicketConfirm($data);
|
||||
|
||||
return json_encode($result);
|
||||
} else {
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function hourTicketReg()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post') {
|
||||
$input = $this->request->getBody();
|
||||
$data = json_decode($input, true);
|
||||
$result = $this->hr->HourTicketReg($data);
|
||||
|
||||
return json_encode($result);
|
||||
} else {
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getHourTicketAll()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post') {
|
||||
$input = $this->request->getBody();
|
||||
$data = json_decode($input, true);
|
||||
$result = $this->hr->getHourTicketAll($data);
|
||||
|
||||
return json_encode($result);
|
||||
} else {
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getHourTicketIssue()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post') {
|
||||
$input = $this->request->getBody();
|
||||
$data = json_decode($input, true);
|
||||
$result = $this->hr->getHourTicketIssue($data);
|
||||
|
||||
return json_encode($result);
|
||||
} else {
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getHourTicketUseNew()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post') {
|
||||
$input = $this->request->getBody();
|
||||
$data = json_decode($input, true);
|
||||
$result = $this->hr->getHourTicketUseNew($data);
|
||||
|
||||
return json_encode($result);
|
||||
} else {
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function setMessageData($lists)
|
||||
{
|
||||
$data = [];
|
||||
foreach ($lists as $type => $list) {
|
||||
foreach ($list as $row) {
|
||||
$user = $this->hr->getUserByEmail($row['email']);
|
||||
if (empty($user)) continue;
|
||||
$type = isset($row['type']) ? $row['type'] : '시차';
|
||||
$start = isset($row['start']) ? date('Y-m-d', strtotime($row['start'])) : date('Y-m-d H:m', strtotime($row['date'] . " " . $row['time']));
|
||||
$end = isset($row['end']) ? date('Y-m-d', strtotime($row['end'])) : date('Y-m-d H:m', strtotime($row['date'] . " " . $row['time'] . " +{$row['hour_ticket']} hours"));
|
||||
$term = isset($row['used']) ? $row['used'] : $row['hour_ticket'];
|
||||
$total_remain = isset($row['total']['remain']) ? $row['total']['remain'] : $row['remain'];
|
||||
$total_used = isset($row['total']['used']) ? $row['total']['used'] : '';
|
||||
$datetime = isset($row['reg_datetime']) ? $row['reg_datetime'] : $row['rep_dt'];
|
||||
$data[] = [
|
||||
'type' => $type,
|
||||
'name' => $user['nickname'],
|
||||
'division' => $user['division'],
|
||||
'team' => $user['team'],
|
||||
'position' => $user['position'],
|
||||
'term' => $term,
|
||||
'total_used' => $total_used,
|
||||
'total_remain' => $total_remain,
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'datetime' => $datetime
|
||||
];
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,593 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Integrate;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\Integrate\IntegrateModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
use Mpdf\Mpdf;
|
||||
class IntegrateController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $integrate;
|
||||
protected $is_pravate_perm = false;
|
||||
private $leads_status = [
|
||||
0 => "미확인", 1 => "인정", 2 => "중복", 3 => "성별불량", 4 => "나이불량", 5 => "콜불량", 6 => "번호불량", 7 => "테스트",
|
||||
8 => "이름불량", 9 => "지역불량", 10 => "업체불량", 11 => "미성년자", 12 => "본인아님", 13 => "쿠키중복", 99 => "확인"
|
||||
];
|
||||
public function __construct()
|
||||
{
|
||||
$this->integrate = model(IntegrateModel::class);
|
||||
if(auth()->user()->inGroup('superadmin','admin','developer', 'agency', 'advertiser')) {
|
||||
$this->is_pravate_perm = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$_get = $this->request->getGet();
|
||||
return view('integrate/DBintegrated', $_get);
|
||||
}
|
||||
public function download()
|
||||
{
|
||||
$_get = $this->request->getGet();
|
||||
return view('integrate/DBdownload', $_get);
|
||||
}
|
||||
|
||||
public function getList()
|
||||
{
|
||||
if ($this->request->isAJAX()) {
|
||||
$date = $this->request->getPost('date') ?? ['sdate' => date('Y-m-d'), 'edate' => date('Y-m-d')];
|
||||
$sdate = (new \DateTime($date['sdate']))->format('Y-m-d') . ' 00:00:00';
|
||||
$edate = (new \DateTime($date['edate']))->format('Y-m-d') . ' 23:59:59';
|
||||
|
||||
//list
|
||||
$list = $this->integrate->getEventLead(['sdate' => $sdate, 'edate' => $edate]);
|
||||
foreach($list['data'] as &$d){
|
||||
// Trim all data
|
||||
$d = array_map('trim', $d);
|
||||
$d['hash_no'] = makeHash($d['info_seq']);
|
||||
$event_url = env('app.eventURL');
|
||||
if($d['another_url'])
|
||||
$event_url = env('app.newEventURL');
|
||||
$d['event_url'] = $event_url.$d['hash_no'];
|
||||
$etc = [];
|
||||
if(!empty($d['email'])) {
|
||||
$etc[] = $d['email'];
|
||||
}
|
||||
$d['dec_phone'] = preg_replace("/([0-9]{3})([0-9]{4})([0-9]{4})/", "$1-$2-$3", $d['dec_phone']);
|
||||
$d['age'] = $d['age'] == 0 ? '' : $d['age'];
|
||||
if(!$this->is_pravate_perm) {
|
||||
if(!preg_match('/test|테스트/i', $d['name']) && $d['status'] != 7) {
|
||||
$d['dec_phone'] = substr($d['dec_phone'],0,3).'<i class="masking">▒▒</i>'.substr($d['dec_phone'],-4);
|
||||
$d['dec_phone'] = html_entity_decode($d['dec_phone']);
|
||||
$name = trim($d['name']);
|
||||
$d['name'] = '';
|
||||
for($ii=0; $ii<mb_strlen($name); $ii++) {
|
||||
if(mb_strlen($name) >= 4 && $ii > 2 && mb_strlen($name)-1 != $ii)
|
||||
continue;
|
||||
else
|
||||
$d['name'] .= (($ii>0&&$ii<mb_strlen($name)-1)||$ii==1)?'<i class="masking">▒</i>':mb_substr($name, $ii, 1);
|
||||
$d['name'] = html_entity_decode($d['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
for($i2=1;$i2<7;$i2++){
|
||||
if(!empty($d['add'.$i2])){
|
||||
if(strpos($d['add'.$i2], "uploads")){
|
||||
$href = "<a href='".str_replace("./","{$event_url}uploads/",$d['add'.$i2])."' target='_blank'>[파일보기]</a>";
|
||||
$etc[] = $href;
|
||||
}else if(strpos($d['add'.$i2], "/v_")){
|
||||
$href = "<a href='{$event_url}img_viewer.php?data={$d['add'.$i2]}' target='_blank'>[파일보기]</a>";
|
||||
$etc[] = $href;
|
||||
}
|
||||
else{
|
||||
$etc[] = $d['add'.$i2];
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!empty($d['memo'])){
|
||||
$etc[] = $d['memo'];
|
||||
}
|
||||
if(!empty($d['addr'])){
|
||||
$etc[] = $d['addr'];
|
||||
}
|
||||
if(!empty($d['branch'])){
|
||||
$etc[] = $d['branch'];
|
||||
}
|
||||
$add = implode('/', $etc);
|
||||
$d['add'][] = $add;
|
||||
}
|
||||
|
||||
$result = $list;
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
private function getColumns()
|
||||
{
|
||||
$columns = [
|
||||
'event_seq' => '이벤트', 'site' => '사이트',
|
||||
'name' => '이름', 'phone' => '연락처',
|
||||
'age' => '나이', 'gender' => '성별', 'branch' => '지점', 'addr' => '주소',
|
||||
'email' => 'Email', 'add1' => '설문1', 'add2' => '설문2', 'add3' => '설문3',
|
||||
'add4' => '설문4', 'add5' => '설문5', 'add6' => '설문6', 'status' => '상태',
|
||||
'memos' => '메모', 'ip' => 'IP', 'reg_date' => '등록일시'
|
||||
];
|
||||
if(auth()->user()->hasPermission('integrate.description')
|
||||
|| auth()->user()->inGroup('superadmin', 'admin', 'developer', 'user')){
|
||||
$columns = array_merge(
|
||||
array_slice($columns, 0, 2, true),
|
||||
['description' => '구분'],
|
||||
array_slice($columns, 2, null, true)
|
||||
);
|
||||
}
|
||||
if(auth()->user()->hasPermission('integrate.media')
|
||||
|| auth()->user()->inGroup('superadmin', 'admin', 'developer', 'user')){
|
||||
$columns = array_merge(
|
||||
array_slice($columns, 0, 2, true),
|
||||
['media' => '매체'],
|
||||
array_slice($columns, 2, null, true)
|
||||
);
|
||||
}
|
||||
if(auth()->user()->hasPermission('integrate.advertiser')
|
||||
|| auth()->user()->inGroup('superadmin', 'admin', 'developer', 'user')){
|
||||
$columns = array_merge(
|
||||
array_slice($columns, 0, 2, true),
|
||||
['advertiser' => '광고주'],
|
||||
array_slice($columns, 2, null, true)
|
||||
);
|
||||
}
|
||||
|
||||
if (getenv('MY_SERVER_NAME') === 'resta' && auth()->user()->inGroup('superadmin', 'admin', 'developer', 'user')) {
|
||||
$columns = array_merge(['company' => '회사명'], $columns);
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
private function transformData($data, $columns)
|
||||
{
|
||||
$transformedData = [];
|
||||
foreach ($data as $row) {
|
||||
$transformedRow = [];
|
||||
$isTestOrStatus7 = preg_match('/test|테스트/i', $row['name']) || $row['status'] == 7;
|
||||
|
||||
foreach ($columns as $key => $header) {
|
||||
$value = $row[$key];
|
||||
if ($key === 'phone') {
|
||||
if (!$this->is_pravate_perm && !$isTestOrStatus7) {
|
||||
$value = substr($value, 0, 3) . '▒▒' . substr($value, -4);
|
||||
$value = html_entity_decode($value);
|
||||
} else {
|
||||
$value = preg_replace("/([0-9]{3})([0-9]{4})([0-9]{4})/", "$1-$2-$3", $value);
|
||||
}
|
||||
} elseif ($key === 'status') {
|
||||
$value = $this->leads_status[$row[$key]];
|
||||
} elseif ($key === 'age') {
|
||||
$value = $value == 0 ? "" : $value;
|
||||
} elseif ($key === 'name' && !$this->is_pravate_perm && !$isTestOrStatus7) {
|
||||
$name = trim($value);
|
||||
$value = '';
|
||||
for ($ii = 0; $ii < mb_strlen($name); $ii++) {
|
||||
if (mb_strlen($name) >= 4 && $ii > 2 && mb_strlen($name) - 1 != $ii) {
|
||||
continue;
|
||||
} else {
|
||||
$value .= (($ii > 0 && $ii < mb_strlen($name) - 1) || $ii == 1) ? '▒' : mb_substr($name, $ii, 1);
|
||||
$value = html_entity_decode($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
$transformedRow[$key] = $value;
|
||||
}
|
||||
$transformedData[] = $transformedRow;
|
||||
}
|
||||
return $transformedData;
|
||||
}
|
||||
|
||||
public function downloadData()
|
||||
{
|
||||
$sdate = $this->request->getPost('sdate');
|
||||
$edate = $this->request->getPost('edate');
|
||||
$advertiser = $this->request->getPost('advertiser');
|
||||
$media = $this->request->getPost('media');
|
||||
$description = $this->request->getPost('description');
|
||||
$message = $this->request->getPost('message');
|
||||
$fileFormat = $this->request->getPost('file_format'); // 파일 형식 추가
|
||||
$user = auth()->user();
|
||||
|
||||
$data = [
|
||||
'sdate' => $sdate,
|
||||
'edate' => $edate,
|
||||
'advertiser' => $advertiser,
|
||||
'media' => $media,
|
||||
'description' => $description,
|
||||
'message' => $message,
|
||||
'username' => $user->username,
|
||||
'reg_date' => date('Y-m-d H:i:s')
|
||||
];
|
||||
|
||||
$this->integrate->saveDownloadData($data);
|
||||
|
||||
$row = $this->integrate->getEventLeadRow($data);
|
||||
if (!$row) {
|
||||
return $this->response->setJSON(['status' => 'error', 'message' => '데이터를 찾을 수 없습니다.']);
|
||||
}
|
||||
|
||||
$columns = $this->getColumns();
|
||||
$transformedData = $this->transformData($row, $columns);
|
||||
|
||||
switch ($fileFormat) {
|
||||
case 'csv':
|
||||
$fileData = $this->createCSVFile($transformedData, $columns);
|
||||
$contentType = 'text/csv';
|
||||
$fileExtension = 'csv';
|
||||
break;
|
||||
case 'pdf':
|
||||
$fileData = $this->createPDFFile($transformedData, $columns);
|
||||
$contentType = 'application/pdf';
|
||||
$fileExtension = 'pdf';
|
||||
break;
|
||||
case 'xlsx':
|
||||
default:
|
||||
$fileData = $this->createExcelFile($transformedData, $columns);
|
||||
$contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
||||
$fileExtension = 'xlsx';
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->response
|
||||
->setHeader('Content-Type', $contentType)
|
||||
->setHeader('Content-Disposition', 'attachment; filename="event_lead_' . date('YmdHis') . '.' . $fileExtension . '"')
|
||||
->setBody($fileData);
|
||||
}
|
||||
|
||||
private function createCSVFile($data, $columns)
|
||||
{
|
||||
$output = fopen('php://temp', 'r+');
|
||||
// UTF-8 BOM 추가
|
||||
fputs($output, "\xEF\xBB\xBF");
|
||||
fputcsv($output, array_values($columns));
|
||||
|
||||
foreach ($data as $row) {
|
||||
$rowData = [];
|
||||
foreach ($columns as $key => $header) {
|
||||
$rowData[] = $row[$key] ?? ''; // 키가 존재하지 않으면 빈 문자열로 대체
|
||||
}
|
||||
fputcsv($output, $rowData);
|
||||
}
|
||||
|
||||
rewind($output);
|
||||
$csvData = stream_get_contents($output);
|
||||
fclose($output);
|
||||
|
||||
return $csvData;
|
||||
}
|
||||
private function createPDFFile($data, $columns)
|
||||
{
|
||||
$html = '<table border="1" style="border-collapse: collapse; width: 100%;"><thead><tr>';
|
||||
foreach ($columns as $header) {
|
||||
$html .= "<th style='padding: 5px;'>{$header}</th>";
|
||||
}
|
||||
$html .= '</tr></thead><tbody>';
|
||||
|
||||
foreach ($data as $row) {
|
||||
$html .= '<tr>';
|
||||
foreach ($columns as $key => $header) {
|
||||
$value = $row[$key] ?? ''; // 키가 존재하지 않으면 빈 문자열로 대체
|
||||
$html .= "<td style='padding: 5px;'>{$value}</td>";
|
||||
}
|
||||
$html .= '</tr>';
|
||||
}
|
||||
$html .= '</tbody></table>';
|
||||
|
||||
$mpdf = new \Mpdf\Mpdf([
|
||||
'default_font' => 'nanumgothic', // 기본 폰트를 나눔고딕으로 설정
|
||||
'orientation' => 'L', // 가로 방향 설정
|
||||
'margin_left' => 5,
|
||||
'margin_right' => 5,
|
||||
'margin_top' => 5,
|
||||
'margin_bottom' => 5,
|
||||
'tempDir' => WRITEPATH . 'tmp', // CodeIgniter 4 writable 디렉토리 설정
|
||||
'fontDir' => array_merge((new \Mpdf\Config\ConfigVariables())->getDefaults()['fontDir'], [
|
||||
FCPATH . 'fonts', // 폰트 파일 경로
|
||||
]),
|
||||
'fontdata' => (new \Mpdf\Config\FontVariables())->getDefaults()['fontdata'] + [
|
||||
'nanumgothic' => [
|
||||
'R' => 'NanumGothic-Regular.ttf',
|
||||
'B' => 'NanumGothic-Bold.ttf',
|
||||
]
|
||||
],
|
||||
'default_font_size' => 12, // 기본 폰트 크기 설정
|
||||
]);
|
||||
|
||||
$mpdf->WriteHTML($html);
|
||||
return $mpdf->Output('', 'S');
|
||||
}
|
||||
private function createExcelFile($data, $columns)
|
||||
{
|
||||
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
// 헤더 설정
|
||||
$columnIndex = 'A';
|
||||
$sheet->setCellValue($columnIndex . '1', '#');
|
||||
$columnIndex++;
|
||||
foreach ($columns as $key => $header) {
|
||||
$sheet->setCellValue($columnIndex . '1', $header);
|
||||
if (in_array($key, ['addr', 'email', 'add1', 'add2', 'add3', 'add4', 'add5', 'add6'])) {
|
||||
$sheet->getColumnDimension($columnIndex)->setAutoSize(true);
|
||||
$sheet->getColumnDimension($columnIndex)->setWidth(200 / 7); // 최대 200픽셀로 제한
|
||||
} else if ($key === 'name') {
|
||||
$sheet->getColumnDimension($columnIndex)->setWidth(100 / 7); // 100픽셀로 설정 (엑셀의 너비 단위는 약 1/7인치)
|
||||
} else {
|
||||
$sheet->getColumnDimension($columnIndex)->setAutoSize(true); // 자동 너비 조정
|
||||
}
|
||||
$columnIndex++;
|
||||
}
|
||||
|
||||
// 필터 설정
|
||||
$sheet->setAutoFilter($sheet->calculateWorksheetDimension());
|
||||
|
||||
// 데이터 삽입
|
||||
$rowIndex = 2; // 데이터는 2번째 행부터 시작
|
||||
$totalRows = count($data);
|
||||
foreach ($data as $row) {
|
||||
$columnIndex = 'A';
|
||||
$sheet->setCellValue($columnIndex . $rowIndex, $totalRows); // 역순 카운트
|
||||
$columnIndex++;
|
||||
|
||||
foreach ($columns as $key => $header) {
|
||||
$value = $row[$key];
|
||||
if ($key === 'phone') {
|
||||
$value = preg_replace("/([0-9]{3})([0-9]{4})([0-9]{4})/", "$1-$2-$3", $value);
|
||||
$sheet->setCellValue($columnIndex . $rowIndex, $value);
|
||||
} elseif($key === 'age') {
|
||||
$value = $value == 0 ? "" : $value;
|
||||
$sheet->setCellValue($columnIndex . $rowIndex, $value);
|
||||
} elseif ($key === 'site') {
|
||||
$sheet->getCell($columnIndex . $rowIndex)->setValueExplicit($value, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
|
||||
} else {
|
||||
$sheet->setCellValue($columnIndex . $rowIndex, $value);
|
||||
}
|
||||
$columnIndex++;
|
||||
}
|
||||
|
||||
$rowIndex++;
|
||||
$totalRows--;
|
||||
}
|
||||
|
||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
|
||||
ob_start();
|
||||
$writer->save('php://output');
|
||||
$excelData = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $excelData;
|
||||
}
|
||||
|
||||
public function getButtons()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post'){
|
||||
$arg = $this->request->getPost();
|
||||
$arg['sdate'] = (new \DateTime($arg['sdate']))->format('Y-m-d') . ' 00:00:00';
|
||||
$arg['edate'] = (new \DateTime($arg['edate']))->format('Y-m-d') . ' 23:59:59';
|
||||
$leadsAll = $this->integrate->getEventLeadCount($arg);
|
||||
|
||||
$filters = [];
|
||||
$filters['data'] = $leadsAll['filteredResult'];
|
||||
$buttons['filtered'] = $this->setCount($leadsAll['filteredResult'], 'count');
|
||||
$buttons['noFiltered'] = $this->setCount($leadsAll['noFilteredResult'], 'total');
|
||||
foreach($buttons['noFiltered'] as $type => $row){
|
||||
foreach($row as $k => $v) {
|
||||
if(!isset($buttons['filtered'][$type][$k]))
|
||||
$buttons['filtered'][$type][$k] = ['count' => 0];
|
||||
$filter_lists[$type][$k] = array_merge($buttons['filtered'][$type][$k], $v);
|
||||
}
|
||||
}
|
||||
if(!empty($filter_lists)){
|
||||
foreach($filter_lists as $type => $row) {
|
||||
$sortedRow = array();
|
||||
|
||||
foreach ($row as $name => $v) {
|
||||
$sortedRow[$name] = array_merge(['label' => $name], $v);
|
||||
}
|
||||
|
||||
asort($sortedRow);
|
||||
$sortedRow = array_values($sortedRow);
|
||||
|
||||
$filters[$type] = $sortedRow;
|
||||
}
|
||||
}
|
||||
$status = $this->integrate->getStatusCount($arg);
|
||||
$filters['status'] = $status;
|
||||
|
||||
return $this->respond($filters);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getEventLeadCount()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
if(!isset($arg['searchData'])) {
|
||||
$arg['searchData'] = [
|
||||
'sdate'=> date('Y-m-d'),
|
||||
'edate'=> date('Y-m-d')
|
||||
];
|
||||
}
|
||||
$data = $this->integrate->getEventLeadCount($arg);
|
||||
|
||||
$adv_counts = array();
|
||||
$med_counts = array();
|
||||
$event_counts = array();
|
||||
foreach ($data as $row) {
|
||||
if (!array_key_exists($row['adv_name'], $adv_counts)) {
|
||||
$adv_counts[$row['adv_name']] = array(
|
||||
'countAll' => 0
|
||||
);
|
||||
}
|
||||
|
||||
if (!array_key_exists($row['med_name'], $med_counts)) {
|
||||
$med_counts[$row['med_name']] = array(
|
||||
'countAll' => 0
|
||||
);
|
||||
}
|
||||
|
||||
$event_counts[$row['description']] = array(
|
||||
'countAll' => $row['countAll'],
|
||||
);
|
||||
|
||||
$adv_counts[$row['adv_name']]['countAll'] += $row['countAll'];
|
||||
$med_counts[$row['med_name']]['countAll'] += $row['countAll'];
|
||||
}
|
||||
|
||||
$result = [
|
||||
'advertiser' => $adv_counts,
|
||||
'media' => $med_counts,
|
||||
'description' => $event_counts,
|
||||
];
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getStatusCount()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
if(!isset($arg['searchData'])) {
|
||||
$arg['searchData'] = [
|
||||
'sdate'=> date('Y-m-d'),
|
||||
'edate'=> date('Y-m-d')
|
||||
];
|
||||
}
|
||||
$result = $this->integrate->getStatusCount($arg);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getMemo()
|
||||
{
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
|
||||
$arg = $this->request->getGet();
|
||||
$result = $this->integrate->getMemo($arg);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function addMemo() {
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post'){
|
||||
$arg = $this->request->getPost();
|
||||
$result = $this->integrate->addMemo($arg);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function setStatus() {
|
||||
if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post'){
|
||||
if(!auth()->user()->hasPermission('integrate.status') && !auth()->user()->inGroup('superadmin', 'admin')){
|
||||
return $this->fail("권한이 없습니다.");
|
||||
}
|
||||
$arg = $this->request->getPost();
|
||||
$result = $this->integrate->setStatus($arg);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
private function setCount($leads, $type)
|
||||
{
|
||||
$data = [
|
||||
'advertiser' => [],
|
||||
'media' => [],
|
||||
'description' => [],
|
||||
];
|
||||
if(getenv('MY_SERVER_NAME') === 'resta' && auth()->user()->inGroup('superadmin', 'admin', 'developer', 'user')){
|
||||
$data['company'] = [];
|
||||
}
|
||||
foreach($leads as $row) {
|
||||
if(getenv('MY_SERVER_NAME') === 'resta' && auth()->user()->inGroup('superadmin', 'admin', 'developer', 'user')){
|
||||
//분류 기준
|
||||
if (!isset($data['company']['리스타'])) {
|
||||
$data['company']['리스타'][$type] = 0;
|
||||
}
|
||||
if($row['status'] == 1 && ($row['company'] != '케어랩스' && $row['company'] != '테크랩스')){
|
||||
$data['company']['리스타'][$type]++;
|
||||
}
|
||||
|
||||
if (isset($row['company'])) {
|
||||
if (!isset($data['company']['케어랩스'])) {
|
||||
$data['company']['케어랩스'][$type] = 0;
|
||||
}
|
||||
|
||||
if (!isset($data['company']['테크랩스'])) {
|
||||
$data['company']['테크랩스'][$type] = 0;
|
||||
}
|
||||
|
||||
if($row['status'] == 1 && $row['company'] == '케어랩스'){
|
||||
$data['company']['케어랩스'][$type]++;
|
||||
}
|
||||
|
||||
if($row['status'] == 1 && $row['company'] == '테크랩스'){
|
||||
$data['company']['테크랩스'][$type]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//광고주 기준
|
||||
if (!empty($row['advertiser'])) {
|
||||
if (!isset($data['advertiser'][$row['advertiser']])) {
|
||||
$data['advertiser'][$row['advertiser']][$type] = 0;
|
||||
}
|
||||
|
||||
if($row['status'] == 1){
|
||||
$data['advertiser'][$row['advertiser']][$type]++;
|
||||
}
|
||||
}
|
||||
|
||||
//매체 기준
|
||||
if (!empty($row['media'])) {
|
||||
if (!isset($data['media'][$row['media']])) {
|
||||
$data['media'][$row['media']][$type] = 0;
|
||||
}
|
||||
|
||||
if($row['status'] == 1){
|
||||
$data['media'][$row['media']][$type]++;
|
||||
}
|
||||
}
|
||||
|
||||
//이벤트 기준
|
||||
if (!empty($row['description'])) {
|
||||
if (!isset($data['description'][$row['description']])) {
|
||||
$data['description'][$row['description']][$type] = 0;
|
||||
}
|
||||
|
||||
if($row['status'] == 1){
|
||||
$data['description'][$row['description']][$type]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
namespace App\Controllers;
|
||||
|
||||
class PageController extends BaseController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$page = new PageController();
|
||||
return $page->view();
|
||||
}
|
||||
|
||||
public function view($page = 'home')
|
||||
{
|
||||
if(!is_file(APPPATH . 'Views/pages/' . $page . '.php')) {
|
||||
throw new \CodeIgniter\Exceptions\PageNotFoundException($page);
|
||||
}
|
||||
|
||||
$data['title'] = ucfirst($page);
|
||||
|
||||
return view('pages/'.$page, $data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
<?php
|
||||
namespace App\Controllers\User;
|
||||
|
||||
use App\Models\Api\CompanyModel;
|
||||
use App\Models\Api\IdentityModel;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
use App\Models\Api\UserModel;
|
||||
use CodeIgniter\Shield\Authentication\Passwords;
|
||||
use CodeIgniter\Shield\Entities\User;
|
||||
|
||||
class UserController extends \CodeIgniter\Controller
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected $user;
|
||||
protected $company;
|
||||
protected $data;
|
||||
protected $logginedUser;
|
||||
protected $validation;
|
||||
|
||||
public function __construct() {
|
||||
$this->user = model(UserModel::class);
|
||||
$this->company = model(CompanyModel::class);
|
||||
$this->logginedUser = auth()->user();
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('users/user');
|
||||
}
|
||||
|
||||
public function myPage()
|
||||
{
|
||||
return view('users/mypage', ['user'=>$this->logginedUser]);
|
||||
}
|
||||
|
||||
public function myPageUpdate()
|
||||
{
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$credentials = [
|
||||
'email' => $this->logginedUser->getEmail(),
|
||||
'password' => $data['old_password'],
|
||||
];
|
||||
|
||||
$validCreds = auth()->check($credentials);
|
||||
if (! $validCreds->isOK()) {
|
||||
return redirect()->back()->with('error', '기존 비밀번호가 일치하지 않습니다.');
|
||||
}
|
||||
|
||||
$rules = [
|
||||
'password' => [
|
||||
'label' => 'Auth.password',
|
||||
'rules' => 'required|' . Passwords::getMaxLengthRule() . '|strong_password[]',
|
||||
'errors' => [
|
||||
'max_byte' => 'Auth.errorPasswordTooLongBytes',
|
||||
],
|
||||
],
|
||||
'password_confirm' => [
|
||||
'label' => 'Auth.passwordConfirm',
|
||||
'rules' => 'required|matches[password]',
|
||||
],
|
||||
];
|
||||
|
||||
if (! $this->validateData($data, $rules, [], config('Auth')->DBGroup)) {
|
||||
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
$cuser = auth()->user();
|
||||
$cuser->fill($data);
|
||||
$this->user->save($cuser);
|
||||
$this->setPasswordChangedAt(true);
|
||||
return redirect()->back()->with('message', '비밀번호가 변경되었습니다.');
|
||||
}
|
||||
|
||||
public function getUsers(){
|
||||
if (/* $this->request->isAJAX() && */strtolower($this->request->getMethod()) === 'get') {
|
||||
$param = $this->request->getGet();
|
||||
$result = $this->user->getUsers($param);
|
||||
foreach ($result['data'] as &$row) {
|
||||
$groups = explode(",", $row['groups']);
|
||||
$groupsMapping = [
|
||||
'superadmin' => '최고관리자',
|
||||
'admin' => '관리자',
|
||||
'developer' => '개발자',
|
||||
'user' => '직원',
|
||||
'agency' => '광고대행사',
|
||||
'advertiser' => '광고주',
|
||||
'guest' => '게스트',
|
||||
];
|
||||
|
||||
foreach ($groups as &$group) {
|
||||
$group = $groupsMapping[$group] ?? '';
|
||||
}
|
||||
|
||||
usort($groups, function ($a, $b) {
|
||||
return strcmp($a, $b);
|
||||
});
|
||||
|
||||
$row['groups'] = implode(',', $groups);
|
||||
|
||||
if($row['active']){
|
||||
$row['active'] = '활성';
|
||||
}else{
|
||||
$row['active'] = '비활성';
|
||||
}
|
||||
};
|
||||
|
||||
$result = [
|
||||
'data' => $result['data'],
|
||||
'recordsTotal' => $result['allCount'],
|
||||
'recordsFiltered' => $result['allCount'],
|
||||
'draw' => intval($param['draw']),
|
||||
];
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getUser(){
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get') {
|
||||
$param = $this->request->getGet();
|
||||
$result = $this->user->getUser($param);
|
||||
$result['groups'] = explode(",", $result['groups']);
|
||||
$result['permissions'] = explode(",", $result['permissions']);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getSearchUsers(){
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get') {
|
||||
$param = $this->request->getGet();
|
||||
$result = $this->user->getSearchUsers($param);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function getBelongUsers(){
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get') {
|
||||
$param = $this->request->getGet();
|
||||
$result = $this->user->getBelongUsers($param['company_id']);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function setUser()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'put') {
|
||||
$param = $this->request->getRawInput();
|
||||
if (!empty($param)) {
|
||||
$company = $this->company->getCompanyByName($param['company_name']);
|
||||
if(!empty($param['company_name'])){
|
||||
if(empty($company)) {
|
||||
return $this->failValidationErrors(["company" => "존재하지 않는 광고주/광고대행사입니다."]);
|
||||
}else{
|
||||
$param['company_id'] = $company['id'];
|
||||
}
|
||||
}
|
||||
if(empty($param['group']) || !$this->checkPermission($this->logginedUser, $param['user_id'], $param['group'])){
|
||||
return $this->failValidationErrors(["groups" => "수정 권한이 없습니다."]);
|
||||
}
|
||||
$result = $this->user->setUser($param);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function setBelongUser()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'put') {
|
||||
$param = $this->request->getRawInput();
|
||||
if (!empty($param)) {
|
||||
$belongUser = $this->user->getBelongUser($param);
|
||||
if(!empty($belongUser)){
|
||||
return $this->failValidationErrors(["username" => "이미 소속되어 있습니다."]);
|
||||
}
|
||||
$result = $this->user->setBelongUser($param);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function exceptBelongUser()
|
||||
{
|
||||
if ($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'delete') {
|
||||
$param = $this->request->getRawInput();
|
||||
if (!empty($param)) {
|
||||
$result = $this->user->exceptBelongUser($param);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function setPasswordChangedAtAjax()
|
||||
{
|
||||
if (/* $this->request->isAJAX() && */strtolower($this->request->getMethod()) === 'get') {
|
||||
$result = $this->setPasswordChangedAt(false);
|
||||
|
||||
return $this->respond($result);
|
||||
}else{
|
||||
return $this->fail("잘못된 요청");
|
||||
}
|
||||
}
|
||||
|
||||
public function setPasswordChangedAt($type = false)
|
||||
{
|
||||
$user = $this->logginedUser;
|
||||
|
||||
if($type === true){
|
||||
$date = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s") . "+90 days"));
|
||||
}else{
|
||||
$date = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s") . "-76 days"));
|
||||
}
|
||||
|
||||
$identityModel = model(IdentityModel::class);
|
||||
$result = $identityModel->setPasswordChangedAt($user->id, $date);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function checkPermission($logginedUser, $updateId, $postGroups)
|
||||
{
|
||||
$updateUser = $this->user->find($updateId);
|
||||
$logginedUserGroups = $logginedUser->getGroups();
|
||||
$updateUserGroups = $updateUser->getGroups();
|
||||
|
||||
// 그룹 순서 정의
|
||||
$groupOrder = array_keys(config('AuthGroups')->groups);
|
||||
foreach ($postGroups as $postGroup) {
|
||||
foreach ($logginedUserGroups as $logginedUserGroup) {
|
||||
$currentGroupIndex = array_search($logginedUserGroup, $groupOrder);
|
||||
$targetGroupIndex = array_search($postGroup, $groupOrder);
|
||||
// superadmin, admin, developer, user 그룹만 수정 가능
|
||||
$editableGroups = ['superadmin', 'admin', 'developer', 'user'];
|
||||
if (in_array($logginedUserGroup, $editableGroups)) {
|
||||
// 자신의 그룹과 상위 그룹은 수정 불가
|
||||
if ($currentGroupIndex >= $targetGroupIndex) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 수정할 대상 사용자의 그룹이 자신보다 높은지 체크
|
||||
foreach ($updateUserGroups as $updateUserGroup) {
|
||||
foreach ($logginedUserGroups as $logginedUserGroup) {
|
||||
$currentGroupIndex = array_search($logginedUserGroup, $groupOrder);
|
||||
$updateGroupIndex = array_search($updateUserGroup, $groupOrder);
|
||||
|
||||
if ($currentGroupIndex >= $updateGroupIndex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Database\Seeds;
|
||||
|
||||
use CodeIgniter\Database\Seeder;
|
||||
use App\Models\Api\BoardModel;
|
||||
use CodeIgniter\I18n\Time;
|
||||
|
||||
class BoardSeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$board = new BoardModel;
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
for ($i = 0; $i < 20; $i++) {
|
||||
$board->save(
|
||||
[
|
||||
'board_title' => $faker->sentence(),
|
||||
'board_description' => $faker->realText(),
|
||||
'created_at' => Time::createFromTimestamp($faker->unixTime()),
|
||||
'updated_at' => Time::now(),
|
||||
'deleted_at' => NULL,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Database\Seeds;
|
||||
|
||||
use CodeIgniter\Database\Seeder;
|
||||
use App\Models\Api\CompanyModel;
|
||||
use CodeIgniter\I18n\Time;
|
||||
|
||||
class CompanySeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$db = \Config\Database::connect();
|
||||
$builder = $db->table('event_advertiser');
|
||||
$builder->select('name');
|
||||
$adv = $builder->get()->getResultArray();
|
||||
|
||||
$compBuilder = $db->table('companies');
|
||||
foreach($adv as $v){
|
||||
$compBuilder->where('name', $v['name']);
|
||||
$existing = $compBuilder->get()->getRow();
|
||||
if(!$existing) {
|
||||
$data = [
|
||||
'type' => '',
|
||||
'name' => $v['name'],
|
||||
'tel' => '',
|
||||
'created_at' => Time::now(),
|
||||
'updated_at' => Time::now(),
|
||||
];
|
||||
$compBuilder->insert($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user