tab('info', _t('@listings', 'Description'), [
'wrapperLI' => static function($html) use ($form) { if (! $form->recordID()) { return $html;} ?>
= $html ?>
text('title', _t('@', 'Title'), '', $translate)
->classAdd('j-title')
->required()
;
$catAcData = [];
$form ->autocomplete('cat_id', _t('@listings', 'Category'), function ($q){
return Listings::ajaxHandlerCategoryAutocomplete(['q' =>$q, 'type' => 'adm-item-form']);
}, function ($id) use (& $catAcData) {
$data = Listings::ajaxHandlerCategoryAutocomplete(['id' => $id, 'type' => 'adm-item-form']);
$catAcData = reset($data);
return $catAcData[2]['title'] ?? '';
})
->required()
->wrapperClassAdd('j-cat_id-block')
->beforeFieldRender(function ($html) use (& $catAcData) { ?>
= $catAcData[2]['parents'] ?? '' ?>
= $html ?>
param('custom', ['init' => [
'onSelect' => function() { ?>getData('cat_id', 0);
if (! $catID) {
return [];
}
if (Listings::CATS_TYPES_EX) {
return Listings::model()->cattypesByCategory($catID);
} else {
return Listings::model()->cattypesSimple(Listings::catData($catID), false);
}
};
$form ->select('cat_type', _t('@listings', 'Listing Type'), 0, $types)
->absentIf('cat_id', function ($val) use ($types) {
$t = $types();
return empty($val) || empty($t) || count($t) == 1;
})
->jsOnChange(function (){ ?>dynprops(Listings::dp(), 'cat_id');
$radioHTML = '';
$form ->text('price', _t('@filter', 'Price'), 0, false)
->stretch('sm')
->beforeFieldRender(function ($html) use ($form, & $radioHTML) { $ex = $form->getData('price_ex', 0); ?>
= $radioHTML ?>
= $html ?>
titleRender(function ($html) use ($form) {
$d = $form->_data();
$cat = Listings::catData($d['cat_id'] ?? 0);
$lang = Lang::current();
if (! empty($cat['settings']['price']['title'][$lang])) {
return $cat['settings']['price']['title'][$lang];
}
return $html;
})
->absentIf('cat_id', function ($val) {
return empty($val) || empty(Listings::catData($val)['settings']['price']['enabled']);
})
->select('price_curr', '', 0, function () use ($form) {
$d = $form->_data();
$selected = Currency::id();
$cat = Listings::catData($d['cat_id'] ?? 0);
$sett = $cat['settings']['price'] ?? [];
if (! empty($sett['curr'])) {
$selected = $sett['curr'];
}
if (! empty($d['price_curr'])) {
$selected = $d['price_curr'];
}
return Currency::options($selected);
})
->stretch('mini')
->together('price')
->checkbox('price_ex2')
->label(function () use ($form) {
$d = $form->_data();
$lang = Lang::current();
$cat = Listings::catData($d['cat_id'] ?? 0);
$sett = $cat['settings']['price'] ?? [];
return ! empty($sett['mod_title'][$lang]) ? $sett['mod_title'][$lang] : _t('@filter', 'Negotiable');
})
->beforeFieldRender(function ($html) use ($form) {
$d = $form->_data();
$cat = Listings::catData($d['cat_id'] ?? 0);
$ex = $cat['settings']['price']['ex'] ?? 0;
if ($ex & ItemPrice::EX_MOD) {
return $html;
}
return '';
})
->onValidate(function ($p) {
$p['result']['price_ex'][] = $p['value'];
return false;
})
->onValue(function ($v) use ($form) {
$ex = $form->getData('price_ex', 0);
if (is_array($ex)) {
$ex = array_sum($ex);
}
return $ex & ItemPrice::EX_MOD;
})
->together('price')
->radio('price_ex1', '', 0, function () use ($form) {
$d = $form->_data();
$cat = Listings::catData($d['cat_id'] ?? 0);
$ex = $cat['settings']['price']['ex'] ?? 0;
$data = [
ItemPrice::EX_FREE => _t('@listings', 'Free'),
ItemPrice::EX_EXCHANGE => _t('@listings', 'Exchange'),
ItemPrice::EX_AGREED => _t('@listings', 'Negotiable'),
];
foreach ($data as $k => $v) {
if ($ex & $k) {
continue;
}
unset($data[$k]);
}
$data[ItemPrice::EX_PRICE] = _t('@listings', 'Price');
if ($ex & ItemPrice::EX_FROM) {
$data[ItemPrice::EX_FROM] = _t('@listings', 'Price From');
}
return $data;
})
->beforeFieldRender(function ($html) use ($form, & $radioHTML) {
$d = $form->_data();
$cat = Listings::catData($d['cat_id'] ?? 0);
$ex = $cat['settings']['price']['ex'] ?? 0;
if (ItemPrice::i()->isRadio($ex)) {
$radioHTML = ''.$html.'
';
}
return '';
})
->onValidate(function ($p) {
$p['result']['price_ex'][] = $p['value'];
return false;
})
->onValue(function ($v) use ($form) {
$ex = $form->getData('price_ex', 0);
if (is_array($ex)) {
$ex = array_sum($ex);
}
$ex = $ex & (ItemPrice::EX_FREE + ItemPrice::EX_EXCHANGE + ItemPrice::EX_AGREED + ItemPrice::EX_FROM);
return ItemPrice::i()->isRadio($ex) ? $ex : 0;
})
->together('price')
->jsOnChange(function () { ?>select('price_ex_mod', '', 1, function () use ($form) {
$cat = Listings::catData($form->getData('cat_id', 0));
return ItemPrice::i()->modifiersOptions($cat['settings'] ?? []);
})
->beforeFieldRender(function ($html) use ($form) {
$cat = Listings::catData($form->getData('cat_id', 0));
$ex = $cat['settings']['price']['ex'] ?? 0;
if ($ex & ItemPrice::EX_MOD_MANY) {
return $html;
}
return '';
})
->stretch('sm')
->together('price')
;
$ownerTypeOptions = function () use ($form) {
$d = $form->_data();
$cat = Listings::catData($d['cat_id'] ?? 0);
return [
Listings::OWNER_PRIVATE => ! empty($cat['owner_private_form']) ? $cat['owner_private_form'] : _t('@listings', 'Individual'),
Listings::OWNER_BUSINESS => ! empty($cat['owner_business_form']) ? $cat['owner_business_form'] : _t('@listings', 'Company'),
];
};
$form ->select('owner_type', '', false, $ownerTypeOptions, false, ['optionsID' => null, 'optionsTitle' => null])
->titleRender(function ($html) use ($ownerTypeOptions) { return join(' / ', $ownerTypeOptions()); })
->absentIf('cat_id', 0)
;
Geo::citySelectForm($form, 'geo_city') # 'geo_region1'
->required()
->absentIf('cat_id', function ($val) {
return empty($val) || empty(Listings::catData($val)['settings']['geo']['enabled']);
})
;
$form ->checkbox('regions_delivery')
->label(_t('@listings', 'Delivery To the Regions'))
->absentIf('cat_id', function ($val) {
$cat = Listings::catData($val)['settings']['geo'] ?? [];
return empty($val) || empty($cat['enabled']) || empty($cat['delivery']);
})
;
if (Geo::districtsEnabled()) { $form
->select('district_id', _t('@', 'District'), 0, function () use ($form) {
$d = $form->_data();
return Geo::districtOptions((int)($d['geo_city'] ?? 0), (int)($d['district_id'] ?? 0), _t('@', 'Not Specified'));
})
->absentIf('cat_id', function ($val) {
return empty($val) || empty(Listings::catData($val)['settings']['geo']['enabled']);
})
->absentIf('geo_city', 0)
;}
if (Geo::metroEnabled()) { $form
->select('metro_id', _t('@', 'Metro'), 0, function () use ($form) {
$d = $form->_data();
$data = Geo::cityMetro($d['geo_city'] ?? 0, ['selected' => $d['metro_id'] ?? 0, 'html' => true]);
return $data['html'] ?? '';
})
->absentIf('cat_id', function ($val) {
$geo = Listings::catData($val)['settings']['geo'] ?? [];
return empty($val) || empty($geo['enabled']) || empty($geo['metro']);
})
->absentIf('geo_city', function ($val) {
return empty($val) || ! Geo::hasMetro($val);
})
;}
Geo::mapAddrPointForm($form, 'addr_addr') # 'addr_lat', 'addr_lon'
->absentIf('cat_id', function ($val) {
$geo = Listings::catData($val)['settings']['geo'] ?? [];
return empty($val) || empty($geo['enabled']) || empty($geo['addr']);
})
->absentIf('geo_city', function ($val, $f, $p = []) use ($form) {
if (! empty($p['data'])) {
$p['data']['addr_addr'] = '';
$p['data']['addr_lat'] = '';
$p['data']['addr_lon'] = '';
}
return empty($val);
})
;
$form ->textarea('descr', _t('@', 'Description'), '', $translate)
->required()
;
$catId = 0;
$form ->imagesTable(Listings::itemImages(), ItemImages::szSmall, ItemImages::szView, _t('@listings', 'Photo'))
->param('rotate', true)
->absentIf('cat_id', static function ($val) use (& $catId) {
$catId = $val;
return empty($val) || empty(Listings::catData($val)['settings']['photos']['limit']);
})
->beforeFieldView(static function($p, $field) use (& $catId, $form) { /** @var ItemImages $field */
if (! $catId) {
$catId = $form->getData('cat_id');
}
$limit = Listings::catData($catId)['settings']['photos']['limit'] ?? 0;
if ($limit) {
$field->setLimit($limit);
}
})
;
$form ->text('video', _t('@listings', 'Video Link'), '', false)
->htmlAfter('' . _t('@listings', 'Youtube, Vimeo') . '')
->absentIf('cat_id', function ($val) {
return empty($val) || empty(Listings::catData($val)['settings']['video']['enabled']);
})
;
$form->divider();
$form->buttonDelete();
# user_id, phones, contacts, publicated_period
$form->whenNew(function () use ($form) {
$form->tab('info');
$form->autocomplete('user_id', _t('@users', 'Owner'), static function ($q) {
if (bff::input()->post('company', TYPE_UINT) || Listings::publisher(Listings::PUBLISHER_COMPANY)) {
return Business::handlerUserCompanyAutocomplete(['q' => $q]);
}
return Listings::ajaxHandlerItemUser(['q' => $q, 'noCompany' => 1]);
}, static function (){}, _te('@users', 'Search owner...'))
->required()
->onValidate(static function ($p) {
$userData = Users::userData($p['value'] ?? 0);
if (empty($userData)) {
Errors::set(_t('@listings', 'Incorrect user email address'), 'user_id');
return false;
}
foreach (['name','phones','contacts'] as $f) {
if (empty($userData[$f])) {
continue;
}
$p['result'][$f] = $userData[$f];
}
return true;
})
->param('custom', ['init' => ['before' => static function () { ?>wrapperAttr('class', 'j-user-id-bl')
;
$period = Listings::itemPublicationPeriod();
if ($period->isAvailable()) {
$form->select('publicated_period', _t('@listings', 'Publishing'), 0, function ($field) use ($period) { /** @var Input $field */
$daysDefault = 0;
$data = $period->options(['default' => & $daysDefault]);
$field->setValue($daysDefault);
foreach ($data as $k => & $v) {
$v['id'] = $k;
$v['to'] = HTML::escape(_t('@item-form', 'before [date]', ['date' => tpl::date(strtotime('+' . $v['days'] .'days'), false)]));
} unset($v);
return $data;
})
->param('optionsTitle', 't')
->param('optionsDataAttributes', ['to'])
->htmlAfter(function ($field) { /** @var $field Input */ ?>
= _t('@item-form', 'before [date]', ['date' => tpl::date(strtotime('+' . $field->value() .'days'), false)]) ?>
jsOnChange(function () { ?>absentIf('cat_id', function ($val) {
return empty($val) || ! empty(Listings::catData($val)['settings']['publication']['infinite']);
});
} else if ($period->isUnavailable()) {
$form->staticText('', _t('@listings', 'Publishing'), function () use ($period) { ?>
= _t('@', 'from [date]', ['date' => tpl::date(time(), false)]); ?>
= _t('@', 'till [date]', ['date' => tpl::date($period->publishTo(['period' => $period->default(),'format' => false]), false)]) ?>
absentIf('cat_id', function ($val) {
return empty($val) || ! empty(Listings::catData($val)['settings']['publication']['infinite']);
});
}
})
->whenEdit(function () use ($form) { $form
->tab('info')
->staticText('user_id', _t('@users', 'Owner'), function ($v) use ($form) {
$user = Users::model()->userData($v, ['user_id', 'email', 'phone_number']);
if (empty($user)) {
return _t('@users', 'Owner was deleted');
}
if ($companyId = $form->getData('company_id')) {
$company = Business::model()->companyData($companyId, ['id', 'title']); ?>
= $company['title'] ?? '' ?>
= $user['email'] ?> = $user['phone_number'] ?>
text('name', _t('@users', 'Name'), '', false);
if (Listings::publisher(Listings::PUBLISHER_USER)) {
$form->required();
}
}
$form->group('phones', _t('@item-form', 'One More Phone'), _t('@users', 'Phones'), ['plus' => ['type' => 'href', 'position' => 'after']])
->param('inline', true)
->param('sortable', false)
->text('v', '', '', false)
->stretch('lg')
->endGroup()
->onValidate(function ($p){
$result = [];
foreach ($p['value'] as $v) {
if (! empty($v['v'])) {
$result[] = $v['v'];
}
}
$p['value'] = $result;
return true;
})
;
$contactFields = Users::contactsFields();
if (! empty($contactFields)) {
$form->union('contacts')
->param('box', false);
foreach ($contactFields as $contact_key => $contact) {
$form->text($contact_key, $contact['title'], '', false)
->stretch('lg');
}
$form->endGroup();
}
$form->custom('status')
->getCustom()
->noTitle()
->onView(function () use ($form){
$d = $form->_data();
$d['user'] = ['blocked' => $d['user_blocked'] ?? 0];
return Listings::template('admin/form.status', $d);
})
->end();
});
# publisher
if (Listings::publisher(Listings::PUBLISHER_COMPANY)) {
$form->whenNew(static function () use ($form) {
$form->tab('info')
->inputHidden('company', 1)
->to('user_id')
->tip(_te('@listings', 'Only users with opened company'));
});
} else if (Listings::publisher([Listings::PUBLISHER_USER_TO_COMPANY, Listings::PUBLISHER_USER_OR_COMPANY])) {
$form->whenNew(static function () use ($form) {
$form->tab('info');
$form->radio('company', '', 0, static function () {
return [
0 => _t('@listings', 'Individual'),
1 => _t('@listings', 'Company'),
];
})
->jsOnChange(static function () { ?>before('user_id')
;
})
->whenEdit(static function () use ($form) {
$form->tab('info');
if (Listings::publisher(Listings::PUBLISHER_USER_OR_COMPANY)) {
$form->radio('company', '', 0, function () {
return [
0 => _t('@listings', 'Individual'),
1 => _t('@listings', 'Company'),
];
})
->after('user_id')
->onValue(static function ($v) use ($form) {
return ! empty($form->getData('company_id')) ? 1 : 0;
})
;
} else if (Listings::publisher(Listings::PUBLISHER_USER_TO_COMPANY)) {
$form->staticText('company_id', '', function ($v) { return $v ? '' . _t('@listings', 'Company') .'' : ''; })
->after('user_id')
;
}
});
}
# Comments, Complaints, Services
$form->whenEdit(function () use ($form) {
if (Listings::commentsEnabled()) {
$form
->tabAjax('comments', _t('@listings', 'Comments'), $form->ajaxUrl('comments-init'), [
'counter' => function() use ($form){ return $form->getData('comments_cnt', 0); }
])
->formAjaxHandler('comments-init', function () use ($form) {
if (! Listings::haveAccessTo('items-comments')) {
Errors::accessDenied();
return [];
}
$id = $form->recordID();
$comments = Listings::itemComments();
$comments->admListingIncludes();
View::start(); ?>
= $comments->admListing($id); ?>
View::stop()];
return $form->appendIncludedStatic($response);
});
}
$form
->tabAjax('claims', _t('@listings', 'Complaints'), $form->ajaxUrl('claims-init'), [
'counter' => static function() use ($form){ return $form->getData('claims_cnt', 0); }
])
->formAjaxHandler('claims-init', function () use ($form) {
if (! Listings::haveAccessTo('claims-edit')) {
Errors::accessDenied();
return [];
}
$id = $form->recordID();
$data['id'] = $id;
$data['claims'] = Listings::model()->claimsListing(['item_id' => $id]);
foreach ($data['claims'] as &$v) {
$v['message'] = Listings::itemClaims()->toText($v['reason'], $v['message']);
}
unset($v);
View::start(); ?>
= Listings::template('admin/items.claims', $data) ?>
View::stop()];
return $form->appendIncludedStatic($response);
});
if (bff::servicesEnabled('listings')) {
$form
->tabAjax('svc', _t('@listings', 'Services'), $form->ajaxUrl('svc-init'))
->formAjaxHandler('svc-init', function () use ($form) {
$form->load();
$data = $form->_data();
$data['services'] = Listings::itemServices()->itemActiveServices($form->recordID(), $data);
View::start(); ?>
= Listings::template('admin/form.svc', $data) ?>
View::stop()];
return $form->appendIncludedStatic($response);
});
}
});
# moderated data
$form->whenEdit(function () use ($form, $translate) {
$form->tab('info');
$moderatedValue = function ($name, $sub = '') use ($form) {
if ($sub) {
$v = $form->getData('moderated_data', [])[$sub][$name] ?? '';
} else {
$v = $form->getData('moderated_data', [])[$name] ?? '';
}
$v = HTML::escape($v);
$v = strtr($v, ['"' => '"']);
return $v;
};
$isVisible = function ($name, $sub = '') use ($form) {
$d = $form->_data();
if ($sub) {
$value = $d[$sub][$name] ?? '';
$moderated = $d['moderated_data'][$sub][$name] ?? '';
} else {
$value = $d[$name] ?? '';
$moderated = $d['moderated_data'][$name] ?? '';
}
if (is_array($value)) {
$lang = $d['lang'] ?? Lang::current();
$value = $value['lang'] ?? reset($value);
}
return ! empty($moderated) && $moderated != $value;
};
foreach ([
'title' => ['class' => 'moderation-compare-inline', 'translate' => $translate],
'addr_addr' => ['class' => 'moderation-compare-inline'],
'descr' => ['highlight' => 1, 'translate' => $translate],
'video' => ['class' => 'moderation-compare-inline'],
'name' => ['class' => 'moderation-compare-inline'],
] as $f => $v) {
if (empty($form->field($f))) {
continue;
}
$form->staticText('', '', function ($html, $field) use ($form, $moderatedValue, $f, $v) {
/** @var Input $field */
$translate = $v['translate'] ?? false;
$lang = $form->getData('lang', Lang::current());
if ($translate) {
$field->wrapperClassAdd('j-lang-form')->wrapperClassAdd('j-lang-form-' . $lang);
if ($lang != Lang::current()) {
$field->wrapperClassAdd('displaynone');
}
}
?>
getData($f, '');
echo \bff\utils\TextParser::highlightStringCompare($m, $translate ? ($d[$lang] ?? '') : $d);
} ?>
after($f)
->afterFieldRender(function ($html) use ($isVisible, $f) { return $isVisible($f) ? $html : ''; })
;
}
$contactFields = Users::contactsFields();
if (! empty($contactFields)) {
$form->to('contacts');
foreach ($contactFields as $contact_key => $contact) {
$form->staticText('', '', function () use ($form, $moderatedValue, $contact_key) { ?>
= $moderatedValue($contact_key, 'contacts') ?>
after($contact_key)
->afterFieldRender(function ($html) use ($isVisible, $contact_key) { return $isVisible($contact_key, 'contacts') ? $html : ''; })
;
}
$form->endGroup();
}
});
# auto-title
$form->divider()
->absentIf('cat_id', function ($val, $field, $o = []) {
if (isset($o['response'])) {
$o['response']['catData'] = Listings::catData($val);
}
return true;
});
$form->jsOnReadyContent(function (){ ?>jsInObject(function () use ($form){ $cat = Listings::catData($form->getData('cat_id', 0)); ?>whenEdit(function () use ($form) {
$form->to('title')->beforeFieldView(function ($p, $field) use ($form) { /** @var Input $field */
$cat = Listings::catData($form->getData('cat_id', 0));
if (! empty($cat['tpl_title_enabled'])) {
HTML::attributeAdd($field->attr, 'disabled', 'disabled');
}
});
});