UrlManager.php 7.01 KB
<?php
    
    namespace frontend\components;
    
    use artbox\core\models\Alias;
    use artbox\core\models\Language;
    use artbox\core\services\Languages;
    use yii\helpers\Json;
    use yii\web\NotFoundHttpException;
    use yii\web\Request;


    /**
     * Url manager extended to work with aliases and languages
     *
     * @package artbox\core\seo
     */
    class UrlManager extends \yii\web\UrlManager
    {
        /**
         * @var bool
         */
        public $hideDefaultLanguagePrefix = false;
        
        /**
         * @see \yii\web\UrlManager
         * @var bool
         */
        public $enablePrettyUrl = true;
        
        /**
         * @see \yii\web\UrlManager
         * @var bool
         */
        public $showScriptName = false;
        
        /**
         * @var \artbox\core\services\Languages
         */
        protected $languages;
        
        /**
         * UrlManager constructor.
         *
         * @param \artbox\core\services\Languages $languages
         * @param array                           $config
         */
        
        public $params = [
            'id' => 'id',
            'page' => 'page',
            'per-page' => 'per_page',
            'book_id' => 'book_id',
            'q' => 'q',
            'tag' => 'tag',
        ];
        public function __construct(Languages $languages, array $config = [])
        {
            $this->languages = $languages;
            
            parent::__construct($config);
        }
    
        /**
         * @param \yii\web\Request $request
         *
         * @return array|bool
         * @throws \artbox\core\exceptions\AliasOverwriteException
         * @throws \yii\base\ExitException
         * @throws \yii\base\InvalidConfigException
         */
        public function parseRequest($request)
        {
	        $redirect = $this->checkRedirect($request->url);
//			die(var_dump($redirect));
	        if ($redirect !== null) {

		        \Yii::$app->response->redirect("/" . $redirect->value, 301);
	        }
            $request = $this->parseLanguage($request);
            $path=$request->pathInfo;

	        if (strlen($path) && $path[strlen($path) - 1] == '/'
		    #    && $path[strlen($path)-2]=='/'
	        )
	        {
	        	throw new NotFoundHttpException();
	        }


            /**
             * @var Alias $alias
             */
            $alias = Alias::find()
                          ->where(
                              [
                                  'value' => trim($request->pathInfo, '/'),
                              ]
                          )
                          ->andWhere(
                              [
                                  'language_id' => $this->languages->getCurrent()->id,
                              ]
                          )
                          ->one();
            $this->invalidParams(\Yii::$app->request->queryParams);
            if ($alias !== null) {
                $params = Json::decode($alias->route);
                
                $route = array_shift($params);
                
                /**
                 * @todo REFACTOR AS SOO AS POSIBLE!
                 *       remove service locator, and implement Dependency Injection
                 * @var \artbox\core\components\SeoComponent $seo
                 */
                $seo = \Yii::$app->get('seo');
                $seo->setAlias($alias);
                return [
                    $route,
                    $params,
                ];
            }
            
            return parent::parseRequest($request);
        }
        
        /**
         * @param array|string $params
         *
         * @return string
         */
        public function createUrl($params)
        {
            if ($this->hideDefaultLanguagePrefix && ( $this->languages->getCurrent(
                    )->url == $this->languages->getDefault()->url )) {
                $prefix = '';
            } else {
                $prefix = '/' . $this->languages->getCurrent()->url;
            }
            
            if (isset($params[ 'alias' ])) {
                if ($params[ 'alias' ] instanceof Alias) {
                    return $prefix . '/' . $params[ 'alias' ]->value;
                } elseif (is_array($params[ 'alias' ])) {
                    return $prefix . '/' . $params[ 'alias' ][ 'value' ];
                }
            }

            return $prefix . parent::createUrl($params);
        }
        
        /**
         * @param $request
         *
         * @return mixed
         * @throws \yii\base\ExitException
         * @throws \yii\base\InvalidConfigException
         */
        protected function parseLanguage(Request $request)
        {
            $split = explode('/', $request->pathInfo);
            if (in_array($split[ 0 ], array_keys($this->languages->getActive()))) {
                if ($this->hideDefaultLanguagePrefix && ( $split[ 0 ] == $this->languages->getDefault()->url )) {
                    unset($split[ 0 ]);
                    
                    \Yii::$app->response->redirect('/' . implode('/', $split), 301)
                                        ->send();
                    \Yii::$app->end();
                } else {
                    $this->languages->setCurrent($split[ 0 ]);
                    
                    unset($split[ 0 ]);
                    
                    $request->setPathInfo(implode('/', $split));
                }
            } else {
                if ($this->hideDefaultLanguagePrefix) {
                    $this->languages->setCurrentDefault();
                } else {
                    \Yii::$app->response->redirect(
                        '/' . $this->languages->getDefault()->url . '/' . implode('/', $split),
                        301
                    )
                                        ->send();
                    \Yii::$app->end();
                }
            }

            return $request;
        }

        /**
         * Looks for rule in table(column)
         * `redirect.from` if findes -
         * redirects to `redirect.to`
         *
         * @param string $url
         */
        protected function checkRedirect(string $url)
        {
	        $url1 = parse_url($url);


	        $string = '{"0":"' . ltrim($url1['path'], "/") . '"';
	        if (isset($url1['query'])) {
		        parse_str($url1['query'], $url1['query']);
		        $string .= (isset($url1['query']['id']))
			        ? ',"id":' . $url1['query']['id']
			        : '';
	        }

	        $string .= '}';

	        $alias = Alias::find()
		        ->where(['route' => trim($string)])
		        ->one();
//	        die(var_dump(Alias::find()
//		        ->where(['route' => $string])->createCommand()->rawSql));
	        return $alias;




        }
        
        protected function invalidParams($requestParams){
            foreach ($requestParams as $key =>$param){
                
                if (!array_key_exists($key, $this->params)){
                    throw new NotFoundHttpException();
                }
            }
        }
    }