writesdown/app-cms

View on GitHub
modules/sitemap/frontend/controllers/DefaultController.php

Summary

Maintainability
D
1 day
Test Coverage
<?php
/**
 * @link      http://www.writesdown.com/
 * @copyright Copyright (c) 2015 WritesDown
 * @license   http://www.writesdown.com/license/
 */

namespace modules\sitemap\frontend\controllers;

use common\models\Media;
use common\models\Option;
use common\models\Post;
use common\models\PostType;
use common\models\Taxonomy;
use common\models\Term;
use Yii;
use yii\data\Pagination;
use yii\filters\AccessControl;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
use yii\web\Controller;

/**
 * Class DefaultController
 *
 * @author  Agiel K. Saputra <13nightevil@gmail.com>
 * @since   0.2.0
 */
class DefaultController extends Controller
{
    /**
     * @var array option for sitemap
     */
    private $_option = [];

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    [
                        'actions'       => ['index', 'style', 'view'],
                        'allow'         => true,
                        'matchCallback' => function () {
                            $option = Option::get('sitemap');

                            return $option['enable_sitemap'];
                        },
                    ],
                ],
            ],
        ];
    }

    /**
     * @return string
     */
    public function actionIndex()
    {
        /* @var $postType PostType */
        /* @var $post Post */
        /* @var $taxonomies Taxonomy[] */
        /* @var $taxonomy Taxonomy */
        /* @var $lastMedia Media */

        $response = Yii::$app->response;
        $response->headers->set('Content-Type', 'text/xml; charset=UTF-8');
        $response->format = $response::FORMAT_RAW;
        $postTypes = PostType::find()->select(['id', 'slug'])->all();
        $taxonomies = Taxonomy::find()->select(['id', 'slug'])->all();
        $items = [];

        foreach ($postTypes as $postType) {
            if (isset($this->_option['post_type'][$postType->id]['enable'])
                && $this->_option['post_type'][$postType->id]['enable']
            ) {
                if ($post = $postType->getPosts()
                    ->andWhere(['status' => Post::STATUS_PUBLISH])
                    ->andWhere(['<=', 'date', date('Y-m-d H:i:s')])
                    ->orderBy(['id' => SORT_DESC])
                    ->one()
                ) {
                    $lastmod = new \DateTime($post->modified, new \DateTimeZone(Option::get('time_zone')));
                    $query = $postType->getPosts()
                        ->andWhere(['status' => Post::STATUS_PUBLISH])
                        ->andWhere(['<=', 'date', date('Y-m-d H:i:s')]);
                    $countQuery = clone $query;
                    $pages = new Pagination([
                        'totalCount' => $countQuery->count(),
                        'pageSize'   => $this->_option['entries_per_page'],
                    ]);
                    for ($i = 1; $i <= $pages->pageCount; $i++) {
                        $items[] = [
                            'loc'     => Yii::$app->urlManager->hostInfo
                                . Url::to(['view', 'type' => 'p', 'slug' => $postType->slug, 'page' => $i]),
                            'lastmod' => $lastmod->format('r'),
                        ];
                    }
                }
            }
        }

        foreach ($taxonomies as $taxonomy) {
            if (isset($this->_option['taxonomy'][$taxonomy->id]['enable'])
                && $this->_option['taxonomy'][$taxonomy->id]['enable']
            ) {
                if ($terms = $taxonomy->terms) {
                    $post = Post::find()
                        ->from(['post' => Post::tableName()])
                        ->innerJoinWith([
                            'terms' => function ($query) {
                                /* @var $query \yii\db\ActiveQuery */
                                $query->from(['term' => Term::tableName()]);
                            },
                        ])
                        ->where(['IN', 'term.id', ArrayHelper::getColumn($terms, 'id')])
                        ->andWhere(['post.status' => Post::STATUS_PUBLISH])
                        ->andWhere(['<=', 'date', date('Y-m-d H:i:s')])
                        ->orderBy(['post.id' => SORT_DESC])
                        ->one();

                    if ($post) {
                        $query = $taxonomy->getTerms();
                        $lastmod = new \DateTime($post->modified, new \DateTimeZone(Option::get('time_zone')));
                        $countQuery = clone $query;
                        $pages = new Pagination([
                            'totalCount' => $countQuery->count(),
                            'pageSize'   => $this->_option['entries_per_page'],
                        ]);

                        for ($i = 1; $i <= $pages->pageCount; $i++) {
                            $items[] = [
                                'loc'     => Yii::$app->urlManager->hostInfo
                                    . Url::to(['view', 'type' => 'c', 'slug' => $taxonomy->slug, 'page' => $i]),
                                'lastmod' => $lastmod->format('r'),
                            ];
                        }
                    }
                }
            }
        }

        if (isset($this->_option['media']['enable']) && $this->_option['media']['enable']) {
            $query = Media::find();
            $countQuery = clone $query;
            $pages = new Pagination([
                'totalCount' => $countQuery->count(),
                'pageSize'   => $this->_option['entries_per_page'],
            ]);

            if ($lastMedia = $query->orderBy(['id' => SORT_DESC])->one()) {
                $lastmod = new \DateTime($lastMedia->modified, new \DateTimeZone(Option::get('time_zone')));
                for ($i = 1; $i <= $pages->pageCount; $i++) {
                    $items[] = [
                        'loc'     => Yii::$app->urlManager->hostInfo
                            . Url::to(['view', 'type' => 'm', 'slug' => 'media', 'page' => $i]),
                        'lastmod' => $lastmod->format('r'),
                    ];
                }
            }
        }

        return $this->renderPartial('index', ['items' => $items]);
    }

    /**
     * @return string
     */
    public function actionStyle()
    {
        $response = Yii::$app->response;
        $response->headers->set('Content-Type', 'text/xml; charset=UTF-8');
        $response->format = $response::FORMAT_RAW;

        return $this->renderPartial('style');
    }

    /**
     * @param string $type
     * @param string $slug
     * @param int    $page
     *
     * @return string
     */
    public function actionView($type, $slug, $page = 1)
    {
        /* @var $taxonomy Taxonomy */
        /* @var $postType PostType */
        /* @var $posts Post[] */
        /* @var $images Media[] */
        /* @var $terms Term[] */
        /* @var $mediaSet Media[] */
        /* @var $post Post */

        $page--;
        $items = [];
        $response = Yii::$app->response;
        $response->headers->set('Content-Type', 'text/xml; charset=UTF-8');
        $response->format = $response::FORMAT_RAW;
        if ($type === 'h') {
            $item['loc'] = Yii::$app->urlManager->hostInfo . Yii::$app->urlManager->baseUrl . '/';
            $item['changefreq'] = $this->_option['home']['changefreq'];
            $item['priority'] = $this->_option['home']['priority'];

            return $this->renderPartial('home', ['item' => $item]);
        } elseif ($type === 'p') {
            $postType = PostType::find()->where(['slug' => $slug])->one();
            $posts = $postType->getPosts()
                ->andWhere(['status' => 'publish'])
                ->andWhere(['<=', 'date', date('Y-m-d H:i:s')])
                ->offset($page * $this->_option['entries_per_page'])
                ->limit($this->_option['entries_per_page'])
                ->all();

            foreach ($posts as $post) {
                $lastmod = new \DateTime($post->modified, new \DateTimeZone(Option::get('time_zone')));
                $items[$post->id]['loc'] = $post->url;
                $items[$post->id]['lastmod'] = $lastmod->format('r');
                $items[$post->id]['changefreq'] = $this->_option['post_type'][$postType->id]['changefreq'];
                $items[$post->id]['priority'] = $this->_option['post_type'][$postType->id]['priority'];

                if ($images = $post->getMedia()->where(['LIKE', 'mime_type', 'image'])->all()) {
                    foreach ($images as $image) {
                        $metadata = $image->getMeta('metadata');
                        $items[$post->id]['image'][$image->id]['loc'] = $image->getUploadUrl()
                            . $metadata['versions']['full']['url'];
                        $items[$post->id]['image'][$image->id]['title'] = $image->title
                            ? $image->title
                            : null;
                        $items[$post->id]['image'][$image->id]['caption'] = $image->excerpt
                            ? $image->excerpt
                            : null;
                    }
                }
            }

            return $this->renderPartial('post-type', ['items' => $items]);
        } elseif ($type === 'c') {
            $taxonomy = Taxonomy::find()->where(['slug' => $slug])->one();
            $terms = $taxonomy->getTerms()
                ->offset($page * $this->_option['entries_per_page'])
                ->limit($this->_option['entries_per_page'])
                ->all();

            foreach ($terms as $term) {
                $post = $term->getPosts()
                    ->andWhere(['status' => Post::STATUS_PUBLISH])
                    ->andWhere(['<=', 'date', date('Y-m-d H:i:s')])
                    ->orderBy(['id' => SORT_DESC])
                    ->one();

                if ($post) {
                    $lastmod = new \DateTime($post->modified, new \DateTimeZone(Option::get('time_zone')));
                    $items[$term->id]['loc'] = $term->url;
                    $items[$term->id]['lastmod'] = $lastmod->format('r');
                    $items[$term->id]['changefreq'] = $this->_option['taxonomy'][$taxonomy->id]['changefreq'];
                    $items[$term->id]['priority'] = $this->_option['taxonomy'][$taxonomy->id]['priority'];
                }
            }

            return $this->renderPartial('taxonomy', ['items' => $items]);
        } elseif ($type === 'm') {
            $mediaSet = Media::find()
                ->offset($page * $this->_option['entries_per_page'])
                ->limit($this->_option['entries_per_page'])
                ->all();
            foreach ($mediaSet as $media) {
                $lastmod = new \DateTime($media->modified, new \DateTimeZone(Option::get('time_zone')));
                $items[$media->id]['loc'] = $media->getUrl();
                $items[$media->id]['lastmod'] = $lastmod->format('r');
                $items[$media->id]['changefreq'] = $this->_option['media']['changefreq'];
                $items[$media->id]['priority'] = $this->_option['media']['priority'];
            }

            return $this->renderPartial('media', ['items' => $items]);
        }

        return $this->redirect(['/site/not-found']);
    }

    /**
     * @inheritdoc
     */
    public function beforeAction($action)
    {
        /*  @var $postType \common\models\PostType */
        /*  @var $taxonomy \common\models\Taxonomy */
        if (parent::beforeAction($action)) {
            $this->_option = Option::get('sitemap');

            return true;
        }

        return false;
    }
}