From 1e9842dc6e3d5ee923e382b0d76594db415ecc4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=A4=80=ED=9D=A0?= Date: Thu, 12 Sep 2024 19:07:29 +0900 Subject: [PATCH] Automation init...3 --- app/Controllers/CrawlerController.php | 11 +- app/Libraries/MyCrawler/MyCrawlerLibrary.php | 71 +++--- app/Libraries/MyCrawler/YamapLibrary.php | 218 ++++++++++++------ app/Libraries/MySocket/MySocketLibrary.php | 2 +- app/Libraries/MySocket/WebLibrary.php | 56 +++-- app/Libraries/MyStorage/FileLibrary.php | 30 +-- .../MyStorage/Mangboard/FileLibrary.php | 121 ++++++++++ .../MyStorage/Mangboard/SmallImageLibrary.php | 82 +++++++ .../MyStorage/MangboardFileLibrary.php | 162 ------------- app/Libraries/MyStorage/MyStorageLibrary.php | 2 +- app/Libraries/MyUtil/ImageLibrary.php | 61 ++--- app/Models/CommonModel.php | 9 + app/Models/Mangboard/BoardModel.php | 3 +- app/Models/Mangboard/FileModel.php | 4 +- 14 files changed, 458 insertions(+), 374 deletions(-) create mode 100644 app/Libraries/MyStorage/Mangboard/FileLibrary.php create mode 100644 app/Libraries/MyStorage/Mangboard/SmallImageLibrary.php delete mode 100644 app/Libraries/MyStorage/MangboardFileLibrary.php diff --git a/app/Controllers/CrawlerController.php b/app/Controllers/CrawlerController.php index 839acfb..20d2f5e 100644 --- a/app/Controllers/CrawlerController.php +++ b/app/Controllers/CrawlerController.php @@ -2,8 +2,6 @@ namespace App\Controllers; -use App\Libraries\MySocket\WebLibrary as MySocketLibrary; -use App\Libraries\MyStorage\MangboardFileLibrary as MyStorageLibrary; use App\Libraries\MyCrawler\YamapLibrary as MyCrawler; use App\Controllers\CommonController; use App\Models\Mangboard\UserModel; @@ -24,16 +22,11 @@ class CrawlerController extends CommonController // getenv('daemonidc.login.user_password') // ); //2. 필요한 로그인한 사용자정보,Socket,Storage 정의후 Crawler에게 전달. - $mySocket = new MySocketLibrary(getenv('yamap.host.url')); - $myStorage = new MyStorageLibrary(getenv('yamap.storage.upload.path')); - $myStorage->setUser($userEntity); - $myStorage->setBoardName(getenv('yamap.storage.board.name')); - $myStorage->setBoardlevel(getenv('yamap.storage.board.level')); - $crawler = new MyCrawler($mySocket, $myStorage); + $crawler = new MyCrawler(); + $crawler->setUserEntity($userEntity); if (in_array("debug", $params)) { $crawler->setDebug(true); } - //3. 실행 $crawler->execute(); return "완료되었습니다."; } catch (\Exception $e) { diff --git a/app/Libraries/MyCrawler/MyCrawlerLibrary.php b/app/Libraries/MyCrawler/MyCrawlerLibrary.php index 2a36dc3..4626767 100644 --- a/app/Libraries/MyCrawler/MyCrawlerLibrary.php +++ b/app/Libraries/MyCrawler/MyCrawlerLibrary.php @@ -2,65 +2,62 @@ namespace App\Libraries\MyCrawler; -use Symfony\Component\DomCrawler\Crawler; use App\Libraries\CommonLibrary; +use Symfony\Component\DomCrawler\Crawler; abstract class MyCrawlerLibrary extends CommonLibrary { - private $_mySocket = null; - private $_myStorage = null; - protected function __construct($mySocket, $myStorage) + protected $_mySocket = null; + protected $_myStorage = null; + protected function __construct() { parent::__construct(); - $this->_mySocket = $mySocket; - $this->_myStorage = $myStorage; } - abstract public function execute(): void; - final protected function getMySocket(): mixed + abstract protected function getMySocket(): mixed; + abstract protected function getMyStorage(): mixed; + final protected function getSelector(string $content, string $tag): Crawler { - if ($this->_mySocket === null) { - throw new \Exception("MySocket이 지정되지 않았습니다."); + $crawler = new Crawler($content); + if ($this->getDebug()) { + log_message("debug", sprintf( + "\n---------%s----------\ntag:%s\n%s\n-------------------\n", + __FUNCTION__, + $tag, + $content + )); + exit; } - return $this->_mySocket; - } - final protected function getMyStorage(): mixed - { - if ($this->_myStorage === null) { - throw new \Exception("MySocket이 지정되지 않았습니다."); - } - return $this->_myStorage; - } - - final protected function getContent(string $url, string $tag): Crawler - { - $response = $this->getMySocket()->getContent($url); - if (!$response) { - throw new \Exception("getCrawler 실패:{$url}"); - } - $crawler = new Crawler($response); return $crawler->filter($tag); } - //Download한 파일 저장후 추가작업시 사용 - final protected function download(string $mediaType, Crawler $crawler, array $options, array $myStorageLibrarys = []): array + protected function save(string $url, string $mediaType, int $file_sequence): mixed + { + $data = $this->getMySocket()->download($url); + $this->getMyStorage()->setOriginName($this->getMySocket()->getFileName()); + $this->getMyStorage()->setOriginContent($data); + $this->getMyStorage()->setOriginType($mediaType); + $this->getMyStorage()->setOriginSequence($file_sequence); + return $this->getMyStorage()->save(); + } + + final protected function download(string $mediaType, Crawler $selector, array $options, array $myStorageLibrarys = []): array { $nodes = []; - $crawler->filter($options["tag"])->each( + $selector->filter($options["tag"])->each( function (Crawler $node) use (&$options, &$nodes): void { - log_message("debug", sprintf("getNode->%s[%s]", $options["tag"], $node->attr($options['attr']))); + log_message("debug", sprintf( + "getNode->%s[%s]", + $options["tag"], + $node->attr($options['attr']) + )); $nodes[] = $node; } ); $file_sequence = 1; foreach ($nodes as $node) { try { - list($fileName, $content) = $this->getMySocket()->download($node->attr($options["attr"])); - $this->getMyStorage()->setOriginName($fileName); - $this->getMyStorage()->setOriginContent($content); - $this->getMyStorage()->setOriginType($mediaType); - $this->getMyStorage()->setOriginSequence($file_sequence); - $myStorageLibrarys[] = $this->getMyStorage()->save(); + $myStorageLibrarys[] = $this->save($node->attr($options["attr"]), $mediaType, $file_sequence); $file_sequence++; log_message("notice", __FUNCTION__ . " OriginType->{$mediaType} 작업 완료"); } catch (\Exception $e) { diff --git a/app/Libraries/MyCrawler/YamapLibrary.php b/app/Libraries/MyCrawler/YamapLibrary.php index 0be1c5d..7f3d79c 100644 --- a/app/Libraries/MyCrawler/YamapLibrary.php +++ b/app/Libraries/MyCrawler/YamapLibrary.php @@ -2,64 +2,113 @@ namespace App\Libraries\MyCrawler; +use App\Libraries\MySocket\WebLibrary as MySocketLibrary; +use App\Libraries\MyStorage\Mangboard\FileLibrary as MyStorageLibrary; +use App\Entities\Mangboard\BoardEntity; +use App\Entities\Mangboard\UserEntity; use App\Models\Mangboard\BoardModel; use Symfony\Component\DomCrawler\Crawler; class YamapLibrary extends MyCrawlerLibrary { - private $_userModel = null; - private $_boardModel = null; - public function __construct($mySocket, $myStorage) + private $_user_entity = null; + private $_board_model = null; + private $_board_name = null; + private $_board_level = null; + private $_media_tags = []; + public function __construct() { - parent::__construct($mySocket, $myStorage); - //원래는 mb_board Table에서 해당Board정보를 읽어서 처리해아함 - $this->getMyStorage()->setBoardTable($this->getBoardModel()->getTable()); + parent::__construct(); } - private function getBoardModel(): BoardModel + final protected function getMySocket(): mixed { - if ($this->_boardModel === null) { - $this->_boardModel = new BoardModel(getenv("yamap.storage.board.table")); + if ($this->_mySocket === null) { + $this->_mySocket = new MySocketLibrary(getenv('yamap.host.url')); } - return $this->_boardModel; + return $this->_mySocket; } - private function createBoard(array $itemInfo, array $myStorageLibrarys): void + final protected function getMyStorage(): mixed + { + if ($this->_myStorage === null) { + $this->_myStorage = new MyStorageLibrary(getenv('yamap.storage.upload.path')); + $this->_myStorage->setBoardName($this->getBoardName()); + $this->_myStorage->setBoardTable($this->getBoardModel()->getTable()); + $this->_myStorage->setUserEntity($this->getUserEntity()); + } + return $this->_myStorage; + } + public function getBoardModel(): BoardModel + { + if ($this->_board_model === null) { + $this->_board_model = new BoardModel("mb_" . $this->getBoardName()); + } + return $this->_board_model; + } + public function getUserEntity(): UserEntity + { + if ($this->_user_entity === null) { + throw new \Exception("사용자정보가 없습니다."); + } + return $this->_user_entity; + } + public function setUserEntity(UserEntity $_user_entity): void + { + $this->_user_entity = $_user_entity; + } + public function getBoardName(): string + { + if ($this->_board_name === null) { + $this->_board_name = getenv('yamap.storage.board.name'); + } + return $this->_board_name; + } + public function getBoardLevel(): int + { + if ($this->_board_level === null) { + $this->_board_level = getenv('yamap.storage.board.level'); + } + return intval($this->_board_level); + } + + private function createBoard(array $listInfo): BoardEntity { //미디어관련정보 entity에 넣기 $formDatas = []; - $formDatas['title'] = $itemInfo["title"]; - $formDatas['user_pid'] = $this->getMyStorage()->getUser()->getPK(); - $formDatas['user_id'] = $this->getMyStorage()->getUser()->getID(); - $formDatas['user_name'] = $itemInfo["nickname"] != "" ? $itemInfo["nickname"] : $this->getMyStorage()->getUser()->getTitle(); - $formDatas['level'] = $this->getMyStorage()->getBoardLevel(); - $formDatas['hit'] = $itemInfo['hit']; - $formDatas['reg_date'] = date("Y-m-d H:i:s", strtotime($itemInfo['date'])); + $formDatas['title'] = $listInfo["title"]; + $formDatas['user_pid'] = $this->getUserEntity()->getPK(); + $formDatas['user_id'] = $this->getUserEntity()->getID(); + $formDatas['user_name'] = $listInfo["nickname"] != "" ? $listInfo["nickname"] : $this->getUserEntity()->getTitle(); + $formDatas['level'] = $this->getBoardLevel(); + $formDatas['hit'] = $listInfo['hit']; + $formDatas['reg_date'] = date("Y-m-d H:i:s", strtotime($listInfo['date'])); $formDatas['data_type'] = "html"; $formDatas['editor_type'] = "S"; - $formDatas['image_path'] = false; - $content = ""; - foreach ($myStorageLibrarys as $myStorageLibrary) { - if ($formDatas['image_path'] === false) { - $formDatas['image_path'] = $myStorageLibrary->getPath(); - } - $content .= $myStorageLibrary->getMediaTag(); - } - $formDatas['content'] = $content; + $formDatas['image_path'] = ""; + $formDatas['content'] = ""; //망보드 게시판에 등록 $entity = $this->getBoardModel()->create($formDatas); - //망보드 파일관리툴에 등록된 파일게시물에 등록한 게시판번호 수정하기 - foreach ($myStorageLibrarys as $myStorageLibrary) { - $myStorageLibrary->setBoardPID(intval($entity->getPK())); - } + log_message("notice", message: __FUNCTION__ . " 작업 완료"); + return $entity; + } + private function modifyBoard(BoardEntity $entity) + { + $formDatas = [ + "image_path" => array_shift($this->_media_tags["image_path"]), + "content" => implode("\n", $this->_media_tags["content"]) + ]; + $this->getBoardModel()->modify($entity, $formDatas); log_message("notice", __FUNCTION__ . " 작업 완료"); } private function mainPage(string $url): array { - $crawler = $this->getContent($url, getenv("yamap.list.tag")); - $items = []; + $listInfos = []; + $response = $this->getMySocket()->getResponse($url); + $selector = $this->getSelector($response, getenv("yamap.list.tag")); //div.bbs_item를 가진 객체를 찾아서 같은 형식의 객체(sibling)를 배열로 넘김 - $crawler->filter(getenv("yamap.list.item.tag"))->each( - function (Crawler $node) use (&$items): void { + // log_message("debug", sprintf("\n-------------MainPage------------\n%s\n--------------------------\n", $selector->html())); + $selector->filter(getenv("yamap.list.item.tag"))->each( + function (Crawler $node) use (&$listInfos): void { //bbs_item에서 span.g_nickname 객체를 찾아서 작성자가 "관리자" 아닌지 확인 후 Return Bool $nickname = $node->filter(getenv("yamap.list.item.nickname.tag"))->text(); $hit = $node->filter(getenv("yamap.list.item.hit.tag"))->text(); @@ -69,63 +118,100 @@ class YamapLibrary extends MyCrawlerLibrary $link_node = $node->filter(getenv("yamap.list.item.link.tag")); $detail_url = $link_node->attr("href"); $title = $link_node->children()->last()->text(); - $items[] = ['title' => $title, 'nickname' => $nickname, 'detail_url' => $detail_url, 'date' => $date, 'hit' => $hit]; + $listInfos[] = ['title' => $title, 'nickname' => $nickname, 'detail_url' => $detail_url, 'date' => $date, 'hit' => $hit]; } } ); - if (!count($items)) { + if (!count($listInfos)) { throw new \Exception("Target URL이 없습니다."); } log_message("notice", __FUNCTION__ . " 작업 완료"); - return $items; + return $listInfos; } - private function detailPage(array $itemInfo) + protected function save(string $url, string $mediaType, int $file_sequence): mixed { - $crawler = $this->getContent($itemInfo['detail_url'], getenv("yamap.view.content.tag")); - //3. Image 처리 - $myStorageLibrarys = $this->download("image", $crawler, ["tag" => "img", "attr" => "src"]); - //4. Video(mp4) 처리 - $myStorageLibrarys = $this->download("video", $crawler, ["tag" => "video", "attr" => "src"], $myStorageLibrarys); - //5.망보드 일반게시판에 게시물 등록 처리 - if (count($myStorageLibrarys)) { - $this->createBoard($itemInfo, $myStorageLibrarys); + $myStorageLibrary = parent::save($url, $mediaType, $file_sequence); + $content = ""; + //Board 게시판 image_path , content용 데이터 배열에 추가 후 modifyBoard에서 처리 + switch ($this->getMyStorage()->getOrintginType()) { + case "image": + $content = sprintf( + "\"%s\"", + $this->getMyStorage()->getPath(), + $this->getMyStorage()->getOriginName(), + $this->getMyStorage()->getOriginName() + ); + break; + case "video": + $content = sprintf( + "", + $this->getMyStorage()->getOriginName(), + $this->getMyStorage()->getPath(), + $this->getMyStorage()->getOriginName(), + $this->getMyStorage()->getMimeType(), + ); + break; } + log_message("debug", sprintf( + "\n--------%s--------\n%s\n--------------------\n", + __FUNCTION__, + $content + )); + $this->_media_tags["image_path"][] = sprintf("%s/%s", $this->getMyStorage()->getPath(), $this->getMyStorage()->getOriginName()); + $this->_media_tags["content"][] = $content; + return $myStorageLibrary; + } + + private function detailPage(array $listInfo): void + { + //1. Yamap ViewPage의 이미지나영상데이터가 있으면 + $response = $this->getMySocket()->getResponse($listInfo['detail_url']); + //1.망보드 일반게시판에 게시물 생성 처리 + $board_entity = $this->createBoard($listInfo); + $this->getMyStorage()->setBoardEntity($board_entity); + $this->_media_tags = ["image_path" => [], "content" => []]; + $selector = $this->getSelector($response, getenv("yamap.view.content.tag")); + //3. Image 처리 + log_message("debug", sprintf("\n-------------DetailPage------------\n%s\n--------------------------\n", $selector->html())); + $myStorageLibrarys = $this->download("image", $selector, ["tag" => "img", "attr" => "src"]); + //4. Video(mp4) 처리 + $myStorageLibrarys = $this->download("video", $selector, ["tag" => "video", "attr" => "src"], $myStorageLibrarys); + //5.망보드 일반게시판에 게시물 수정 처리 + $this->modifyBoard($board_entity); log_message("notice", __FUNCTION__ . " 작업 완료"); } public function execute(): void { - //. 해당사이트 MainPage 처리 - $itemInfos = []; if ($this->getDebug()) { - $itemInfos[] = [ - 'title' => getenv("yamap.view.test.title"), - 'nickname' => getenv("yamap.view.test.nickname"), + $listInfos = [ + 'title' => getenv("yamap.view.test.title"), + 'nickname' => getenv("yamap.view.test.nickname"), 'detail_url' => getenv("yamap.view.test.url"), - 'time' => date("Y-m-d H:i:s"), - 'hit' => 1 + 'time' => date("Y-m-d H:i:s"), + 'hit' => 1, ]; } else { - $itemInfos = $this->mainPage(getenv("yamap.list.url")); + $listInfos = $this->mainPage(getenv("yamap.list.url")); } - if (!count($itemInfos)) { - throw new \Exception("Yamap 사이트에서 게시물이 존재하지 않습니다."); - } - //Limit가 0이면 $itemInfos 갯수만큼 다하고, LIMIT 갯수 혹은 $items의 갯수중 작은수만큼 한다. + //Limit가 0이면 $listInfos 갯수만큼 다하고, LIMIT 갯수 혹은 item의 갯수중 작은수만큼 한다. $max_limit = intval(getenv("yamap.list.max_limit")); if ($max_limit) { - $max_limit = count($itemInfos) <= $max_limit ? count($itemInfos) : $max_limit; + $max_limit = count($listInfos) <= $max_limit ? count($listInfos) : $max_limit; } else { - $max_limit = count($itemInfos); + $max_limit = count($listInfos); } $i = 1; - foreach ($itemInfos as $itemInfo) { - if ($i < $max_limit) { + foreach ($listInfos as $listInfo) { + if ($i <= $max_limit) { try { - log_message("notice", "게시물 {$i}번째 {$itemInfo["nickname"]} 작업시작"); - $this->detailPage($itemInfo); - log_message("notice", "게시물 {$i}번째 {$itemInfo["nickname"]} 작업완료."); + log_message("notice", "게시물 {$i}번째 {$listInfo["nickname"]} 작업시작"); + $this->detailPage($listInfo); + log_message("notice", "게시물 {$i}번째 {$listInfo["nickname"]} 작업완료."); $i++; } catch (\Exception $e) { log_message("debug", $e->getMessage()); diff --git a/app/Libraries/MySocket/MySocketLibrary.php b/app/Libraries/MySocket/MySocketLibrary.php index fdb2311..9ba7473 100644 --- a/app/Libraries/MySocket/MySocketLibrary.php +++ b/app/Libraries/MySocket/MySocketLibrary.php @@ -13,7 +13,7 @@ abstract class MySocketLibrary extends CommonLibrary $this->_host = $host; } abstract public function getClient(); - final protected function getHost(): string + final public function getHost(): string { return $this->_host; } diff --git a/app/Libraries/MySocket/WebLibrary.php b/app/Libraries/MySocket/WebLibrary.php index c034751..3648be0 100644 --- a/app/Libraries/MySocket/WebLibrary.php +++ b/app/Libraries/MySocket/WebLibrary.php @@ -9,8 +9,7 @@ class WebLibrary extends MySocketLibrary { private $_client = null; private $_cookieJar = null; - - + private $_file_name = ""; public function __construct(string $host) { parent::__construct($host); @@ -38,18 +37,40 @@ class WebLibrary extends MySocketLibrary return strpos($url, 'http://') !== false || strpos($url, 'https://') !== false; } - public function getContent(string $url, array $options = []): string + public function getResponse(string $url, $type = "default"): string { //url에 http 나 https가 포함되어 있지않으면 if (!($this->isContainsHttpOrHttps($url))) { $url = $this->gethost() . $url; } + //기본 + $options = [ + 'cookies' => $this->getCookieJar(), + ]; + switch ($type) { + case 'agent': + // User-Agent 목록 배열 + $userAgents = [ + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1', + 'Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36' + ]; + // 배열에서 랜덤으로 하나의 User-Agent 선택 + $randomUserAgent = $userAgents[array_rand($userAgents)]; + $options['headers'] = [ + 'User-Agent' => $randomUserAgent, + ]; + break; + } log_message("debug", "Socket URL-> " . $url); $response = $this->getClient()->get($url, $options); if ($response->getStatusCode() != 200) { throw new \Exception("error", "{$url} 접속실패: " . $response->getStatusCode()); } - return $response->getBody()->getContents(); + // return $response->getBody()->getContents(); + return $response->getBody(); } // 로그인 메서드 @@ -74,24 +95,19 @@ class WebLibrary extends MySocketLibrary } } - // 파일 다운로드 메서드 - public function download(string $url): array + final public function getFileName(): string { - $fileNames = explode('/', $url); - if (!is_array($fileNames) || !count($fileNames)) { + return $this->_file_name; + } + final public function download(string $url): string + { + $file_names = explode('/', $url); + if (!is_array($file_names) || !count($file_names)) { throw new \Exception("Socket URL Error:" . $this->getHost() . $url); } - $fileName = array_pop($fileNames); - if (!$this->getDebug()) { - $content = $this->getContent($url, [ - 'cookies' => $this->getCookieJar(), - // 'sink' => $savePath, - ]); - if (!$content) { - throw new \Exception("{$fileName} 파일 다운로드 실패"); - } - log_message("notice", "{$fileName} 파일이 다운로드되었습니다!"); - } - return array($fileName, $content); + $this->_file_name = array_pop($file_names); + $response = $this->getResponse($url); + log_message("notice", "{$this->_file_name} 파일이 다운로드되었습니다!"); + return $response; } } diff --git a/app/Libraries/MyStorage/FileLibrary.php b/app/Libraries/MyStorage/FileLibrary.php index 30e04f5..ec9d2ea 100644 --- a/app/Libraries/MyStorage/FileLibrary.php +++ b/app/Libraries/MyStorage/FileLibrary.php @@ -38,35 +38,7 @@ class FileLibrary extends MyStorageLibrary { return $this->_fileSequence; } - final public function getMediaTag(): string - { - $mediaTag = ""; - switch ($this->getOrintginType()) { - case "image": - $mediaTag = sprintf( - "\"%s\"", - $this->getUploadPath(), - $this->getPath(), - $this->getOriginName(), - $this->getOriginName() - ); - break; - case "video": - $mediaTag = sprintf( - "", - $this->getOriginName(), - $this->getUploadPath(), - $this->getPath(), - $this->getOriginName(), - $this->getMimeType(), - ); - break; - } - return $mediaTag; - } + public function save(): static { $fullPath = WRITEPATH . $this->getUploadPath() . DIRECTORY_SEPARATOR . $this->getPath(); diff --git a/app/Libraries/MyStorage/Mangboard/FileLibrary.php b/app/Libraries/MyStorage/Mangboard/FileLibrary.php new file mode 100644 index 0000000..89e50a5 --- /dev/null +++ b/app/Libraries/MyStorage/Mangboard/FileLibrary.php @@ -0,0 +1,121 @@ +_imageLibrary = new SmallImageLibrary(); + $fullPath = WRITEPATH . $this->getUploadPath() . DIRECTORY_SEPARATOR . $this->getPath(); + $this->_imageLibrary->setDebug($this->getDebug()); + $this->_imageLibrary->setSourcePath($fullPath); + $this->_imageLibrary->setDestinationPath($fullPath); + } + public function getFileModel(): FileModel + { + if ($this->_file_model === null) { + return $this->_file_model = new FileModel(); + } + return $this->_file_model; + } + public function getFileEntity(): FileEntity + { + return $this->_file_entity; + } + private function setFileEntity(FileEntity $file_entity): void + { + $this->_file_entity = $file_entity; + } + public function getBoardName(): string + { + if ($this->_board_name === null) { + throw new \Exception("Board Name이 없습니다."); + } + return $this->_board_name; + } + public function setBoardName(string $board_name): void + { + $this->_board_name = $board_name; + } + public function getBoardTable(): string + { + if ($this->_board_table === null) { + throw new \Exception("Board Table이 없습니다."); + } + return $this->_board_table; + } + public function setBoardTable(string $board_table): void + { + $this->_board_table = $board_table; + } + public function getUserEntity(): UserEntity + { + if ($this->_user_entity === null) { + throw new \Exception("사용자정보가 없습니다."); + } + return $this->_user_entity; + } + public function setUserEntity(UserEntity $user_entity): void + { + $this->_user_entity = $user_entity; + } + public function getBoardEntity(): BoardEntity + { + return $this->_board_entity; + } + public function setBoardEntity(BoardEntity $board_entity): void + { + $this->_board_entity = $board_entity; + } + + public function save(): static + { + parent::save(); + //파일관리 table에 등록 + $formDatas = []; + //Board PID 넣기 + $formDatas['board_pid'] = $this->getBoardEntity()->getPk(); + //작은이미지생성후 Path/파일명 넣기 + $fileInfos = pathinfo($this->_imageLibrary->getDestinationPath() . DIRECTORY_SEPARATOR . $this->getOriginName(), PATHINFO_ALL); + $dstFile = $fileInfos['filename'] . "_small." . $fileInfos['extension']; + $this->_imageLibrary->setDestinationFile($dstFile); + $formDatas['file_path'] = $this->_imageLibrary->create($this->getOriginName()); + + $formDatas['user_pid'] = $this->getUserEntity()->getPK(); + $formDatas['user_name'] = $this->getUserEntity()->getTitle(); + $formDatas['board_name'] = $this->getBoardName(); + $formDatas['table_name'] = $this->getBoardTable(); + $formDatas['file_name'] = $this->getOriginName(); + $formDatas['file_type'] = $this->getMimeType(); + $formDatas['file_caption'] = $this->getOriginName(); + $formDatas['file_alt'] = $this->getOriginName(); + $formDatas['file_description'] = "Filedata"; + $formDatas['file_size'] = $this->getFileSize(); + $formDatas['file_sequence'] = $this->getOriginSequence(); + $formDatas['reg_date'] = date("Y-m-d H:i:s"); + $entity = $this->getFileModel()->create($formDatas); + log_message("notice", sprintf( + "%s %s번째 작업 완료", + __FUNCTION__, + $this->getOriginSequence() + )); + $this->setFileEntity($entity); + return $this; + } +} diff --git a/app/Libraries/MyStorage/Mangboard/SmallImageLibrary.php b/app/Libraries/MyStorage/Mangboard/SmallImageLibrary.php new file mode 100644 index 0000000..83d533b --- /dev/null +++ b/app/Libraries/MyStorage/Mangboard/SmallImageLibrary.php @@ -0,0 +1,82 @@ +getUploadPath() . DIRECTORY_SEPARATOR . $this->getPath(); + // $image = new ImageLibrary(); + // $image->setDebug($this->getDebug()); + // $image->setSourcePath($fullPath); + // $image->setDestinationPath($fullPath); + // //저장파일명 + // $fileInfos = pathinfo($image->getDestinationPath() . DIRECTORY_SEPARATOR . $this->getOriginName(), PATHINFO_ALL); + // $dstFile = $fileInfos['filename'] . "_small." . $fileInfos['extension']; + // $image->setDestinationFile($dstFile); + // $result = $image->create($this->getOriginName(), $width, $height); + // log_message("notice", sprintf( + // "%s %s번째:%s 작업 완료", + // __FUNCTION__, + // $this->getOriginSequence(), + // $this->getPath() + // )); + // //정석방식 + // // if ($result) { + // // if ($result) { + // // //작은이미지 생성후 목적지 Path와 파일명을 다시 file_path에 넣는다. URL이 되기때문에 /로 넣어야함 + // // return = sprintf( + // // "%s/%s", + // // $entity->getPath(), + // // $image->getDestinationFile() + // // )); + // // } else { + // // //원본이미지 생성후 목적지 Path와 파일명을 다시 file_path에 넣는다. URL이 되기때문에 /로 넣어야함 + // // return sprintf( + // // "%s/%s", + // // $entity->getPath(), + // // $this->getOriginName() + // // )); + // // } + // // } + // //망보드 방식 + // //mb_files에서 file_path가 망보드 게시판 파일관리에서 image로 표시되어 file_path+file_name로 설정 + // //원본이미지 생성후 목적지 Path와 파일명을 다시 file_path에 넣는다. URL이 되기때문에 /로 넣어야함 + // $this->_imagePath = sprintf("%s/%s", $this->getPath(), $this->getOriginName()); + // return $this; + // } + public function create(string $file, int $width = 480, int $height = 319): bool|string + { + try { + if (!$this->isFileType($this->getSourcePath(), $file)) { + throw new \Exception("{$file} Image 형식파일이 아닙니다."); + } + //저장할 디렉토리 생성 + $this->makeDirectory($this->getDestinationPath()); + // 이미지 파일 로드 + $this->load($this->getSourcePath() . DIRECTORY_SEPARATOR . $file); + // 200x200으로 이미지 크기 조정 + $this->resize($width, $height); + // 파일 저장 + $this->save($this->getDestinationPath() . DIRECTORY_SEPARATOR . $this->getDestinationFile()); + // 메모리 해제 + $this->destroy(); + log_message("debug", sprintf( + "%s %s->%s(W:%s,H:%s) 작업완료)", + __FUNCTION__, + $file, + $this->getDestinationFile(), + $width, + $height + )); + return sprintf("%s/%s", $this->getSourcePath(), $file); + } catch (\Exception $e) { + log_message("warning", $e->getMessage()); + return false; + } + } +} diff --git a/app/Libraries/MyStorage/MangboardFileLibrary.php b/app/Libraries/MyStorage/MangboardFileLibrary.php deleted file mode 100644 index 0cace68..0000000 --- a/app/Libraries/MyStorage/MangboardFileLibrary.php +++ /dev/null @@ -1,162 +0,0 @@ -_fileEntity; - } - private function setFileEntity(FileEntity $fileEntity): void - { - $this->_fileEntity = $fileEntity; - } - public function getModel(): FileModel - { - if ($this->_model === null) { - return $this->_model = new FileModel(); - } - return $this->_model; - } - public function getUser(): UserEntity - { - if ($this->_user === null) { - throw new \Exception("사용자정보가 없습니다."); - } - return $this->_user; - } - public function setUser(UserEntity $user): void - { - $this->_user = $user; - } - public function getBoardName(): string - { - if ($this->_boardName === null) { - throw new \Exception("BoardModel이 지정되지 않았습니다."); - } - return $this->_boardName; - } - public function setBoardName(string $boardName): void - { - $this->_boardName = $boardName; - } - public function getBoardTable(): string - { - if ($this->_boardTable === null) { - throw new \Exception("BoardModel이 지정되지 않았습니다."); - } - return $this->_boardTable; - } - public function setBoardTable(string $boardTable): void - { - $this->_boardTable = $boardTable; - } - public function getBoardLevel(): int - { - if ($this->_boardLevel === null) { - throw new \Exception("BoardModel Level이 지정되지 않았습니다."); - } - return intval($this->_boardLevel); - } - public function setBoardLevel(string $boardLevel): void - { - $this->_boardLevel = $boardLevel; - } - - //망보드 Board Table생성 후 관련된 mb_files Table에 Board번호를 넣기 위함 - public function setBoardPID(int $board_pid): void - { - $formDatas['board_pid'] = $board_pid; - $this->getModel()->modify($this->getFileEntity(), $formDatas); - log_message("notice", __FUNCTION__ . " 작업 완료"); - } - - //작은이미지 생성 - private function save_smallimage(int $width = 480, int $height = 319): string - { - $fullPath = WRITEPATH . $this->getUploadPath() . DIRECTORY_SEPARATOR . $this->getPath(); - $image = new ImageLibrary(); - $image->setDebug($this->getDebug()); - $image->setSourcePath($fullPath); - $image->setDestinationPath($fullPath); - //저장파일명 - $fileInfos = pathinfo($image->getDestinationPath() . DIRECTORY_SEPARATOR . $this->getOriginName(), PATHINFO_ALL); - $dstFile = $fileInfos['filename'] . "_small." . $fileInfos['extension']; - $image->setDestinationFile($dstFile); - $result = $image->create($this->getOriginName(), $width, $height); - log_message("notice", sprintf( - "%s %s번째:%s 작업 완료", - __FUNCTION__, - $this->getOriginSequence(), - $this->getPath() - )); - //정석방식 - // if ($result) { - // if ($result) { - // //작은이미지 생성후 목적지 Path와 파일명을 다시 file_path에 넣는다. URL이 되기때문에 /로 넣어야함 - // return = sprintf( - // "%s/%s", - // $entity->getPath(), - // $image->getDestinationFile() - // )); - // } else { - // //원본이미지 생성후 목적지 Path와 파일명을 다시 file_path에 넣는다. URL이 되기때문에 /로 넣어야함 - // return sprintf( - // "%s/%s", - // $entity->getPath(), - // $this->getOriginName() - // )); - // } - // } - //망보드 방식 - //mb_files에서 file_path가 망보드 게시판 파일관리에서 image로 표시되어 file_path+file_name로 설정 - //원본이미지 생성후 목적지 Path와 파일명을 다시 file_path에 넣는다. URL이 되기때문에 /로 넣어야함 - return sprintf("%s/%s", $this->getPath(), $this->getOriginName()); - } - - public function save(): static - { - parent::save(); - $formDatas = []; - //작은이미지생성후 Path/파일명 넣기 - $formDatas['file_path'] = $this->save_smallimage(); - $formDatas['user_pid'] = $this->getUser()->getPK(); - $formDatas['user_name'] = $this->getUser()->getTitle(); - $formDatas['board_name'] = $this->getBoardName(); - $formDatas['table_name'] = $this->getBoardTable(); - $formDatas['file_name'] = $this->getOriginName(); - $formDatas['file_type'] = $this->getMimeType(); - $formDatas['file_caption'] = $this->getOriginName(); - $formDatas['file_alt'] = $this->getOriginName(); - $formDatas['file_description'] = "Filedata"; - $formDatas['file_size'] = $this->getFileSize(); - $formDatas['file_sequence'] = $this->getOriginSequence(); - $formDatas['reg_date'] = date("Y-m-d H:i:s"); - //망보드 파일관리 table에 등록 - $entity = $this->getModel()->create($formDatas); - log_message("notice", sprintf( - "%s %s번째 작업 완료", - __FUNCTION__, - $this->getOriginSequence() - )); - $this->setFileEntity($entity); - return $this; - } -} diff --git a/app/Libraries/MyStorage/MyStorageLibrary.php b/app/Libraries/MyStorage/MyStorageLibrary.php index a86bef6..648d8ec 100644 --- a/app/Libraries/MyStorage/MyStorageLibrary.php +++ b/app/Libraries/MyStorage/MyStorageLibrary.php @@ -14,7 +14,7 @@ abstract class MyStorageLibrary extends CommonLibrary { parent::__construct(); } - abstract public function save(): mixed; + abstract public function save(): static; final public function getOriginName(): string { return $this->_originName; diff --git a/app/Libraries/MyUtil/ImageLibrary.php b/app/Libraries/MyUtil/ImageLibrary.php index fafb420..5ef586c 100644 --- a/app/Libraries/MyUtil/ImageLibrary.php +++ b/app/Libraries/MyUtil/ImageLibrary.php @@ -18,42 +18,42 @@ class ImageLibrary extends MyUtilLibrary parent::__construct(); } // 이미지의 현재 너비를 반환하는 메소드 - public function getSourcePath(): string + final public function getSourcePath(): string { return $this->_srcPath; } - public function setSourcePath(string $srcPath): void + final public function setSourcePath(string $srcPath): void { $this->_srcPath = $srcPath; } - public function getDestinationPath(): string + final public function getDestinationPath(): string { return $this->_dstPath; } - public function setDestinationPath(string $dstPath): void + final public function setDestinationPath(string $dstPath): void { $this->_dstPath = $dstPath; } - public function getDestinationFile(): string + final public function getDestinationFile(): string { return $this->_dstFile; } - public function setDestinationFile(string $dstFile): void + final public function setDestinationFile(string $dstFile): void { $this->_dstFile = $dstFile; } - public function getWidth() + final public function getWidth() { return imagesx($this->_image); } // 이미지의 현재 높이를 반환하는 메소드 - public function getHeight() + final public function getHeight() { return imagesy($this->_image); } // 이미지 파일을 로드하는 메소드 - private function load($file) + final protected function load($file) { $imageInfo = getimagesize($file); $this->_imageType = $imageInfo[2]; @@ -73,33 +73,33 @@ class ImageLibrary extends MyUtilLibrary } } // 이미지 크기를 지정된 너비, 높이로 변경하는 메소드 - private function resize($width, $height) + final protected function resize($width, $height) { $newImage = imagecreatetruecolor($width, $height); imagecopyresampled($newImage, $this->_image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight()); $this->_image = $newImage; } // 이미지 비율을 유지하면서 크기를 조정하는 메소드 - private function resizeToWidth($width) + final protected function resizeToWidth($width) { $ratio = $width / $this->getWidth(); $height = $this->getHeight() * $ratio; $this->resize($width, $height); } - private function resizeToHeight($height) + final protected function resizeToHeight($height) { $ratio = $height / $this->getHeight(); $width = $this->getWidth() * $ratio; $this->resize($width, $height); } - private function scale($scale) + final protected function scale($scale) { $width = $this->getWidth() * ($scale / 100); $height = $this->getHeight() * ($scale / 100); $this->resize($width, $height); } // 이미지를 저장하는 메소드 - private function save($file, $imageType = IMAGETYPE_WEBP, $compression = 75) + final protected function save($file, $imageType = IMAGETYPE_WEBP, $compression = 75) { switch ($imageType) { case IMAGETYPE_JPEG: @@ -118,39 +118,8 @@ class ImageLibrary extends MyUtilLibrary } } // 메모리 해제를 위한 메소드 - private function destroy() + final protected function destroy() { imagedestroy($this->_image); } - - public function create(string $file, int $width = 480, int $height = 319): bool - { - try { - if (!$this->isFileType($this->getSourcePath(), $file)) { - throw new \Exception("{$file} Image 형식파일이 아닙니다."); - } - //저장할 디렉토리 생성 - $this->makeDirectory($this->getDestinationPath()); - // 이미지 파일 로드 - $this->load($this->getSourcePath() . DIRECTORY_SEPARATOR . $file); - // 200x200으로 이미지 크기 조정 - $this->resize($width, $height); - // 파일 저장 - $this->save($this->getDestinationPath() . DIRECTORY_SEPARATOR . $this->getDestinationFile()); - // 메모리 해제 - $this->destroy(); - log_message("debug", sprintf( - "%s %s->%s(W:%s,H:%s) 작업완료)", - __FUNCTION__, - $file, - $this->getDestinationFile(), - $width, - $height - )); - return true; - } catch (\Exception $e) { - log_message("warning", $e->getMessage()); - return false; - } - } } diff --git a/app/Models/CommonModel.php b/app/Models/CommonModel.php index 52238e6..c749bb5 100644 --- a/app/Models/CommonModel.php +++ b/app/Models/CommonModel.php @@ -138,6 +138,15 @@ abstract class CommonModel extends Model //create , modify 직전 작업용 작업 final protected function convertEntityData(string $field, array $formDatas): string|int { + if ($formDatas[$field] === null) { + throw new \Exception( + sprintf( + "\n-------%s FormDatas 오류--------\n%s\n-----------------------\n", + __FUNCTION__, + var_export($formDatas, true) + ) + ); + } switch ($field) { case $this->getPKField(): //$formDatas에 전달된 값이 없는경우 diff --git a/app/Models/Mangboard/BoardModel.php b/app/Models/Mangboard/BoardModel.php index 038969e..f520806 100644 --- a/app/Models/Mangboard/BoardModel.php +++ b/app/Models/Mangboard/BoardModel.php @@ -110,7 +110,8 @@ class BoardModel extends CommonModel $rules[$field] = "if_exist|valid_date"; break; case "content": - $rules[$field] = "required|trim|string"; + case "image_path": + $rules[$field] = "if_exist|trim|string"; break; case 'hit': case 'level': diff --git a/app/Models/Mangboard/FileModel.php b/app/Models/Mangboard/FileModel.php index c7e3945..296feb4 100644 --- a/app/Models/Mangboard/FileModel.php +++ b/app/Models/Mangboard/FileModel.php @@ -73,12 +73,12 @@ class FileModel extends CommonModel case "file_name": case "file_path": case "file_type": - $rules[$field] = "required|trim|string"; + $rules[$field] = "required|string"; break; case "file_description": case "file_caption": case "file_alt": - $rules[$field] = "if_exist|trim|string"; + $rules[$field] = "if_exist|string"; break; case "reg_date": $rules[$field] = "if_exist|valid_date";