<?php
namespace Plugin\CustomGMC\Controller\Admin;
use Eccube\Controller\AbstractController;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Repository\CategoryRepository;
use Eccube\Repository\Master\PageMaxRepository;
use Eccube\Repository\ProductRepository;
use Eccube\Repository\TaxRuleRepository;
use Eccube\Util\CacheUtil;
use Eccube\Util\FormUtil;
use Knp\Component\Pager\Paginator;
use Knp\Component\Pager\PaginatorInterface;
use PharIo\Manifest\Url;
use Plugin\CustomGMC\Form\Type\Admin\SearchProductType;
use Plugin\CustomGMC\Repository\ConfigRepository;
use Plugin\CustomGMC\Utils\Constants;
use Plugin\CustomGMC\Repository\ProductRepository as CustomGMCProductRepository;
use Plugin\CustomGMC\Services\HandleTokenExpiredService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class ProductController extends AbstractController
{
/**
* @var ConfigRepository
*/
protected $configRepository;
/**
* @var TaxRuleRepository
*/
protected $taxRuleRepository;
/**
* @var ProductRepository
*/
protected $productRepository;
/**
* @var PageMaxRepository
*/
protected $pageMaxRepository;
/**
* @var HandleTokenExpiredService
*/
protected $handleTokenExpiredService;
protected $customGMCProductRepository;
/**
* ConfigController constructor.
*
* @param ConfigRepository $configRepository
* @param CategoryRepository $categoryRepository
* @param ProductRepository $productRepository
* @param PageMaxRepository $pageMaxRepository
* @param HandleTokenExpiredService $handleTokenExpiredService
*/
public function __construct(
ConfigRepository $configRepository,
TaxRuleRepository $taxRuleRepository,
ProductRepository $productRepository,
PageMaxRepository $pageMaxRepository,
HandleTokenExpiredService $handleTokenExpiredService,
CustomGMCProductRepository $customGMCProductRepository
){
$this->taxRuleRepository = $taxRuleRepository;
$this->productRepository = $productRepository;
$this->pageMaxRepository = $pageMaxRepository;
$this->configRepository = $configRepository->get();
$this->handleTokenExpiredService = $handleTokenExpiredService;
$this->customGMCProductRepository = $customGMCProductRepository;
}
/**
* @Route("/%eccube_admin_route%/custom_gmc/product", name="custom_gmc_admin_product")
* @Route("/%eccube_admin_route%/custom_gmc/product/page/{page_no}", requirements={"page_no" = "\d+"}, name="custom_gmc_admin_product_page")
* @Template("@CustomGMC/admin/Product/list.twig")
*/
public function index(Request $request, $page_no = null, PaginatorInterface $paginator)
{
if (!$this->handleTokenExpiredService->tokenIsValid()) {
$this->addError('admin.gmc.token_expired', 'admin');
return $this->redirectToRoute('custom_gmc_admin_auth');
}
$builder = $this->formFactory
->createBuilder(SearchProductType::class);
$event = new EventArgs(
[
'builder' => $builder,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::ADMIN_PRODUCT_INDEX_INITIALIZE);
$searchForm = $builder->getForm();
/**
* ページの表示件数は, 以下の順に優先される.
* - リクエストパラメータ
* - セッション
* - デフォルト値
* また, セッションに保存する際は mtb_page_maxと照合し, 一致した場合のみ保存する.
**/
$page_count = $this->session->get(
'eccube.admin.product.search.page_count',
$this->eccubeConfig->get('eccube_default_page_count')
);
$page_count_param = (int) $request->get('page_count');
$pageMaxis = $this->pageMaxRepository->findAll();
if ($page_count_param) {
foreach ($pageMaxis as $pageMax) {
if ($page_count_param == $pageMax->getName()) {
$page_count = $pageMax->getName();
$this->session->set('eccube.admin.product.search.page_count', $page_count);
break;
}
}
}
if ('POST' === $request->getMethod()) {
$searchForm->handleRequest($request);
if ($searchForm->isValid()) {
/**
* 検索が実行された場合は, セッションに検索条件を保存する.
* ページ番号は最初のページ番号に初期化する.
*/
$page_no = 1;
$searchData = $searchForm->getData();
// 検索条件, ページ番号をセッションに保持.
$this->session->set('eccube.admin.product.search', FormUtil::getViewData($searchForm));
$this->session->set('eccube.admin.product.search.page_no', $page_no);
} else {
// 検索エラーの際は, 詳細検索枠を開いてエラー表示する.
return [
'searchForm' => $searchForm->createView(),
'pagination' => [],
'pageMaxis' => $pageMaxis,
'page_no' => $page_no,
'page_count' => $page_count,
'has_errors' => true,
];
}
} else {
if (null !== $page_no || $request->get('resume')) {
/*
* ページ送りの場合または、他画面から戻ってきた場合は, セッションから検索条件を復旧する.
*/
if ($page_no) {
// ページ送りで遷移した場合.
$this->session->set('eccube.admin.product.search.page_no', (int) $page_no);
} else {
// 他画面から遷移した場合.
$page_no = $this->session->get('eccube.admin.product.search.page_no', 1);
}
$viewData = $this->session->get('eccube.admin.product.search', []);
$searchData = FormUtil::submitAndGetData($searchForm, $viewData);
} else {
/**
* 初期表示の場合.
*/
$page_no = 1;
// submit default value
$viewData = FormUtil::getViewData($searchForm);
$searchData = FormUtil::submitAndGetData($searchForm, $viewData);
// セッション中の検索条件, ページ番号を初期化.
$this->session->set('eccube.admin.product.search', $viewData);
$this->session->set('eccube.admin.product.search.page_no', $page_no);
}
}
$qb = $this->customGMCProductRepository->getQueryBuilderBySearchDataForAdmin($searchData);
$event = new EventArgs(
[
'qb' => $qb,
'searchData' => $searchData,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::ADMIN_PRODUCT_INDEX_SEARCH);
$pagination = $paginator->paginate(
$qb,
$page_no,
$page_count
);
return [
'searchForm' => $searchForm->createView(),
'pagination' => $pagination,
'pageMaxis' => $pageMaxis,
'page_no' => $page_no,
'page_count' => $page_count,
'has_errors' => false,
];
}
/**
* Bulk public action
*
* @Route("/%eccube_admin_route%/product/bulk/gmc", name="admin_product_bulk_to_gmc", methods={"POST"})
*
* @param Request $request
* @param ProductStatus $ProductStatus
*
* @return RedirectResponse
*/
public function sendProductsToGMC(Request $request, CacheUtil $cacheUtil)
{
$this->isTokenValid();
if (!$this->handleTokenExpiredService->tokenIsValid()) {
$this->addError('admin.gmc.token_expired', 'admin');
return $this->redirectToRoute('custom_gmc_admin_auth');
}
try {
$url = Constants::GOOGLE_SHOPPING_API_URL.$this->configRepository->getMerchantId().'/products';
// CURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Accept: application/json',
'Authorization: Bearer ' . $this->session->get('gmc_access_token')
));
/** @var Product[] $Products */
$Products = $this->productRepository->findBy(['id' => $request->get('ids')]);
foreach ($Products as $key => $Product) {
// Update product status to GMC
if ($Product->getGMCProductId()) {
$url = $url.'/'.$Product->getGMCProductId();
curl_setopt($ch, CURLOPT_URL, $url);
$data = array(
'title' => $Product->getName(),
'description' => $Product->getDescriptionDetail(),
'imageLink' => $request->getUriForPath('/html/upload/save_image/'.$Product->getMainFileName()),
'price' => array(
'value' => $Product->getPrice02Max(),
'currency' => 'JPY',
),
);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
} else {
// Insert product to GMC
$data = array(
'kind' => "content#product",
'title' => $Product->getName(),
'description' => $Product->getDescriptionDetail(),
"link" => $request->getUriForPath($this->generateUrl('product_detail', ['id' => $Product->getId()])),
'offerId' => $Product->getId(),
'imageLink' => $request->getUriForPath('/html/upload/save_image/'.$Product->getMainFileName()),
'contentLanguage' => 'JA',
'targetCountry' => 'JP',
'channel' => "online",
'availability' => "in stock",
'condition' => 'new',
'price' => array(
'value' => $Product->getPrice02Max(),
'currency' => 'JPY',
),
);
curl_setopt($ch, CURLOPT_POST, true);
}
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$result = json_decode(curl_exec ($ch));
if (isset($result->error)) { /* Handle error */
$this->addError($result->error->message, 'admin');
} else {
if ($result && isset($result->id)) {
$Product->setGMCProductId($result->id);
$this->productRepository->save($Product);
$this->entityManager->flush();
$this->addSuccess('admin.gmc.send_product.success', 'admin');
}
$cacheUtil->clearDoctrineCache();
}
}
} catch (\Exception $e) {
$this->addError($e->getMessage(), 'admin');
}
return $this->redirectToRoute('custom_gmc_admin_product');
}
/**
* Bulk public action
*
* @Route("/%eccube_admin_route%/product/bulk/gmc/{id}/delete", name="admin_product_bulk_delete_to_gmc", methods={"DELETE"})
*
* @param Request $request
* @param ProductStatus $ProductStatus
*
* @return RedirectResponse
*/
public function bulkDeleteProducts(Request $request, $id = null, CacheUtil $cacheUtil)
{
$this->isTokenValid();
if (!$this->handleTokenExpiredService->tokenIsValid()) {
$this->addError('admin.gmc.token_expired', 'admin');
return $this->redirectToRoute('custom_gmc_admin_auth');
}
try {
$url = Constants::GOOGLE_SHOPPING_API_URL.$this->configRepository->getMerchantId().'/products';
// CURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Accept: application/json',
'Authorization: Bearer ' . $this->session->get('gmc_access_token')
));
/** @var Product[] $Products */
$Product = $this->productRepository->find($id);
// Update product status to GMC
$result = null;
$success = true;
$message = '';
if ($Product->getGMCProductId()) {
$url = $url.'/'.$Product->getGMCProductId();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
$result = json_decode(curl_exec ($ch));
if (isset($result->error)) { /* Handle error */
$message = $result->error->message;
$success = false;
$this->addError($result->error->message, 'admin');
} else {
$Product->setGMCProductId('');
$this->productRepository->save($Product);
$this->entityManager->flush();
$this->addSuccess('admin.gmc.delete_product.success', 'admin');
$cacheUtil->clearDoctrineCache();
}
} else {
$success = false;
$message = trans('admin.gmc.delete_product.not_found');
$this->addError('admin.gmc.delete_product.not_found', 'admin');
}
} catch (\Exception $e) {
$success = false;
$message = $e->getMessage();
}
return $this->json(['success' => $success, 'message' => $message]);
}
}