This commit is contained in:
Jaybe
2025-03-05 14:02:29 +09:00
commit 247a7808d3
357 changed files with 161196 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
<IfModule authz_core_module>
Require all denied
</IfModule>
<IfModule !authz_core_module>
Deny from all
</IfModule>
+74
View File
@@ -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);
}
}
+180
View File
@@ -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);
}
}
+131
View File
@@ -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;
}
}
+67
View File
@@ -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);
}
}
+73
View File
@@ -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);
}
}
+58
View File
@@ -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);
}
}
+58
View File
@@ -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);
}
}
+58
View File
@@ -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);
}
}
+87
View File
@@ -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);
}
}
+15
View File
@@ -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/
*/
+360
View File
@@ -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;
}
+474
View File
@@ -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;
}
}
+154
View File
@@ -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.*',
],
];
}
+138
View File
@@ -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';
}
+98
View File
@@ -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'];
}
+32
View File
@@ -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);
+21
View File
@@ -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);
+32
View File
@@ -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);
+20
View File
@@ -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;
}
+169
View File
@@ -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,
];
}
+94
View File
@@ -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);
+176
View File
@@ -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;
}
+107
View File
@@ -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;
}
+214
View File
@@ -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';
}
}
}
+43
View File
@@ -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;
}
+124
View File
@@ -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');
}
}
+83
View File
@@ -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 = '';
}
+48
View File
@@ -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();
}
});
+77
View File
@@ -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;
}
+30
View File
@@ -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;
}
+105
View File
@@ -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 dont 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/*'
]
]
];
}
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace Config;
use CodeIgniter\Config\ForeignCharacters as BaseForeignCharacters;
class ForeignCharacters extends BaseForeignCharacters
{
}
+77
View File
@@ -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);
}
}
+40
View File
@@ -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',
];
}
+42
View File
@@ -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';
}
+31
View File
@@ -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,
];
}
+51
View File
@@ -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;
}
+150
View File
@@ -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,
// ],
];
}
+52
View File
@@ -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_';
}
+530
View File
@@ -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;
}
}
+76
View File
@@ -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',
];
}
+37
View File
@@ -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;
}
+75
View File
@@ -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';
}
+28
View File
@@ -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',
];
}
+286
View File
@@ -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');
+113
View File
@@ -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 = [];
}
+101
View File
@@ -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';
}
+32
View File
@@ -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();
* }
*/
}
+102
View File
@@ -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;
}
+57
View File
@@ -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');
}
}
+91
View File
@@ -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;
}
+252
View File
@@ -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',
];
}
+59
View File
@@ -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',
],
];
}
+56
View File
@@ -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;
}
}
*/
}
+162
View File
@@ -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);
}
}
+121
View File
@@ -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
+424
View File
@@ -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;
}
}
+17
View File
@@ -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("/");
}
}
+58
View File
@@ -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("잘못된 요청");
}
}
}
+17
View File
@@ -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);
}
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\Controllers;
use App\Controllers\BaseController;
class GuestController extends BaseController
{
public function index()
{
return view('guest/guest');
}
}
+47
View File
@@ -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">&#9618;&#9618;</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">&#9618;</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) . '&#9618;&#9618;' . 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) ? '&#9618;' : 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;
}
}
+22
View File
@@ -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);
}
}
+286
View File
@@ -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;
}
}
View File
View File
+28
View File
@@ -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,
]
);
}
}
}
+34
View File
@@ -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);
}
}
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Database\Seeds;
use CodeIgniter\Database\Seeder;
class EventAdvertiserSeeder extends Seeder
{
public function run()
{
//companies와 event_advertiser name 같은것 company_seq 연결
$db = \Config\Database::connect();
$builder = $db->table('companies');
$builder->select('id, name');
$adv = $builder->get()->getResultArray();
$compBuilder = $db->table('event_advertiser');
foreach($adv as $v){
$compBuilder->where('name', $v['name']);
//$compBuilder->where('company_seq', null);
$data = [
'company_seq' => $v['id'],
];
$compBuilder->update($data);
}
}
}
+216
View File
@@ -0,0 +1,216 @@
<?php
namespace App\Database\Seeds;
use CodeIgniter\Database\Seeder;
use CodeIgniter\Shield\Entities\User;
use CodeIgniter\Shield\Models\UserModel;
class UserSeeder extends Seeder
{
public function run()
{
$user = new UserModel;
$faker = \Faker\Factory::create();
$data = [
/* array(
"username" => "yskim",
"email" => "ryan1219@carelabs.co.kr"
),
array(
"username" => "hsm",
"email" => "hsm0301@carelabs.co.kr"
),
array(
"username" => "lek",
"email" => "eunkyoung@carelabs.co.kr"
),
array(
"username" => "kuhellian",
"email" => "kimcg@carelabs.co.kr"
),
array(
"username" => "vcvxvz",
"email" => "nylee@carelabs.co.kr"
),
array(
"username" => "dudtjr9169",
"email" => "kys9169@carelabs.co.kr"
),
array(
"username" => "hermesheo",
"email" => "min.heo@carelabs.co.kr"
), */
/* array(
"username" => "jms",
"email" => "jms@carelabs.co.kr"
), */
/* array(
"username" => "kumssac",
"email" => "kumssac@carelabs.co.kr"
),
array(
"username" => "hjs",
"email" => "spacejin01@carelabs.co.kr"
),
array(
"username" => "yjj",
"email" => "yjj@carelabs.co.kr"
), */
/* array(
"username" => "jaybe",
"email" => "jaybe@carelabs.co.kr"
), */
/* array(
"username" => "dltjwls247",
"email" => "seo@carelabs.co.kr"
),
array(
"username" => "designloop",
"email" => "dloop@carelabs.co.kr"
),
array(
"username" => "gblagdog",
"email" => "gblagdog@carelabs.co.kr"
),
array(
"username" => "sgksks",
"email" => "sgksks@carelabs.co.kr"
),
array(
"username" => "hahazz",
"email" => "hahazz@carelabs.co.kr"
),
array(
"username" => "darkyong",
"email" => "darkyong@carelabs.co.kr"
),
array(
"username" => "chosk",
"email" => "chosk@carelabs.co.kr"
),
array(
"username" => "zfkltm320",
"email" => "zfkltm320@carelabs.co.kr"
),
array(
"username" => "jinseon5415",
"email" => "jinseon5415@carelabs.co.kr"
),
array(
"username" => "hamstouch",
"email" => "hamstouch@carelabs.co.kr"
),
array(
"username" => "gschoi",
"email" => "gs.choi@carelabs.co.kr"
),
array(
"username" => "hokeg1",
"email" => "hokeg1@carelabs.co.kr"
),
array(
"username" => "kimhr425",
"email" => "kimhr425@carelabs.co.kr"
),
array(
"username" => "gksquf123",
"email" => "gksquf123@carelabs.co.kr"
),
array(
"username" => "hyeji0125",
"email" => "hyeji0125@carelabs.co.kr"
),
array(
"username" => "zxwcll",
"email" => "zxwcll@carelabs.co.kr"
),
array(
"username" => "rong2",
"email" => "rong2@carelabs.co.kr"
),
array(
"username" => "oklhw38",
"email" => "oklhw38@carelabs.co.kr"
),
array(
"username" => "loveholic",
"email" => "loveholic@carelabs.co.kr"
),
array(
"username" => "future",
"email" => "future@carelabs.co.kr"
), */
/* array(
"username" => "tjwlgml47",
"email" => "tjwlgml47@carelabs.co.kr"
), */
/* array(
"username" => "azure871129",
"email" => "yjm@carelabs.co.kr"
),
array(
"username" => "osd92",
"email" => "osd92@carelabs.co.kr"
),
array(
"username" => "clapone",
"email" => "clapone@carelabs.co.kr"
),
array(
"username" => "rhea7904",
"email" => "rhea7904@carelabs.co.kr"
),
array(
"username" => "dkstjrals",
"email" => "dkstjrals@carelabs.co.kr"
), */
/* array(
"username" => "ms1114",
"email" => "ms1114@carelabs.co.kr"
), */
/* array(
"username" => "khjkhj1202",
"email" => "khjkhj1202@carelabs.co.kr"
),
array(
"username" => "ohyeonjae",
"email" => "ohyeonjae@carelabs.co.kr"
),
array(
"username" => "chanyeong",
"email" => "chanyeong@carelabs.co.kr"
), */
/* array(
"username" => "pjh8778",
"nickname" => "박종호",
"email" => "pjh8778@carelabs.co.kr",
),
array(
"username" => "sungjin",
"nickname" => "박성진",
"email" => "sunshine_psj@carelabs.co.kr"
), */
array(
"username" => "jinhong",
"nickname" => "김진홍",
"email" => "jinhong@carelabs.co.kr",
),
];
for ($i = 0; $i < count($data); $i++) {
$data[$i]['password'] = '1234';
$data[$i]['password_confirm'] = '1234';
$userModel = model(UserModel::class);
$user = new User();
$user->fill($data[$i]);
$userModel->save($user);
$user = $userModel->findById($userModel->getInsertID());
$user->addGroup('guest');
$user->activate();
}
}
}
View File
+28
View File
@@ -0,0 +1,28 @@
<?php
namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
class AuthFilter implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null)
{
if (is_cli()) return;
$auth = service('auth');
if (!$auth->loggedIn()) {
if ($request->isAJAX()) {
return service('response')->setStatusCode(401)->setJSON(['message' => 'Unauthorized']);
} else {
return redirect()->to('/login');
}
}
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// Do something here
}
}

Some files were not shown because too many files have changed in this diff Show More