SiteMapController.php 8.17 KB
<?php

namespace console\controllers;

use common\models\Articles;
use common\models\Seo;
use common\modules\product\helpers\FilterHelper;
use common\modules\product\models\Brand;
use common\modules\product\models\Category;
use common\modules\product\models\Product;
use common\modules\product\models\ProductVariant;
use frontend\models\ProductFrontendSearch;
use Yii;
use common\models\Page;
use common\models\PageSearch;
use yii\data\Pagination;
use yii\db\ActiveQuery;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
use yii\console\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use developeruz\db_rbac\behaviors\AccessBehavior;


/**
 * PageController implements the CRUD actions for Page model.
 */
class SiteMapController extends Controller
{

    private $urlList = ['http://www.rukzachok.com.ua/'];
    private $urlBlockedList = [];
    private $count = 1;

    public function getAddStatic() {

        return [
            'http://www.rukzachok.com.ua',
            'http://www.rukzachok.com.ua/catalog'
        ];

    }

    public function getStaticPages() {

        return Page::find()->all();

    }

    public function getCategories() {

        return Category::find()->andWhere(['not like', 'meta_robots', 'noindex'])->all();

    }

    public function checkFilter($category, $filter) {

        $productModel = new ProductFrontendSearch();
        $productProvider = $productModel->search($category, $filter);
        if(!empty($productProvider->models)){
           return true;
        } else {
           return false;
        }

    }

    public function getProducts() {

        return Product::find()->all();

    }

    public function getSeoLinks() {

        return Seo::find()->all();

    }

    public function getBlocked() {

        return Seo::find()->where(['like', 'meta', 'noindex'])->all();

    }

    public function getArticles() {

        return Articles::find()->all();

    }

    public function getBrands($category) {

        return $category->brands;
    }

    /**
     * @param $category Category;
     * @return mixed
     */
    public function getFilters($category) {

        return $category->getActiveFilters()->all();

    }

    public function checkUrl($url) {

        if (preg_match('/filters:[^=]+=[^=]+;[^=]+=[^=]+/', $url)) {
            $reverse_url = preg_replace('/filters:([^=]+=[^=]+);([^=]+=[^=]+)/', 'filters:$2;$1', $url);
        }

        if(in_array($url, $this->urlList) || (isset($reverse_url) && in_array($reverse_url, $this->urlList)) || in_array($url, $this->urlBlockedList)) {
            return false;
        } else {
            $this->urlList[] = $url;
            return true;
        }

    }

    public function createRow( $url, $priority, &$content ) {

        if($this->checkUrl($url)){
            print $this->count++ . "\n";
            $content .= '<url>' .
                '<loc>' . htmlspecialchars($url) . '</loc>' .
                '<lastmod>' . date('Y-m-d') . '</lastmod>' .
                '<changefreq>Weekly</changefreq>' .
                '<priority>' . $priority .'</priority>' .
                '</url>';
        }

    }

    public function actionProcess() {

        $config = ArrayHelper::merge(
            require(__DIR__ . '/../../frontend/config/main.php'),
            require(__DIR__ . '/../../common/config/main.php')

        );

        Yii::$app->urlManager->addRules($config['components']['urlManager']['rules']);

        $dirName = Yii::getAlias('@frontend').'/web';

        $filename = 'sitemap.xml';

        setlocale(LC_ALL, 'ru_RU.CP1251');

        $handle = fopen($dirName .'/'. $filename, "w");

        $content = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';

        //init $urlBlockedList
        foreach ($this->getBlocked() as $link) {
            $url = Yii::$app->urlManager->baseUrl.$link->url;
            $this->urlBlockedList[] = $url;
        }

        //home page + home catalog
        foreach ($this->getAddStatic() as $page) {
            $this->createRow($page , 1,$content);
        }

        //static pages (contacts, about, etc)
        foreach ($this->getStaticPages() as $page) {
            $url = Url::to(['text/index','translit' => $page->translit]);
            $this->createRow($url , 1,$content);
        }

        //categories
        foreach ($this->getCategories() as $category) {
            /**
             * @var $query  ActiveQuery
             */
            $query = $category->getProducts()->select(['product.*']);
            $query->joinWith(['enabledVariants']);
            $query->andWhere(['!=', ProductVariant::tableName() .'.stock', 0]);
            $count = $query->count();
            $pages = new Pagination(['totalCount' => $count,'pageSize'=>16]);


            for($i=1; $i<=$pages->getPageCount(); $i++){
                if($i==1){
                    $url = Url::to(['catalog/category', 'category' => $category]);
                } else {
                    $url = Url::to(['catalog/category', 'category' => $category, 'page'=>$i, 'per-page'=>$pages->pageSize]);
                }
                $this->createRow($url , 1,$content);
            }
        }

        //products
        foreach ($this->getProducts() as $product) {

            $url = Url::to(['catalog/product', 'product' => $product]);
            $this->createRow($url , 0.9, $content);
        }

        //articles
        foreach ($this->getArticles() as $article) {

            $url = Url::to(['articles/show', 'translit' => $article->translit]);
            $this->createRow($url , 0.8,$content);

        }

        //brands
        foreach($this->getCategories() as $category) {

            foreach ($this->getBrands($category) as $brand) {
                if($this->checkFilter($category, ['brands' => [$brand->brand_id]])){
                    $url = Url::to(['catalog/category', 'category' => $category, 'filters' => ['brands' => [$brand->alias]]]);
                    $this->createRow($url , 0.8, $content);
                }
            }

            foreach ($this->getBrands($category) as $brand) {
                $url = Url::to(['catalog/brand', 'brand' => $brand->alias]);
                $this->createRow($url, 0.8, $content);
            }

        }

        //filters 1 lvl
        foreach($this->getCategories() as $category) {
            foreach ($this->getFilters($category) as $filter) {
                if($this->checkFilter($category, [$filter['group_alias'] => [$filter['option_alias']]])){
                    $url = Url::to(['catalog/category', 'category' => $category, 'filters' => [$filter['group_alias'] => [$filter['option_alias']]] ]);
                    $this->createRow($url , 0.8, $content);
                }

            }
        }

        //seo links
        foreach($this->getSeoLinks() as $link) {
            $url = Yii::$app->urlManager->baseUrl.$link->url;
            $this->createRow($url , 0.7, $content);

        }

        //filters 2 lvl
        foreach($this->getCategories() as $category) {
            foreach ($this->getFilters($category) as $filter1) {
                foreach ($this->getFilters($category) as $filter2) {
                    if($this->checkFilter($category, [$filter1['group_alias'] => [$filter1['option_alias']],$filter2['group_alias'] => [$filter2['option_alias']]] )){
                        $url = Url::to(['catalog/category', 'category' => $category, 'filters' => [$filter1['group_alias'] => [$filter1['option_alias']],$filter2['group_alias'] => [$filter2['option_alias']]] ]);
                        $this->createRow($url , 0.7, $content);
                    }

                }

                foreach ($this->getBrands($category) as $brand) {
                    if($this->checkFilter($category, ['brands' => [$brand->brand_id], $filter1['group_alias'] =>  [$filter1['option_alias']]] )){
                        $url = Url::to(['catalog/category', 'category' => $category, 'filters' => ['brands' => [$brand->alias],$filter1['group_alias'] => [$filter1['option_alias']]]]);
                        $this->createRow($url , 0.7,$content);
                    }

                }
            }
        }



        $content .= '</urlset>';

        fwrite($handle, $content);
        fclose($handle);

        print $dirName .'/'. $filename;
    }

}