CatalogUrlManager.php 6.95 KB
<?php

namespace common\modules\product;

use common\modules\product\models\Brand;
use common\modules\product\models\CategorySearch;
use common\modules\product\models\ProductSearch;
use common\modules\rubrication\models\TaxOption;
use Yii;
use yii\helpers\Url;
use yii\web\UrlRuleInterface;

class CatalogUrlManager implements UrlRuleInterface {
    public $route_map = [];

    public $option_prefix = 'o:';
    /**
     * Parses the given request and returns the corresponding route and parameters.
     * @param \yii\web\UrlManager $manager the URL manager
     * @param \yii\web\Request $request the request component
     * @return array|boolean the parsing result. The route and the parameters are returned as an array.
     * If false, it means this rule cannot be used to parse this path info.
     */
    public function parseRequest($manager, $request)
    {
        $pathInfo = $request->getPathInfo();
        $paths = explode('/', $pathInfo);

        if (!array_key_exists($paths[0], $this->route_map)) {
            return false;
        }

        $params = [];
        if ($paths[0] == 'catalog') {
            $route = 'catalog/category';
            // Category
            if (!empty($paths[1])) {
                $category = CategorySearch::findByAlias($paths[1]);
                if (empty($category)) {
                    http_redirect(Url::to(['/']));
                }
                $params['category'] = $category;
            }
            if (!empty($paths[2])) {
                // Filter
                if (strpos($paths[2], 'filter:') === 0) {
                    $params['filter'] = [];
                    $filter_str = substr($paths[2], 7);
                    $filter_options = explode(';', $filter_str);
                    foreach ($filter_options as $filter_option) {
                        if (empty($filter_option)) {
                            continue;
                        }
                        list($filter_key, $filter_option) = explode('=', $filter_option);
                        if($filter_key == 'prices') { // price-interval section
                            $prices = explode(':', $filter_option);
                            $params['filter'][$filter_key] = [
                                'min' => floatval($prices[0]),
                                'max' => floatval($prices[1]),
                            ];
                        } elseif (strpos($filter_key, $this->option_prefix) === 0) { // options section
                            $params['filter']['options'][substr($filter_key, 2)] = explode(',', $filter_option);
                        } else { // brands and other sections
                            $params['filter'][$filter_key] = explode(',', $filter_option);
                        }

                    }
                } elseif (strpos($paths[2], 'word:') === 0) {
                    $params['word'] = substr($paths[2], 5);
                }
            }
        } elseif ($paths[0] == 'product') {
            $product = ProductSearch::findByAlias($paths[1]);
            if (empty($product->product_id)) {
                throw new HttpException(404 ,'Page not found');
            }
            $route = 'catalog/product';
            $params = [
                'product' => $product,
            ];
        } elseif ($paths[0] == 'brand') {

        }

        return [$route, $params];
    }
    /**
     * Creates a URL according to the given route and parameters.
     * @param \yii\web\UrlManager $manager the URL manager
     * @param string $route the route. It should not have slashes at the beginning or the end.
     * @param array $params the parameters
     * @return string|boolean the created URL, or false if this rule cannot be used for creating this URL.
     */
    public function createUrl($manager, $route, $params)
    {
        if (!in_array($route, $this->route_map)) {
            return false;
        }

        switch($route) {
            case 'catalog/category':
                if (!empty($params['category'])) {
                    $category_alias = is_object($params['category']) ? $params['category']->alias : strtolower($params['category']);
                    $url = 'catalog/'. $category_alias .'/';
                } else {
                    $url = 'catalog/';
                }

                if (!empty($params['word'])) {
                    if (!is_array($params['word'])) {
                        $params['word'] = [$params['word']];
                    }
                    $url .= 'word:'. implode(';', $params['word']);
                    unset($params['word']);
                }

                $filter = [];
                if (!empty($params['filter'])) {
                    foreach ($params['filter'] as $key => $values) {
                        switch($key) {
                            case 'prices':
                                $filter[] = $key .'='. implode(':', $values);
                                break;

                            case 'options':
                                foreach($values as $group => &$value_items) {
                                    foreach($value_items as &$value_item) {
                                        $value_item = $this->option_value_encode($value_item);
                                        if (empty($value_item)) {
                                            unset($value_item);
                                        }
                                    }
                                    $filter[] = $this->option_prefix. $group .'='. implode(',', $value_items);
                                }
                                break;

                            default:
                                foreach($values as &$value) {
                                    $value = $this->option_value_encode($value);
                                    if (empty($value)) {
                                        unset($value);
                                    }
                                }
                                $filter[] = $key .'='. implode(',', $values);
                                break;
                        }
                    }
                    $url .= 'filter:'. implode(';', $filter);
                }

                if (!empty($params) && ($query = http_build_query($params)) !== '') {
                    $url .= '?' . $query;
                }

                return $url;
                break;

            case 'catalog/product':
                if (!empty($params['product'])) {
                    $product_alias = is_object($params['product']) ? $params['product']->alias : strtolower($params['product']);
                }
                $url = 'product/'. $product_alias;

                if (!empty($params) && ($query = http_build_query($params)) !== '') {
                    $url .= '?' . $query;
                }

                return $url;
                break;
        }
    }

    private function option_value_encode($value) {
        return str_replace(array(',', '/'), array('~', '&s;'), $value);
    }
}