Вывод полей в таблице заказов minishop2
Приветствую!
Столкнулся с задачей изменить таблицу заказов minishop2.
Но на просторах интернета, так и не нашел подобного решения.
Существуют внятные и понятные (даже для моего уровня программирования) статьи о том как добавить новое поле, к примеру в закладку адрес, но вот по работе с самой таблицей, информации очень мало.
Если более детально описать, то требуется в таблицу с заказами вывести любое поле из таблицы ms2_order_addresses.
У меня получилось добавить новые колонки в таблице, но они пусты. На сколько я понимаю, в момент генерации таблицы нет запроса к ms2_order_addresses, сама таблица работает с ms2_orders.

На скрине колонка «Адрес получателя» живет аккурат в таблице ms2_order_addresses и пуста.
Буду благодарен помощи!
Обновление 19.03.2025
Благодаря персту указующему, в лице Евгений Webinmd я смог разобраться.
Немного забегая вперед, данный текст я пишу из двух умыслов.
Во-первых, я скромно надеюсь, что кому-то это будет полезно, а во-вторых, будет здорово, если кто-то укажет мне на мои ошибки и недочеты, т.к. мой уровень программирования, ограничивается if else и echo «Hello, world!»; =))) А если уж совсем на чистоту, из всего кода, который я буду приводить ниже, я 70% не понимаю, от слова совсем!
И так, приступим!
Действительно за вывод колонок в таблице с заказами отвечает процессор getlist.
Его можно найти core/components/minishop2/processors/mgr/
так же, за вывод колонок отвечает файл orders.grid.js
он живет assets/components/minishop2/js/mgr/orders/orders.grid.js
Так же понадобится системная настройка ms2_order_grid_fields — в ней нужно дописывать необходимые нам поля.
И так. Теперь по порядку.
Опираясь на эту статью я родил следующее:
1. Я создал новый процессор getlist_custom.class.php и разместил его по адресу: core/components/minishop2/processors/mgr/orders/getlist_custom.class.php
По сути я просто скопировал оригинальный getlist.class.php, но внес некоторые изменения. А именно:
Т.е. я дополнил запрос в БД нужными мне полями.
и вот здесь, тоже внес некоторые изменения:
На сколько я понимаю, тут я добавляю в массив данных нужные мне значения.
Собственно это почти все изменения, которые я внес, осталось совсем чуть-чуть!
В самом начале файла
И в самом низу файла:
Теперь настала очередь, создать кастомный файл с яваскриптами.
У меня он именуется orderGridChange.js и лежит assets/custom/orderGridChange.js
По сути, я скопировал файл из orders.grid.js и немного изменил его
В этой части
action: 'mgr/orders/getlist_custom',
Так же во всех местах где встречался объект (?) Orders, я его заменил на customOrders, тут я затрудняюсь дать пояснения, для чего я это сделал, но по всей видимости не работало =)
Далее:
Я добавил нужные мне поля.
Кстати, я не добавлял новых полей в таблицу, а использовал уже имеющийся, собственно поэтому у меня поле 'city' по сути является именем получателя, и т.д., не знаю, чем это аукнется в дальнейшем, но пока так как есть. Кстати, тут было бы тоже здорово, узнать ваше мнение, стоит ли завести новые поля или так тоже ничего?
Еще, что бы все заработало, нужно создать плагин.
Я назвал его orderGridChange
И если, я ничего не упустил, то в завершение, в системных настройках ms2_order_grid_fields нужно указать перечень полей, нужных для вывода в таблице, у меня это выглядит так: id,num,customer,status,cost,delivery,payment,createdon,comment,order_comment,region,city,updatedon,text_address,phone
Всем удачи, и спасибо за помощь!
Столкнулся с задачей изменить таблицу заказов minishop2.
Но на просторах интернета, так и не нашел подобного решения.
Существуют внятные и понятные (даже для моего уровня программирования) статьи о том как добавить новое поле, к примеру в закладку адрес, но вот по работе с самой таблицей, информации очень мало.
Если более детально описать, то требуется в таблицу с заказами вывести любое поле из таблицы ms2_order_addresses.
У меня получилось добавить новые колонки в таблице, но они пусты. На сколько я понимаю, в момент генерации таблицы нет запроса к ms2_order_addresses, сама таблица работает с ms2_orders.

На скрине колонка «Адрес получателя» живет аккурат в таблице ms2_order_addresses и пуста.
Буду благодарен помощи!
Обновление 19.03.2025
Благодаря персту указующему, в лице Евгений Webinmd я смог разобраться.
Немного забегая вперед, данный текст я пишу из двух умыслов.
Во-первых, я скромно надеюсь, что кому-то это будет полезно, а во-вторых, будет здорово, если кто-то укажет мне на мои ошибки и недочеты, т.к. мой уровень программирования, ограничивается if else и echo «Hello, world!»; =))) А если уж совсем на чистоту, из всего кода, который я буду приводить ниже, я 70% не понимаю, от слова совсем!
И так, приступим!
Его можно найти core/components/minishop2/processors/mgr/
так же, за вывод колонок отвечает файл orders.grid.js
он живет assets/components/minishop2/js/mgr/orders/orders.grid.js
Так же понадобится системная настройка ms2_order_grid_fields — в ней нужно дописывать необходимые нам поля.
И так. Теперь по порядку.
Опираясь на эту статью я родил следующее:
1. Я создал новый процессор getlist_custom.class.php и разместил его по адресу: core/components/minishop2/processors/mgr/orders/getlist_custom.class.php
<?php
require_once(dirname(__FILE__) . '/getlist.class.php');
class msOrderGetListProcessorCustom extends modObjectGetListProcessor
{
public $classKey = 'msOrder';
public $languageTopics = ['default', 'minishop2:manager'];
public $defaultSortField = 'id';
public $defaultSortDirection = 'DESC';
public $permission = 'msorder_list';
/** @var miniShop2 $ms2 */
protected $ms2;
/** @var xPDOQuery $query */
protected $query;
/**
* @return bool|null|string
*/
public function initialize()
{
$this->ms2 = $this->modx->getService('miniShop2');
if (!$this->modx->hasPermission($this->permission)) {
return $this->modx->lexicon('access_denied');
}
return parent::initialize();
}
/**
* @param xPDOQuery $c
*
* @return xPDOQuery
*/
public function prepareQueryBeforeCount(xPDOQuery $c)
{
$c->leftJoin('modUser', 'User');
$c->leftJoin('modUserProfile', 'UserProfile');
$c->leftJoin('msOrderStatus', 'Status');
$c->leftJoin('msDelivery', 'Delivery');
$c->leftJoin('msPayment', 'Payment');
$c->leftJoin('msOrderAddress', 'Address');
//$c->leftJoin('msOrderAddress', 'Region');
$query = trim($this->getProperty('query'));
if (!empty($query)) {
if (is_numeric($query)) {
$c->andCondition([
'id' => $query,
'OR:Address.phone:LIKE' => "%{$query}%",
//'OR:User.id' => $query,
]);
} else {
$c->where([
'num:LIKE' => "{$query}%",
'OR:order_comment:LIKE' => "%{$query}%",
'OR:Address.comment:LIKE' => "%{$query}%",
'OR:User.username:LIKE' => "%{$query}%",
'OR:UserProfile.fullname:LIKE' => "%{$query}%",
'OR:UserProfile.email:LIKE' => "%{$query}%",
'OR:Address.phone:LIKE' => "%{$query}%",
]);
}
}
if ($status = $this->getProperty('status')) {
$c->where([
'status' => $status,
]);
}
if ($customer = $this->getProperty('customer')) {
$c->where([
'user_id' => (int)$customer,
]);
}
if ($context = $this->getProperty('context')) {
$c->where([
'context' => $context,
]);
}
if ($date_start = $this->getProperty('date_start')) {
$c->andCondition([
'createdon:>=' => date('Y-m-d 00:00:00', strtotime($date_start)),
], null, 1);
}
if ($date_end = $this->getProperty('date_end')) {
$c->andCondition([
'createdon:<=' => date('Y-m-d 23:59:59', strtotime($date_end)),
], null, 1);
}
$this->query = clone $c;
$c->select(
$this->modx->getSelectColumns('msOrder', 'msOrder', '', ['status', 'delivery', 'payment'], true) . ',
msOrder.status as status_id, msOrder.delivery as delivery_id, msOrder.payment as payment_id,
UserProfile.fullname as customer, User.username as customer_username,
Address.region as region, Address.text_address as text_address, Address.city as city, Address.phone as phone,
Status.name as status, Status.color, Delivery.name as delivery, Payment.name as payment'
);
$c->groupby($this->classKey . '.id');
return $c;
}
/**
* @param xPDOQuery $c
*
* @return xPDOQuery
*/
public function prepareQueryAfterCount(xPDOQuery $c)
{
$total = 0;
$limit = (int)$this->getProperty('limit');
$start = (int)$this->getProperty('start');
$q = clone $c;
$q->query['columns'] = ['SQL_CALC_FOUND_ROWS msOrder.id, fullname as customer'];
$sortClassKey = $this->getSortClassKey();
$sortKey = $this->modx->getSelectColumns(
$sortClassKey,
$this->getProperty('sortAlias', $sortClassKey),
'',
[$this->getProperty('sort')]
);
if (empty($sortKey)) {
$sortKey = $this->getProperty('sort');
}
$q->sortby($sortKey, $this->getProperty('dir'));
if ($limit > 0) {
$q->limit($limit, $start);
}
$ids = [];
if ($q->prepare() and $q->stmt->execute()) {
$ids = $q->stmt->fetchAll(PDO::FETCH_COLUMN);
$total = $this->modx->query('SELECT FOUND_ROWS()')->fetchColumn();
}
$ids = empty($ids) ? "(0)" : "(" . implode(',', $ids) . ")";
$c->query['where'] = [
[
new xPDOQueryCondition(['sql' => 'msOrder.id IN ' . $ids, 'conjunction' => 'AND']),
]
];
$c->sortby($sortKey, $this->getProperty('dir'));
$this->setProperty('total', $total);
return $c;
}
/**
* @return array
*/
public function getData()
{
$c = $this->modx->newQuery($this->classKey);
$c = $this->prepareQueryBeforeCount($c);
$c = $this->prepareQueryAfterCount($c);
return [
'results' => ($c->prepare() and $c->stmt->execute()) ? $c->stmt->fetchAll(PDO::FETCH_ASSOC) : [],
'total' => (int)$this->getProperty('total'),
];
}
/**
* @param array $data
*
* @return array
*/
public function iterate(array $data)
{
$list = [];
$list = $this->beforeIteration($list);
$this->currentIndex = 0;
/** @var xPDOObject|modAccessibleObject $object */
foreach ($data['results'] as $array) {
$list[] = $this->prepareArray($array);
$this->currentIndex++;
}
return $this->afterIteration($list);
}
/**
* @param array $data
*
* @return array
*/
public function prepareArray(array $data)
{
if (empty($data['customer'])) {
$data['customer'] = $data['customer_username'];
}
if (isset($data['cost'])) {
$data['cost'] = $this->ms2->formatPrice($data['cost']);
}
if (isset($data['cart_cost'])) {
$data['cart_cost'] = $this->ms2->formatPrice($data['cart_cost']);
}
if (isset($data['delivery_cost'])) {
$data['delivery_cost'] = $this->ms2->formatPrice($data['delivery_cost']);
}
if (isset($data['weight'])) {
$data['weight'] = $this->ms2->formatWeight($data['weight']);
}
if (isset($data['region'])) {
//$data['customer'] = $data['customer_username'];
$data['region'] = $data['region'];
}
if (isset($data['text_address'])) {
$data['text_address'] = $data['text_address'];
}
if (isset($data['city'])) {
$data['city'] = $data['city'];
}
if (isset($data['phone'])) {
$data['phone'] = $data['phone'];
}
$data['actions'] = [
[
'cls' => '',
'icon' => 'icon icon-edit',
'title' => $this->modx->lexicon('ms2_menu_update'),
'action' => 'updateOrder',
'button' => true,
'menu' => true,
],
[
'cls' => [
'menu' => 'red',
'button' => 'red',
],
'icon' => 'icon icon-trash-o',
'title' => $this->modx->lexicon('ms2_menu_remove'),
'multiple' => $this->modx->lexicon('ms2_menu_remove_multiple'),
'action' => 'removeOrder',
'button' => true,
'menu' => true,
],
/*
array(
'cls' => '',
'icon' => 'icon icon-cog actions-menu',
'menu' => false,
'button' => true,
'action' => 'showMenu',
'type' => 'menu',
),
*/
];
return $data;
}
/**
* @param array $array
* @param bool $count
*
* @return string
*/
public function outputArray(array $array, $count = false)
{
if ($count === false) {
$count = count($array);
}
$selected = $this->query;
$selected->query['columns'] = [];
$selected->query['limit'] =
$selected->query['offset'] = 0;
$selected->where(['type' => 0]);
$selected->select('SUM(msOrder.cost)');
$selected->prepare();
$selected->stmt->execute();
$month = $this->modx->newQuery($this->classKey);
$statuses = $this->modx->getOption('ms2_status_for_stat', null, '2,3');
$statuses = array_map('trim', explode(',', $statuses));
$month->where(['status:IN' => $statuses, 'type' => 0]);
$month->where('createdon BETWEEN NOW() - INTERVAL 30 DAY AND NOW()');
$month->select('SUM(msOrder.cost) as sum, COUNT(msOrder.id) as total');
$month->prepare();
$month->stmt->execute();
$month = $month->stmt->fetch(PDO::FETCH_ASSOC);
$data = [
'success' => true,
'results' => $array,
'total' => $count,
'num' => number_format($count, 0, '.', ' '),
'sum' => number_format(round($selected->stmt->fetchColumn()), 0, '.', ' '),
'month_sum' => number_format(round($month['sum']), 0, '.', ' '),
'month_total' => number_format($month['total'], 0, '.', ' '),
];
return json_encode($data);
}
}
return 'msOrderGetListProcessorCustom';
По сути я просто скопировал оригинальный getlist.class.php, но внес некоторые изменения. А именно:
$c->select(
$this->modx->getSelectColumns('msOrder', 'msOrder', '', ['status', 'delivery', 'payment'], true) . ',
msOrder.status as status_id, msOrder.delivery as delivery_id, msOrder.payment as payment_id,
UserProfile.fullname as customer, User.username as customer_username,
Address.region as region, Address.text_address as text_address, Address.city as city, Address.phone as phone,
Status.name as status, Status.color, Delivery.name as delivery, Payment.name as payment'
);
строка — Address.region as region, Address.text_address as text_address, Address.city as city, Address.phone as phone,Т.е. я дополнил запрос в БД нужными мне полями.
и вот здесь, тоже внес некоторые изменения:
if (empty($data['customer'])) {
$data['customer'] = $data['customer_username'];
}
if (isset($data['cost'])) {
$data['cost'] = $this->ms2->formatPrice($data['cost']);
}
if (isset($data['cart_cost'])) {
$data['cart_cost'] = $this->ms2->formatPrice($data['cart_cost']);
}
if (isset($data['delivery_cost'])) {
$data['delivery_cost'] = $this->ms2->formatPrice($data['delivery_cost']);
}
if (isset($data['weight'])) {
$data['weight'] = $this->ms2->formatWeight($data['weight']);
}
if (isset($data['region'])) {
//$data['customer'] = $data['customer_username'];
$data['region'] = $data['region'];
}
if (isset($data['text_address'])) {
$data['text_address'] = $data['text_address'];
}
if (isset($data['city'])) {
$data['city'] = $data['city'];
}
if (isset($data['phone'])) {
$data['phone'] = $data['phone'];
}
Начиная со строки if (isset($data['region'])) и до концаНа сколько я понимаю, тут я добавляю в массив данных нужные мне значения.
Собственно это почти все изменения, которые я внес, осталось совсем чуть-чуть!
В самом начале файла
require_once(dirname(__FILE__) . '/getlist.class.php');
class msOrderGetListProcessor<strong>Custom</strong> extends modObjectGetListProcessor
Если еще вторую строчку я понимаю, для чего она нужна, то первую, там где идет подключение оригинального процессора — остается для меня загадкой, но без нее не работает =)И в самом низу файла:
return 'msOrderGetListProcessorCustom';
Тут собственно надо в вывод указать, то что нужно возвращать уже не оригинал результата действия процессора, а измененный, тот, который я создал. Справедливости ради стоит сказать, что я не очень понимаю, что такое процессор, да и вообще как это все устроено. Буду рад если кто разъяснит.Теперь настала очередь, создать кастомный файл с яваскриптами.
У меня он именуется orderGridChange.js и лежит assets/custom/orderGridChange.js
По сути, я скопировал файл из orders.grid.js и немного изменил его
if(Ext.ComponentMgr.types['minishop2-grid-orders']) {
miniShop2.grid.customOrders = function (config) {
config = config || {};
if (!config.id) {
config.id = 'minishop2-grid-orders';
}
Ext.applyIf(config, {
baseParams: {
action: 'mgr/orders/getlist_custom',
sort: 'id',
dir: 'desc',
},
multi_select: true,
changed: false,
stateful: true,
stateId: config.id,
});
miniShop2.grid.customOrders.superclass.constructor.call(this, config);
};
Ext.extend(miniShop2.grid.customOrders, Ext.ComponentMgr.types['minishop2-grid-orders'], {
getFields: function () {
return miniShop2.config['order_grid_fields'];
},
getColumns: function () {
var all = {
id: {width: 35},
//customer: {width: 100, renderer: function (val, cell, row) {
// return miniShop2.utils.userLink(val, row.data['user_id'], true);
//}},
customer: {width: 50},
//num: {width: 20},
//receiver: {width: 100},
//createdon: {width: 20, renderer: miniShop2.utils.formatDate},
//updatedon: {width: 20, renderer: miniShop2.utils.formatDate},
cost: {width: 50, renderer: this._renderCost},
cart_cost: {width: 50},
delivery_cost: {width: 75},
weight: {width: 50},
status: {width: 50, renderer: miniShop2.utils.renderBadge},
delivery: {width: 75},
order_comment: {width: 100},
payment: {width: 75},
text_address: {width: 150},
city: {width: 100}, //получатель
region: {width: 75}, //дата доставки
phone: {width: 100}, //телефон заказчика
//context: {width: 50},
actions: {width: 75, id: 'actions', renderer: miniShop2.utils.renderActions, sortable: false},
};
var fields = this.getFields();
var columns = [];
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
if (all[field]) {
Ext.applyIf(all[field], {
header: _('ms2_' + field),
dataIndex: field,
sortable: true,
});
columns.push(all[field]);
}
}
return columns;
},
getTopBar: function () {
return [];
},
getListeners: function () {
return {
rowDblClick: function (grid, rowIndex, e) {
var row = grid.store.getAt(rowIndex);
this.updateOrder(grid, e, row);
},
afterrender: function (grid) {
var params = miniShop2.utils.Hash.get();
var order = params['order'] || '';
if (order) {
this.updateOrder(grid, Ext.EventObject, {data: {id: order}});
}
},
};
},
orderAction: function (method) {
var ids = this._getSelectedIds();
if (!ids.length) {
return false;
}
MODx.Ajax.request({
url: this.config.url,
params: {
action: 'mgr/orders/multiple',
method: method,
ids: Ext.util.JSON.encode(ids),
},
listeners: {
success: {
fn: function () {
//noinspection JSUnresolvedFunction
this.refresh();
}, scope: this
},
failure: {
fn: function (response) {
MODx.msg.alert(_('error'), response.message);
}, scope: this
},
}
})
},
updateOrder: function (btn, e, row) {
if (typeof(row) != 'undefined') {
this.menu.record = row.data;
}
var id = this.menu.record.id;
MODx.Ajax.request({
url: this.config.url,
params: {
action: 'mgr/orders/get',
id: id
},
listeners: {
success: {
fn: function ® {
var w = Ext.getCmp('minishop2-window-order-update');
if (w) {
w.close();
}
w = MODx.load({
xtype: 'minishop2-window-order-update',
id: 'minishop2-window-order-update',
record: r.object,
listeners: {
success: {
fn: function () {
this.refresh();
}, scope: this
},
hide: {
fn: function () {
miniShop2.utils.Hash.remove('order');
if (miniShop2.grid.Orders.changed === true) {
Ext.getCmp('minishop2-grid-orders').getStore().reload();
miniShop2.grid.Orders.changed = false;
}
}
},
afterrender: function () {
miniShop2.utils.Hash.add('order', r.object['id']);
}
}
});
w.fp.getForm().reset();
w.fp.getForm().setValues(r.object);
w.show(e.target);
}, scope: this
}
}
});
},
removeOrder: function () {
var ids = this._getSelectedIds();
Ext.MessageBox.confirm(
_('ms2_menu_remove_title'),
ids.length > 1
? _('ms2_menu_remove_multiple_confirm')
: _('ms2_menu_remove_confirm'),
function (val) {
if (val == 'yes') {
this.orderAction('remove');
}
},
this
);
},
_renderCost: function (val, idx, rec) {
return rec.data['type'] != undefined && rec.data['type'] == 1
? '-' + val
: val;
},
});
Ext.reg('minishop2-grid-orders', miniShop2.grid.customOrders);
}
а именноif(Ext.ComponentMgr.types['minishop2-grid-orders']) {
Это самая первая строчка, которая создает условие на весь код, и закрывается скобка в самом конце файла, на эту скобку было потрачено около часа, т.к. я ее пропустил, не повторяйте мою ошибку=)))В этой части
Ext.applyIf(config, {
baseParams: {
action: 'mgr/orders/getlist_custom',
sort: 'id',
dir: 'desc',
},
я указал отсылку на новый процессор, строкаaction: 'mgr/orders/getlist_custom',
Так же во всех местах где встречался объект (?) Orders, я его заменил на customOrders, тут я затрудняюсь дать пояснения, для чего я это сделал, но по всей видимости не работало =)
miniShop2.grid.<strong>customOrders</strong>
Далее:
getColumns: function () {
var all = {
id: {width: 35},
//customer: {width: 100, renderer: function (val, cell, row) {
// return miniShop2.utils.userLink(val, row.data['user_id'], true);
//}},
customer: {width: 50},
//num: {width: 20},
//receiver: {width: 100},
//createdon: {width: 20, renderer: miniShop2.utils.formatDate},
//updatedon: {width: 20, renderer: miniShop2.utils.formatDate},
cost: {width: 50, renderer: this._renderCost},
cart_cost: {width: 50},
delivery_cost: {width: 75},
weight: {width: 50},
status: {width: 50, renderer: miniShop2.utils.renderBadge},
delivery: {width: 75},
order_comment: {width: 100},
payment: {width: 75},
text_address: {width: 150},
city: {width: 100}, //получатель
region: {width: 75}, //дата доставки
phone: {width: 100}, //телефон заказчика
//context: {width: 50},
actions: {width: 75, id: 'actions', renderer: miniShop2.utils.renderActions, sortable: false},
};
Я добавил нужные мне поля.
text_address: {width: 150},
city: {width: 100}, //получатель
region: {width: 75}, //дата доставки
phone: {width: 100}, //телефон заказчика
Кстати, я не добавлял новых полей в таблицу, а использовал уже имеющийся, собственно поэтому у меня поле 'city' по сути является именем получателя, и т.д., не знаю, чем это аукнется в дальнейшем, но пока так как есть. Кстати, тут было бы тоже здорово, узнать ваше мнение, стоит ли завести новые поля или так тоже ничего?
Еще, что бы все заработало, нужно создать плагин.
Я назвал его orderGridChange
<?php
switch ($modx->event->name) {
case 'msOnManagerCustomCssJs':
$modx->controller->addLastJavascript(MODX_ASSETS_URL.'custom/orderGridChange.js');
break;
}
Плагину, нужно поставить галку в закладке системные события напротив msOnManagerCustomCssJsИ если, я ничего не упустил, то в завершение, в системных настройках ms2_order_grid_fields нужно указать перечень полей, нужных для вывода в таблице, у меня это выглядит так: id,num,customer,status,cost,delivery,payment,createdon,comment,order_comment,region,city,updatedon,text_address,phone
Всем удачи, и спасибо за помощь!
Комментарии: 6
Вам нужно переопределить процессор getlist скорей всего. Посмотрите вот эту статейку, там есть кусок описания про переопредление. ВОзможно вам поможет.
modx.pro/howto/24899
modx.pro/howto/24899
Спасибо за наводку! Покурю… кстати, а где сами процессоры minishopa живут? Что называется, что бы за образец взять скрипты. Забегая вперед, я знаю, что изменять исходники — дурной тон=)
Процессоры лежат тут:
core/components/minishop2/processors/mgr/
В статье описано как не изменять исходники, там же и про процессор написано.
При большом желании можно изменить исходник, проверить работает ли сама идея и потом уже переопределять
core/components/minishop2/processors/mgr/
В статье описано как не изменять исходники, там же и про процессор написано.
При большом желании можно изменить исходник, проверить работает ли сама идея и потом уже переопределять
да, да, именно так я и планировал поступить=) Спасибо!
Разобрался, все сделал! Спасибо за помощь!
Разобрался, все сделал! Спасибо за помощь!
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.