<?php
/*
* Copyright (C) 2018 SPREAD WORKS Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Plugin\TabaBannerManager2\Controller;
use Eccube\Application;
use Eccube\Controller\AbstractController;
use Eccube\Common\Constant;
use Plugin\TabaBannerManager2\Common\Constants;
use Plugin\TabaBannerManager2\Entity\Area;
use Plugin\TabaBannerManager2\Entity\Banner;
use Plugin\TabaBannerManager2\Repository\AreaRepository;
use Plugin\TabaBannerManager2\Repository\BannerRepository;
use Plugin\TabaBannerManager2\Form\Type\AreaType;
use Plugin\TabaBannerManager2\Form\Type\BannerType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
/**
* 管理画面用コントローラー
*
* @Route(Plugin\TabaBannerManager2\Common\Constants::ADMIN_URI_PREFIX,name=Plugin\TabaBannerManager2\Common\Constants::ADMIN_BIND_PREFIX)
*/
class AdminController extends AbstractController
{
/**
* @var AreaRepository
*/
private $areaRepo;
/**
* @var BannerRepository
*/
private $bannerRepo;
/**
* @var CsrfTokenManagerInterface
*/
protected $csrfTokenManager;
/**
*
* @param AreaRepository $areaRepo
* @param BannerRepository $bannerRepo
* @param CsrfTokenManagerInterface $csrfTokenManager
*/
public function __construct(AreaRepository $areaRepo, BannerRepository $bannerRepo, CsrfTokenManagerInterface $csrfTokenManager)
{
$this->areaRepo = $areaRepo;
$this->bannerRepo = $bannerRepo;
$this->csrfTokenManager = $csrfTokenManager;
}
/**
* index
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
*
* @Route("/",name="_index")
*/
public function index(Request $request)
{
return $this->redirectToRoute(Constants::ADMIN_BIND_PREFIX . '_area_list');
}
/**
* バナーエリア / リスト
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
*
* @Route("/area_list",name="_area_list")
* @Template("@TabaBannerManager2/admin/area_list.twig")
*/
public function area_list(Request $request)
{
$list = $this->areaRepo->getList();
return [
'list' => $list
];
}
/**
* バナーエリア / 新規登録・編集
*
* @param Request $request
* @param integer $area_id
* @return \Symfony\Component\HttpFoundation\Response
*
* @Route("/area_edit",name="_area_new")
* @Route("/area_edit/{area_id}",name="_area_edit",requirements={"area_id" = "\d+"})
* @Template("@TabaBannerManager2/admin/area_edit.twig")
*/
public function area_edit(Request $request, $area_id = null)
{
$area = null;
if ($area_id) {
if (! ($area = $this->areaRepo->find($area_id))) {
throw new NotFoundHttpException();
}
} else {
$area = new Area(true);
}
// フォームの生成
$builder = $this->formFactory->createBuilder(AreaType::class, $area);
$form = $builder->getForm();
// 登録・変更実行
if ('POST' === $request->getMethod()) {
// データキーが入力されていない場合
// 値を生成しリクエスト値にセットします。
$params = $request->request->all();
if (empty($params[$form->getName()]['data_key'])) {
$data_key = "area";
$id = $this->areaRepo->getMaxAreaId() + 1;
for ($i = $id; $i <= 1000 + $id; $i) {
if (! $this->areaRepo->getList(array(
'data_key' => $data_key . "_" . $i
))) {
$data_key = $data_key . "_" . $i;
break;
}
}
$params[$form->getName()]['data_key'] = $data_key;
$request->request->replace($params);
}
$form->handleRequest($request);
if ($form->isValid()) {
// $data = $form->getData();
if ($this->areaRepo->save($area)) {
$this->addSuccess('admin.common.save_complete', 'admin');
return $this->redirectToRoute(Constants::ADMIN_BIND_PREFIX . '_area_edit', array(
'area_id' => $area->getAreaId()
));
} else {
$this->addError('admin.common.save_error', 'admin');
}
} else {
$this->addError('admin.common.save_error', 'admin');
}
}
return [
'form' => $form->createView(),
'area' => $area
];
}
/**
* バナーエリア / 削除
*
* @param Application $app
* @param Request $request
* @param integer $area_id
* @return \Symfony\Component\HttpFoundation\Response
*
* @Route("/area_delete/{area_id}",name="_area_delete",requirements={"area_id" = "\d+"})
*/
public function area_delete(Request $request, $area_id)
{
// バナーエリア操作オブジェクトの生成
$status = false;
if (! empty($area_id) && ($area = $this->areaRepo->find($area_id))) {
$status = $this->areaRepo->delete($area);
} else {
throw new NotFoundHttpException();
}
if ($status) {
$this->addSuccess('admin.common.delete_complete', 'admin');
} else {
$this->addError('admin.common.delete_error', 'admin');
}
return $this->redirectToRoute(Constants::ADMIN_BIND_PREFIX . '_area_list');
}
/**
* バナー / リスト
*
* @param Application $app
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
*
* @Route("/banner_list/{area_id}",name="_banner_list",requirements={"area_id" = "\d+"})
* @Template("@TabaBannerManager2/admin/banner_list.twig")
*/
public function banner_list(Request $request, $area_id)
{
// バナーエリア取得
$area = null;
if (! ($area = $this->areaRepo->find($area_id))) {
throw new NotFoundHttpException();
}
// バナーリスト取得
$list = $this->bannerRepo->getList($area_id);
return [
'csrf_token' => $this->csrfTokenManager->getToken(Constant::TOKEN_NAME)->getValue(),
'area' => $area,
'list' => $list
];
}
/**
* バナー / 新規登録・編集
*
* @param Application $app
* @param Request $request
* @param integer $id
* @return \Symfony\Component\HttpFoundation\Response
*
* @Route("/banner_edit/{area_id}",name="_banner_new",requirements={"area_id" = "\d+"})
* @Route("/banner_edit/{area_id}/{banner_id}",name="_banner_edit",requirements={"area_id" = "\d+","banner_id" = "\d+"})
* @Template("@TabaBannerManager2/admin/banner_edit.twig")
*/
public function banner_edit(Request $request, $area_id, $banner_id = null)
{
// バナーエリア取得
$area = null;
if (! ($area = $this->areaRepo->find($area_id))) {
throw new NotFoundHttpException();
}
// バナー操作オブジェクトの生成
$banner = null;
if ($banner_id) {
if (! ($banner = $this->bannerRepo->find($banner_id))) {
throw new NotFoundHttpException();
}
} else {
$banner = new Banner(true);
}
$banner->setArea($area);
$originBannerFileName = $banner->getBannerFileName();
$originBannerFileName2 = $banner->getBannerFileName2();
$originBannerFileName3 = $banner->getBannerFileName3();
$originBannerFileName4 = $banner->getBannerFileName4();
$originBannerFileName5 = $banner->getBannerFileName5();
$imageEdited = false; // 画像編集済みかチェックするフラグ
// フォームの生成
$builder = $this->formFactory->createBuilder(BannerType::class, $banner);
$form = $builder->getForm();
// 登録・変更実行
if ('POST' === $request->getMethod()) {
$form->handleRequest($request);
//
// 画像 1
//
if ($originBannerFileName != $banner->getBannerFileName()) $imageEdited = true;
if ($form->isValid()) {
$imageEdited = false;
if ($this->bannerRepo->save($banner)) {
//
// 画像 1
//
// 画像を移動
if (!empty($banner->getBannerFileName()) && file_exists($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $banner->getBannerFileName())) {
rename($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $banner->getBannerFileName(), $this->eccubeConfig['eccube_save_image_dir'] . '/' . $banner->getBannerFileName());
}
// 画像削除
$oldPath = $newPath = null;
if ($originBannerFileName) $oldPath = $this->eccubeConfig['eccube_save_image_dir'] . '/' . $originBannerFileName;
if ($banner->getBannerFileName()) $newPath = $this->eccubeConfig['eccube_save_image_dir'] . '/' . $banner->getBannerFileName();
if (!$banner->getBannerFileName()) {
if (file_exists($newPath)) unlink($newPath);
if (file_exists($oldPath)) unlink($oldPath);
} else if ($originBannerFileName != $banner->getBannerFileName()) {
if (file_exists($oldPath)) unlink($oldPath);
}
//
// 画像 2
//
// 画像を移動
if (!empty($banner->getBannerFileName2()) && file_exists($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $banner->getBannerFileName2())) {
rename($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $banner->getBannerFileName2(), $this->eccubeConfig['eccube_save_image_dir'] . '/' . $banner->getBannerFileName2());
}
// 画像削除
$oldPath = $newPath = null;
if ($originBannerFileName2) $oldPath = $this->eccubeConfig['eccube_save_image_dir'] . '/' . $originBannerFileName2;
if ($banner->getBannerFileName2()) $newPath = $this->eccubeConfig['eccube_save_image_dir'] . '/' . $banner->getBannerFileName2();
if (!$banner->getBannerFileName2()) {
if (file_exists($newPath)) unlink($newPath);
if (file_exists($oldPath)) unlink($oldPath);
} else if ($originBannerFileName2 != $banner->getBannerFileName2()) {
if (file_exists($oldPath)) unlink($oldPath);
}
//
// 画像 3
//
// 画像を移動
if (!empty($banner->getBannerFileName3()) && file_exists($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $banner->getBannerFileName3())) {
rename($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $banner->getBannerFileName3(), $this->eccubeConfig['eccube_save_image_dir'] . '/' . $banner->getBannerFileName3());
}
// 画像削除
$oldPath = $newPath = null;
if ($originBannerFileName3) $oldPath = $this->eccubeConfig['eccube_save_image_dir'] . '/' . $originBannerFileName3;
if ($banner->getBannerFileName3()) $newPath = $this->eccubeConfig['eccube_save_image_dir'] . '/' . $banner->getBannerFileName3();
if (!$banner->getBannerFileName3()) {
if (file_exists($newPath)) unlink($newPath);
if (file_exists($oldPath)) unlink($oldPath);
} else if ($originBannerFileName3 != $banner->getBannerFileName3()) {
if (file_exists($oldPath)) unlink($oldPath);
}
//
// 画像 4
//
// 画像を移動
if (!empty($banner->getBannerFileName4()) && file_exists($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $banner->getBannerFileName4())) {
rename($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $banner->getBannerFileName4(), $this->eccubeConfig['eccube_save_image_dir'] . '/' . $banner->getBannerFileName4());
}
// 画像削除
$oldPath = $newPath = null;
if ($originBannerFileName4) $oldPath = $this->eccubeConfig['eccube_save_image_dir'] . '/' . $originBannerFileName4;
if ($banner->getBannerFileName4()) $newPath = $this->eccubeConfig['eccube_save_image_dir'] . '/' . $banner->getBannerFileName4();
if (!$banner->getBannerFileName4()) {
if (file_exists($newPath)) unlink($newPath);
if (file_exists($oldPath)) unlink($oldPath);
} else if ($originBannerFileName4 != $banner->getBannerFileName4()) {
if (file_exists($oldPath)) unlink($oldPath);
}
//
// 画像 5
//
// 画像を移動
if (!empty($banner->getBannerFileName5()) && file_exists($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $banner->getBannerFileName5())) {
rename($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $banner->getBannerFileName5(), $this->eccubeConfig['eccube_save_image_dir'] . '/' . $banner->getBannerFileName5());
}
// 画像削除
$oldPath = $newPath = null;
if ($originBannerFileName5) $oldPath = $this->eccubeConfig['eccube_save_image_dir'] . '/' . $originBannerFileName5;
if ($banner->getBannerFileName5()) $newPath = $this->eccubeConfig['eccube_save_image_dir'] . '/' . $banner->getBannerFileName5();
if (!$banner->getBannerFileName5()) {
if (file_exists($newPath)) unlink($newPath);
if (file_exists($oldPath)) unlink($oldPath);
} else if ($originBannerFileName5 != $banner->getBannerFileName5()) {
if (file_exists($oldPath)) unlink($oldPath);
}
$this->addSuccess('admin.common.save_complete', 'admin');
return $this->redirectToRoute(Constants::ADMIN_BIND_PREFIX . '_banner_edit', [
'area_id' => $area_id,
'banner_id' => $banner->getBannerId()
]);
} else {
$this->addError('admin.common.save_error', 'admin');
}
}
}
return [
'csrf_token' => $this->csrfTokenManager->getToken(Constant::TOKEN_NAME)->getValue(),
'form' => $form->createView(),
'area' => $area,
'banner' => $banner,
'image_edited' => $imageEdited,
];
}
/**
* バナー / 削除
*
* @param Application $app
* @param Request $request
* @param integer $banner_id
* @return \Symfony\Component\HttpFoundation\Response
*
* @Route("/banner_delete/{banner_id}",name="_banner_delete",requirements={"banner_id" = "\d+"})
*/
public function banner_delete(Request $request, $banner_id = null)
{
// バナーエリア操作オブジェクトの生成
$status = false;
$banner = $this->bannerRepo->find($banner_id);
$area_id = $banner->getAreaId();
if (! empty($banner)) {
$status = $this->bannerRepo->delete($banner);
} else {
throw new NotFoundHttpException();
}
if ($status) {
$this->addSuccess('admin.common.delete_complete', 'admin');
} else {
$this->addError('admin.common.delete_error', 'admin');
}
return $this->redirectToRoute(Constants::ADMIN_BIND_PREFIX . '_banner_list', [
'area_id' => $area_id
]);
}
/**
* バナー画像アップロード
*
* @param Request $request
* @throws BadRequestHttpException
* @throws UnsupportedMediaTypeHttpException
* @return \Symfony\Component\HttpFoundation\Response
*
* @Route("/banner_upload",name="_banner_upload")
*/
public function banner_upload(Request $request)
{
// CSRF
if (!$this->csrfTokenManager->isTokenValid(new CsrfToken(Constant::TOKEN_NAME, $request->get(Constant::TOKEN_NAME)))) {
throw new AccessDeniedHttpException('CSRF token is invalid.');
}
// XMLHttpRequest
if (! $request->isXmlHttpRequest()) {
throw new BadRequestHttpException('Request is invalid.');
}
$files = $request->files->get(Constants::PLUGIN_CODE_LC . '_banner');
$file_name = null;
if (count($files) > 0) {
foreach ($files as $file) {
// log_debug("[FILE OBJECT] " . print_r($file, true));
if (0 !== strpos($file->getMimeType(), 'image')) {
throw new UnsupportedMediaTypeHttpException('File format is invalid.');
}
$extension = $file->getClientOriginalExtension();
$file_name = date('mdHis') . uniqid('_') . '.' . $extension;
$file->move($this->eccubeConfig['eccube_temp_image_dir'], $file_name);
break;
}
}
return new JsonResponse(array(
'file' => $file_name
));
}
/**
* バナー / ソート
*
* @param Request $request
* @param integer $area_id
* @return \Symfony\Component\HttpFoundation\Response
*
* @Route("/banner_sort/{area_id}",name="_banner_sort",requirements={"area_id" = "\d+"})
*/
public function banner_sort(Request $request, $area_id)
{
// CSRF
if (! $this->csrfTokenManager->isTokenValid(new CsrfToken(Constant::TOKEN_NAME, $request->get(Constant::TOKEN_NAME)))) {
throw new AccessDeniedHttpException('CSRF token is invalid.');
}
// XMLHttpRequest
if (! $request->isXmlHttpRequest()) {
throw new BadRequestHttpException('Request is invalid.');
}
$params = $request->request->all();
if (!empty($area_id) && isset($params['banner_ids']) && is_array($params['banner_ids'])) {
if (! ($this->areaRepo->find($area_id))) {
throw new NotFoundHttpException();
}
$no = 1;
foreach ($params['banner_ids'] as $banner_id) {
$banner = $this->bannerRepo->find($banner_id);
$banner->setOrderNo($no ++);
if (! ($this->bannerRepo->save($banner))) {
log_debug("順番の更新が出来ませんでした");
}
}
} else {
throw new BadRequestHttpException('必要なパラメーターが取得できません');
}
return new JsonResponse([]);
}
/**
* 各種ファイルを出力します。
*
* @param Request $request
* @param string $file
* @throws NotFoundHttpException
* @return BinaryFileResponse
*
* @Route("/assets/{file}",name="_assets",requirements={"file" = "[a-zA-Z0-9-_/\s.]+"})
*/
public function assets(Request $request,$file) {
if (strpos($file,'..')) {
log_critical("ディレクトリトラバーサル攻撃の可能性があります。 [FILE] " . $file);
throw new NotFoundHttpException();
}
$file = Constants::TEMPLATE_PATH . DIRECTORY_SEPARATOR . "admin" . DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . $file;
if (file_exists($this->eccubeConfig['plugin_realdir'] . DIRECTORY_SEPARATOR . $file)) {
log_debug("[ASSETS] [FILE] " . $file);
// 拡張子によりMIMEを設定します。
$suffixes = explode(".",$file);
$suffix = end($suffixes);
$suffix_def = array(
"jpeg" => "image/jpg",
"jpg" => "image/jpg",
"gif" => "image/gif",
"png" => "image/png",
"svg" => "image/svg+xml",
"js" => "application/x-javascript",
"css" => "text/css",
);
if (in_array($suffix,array_keys($suffix_def))) {
$response = new BinaryFileResponse($this->eccubeConfig['plugin_realdir'] . DIRECTORY_SEPARATOR . $file);
$response->headers->set('Content-Type',$suffix_def[$suffix]);
return $response;
} else {
throw new NotFoundHttpException();
}
} else {
throw new NotFoundHttpException();
}
}
}