<?php
namespace AppBundle\Controller\Admin\Base;
use AppBundle\Doctrine\Filter\PostTypeFilter;
use AppBundle\Service\ContentManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Query\FilterCollection;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\DependencyInjection\Container;
use AppBundle\Component\PageBuilder\PageBuilder;
use Doctrine\ORM\EntityNotFoundException;
use AppBundle\Controller\Admin\Base\FacilityBaseController;
use Symfony\Component\Form\Extension\Core\Type;
use AppBundle\Entity\Master\Facility;
class FacilityArticleBaseController extends FacilityBaseController
{
protected function buildSearchForm($data = [], $params = [])
{
$settings = $this->entity_settings;
$form = parent::buildSearchForm($data, $params);
if($settings->get('relations.category')){
$category_class = $this->models['category'];
$repo = $this->getDoctrine()->getRepository($category_class);
$criteria = [];
if ($this->entity_settings->isMultilingual()) {
$criteria['language_alias'] = $this->container->getParameter('language.default', 'jp');
}
$categories = $repo->findBy($criteria, ['sort_num' => 'ASC', 'id' => 'ASC']);
$categoryList = [];
foreach($categories as $category){
$categoryList[$category->getTitle()] = $category->getId();
}
$form->add('category', Type\ChoiceType::class, [
'required' => false,
'label' => 'カテゴリー:',
'choices' => $categoryList,
'placeholder' => '(指定なし)',
'attr' => [
'class' => 'form-control form-control-inline'
],
'label_attr' => [
'class' => null
]
]);
}
return $form;
}
/**
* @param FilterControllerEvent $event
* @throws EntityNotFoundException
*/
public function before(FilterControllerEvent $event)
{
parent::before($event);
}
/**
* @param string $action
* @param FilterControllerEvent $event
* @throws NotFoundHttpException
*/
protected function beforeActionCheck($action, FilterControllerEvent $event)
{
parent::beforeActionCheck($action, $event);
$settings = $this->entity_settings;
// 各アクションの before メソッドが存在すれば実行する
switch ($action) {
case 'previewAction':
if (!$settings->get('actions.preview')) {
throw new NotFoundHttpException();
}
if (method_exists($this, 'beforePreviewAction')) {
$this->beforePreviewAction($event);
}
break;
}
}
/**
* 施設を取得する
*
* @param $code
* @return null|object
*/
protected function getFacilityByCode($code)
{
if (!empty($this->facility)) {
return $this->facility;
} else {
$repo = $this->getDoctrine()->getRepository(Facility::class);
return $repo->findOneBy(['code' => $code]);
}
}
/**
* 施設のホームページを取得
*
* @param $code
* @return string
*/
protected function getFacilityHomeUrl($code)
{
$facility = $this->getFacilityByCode($code);
if ($facility) {
$website = $this->facility->getWebsite();
if(empty($website)){
return rtrim(CMS__WEB_ROOT_PATH, '/') . '/' . $code;
} else {
return rtrim($this->facility->getWebsite(), '/');
}
} else {
false;
}
}
/**
* 施設に応じて入力項目を変更する
*
* @param $builder
* @param $facility_code
* @param $entity
*/
protected function initForm($builder, $facility_code, $entity = null)
{
}
/**
* 保存前の値を編集する
*
* @param $formData
* @param $mode
* @return mixed
*/
protected function filterFormData($formData, $mode)
{
return $formData;
}
/**
* @param $facility
* @param $id
* @param array $params
* @return string | null
*/
protected function getPreviewPageUrl($facility, $id, $params=[])
{
if ($this->entity_settings->get('actions.preview')) {
return $this->get('router')->generate($this->routes['preview'], $params);
} else {
return null;
}
}
/**
* @param Request $request
* @param $facility
* @param $id
* @return Response
*/
public function previewAction(Request $request, $facility, $id)
{
if ($this->container->has('profiler'))
{
$this->container->get('profiler')->disable();
}
$em = $this->getDoctrine()->getManager();
/** @var FilterCollection $filters */
$filters = $em->getFilters();
if($filters->isEnabled('post_type')){
/** @var PostTypeFilter $filter */
$filter = $filters->getFilter('post_type');
$filter->disableForEntity($this->models['item']);
}
$repo = $this->getDoctrine()->getRepository($this->models['item']);
$comparisonId = $request->query->get('comparison');
$entry = $repo->findOneBy(['id' => $id]);
if(!$entry){
throw $this->createNotFoundException();
}
if($comparisonId){
$comparison = $repo->findOneBy(['id' => $comparisonId]);
} elseif(method_exists($repo, 'findMasterEntity')){
$master = $repo->findMasterEntity($entry);
if($master && $master->getId() === $entry->getId()){
$comparison = null;
} else {
$comparison = $master;
}
} else {
$comparison = null;
}
if($comparison) {
$params1 = $this->generatePreviewParams($comparison);
$preview1 = $this->getPreviewPageUrl($facility, $comparison->getId(), $params1);
} else {
$preview1 = null;
}
$params2 = $this->generatePreviewParams($entry);
$preview2 = $this->getPreviewPageUrl($facility, $entry->getId(), $params2);
/** @var ContentManager $manager */
$manager = $this->get('app.content_manager');
$diffHighlight = $this->entity_settings->get('diff_highlight', false);
if($diffHighlight && $comparison) {
$diff = $manager->blockDiff($this->form_class, $entry, $comparison, [
'entity_settings' => $this->entity_settings
]);
} else {
$diff = [];
}
return $this->render('::admin/controller-templates/diff.html.php', [
'entry' => $entry,
'comparison' => $comparison,
'preview1' => $preview1,
'preview2' => $preview2,
'diff' => $diff,
]);
}
/**
*
* @param Request $request
* @param $id
* @return JsonResponse
* @throws NotFoundHttpException
*/
public function autoSaveAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$filters = $em->getFilters();
if ($filters->isEnabled('post_type')) {
$filters->disable('post_type');
}
$entity = $this->findEntity($id);
$repo = $this->getDoctrine()->getRepository($this->models['item']);
if (!$entity) {
throw new NotFoundHttpException();
}
$builder = $this->createPageBuilder($this->form_class, $entity);
try {
$violations = $builder->handleRequest($request);
$formData = $builder->getData();
if (property_exists($entity, 'slug') && $entity->slug == '' && empty($formData['slug'])) {
$formData['slug'] = $this->generateUniqueId();
}
// ドラフトの作成
$revisions = $repo->findAllRevisions($id, 'draft');
if ($revisions) {
$revision = $revisions[0];
} else {
//$revision = $this->duplicateEntity($entity);
$revision = clone $entity;
$revision->setRevisionParent($entity->getId());
$revision->setPostType('draft');
$em->persist($revision);
}
$revision->bindFormData($formData);
$em->flush();
} catch (\Exception $ex) {
return new JsonResponse([
'status' => 'failed',
'message' => $ex->getMessage(),
'trace' => $ex->getTraceAsString()
]);
}
return new JsonResponse([
'status' => 'done'
]);
}
/**
*
* @return array
*/
protected function getDatatableColumns()
{
$columns = [];
$settings = $this->entity_settings;
if($settings->get('relations.category')){
$columns[] = [
"sTitle" => "カテゴリ",
"width" => "130px",
"mData" => "category",
"@render" => "function(data, type, row) {
if(null !== data && 'undefined' !== typeof data.title){
return data.title;
} else {
return '(なし)';
}
}"
];
}
if($settings->get('relations.tag')){
$columns[] = [
"sTitle" => "タグ",
"width" => "130px",
"mData" => "tags",
"sortable" => false,
"@render" => "function(data, type, row) {
if(data.length == 0){
return 'なし';
} else {
var data_list = [];
for (var i=0; i < data.length; i++ ){
data_list.push(data[i]['title']);
}
return data_list.join('<br>');
}
}"
];
}
$columns[] = [
"sTitle" => "タイトル",
"mData" => "title",
"@render" => "function(data, type, row){
return ('' == data) ? '<strong>(無題)</strong>':'<strong>' + data + '</strong>';
}"
];
return $columns;
}
protected function getDefaultOrderBy()
{
return ['sort_num' => 'asc', 'id' => 'desc'];
}
protected function baseMeta($mode, $meta = [], $id = null)
{
$facility = $this->facility;
switch ($mode) {
case "TOP":
case "INDEX":
$meta["page"]["title"] = $meta["base"]["title"] . " | 一覧";
$meta["page"]["path"] = $meta["base"]["path"];
$meta["breadcrumbs"]["current"]["title"] = $meta["base"]["title"];
$meta["breadcrumbs"]["parent"]["title"] = "TOP";
$meta["breadcrumbs"]["parent"]["path"] = "/admin/";
break;
case "NEW":
$meta["page"]["title"] = $meta["base"]["title"] . " | 新規作成";
$meta["page"]["path"] = $meta["base"]["path"] . "new/";
$meta["breadcrumbs"]["current"]["title"] = "新規作成";
$meta["breadcrumbs"]["parent"]["title"] = $meta["base"]["title"];
$meta["breadcrumbs"]["parent"]["path"] = $meta["base"]["path"];
break;
case "DETAIL":
$meta["page"]["title"] = $meta["base"]["title"] . " | 詳細";
$meta["page"]["path"] = $meta["base"]["path"] . $id . '/';
$meta["breadcrumbs"]["current"]["title"] = "詳細";
$meta["breadcrumbs"]["parent"]["title"] = $meta["base"]["title"];
$meta["breadcrumbs"]["parent"]["path"] = $meta["base"]["path"];
break;
case "EDIT":
$meta["page"]["title"] = $meta["base"]["title"] . " | 編集";
$meta["page"]["path"] = $meta["base"]["path"] . $id . '/edit/';
$meta["breadcrumbs"]["current"]["title"] = "編集";
$meta["breadcrumbs"]["parent"]["title"] = $meta["base"]["title"];
$meta["breadcrumbs"]["parent"]["path"] = $meta["base"]["path"];
break;
case "IMPORT":
$meta["page"]["title"] = $meta["base"]["title"] . " | インポート";
$meta["page"]["path"] = $meta["base"]["path"] . "import/";
$meta["breadcrumbs"]["current"]["title"] = "インポート";
$meta["breadcrumbs"]["parent"]["title"] = $meta["base"]["title"];
$meta["breadcrumbs"]["parent"]["path"] = $meta["base"]["path"];
break;
default:
$meta["page"]["title"] = "[Unknown]";
$meta["page"]["path"] = "/unknown";
$meta["breadcrumbs"]["current"]["title"] = "[Unknown]";
$meta["breadcrumbs"]["parent"]["title"] = "[Unknown]";
$meta["breadcrumbs"]["parent"]["path"] = "/unknown";
}
return $meta;
}
/**
* @param Request $request
* @return RedirectResponse|Response
*/
public function importAction(Request $request)
{
set_time_limit(0);
$meta = $this->meta('IMPORT');
$builder = $this->createPageBuilder(AdminImportForm::class, null);
if ($request->isMethod('post')) {
// ファイル取得
$file = $request->files->get("__block_file")["file"];
$import = $this->get("app.helper.import_helper");
$params = $request->request->all();
$formatData = $import->getFormatData($params, $file);
$isDelete = (boolean)$params["__block_is_delete"]["value"];
if (!empty($formatData) && method_exists($this, "importExecuting")) {
$this->importExecuting($formatData, $isDelete);
return $this->redirectToRoute($meta["redirect"], ["facility" => $this->facility->getCode()]);
}
}
return $this->render(rtrim($this->templateDirectory) . '/' . 'import.html.php', [
'meta' => $meta,
'builder' => $builder
]);
}
protected function importExecuting($formatData, $isDelete)
{
$import = $this->get("app.helper.import_helper");
$em = $this->getDoctrine()->getManager();
$entity = new $this->models['item']();
foreach ($formatData as $format) {
$data = [];
$publicDate = new \DateTime($format["post_date"]);
$data["status"] = $format["status"];
$data["public_date"] = $publicDate;
$data["publish_at"] = $publicDate;
$data["title"] = $format["title"];
$data["post_type"] = "master";
// カテゴリ
if (!empty($format["category"])) {
$category = [];
$category["title"] = $format["category"];
$data["category"] = $this->getCategoryIdForImport(
$this->models['category'], $category
);
}
// サブカテゴリ
if (!empty($format["sub_category"])) {
$category = [];
$category["title"] = $format["sub_category"];
$category["main_category"] = $data["category"];
$data["sub_category"] = $this->getCategoryIdForImport(
$this->models['subcategory'], $category
);
}
// タグ
if (!empty($format["tags"])) {
$tags = explode(",", $format["tags"]);
foreach ($tags as $v) {
$tag = [];
$tag["name"] = $v;
$tag["alias"] = $this->generateUniqueId();
$data["tags"][] = $this->getCategoryIdForImport(
$this->models['tag'], $tag, "name"
);
}
}
$data["detail_type"] = "article";
// カスタムブロック
$data["customblock"] = ["visual1__" . $this->generateUniqueId() => [
"values" => $import->importFile($format["contents"]),
"is_active" => true
]];
$entity->bindFormData($data);
$em->persist($entity);
$em->flush();
$em->clear();
}
return true;
}
/**
* @param $entity_class
* @param $data
* @param string $value_name
* @return mixed
*/
protected function getCategoryIdForImport($entity_class, $data, $value_name = "title")
{
$repository = $this->getDoctrine()->getRepository($entity_class);
$entries = $repository->findBy(["{$value_name}" => $data[$value_name], "facility" => $this->facility->getId()]);
if (!empty($entries)) {
return $entries[0];
} else {
// 新規登録
$em = $this->getDoctrine()->getManager();
$entity = new $entity_class();
$entity->setFacility($this->facility);
$entity->bindFormData($data);
$em->persist($entity);
$em->flush();
return $entity;
}
}
}