Если кому интересно, делюсь решением. Если что не так в коде, - знающих прошу подсказать.
1. Для начала создал таблицу для группы полей в базе. В моём случае выглядит так (префикс надо поменять на свой):
CREATE TABLE IF NOT EXISTS `ww1rs_customs_before` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`item_id` int(11) NOT NULL,
`type` varchar(64) NOT NULL,
`text` text NOT NULL,
`name` varchar(255) NOT NULL,
`ordering` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2. Создал файл customs_before.php в папке administrator/components/com_djcatalog2/helpers/ такого содержания:
<?php
defined('_JEXEC') or die();
class DJCatalog2CustomsBeforeHelper extends JObject {
public static function renderInput($itemtype, $itemid=null) {
if (!$itemtype) {
return false;
}
$db = JFactory::getDbo();
$atts = array();
if ($itemid) {
$db->setQuery('SELECT * '.
' FROM #__customs_before '.
' WHERE item_id='.intval($itemid).
' AND type='.$db->Quote($itemtype).
' ORDER BY ordering ASC, name ASC ');
$atts = $db->loadObjectList();
}
$out = '';
if (count($atts)) {
$out .= '<ul>';
foreach ($atts as $attachment) {
$out .= '
<li>
<label for="djc2_customs_beforeOrder_'.$attachment->id.'">'.JText::_('COM_DJCATALOG2_CUSTOMS_BEFORE_ORDER_LABEL').'</label>
<input id="djc2_customs_beforeOrder_'.$attachment->id.'" type="text" name="customs_before_order_'.$itemtype.'['.$attachment->id.']" value="'.$attachment->ordering.'" />
<label for="djc2_customs_beforeCaption_'.$attachment->id.'">'.JText::_('COM_DJCATALOG2_CUSTOMS_BEFORE_CAPTION_LABEL').'</label>
<input id="djc2_customs_beforeCaption_'.$attachment->id.'" type="text" name="customs_before_name_'.$itemtype.'['.$attachment->id.']" value="'.$attachment->name.'" />
<label for="djc2_customs_beforeDelete_'.$attachment->id.'">'.JText::_('COM_DJCATALOG2_CUSTOMS_BEFORE_DELETE_LABEL').'</label>
<input id="djc2_customs_beforeDelete_'.$attachment->id.'" type="checkbox" name="customs_before_delete_'.$itemtype.'['.$attachment->id.']" value="1" />
<span class="faux-label">'.JText::_('COM_DJCATALOG2_CUSTOMS_BEFORE').'</span>
<textarea name="customs_before_text_'.$itemtype.'['.$attachment->id.']" >'.$attachment->text.'</textarea>
<input type="hidden" name="customs_before_id_'.$itemtype.'[]" value="'.$attachment->id.'" />
</li>
<li><div style="clear:both; border-bottom:1px dashed #ccc; width: 100%; padding-top: 10px; margin-bottom: 10px;"></div></li>
';
}
$out .= '</ul>';
}
else {
$out .= JText::_('COM_DJCATALOG2_NO_CUSTOMS_BEFORE_INCLUDED').'<br />';
}
$out .= '
<ul id="customs_before_uploader_'.$itemtype.'">
<li>
<span class="faux-label">'.JText::_('COM_DJCATALOG2_CUSTOMS_BEFORE_CAPTION_LABEL').'</span>
<input type="text" name="customs_before_new_name_'.$itemtype.'[]" />
<span class="faux-label">'.JText::_('COM_DJCATALOG2_CUSTOMS_BEFORE').'</span>
<textarea name="customs_before_new_text_'.$itemtype.'[]" ></textarea>
<input type="hidden" name="new_customs_id_'.$itemtype.'[]" value="0" />
</li>
</ul>
<div style="clear:both; border-bottom:1px dashed #ccc; width: 100%; padding-top: 10px; margin-bottom: 10px;"></div>
<div class="button2-left"><div class="blank"><span onclick="addAttr_'.$itemtype.'(); return false;">'.JText::_('COM_DJCATALOG2_ADD_CUSTOMS_BEFORE_LINK').'</span></div></div>
';
$out .= '
<script type="text/javascript">
function addAttr_'.$itemtype.'(){
var customs_before_name = document.createElement(\'input\');
customs_before_name.setAttribute(\'name\',\'customs_before_new_name_'.$itemtype.'[]\');
customs_before_name.setAttribute(\'type\',\'text\');
var customs_before_text = document.createElement(\'textarea\');
customs_before_text.setAttribute(\'name\',\'customs_before_new_text_'.$itemtype.'[]\');
var namelabel = document.createElement(\'span\');
namelabel.setAttribute(\'class\',\'faux-label\');
namelabel.innerHTML=\''.JText::_('COM_DJCATALOG2_CUSTOMS_BEFORE_CAPTION_LABEL').'\';
var customs_beforetext_label = document.createElement(\'span\');
customs_beforetext_label.setAttribute(\'class\',\'faux-label\');
customs_beforetext_label.innerHTML=\''.JText::_('COM_DJCATALOG2_CUSTOMS_BEFORE').'\';
var new_customs = document.createElement(\'input\');
new_customs.setAttribute(\'name\',\'new_customs_id_'.$itemtype.'[]\');
new_customs.setAttribute(\'type\',\'hidden\');
var customs_beforeFormDiv = document.createElement(\'li\');
customs_beforeFormDiv.appendChild(namelabel);
customs_beforeFormDiv.appendChild(customs_before_name);
customs_beforeFormDiv.appendChild(customs_beforetext_label);
customs_beforeFormDiv.appendChild(customs_before_text);
customs_beforeFormDiv.appendChild(new_customs);
var ni = document.id(\'customs_before_uploader_'.$itemtype.'\');
ni.appendChild(customs_beforeFormDiv);
}
</script>
';
return $out;
}
public static function deleteCustomsBefore($itemtype, $itemid) {
if (!$itemtype || !$itemid) {
return false;
}
$db = JFactory::getDbo();
$atts = array();
$db->setQuery('SELECT id, name '.
' FROM #__customs_before '.
' WHERE item_id='.intval($itemid).
' AND type='.$db->Quote($itemtype).
' ORDER BY ordering ASC, name ASC ');
$atts = $db->loadObjectList();
$atts_to_remove = array();
if (count($atts)) {
foreach ($atts as $key=>$attachment) {
$atts_to_remove[] = $attachment->id;
}
}
if (count($atts_to_remove)) {
$ids = implode(',',$atts_to_remove);
$db->setQuery('DELETE FROM #__customs_before WHERE id IN ('.$db->getEscaped($ids, false).')');
$db->query();
}
return true;
}
public static function saveCustomsBefore($itemtype, $itemid, &$params, $isNew) {
if (!$itemtype || !$itemid || empty($params)) {
return false;
}
$db = JFactory::getDbo();
$app = JFactory::getApplication();
$custom_id = JRequest::getVar('customs_before_id_'.$itemtype, array(),'default');
$delete = JRequest::getVar('customs_before_delete_'.$itemtype, array(),'default');
$order = JRequest::getVar('customs_before_order_'.$itemtype, array(),'default');
$name = JRequest::getVar('customs_before_name_'.$itemtype, array(),'default');
$text = JRequest::getVar('customs_before_text_'.$itemtype, array(),'default');
$new_customs = JRequest::getVar('new_customs_id_'.$itemtype, array(),'default');
$atts_to_update = array();
$atts_to_save = array();
$atts_to_copy = array();
$orderingCounter = 0;
//delete
if (count($delete) && !$isNew) {
$cids = implode(',', array_keys($delete));
$db->setQuery('DELETE FROM #__customs_before WHERE id IN ('.$db->getEscaped($cids, false).')');
$db->query();
foreach ($delete as $key => $value) {
if ($value == 1) {
$idx = array_search($key, $custom_id);
if (array_key_exists($idx, $custom_id)) {
unset($custom_id[$idx]);
}
}
}
}
if (count($custom_id)) {
$ids = implode(',', $custom_id);
$db->setQuery('SELECT * FROM #__customs_before WHERE id IN ('.$db->getEscaped($ids, false).') ORDER BY ordering ASC, name ASC');
$atts = $db->loadObjectList();
foreach ($custom_id as $key) {
foreach ($atts as $attachment) {
if ($attachment->id == $key && !array_key_exists($key, $delete)) {
$obj = array();
$obj['id'] = ($isNew)? null:$key;
if (isset($order[$key])) {
$obj['ordering'] = intval($order[$key]);
} else {
$obj['ordering'] = $attachment->ordering;
}
$obj['type'] = $itemtype;
if (isset($text[$key])) {
$obj['name'] = $name[$key];
} else {
$obj['name'] = '';
}
if (isset($text[$key])) {
$obj['text'] = $text[$key];
} else {
$obj['text'] = '';
}
if ($obj['id']) {
$atts_to_update[] = $obj;
} else {
$atts_to_copy[] = $obj;
}
}
}
}
usort($atts_to_update, array('DJCatalog2FileHelper', 'setOrdering'));
}
$name = JRequest::getVar('customs_before_new_name_'.$itemtype,array(),'default');
$text = JRequest::getVar('customs_before_new_text_'.$itemtype, array(),'default');
foreach ($new_customs as $key => $val) {
$obj = array();
$obj['id'] = null;
$obj['ordering'] = 0;
$obj['item_id'] = $itemid;
$obj['type'] = $itemtype;
if (isset($text[$key]) && $text[$key] != '') {
$obj['text'] = $text[$key];
}
if (isset($name[$key]) && $name[$key] != '') {
$obj['name'] = $name[$key];
}
if ((isset($text[$key]) && $text[$key] != '') || (isset($name[$key]) && $name[$key] != '')) {
$atts_to_save[] = $obj;
} else {
$app->setError(JText::_('COM_DJCATALOG2_CUSTOMS_ERROR'));
}
}
// order
$ordering = 1;
foreach ($atts_to_update as $k=>$v) {
$atts_to_update[$k]['ordering'] = $ordering++;
$obj = new stdClass();
foreach ($atts_to_update[$k] as $key=>$data) {
$obj->$key = $data;
}
if ($isNew) {
$ret = $db->insertObject( '#__customs_before', $obj, 'id');
} else {
$ret = $db->updateObject( '#__customs_before', $obj, 'id', false);
}
if( !$ret ){
$app->setError(JText::_('COM_DJCATALOG2_CUSTOMS_STORE_ERROR').$db->getErrorMsg());
continue;
}
}
$atts_to_process = array_merge($atts_to_copy, $atts_to_save);
foreach ($atts_to_process as $k=>$v) {
$atts_to_process[$k]['ordering'] = $ordering++;
$obj = new stdClass();
foreach ($atts_to_process[$k] as $key=>$data) {
$obj->$key = $data;
}
$ret = $db->insertObject( '#__customs_before', $obj, 'id');
if( !$ret ){
unset($atts_to_process[$k]);
$app->setError(JText::_('COM_DJCATALOG2_CUSTOMS_STORE_ERROR').$db->getErrorMsg());
continue;
}
}
return true;
}
public static function setOrdering($fild1, $fild2){
return (int)($fild1['ordering'] - $fild2['ordering']);
}
}
3. В файле administrator/components/com_djcatalog2/views/item/tmpl/edit.php:
просле строк:
<fieldset class="adminform">
<?php echo DJCatalog2FileHelper::renderInput('item',JRequest::getVar('id', null)); ?>
</fieldset>
вставил:
<?php echo JHtml::_('sliders.panel',JText::_('COM_DJCATALOG2_CUSTOMS_BEFORE_NAME'), 'item-customs_before'); ?>
<fieldset class="adminform">
<?php echo DJCatalog2CustomsBeforeHelper::renderInput('item',JRequest::getVar('id', null)); ?>
</fieldset>
4. В файле administrator/components/com_djcatalog2/lib/events.php:
находим строки:
// saving attachments
if (!DJCatalog2FileHelper::saveFiles('item',$table->id, $params, $isNew)) {
$app->enqueueMessage(JText::_('COM_DJCATALOG2_ERROR_SAVING_FILES'),'error');
}
после них вставляем:
if (!DJCatalog2CustomsBeforeHelper::saveCustomsBefore('item',$table->id, $params, $isNew)) {
$app->enqueueMessage(JText::_('COM_DJCATALOG2_ERROR_SAVING_FILES'),'error');
}
находим строки:
if (!DJCatalog2FileHelper::deleteFiles('item',$table->id)) {
$app->enqueueMessage(JText::_('COM_DJCATALOG2_ERROR_DELETING_FILE'),'error');
}
после них вставляем:
if (!DJCatalog2CustomsBeforeHelper::deleteCustomsBefore('item',$table->id)) {
$app->enqueueMessage(JText::_('COM_DJCATALOG2_ERROR_DELETING_FILE'),'error');
}
5. И последний штрих. Подключаем хелпер в файле administrator/components/com_djcatalog2/admin.djcatalog2.php:
после строки:
require_once(JPATH_COMPONENT.DS.'helpers'.DS.'file.php');
вставляем:
require_once(JPATH_COMPONENT.DS.'helpers'.DS.'customs_before.php');
У меня всё нормально добавляется-удаляется-обновляется.
На языковом файле я тут останавливаться не буду.
Теперь осталось вывести эти поля в карточке товара.