Как и обещал сделал ручную сборку с мануалом по установке и с учётом большинства изменений(сразу,у меня 0.1.8), из того что помню:
- устранена проблема с IE (пост #72, 4 стр. afwollis);
- добавлено в админке checkbox "Выбрать все" для выбора всех категорий (спасибо berikiushi);
- назначение товару нескольких свойств (спасибо afwollis - пост #53) при редактировании товара;
- логическое И (и то, и то обязательно) при фильтрации в категории по свойствам товара (спасибо afwollis - пост #79)
- ... может чтото ещё...непомню (собирал ночью)
Начнём,
1) Делаем запрос в базу данных(у меня ПРЕФИКС oc_):
CREATE TABLE IF NOT EXISTS `oc_category_option` (
`option_id` int(10) NOT NULL AUTO_INCREMENT,
`type` int(1) DEFAULT '0',
`sort_order` int(10) DEFAULT '0',
PRIMARY KEY (`option_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `oc_category_option_description` (
`option_id` int(10) NOT NULL DEFAULT '0',
`language_id` int(10) NOT NULL DEFAULT '0',
`name` varchar(127) DEFAULT NULL,
PRIMARY KEY (`option_id`,`language_id`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `oc_category_option_to_category` (
`option_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`category_id`,`option_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `oc_category_option_value` (
`value_id` int(10) NOT NULL AUTO_INCREMENT,
`option_id` int(10) DEFAULT '0',
PRIMARY KEY (`value_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `oc_category_option_value_description` (
`value_id` int(10) NOT NULL DEFAULT '0',
`language_id` int(10) NOT NULL DEFAULT '0',
`option_id` int(10) NOT NULL DEFAULT '0',
`name` varchar(127) DEFAULT NULL,
PRIMARY KEY (`value_id`,`language_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `oc_product_to_value` (
`product_id` int(11) NOT NULL,
`value_id` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`product_id`,`value_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
2) В файле admin|view|template|catalog|product_form.tpl
После
<a tab="#tab_links"><?php echo $tab_links; ?></a>Вставляем<a tab="#tab_filter">Опции фильтра</a>
Далее после блока
<div id="tab_general"></div>, примерно 59 строка, перед <div id="tab_data">Вставляем
<!-- Start tab filter-->
<div id="tab_filter">
Сначала необходимо выбрать категории товара
</div>
<!-- End tab filter-->Теперь идем в конец файла, ДО
<?php echo $footer; ?>Вставляем
<script type="text/javascript"><!--
$('input[name=product_category[]]').live('change', function() {
getOptions();
});
<?php if (isset($this->request->get['product_id'])) { ?>
<?php $if_product_id = '&product_id=' . $this->request->get['product_id']; ?>
getOptions();
<?php } else { ?>
<?php $if_product_id = ''; ?>
<?php } ?>
function getOptions() {
var loadUrl = '';
var fields = $("input[name=product_category[]]").serializeArray();
jQuery.each(fields, function(i, field){
if (i == 0) {
loadUrl += field.value;
} else {
loadUrl += '_' + field.value;
}
});
$('#tab_filter').load('index.php?route=catalog/product/filter&token=<?php echo $token; ?><?php echo $if_product_id; ?>&path=' + loadUrl);
}
//--></script>Сохраняем и закрываем.3) Открываем файл admin|model|catalog|product.php
После блока (метод addProduct) гдето 21 строка
if (isset($data['product_store'])) {
foreach ($data['product_store'] as $store_id) {
$this->db->query("INSERT INTO " . DB_PREFIX . "product_to_store SET product_id = '" . (int)$product_id . "', store_id = '" . (int)$store_id . "'");
}
}Вставляем
// Start Filter
if (isset($data['product_to_value_id'])) {
foreach ($data['product_to_value_id'] as $value_id) {
$this->db->query("INSERT INTO " . DB_PREFIX . "product_to_value SET product_id = '" . (int)$product_id . "', value_id = '" . (int)$value_id . "'");
}
}
// End filterПосле блока (метод updateProduct)
$this->db->query("DELETE FROM " . DB_PREFIX . "product_to_store WHERE product_id = '" . (int)$product_id . "'");
if (isset($data['product_store'])) {
foreach ($data['product_store'] as $store_id) {
$this->db->query("INSERT INTO " . DB_PREFIX . "product_to_store SET product_id = '" . (int)$product_id . "', store_id = '" . (int)$store_id . "'");
}
}Вставляем
// Start filter
$this->db->query("DELETE FROM " . DB_PREFIX . "product_to_value WHERE product_id = '" . (int)$product_id . "'");
if (isset($data['product_to_value_id'])) {
foreach ($data['product_to_value_id'] as $value_id) {
$this->db->query("INSERT INTO " . DB_PREFIX . "product_to_value SET product_id = '" . (int)$product_id . "', value_id = '" . (int)$value_id . "'");
}
}
// End filterПосле (метод copyProduct)
$data = array_merge($data, array('product_store' => $this->getProductStores($product_id)));Вставляем
// Start filter
$data = array_merge($data, array('product_to_value_id' => $this->getProductValues($product_id)));
// End filterПосле (метод deleteProduct)
$this->db->query("DELETE FROM " . DB_PREFIX . "product_to_store WHERE product_id = '" . (int)$product_id . "'");Вставляем
// Start filter
$this->db->query("DELETE FROM " . DB_PREFIX . "product_to_value WHERE product_id = '" . (int)$product_id . "'");
// End filterИдем в конец файла, до закрытия класса вставляем
// Start filter
public function getProductValues($product_id) {
$values_id = array();
$query = $this->db->query("SELECT p2v.value_id AS value_id FROM " . DB_PREFIX . "product_to_value p2v WHERE p2v.product_id = '" . (int)$product_id . "'");
foreach ($query->rows as $result) {
$values_id[] = $result['value_id'];
}
return $values_id;
}
// End filterСохраняем и закрываем.4) Открываем admin|controller|catalog|product.php
в районе 1100 строки, после
foreach($results as $option) {
$this->data['category_options'][] = array(Должно быть(если нет вставляем!)
'option_id' => $option['option_id'],в итоге должно быть:
foreach($results as $option) {
$this->data['category_options'][] = array(
'option_id' => $option['option_id'],
'name' => $option['name'],
'type' => $option['type'],
'category_option_values' => $this->model_catalog_filter->getOptionValues($option['option_id'])
);
}и идем в конец файла, до закрытия класса вставляем
// Start filter
public function filter() {
$this->load->model('catalog/filter');
$this->load->model('catalog/product');
$this->data['category_options'] = array();
if (isset($this->request->get['path']) && $this->request->get['path'] != '') {
$parts = explode('_', $this->request->get['path']);
$results = $this->model_catalog_filter->getOptionByCategoriesId($parts);
if ($results) {
foreach($results as $option) {
$this->data['category_options'][] = array(
'option_id' => $option['option_id'],
'name' => $option['name'],
'type' => $option['type'],
'category_option_values' => $this->model_catalog_filter->getOptionValues($option['option_id'
])
);
}
} else {
$this->data['message'] = 'Этой категории товаров не присвоен ниодин фильтр';
}
} else {
$this->data['message'] = 'Сначала выберите категорию товаров';
}
if (isset($this->request->get['product_id'])) {
$product_id = $this->request->get['product_id'];
} else {
$product_id = 0;
}
$product_info = $this->model_catalog_product->getProductValues($product_id);
if (isset($this->request->post['product_to_value_id'])) {
$this->data['product_to_value_id'] = $this->request->post['product_to_value_id'];
} elseif (isset($product_info)) {
$this->data['product_to_value_id'] = $this->model_catalog_product->getProductValues($product_id);
} else {
$this->data['product_to_value_id'] = array();
}
$this->data['language_id'] = $this->config->get('config_language_id');
$this->template = 'catalog/get_ajax_options.tpl';
$this->response->setOutput($this->render(TRUE), $this->config->get('config_compression'));
}
// End filterСохраняем и закрываем.5) Открываем catalog|model|catalog|product.php
Заменяем
public function getProductsByCategoryId($category_id, $sort = 'p.sort_order', $order = 'ASC', $start = 0, $limit = 20) {На
public function getProductsByCategoryId($category_id, $values, $sort = 'p.sort_order', $order = 'ASC', $start = 0, $limit = 20) {До блока 17 строка
$sort_data = array(
'pd.name',
'p.sort_order',
'special',
'rating',
'p.price',
'p.model'
);Вставляем
// Start filter
/*
if (isset($values) && $values != '') {
$data = array();
foreach (explode('_', $values) as $value_id) {
$data[] = "value_id = '" . (int)$value_id . "'";
}
$sql .= " AND p.product_id IN (SELECT product_id FROM " . DB_PREFIX . "product_to_value WHERE " . implode(" OR ", $data) . ")";
}
*/
if (isset($values) && $values != '') {
$data = array();
$values_without_underline = "";
$values_for_IN = "";
foreach (explode('_', $values) as $value_id) {
if (empty($values_for_IN)) {
$values_for_IN = "'".$value_id."'";
} else {
$values_for_IN .= ", '".$value_id."'";
}
$values_without_underline .= $value_id;
}
// http://forums.mysql.com/read.php?78,354483,354598#msg-354598
//(SELECT GROUP_CONCAT(DISTINCT Tag_id ORDER BY Tag_id ASC SEPARATOR '') FROM Tag_has_Post WHERE Post_id=t.Post_id AND Tag_id IN (2,5))='25';
$sql .= " AND (SELECT GROUP_CONCAT(DISTINCT value_id SEPARATOR '') FROM oc_product_to_value WHERE product_id=p.product_id AND value_id IN (".$values_for_IN."))='".$values_without_underline."'";
}
// End filterЗаменяем весь метод public function getTotalProductsByCategoryId (теперь гдето с 84 по 85 строку)На
public function getTotalProductsByCategoryId($category_id = 0, $values) {
$sql = "SELECT COUNT(*) AS total FROM " . DB_PREFIX . "product_to_category p2c LEFT JOIN " . DB_PREFIX . "product p ON (p2c.product_id = p.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "' AND p2c.category_id = '" . (int)$category_id . "'";
// Start filter
/*
if (isset($values) && $values != '') {
$data = array();
foreach (explode('_', $values) as $value_id) {
$data[] = "value_id = '" . (int)$value_id . "'";
}
$sql .= " AND p.product_id IN (SELECT product_id FROM " . DB_PREFIX . "product_to_value WHERE " . implode(" OR ", $data) . ")";
}
*/
if (isset($values) && $values != '') {
$data = array();
$values_without_underline = "";
$values_for_IN = "";
foreach (explode('_', $values) as $value_id) {
if (empty($values_for_IN)) {
$values_for_IN = "'".$value_id."'";
} else {
$values_for_IN .= ", '".$value_id."'";
}
$values_without_underline .= $value_id;
}
// http://forums.mysql.com/read.php?78,354483,354598#msg-354598
//(SELECT GROUP_CONCAT(DISTINCT Tag_id ORDER BY Tag_id ASC SEPARATOR '') FROM Tag_has_Post WHERE Post_id=t.Post_id AND Tag_id IN (2,5))='25';
$sql .= " AND (SELECT GROUP_CONCAT(DISTINCT value_id SEPARATOR '') FROM oc_product_to_value WHERE product_id=p.product_id AND value_id IN (".$values_for_IN."))='".$values_without_underline."'";
}
// End filter
$query = $this->db->query($sql);
return $query->row['total'];
}Сохраняем, закрываем.6) Открываем catalog|controller|product|category.php
Заменяем
$product_total = $this->model_catalog_product->getTotalProductsByCategoryId($category_id);На
$product_total = $this->model_catalog_product->getTotalProductsByCategoryId($category_id,
$values = NULL);Заменяем
$results = $this->model_catalog_product->getProductsByCategoryId($category_id,
$sort, $order, ($page - 1) * $this->config->get('config_catalog_limit'), $this->config->get('config_catalog_limit'));На
$results = $this->model_catalog_product->getProductsByCategoryId($category_id,
$values = NULL, $sort, $order, ($page - 1) * $this->config->get('config_catalog_limit'), $this->config->get('config_catalog_limit'));Сохраняем, закрываем.7) Качаем архив manual_Openstore_module_product.zip и извлекаем в корень сайта с заменой.
8) Идем в админку -> дополнения и включаем фильтр, добавляем опции.
manual_Openstore_module_product.zip