2
0
forked from Wavyzz/dolibarr

Merge branch '12.0' of git@github.com:Dolibarr/dolibarr.git into 12.0

This commit is contained in:
Laurent Destailleur
2020-06-20 12:19:36 +02:00
5 changed files with 92 additions and 140 deletions

View File

@@ -341,74 +341,6 @@ class FormAdvTargetEmailing extends Form
return $return; return $return;
} }
/**
* Return combo list with customer categories
*
* @param string $htmlname Name of categorie
* @param array $selected_array value selected
* @return string HTML combo
*/
public function multiselectCustomerCategories($htmlname = 'cust_cat', $selected_array = array())
{
return $this->multiselectCategories($htmlname, $selected_array, 2);
}
/**
* Return combo list with customer contact
*
* @param string $htmlname Name of categorie
* @param array $selected_array value selected
* @return string HTML combo
*/
public function multiselectContactCategories($htmlname = 'contact_cat', $selected_array = array())
{
return $this->multiselectCategories($htmlname, $selected_array, 4);
}
/**
* Return combo list of categories
*
* @param string $htmlname Name of categorie
* @param array $selected_array Value selected
* @param int $type Type
* @return string HTML combo
*/
public function multiselectCategories($htmlname = '', $selected_array = array(), $type = 0)
{
global $conf, $langs, $user;
$langs->load("dict");
$options_array = array();
$sql = "SELECT rowid, label FROM ".MAIN_DB_PREFIX."categorie";
$sql .= " WHERE type=".$type;
dol_syslog(__METHOD__, LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql)
{
$num = $this->db->num_rows($resql);
$i = 0;
if ($num)
{
while ($i < $num)
{
$obj = $this->db->fetch_object($resql);
$options_array[$obj->rowid] = $obj->label;
$i++;
}
}
}
else
{
dol_print_error($this->db);
}
return $this->advMultiselectarray($htmlname, $options_array, $selected_array);
}
/** /**
* Return a combo list to select emailing target selector * Return a combo list to select emailing target selector
* *

View File

@@ -3544,10 +3544,19 @@ if ($action == 'create')
} }
// Other attributes // Other attributes
$parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="2"', 'cols' => '2'); $parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="2"', 'cols' => '2', 'socid'=>$socid);
$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
print $hookmanager->resPrint; print $hookmanager->resPrint;
if (empty($reshook)) { if (empty($reshook)) {
if (!empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_INVOICE)) {
// copy from thirdparty
$tpExtrafields = new Extrafields($db);
$tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($soc->table_element);
if ($soc->fetch_optionals() > 0) {
$object->array_options = array_merge($object->array_options, $soc->array_options);
}
};
print $object->showOptionals($extrafields, 'edit', $parameters); print $object->showOptionals($extrafields, 'edit', $parameters);
} }

View File

@@ -455,6 +455,7 @@ if (!$sall) $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'paiement_facture as pf ON pf.f
if ($sall || $search_product_category > 0) $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'facturedet as pd ON f.rowid=pd.fk_facture'; if ($sall || $search_product_category > 0) $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'facturedet as pd ON f.rowid=pd.fk_facture';
if ($search_product_category > 0) $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product=pd.fk_product'; if ($search_product_category > 0) $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product=pd.fk_product';
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet as p ON p.rowid = f.fk_projet"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet as p ON p.rowid = f.fk_projet";
$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'user AS u ON f.fk_user_author = u.rowid';
// We'll need this table joined to the select in order to filter by sale // We'll need this table joined to the select in order to filter by sale
if ($search_sale > 0 || (!$user->rights->societe->client->voir && !$socid)) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; if ($search_sale > 0 || (!$user->rights->societe->client->voir && !$socid)) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
if ($search_user > 0) if ($search_user > 0)
@@ -462,7 +463,7 @@ if ($search_user > 0)
$sql .= ", ".MAIN_DB_PREFIX."element_contact as ec"; $sql .= ", ".MAIN_DB_PREFIX."element_contact as ec";
$sql .= ", ".MAIN_DB_PREFIX."c_type_contact as tc"; $sql .= ", ".MAIN_DB_PREFIX."c_type_contact as tc";
} }
$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'user AS u ON f.fk_user_author = u.rowid';
$sql .= ' WHERE f.fk_soc = s.rowid'; $sql .= ' WHERE f.fk_soc = s.rowid';
$sql .= ' AND f.entity IN ('.getEntity('invoice').')'; $sql .= ' AND f.entity IN ('.getEntity('invoice').')';
if (!$user->rights->societe->client->voir && !$socid) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; if (!$user->rights->societe->client->voir && !$socid) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id;

View File

@@ -48,7 +48,7 @@ function emailing_prepare_head(Mailing $object)
$h++; $h++;
} }
if (empty($conf->global->EMAILING_USE_ADVANCED_SELECTOR)) if (!empty($conf->global->EMAILING_USE_ADVANCED_SELECTOR))
{ {
$head[$h][0] = DOL_URL_ROOT."/comm/mailing/advtargetemailing.php?id=".$object->id; $head[$h][0] = DOL_URL_ROOT."/comm/mailing/advtargetemailing.php?id=".$object->id;
$head[$h][1] = $langs->trans("MailAdvTargetRecipients"); $head[$h][1] = $langs->trans("MailAdvTargetRecipients");

View File

@@ -15,6 +15,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) {
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
}
print '<script type="text/javascript" language="javascript"> print '<script type="text/javascript" language="javascript">
$(document).ready(function() { $(document).ready(function() {
@@ -135,7 +139,7 @@ print '</td></tr>'."\n";
// Customer Country // Customer Country
print '<tr><td>'.$langs->trans("Country"); print '<tr><td>'.$langs->trans("Country");
if (count($array_query['cust_country']) > 0) { if (!empty($array_query['cust_country'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'."\n"; print '</td><td>'."\n";
@@ -145,7 +149,7 @@ print '</td></tr>'."\n";
// State Customer // State Customer
print '<tr><td>'.$langs->trans('Status').' '.$langs->trans('ThirdParty'); print '<tr><td>'.$langs->trans('Status').' '.$langs->trans('ThirdParty');
if (count($array_query['cust_status']) > 0) { if (!empty($array_query['cust_status'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'; print '</td><td>';
@@ -173,7 +177,7 @@ print '</td></tr>'."\n";
// Prospect/Customer // Prospect/Customer
$selected = $array_query['cust_typecust']; $selected = $array_query['cust_typecust'];
print '<tr><td>'.$langs->trans('ProspectCustomer').' '.$langs->trans('ThirdParty'); print '<tr><td>'.$langs->trans('ProspectCustomer').' '.$langs->trans('ThirdParty');
if (count($array_query['cust_typecust']) > 0) { if (!empty($array_query['cust_typecust'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'; print '</td><td>';
@@ -189,7 +193,7 @@ print '</td></tr>'."\n";
// Prospection status // Prospection status
print '<tr><td>'.$langs->trans('ProspectLevel'); print '<tr><td>'.$langs->trans('ProspectLevel');
if (count($array_query['cust_prospect_status']) > 0) { if (!empty($array_query['cust_prospect_status'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'; print '</td><td>';
@@ -199,7 +203,7 @@ print '</td></tr>'."\n";
// Prospection comm status // Prospection comm status
print '<tr><td>'.$langs->trans('StatusProsp'); print '<tr><td>'.$langs->trans('StatusProsp');
if (count($array_query['cust_comm_status']) > 0) { if (!empty($array_query['cust_comm_status'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'; print '</td><td>';
@@ -209,7 +213,7 @@ print '</td></tr>'."\n";
// Customer Type // Customer Type
print '<tr><td>'.$langs->trans("ThirdPartyType"); print '<tr><td>'.$langs->trans("ThirdPartyType");
if (count($array_query['cust_typeent']) > 0) { if (!empty($array_query['cust_typeent'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'."\n"; print '</td><td>'."\n";
@@ -219,7 +223,7 @@ print '</td></tr>'."\n";
// Staff number // Staff number
print '<td>'.$langs->trans("Staff"); print '<td>'.$langs->trans("Staff");
if (count($array_query['cust_effectif_id']) > 0) { if (!empty($array_query['cust_effectif_id'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'; print '</td><td>';
@@ -229,7 +233,7 @@ print '</td></tr>'."\n";
// Sales manager // Sales manager
print '<tr><td>'.$langs->trans("SalesRepresentatives"); print '<tr><td>'.$langs->trans("SalesRepresentatives");
if (count($array_query['cust_saleman']) > 0) { if (!empty($array_query['cust_saleman'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'."\n"; print '</td><td>'."\n";
@@ -240,7 +244,7 @@ print '</td></tr>'."\n";
// Customer Default Langauge // Customer Default Langauge
if (!empty($conf->global->MAIN_MULTILANGS)) { if (!empty($conf->global->MAIN_MULTILANGS)) {
print '<tr><td>'.$langs->trans("DefaultLang"); print '<tr><td>'.$langs->trans("DefaultLang");
if (count($array_query['cust_language']) > 0) { if (!empty($array_query['cust_language'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'."\n"; print '</td><td>'."\n";
@@ -252,11 +256,12 @@ if (!empty($conf->global->MAIN_MULTILANGS)) {
if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) {
// Customer Categories // Customer Categories
print '<tr><td>'.$langs->trans("CustomersCategoryShort"); print '<tr><td>'.$langs->trans("CustomersCategoryShort");
if (count($array_query['cust_categ']) > 0) { if (!empty($array_query['cust_categ'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'."\n"; print '</td><td>'."\n";
print $formadvtargetemaling->multiselectCustomerCategories('cust_categ', $array_query['cust_categ']); $cate_arbo = $form->select_all_categories(Categorie::TYPE_CUSTOMER, null, 'parent', null, null, 1);
print $form->multiselectarray('cust_categ', $cate_arbo, GETPOST('cust_categ', 'array'), null, null, null, null, "90%");
print '</td><td>'."\n"; print '</td><td>'."\n";
print '</td></tr>'."\n"; print '</td></tr>'."\n";
} }
@@ -346,7 +351,7 @@ if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) {
// State Contact // State Contact
print '<tr><td>'.$langs->trans('Status').' '.$langs->trans('Contact'); print '<tr><td>'.$langs->trans('Status').' '.$langs->trans('Contact');
if (count($array_query['contact_status']) > 0) { if (!empty($array_query['contact_status'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'; print '</td><td>';
@@ -364,7 +369,7 @@ print '</td></tr>'."\n";
// Civility // Civility
print '<tr><td width="15%">'.$langs->trans("UserTitle"); print '<tr><td width="15%">'.$langs->trans("UserTitle");
if (count($array_query['contact_civility']) > 0) { if (!empty($array_query['contact_civility'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'; print '</td><td>';
@@ -389,7 +394,7 @@ print '</td></tr>'."\n";
// Contact Country // Contact Country
print '<tr><td>'.$langs->trans('Contact').' '.$langs->trans("Country"); print '<tr><td>'.$langs->trans('Contact').' '.$langs->trans("Country");
if (count($array_query['contact_country']) > 0) { if (!empty($array_query['contact_country'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'."\n"; print '</td><td>'."\n";
@@ -448,11 +453,12 @@ print '</td></tr>'."\n";
if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) {
// Customer Categories // Customer Categories
print '<tr><td>'.$langs->trans("ContactCategoriesShort"); print '<tr><td>'.$langs->trans("ContactCategoriesShort");
if (count($array_query['contact_categ']) > 0) { if (!empty($array_query['contact_categ'])) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'."\n"; print '</td><td>'."\n";
print $formadvtargetemaling->multiselectContactCategories('contact_categ', $array_query['contact_categ']); $cate_arbo = $form->select_all_categories(Categorie::TYPE_CONTACT, null, 'parent', null, null, 1);
print $form->multiselectarray('contact_categ', $cate_arbo, GETPOST('contact_categ', 'array'), null, null, null, null, "90%");
print '</td><td>'."\n"; print '</td><td>'."\n";
print '</td></tr>'."\n"; print '</td></tr>'."\n";
} }
@@ -465,62 +471,66 @@ if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) {
dol_include_once('/core/class/extrafields.class.php'); dol_include_once('/core/class/extrafields.class.php');
$extrafields = new ExtraFields($db); $extrafields = new ExtraFields($db);
$extrafields->fetch_name_optionals_label($elementype); $extrafields->fetch_name_optionals_label($elementype);
foreach ($extrafields->attributes[$elementtype]['type'] as $key=>&$value) { if (!empty($extrafields->attributes[$elementtype]['type'])) {
if ($value == 'radio')$value = 'select'; foreach ($extrafields->attributes[$elementtype]['type'] as $key => &$value) {
if ($value == 'radio')
$value = 'select';
} }
}
if (!empty($extrafields->attributes[$elementtype]['label'])) {
foreach ($extrafields->attributes[$elementtype]['label'] as $key => $val) { foreach ($extrafields->attributes[$elementtype]['label'] as $key => $val) {
print '<tr><td>'.$extrafields->attributes[$elementtype]['label'][$key]; print '<tr><td>' . $extrafields->attributes[$elementtype]['label'][$key];
if ($array_query['options_'.$key.'_cnct'] != '' || (is_array($array_query['options_'.$key.'_cnct']) && count($array_query['options_'.$key.'_cnct']) > 0)) { if ($array_query['options_' . $key . '_cnct'] != '' || (is_array($array_query['options_' . $key . '_cnct']) && count($array_query['options_' . $key . '_cnct']) > 0)) {
print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing'); print img_picto($langs->trans('AdvTgtUse'), 'ok.png@advtargetemailing');
} }
print '</td><td>'; print '</td><td>';
if (($extrafields->attributes[$elementtype]['type'][$key] == 'varchar') || ($extrafields->attributes[$elementtype]['type'][$key] == 'text')) { if (($extrafields->attributes[$elementtype]['type'][$key] == 'varchar') || ($extrafields->attributes[$elementtype]['type'][$key] == 'text')) {
print '<input type="text" name="options_'.$key.'_cnct"/></td><td>'."\n"; print '<input type="text" name="options_' . $key . '_cnct"/></td><td>' . "\n";
print $form->textwithpicto('', $langs->trans("AdvTgtSearchTextHelp"), 1, 'help'); print $form->textwithpicto('', $langs->trans("AdvTgtSearchTextHelp"), 1, 'help');
} elseif (($extrafields->attributes[$elementtype]['type'][$key] == 'int') || ($extrafields->attributes[$elementtype]['type'][$key] == 'double')) { } elseif (($extrafields->attributes[$elementtype]['type'][$key] == 'int') || ($extrafields->attributes[$elementtype]['type'][$key] == 'double')) {
print $langs->trans("AdvTgtMinVal").'<input type="text" name="options_'.$key.'_min_cnct"/>'; print $langs->trans("AdvTgtMinVal") . '<input type="text" name="options_' . $key . '_min_cnct"/>';
print $langs->trans("AdvTgtMaxVal").'<input type="text" name="options_'.$key.'_max_cnct"/>'; print $langs->trans("AdvTgtMaxVal") . '<input type="text" name="options_' . $key . '_max_cnct"/>';
print '</td><td>'."\n"; print '</td><td>' . "\n";
print $form->textwithpicto('', $langs->trans("AdvTgtSearchIntHelp"), 1, 'help'); print $form->textwithpicto('', $langs->trans("AdvTgtSearchIntHelp"), 1, 'help');
} elseif (($extrafields->attributes[$elementtype]['type'][$key] == 'date') || ($extrafields->attributes[$elementtype]['type'][$key] == 'datetime')) { } elseif (($extrafields->attributes[$elementtype]['type'][$key] == 'date') || ($extrafields->attributes[$elementtype]['type'][$key] == 'datetime')) {
print '<table class="nobordernopadding"><tr>'; print '<table class="nobordernopadding"><tr>';
print '<td>'.$langs->trans("AdvTgtStartDt").'</td><td>'; print '<td>' . $langs->trans("AdvTgtStartDt") . '</td><td>';
print $form->selectDate('', 'options_'.$key.'_st_dt_cnct'); print $form->selectDate('', 'options_' . $key . '_st_dt_cnct');
print '</td><td>'.$langs->trans("AdvTgtEndDt").'</td><td>'; print '</td><td>' . $langs->trans("AdvTgtEndDt") . '</td><td>';
print $form->selectDate('', 'options_'.$key.'_end_dt_cnct'); print $form->selectDate('', 'options_' . $key . '_end_dt_cnct');
print '</td></tr></table>'; print '</td></tr></table>';
print '</td><td>'."\n"; print '</td><td>' . "\n";
print $form->textwithpicto('', $langs->trans("AdvTgtSearchDtHelp"), 1, 'help'); print $form->textwithpicto('', $langs->trans("AdvTgtSearchDtHelp"), 1, 'help');
} elseif (($extrafields->attributes[$elementtype]['type'][$key] == 'boolean')) { } elseif (($extrafields->attributes[$elementtype]['type'][$key] == 'boolean')) {
print $form->selectarray( print $form->selectarray(
'options_'.$key.'_cnct', 'options_' . $key . '_cnct',
array( array(
'' => '', '' => '',
'1' => $langs->trans('Yes'), '1' => $langs->trans('Yes'),
'0' => $langs->trans('No') '0' => $langs->trans('No')
), ),
$array_query['options_'.$key.'_cnct'] $array_query['options_' . $key . '_cnct']
); );
print '</td><td>'."\n"; print '</td><td>' . "\n";
} elseif (($extrafields->attributes[$elementtype]['type'][$key] == 'select')) { } elseif (($extrafields->attributes[$elementtype]['type'][$key] == 'select')) {
print $formadvtargetemaling->advMultiselectarray('options_'.$key.'_cnct', $extrafields->attributes[$key]['param']['options'], $array_query['options_'.$key.'_cnct']); print $formadvtargetemaling->advMultiselectarray('options_' . $key . '_cnct', $extrafields->attributes[$key]['param']['options'], $array_query['options_' . $key . '_cnct']);
print '</td><td>'."\n"; print '</td><td>' . "\n";
} elseif (($extrafields->attributes[$elementtype]['type'][$key] == 'sellist')) { } elseif (($extrafields->attributes[$elementtype]['type'][$key] == 'sellist')) {
print $formadvtargetemaling->advMultiselectarraySelllist('options_'.$key.'_cnct', $extrafields->attributes[$key]['param']['options'], $array_query['options_'.$key.'_cnct']); print $formadvtargetemaling->advMultiselectarraySelllist('options_' . $key . '_cnct', $extrafields->attributes[$key]['param']['options'], $array_query['options_' . $key . '_cnct']);
print '</td><td>'."\n"; print '</td><td>' . "\n";
} else { } else {
print '<table class="nobordernopadding"><tr>'; print '<table class="nobordernopadding"><tr>';
print '<td></td><td>'; print '<td></td><td>';
if (is_array($array_query['options_'.$key.'_cnct'])) { if (is_array($array_query['options_' . $key . '_cnct'])) {
print $extrafields->showInputField($key, implode(',', $array_query['options_'.$key.'_cnct']), '', '_cnct'); print $extrafields->showInputField($key, implode(',', $array_query['options_' . $key . '_cnct']), '', '_cnct');
} else { } else {
print $extrafields->showInputField($key, $array_query['options_'.$key.'_cnct'], '', '_cnct'); print $extrafields->showInputField($key, $array_query['options_' . $key . '_cnct'], '', '_cnct');
} }
print '</td></tr></table>'; print '</td></tr></table>';
print '</td><td>'."\n"; print '</td><td>' . "\n";
}
print '</td></tr>' . "\n";
} }
print '</td></tr>'."\n";
} }
} }
print '<tr>'."\n"; print '<tr>'."\n";