Commit de350755 by semenov

Доработка свойств товаров

parent fc4d97ab
<?php
/**
* @author Semenov Alexander <semenov@skeeks.com>
* @link http://skeeks.com/
* @copyright 2010 SkeekS (СкикС)
* @date 09.03.2015
*/
namespace skeeks\modules\cms\catalog\controllers;
use skeeks\cms\modules\admin\controllers\AdminModelEditorSmartController;
use skeeks\modules\cms\catalog\models\Product;
use skeeks\modules\cms\catalog\models\ProductPropertyEnum;
/**
* Class AdminProductController
* @package skeeks\modules\cms\catalog\controllers
*/
class AdminProductPropertyEnumController extends AdminModelEditorSmartController
{
public function init()
{
$this->_label = "Управление значениями свойств";
$this->_modelShowAttribute = "value";
$this->_modelClassName = ProductPropertyEnum::className();
$this->modelValidate = true;
$this->enableScenarios = true;
parent::init();
}
}
\ No newline at end of file
......@@ -50,8 +50,6 @@ class m150310_110557_create_product_property__product__map extends Migration
$this->execute("ALTER TABLE {{%catalog_product_property_map}} ADD INDEX(value);");
$this->execute("ALTER TABLE {{%catalog_product_property_map}} ADD UNIQUE(property_id,product_id);");
$this->execute("ALTER TABLE {{%catalog_product_property_map}} COMMENT = 'Связь товара свойства и значения';");
$this->addForeignKey(
......
<?php
/**
* @author Semenov Alexander <semenov@skeeks.com>
* @link http://skeeks.com/
* @copyright 2010 SkeekS (СкикС)
* @date 10.03.2015
*/
use yii\db\Schema;
use yii\db\Migration;
class m150514_110557_create_table__catalog_product_property_enum extends Migration
{
public function up()
{
$tableExist = $this->db->getTableSchema("{{%catalog_product_property_enum}}", true);
if ($tableExist)
{
return true;
}
$tableOptions = null;
if ($this->db->driverName === 'mysql') {
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB';
}
$this->createTable("{{%catalog_product_property_enum}}", [
'id' => Schema::TYPE_PK,
'created_by' => Schema::TYPE_INTEGER . ' NULL',
'updated_by' => Schema::TYPE_INTEGER . ' NULL',
'created_at' => Schema::TYPE_INTEGER . ' NULL',
'updated_at' => Schema::TYPE_INTEGER . ' NULL',
'property_id' => Schema::TYPE_INTEGER . ' NULL',
'value' => Schema::TYPE_STRING . '(255) NOT NULL',
'def' => "CHAR(1) NOT NULL DEFAULT 'N'",
'code' => Schema::TYPE_STRING. '(32) NOT NULL',
'priority' => Schema::TYPE_INTEGER. "(11) NOT NULL DEFAULT '500'",
], $tableOptions);
$this->execute("ALTER TABLE {{%catalog_product_property_enum}} ADD INDEX(updated_by);");
$this->execute("ALTER TABLE {{%catalog_product_property_enum}} ADD INDEX(created_by);");
$this->execute("ALTER TABLE {{%catalog_product_property_enum}} ADD INDEX(created_at);");
$this->execute("ALTER TABLE {{%catalog_product_property_enum}} ADD INDEX(updated_at);");
$this->execute("ALTER TABLE {{%catalog_product_property_enum}} ADD INDEX(property_id);");
$this->execute("ALTER TABLE {{%catalog_product_property_enum}} ADD INDEX(def);");
$this->execute("ALTER TABLE {{%catalog_product_property_enum}} ADD INDEX(code);");
$this->execute("ALTER TABLE {{%catalog_product_property_enum}} ADD INDEX(priority);");
$this->execute("ALTER TABLE {{%catalog_product_property_enum}} ADD INDEX(value);");
$this->execute("ALTER TABLE {{%catalog_product_property_enum}} COMMENT = 'Справочник значений свойств типа список';");
$this->addForeignKey(
'catalog_product_property_enum_created_by', "{{%catalog_product_property_enum}}",
'created_by', '{{%cms_user}}', 'id', 'RESTRICT', 'RESTRICT'
);
$this->addForeignKey(
'catalog_product_property_enum_updated_by', "{{%catalog_product_property_enum}}",
'updated_by', '{{%cms_user}}', 'id', 'RESTRICT', 'RESTRICT'
);
$this->addForeignKey(
'catalog_product_property_enum_property_id', "{{%catalog_product_property_enum}}",
'property_id', '{{%catalog_product_property}}', 'id', 'CASCADE', 'CASCADE'
);
}
public function down()
{
$this->dropForeignKey("catalog_product_property_enum_created_by", "{{%catalog_product_property_enum}}");
$this->dropForeignKey("catalog_product_property_enum_updated_by", "{{%catalog_product_property_enum}}");
$this->dropForeignKey("catalog_product_property_enum_property_id", "{{%catalog_product_property_enum}}");
$this->dropTable("{{%catalog_product_property_enum}}");
}
}
\ No newline at end of file
<?php
/**
* @author Semenov Alexander <semenov@skeeks.com>
* @link http://skeeks.com/
* @copyright 2010 SkeekS (СкикС)
* @date 29.04.2015
*/
use yii\db\Schema;
use yii\db\Migration;
class m150514_120857_alter_table__catalog_product_property extends Migration
{
public function safeUp()
{
$this->execute("ALTER TABLE {{%catalog_product_property%}} ADD `smart_filtrable` CHAR(1) NOT NULL DEFAULT 'N' ;");
}
public function safeDown()
{
echo "m150514_120857_alter_table__catalog_product_property cannot be reverted.\n";
return false;
}
}
......@@ -285,9 +285,17 @@ class Product extends PageAdvanced
*/
public function getPropertiesAll()
{
return ProductProperty::find()->active()->orderBy("priority ASC")->all();
return ProductProperty::find()->active()->orderBy("priority DESC")->all();
}
/**
* @param $id
* @return array|null|\yii\db\ActiveRecord
*/
public function findPropertyValue($id)
{
return $this->getPropertyValues()->where(['property_id' => $id]);
}
/**
* @return string
......@@ -310,7 +318,7 @@ class Product extends PageAdvanced
}
/**
* @return FormValidateModel
* @return PropertiesValidateModel
*/
public function createPropertiesValidateModel()
{
......
......@@ -7,7 +7,9 @@
*/
namespace skeeks\modules\cms\catalog\models;
use skeeks\cms\base\PropertyType;
use skeeks\cms\base\propertyTypes\PropertyTypeStandartElement;
use skeeks\cms\components\Cms;
use skeeks\modules\cms\catalog\query\ProductPropertyQuery;
use \Yii as Yii;
use skeeks\cms\base\db\ActiveRecord;
......@@ -17,6 +19,8 @@ use skeeks\cms\models\behaviors\HasStatus;
use skeeks\cms\models\behaviors\Implode;
use skeeks\cms\models\Core;
use yii\base\Model;
use yii\db\BaseActiveRecord;
use yii\helpers\ArrayHelper;
use yii\widgets\ActiveForm;
/**
......@@ -44,6 +48,7 @@ use yii\widgets\ActiveForm;
* @property string $with_description
* @property string $searchable
* @property string $filtrable
* @property string $smart_filtrable
* @property string $is_required
* @property integer $version
* @property string $component
......@@ -61,6 +66,29 @@ class ProductProperty extends Core
return '{{%catalog_product_property}}';
}
public function init()
{
parent::init();
$this->on(BaseActiveRecord::EVENT_BEFORE_INSERT, [$this, "processBeforeSave"]);
$this->on(BaseActiveRecord::EVENT_BEFORE_UPDATE, [$this, "processBeforeSave"]);
}
public function processBeforeSave()
{
if ($this->component)
{
/**
* @var $propertyType PropertyType
*/
$propertyTypeClassName = $this->component;
$propertyType = new $propertyTypeClassName();
$this->property_type = $propertyType->code;
$this->multiple = $propertyType->multiple ? Cms::BOOL_Y : Cms::BOOL_N;
}
}
/**
* @inheritdoc
*/
......@@ -77,14 +105,22 @@ class ProductProperty extends Core
{
return array_merge(parent::rules(), [
[['created_by', 'updated_by', 'created_at', 'updated_at', 'group_id', 'priority', 'row_count', 'col_count', 'multiple_cnt', 'version'], 'integer'],
[['name'], 'required'],
[['name', 'component'], 'required'],
[['default_value', 'component_settings'], 'string'],
[['name', 'component', 'hint'], 'string', 'max' => 255],
[['code'], 'string', 'max' => 32],
[['active', 'property_type', 'list_type', 'multiple', 'with_description', 'searchable', 'filtrable', 'is_required'], 'string', 'max' => 1],
[['active', 'property_type', 'list_type', 'multiple', 'with_description', 'searchable', 'smart_filtrable', 'filtrable', 'is_required'], 'string', 'max' => 1],
[['file_type'], 'string', 'max' => 200],
[['tmp_id'], 'string', 'max' => 40],
[['code'], 'unique']
[['code'], 'unique'],
['code', 'default', 'value' => function($model, $attribute)
{
return "sx_auto_" . md5(rand(1, 10) . time());
}],
['priority', 'default', 'value' => function($model, $attribute)
{
return 500;
}],
]);
}
......@@ -126,6 +162,7 @@ class ProductProperty extends Core
'with_description' => Yii::t('app', 'Выводить поле для описания значения'),
'searchable' => Yii::t('app', 'Значения свойства участвуют в поиске'),
'filtrable' => Yii::t('app', 'Выводить на странице списка элементов поле для фильтрации по этому свойству'),
'smart_filtrable' => Yii::t('app', 'Показывать в умном фильтре'),
'is_required' => Yii::t('app', 'Is Required'),
'version' => Yii::t('app', 'Version'),
'component' => Yii::t('app', 'Тип'),
......@@ -160,42 +197,18 @@ class ProductProperty extends Core
*/
public function renderActiveForm(ActiveForm $activeForm, Model $model)
{
$elementClass = $this->component;
/**
* @var $field ActiveField
* @var $propertyType PropertyType
*/
$field = $activeForm
->field($model, $this->getFormAttribute());
if (!$field)
{
return '';
}
$elementConfig = (array) $this->component_settings;
//Элемент или виджет
if (is_subclass_of($this->component, PropertyTypeStandartElement::className()))
{
$elementClass = $this->component;
$field->{$elementClass::$elementCode}($elementConfig);
} else
{
$field->widget($this->component, $elementConfig);
}
if ($this->hint)
{
$field->hint((string) $this->hint);
}
if ($this->name)
{
$field->label($this->name);
} else
{
$field->label(false);
}
$propertyType = new $elementClass([
'model' => $model,
'property' => $this,
'activeForm' => $activeForm,
]);
return $field;
return $propertyType->renderForActiveForm();
}
......@@ -208,7 +221,7 @@ class ProductProperty extends Core
$rules = [];
if ($this->is_required)
if ($this->is_required == Cms::BOOL_Y)
{
$rules = ['required'];
}
......@@ -234,4 +247,99 @@ class ProductProperty extends Core
{
return "property_" . $this->id;
}
/**
* @param $modelWhithProperties
* @return mixed
*/
public function value($modelWhithProperties)
{
if ($this->multiple == "Y")
{
if ($values = $modelWhithProperties->findPropertyValue($this->id)->all())
{
return ArrayHelper::map($values, "id", "value");
} else
{
return [];
}
} else
{
if ($value = $modelWhithProperties->findPropertyValue($this->id)->one())
{
return $value->value;
} else
{
return null;
}
}
}
/**
* @param $modelWhithProperties
* @param $value
* @return $this
*/
public function saveValue($modelWhithProperties, $value)
{
if ($this->multiple == "Y")
{
$propertyValues = $modelWhithProperties->getPropertyValues()->where(['property_id' => $this->id])->all();
if ($propertyValues)
{
foreach ($propertyValues as $pv)
{
$pv->delete();
}
}
$values = (array) $value;
if ($values)
{
foreach ($values as $key => $value)
{
$productPropertyValue = new ProductPropertyMap([
'product_id' => $modelWhithProperties->id,
'property_id' => $this->id,
'value' => $value,
]);
$productPropertyValue->save(false);
}
}
} else
{
/**
* @var $propertyValue ProductPropertyMap
*/
if ($productPropertyValue = $modelWhithProperties->getPropertyValues()->where(['property_id' => $this->id])->one())
{
$productPropertyValue->value = $value;
} else
{
$productPropertyValue = new ProductPropertyMap([
'product_id' => $modelWhithProperties->id,
'property_id' => $this->id,
'value' => $value,
]);
}
$productPropertyValue->save();
}
return $this;
}
/**
* @return \yii\db\ActiveQuery
*/
public function getProductPropertyEnums()
{
return $this->hasMany(ProductPropertyEnum::className(), ['property_id' => 'id']);
}
}
\ No newline at end of file
<?php
/**
* @author Semenov Alexander <semenov@skeeks.com>
* @link http://skeeks.com/
* @copyright 2010 SkeekS (СкикС)
* @date 14.05.2015
*/
namespace skeeks\modules\cms\catalog\models;
use skeeks\cms\base\db\ActiveRecord;
use skeeks\cms\models\behaviors\HasDescriptionsBehavior;
use skeeks\cms\models\behaviors\HasFiles;
use skeeks\cms\models\behaviors\HasStatus;
use skeeks\cms\models\behaviors\Implode;
use skeeks\cms\models\Core;
use \Yii;
/**
* Class ProductPropertyEnum
* @package skeeks\modules\cms\catalog\models
*/
class ProductPropertyEnum extends Core
{
/**
* @inheritdoc
*/
public static function tableName()
{
return '{{%catalog_product_property_enum}}';
}
/**
* @inheritdoc
*/
public function rules()
{
return array_merge(parent::rules(),[
[['created_by', 'updated_by', 'created_at', 'updated_at', 'property_id', 'priority'], 'integer'],
[['value'], 'required'],
[['value'], 'string', 'max' => 255],
[['def'], 'string', 'max' => 1],
[['code'], 'string', 'max' => 32],
['code', 'default', 'value' => function($model, $attribute)
{
return "sx_auto_" . md5(rand(1, 10) . time());
}],
['priority', 'default', 'value' => function($model, $attribute)
{
return 500;
}],
]);
}
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['create'] = $scenarios[self::SCENARIO_DEFAULT];
$scenarios['update'] = $scenarios[self::SCENARIO_DEFAULT];
return $scenarios;
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return array_merge(parent::attributeLabels(), [
'id' => Yii::t('app', 'ID'),
'created_by' => Yii::t('app', 'Created By'),
'updated_by' => Yii::t('app', 'Updated By'),
'created_at' => Yii::t('app', 'Created At'),
'updated_at' => Yii::t('app', 'Updated At'),
'property_id' => Yii::t('app', 'Property ID'),
'value' => Yii::t('app', 'Value'),
'def' => Yii::t('app', 'Def'),
'code' => Yii::t('app', 'Code'),
'priority' => Yii::t('app', 'Priority'),
]);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getProperty()
{
return $this->hasOne(CatalogProductProperty::className(), ['id' => 'property_id']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getCreatedBy()
{
return $this->hasOne(CmsUser::className(), ['id' => 'created_by']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getUpdatedBy()
{
return $this->hasOne(CmsUser::className(), ['id' => 'updated_by']);
}
}
\ No newline at end of file
<?php
use yii\helpers\Html;
use skeeks\cms\modules\admin\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model \yii\db\ActiveRecord */
?>
<?php $form = ActiveForm::begin(); ?>
<? if ($form_id = \Yii::$app->request->get('property_id')) : ?>
<?= $form->field($model, 'property_id')->hiddenInput(['value' => $form_id])->label(false); ?>
<? else: ?>
<?= $form->field($model, 'property_id')->widget(
\skeeks\widget\chosen\Chosen::className(), [
'items' => \yii\helpers\ArrayHelper::map(
\skeeks\modules\cms\catalog\models\ProductProperty::find()->all(),
"id",
"name"
),
]);
?>
<? endif; ?>
<?= $form->field($model, 'value')->textInput(['maxlength' => 255]) ?>
<?= $form->field($model, 'code')->textInput(['maxlength' => 32]) ?>
<?= $form->buttonsCreateOrUpdate($model); ?>
<?php ActiveForm::end(); ?>
......@@ -118,6 +118,7 @@ use skeeks\cms\modules\admin\widgets\Pjax;
'relation' => [
'product_id' => 'id'
],
'controllerRoute' => 'catalog/admin-product-property-map',
'gridViewOptions' => [
......@@ -167,13 +168,13 @@ use skeeks\cms\modules\admin\widgets\Pjax;
<? endif;?>
<?= $form->buttonsCreateOrUpdate($model); ?>
<?php ActiveForm::end(); ?>
<?= $model->renderPropertiesForm(); ?>
<div class="sx-box sx-p-10 sx-mt-10">
<h2>Дополнительные свойства</h2>
<?= $model->renderPropertiesForm(); ?>
</div>
......
......@@ -11,7 +11,7 @@ use skeeks\cms\modules\admin\widgets\Pjax;
<?php $form = ActiveForm::begin(); ?>
<?= $form->fieldSet('Основная информация') ?>
<?= $form->fieldSet('Основные настройки') ?>
<? if ($group_id = \Yii::$app->request->get('group_id')) : ?>
......@@ -47,17 +47,64 @@ use skeeks\cms\modules\admin\widgets\Pjax;
<?= $form->fieldRadioListBoolean($model, 'searchable') ?>
<?= $form->fieldRadioListBoolean($model, 'filtrable') ?>
<?/*= $form->fieldRadioListBoolean($model, 'with_description') */?>
<?= $form->fieldRadioListBoolean($model, 'smart_filtrable') ?>
<?= $form->fieldRadioListBoolean($model, 'with_description') ?>
<?= $form->fieldInputInt($model, 'priority') ?>
<?/*= $form->field($model, 'default_value')->textInput() */?><!--
<?/*= $form->field($model, 'default_value')->textInput() */?>
<!--
--><?/*= $form->fieldInputInt($model, 'multiple_cnt') */?>
<?= $form->fieldSetEnd(); ?>
<? if (!$model->isNewRecord) : ?>
<?= $form->fieldSet('Значения для списка') ?>
<?= \skeeks\cms\modules\admin\widgets\RelatedModelsGrid::widget([
'label' => "Значения для списка",
'hint' => "Вы можете привязать к товару несколько свойст, и задать им значение",
'parentModel' => $model,
'relation' => [
'property_id' => 'id'
],
'sort' => [
'defaultOrder' =>
[
'priority' => SORT_DESC
]
],
'controllerRoute' => 'catalog/admin-product-property-enum',
'gridViewOptions' => [
'sortable' => true,
'columns' => [
//['class' => 'yii\grid\SerialColumn'],
/*[
'class' => \yii\grid\DataColumn::className(),
'value' => function(\skeeks\modules\cms\catalog\models\ProductPropertyMap $model)
{
return $model->fetchProductProperty()->name;
},
'format' => 'html',
'label' => 'Свойство',
'enableSorting' => true,
'attribute' => "property_id"
],*/
'id',
'code',
'value',
'priority',
'def',
],
],
]); ?>
<?= $form->fieldSetEnd(); ?>
<? endif; ?>
<?= $form->buttonsCreateOrUpdate($model); ?>
<?php ActiveForm::end(); ?>
......
......@@ -15,12 +15,15 @@ use skeeks\cms\modules\admin\widgets\GridView;
/* @var $searchModel \skeeks\cms\models\Search */
/* @var $dataProvider yii\data\ActiveDataProvider */
//$dataProvider->query->orderBy('published_at DESC');
$dataProvider->sort->defaultOrder = ['priority' => SORT_DESC];
$dataProvider->pagination->pageSize = 10000;
?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'sortable' => true,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
......@@ -31,6 +34,7 @@ use skeeks\cms\modules\admin\widgets\GridView;
'name',
[
'class' => \skeeks\cms\grid\BooleanColumn::className(),
'attribute' => 'active',
......@@ -52,6 +56,9 @@ use skeeks\cms\modules\admin\widgets\GridView;
'filter' => false
],
'code',
'priority',
],
]); ?>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment