SeoUrlManager.php 6.71 KB
<?php
    
    namespace artbox\core\components;
    
    use artbox\catalog\helpers\FilterHelper;
    use artbox\core\models\Alias;
    use artbox\core\models\Language;
    use yii\helpers\Json;
    use yii\web\UrlManager;
    use Yii;
    
    /**
     * Class SeoUrlManager
     *
     * @package artbox\core\components
     */
    class SeoUrlManager extends UrlManager
    {
        /**
         * Whether to try to redirect from non-seo to seo
         *
         * @var bool
         */
        public $forceRedirect = false;
        
        /**
         * Routes which will be used in alias db query
         *
         * @var array $skipRoute
         */
        public $skipRoute = [];
        
        /**
         * @inheritdoc
         */
        public function parseRequest($request)
        {
            /**
             * @var \artbox\core\components\LanguageRequest $request
             * @var SeoComponent                            $seo
             */
            
            $seo = Yii::$app->get('seo');
            
            // This function called before url parsed by LanguageRequest, so $language is null
            $request->getLanguageUrl();
            $language = Language::getCurrent();
            if ($request->pathInfo === '') {
                // Do redirect if no active alias for homepage
                $alias = Alias::findRoute([ 'site/index' ], $language);
                if ($alias) {
                    $seo->setAlias($alias);
                    
                    $route = Json::decode($alias->route);
                    
                    $result[] = array_shift($route);
                    $result[] = $route;
                    
    
                    return $result;
                }
            } else {
                $alias = Alias::findUrl($request->pathInfo, $language);
            }
            if ($this->forceRedirect && empty($alias)) {
                $get = $request->get();
                foreach ($get as $index => $item) {
                    if ($value = intval($item)) {
                        $get[ $index ] = $value;
                    }
                }
                $alias = Alias::findRoute(array_merge([ $request->pathInfo ], $get), $language);
                if ($alias) {
                    \Yii::$app->response->redirect(Json::decode($alias->route));
                }
            }
            
            if (!empty($alias)) {
                /**
                 */
                $seo->setAlias($alias);
                
                $route = Json::decode($alias->route);
                
                $result[] = array_shift($route);
                $result[] = $route;
                
                return $result;
            }
           
            return parent::parseRequest($request);
        }
        
        /**
         * #1 Decide set or not language in the beginning of url (is there one active or more)
         * #2 Add hash or not (is there $params['#'] or not)
         * #3 Create url by ready alias or not
         * #4 Does language setted from param ( $language_id )
         *
*@inheritdoc
         */
        public function createUrl($params)
        {
            /**
             * Decide how much active languages (1)
             */
            $count = count(Language::getActive());

            if (!empty($params[ 0 ]) && $params[ 0 ] === 'site/index') {
                if ($count > 1) {
                    return '/';
                } else {
                    return '/' . Language::getCurrent()->url;
                }
            }
            
            /**
             * (1,2,3)
             */
            if (!empty($params[ 'alias' ]) && $params[ 'alias' ] instanceof Alias) {
                /**
                 * @var Alias $alias
                 */
                $alias = $params[ 'alias' ];
                $language = Language::getCurrent();
                $hash = isset($params[ '#' ]) ? '#' . $params[ '#' ] : '';
                return ( $count > 1 ) ? ( '/' . $language->url . '/' . $alias->value ) : ( '/' . $alias->value ) . $hash;
            }
    
            /**
             * (4)
             */
            if (!empty($params[ 'language_id' ])) {
                $language = Language::findOne($params[ 'language_id' ]);
                unset($params[ 'language_id' ]);
            }
            if (empty($language)) {
                $language = Language::getCurrent();
            }
            /**
             * @var \artbox\core\components\AliasCache $cacheModel
             */
            $cacheModel = \Yii::$app->get('aliasCache', false);
            $rules = [];
            foreach ($this->rules as $rule) {
                if (!in_array($rule->route, $this->skipRoute)) {
                    $rules[] = $rule->route;
                }
            }
            $diff = null;
            if (!in_array($params[ 0 ], $rules)) {
                if (count($params) > 2 && !empty($params[ 'id' ])) {
                    $aliasParams = [
                        $params[ 0 ],
                        'id' => $params[ 'id' ],
                    ];
                } else {
                    $aliasParams = $params;
                }
                if ($cacheModel) {
                    $alias = $cacheModel->getOrSet(
                        $aliasParams,
                        $language,
                        function () use ($aliasParams, $language) {
                            return Alias::findRoute($aliasParams, $language);
                        }
                    );
                } else {
                    $alias = Alias::findRoute($aliasParams, $language);
                }
                if (!empty($alias)) {
                    $diff = array_diff($params, $aliasParams);
                }
            } else {
                $alias = null;
            }
            if (!empty($alias)) {
                $value = $alias->value;
                return ( $count > 1 ) ? ( '/' . $language->url . '/' . $value ) : ( '/' . $value ) . ( $diff ? ( '?' . http_build_query(
                            $diff
                        ) ) : '' );
            } else {
                $url = parent::createUrl($params);
                /**
                 * @var FilterHelper $filter
                 */
                if (class_exists('artbox\catalog\helpers\FilterHelper')) {
                    $filter = \Yii::$app->get('filter');
                    $result = ( $count > 1 ) ? ( '/' . $language->url . $filter->filterObj->replaceFilterUrl(
                            $url
                        ) ) : $filter->filterObj->replaceFilterUrl($url);
                } else {
                    $result = ( $count > 1 ) ? ( '/' . $language->url . $url ) : $url;
                }
                return $result;
            }
        }
    }