You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							90 lines
						
					
					
						
							2.5 KiB
						
					
					
				
			
		
		
	
	
							90 lines
						
					
					
						
							2.5 KiB
						
					
					
				<?php | 
						|
 | 
						|
namespace frontend\urls; | 
						|
 | 
						|
use core\entities\post\Post; | 
						|
use core\entities\post\PostType; | 
						|
use core\repositories\post\read\PostReadRepository; | 
						|
use yii\base\BaseObject; | 
						|
use yii\base\InvalidParamException; | 
						|
use yii\caching\Cache; | 
						|
use yii\web\UrlNormalizerRedirectException; | 
						|
use yii\web\UrlRuleInterface; | 
						|
 | 
						|
class PostUrlRule extends BaseObject implements UrlRuleInterface | 
						|
{ | 
						|
    private $repository; | 
						|
    private $cache; | 
						|
 | 
						|
    public function __construct(PostReadRepository $repository, Cache $cache, $config = []) | 
						|
    { | 
						|
        parent::__construct($config); | 
						|
        $this->repository = $repository; | 
						|
        $this->cache = $cache; | 
						|
    } | 
						|
 | 
						|
    public function parseRequest($manager, $request) | 
						|
    { | 
						|
        $path = $request->pathInfo; | 
						|
 | 
						|
        $result = $this->cache->getOrSet(['post_route', 'path' => $path], function () use ($path) { | 
						|
            if (!$post = $this->repository->findBySlug($this->getPathSlug($path))) { | 
						|
                return ['id' => null, 'path' => null]; | 
						|
            } | 
						|
            return ['id' => $post->id, 'path' => $this->getPagePath($post)]; | 
						|
        }, 1000); | 
						|
 | 
						|
        if (empty($result['id'])) { | 
						|
            return false; | 
						|
        } | 
						|
 | 
						|
        if ($path != $result['path']) { | 
						|
            throw new UrlNormalizerRedirectException(['post/post', 'id' => $result['id']], 301); | 
						|
        } | 
						|
 | 
						|
        return ['post/post', ['id' => $result['id']]]; | 
						|
    } | 
						|
 | 
						|
    public function createUrl($manager, $route, $params) | 
						|
    { | 
						|
        if ($route == 'post/post') { | 
						|
            if (empty($params['id'])) { | 
						|
                throw new InvalidParamException('Empty id.'); | 
						|
            } | 
						|
            $id = $params['id']; | 
						|
 | 
						|
            $url = $this->cache->getOrSet(['post_route', 'id' => $id], function () use ($id) { | 
						|
                if (!$post = $this->repository->find($id)) { | 
						|
                    return null; | 
						|
                } | 
						|
                return $this->getPagePath($post); | 
						|
            }); | 
						|
 | 
						|
            if (!$url) { | 
						|
                throw new InvalidParamException('Undefined id.'); | 
						|
            } | 
						|
 | 
						|
            unset($params['id']); | 
						|
            if (!empty($params) && ($query = http_build_query($params)) !== '') { | 
						|
                $url .= '?' . $query; | 
						|
            } | 
						|
 | 
						|
            return $url; | 
						|
        } | 
						|
        return false; | 
						|
    } | 
						|
 | 
						|
    private function getPathSlug($path): string | 
						|
    { | 
						|
        $chunks = explode('/', $path); | 
						|
        return end($chunks); | 
						|
    } | 
						|
 | 
						|
    private function getPagePath(Post $post): string | 
						|
    { | 
						|
    	$type = PostType::findOne($post->type_id); | 
						|
    	$chunks = [$type->name]; | 
						|
        $chunks[] = $post->slug; | 
						|
        return implode('/', $chunks); | 
						|
    } | 
						|
} |