<?php
namespace AppBundle\Controller;
use AppBundle\Component\Util\Hash;
use Doctrine\ORM\EntityNotFoundException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use AppBundle\Controller\BaseController;
use AppBundle\Component\PageBuilder\PageBuilder;
use AppBundle\Entity\Master\Facility;
class FacilityDisplayBaseController extends BaseController
{
public $facility = null;
protected $entityClass = null;
protected $categoryClass = null;
protected $formClass = null;
protected $redirect_route = null;
protected $default_setting = null;
protected $entity_setting = null;
public $views = [
"top" => "",
"index" => "",
"detail" => "",
"facility_index" => "",
"facility_detail" => ""
];
public $settings = [
"pageLimit" => 10,
"pagerNum" => 5,
"theme" => "pattern1"
];
public function before(FilterControllerEvent $event)
{
parent::before($event);
$request = $event->getRequest();
$facility_code = $request->attributes->get('facility');
if (!is_null($facility_code)) {
$em = $this->getDoctrine()->getManager();
$facility = $this->getFacilityByCode($facility_code);
if(!$facility){
throw $this->createNotFoundException('Facility "' . $facility_code . '" not found.');
}
$filter = $em->getFilters()->enable('facility');
$filter->setParameter('facility_id', $facility->getId());
$this->facility = $facility;
}
}
public function groupTopAction(Request $request)
{
return $this->renderFront($this->views["top"]);
}
public function groupListAction(Request $request)
{
// 記事
$listData = $this->getList($request);
extract($listData);
$cms__categories = $this->getCategories();
$cms__archives = $this->getArchive();
$cms__is_facility = $this->isFacility();
// リダイレクト処理
if (!is_null($this->redirect_route) && $cms__pager['is_out_of_range'] && !CMS__IS_FRONT_ROUTING) {
$params = $cms__queryParams;
if ($cms__pager['last'] > 1) {
$params['page'] = $cms__pager['last'];
}
return $this->redirectToRoute($this->redirect_route, $params);
}
return $this->renderFront($this->views["index"], compact(
"cms__items",
"cms__pager",
"cms__queryParams",
"cms__categories",
"cms__archives",
"cms__is_facility"
));
}
public function groupDetailAction(Request $request, $id)
{
$detailData = $this->getDetail($request, $id, null, $this->settings["theme"]);
extract($detailData);
$cms__categories = $this->getCategories();
$cms__archives = $this->getArchive();
$cms__is_facility = $this->isFacility();
return $this->renderFront($this->views['detail'], compact(
"cms__item",
"cms__builder",
"cms__contents",
"cms__blocks",
"cms__isPreview",
"cms__detailPager",
"cms__queryParams",
"cms__categories",
"cms__archives",
"cms__is_facility"
));
}
public function facilityTopAction(Request $request, $facility)
{
return null;
}
public function facilityListAction(Request $request, $facility)
{
$facility_id = null;
if (!is_null($this->facility)) {
$facility_id = $this->facility->getId();
}
// 記事
$listData = $this->getList($request, $facility_id);
extract($listData);
$cms__categories = $this->getCategories($facility_id);
$cms__archives = $this->getArchive($facility_id);
$cms__is_facility = $this->isFacility();
// リダイレクト処理
if (!is_null($this->redirect_route) && $cms__pager['is_out_of_range'] && !CMS__IS_FRONT_ROUTING) {
$params = $cms__queryParams;
$params['facility'] = $facility;
if ($cms__pager['last'] > 1) {
$params['page'] = $cms__pager['last'];
}
return $this->redirectToRoute($this->redirect_route, $params);
}
return $this->renderFront("{$facility}/" . $this->views["facility_index"], compact(
"cms__items",
"cms__pager",
"cms__queryParams",
"cms__categories",
"cms__archives",
"cms__is_facility"
));
}
public function facilityDetailAction(Request $request, $facility, $id)
{
$facility_id = null;
if (!is_null($this->facility)) {
$facility_id = $this->facility->getId();
}
$detailData = $this->getDetail($request, $id, $facility_id, $this->settings["theme"]);
extract($detailData);
$cms__categories = $this->getCategories($facility_id);
$cms__archives = $this->getArchive($facility_id);
$cms__is_facility = $this->isFacility();
return $this->renderFront("{$facility}/" . $this->views['facility_detail'], compact(
"cms__item",
"cms__builder",
"cms__contents",
"cms__blocks",
"cms__isPreview",
"cms__detailPager",
"cms__queryParams",
"cms__categories",
"cms__archives",
"cms__is_facility"
));
}
/**
* @param $request
* @param null $facility_id
* @return array
*/
protected function getList(Request $request, $facility_id = null)
{
$items = [];
$pager = null;
$repository = $this->getDoctrine()->getRepository($this->entityClass);
$queryParams = $request->query->all();
unset($queryParams["facility"]);
unset($queryParams["page"]);
if (method_exists($repository, "getListQueryBuilder")) {
$query = $queryParams;
if (!empty($query['category'])) {
$categories_id = [];
$categories_id[] = (int)$query['category'];
// 子カテゴリのIDを取得
$repo_category = $this->getDoctrine()->getRepository($this->categoryClass);
if ($repo_category) {
$category = $repo_category->findOneBy(['id' => $query['category']]);
foreach ($category->getDescendants() as $descendant) {
$categories_id[] = $descendant->getId();
}
}
$query['category'] = $categories_id;
}
$qb = $repository->getListQueryBuilder($query, $facility_id);
$page = $request->query->getInt('page', 1);
if($page < 1){
$page = 1;
}
$limit = !empty($this->settings['pageLimit']) ? $this->settings['pageLimit'] : 10;
$query = $qb->getQuery();
// ページング生成
$pager = $this->getListPager($query, $page, $limit);
$items = $query->getResult();
}
return [
"cms__pager" => $pager,
"cms__items" => $items,
"cms__queryParams" => $queryParams
];
}
/**
* @param $query
* @param $page
* @param $limit
* @return array|null
*/
protected function getListPager($query, $page, $limit)
{
$paginator = $this->paginate($query, $page, $limit);
$all_count = count($paginator);
$is_out_of_range = false;
if (!isset($this->settings["pagerNum"]) || !is_numeric($this->settings["pagerNum"])) {
return null;
}
$pager_num = $this->settings["pagerNum"];
//ページャ生成
$first = 1;
if($all_count > 0){
$last = intval(ceil($all_count/$limit));
}else{
$last = 1;
}
if($pager_num > $last){
$pager_num = $last;
}
//指定ページ
$target_page = $page;
if($target_page == 0 OR $last < $target_page) {
//範囲外
$is_out_of_range = true;
return compact('last', 'is_out_of_range');
}
//Prev&Next
if($target_page > 1) {
$offset = ($target_page-1) * $limit;
$prev = $target_page - 1;
$next = $target_page + 1;
}else{
$offset = 0;
$prev = 1;
$next = 2;
}
if($last < $next){
$next = $last;
}
$start_page = 1;
$end_page = $pager_num;
if($last > $pager_num){
$center_num = intval(ceil($pager_num/2));
if($target_page > $center_num) {
if($last - $center_num < $target_page){
$start_page = $last - $pager_num + 1;
$end_page = $start_page + $pager_num - 1;
} else {
$start_page = $target_page - $center_num + 1;
$end_page = $target_page + $center_num - 1;
}
}
}
if($all_count == 0) {
$end_page = -1;
}
$end_view_count = $offset + $limit;
if($all_count < $end_view_count) {
$end_view_count = $all_count;
}
$pager = [
"active_page" => $target_page,
"first" => $first,
"prev" => $prev,
"next" => $next,
"last" => $last,
"start_page" => $start_page,
"end_page" => $end_page,
"start_view_count" => ($all_count < 1)?0:$offset + 1,
"end_view_count" => $end_view_count,
"all_count" => $all_count,
'is_out_of_range' => $is_out_of_range
];
return $pager;
}
/**
* @param $request
* @param $id
* @param null $class
* @param bool $single
* @return object|null
*/
protected function findItem($request, $id, $class=null, $single = false)
{
$item = $this->findItemBy($request, $class, ['id' => $id]);
if ($single && !$item) {
$item = new $class();
if (method_exists($item, 'setDefaultValues')) {
$access_token = md5(uniqid(mt_rand(), true));
$item->setDefaultValues($this->facility, $access_token);
$em = $this->getDoctrine()->getManager();
$em->persist($item);
$em->flush($item);
}
}
return $item;
}
/**
* @param $request
* @param null $id
* @param null $facility_id
* @param string $theme
* @return array
*/
protected function getDetail($request, $id = null, $facility_id = null, $theme = "default", $is_only_one = false)
{
$em = $this->getDoctrine()->getManager();
$mode = $request->query->get('cms_mode', 'default');
$isPreview = in_array($mode, ['preview', 'tmp_preview']) ? true : false;
$item = $this->findItem($request, $id, $this->entityClass, $is_only_one);
if (!$item) {
// 記事が存在しない場合
throw $this->createNotFoundException();
}
$block = $this->getBlock($item, $this->formClass, $theme);
$queryParams = $request->query->all();
if(!$em->getFilters()->isEnabled('public')) {
$em->getFilters()->enable('public');
}
$detailPager = $this->getDetailPager($item->id, $item->public_date, $facility_id);
return [
"cms__item" => $item,
"cms__builder" => $block['builder'],
"cms__contents" => $block['contents'],
"cms__blocks" => $block['blocks'],
"cms__detailPager" => $detailPager,
"cms__isPreview" => $isPreview,
"cms__queryParams" => $queryParams
];
}
protected function getBlock($item, $form_class, $theme = 'default', $block_form_name = 'customblock')
{
$contents = null;
$blocks = null;
$builder = $this->createPageBuilder($form_class, $item);
if (!is_null($form_class)) {
// テーマがあれば利用(ないものはdefault)
$builder->setTheme($theme);
$contents = $builder->findBlockByName($block_form_name);
$blocks = $builder->getBlocks();
}
return compact(
'contents',
'blocks',
'builder'
);
}
/***
* 詳細ページャー取得
* @param string $id
* @param string $date
* @return array
*/
protected function getDetailPager($id, $date, $facility_id = null)
{
$repository = $this->getDoctrine()->getRepository($this->entityClass);
$pager = [];
$next = [];
$prev = [];
if (method_exists($repository, "getDetailPagerQueryBuilder")) {
//前
$qb = $repository->getDetailPagerQueryBuilder($id, $date, $facility_id);
$pager['prev'] = $qb->getQuery()->getResult();
if (count($pager['prev']) > 0) {
foreach ($pager['prev'] as $p) {
$prev = $p;
}
}
//次
$qb = $repository->getDetailPagerQueryBuilder($id, $date, $facility_id, "<", "DESC");
$pager['next'] = $qb->getQuery()->getResult();
if (count($pager['next']) > 0) {
foreach ($pager['next'] as $p) {
$next = $p;
}
}
}
$detailPager = [
"prev" => $prev,
"next" => $next
];
return $detailPager;
}
/***
* アーカイブ取得
* @return array //投稿月をもとに記事数を集計する
*/
protected function getArchive($facility_id = null)
{
$archiveList = [];
$repository = $this->getDoctrine()->getRepository($this->entityClass);
if (method_exists($repository, "getArchiveQueryBuilder")) {
$qb = $repository->getArchiveQueryBuilder($facility_id);
$result = $qb->getQuery()->getResult();
if (count($result) > 0) {
foreach ($result as $archive) {
$year = date('Y', strtotime($archive['public_year_month']));
$month = date('n', strtotime($archive['public_year_month']));
if (!isset($archiveList[$year]['total'])) {
$archiveList[$year]['total'] = 0;
}
$archiveList[$year]['month'][$month]['count'] = $archive['group_count'];
$archiveList[$year]['total'] += $archive['group_count'];
}
}
}
return $archiveList;
}
/***
* カテゴリ取得
* @return array //各カテゴリごとに集計する
*/
protected function getCategories($facility_id = null)
{
$categoryList = [];
$categoryList['total'] = 0;
$categoryList['list'] = [];
if (!isset($this->categoryClass) || is_null($this->categoryClass)) {
return $categoryList;
}
// カテゴリごとのカウント
$categoryRepository = $this->getDoctrine()->getRepository($this->categoryClass);
if (method_exists($categoryRepository, "getArchivesCategoryList")) {
if($this->entity_setting){
$multi_category = Hash::get($this->entity_setting, "item.multi_category", false);
} else {
$multi_category = false;
}
$categoryList = $categoryRepository->getArchivesCategoryList(null, $multi_category);
}
$repo = $this->getDoctrine()->getRepository($this->entityClass);
if (method_exists($repo, "getAllCountQueryBuilder")) {
$qb = $repo->getAllCountQueryBuilder($facility_id);
$totalCount = $qb->getQuery()->getResult();
$categoryList['total'] = $totalCount[0]['1'];
}
// カテゴリそのもののリスト
if (method_exists($categoryRepository, "getCategoryList")) {
$list = $categoryRepository->getCategoryList(null, "", false);
$list = array_flip($list);
$categoryList['list'] = $list;
}
return $categoryList;
}
protected function getPreviewBy($criteria = [], $class = null)
{
$em = $this->getDoctrine()->getManager();
if(is_null($class)){
$class = $this->entityClass;
}
$repository = $this->getDoctrine()->getRepository($class);
$filters = $em->getFilters();
if ($filters->isEnabled('public')) {
$filters->disable('public');
}
$filters->disable('post_type');
$parent = $repository->findOneBy($criteria);
if($parent) {
$post = $repository->findOneBy([
'revision_parent' => $parent->getId(),
'post_type' => 'preview'
]);
if(!$post) {
$post = $parent;
}
} else {
$post = null;
}
$filters->enable('public');
$filters->enable('post_type');
return $post;
}
protected function getPreview($id=null, $class=null)
{
return $this->getPreviewBy(['id' => $id], $class);
}
/**
* 施設を取得する
*
* @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]);
}
}
/**
* 施設かどうか
* @return bool
*/
protected function isFacility()
{
return !is_null($this->facility);
}
}