Commit 5aa7418e91ad61ac033b90ef0263d30c2aec5160

Authored by Karnovsky A
1 parent b15c889e

Base-product#3 functional

common/config/main.php
@@ -100,6 +100,27 @@ return [ @@ -100,6 +100,27 @@ return [
100 'model' => '\common\modules\product\models\ProductCategory', 100 'model' => '\common\modules\product\models\ProductCategory',
101 ] 101 ]
102 ], 102 ],
  103 + 'product_option' => [
  104 + 'name' => Yii::t('product', 'Properties'),
  105 + 'field' => 'options',
  106 + 'entity1' => [
  107 + 'model' => '\common\modules\product\models\Product',
  108 + 'label' => 'Product',
  109 + 'listField' => 'fullname',
  110 + 'key' => 'product_id',
  111 + 'linked_key' => 'product_id',
  112 + ],
  113 + 'entity2' => [
  114 + 'model' => '\common\modules\rubrication\models\TaxOption',
  115 + 'label' => 'Option',
  116 + 'listField' => 'ValueeRenderFlash',
  117 + 'key' => 'tax_option_id',
  118 + 'linked_key' => 'option_id',
  119 + ],
  120 + 'via' => [
  121 + 'model' => 'common\modules\product\models\ProductOption',
  122 + ]
  123 + ],
103 'tax_group_to_category' => [ 124 'tax_group_to_category' => [
104 'name' => Yii::t('product', 'Характеристики по категориям'), 125 'name' => Yii::t('product', 'Характеристики по категориям'),
105 'field' => 'group_to_category', 126 'field' => 'group_to_category',
common/modules/product/controllers/ManageController.php
@@ -33,6 +33,24 @@ class ManageController extends Controller @@ -33,6 +33,24 @@ class ManageController extends Controller
33 } 33 }
34 34
35 public function actionTest() { 35 public function actionTest() {
  36 + return;
  37 + foreach(Product::find()->all() as $product) {
  38 + if (!$product->variant) {
  39 + $product->save();
  40 + $variantModel = new ProductVariant();
  41 + $variantModel->product_id = $product->product_id;
  42 + $variantModel->name = 'test-'. uniqid();
  43 + $variantModel->sku = $variantModel->name;
  44 + $variantModel->price = rand(5, 200000);
  45 + $variantModel->price_old = rand(0, 5) > 3 ? $variantModel->price* (1+rand(0, 10) / 10) : $variantModel->price;
  46 + $variantModel->product_unit_id = rand(1, 5);
  47 + $variantModel->stock = rand(0, 50);
  48 + $variantModel->save();
  49 + }
  50 + }
  51 +
  52 + return;
  53 +
36 $categories = Category::find()->where(['depth' => 2])->all(); 54 $categories = Category::find()->where(['depth' => 2])->all();
37 $cats_ids = []; 55 $cats_ids = [];
38 foreach($categories as $cat) { 56 foreach($categories as $cat) {
@@ -122,8 +140,11 @@ class ManageController extends Controller @@ -122,8 +140,11 @@ class ManageController extends Controller
122 if ($model->load(Yii::$app->request->post()) && $model->save()) { 140 if ($model->load(Yii::$app->request->post()) && $model->save()) {
123 return $this->redirect(['view', 'id' => $model->product_id]); 141 return $this->redirect(['view', 'id' => $model->product_id]);
124 } else { 142 } else {
  143 + $groups = $model->category->getTaxGroups();
  144 +
125 return $this->render('update', [ 145 return $this->render('update', [
126 'model' => $model, 146 'model' => $model,
  147 + 'groups' => $groups,
127 ]); 148 ]);
128 } 149 }
129 } 150 }
common/modules/product/models/Product.php
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 2
3 namespace common\modules\product\models; 3 namespace common\modules\product\models;
4 4
  5 +use common\behaviors\Slug;
5 use common\modules\rubrication\models\TaxOption; 6 use common\modules\rubrication\models\TaxOption;
6 use Yii; 7 use Yii;
7 use common\modules\relation\relationBehavior; 8 use common\modules\relation\relationBehavior;
@@ -23,6 +24,9 @@ class Product extends \yii\db\ActiveRecord @@ -23,6 +24,9 @@ class Product extends \yii\db\ActiveRecord
23 { 24 {
24 /** @var array $variants */ 25 /** @var array $variants */
25 public $_variants = []; 26 public $_variants = [];
  27 +
  28 + /** @var array $_images */
  29 + public $imagesUpload = [];
26 /** 30 /**
27 * @inheritdoc 31 * @inheritdoc
28 */ 32 */
@@ -32,9 +36,16 @@ class Product extends \yii\db\ActiveRecord @@ -32,9 +36,16 @@ class Product extends \yii\db\ActiveRecord
32 [ 36 [
33 'class' => relationBehavior::className(), 37 'class' => relationBehavior::className(),
34 'relations' => [ 38 'relations' => [
35 - 'product_categories' => 'entity1' // Product category 39 + 'product_categories' => 'entity1', // Product category
  40 + 'product_option' => 'entity1' // Product category
36 ] 41 ]
37 ], 42 ],
  43 + [
  44 + 'class' => Slug::className(),
  45 + 'in_attribute' => 'name',
  46 + 'out_attribute' => 'alias',
  47 + 'translit' => true
  48 + ]
38 ]; 49 ];
39 } 50 }
40 51
@@ -54,7 +65,10 @@ class Product extends \yii\db\ActiveRecord @@ -54,7 +65,10 @@ class Product extends \yii\db\ActiveRecord
54 return [ 65 return [
55 [['brand_id'], 'integer'], 66 [['brand_id'], 'integer'],
56 [['name'], 'string', 'max' => 150], 67 [['name'], 'string', 'max' => 150],
57 - [['categories', 'variants'], 'safe'], 68 + [['alias'], 'string', 'max' => 250],
  69 + [['categories', 'variants', 'options'], 'safe'],
  70 + [['imagesUpload'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg, gif'],
  71 + [['description', 'video'], 'safe'],
58 // [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], 72 // [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']],
59 ]; 73 ];
60 } 74 }
@@ -70,6 +84,8 @@ class Product extends \yii\db\ActiveRecord @@ -70,6 +84,8 @@ class Product extends \yii\db\ActiveRecord
70 'brand_id' => Yii::t('product', 'Brand'), 84 'brand_id' => Yii::t('product', 'Brand'),
71 'categories' => Yii::t('product', 'Categories'), // relation behavior field 85 'categories' => Yii::t('product', 'Categories'), // relation behavior field
72 'category' => Yii::t('product', 'Category'), // relation behavior field 86 'category' => Yii::t('product', 'Category'), // relation behavior field
  87 + 'image' => Yii::t('product', 'Image'),
  88 + 'images' => Yii::t('product', 'Images'),
73 ]; 89 ];
74 } 90 }
75 91
@@ -97,6 +113,10 @@ class Product extends \yii\db\ActiveRecord @@ -97,6 +113,10 @@ class Product extends \yii\db\ActiveRecord
97 return $this->hasMany(ProductImage::className(), ['product_id' => 'product_id']); 113 return $this->hasMany(ProductImage::className(), ['product_id' => 'product_id']);
98 } 114 }
99 115
  116 + public function setImages($images) {
  117 + $this->_images = $images;
  118 + }
  119 +
100 /** 120 /**
101 * @return \yii\db\ActiveQuery 121 * @return \yii\db\ActiveQuery
102 */ 122 */
@@ -146,6 +166,10 @@ class Product extends \yii\db\ActiveRecord @@ -146,6 +166,10 @@ class Product extends \yii\db\ActiveRecord
146 return $categories->one(); 166 return $categories->one();
147 } 167 }
148 168
  169 + public function getOptions() {
  170 + return $this->getRelations('product_option');
  171 + }
  172 +
149 /** 173 /**
150 * @inheritdoc 174 * @inheritdoc
151 * @return ProductQuery the active query used by this AR class. 175 * @return ProductQuery the active query used by this AR class.
@@ -159,11 +183,18 @@ class Product extends \yii\db\ActiveRecord @@ -159,11 +183,18 @@ class Product extends \yii\db\ActiveRecord
159 { 183 {
160 parent::afterSave($insert, $changedAttributes); 184 parent::afterSave($insert, $changedAttributes);
161 185
  186 + foreach($this->imagesUpload as $image) {
  187 + $image->saveAs('/images/items/' . $image->baseName .'_'. uniqid() . '.' . $image->extension);
  188 + }
  189 +
162 $todel = []; 190 $todel = [];
163 foreach ($this->variants ? : [] as $_variant) { 191 foreach ($this->variants ? : [] as $_variant) {
164 $todel[$_variant->product_variant_id] = $_variant->product_variant_id; 192 $todel[$_variant->product_variant_id] = $_variant->product_variant_id;
165 } 193 }
166 foreach ($this->_variants as $_variant) { 194 foreach ($this->_variants as $_variant) {
  195 + if (!is_array($_variant)) {
  196 + return;
  197 + }
167 if (!empty($_variant['product_variant_id'])) { 198 if (!empty($_variant['product_variant_id'])) {
168 unset($todel[$_variant['product_variant_id']]); 199 unset($todel[$_variant['product_variant_id']]);
169 $model = ProductVariant::findOne($_variant['product_variant_id']); 200 $model = ProductVariant::findOne($_variant['product_variant_id']);
common/modules/product/models/ProductOption.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace common\modules\product\models;
  4 +
  5 +use Yii;
  6 +
  7 +/**
  8 + * This is the model class for table "product_option".
  9 + *
  10 + * @property integer $product_id
  11 + * @property integer $option_id
  12 + *
  13 + * @property Product $product
  14 + * @property TaxOption $option
  15 + */
  16 +class ProductOption extends \yii\db\ActiveRecord
  17 +{
  18 + /**
  19 + * @inheritdoc
  20 + */
  21 + public static function tableName()
  22 + {
  23 + return 'product_option';
  24 + }
  25 +
  26 + /**
  27 + * @inheritdoc
  28 + */
  29 + public function rules()
  30 + {
  31 + return [
  32 + [['product_id', 'option_id'], 'required'],
  33 + [['product_id', 'option_id'], 'integer'],
  34 + [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']],
  35 + [['option_id'], 'exist', 'skipOnError' => true, 'targetClass' => TaxOption::className(), 'targetAttribute' => ['option_id' => 'tax_option_id']],
  36 + ];
  37 + }
  38 +
  39 + /**
  40 + * @inheritdoc
  41 + */
  42 + public function attributeLabels()
  43 + {
  44 + return [
  45 + 'product_id' => Yii::t('product', 'Product ID'),
  46 + 'option_id' => Yii::t('product', 'Option ID'),
  47 + ];
  48 + }
  49 +
  50 + /**
  51 + * @return \yii\db\ActiveQuery
  52 + */
  53 + public function getProduct()
  54 + {
  55 + return $this->hasOne(Product::className(), ['product_id' => 'product_id']);
  56 + }
  57 +
  58 + /**
  59 + * @return \yii\db\ActiveQuery
  60 + */
  61 + public function getOption()
  62 + {
  63 + return $this->hasOne(TaxOption::className(), ['tax_option_id' => 'option_id']);
  64 + }
  65 +}
common/modules/product/models/ProductSearch.php
@@ -6,6 +6,7 @@ use Yii; @@ -6,6 +6,7 @@ use Yii;
6 use yii\base\Model; 6 use yii\base\Model;
7 use yii\data\ActiveDataProvider; 7 use yii\data\ActiveDataProvider;
8 use common\modules\product\models\Product; 8 use common\modules\product\models\Product;
  9 +use yii\web\NotFoundHttpException;
9 10
10 /** 11 /**
11 * ProductSearch represents the model behind the search form about `common\modules\product\models\Product`. 12 * ProductSearch represents the model behind the search form about `common\modules\product\models\Product`.
@@ -70,7 +71,7 @@ class ProductSearch extends Product @@ -70,7 +71,7 @@ class ProductSearch extends Product
70 71
71 public static function findByAlias($alias) { 72 public static function findByAlias($alias) {
72 /** @var ProductQuery $query */ 73 /** @var ProductQuery $query */
73 - $query = Category::find(); 74 + $query = Product::find();
74 $query->byAlias($alias); 75 $query->byAlias($alias);
75 if (($model = $query->one()) !== null) { 76 if (($model = $query->one()) !== null) {
76 return $model; 77 return $model;
common/modules/product/views/manage/_form.php
@@ -20,6 +20,9 @@ use unclead\widgets\MultipleInputColumn; @@ -20,6 +20,9 @@ use unclead\widgets\MultipleInputColumn;
20 20
21 <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?> 21 <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
22 22
  23 + <?= $form->field($model, 'description')->widget(\mihaildev\ckeditor\CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ], ]); ?>
  24 + <?= $form->field($model, 'video')->textarea()->label('Video embeded'); ?>
  25 +
23 <?= $form->field($model, 'brand_id')->dropDownList( 26 <?= $form->field($model, 'brand_id')->dropDownList(
24 ArrayHelper::map(ProductHelper::getBrands()->all(), 'brand_id', 'name'), 27 ArrayHelper::map(ProductHelper::getBrands()->all(), 'brand_id', 'name'),
25 [ 28 [
@@ -30,21 +33,18 @@ use unclead\widgets\MultipleInputColumn; @@ -30,21 +33,18 @@ use unclead\widgets\MultipleInputColumn;
30 <?= $form->field($model, 'categories')->dropDownList( 33 <?= $form->field($model, 'categories')->dropDownList(
31 ArtboxTreeHelper::treeMap(ProductHelper::getCategories(), 'category_id', 'name'), 34 ArtboxTreeHelper::treeMap(ProductHelper::getCategories(), 'category_id', 'name'),
32 [ 35 [
33 -// 'prompt' => Yii::t('product', 'Select category'),  
34 'multiple' => true 36 'multiple' => true
35 ] 37 ]
36 ) ?> 38 ) ?>
37 39
38 - <?php /*= $form->field($model, 'images[]')->widget(FileInput::classname(), [ 40 +
  41 +
  42 + <?php /*= $form->field($model, 'imagesUpload[]')->widget(FileInput::classname(), [
39 'options' => [ 43 'options' => [
40 'accept' => 'image/*', 44 'accept' => 'image/*',
41 'multiple' => true, 45 'multiple' => true,
42 ], 46 ],
43 - 'pluginOptions' => [  
44 -// 'uploadUrl' => \yii\helpers\Url::to(['/site/file-upload']),  
45 - ]  
46 - ]);  
47 - */?> 47 + ]);*/?>
48 48
49 <?= $form->field($model, 'variants')->widget(MultipleInput::className(), [ 49 <?= $form->field($model, 'variants')->widget(MultipleInput::className(), [
50 'columns' => [ 50 'columns' => [
@@ -90,6 +90,16 @@ use unclead\widgets\MultipleInputColumn; @@ -90,6 +90,16 @@ use unclead\widgets\MultipleInputColumn;
90 ]); 90 ]);
91 ?> 91 ?>
92 92
  93 + <?php foreach($groups->all() as $group) :?>
  94 + <?= $form->field($model, 'options')->checkboxList(
  95 + ArrayHelper::map($group->options, 'tax_option_id', 'ValueRenderFlash'),
  96 + [
  97 + 'multiple' => true,
  98 + 'unselect' => null,
  99 + ]
  100 + )->label($group->name);?>
  101 + <?php endforeach?>
  102 +
93 <div class="form-group"> 103 <div class="form-group">
94 <?= Html::submitButton($model->isNewRecord ? Yii::t('product', 'Create') : Yii::t('product', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> 104 <?= Html::submitButton($model->isNewRecord ? Yii::t('product', 'Create') : Yii::t('product', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
95 </div> 105 </div>
common/modules/product/views/manage/update.php
@@ -18,6 +18,7 @@ $this-&gt;params[&#39;breadcrumbs&#39;][] = Yii::t(&#39;product&#39;, &#39;Update&#39;); @@ -18,6 +18,7 @@ $this-&gt;params[&#39;breadcrumbs&#39;][] = Yii::t(&#39;product&#39;, &#39;Update&#39;);
18 18
19 <?= $this->render('_form', [ 19 <?= $this->render('_form', [
20 'model' => $model, 20 'model' => $model,
  21 + 'groups' => $groups,
21 ]) ?> 22 ]) ?>
22 23
23 </div> 24 </div>
common/modules/rubrication/helpers/RubricationHelper.php
@@ -40,4 +40,12 @@ class RubricationHelper { @@ -40,4 +40,12 @@ class RubricationHelper {
40 return $module->types; 40 return $module->types;
41 41
42 } 42 }
  43 +
  44 + public function checkboxList($items, $options = [])
  45 + {
  46 + $this->adjustLabelFor($options);
  47 + $this->parts['{input}'] = Html::activeCheckboxList($this->model, $this->attribute, $items, $options);
  48 +
  49 + return $this;
  50 + }
43 } 51 }
44 \ No newline at end of file 52 \ No newline at end of file
common/modules/rubrication/models/TaxGroup.php
@@ -23,6 +23,7 @@ use Yii; @@ -23,6 +23,7 @@ use Yii;
23 */ 23 */
24 class TaxGroup extends \yii\db\ActiveRecord 24 class TaxGroup extends \yii\db\ActiveRecord
25 { 25 {
  26 + public $_options = [];
26 /** 27 /**
27 * @inheritdoc 28 * @inheritdoc
28 */ 29 */
console/migrations/m160304_065108_product.php
@@ -69,7 +69,10 @@ class m160304_065108_product extends Migration @@ -69,7 +69,10 @@ class m160304_065108_product extends Migration
69 $this->createTable('{{%product}}', [ 69 $this->createTable('{{%product}}', [
70 'product_id' => $this->primaryKey(), 70 'product_id' => $this->primaryKey(),
71 'name' => $this->string(255)->notNull(), 71 'name' => $this->string(255)->notNull(),
  72 + 'alias' => $this->string(255),
72 'brand_id' => $this->integer(), 73 'brand_id' => $this->integer(),
  74 + 'description' => $this->text(),
  75 + 'video' => $this->text(),
73 ], $tableOptions); 76 ], $tableOptions);
74 77
75 $this->addForeignKey('fki_product_id', 'product_category', 'product_id', 'product', 'product_id', 'NO ACTION', 'NO ACTION'); 78 $this->addForeignKey('fki_product_id', 'product_category', 'product_id', 'product', 'product_id', 'NO ACTION', 'NO ACTION');
console/migrations/m160324_075409_product_option.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\db\Migration;
  4 +
  5 +class m160324_075409_product_option extends Migration
  6 +{
  7 + public function up()
  8 + {
  9 + $tableOptions = null;
  10 + if ($this->db->driverName === 'mysql') {
  11 + // Only for MySQL
  12 + $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
  13 +
  14 + // @todo https://habrahabr.ru/post/138947/
  15 + } elseif ($this->db->driverName === 'pgsql') {
  16 + // Only for PostgreSQL
  17 + // @todo use intarray field for tax_options
  18 + }
  19 +
  20 + $this->createTable('{{%product_option}}', [
  21 + 'product_id' => $this->integer()->notNull(),
  22 + 'option_id' => $this->integer()->notNull(),
  23 + ], $tableOptions);
  24 + $this->addPrimaryKey('product_option_pkey', 'product_option', ['product_id', 'option_id']);
  25 + $this->addForeignKey('product_option_product_fkey', 'product_option', 'product_id', 'product', 'product_id', 'NO ACTION', 'NO ACTION');
  26 + $this->addForeignKey('product_option_option_fkey', 'product_option', 'option_id', 'tax_option', 'tax_option_id', 'NO ACTION', 'NO ACTION');
  27 + }
  28 +
  29 + public function down()
  30 + {
  31 + $this->dropTable('{{%product_option}}');
  32 + }
  33 +
  34 + /*
  35 + // Use safeUp/safeDown to run migration code within a transaction
  36 + public function safeUp()
  37 + {
  38 + }
  39 +
  40 + public function safeDown()
  41 + {
  42 + }
  43 + */
  44 +}
frontend/controllers/CatalogController.php
@@ -7,8 +7,11 @@ use common\modules\product\models\Category; @@ -7,8 +7,11 @@ use common\modules\product\models\Category;
7 use common\modules\product\models\CategorySearch; 7 use common\modules\product\models\CategorySearch;
8 use common\modules\product\models\Product; 8 use common\modules\product\models\Product;
9 use common\modules\product\models\ProductCategory; 9 use common\modules\product\models\ProductCategory;
  10 +use common\modules\product\models\ProductOption;
10 use common\modules\product\models\ProductSearch; 11 use common\modules\product\models\ProductSearch;
11 use common\modules\product\models\ProductVariant; 12 use common\modules\product\models\ProductVariant;
  13 +use common\modules\rubrication\models\TaxGroup;
  14 +use common\modules\rubrication\models\TaxOption;
12 use yii\data\ActiveDataProvider; 15 use yii\data\ActiveDataProvider;
13 use yii\data\Pagination; 16 use yii\data\Pagination;
14 use yii\data\Sort; 17 use yii\data\Sort;
@@ -56,10 +59,34 @@ class CatalogController extends \yii\web\Controller @@ -56,10 +59,34 @@ class CatalogController extends \yii\web\Controller
56 ]); 59 ]);
57 $all_count = $query->count(); 60 $all_count = $query->count();
58 61
  62 + $brandsQuery = Brand::find()
  63 + ->innerJoinWith('products')
  64 + ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. Product::tableName() .'.product_id')
  65 + ->where([
  66 + ProductCategory::tableName() .'.category_id' => $category->category_id
  67 + ])
  68 + ->groupBy(Brand::tableName() .'.brand_id');
  69 + $brands = $brandsQuery->all();
  70 + $brands_count = $brandsQuery->count();
  71 +
  72 + $optionsQuery = TaxOption::find()
  73 +// ->select([TaxOption::tableName() .'.tax_option_id', TaxOption::tableName() .'.alias'])
  74 + ->innerJoin(ProductOption::tableName(), ProductOption::tableName() .'.option_id='. TaxOption::tableName() .'.tax_option_id')
  75 + ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. ProductOption::tableName() .'.product_id')
  76 + ->where([
  77 + ProductCategory::tableName() .'.category_id' => $category->category_id
  78 + ])
  79 + ->groupBy(TaxOption::tableName() .'.tax_option_id');
  80 + $all_options = [];
  81 + foreach($optionsQuery->all() as $_option) {
  82 + $all_options[] = $_option;
  83 + }
  84 +
59 $priceQuery = clone $query; 85 $priceQuery = clone $query;
60 $priceMin = $priceMinCurr = $priceQuery->min(ProductVariant::tableName() .'.price'); 86 $priceMin = $priceMinCurr = $priceQuery->min(ProductVariant::tableName() .'.price');
61 $priceMax = $priceMaxCurr = $priceQuery->max(ProductVariant::tableName() .'.price'); 87 $priceMax = $priceMaxCurr = $priceQuery->max(ProductVariant::tableName() .'.price');
62 88
  89 + // Prices
63 if (($price_interval = \Yii::$app->request->get('price_interval')) != false) { 90 if (($price_interval = \Yii::$app->request->get('price_interval')) != false) {
64 $price_interval = explode(';', $price_interval); 91 $price_interval = explode(';', $price_interval);
65 $price_interval = [ 92 $price_interval = [
@@ -75,21 +102,40 @@ class CatalogController extends \yii\web\Controller @@ -75,21 +102,40 @@ class CatalogController extends \yii\web\Controller
75 $priceMaxCurr = $price_interval[1]; 102 $priceMaxCurr = $price_interval[1];
76 } 103 }
77 } 104 }
  105 +
  106 + $groups = [];
  107 + foreach($category->getTaxGroups()->all() as $_group) {
  108 + $groups[$_group->tax_group_id] = $_group;
  109 + }
  110 + foreach ($all_options as $option) {
  111 + $groups[$option->tax_group_id]->_options[] = $option;
  112 + }
  113 + foreach($groups as $i => $group) {
  114 + if (empty($group->_options))
  115 + unset($groups[$i]);
  116 + }
  117 +
  118 + // Options
  119 + if (($options = \Yii::$app->request->get('option')) != false) {
  120 + $query->innerJoin(ProductOption::tableName(), ProductOption::tableName() .'.product_id='. Product::tableName() .'.product_id');
  121 + $query->innerJoin(TaxOption::tableName(), TaxOption::tableName() .'.tax_option_id='. ProductOption::tableName() .'.option_id');
  122 + foreach($options as $group_alias => $option_alias) {
  123 + $group = TaxGroup::find()->where(['like', 'alias', $group_alias])->one();
  124 + if (!$group) {
  125 + continue;
  126 + }
  127 + $query->andWhere([TaxOption::tableName() .'.tax_group_id' => $group->tax_group_id, TaxOption::tableName() .'.alias' => $option_alias]);
  128 + }
  129 + }
  130 +
78 $count = $query->count(); 131 $count = $query->count();
  132 +
79 $pages = new Pagination(['totalCount' => $count, 'pageSize' => $per_page]); 133 $pages = new Pagination(['totalCount' => $count, 'pageSize' => $per_page]);
80 $query->offset($pages->offset) 134 $query->offset($pages->offset)
81 ->orderBy($sort->orders) 135 ->orderBy($sort->orders)
82 ->limit($pages->limit); 136 ->limit($pages->limit);
83 $products = $query->all(); 137 $products = $query->all();
84 138
85 - $brandsQuery = Brand::find()->innerJoinWith('products')->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. Product::tableName() .'.product_id')->where([  
86 - ProductCategory::tableName() .'.category_id' => $category->category_id  
87 - ])->groupBy(Brand::tableName() .'.brand_id');  
88 - $brands = $brandsQuery->all();  
89 - $brands_count = $brandsQuery->count();  
90 -  
91 - $groups = $category->getTaxGroups()->all();  
92 -  
93 return $this->render( 139 return $this->render(
94 'products', 140 'products',
95 [ 141 [
@@ -107,6 +153,7 @@ class CatalogController extends \yii\web\Controller @@ -107,6 +153,7 @@ class CatalogController extends \yii\web\Controller
107 'brands' => $brands, 153 'brands' => $brands,
108 'brands_count' => $brands_count, 154 'brands_count' => $brands_count,
109 'groups' => $groups, 155 'groups' => $groups,
  156 + 'options' => $options,
110 ] 157 ]
111 ); 158 );
112 } 159 }
@@ -118,7 +165,22 @@ class CatalogController extends \yii\web\Controller @@ -118,7 +165,22 @@ class CatalogController extends \yii\web\Controller
118 if (empty($product->product_id)) { 165 if (empty($product->product_id)) {
119 throw new HttpException(404 ,'Page not found'); 166 throw new HttpException(404 ,'Page not found');
120 } 167 }
121 - return $this->render('product'); 168 + $groups = [];
  169 + foreach($product->category->getTaxGroups()->all() as $_group) {
  170 + $groups[$_group->tax_group_id] = $_group;
  171 + }
  172 + foreach ($product->options as $option) {
  173 + $groups[$option->tax_group_id]->_options[] = $option;
  174 + }
  175 + foreach($groups as $i => $group) {
  176 + if (empty($group->_options))
  177 + unset($groups[$i]);
  178 + }
  179 +
  180 + return $this->render('product', [
  181 + 'product' => $product,
  182 + 'properties' => $groups,
  183 + ]);
122 } 184 }
123 185
124 public function actionBrands() 186 public function actionBrands()
frontend/views/catalog/product.php 0 → 100644
  1 +<?php
  2 +/** @var $this \yii\web\View */
  3 +/** @var $dataProvider \yii\data\ActiveDataProvider */
  4 +
  5 +$this->title = $product->name;
  6 +foreach($product->category->getParents()->all() as $parent) {
  7 + $this->params['breadcrumbs'][] = ['label' => $parent->name, 'url' => ['catalog/category', 'alias' => $parent->alias]];
  8 +}
  9 +$this->params['breadcrumbs'][] = ['label' => $product->category->name, 'url' => ['catalog/category', 'alias' => $product->category->alias]];
  10 +$this->params['breadcrumbs'][] = $product->name .' #'. $product->variant->sku;
  11 +?>
  12 +<h1 class="open_card_item_title"><?= $product->name .' '. $product->variant->name?></h1>
  13 +
  14 +<div class="item_3_blocks_wrap"> <!-- flex container -->
  15 + <div class="item_img_block"> <!-- блок с фотографиями -->
  16 + <div class="main_img">
  17 + <?php if (empty($product->image)) :?>
  18 + <img src="/images/no_photo_big.png" alt="<?= $product->name?>">
  19 + <?php else :?>
  20 + <img src="/images/<?= $product->image->image?>" alt="<?= $product->image->alt ? $product->image->alt : $product->name?>">
  21 + <?php endif?>
  22 + <!--<span class="new">НОВИНКА</span>
  23 + <span class="top">ТОП</span>-->
  24 + </div>
  25 + <?php if (!empty($product->images)) :?>
  26 + <div class="main_img_slide">
  27 + <?php foreach($product->images as $image) :?>
  28 + <div class="small_img_block active">
  29 + <img src="/images/<?= $image->image?>" alt="<?= $image->alt ? $image->alt : $product->name?>">
  30 + </div>
  31 + <?php endforeach?>
  32 +
  33 + <img class="slider_arrow_right" src="/images/slider_right.png" alt="">
  34 + <img class="slider_arrow_left" src="/images/slider_left.png" alt="">
  35 + </div>
  36 + <?php endif?>
  37 +
  38 + </div> <!-- конец блока с фотографиями -->
  39 +
  40 +
  41 + <div class="busket_block"> <!-- блок с счетчиком и кнопкой добавить в корзину -->
  42 + <div class="top_code">
  43 + <span class="code">Код: <?= $product->variant->sku?></span>
  44 + <span class="have"><img src="/images/ok_icon_green.png" alt=""><?= $product->stock !== 0 ? ' есть в наличии' : ' нет в наличии'?></span>
  45 + </div>
  46 +
  47 + <div class="grey_bg">
  48 + <div class="counter">
  49 + <div class="price"><?= $product->variant->price?></div>
  50 + <div class="sign">грн.</div>
  51 + <div class="count_block">
  52 + <div class="count_number">1</div>
  53 + <div class="count_buttons">
  54 + <div class="button_plus">+</div>
  55 + <div class="button_minus">-</div>
  56 + </div>
  57 + </div>
  58 + </div>
  59 +
  60 + <div class="in_cart_btn">
  61 + <a href="#">
  62 + <button class="cart_btn" data-id="<?= $product->variant->product_variant_id?>"> в корзину <img src="/images/ico_basket_white.png" alt=""></button>
  63 + </a>
  64 + </div>
  65 +
  66 + <!--<div class="to_compare_link">
  67 + <img src="/images/ico_scales.png" alt="">
  68 + <a href="#" class="add_to_compare">добавить к сравнению</a>
  69 + </div>-->
  70 + </div>
  71 + <div class="quick_order">
  72 + <form action="">
  73 + <span class="text">БЫСТРЫЙ ЗАКАЗ</span>
  74 + <input type="text" class="quick_order_phone" name="quick_order_phone" placeholder="(0XX) XXX-XX-XX">
  75 + <button type="submit">заказать</button>
  76 + </form>
  77 + </div>
  78 +
  79 + <div class="delivery">
  80 + <p>
  81 + Доставка товара на следующий день после выставления счета. Мы доставим “День в <br> день” — уточните это у менеджера.
  82 + </p>
  83 + <a href="#">Подробно о доставке</a>
  84 + </div>
  85 +
  86 + </div><!-- конец блока с счетчиком и кнопкой добавить в корзину -->
  87 +
  88 + <div class="character_block"> <!-- блок с характеристиками -->
  89 + <?php if (!empty($properties)) :?>
  90 + <h3>Характеристики</h3>
  91 + <ul>
  92 + <?php foreach($properties as $group) :?>
  93 + <li>
  94 + <div class="each">
  95 + <div class="title"><?= $group->name?></div>
  96 + <div class="tech">
  97 + <?php foreach($group->_options as $option) :?>&nbsp;<?= $option->ValueRenderHTML?><?php endforeach?>
  98 + </div>
  99 + </div>
  100 + </li>
  101 + <?php endforeach?>
  102 + </ul>
  103 + <?php endif?>
  104 +
  105 + <!--<div class="tech_links">
  106 + <a href="#">Описание</a>
  107 + <a href="#">Видео</a>
  108 + <a href="#">Отзывы(12)</a>
  109 + </div>-->
  110 +
  111 + </div><!-- закрытие блока с характеристиками -->
  112 +
  113 + <div class="tabs_block"> <!-- Табы с описанием видео и отзывами -->
  114 + <div class="ionTabs" id="tabs_1" data-name="Tabs_Group_name">
  115 + <ul class="ionTabs__head">
  116 + <?php if (!empty($properties)) :?>
  117 + <li class="ionTabs__tab" data-target="Tab_1_name">Характеристики</li>
  118 + <?php endif?>
  119 + <?php if (!empty($product->description)) :?>
  120 + <li class="ionTabs__tab" data-target="Tab_2_name">Описание</li>
  121 + <?php endif?>
  122 + <?php if (!empty($product->description)) :?>
  123 + <li class="ionTabs__tab" data-target="Tab_3_name">Видео</li>
  124 + <?php endif?>
  125 +<!-- <li class="ionTabs__tab" data-target="Tab_4_name">Отзывы(12)</li>-->
  126 + </ul>
  127 + <div class="ionTabs__body">
  128 + <?php if (!empty($properties)) :?>
  129 + <div class="ionTabs__item" data-name="Tab_1_name">
  130 + <ul>
  131 + <?php foreach($properties as $group) :?>
  132 + <li>
  133 + <div class="each">
  134 + <div class="title"><?= $group->name?></div>
  135 + <div class="tech">
  136 + <?php foreach($group->_options as $option) :?>&nbsp;<?= $option->ValueRenderHTML?><?php endforeach?>
  137 + </div>
  138 + </div>
  139 + </li>
  140 + <?php endforeach?>
  141 + </ul>
  142 + </div>
  143 + <?php endif?>
  144 + <?php if (!empty($product->description)) :?>
  145 + <div class="ionTabs__item" data-name="Tab_2_name">
  146 + <?= $product->description?>
  147 + </div>
  148 + <?php endif?>
  149 + <?php if (!empty($product->video)) :?>
  150 + <div class="ionTabs__item" data-name="Tab_3_name">
  151 + <?= $product->video?>
  152 + </div>
  153 + <?php endif?>
  154 + <!--<div class="ionTabs__item" data-name="Tab_4_name">
  155 + <span class="tabs_item_name">Отзывы</span>
  156 + </div>-->
  157 +
  158 + <div class="ionTabs__preloader"></div>
  159 + </div>
  160 + </div>
  161 +
  162 + </div> <!-- конец табов с описанием видео и отзывами -->
  163 +
  164 +</div> <!-- end flex container -->
frontend/views/catalog/product_item.php
@@ -4,12 +4,21 @@ @@ -4,12 +4,21 @@
4 <div class="item" data-id="<?= $product->product_id?>"> 4 <div class="item" data-id="<?= $product->product_id?>">
5 <!--<div class="new">АКЦИЯ</div> 5 <!--<div class="new">АКЦИЯ</div>
6 <div class="top">Toп</div>--> 6 <div class="top">Toп</div>-->
7 - <a href="#" class="item_link"><div class="pic"><img src="/images/items/01.jpg"></div> 7 + <a href="<?= \yii\helpers\Url::to(['catalog/product', 'alias' => $product->alias])?>" class="item_link">
  8 + <div class="pic">
  9 + <?php if (empty($product->image)) :?>
  10 + <img src="/images/no_photo.png">
  11 + <?php else :?>
  12 + <img src="/images/<?= $product->image->image?>" alt="<?= $product->image->alt ? $product->image->alt : $product->name?>">
  13 + <?php endif?>
  14 + </div>
8 <div class="title_item"><?= $product->name?></div></a> 15 <div class="title_item"><?= $product->name?></div></a>
9 <div class="brand">Бренд: <span><?= $product->brand->name?></span></div> 16 <div class="brand">Бренд: <span><?= $product->brand->name?></span></div>
10 <div class="type"><?= implode(', ', $product->categoriesNames)?></div> 17 <div class="type"><?= implode(', ', $product->categoriesNames)?></div>
  18 + <?php if($product->variant) :?>
11 <div class="price"><?= $product->variant->price?> <span>грн.</span></div> 19 <div class="price"><?= $product->variant->price?> <span>грн.</span></div>
12 <button class="basket_add_but" data-id="<?= $product->variant->product_variant_id?>">в корзину</button> 20 <button class="basket_add_but" data-id="<?= $product->variant->product_variant_id?>">в корзину</button>
  21 + <?php endif?>
13 <a href="#" class="compare_add_but" data-id="<?= $product->product_id?>"><span>добавить к сравнению</span></a> 22 <a href="#" class="compare_add_but" data-id="<?= $product->product_id?>"><span>добавить к сравнению</span></a>
14 <img class="item_bottom_img" src="/images/nc_item_bottom.png" alt=""> 23 <img class="item_bottom_img" src="/images/nc_item_bottom.png" alt="">
15 </div> 24 </div>
16 \ No newline at end of file 25 \ No newline at end of file
frontend/views/catalog/products.php
@@ -74,9 +74,9 @@ $this-&gt;params[&#39;breadcrumbs&#39;][] = $category-&gt;name; @@ -74,9 +74,9 @@ $this-&gt;params[&#39;breadcrumbs&#39;][] = $category-&gt;name;
74 <li><?= $group->name?> 74 <li><?= $group->name?>
75 <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> 75 <div class="arrow"><img src="/images/head_down.png" alt=""></i></div>
76 <div class="price_filter"> 76 <div class="price_filter">
77 - <?php foreach($group->options as $option) :?> 77 + <?php foreach($group->_options as $option) :?>
78 <div class="checkbox"> 78 <div class="checkbox">
79 - <label><input type="checkbox" name="option[<?= $group->alias?>][]" value="<?= $option->alias?>" /></label> 79 + <label><input type="checkbox" name="option[<?= $group->alias?>][]" value="<?= $option->alias?>"<?= (isset($options[$group->alias]) && in_array($option->alias, $options[$group->alias])) ? ' checked' : ''?> /></label>
80 <a href="#"><?= $option->ValueRenderHTML?></a> 80 <a href="#"><?= $option->ValueRenderHTML?></a>
81 </div> 81 </div>
82 <?php endforeach?> 82 <?php endforeach?>
frontend/web/images/no_photo.png 0 → 100644

23.4 KB

frontend/web/images/no_photo_big.png 0 → 100644

9.21 KB