diff --git a/frontend/controllers/CatalogController.php b/frontend/controllers/CatalogController.php new file mode 100755 index 0000000..b96936a --- /dev/null +++ b/frontend/controllers/CatalogController.php @@ -0,0 +1,233 @@ +request->get('category'); + $filter = Yii::$app->request->get('filters', [ ]); + $filter_check = $filter; + + if(empty( $category->category_id ) && empty( $word )) { + return $this->render('catalog'); + } + + ProductHelper::addLastCategory($category->category_id); + + $params = [ ]; + + $optionsList = ArrayHelper::getColumn(TaxGroup::find() + ->where([ 'is_filter' => 'TRUE' ]) + ->all(), 'alias'); + + if(!empty( $filter[ 'brands' ] )) { + unset( $filter_check[ 'brands' ] ); + $brands = Brand::find() + ->select('brand_id') + ->where([ + 'in', + 'alias', + $filter[ 'brands' ], + ]) + ->all(); + $params[ 'brands' ] = [ ]; + foreach($brands as $brand) { + $params[ 'brands' ][] = $brand->brand_id; + } + } + + if(!empty( $filter[ 'special' ] )) { + unset( $filter_check[ 'special' ] ); + if(!is_array($filter[ 'special' ])) { + $filter[ 'special' ] = [ $filter[ 'special' ] ]; + } + if(in_array('new', $filter[ 'special' ])) { + $params[ 'special' ][ 'is_new' ] = true; + } + if(in_array('top', $filter[ 'special' ])) { + $params[ 'special' ][ 'is_top' ] = true; + } + if(in_array('promo', $filter[ 'special' ])) { + $params[ 'special' ][ 'akciya' ] = true; + } + } + + if(!empty( $filter[ 'prices' ] )) { + unset( $filter_check[ 'prices' ] ); + $params[ 'prices' ] = $filter[ 'prices' ]; + } + + foreach($optionsList as $optionList) { + + if(isset( $filter[ $optionList ] )) { + unset( $filter_check[ $optionList ] ); + $params[ $optionList ] = $filter[ $optionList ]; + } + + } + + if(!empty( $filter_check )) { + $filter = array_diff_key($filter, $filter_check); + Yii::$app->response->redirect([ + 'catalog/category', + 'category' => $category, + 'filters' => $filter, + ], 301); + } + + $productModel = new ProductFrontendSearch(); + //$productQuery = $productModel->getSearchQuery($category, $params); + $productProvider = $productModel->search($category, $params); + + $brandModel = new BrandSearch(); + $brands = $brandModel->getBrands($category, $params) + ->all(); + + $groups = $category->getActiveFilters()->all(); + + $groups = ArrayHelper::index($groups, null, 'name'); + + $priceLimits = $productModel->priceLimits($category, $params); + + /* + * Greedy search for comments and rating + */ + $query = $productProvider->query; + $query->with([ + 'variant', + 'comments', + 'averageRating', + ]); + /* + * End of greedy search for rating and comments + */ + $dataProvider = new ActiveDataProvider([ + 'query' => $query, + 'pagination' => [ + 'pageSize' => 15, + ], + ]); + + + $products = Product::find()->joinWith('categories') + ->where([ + 'category.category_id' => $category->getChildrenByDepth(2)->column(), + ]); + $productsProvider = new ActiveDataProvider([ + 'query' => $products, + 'pagination' => [ + 'pageSize' => 15, + ], + ]); + return $this->render('products', [ + 'category' => $category, + 'brandModel' => $brandModel, + 'dataProvider' => $dataProvider, + 'brands' => $brands, + 'filter' => $filter, + 'params' => $params, + 'productModel' => $productModel, + 'productsProvider' => $dataProvider, + 'groups' => $groups, + 'priceLimits' => $priceLimits, + ]); + + } + + /** + * @param string $product + * @param string $variant + * @return string + */ + public function actionProduct($product, $variant) + { + + + $product = Product::find() + ->joinWith([ + 'variants' => function($query) { + $query->indexBy('sku'); + } + ], true, 'INNER JOIN') + ->where([ + 'product.alias' => $product, + 'product_variant.sku' => $variant, + ])->with('category.parent')->one(); + $variant = $product->variants[$variant]; + $variants = $product->variants; + return $this->render('view', [ + 'variants' => $variants, + 'product' => $product, + 'variant' => $variant, + ]); + } + + public function actionBrands() + { + $dataProvider = new ActiveDataProvider([ + 'query' => Brand::find()->orderBy('name'), + 'pagination' => [ + 'pageSize' => -1, + ] + ]); + + return $this->render('brands', [ + 'dataProvider' => $dataProvider, + ]); + } + + public function actionBrand($brand) + { + $brand = BrandSearch::findByAlias($brand); + + $params = [ + 'brands' => $brand->brand_id, + ]; + + $productModel = new ProductFrontendSearch(); + $productProvider = $productModel->search(null, $params); + + $priceLimits = $productModel->priceLimits(null, $params); + + return $this->render('brand', [ + 'productModel' => $productModel, + 'productProvider' => $productProvider, + 'brand' => $brand, + 'priceLimits' => $priceLimits, + ]); + } + +} diff --git a/frontend/models/ProductFrontendSearch.php b/frontend/models/ProductFrontendSearch.php new file mode 100755 index 0000000..34ffaf6 --- /dev/null +++ b/frontend/models/ProductFrontendSearch.php @@ -0,0 +1,197 @@ + $this->getSearchQuery($category, $params), + 'pagination' => [ + 'pageSize' => 15, + ], + 'sort' => [ + 'attributes' => [ + 'name' => [ + 'asc' => ['name' => SORT_ASC], + 'desc' => ['name' => SORT_DESC], + 'default' => SORT_DESC, + 'label' => 'имени', + ], + 'price' => [ + 'asc' => [ProductVariant::tableName() .'.price' => SORT_ASC], + 'desc' => [ProductVariant::tableName() .'.price' => SORT_DESC], + 'default' => SORT_DESC, + 'label' => 'по цене', + ], + ], + ] + ]); + + if (!$this->validate()) { + return $dataProvider; + } + + + + return $dataProvider; + } + + /** + * @param null|Category $category + * @param array $params + * @return ActiveQuery + */ + public function getSearchQuery($category = null, $params = []) { + if (!empty($category)) { + /** @var ActiveQuery $query */ +// $query = $category->getRelations('product_categories'); + $query = $category->getProducts(); + } else { + $query = Product::find(); + } + $query->select(['product.*']); + $query->joinWith(['enabledVariants','brand','options', 'category']); + + $query->groupBy(['product.product_id', 'product_variant.price']); + + ProductHelper::_setQueryParams($query, $params); + + $query->andWhere(['!=', ProductVariant::tableName() .'.stock', 0]); + + return $query; + } + + public function optionsForCategory($category = null, $params = []) { + $query = TaxOption::find() + ->select([ + TaxOption::tableName() .'.*', + ]) + ->leftJoin(ProductOption::tableName(), ProductOption::tableName() .'.option_id='. TaxOption::tableName() .'.tax_option_id') + ->joinWith('taxGroup') + ->where([TaxGroup::tableName() .'.is_filter' => true]); + + $query->innerJoin('product_variant', 'product_variant.product_id = '. ProductOption::tableName() .'.product_id'); + $query->andWhere(['!=', 'product_variant.stock', 0]); + $query->groupBy(TaxOption::tableName() .'.tax_option_id'); +// $query->having(['>', 'COUNT(product_variant.product_variant_id)', 0]); + + if (!empty($category)) { + $query->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. ProductOption::tableName() .'.product_id'); + $query->andWhere([ProductCategory::tableName() .'.category_id' => $category->category_id]); + } + + $query->orderBy(TaxOption::tableName() .'.sort', SORT_ASC); + $query->limit(null); + +// $queryCount = ProductOption::find() +// ->select(['COUNT('. ProductOption::tableName() .'.product_id)']) +// ->where(ProductOption::tableName() .'.option_id = '. TaxOption::tableName() .'.tax_option_id'); +// $queryCount->andWhere('(SELECT COUNT(pv.product_variant_id) FROM "product_variant" "pv" WHERE pv.stock != 0 AND pv.product_id = '. ProductOption::tableName() .'.product_id) > 0'); +// if (!empty($category)) { +// $queryCount->andWhere('(SELECT COUNT(pc.product_id) FROM product_category pc WHERE pc.product_id = '. ProductOption::tableName() .'.product_id AND pc.category_id = '. $category->category_id .') > 0'); +// } +// if (!empty($params['options'])) { +// $queryCount->innerJoin('tax_option', 'tax_option.tax_option_id = product_option.option_id'); +// $queryCount->innerJoin('tax_group', 'tax_group.tax_group_id = tax_option.tax_group_id'); +// foreach ($params['options'] as $group => $options) { +// $queryCount->andWhere([ +// 'tax_group.alias' => $group, +// 'tax_option.alias' => $options +// ]); +// } +// } +// if (!empty($params['brands'])) { +// $queryCount->innerJoin(Product::tableName(), 'product.product_id='. ProductOption::tableName() .'.product_id'); +// $queryCount->andWhere(['product.brand_id' => $params['brands']]); +// } +// if (!empty($params['prices'])) { +// if ($params['prices']['min'] > 0) { +// $queryCount->andWhere(['>=', 'pv.price', $params['prices']['min']]); +// } +// if ($params['prices']['max'] > 0) { +// $queryCount->andWhere(['<=', 'pv.price', $params['prices']['max']]); +// } +// } +// $query->addSelect(['_items_count' => $queryCount]); + + return $query; + } + + public function priceLimits($category = null, $params = []) { + if (!empty($category)) { + /** @var ActiveQuery $query */ +// $query = $category->getRelations('product_categories'); + $query = $category->getProducts(); + } else { + $query = Product::find(); + } + $query->joinWith('variant'); + + // Price filter fix + unset($params['prices']); + + ProductHelper::_setQueryParams($query, $params, false); + +// $query->select([ +// 'MIN('. ProductVariant::tableName() .'.price) AS priceMIN', +// 'MAX('. ProductVariant::tableName() .'.price) AS priceMAX', +// ]); + + return [ + 'min' => $query->min(ProductVariant::tableName() .'.price'), + 'max' => $query->max(ProductVariant::tableName() .'.price'), + ]; + } +} \ No newline at end of file diff --git a/frontend/views/catalog/_product_list.php b/frontend/views/catalog/_product_list.php new file mode 100755 index 0000000..35eadff --- /dev/null +++ b/frontend/views/catalog/_product_list.php @@ -0,0 +1,31 @@ + + +
diff --git a/frontend/views/catalog/products.php b/frontend/views/catalog/products.php new file mode 100755 index 0000000..a23e024 --- /dev/null +++ b/frontend/views/catalog/products.php @@ -0,0 +1,221 @@ +title = $category->first_text; +$this->params['breadcrumbs'][] = $this->title; + +?> += FilterWidget::widget([ + 'category'=>$category, + 'groups'=> $groups, + 'filter'=> $filter, +])?> +