<?php
    namespace common\components;
    
    use common\models\SitemapDynamic;
    use common\models\SitemapStatic;
    use yii\base\Object;
    use yii\db\ActiveRecord;
    use yii\helpers\Html;
    use yii\web\UrlManager;
    
    class Sitemap extends Object
    {
        public $entities = [];
        public $path = '@frontend/web/sitemap.xml';
        public $url = 'sitemap.xml';
        
        /**
         * Get absolute url to sitemap.xml
         *
         * @return string
         */
        public function getUrl(): string
        {
            /**
             * @var UrlManager $urlManager
             */
            $urlManager = \Yii::$app->get('urlManagerFrontend');
            return $urlManager->createAbsoluteUrl('/' . $this->url);
        }
    
        /**
         * Check whether sitemap.xml exist
         *
         * @return bool
         */
        public function checkFileExist(): bool
        {
            return file_exists(\Yii::getAlias($this->path));
        }
        /**
         * Generate sitemap XML in $path
         *
         * @return bool
         */
        public function generateXML(): bool
        {
            return $this->saveXML($this->generateOneShot());
        }
        
        /**
         * Save generated xml to $path file
         *
         * @param string $xml
         *
         * @return bool
         */
        protected function saveXML(string $xml): bool
        {
            $realpath = \Yii::getAlias($this->path);
            if (file_put_contents($realpath, $xml)) {
                return true;
            } else {
                return false;
            }
        }
        
        /**
         * Generate xml from configs
         *
         * @return string
         */
        public function generateOneShot(): string
        {
            /**
             * @var UrlManager $urlManager
             */
            $urlManager = \Yii::$app->get('urlManagerFrontend');
            $content = '<?xml version="1.0" encoding="UTF-8"?>';
            $content .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
            /**
             * @var SitemapStatic[] $static
             */
            // ***** Begin generating static pages
            $static = SitemapStatic::find()
                                   ->all();
            foreach ($static as $item) {
                $content .= Html::tag(
                    'url',
                    Html::tag('loc', $item->url) . Html::tag('lastmod', date('Y-m-d')) . Html::tag(
                        'changefreq',
                        $item->frequency
                    ) . Html::tag('priority', $item->priority)
                );
            }
            // ***** <<< End
            /**
             * @var SitemapDynamic $dynamic
             */
            $dynamic = SitemapDynamic::find()
                                     ->indexBy('entity')
                                     ->where([ 'status' => 1 ])
                                     ->all();
            $entities = $this->entities;
            foreach ($entities as $entity) {
                /**
                 * @var string $class
                 */
                $class = $entity[ 'class' ];
                /**
                 * @var ActiveRecord $classInstance
                 */
                $classInstance = new $class();
                if (is_subclass_of($classInstance, ActiveRecord::className())) {
                    if (!empty( $dynamic[ $class ] )) {
                        /**
                         * @var SitemapDynamic $model
                         */
                        $model = $dynamic[ $class ];
                        $query = $classInstance::find();
                        if (isset( $entity[ 'conditions' ] )) {
                            foreach ($entity[ 'conditions' ] as $condition) {
                                $query->where($condition);
                            }
                        }
                        $result = $query->all();
                        foreach ($result as $record) {
                            $content .= Html::tag(
                                'url',
                                Html::tag(
                                    'loc',
                                    $urlManager->createAbsoluteUrl(
                                        [
                                            $entity[ 'url' ],
                                            'id' => $record->getAttribute('id'),
                                        ]
                                    )
                                ) . Html::tag('lastmod', date('Y-m-d')) . Html::tag(
                                    'changefreq',
                                    $model->frequency
                                ) . Html::tag('priority', $model->priority)
                            );
                        }
                    }
                }
            }
            $content .= '</urlset>';
            return $content;
        }
    }