From a1726fc994bc2b21dafcd21be3fa31f5f7ca4a2d Mon Sep 17 00:00:00 2001 From: Ere Maijala Date: Sat, 1 Dec 2018 20:22:46 +0200 Subject: [PATCH 001/154] Print VAT summary only if there are invoice rows. --- invoice_printer_base.php | 1 + 1 file changed, 1 insertion(+) diff --git a/invoice_printer_base.php b/invoice_printer_base.php index e0640735..138e87e1 100644 --- a/invoice_printer_base.php +++ b/invoice_printer_base.php @@ -1222,6 +1222,7 @@ protected function printSummary() // VAT Breakdown if ($this->senderData['vat_registered'] && getSetting('invoice_show_vat_breakdown') + && $this->groupedVATs ) { $pdf->SetFont('Helvetica', '', 9); $pdf->SetXY($this->left, $startY + 5); From c547a78e52246e8aad66308a146c19fb952badde Mon Sep 17 00:00:00 2001 From: Ere Maijala Date: Sat, 1 Dec 2018 20:23:04 +0200 Subject: [PATCH 002/154] Fix printing of header and footer. --- invoice_printer_base.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/invoice_printer_base.php b/invoice_printer_base.php index 138e87e1..86015e81 100644 --- a/invoice_printer_base.php +++ b/invoice_printer_base.php @@ -2704,13 +2704,13 @@ protected function getRecipientAddress() protected function getPdfData() { $pdf = $this->pdf; - $pdf->printHeader(false); - $pdf->printFooter(false); foreach ($this->attachments as $attachment) { $attachment = getInvoiceAttachment($attachment['id']); if ('application/pdf' !== $attachment['mimetype']) { // Import image $pdf->AddPage(); + $pdf->printHeader(false); + $pdf->printFooter(false); $pdf->Image( '@' . $attachment['filedata'], $this->left, From 279517a057450430140c6fb2ccee371845772f08 Mon Sep 17 00:00:00 2001 From: Ere Maijala Date: Sat, 1 Dec 2018 20:23:28 +0200 Subject: [PATCH 003/154] Fix a translation typo. --- lang/en-US.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/en-US.ini b/lang/en-US.ini index f3e72ea7..de47a56e 100644 --- a/lang/en-US.ini +++ b/lang/en-US.ini @@ -81,7 +81,7 @@ LoginName = 'User ID' Password = 'Password' Type = 'User Type' Bank = 'Bank' -Account = 'Accout' +Account = 'Account' AccountIBAN = 'IBAN' SWIFTBIC = 'SWIFT/BIC' FirstBank = '1st Bank Account' From d1a30a64f7fb1bc0deaaed2f0ce1ff0b95c95289 Mon Sep 17 00:00:00 2001 From: Ere Maijala Date: Sat, 1 Dec 2018 20:23:38 +0200 Subject: [PATCH 004/154] Add support for printing multiple to a PDF from invoice and offer lists. --- css/style.css | 4 +- form_funcs.php | 194 ++++++++++++------------------ invoice.php | 74 +++++++++--- invoice_printer_base.php | 36 ++++-- invoice_printer_blank.php | 10 +- invoice_printer_finvoice.php | 6 +- invoice_printer_finvoice_soap.php | 6 +- js/mlinvoice.js | 17 ++- list.php | 49 +++++++- open_invoices.php | 6 +- sqlfuncs.php | 75 ++++++++++++ 11 files changed, 308 insertions(+), 169 deletions(-) diff --git a/css/style.css b/css/style.css index 3d1fc921..1b56984f 100755 --- a/css/style.css +++ b/css/style.css @@ -220,10 +220,10 @@ td.button { vertical-align: top; } -td.button .dropdownmenu.ui-widget-content, .send-buttons .dropdownmenu.ui-widget-content { +td.button .dropdownmenu.ui-widget-content, .send-buttons .dropdownmenu.ui-widget-content, .selection-buttons .dropdownmenu.ui-widget-content { border: 0 } -.send-buttons .dropdownmenu { +.send-buttons .dropdownmenu, .selection-buttons .dropdownmenu { display: inline-block; } diff --git a/form_funcs.php b/form_funcs.php index 1ab6c295..75c9e7c1 100644 --- a/form_funcs.php +++ b/form_funcs.php @@ -317,93 +317,95 @@ function saveFormData($table, &$primaryKey, &$formElements, &$values, &$warnings return $missingValues; } - $strFields = implode(', ', $fields); - $strInsert = implode(', ', $insert); - $strUpdateFields = implode(', ', $updateFields); - - dbQueryCheck('SET AUTOCOMMIT = 0'); - dbQueryCheck('BEGIN'); - try { - // Special case for invoice rows - update product stock balance - if (isset($values['invoice_id'])) { - $invoiceId = $values['invoice_id']; - } elseif ($table == '{prefix}invoice_row') { - $rows = dbParamQuery( - 'SELECT invoice_id FROM {prefix}invoice_row WHERE id=?', - [$primaryKey] - ); - $invoiceId = isset($rows[0]['invoice_id']) - ? $rows[0]['invoice_id'] : null; - } - if ($table == '{prefix}invoice_row' && !isOffer($invoiceId)) { - updateProductStockBalance( - isset($primaryKey) ? $primaryKey : null, - isset($values['product_id']) ? $values['product_id'] : null, - $values['pcs'] - ); - } - - if (!isset($primaryKey) || !$primaryKey) { - if ($parentKeyName) { - $strFields .= ", $parentKeyName"; - $strInsert .= ', ?'; - $arrValues[] = $parentKey; - } - $strQuery = "INSERT INTO $table ($strFields) VALUES ($strInsert)"; - dbParamQuery($strQuery, $arrValues, 'exception'); - $primaryKey = mysqli_insert_id($dblink); - } else { - // Special case for invoice - update product stock balance for all - // invoice rows if the invoice was previously deleted - if ($table == '{prefix}invoice' && !isOffer($primaryKey)) { - $checkValues = dbParamQuery( - 'SELECT deleted FROM {prefix}invoice WHERE id=?', + if ($fields) { + $strFields = implode(', ', $fields); + $strInsert = implode(', ', $insert); + $strUpdateFields = implode(', ', $updateFields); + + dbQueryCheck('SET AUTOCOMMIT = 0'); + dbQueryCheck('BEGIN'); + try { + // Special case for invoice rows - update product stock balance + if (isset($values['invoice_id'])) { + $invoiceId = $values['invoice_id']; + } elseif ($table == '{prefix}invoice_row') { + $rows = dbParamQuery( + 'SELECT invoice_id FROM {prefix}invoice_row WHERE id=?', [$primaryKey] ); - if ($checkValues[0]['deleted']) { - $rows = dbParamQuery( - 'SELECT product_id, pcs FROM {prefix}invoice_row WHERE invoice_id=? AND deleted=0', + $invoiceId = isset($rows[0]['invoice_id']) + ? $rows[0]['invoice_id'] : null; + } + if ($table == '{prefix}invoice_row' && !isOffer($invoiceId)) { + updateProductStockBalance( + isset($primaryKey) ? $primaryKey : null, + isset($values['product_id']) ? $values['product_id'] : null, + $values['pcs'] + ); + } + + if (!isset($primaryKey) || !$primaryKey) { + if ($parentKeyName) { + $strFields .= ", $parentKeyName"; + $strInsert .= ', ?'; + $arrValues[] = $parentKey; + } + $strQuery = "INSERT INTO $table ($strFields) VALUES ($strInsert)"; + dbParamQuery($strQuery, $arrValues, 'exception'); + $primaryKey = mysqli_insert_id($dblink); + } else { + // Special case for invoice - update product stock balance for all + // invoice rows if the invoice was previously deleted + if ($table == '{prefix}invoice' && !isOffer($primaryKey)) { + $checkValues = dbParamQuery( + 'SELECT deleted FROM {prefix}invoice WHERE id=?', [$primaryKey] ); - foreach ($rows as $row) { - updateProductStockBalance( - null, $row['product_id'], $row['pcs'] + if ($checkValues[0]['deleted']) { + $rows = dbParamQuery( + 'SELECT product_id, pcs FROM {prefix}invoice_row WHERE invoice_id=? AND deleted=0', + [$primaryKey] ); + foreach ($rows as $row) { + updateProductStockBalance( + null, $row['product_id'], $row['pcs'] + ); + } } } - } - if ('{prefix}send_api_config' === $table - || '{prefix}attachment' === $table - || '{prefix}invoice_attachment' === $table - ) { - $strQuery = "UPDATE $table SET $strUpdateFields WHERE id=?"; - } else { - $strQuery = "UPDATE $table SET $strUpdateFields, deleted=0 WHERE id=?"; + if ('{prefix}send_api_config' === $table + || '{prefix}attachment' === $table + || '{prefix}invoice_attachment' === $table + ) { + $strQuery = "UPDATE $table SET $strUpdateFields WHERE id=?"; + } else { + $strQuery = "UPDATE $table SET $strUpdateFields, deleted=0 WHERE id=?"; + } + $arrValues[] = $primaryKey; + dbParamQuery($strQuery, $arrValues, 'exception'); } - $arrValues[] = $primaryKey; - dbParamQuery($strQuery, $arrValues, 'exception'); - } - if ($table === '{prefix}company') { - saveTags( - 'company', - $primaryKey, - !empty($values['tags']) ? $values['tags'] : '' - ); - } elseif ($table === '{prefix}company_contact') { - saveTags( - 'contact', - $primaryKey, - !empty($values['tags']) ? $values['tags'] : '' - ); + if ($table === '{prefix}company') { + saveTags( + 'company', + $primaryKey, + !empty($values['tags']) ? $values['tags'] : '' + ); + } elseif ($table === '{prefix}company_contact') { + saveTags( + 'contact', + $primaryKey, + !empty($values['tags']) ? $values['tags'] : '' + ); + } + } catch (Exception $e) { + dbQueryCheck('ROLLBACK'); + dbQueryCheck('SET AUTOCOMMIT = 1'); + die($e->getMessage()); } - } catch (Exception $e) { - dbQueryCheck('ROLLBACK'); + dbQueryCheck('COMMIT'); dbQueryCheck('SET AUTOCOMMIT = 1'); - die($e->getMessage()); } - dbQueryCheck('COMMIT'); - dbQueryCheck('SET AUTOCOMMIT = 1'); // Special case for invoices - check for duplicate invoice numbers if ($table == '{prefix}invoice' && isset($values['invoice_no']) @@ -430,46 +432,8 @@ function saveFormData($table, &$primaryKey, &$formElements, &$values, &$warnings // Special case for invoices - check, according to settings, that the invoice has // an invoice number and a reference number - if ($table == '{prefix}invoice' && $onPrint && !isOffer($primaryKey) - && (getSetting('invoice_add_number') - || getSetting('invoice_add_reference_number')) - ) { - dbQueryCheck( - 'LOCK TABLES {prefix}invoice WRITE, {prefix}settings READ' - . ', {prefix}company READ' - ); - $rows = dbParamQuery( - 'SELECT invoice_no, ref_number, base_id, company_id, invoice_date,' - . "interval_type FROM $table WHERE id=?", - [$primaryKey] - ); - $data = isset($rows[0]) ? $rows[0] : null; - $needInvNo = getSetting('invoice_add_number'); - $needRefNo = getSetting('invoice_add_reference_number'); - if (($needInvNo && empty($data['invoice_no'])) - || ($needRefNo && empty($data['ref_number'])) - ) { - $defaults = getInvoiceDefaults( - $primaryKey, $data['base_id'], $data['company_id'], - dateConvDBDate2Date($data['invoice_date']), $data['interval_type'], - $data['invoice_no'] - ); - $sql = "UPDATE {prefix}invoice SET"; - $updateStrings = []; - $params = []; - if ($needInvNo && empty($data['invoice_no'])) { - $updateStrings[] = 'invoice_no=?'; - $params[] = $defaults['invoice_no']; - } - if ($needRefNo && empty($data['ref_number'])) { - $updateStrings[] = 'ref_number=?'; - $params[] = $defaults['ref_no']; - } - $sql .= ' ' . implode(', ', $updateStrings) . ' WHERE id=?'; - $params[] = $primaryKey; - dbParamQuery($sql, $params); - } - dbQueryCheck('UNLOCK TABLES'); + if ($table == '{prefix}invoice' && $onPrint && !isOffer($primaryKey)) { + verifyInvoiceDataForPrinting($primaryKey); } return true; diff --git a/invoice.php b/invoice.php index bf3a80b5..70debb0a 100755 --- a/invoice.php +++ b/invoice.php @@ -116,19 +116,63 @@ $printParameters[1] = $language; } -$printer = getInvoicePrinter($printTemplateFile); -$printer->init( - $intInvoiceId, $printParameters, $printOutputFileName, - $dateOverride, $printTemplate, $authenticated -); -$printer->printInvoice(); - -if ($authenticated && sesWriteAccess()) { - dbParamQuery( - 'UPDATE {prefix}invoice SET print_date=? where id=?', - [ - date('Ymd'), - $intInvoiceId - ] +if ($authenticated && is_array($intInvoiceId)) { + + if (!sesWriteAccess()) { + die('Write access required for printing multiple'); + } + + include_once 'pdf.php'; + $mainPdf = new PDF('P', 'mm', 'A4', _CHARSET_ == 'UTF-8', _CHARSET_, false); + foreach ($intInvoiceId as $singleId) { + $printer = getInvoicePrinter($printTemplateFile); + $uses = class_uses($printer); + if (in_array('InvoicePrinterEmailTrait', $uses) + || $printer instanceof InvoicePrinterXSLT + || $printer instanceof InvoicePrinterBlank + ) { + die('Cannot print multiple with the given print template'); + } + + verifyInvoiceDataForPrinting($singleId); + + $printer->init( + $singleId, $printParameters, $printOutputFileName, + $dateOverride, $printTemplate, $authenticated + ); + + $pdfResult = $printer->createPrintout(); + + // Import PDF + $pageCount = $mainPdf->setSourceFile( + \setasign\Fpdi\PdfParser\StreamReader::createByString($pdfResult['data']) + ); + for ($i = 1; $i <= $pageCount; $i++) { + $tplx = $mainPdf->importPage($i); + $size = $mainPdf->getTemplateSize($tplx); + $mainPdf->AddPage('P', array($size['width'], $size['height'])); + $mainPdf->useTemplate($tplx); + } + + if ($authenticated && sesWriteAccess()) { + updateInvoicePrintDate($singleId); + } + } + $filename = Translator::Translate('File') . '_' . date('Y-m-d_H:i:s') . '.pdf'; + $pdfResult['headers']['Content-Disposition'] = 'inline; filename="' . $filename . '"'; + foreach ($pdfResult['headers'] as $header => $value) { + header("$header: $value"); + } + echo $mainPdf->Output('', 'S'); +} else { + $printer = getInvoicePrinter($printTemplateFile); + $printer->init( + $intInvoiceId, $printParameters, $printOutputFileName, + $dateOverride, $printTemplate, $authenticated ); -} + $printer->printInvoice(); + + if ($authenticated && sesWriteAccess()) { + updateInvoicePrintDate($intInvoiceId); + } +} \ No newline at end of file diff --git a/invoice_printer_base.php b/invoice_printer_base.php index 86015e81..a2be6472 100644 --- a/invoice_printer_base.php +++ b/invoice_printer_base.php @@ -639,8 +639,8 @@ public function printInvoice() } $result = $this->createPrintout(); - foreach ($result['headers'] as $header) { - header($header); + foreach ($result['headers'] as $header => $value) { + header("$header: $value"); } echo $result['data']; } @@ -714,16 +714,8 @@ public function createPrintout() $this->printSummary(); } - $filename = basename($this->getPrintOutFileName()); return [ - 'headers' => [ - 'Content-Type: application/pdf', - 'Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1', - 'Pragma: public', - 'Expires: Mon, 26 Jul 1997 05:00:00 GMT', - 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT', - 'Content-Disposition: inline; filename="' . $filename . '"' - ], + 'headers' => $this->getHttpHeaders(), 'data' => $this->getPdfData() ]; } @@ -2743,11 +2735,31 @@ protected function getPdfData() for ($i = 1; $i <= $pageCount; $i++) { $tplx = $pdf->importPage($i); $size = $pdf->getTemplateSize($tplx); - $pdf->AddPage('P', array($size['w'], $size['h'])); + $pdf->AddPage('P', [$size['width'], $size['height']]); + $pdf->printHeader(false); + $pdf->printFooter(false); $pdf->useTemplate($tplx); } } return $pdf->Output('', 'S'); } + + /** + * Get HTTP headers for printout + * + * @return array + */ + protected function getHttpHeaders() + { + $filename = basename($this->getPrintOutFileName()); + return [ + 'Content-Type' => 'application/pdf', + 'Cache-Control' => 'private, must-revalidate, post-check=0, pre-check=0, max-age=1', + 'Pragma' => 'public', + 'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT', + 'Last-Modified' => gmdate('D, d M Y H:i:s') . ' GMT', + 'Content-Disposition' => 'inline; filename="' . $filename . '"' + ]; + } } diff --git a/invoice_printer_blank.php b/invoice_printer_blank.php index a2e7bcdc..06c303e5 100644 --- a/invoice_printer_blank.php +++ b/invoice_printer_blank.php @@ -56,16 +56,8 @@ public function createPrintout() $this->printSeparatorLine(); $this->printForeword(); - $filename = basename($this->getPrintOutFileName()); return [ - 'headers' => [ - 'Content-Type: application/pdf', - 'Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1', - 'Pragma: public', - 'Expires: Mon, 26 Jul 1997 05:00:00 GMT', - 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT', - 'Content-Disposition: inline; filename="' . $filename . '"' - ], + 'headers' => $this->getHttpHeaders(), 'data' => $this->pdf->Output('', 'S') ]; } diff --git a/invoice_printer_finvoice.php b/invoice_printer_finvoice.php index e85e63d6..13f8d7d8 100644 --- a/invoice_printer_finvoice.php +++ b/invoice_printer_finvoice.php @@ -50,13 +50,13 @@ public function createPrintout() $this->xsltParams['printTransmissionDetails'] = false; parent::transform('create_finvoice.xsl', 'Finvoice.xsd'); $headers = [ - 'Content-Type: text/xml; charset=ISO-8859-15' + 'Content-Type' => 'text/xml; charset=ISO-8859-15' ]; $filename = $this->getPrintoutFileName(); if ($this->printStyle) { - $headers[] = "Content-Disposition: inline; filename=$filename"; + $headers['Content-Disposition'] = "inline; filename=$filename"; } else { - $headers[] = "Content-Disposition: attachment; filename=$filename"; + $headers['Content-Disposition'] = "attachment; filename=$filename"; } return [ 'headers' => $headers, diff --git a/invoice_printer_finvoice_soap.php b/invoice_printer_finvoice_soap.php index b23dfb7b..69d52efd 100644 --- a/invoice_printer_finvoice_soap.php +++ b/invoice_printer_finvoice_soap.php @@ -56,13 +56,13 @@ public function createPrintout() parent::transform('create_finvoice_soap_envelope.xsl'); $headers = [ - 'Content-Type: text/xml; charset=ISO-8859-15' + 'Content-Type' => 'text/xml; charset=ISO-8859-15' ]; $filename = $this->getPrintoutFileName(); if ($this->printStyle) { - $headers[] = "Content-Disposition: inline; filename=$filename"; + $headers['Content-Disposition'] = "inline; filename=$filename"; } else { - $headers[] = "Content-Disposition: attachment; filename=$filename"; + $headers['Content-Disposition'] = "attachment; filename=$filename"; } return [ 'headers' => $headers, diff --git a/js/mlinvoice.js b/js/mlinvoice.js index 6ab9368f..2aef2487 100644 --- a/js/mlinvoice.js +++ b/js/mlinvoice.js @@ -1312,7 +1312,7 @@ var MLInvoice = (function MLInvoice() { }); } - function _setupMultiEdit() { + function _setupListMultiSelect() { $('a.actionlink.update-selected-rows').click(function editSelectedClick() { var list = $(this).data('list'); var ids = $(this).closest('.list_container').find('.cb-select-row:checked').map(function mapChecked() { @@ -1321,6 +1321,19 @@ var MLInvoice = (function MLInvoice() { window.location.href = '?func=multiedit&list=' + encodeURIComponent(list) + '&' + ids.join('&'); return false; }); + + $('.print-selected-rows .print-selected-item').click(function printSelectedClick() { + var ids = $(this).closest('.list_container').find('.cb-select-row:checked').map(function mapChecked() { + return 'id[]=' + encodeURIComponent(this.value); + }).get(); + var target = 'invoice.php?template=' + encodeURIComponent($(this).data('templateId')) + '&' + ids.join('&'); + if ($(this).data('style') === 'openwindow') { + window.open(target); + } else { + window.location.href = target; + } + return false; + }); } function init() { @@ -1337,7 +1350,7 @@ var MLInvoice = (function MLInvoice() { _initFormButtons(); updateSendApiButtons(); _setupInvoiceAttachments(); - _setupMultiEdit(); + _setupListMultiSelect(); } return { diff --git a/list.php b/list.php index 7c187329..3e26d203 100755 --- a/list.php +++ b/list.php @@ -43,13 +43,14 @@ * @param string $prefilter Prefilter * @param bool $invoiceTotal Whether to display invoice total * @param bool $highlightOverdue Whether to highlight overdue rows + * @param string $printType Print template type for printing multiple * * @return void */ function createList($strFunc, $strList, $strTableName = '', $strTitleOverride = '', - $prefilter = '', $invoiceTotal = false, $highlightOverdue = false + $prefilter = '', $invoiceTotal = false, $highlightOverdue = false, + $printType = '' ) { - $strWhereClause = $prefilter ? $prefilter : getRequest('where', ''); include 'list_switch.php'; @@ -62,6 +63,29 @@ function createList($strFunc, $strList, $strTableName = '', $strTitleOverride = return; } + $printTemplates = []; + if ($printType) { + $templateCandidates = dbParamQuery( + 'SELECT * FROM {prefix}print_template WHERE deleted=0 and type=? and inactive=0 ORDER BY order_no', + [$printType] + ); + $templates = []; + foreach ($templateCandidates as $candidate) { + $printer = getInvoicePrinter($candidate['filename']); + if (null === $printer) { + continue; + } + $uses = class_uses($printer); + if (in_array('InvoicePrinterEmailTrait', $uses) + || $printer instanceof InvoicePrinterXSLT + || $printer instanceof InvoicePrinterBlank + ) { + continue; + } + $printTemplates[] = $candidate; + } + } + if ($strListFilter) { if ($strWhereClause) { // Special case: don't apply archived filter for invoices if search terms @@ -79,7 +103,7 @@ function createList($strFunc, $strList, $strTableName = '', $strTitleOverride = if (!$strTableName) { $strTableName = "list_$strList"; } - $strTableName .= '_v2'; + $strTableName .= '_2'; if ($strTitleOverride) { $strTitle = $strTitleOverride; @@ -388,8 +412,23 @@ className: ''
: - - + + +
Date: Sat, 1 Dec 2018 23:06:15 +0200 Subject: [PATCH 005/154] Make setup a bit more robust and able to update the password of admin user also when the database already exists. Closes #319. --- setup.php | 64 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/setup.php b/setup.php index abb31f18..5a5ea9c9 100644 --- a/setup.php +++ b/setup.php @@ -68,15 +68,21 @@ public function initialSetup() $password = $_POST['password']; $prefix = $_POST['prefix']; $adminPassword = $_POST['adminpass']; + $adminPassword2 = $_POST['adminpass2']; $lang = $_POST['lang']; $defaultlang = $_POST['defaultlang']; $encryptionKey = $_POST['encryptionkey']; if (empty($lang)) { $formMessage = 'At least one language must be selected'; - } elseif (strlen($encryptionKey) < 32) { + } + if (strlen($encryptionKey) < 32) { $formMessage = 'Encryption key must be at least 32 characters'; - } else { + } + if ($adminPassword !== $adminPassword2) { + $formMessage = 'Password for the admin user does not match the verification'; + } + if ('' === $formMessage) { $initParams = compact( 'host', 'database', 'username', 'password', 'prefix', 'lang', 'defaultlang', 'encryptionKey' @@ -103,11 +109,9 @@ public function initialSetup() $this->errorMsg = 'Could not write to config.php'; } else { if (!$tablesExist) { - if ($this->createDatabaseTables($adminPassword)) { - $setupComplete = true; - } + $setupComplete = $this->createDatabaseTables($adminPassword); } else { - $setupComplete = true; + $setupComplete = empty($adminPassword) || $this->updateAdminPassword($adminPassword); } } } @@ -224,13 +228,19 @@ public function initialSetup()

- Please enter also a password for the 'admin' user that you can use to log in after setup is complete. + A user called 'admin' will be automatically created and can be used as the login user. + Please enter a password for 'admin' that you can use to log in after setup is complete.

-

+

+ +

@@ -453,12 +463,12 @@ protected function initDatabaseConnection($settings = []) */ protected function checkDatabaseTables($db, $prefix) { - $res = mysqli_query($db, "SHOW TABLES LIKE '" . $prefix . "_%'"); + $res = mysqli_query($db, "SHOW TABLES LIKE '" . $prefix . "_invoice'"); if (false === $res) { $this->errorMsg = mysqli_error($db); return false; } - if (mysqli_fetch_row($res)) { + if ($row = mysqli_fetch_row($res)) { return true; } return false; @@ -489,15 +499,31 @@ protected function createDatabaseTables($adminPassword = '') } if ('' !== $adminPassword) { - $res = mysqli_query( - $db, - 'UPDATE ' . _DB_PREFIX_ . "_users SET passwd = '" - . password_hash($adminPassword, PASSWORD_DEFAULT) . "' WHERE " - . "login = 'admin'" - ); - if (false === $res) { - die(mysqli_error($db)); - } + $this->updateAdminPassword($adminPassword); + } + + return true; + } + + /** + * Update password for the admin user + * + * @param string $adminPassword New password + * + * @return bool + */ + protected function updateAdminPassword($adminPassword = '') + { + include_once 'config.php'; + $db = $this->initDatabaseConnection(); + $res = mysqli_query( + $db, + 'UPDATE ' . _DB_PREFIX_ . "_users SET passwd = '" + . password_hash($adminPassword, PASSWORD_DEFAULT) . "' WHERE " + . "login = 'admin'" + ); + if (false === $res) { + die(mysqli_error($db)); } return true; From a06944a5de8ee09bd2ee1b6676aa11ef0f8cee59 Mon Sep 17 00:00:00 2001 From: Ere Maijala Date: Sun, 2 Dec 2018 18:43:30 +0200 Subject: [PATCH 006/154] Encapsulate form_switch to avoid registering so many globals. --- ext_search.php | 91 ++++++++++++++++++++++++----------------------- form.php | 93 ++++++++++++++++++++++++------------------------- form_config.php | 58 ++++++++++++++++++++++++++++++ form_funcs.php | 70 ------------------------------------- form_switch.php | 2 -- json.php | 11 +++--- multiedit.php | 7 ++-- 7 files changed, 158 insertions(+), 174 deletions(-) create mode 100644 form_config.php diff --git a/ext_search.php b/ext_search.php index 1797b48a..27598abd 100755 --- a/ext_search.php +++ b/ext_search.php @@ -31,6 +31,7 @@ require_once 'sessionfuncs.php'; require_once 'miscfuncs.php'; require_once 'datefuncs.php'; +require_once 'form_config.php'; sesVerifySession(); @@ -62,7 +63,7 @@ $astrSelectedFields = []; } -require 'form_switch.php'; +$formConfig = getFormConfig($strForm); for ($j = 0; $j < count($astrSelectedFields); $j ++) { $tmpDelete = getPost('delete_' . $astrSelectedFields[$j] . '_x', false); @@ -73,32 +74,30 @@ $strFields = implode(',', $astrSelectedFields); -for ($j = 0; $j < count($astrFormElements); $j ++) { - if ($astrFormElements[$j]['type'] == 'RESULT' - && $astrFormElements[$j]['name'] != '' - ) { - $astrFormElements[$j]['type'] = 'TEXT'; +foreach ($formConfig['fields'] as &$field) { + if ($field['type'] == 'RESULT' && $field['name'] != '') { + $field['type'] = 'TEXT'; } } $listValues = []; -for ($j = 0; $j < count($astrFormElements); $j ++) { - if ($astrFormElements[$j]['type'] != '' - && $astrFormElements[$j]['type'] != 'LABEL' - && $astrFormElements[$j]['type'] != 'HID_INT' - && $astrFormElements[$j]['type'] != 'IFORM' - && $astrFormElements[$j]['type'] != 'BUTTON' - && $astrFormElements[$j]['type'] != 'JSBUTTON' - && $astrFormElements[$j]['type'] != 'DROPDOWNMENU' - && !in_array($astrFormElements[$j]['name'], $astrSelectedFields, true) +foreach ($formConfig['fields'] as $field) { + if ($field['type'] != '' + && $field['type'] != 'LABEL' + && $field['type'] != 'HID_INT' + && $field['type'] != 'IFORM' + && $field['type'] != 'BUTTON' + && $field['type'] != 'JSBUTTON' + && $field['type'] != 'DROPDOWNMENU' + && !in_array($field['name'], $astrSelectedFields, true) ) { - $listValues[$astrFormElements[$j]['name']] = str_replace( + $listValues[$field['name']] = str_replace( '
', ' ', - Translator::translate($astrFormElements[$j]['label']) + Translator::translate($field['label']) ); } - $strControlType = $astrFormElements[$j]['type']; - $strControlName = $astrFormElements[$j]['name']; + $strControlType = $field['type']; + $strControlName = $field['name']; if ($strControlType == 'IFORM' || $strControlType == 'BUTTON') { $astrValues[$strControlName] = ''; @@ -122,9 +121,8 @@ $strOnLoad = ''; if ($blnSearch || $blnSave) { $strWhereClause = ''; - for ($j = 0; $j < count($astrFormElements); $j ++) { - $elem = $astrFormElements[$j]; - $name = $elem['name']; + foreach ($formConfig['fields'] as $field) { + $name = $field['name']; if (in_array($name, $astrSelectedFields, true)) { $strSearchOperator = getPost("operator_$name", ''); if ($strSearchOperator) { @@ -133,27 +131,28 @@ $strSearchMatch = getPost("searchmatch_$name", '='); // do LIKE || NOT LIKE search to elements with text or varchar datatype - if ($elem['type'] == 'TEXT' || $elem['type'] == 'AREA') { + if ($field['type'] == 'TEXT' || $field['type'] == 'AREA') { if ($strSearchMatch == '=') { $strSearchMatch = 'LIKE'; } else { $strSearchMatch = 'NOT LIKE'; } $strSearchValue = "'%" . addcslashes($astrValues[$name], "'\\") . "%'"; - } elseif ($astrFormElements[$j]['type'] == 'INT' - || $astrFormElements[$j]['type'] == 'LIST' - || $astrFormElements[$j]['type'] == 'SELECT' - || $astrFormElements[$j]['type'] == 'SEARCHLIST' - || $astrFormElements[$j]['type'] == 'TAGS' + } elseif ($field['type'] == 'INT' + || $field['type'] == 'LIST' + || $field['type'] == 'SELECT' + || $field['type'] == 'SEARCHLIST' + || $field['type'] == 'TAGS' ) { $strSearchValue = $astrValues[$name]; - } elseif ($astrFormElements[$j]['type'] == 'CHECK') { + } elseif ($field['type'] == 'CHECK') { $strSearchValue = $astrValues[$name] ? 1 : 0; - } elseif ($astrFormElements[$j]['type'] == 'INTDATE') { + } elseif ($field['type'] == 'INTDATE') { $strSearchValue = dateConvDate2DBDate($astrValues[$name]); } if ($strSearchValue) { - $strWhereClause .= "$strSearchOperator$strListTableAlias$name $strSearchMatch $strSearchValue"; + $tableAlias = $formConfig['tableAlias']; + $strWhereClause .= "$strSearchOperator$tableAlias$name $strSearchMatch $strSearchValue"; } } } @@ -214,22 +213,22 @@ 1) { $strSelectedOperator = getPost( - 'operator_' . $astrFormElements[$j]['name'], 'AND' + 'operator_' . $field['name'], 'AND' ); $strOperator = htmlListBox( - 'operator_' . $astrFormElements[$j]['name'], + 'operator_' . $field['name'], [ 'AND' => Translator::translate('SearchAND'), 'OR' => Translator::translate('SearchOR') @@ -246,26 +245,26 @@ ?> - + - +

@@ -84,13 +85,13 @@ function createForm($strFunc, $strList, $strForm) } if ('new' === $action) { - $readOnlyForm = false; + $formConfig['readOnly'] = false; } $redirect = getRequest('redirect', null); if (isset($redirect)) { // Redirect after save - foreach ($astrFormElements as $elem) { + foreach ($formConfig['fields'] as $elem) { if ($elem['name'] == $redirect) { if ($elem['style'] == 'redirect') { $newLocation = str_replace( @@ -105,8 +106,8 @@ function createForm($strFunc, $strList, $strForm) } } - if ('delete' === $action && $intKeyValue && !$readOnlyForm) { - deleteRecord($strTable, $intKeyValue); + if ('delete' === $action && $intKeyValue && !$formConfig['readOnly']) { + deleteRecord($formConfig['table'], $intKeyValue); unset($intKeyValue); unset($astrValues); if (getSetting('auto_close_after_delete')) { @@ -124,7 +125,7 @@ function createForm($strFunc, $strList, $strForm) } if (isset($intKeyValue) && $intKeyValue) { - $res = fetchRecord($strTable, $intKeyValue, $astrFormElements, $astrValues); + $res = fetchRecord($formConfig['table'], $intKeyValue, $formConfig['fields'], $astrValues); if ($res === 'deleted') { $strMessage .= Translator::translate('DeletedRecord') . '
'; } elseif ($res === 'notfound') { @@ -142,7 +143,7 @@ function createForm($strFunc, $strList, $strForm) unset($astrValues['id']); $id = 0; $res = saveFormData( - $strTable, $id, $astrFormElements, $astrValues, $warnings + $formConfig['table'], $id, $formConfig['fields'], $astrValues, $warnings ); if ($res === true) { $qs = preg_replace('/&id=\w*/', "&id=$id", $_SERVER['QUERY_STRING']); @@ -154,7 +155,7 @@ function createForm($strFunc, $strList, $strForm) } if (!isset($astrValues)) { - $astrValues = getFormDefaultValues($astrFormElements); + $astrValues = getFormDefaultValues($formConfig['fields']); } ?> @@ -172,8 +173,8 @@ function createForm($strFunc, $strList, $strForm) @@ -217,8 +218,8 @@ function ($s) { $prevPosition = false; $prevColSpan = 1; $rowOpen = false; - $formFieldMode = sesWriteAccess() && !$readOnlyForm ? 'MODIFY' : 'READONLY'; - foreach ($astrFormElements as $elem) { + $formFieldMode = sesWriteAccess() && !$formConfig['readOnly'] ? 'MODIFY' : 'READONLY'; + foreach ($formConfig['fields'] as $elem) { if ($elem['type'] === false) { continue; } @@ -322,7 +323,7 @@ function ($s) { echo '
'; $haveChildForm = true; createIForm( - $astrFormElements, $elem, + $formConfig['fields'], $elem, isset($intKeyValue) ? $intKeyValue : 0, $intKeyValue ? false : true, $strForm ); break; @@ -511,7 +512,7 @@ function save_record(redirect_url, redir_style, on_print) var formdata = new FormData(); ", + 'url': "json.php?func=put_", 'type': 'POST', 'dataType': 'json', 'data': formdata, @@ -566,7 +567,7 @@ function save_record(redirect_url, redir_style, on_print) if (data.missing_fields) { MLInvoice.errormsg(': ' + data.missing_fields); } else { - + if (typeof on_print !== 'undefined' && on_print) { $('input#invoice_no').val(data.invoice_no); $('input#ref_number').val(data.ref_number); @@ -597,10 +598,10 @@ function save_record(redirect_url, redir_style, on_print) \n"; - if ($addressAutocomplete && getSetting('address_autocomplete')) { + if ($formConfig['addressAutocomplete'] && getSetting('address_autocomplete')) { ?> EOS; - $updateStockBalanceCode = << - $locUpdateStockBalance -
- -EOS; + $updateStockBalanceCode = '' . Translator::translate('UpdateStockBalance') . ''; } $barcodeTypes = [ diff --git a/htmlfuncs.php b/htmlfuncs.php index ceb5badc..cbefe290 100755 --- a/htmlfuncs.php +++ b/htmlfuncs.php @@ -134,7 +134,9 @@ function htmlPageStart($strTitle = '', $arrExtraScripts = []) 'RemoveAttachment', 'LargeFile', 'SendToClient', - 'Description' + 'Description', + 'Save', + 'UpdateStockBalance' ]; $res = dbQueryCheck( diff --git a/index.php b/index.php index eff235db..2bfb5bf0 100644 --- a/index.php +++ b/index.php @@ -242,7 +242,7 @@ if ($strFunc == 'open_invoices') { createOpenInvoiceList(); } elseif ($strFunc == 'archived_invoices') { - createList('archived_invoices', 'invoice', 'archived_invoices', ''); + createList('archived_invoices', 'archived_invoices', 'archived_invoices', ''); } else { if ($strList == 'settings') { createSettingsList(); diff --git a/js/mlinvoice.js b/js/mlinvoice.js index 2bd58d68..22678d12 100644 --- a/js/mlinvoice.js +++ b/js/mlinvoice.js @@ -1137,6 +1137,11 @@ var MLInvoice = (function MLInvoice() { if ($('#company_id.select2').val()) { _onChangeCompany(); } + // Stock balance + $('.update-stock-balance').click(function updateStockBalanceClick() { + updateStockBalance(); + return false; + }); } function updateSendApiButtons() @@ -1355,6 +1360,63 @@ var MLInvoice = (function MLInvoice() { _setupListMultiSelect(); } + function updateStockBalance() + { + var buttons = {}; + buttons[translate('Save')] = function onSaveStockBalance() { + saveStockBalance(); + }; + buttons[translate('Close')] = function onCloseStockBalance() { + $('#update_stock_balance').dialog('close'); + }; + $('#update_stock_balance').dialog( + { + modal: true, width: 400, height: 240, resizable: false, zIndex: 900, + buttons: buttons, + title: translate('UpdateStockBalance'), + } + ); + } + + function saveStockBalance() + { + $.ajax({ + url: 'json.php?func=update_stock_balance', + type: 'POST', + data: { + product_id: $('#record_id').val(), + stock_balance_change: document.getElementById('stock_balance_change').value.replace(translate('DecimalSeparator'), '.'), + stock_balance_change_desc: document.getElementById('stock_balance_change_desc').value + }, + success: function updateStockBalanceDone(data) { + if (data.missing_fields) { + alert(translate('ErrValueMissing') + ': ' + data.missing_fields); + } else { + var new_balance = parseFloat(data.new_stock_balance).toFixed(2).replace('.', translate('DecimalSeparator')); + $('#stock_balance').val(new_balance); + updateStockBalanceLog(); + $('#update_stock_balance').dialog('close'); + } + } + }); + } + + function updateStockBalanceLog() + { + $('#stock_balance_change_log > tbody > tr').slice(1).remove(); + $.ajax({ + url: 'json.php?func=get_stock_balance_rows', + type: 'POST', + data: { + product_id: $('#record_id').val(), + }, + success: function getStockBalanceRowsDone(data) { + $('#stock_balance_change_log').append(data); + } + }); + } + + return { init: init, addTranslation: addTranslation, @@ -1379,6 +1441,8 @@ var MLInvoice = (function MLInvoice() { calculateInvoiceRowSummary: calculateInvoiceRowSummary, updateSendApiButtons: updateSendApiButtons, clearMessages: clearMessages, - ajaxErrorHandler: ajaxErrorHandler + ajaxErrorHandler: ajaxErrorHandler, + updateStockBalance: updateStockBalance, + updateStockBalanceLog: updateStockBalanceLog } })(); diff --git a/js/stock_balance.js b/js/stock_balance.js deleted file mode 100644 index d6c5c502..00000000 --- a/js/stock_balance.js +++ /dev/null @@ -1,58 +0,0 @@ -/* global $ */ -/* exported update_stock_balance */ -function update_stock_balance(translations) -{ - var buttons = {}; - buttons[translations.save] = function onSaveStockBalance() { - save_stock_balance(translations); - }; - buttons[translations.close] = function onCloseStockBalance() { - $('#update_stock_balance').dialog('close'); - }; - $('#update_stock_balance').dialog( - { - modal: true, width: 400, height: 240, resizable: false, zIndex: 900, - buttons: buttons, - title: translations.title, - } - ); -} - -function save_stock_balance(translations) -{ - $.ajax({ - url: 'json.php?func=update_stock_balance', - type: 'POST', - data: { - product_id: $('#record_id').val(), - stock_balance_change: document.getElementById('stock_balance_change').value.replace(translations.decimal_separator, '.'), - stock_balance_change_desc: document.getElementById('stock_balance_change_desc').value - }, - success: function updateStockBalanceDone(data) { - if (data.missing_fields) { - alert(translations.missing + data.missing_fields); - } else { - var new_balance = parseFloat(data.new_stock_balance).toFixed(2).replace('.', translations.decimal_separator); - $('#stock_balance').val(new_balance); - update_stock_balance_log(); - $('#update_stock_balance').dialog('close'); - } - } - }); -} - -function update_stock_balance_log() -{ - $('#stock_balance_change_log > tbody > tr').slice(1).remove(); - $.ajax({ - url: 'json.php?func=get_stock_balance_rows', - type: 'POST', - data: { - product_id: $('#record_id').val(), - }, - success: function getStockBalanceRowsDone(data) { - $('#stock_balance_change_log').append(data); - } - }); -} - diff --git a/json.php b/json.php index aa2b93ed..c5bbba3c 100644 --- a/json.php +++ b/json.php @@ -43,6 +43,7 @@ require_once 'settings.php'; require_once 'memory.php'; require_once 'form_config.php'; +require_once 'list_config.php'; sesVerifySession(false); @@ -380,9 +381,8 @@ $tableId = getRequest('tableid', ''); - include 'list_switch.php'; - - if (!$strTable) { + $listConfig = getListConfig($strList); + if (!$listConfig) { header('HTTP/1.1 400 Bad Request'); die('Invalid table name'); } @@ -392,12 +392,12 @@ $sort = []; $columns = getRequest('columns', []); if ($orderCols = getRequest('order', [])) { - for ($i = 0; $i < count($orderCols); $i ++) { - if (!isset($orderCols[$i]['column'])) { + foreach ($orderCols as $orderCol) { + if (!isset($orderCol['column'])) { continue; } - $sortColumn = $orderCols[$i]['column']; - $sortDir = $orderCols[$i]['dir']; + $sortColumn = $orderCol['column']; + $sortDir = $orderCol['dir']; $sort[] = [ $sortColumn => $sortDir === 'desc' ? 'desc' : 'asc' ]; @@ -884,7 +884,7 @@ function getInvoiceListTotal($where) $strFunc = 'invoices'; $strList = 'invoice'; - include 'list_switch.php'; + $listConfig = getListConfig($strList); $strWhereClause = ''; $joinOp = 'WHERE'; @@ -910,12 +910,12 @@ function getInvoiceListTotal($where) $joinOp = ' AND'; } } - if (!getSetting('show_deleted_records')) { - $strWhereClause .= "$joinOp $strDeletedField=0"; + if (!getSetting('show_deleted_records') && $listConfig['deletedField']) { + $strWhereClause .= "$joinOp {$listConfig['deletedField']}=0"; $joinOp = ' AND'; } - $sql = "SELECT sum(it.row_total) as total_sum from $strTable $strJoin $strWhereClause"; + $sql = "SELECT sum(it.row_total) as total_sum from {$listConfig['table']} {$listConfig['displayJoin']} $strWhereClause"; $sum = 0; $rows = dbParamQuery($sql, $arrQueryParams); diff --git a/list.php b/list.php index 3e26d203..a16db046 100755 --- a/list.php +++ b/list.php @@ -30,6 +30,7 @@ require_once "miscfuncs.php"; require_once "datefuncs.php"; require_once "memory.php"; +require_once "list_config.php"; use Michelf\Markdown; @@ -53,13 +54,12 @@ function createList($strFunc, $strList, $strTableName = '', $strTitleOverride = ) { $strWhereClause = $prefilter ? $prefilter : getRequest('where', ''); - include 'list_switch.php'; - if (!$strList) { $strList = $strFunc; } - if (!$strTable) { + $listConfig = getListConfig($strList); + if (!$listConfig) { return; } @@ -86,17 +86,17 @@ function createList($strFunc, $strList, $strTableName = '', $strTitleOverride = } } - if ($strListFilter) { + if ($listConfig['listFilter']) { if ($strWhereClause) { // Special case: don't apply archived filter for invoices if search terms // already contain archived status if ($strList != 'invoices' || strpos($strWhereClause, 'i.archived') === false ) { - $strWhereClause .= " AND $strListFilter"; + $strWhereClause .= " AND {$listConfig['listFilter']}"; } } else { - $strWhereClause = $strListFilter; + $strWhereClause = $listConfig['listFilter']; } } @@ -105,11 +105,7 @@ function createList($strFunc, $strList, $strTableName = '', $strTitleOverride = } $strTableName .= '_2'; - if ($strTitleOverride) { - $strTitle = $strTitleOverride; - } else { - $strTitle = ''; - } + $strTitle = $listConfig['title']; $params = [ 'listfunc' => $strFunc, @@ -177,7 +173,7 @@ function createList($strFunc, $strList, $strTableName = '', $strTitleOverride = $field) { + foreach ($listConfig['fields'] as $field) { if ('HIDDEN' === $field['type']) { continue; } @@ -185,6 +181,7 @@ function createList($strFunc, $strList, $strTableName = '', $strTitleOverride = $strWidth = isset($field['width']) ? ($field['width'] . 'px') : ''; $sortable = !isset($field['sort']) || $field['sort'] ? 'true' : 'false'; $class = $customPriceSettings && $customPriceSettings['valid'] + && 'custom_price' === $field['name'] ? 'editable' : ''; ?> { @@ -209,7 +206,7 @@ className: '' for (var i = 0, len = json.data.length; i < len; i++) { $field) { + foreach ($listConfig['fields'] as $field) { if ('HIDDEN' === $field['type']) { continue; } @@ -388,7 +385,7 @@ className: '' ID Link ' function createJSONList($strFunc, $strList, $startRow, $rowCount, $sort, $filter, $where, $requestId, $listId, $companyId = null ) { - include "list_switch.php"; - global $dblink; - if (!sesAccessLevel($levelsAllowed) && !sesAdminAccess()) { + $listConfig = getListConfig($strList); + if (!$listConfig) { + return; + } + + if (!sesAccessLevel($listConfig['accessLevels']) && !sesAdminAccess()) { ?>
@@ -471,10 +471,6 @@ function createJSONList($strFunc, $strList, $startRow, $rowCount, $sort, $filter return; } - if (!$strTable) { - return; - } - $params = createListQueryParams( $strFunc, $strList, $startRow, $rowCount, $sort, $filter, $where ); @@ -487,7 +483,7 @@ function createJSONList($strFunc, $strList, $startRow, $rowCount, $sort, $filter // Total count $fullQuery - = "SELECT COUNT(*) AS cnt FROM $strTable $strCountJoin $strWhereClause"; + = "SELECT COUNT(*) AS cnt FROM {$listConfig['table']} $strCountJoin $strWhereClause"; $rows = dbParamQuery($fullQuery, $queryParams); $totalCount = $filteredCount = $rows[0]['cnt']; @@ -498,7 +494,7 @@ function createJSONList($strFunc, $strList, $startRow, $rowCount, $sort, $filter // Filtered count $fullQuery - = "SELECT COUNT(*) as cnt FROM $strTable $strCountJoin $strWhereClause"; + = "SELECT COUNT(*) as cnt FROM {$listConfig['table']} $strCountJoin $strWhereClause"; $rows = dbParamQuery($fullQuery, $queryParams); $filteredCount = $rows[0]['cnt']; } @@ -514,11 +510,11 @@ function createJSONList($strFunc, $strList, $startRow, $rowCount, $sort, $filter } // Build the final select clause - $strSelectClause = $strPrimaryKey; - if ($strDeletedField) { - $strSelectClause .= ", $strDeletedField"; + $strSelectClause = $listConfig['primaryKey']; + if ($listConfig['deletedField']) { + $strSelectClause .= ", {$listConfig['deletedField']}"; } - foreach ($astrShowFields as $field) { + foreach ($listConfig['fields'] as $field) { if ('HIDDEN' === $field['type'] || !empty($field['virtual'])) { continue; } @@ -529,12 +525,12 @@ function createJSONList($strFunc, $strList, $startRow, $rowCount, $sort, $filter // Include any custom prices $strSelectClause .= << $records ]; return json_encode($results); - } /** @@ -661,10 +658,10 @@ function createJSONList($strFunc, $strList, $startRow, $rowCount, $sort, $filter function createListQueryParams($strFunc, $strList, $startRow, $rowCount, $sort, $filter, $where ) { - include "list_switch.php"; - global $dblink; + $listConfig = getListConfig($strList); + $terms = ''; $joinOp = ''; $arrQueryParams = []; @@ -705,28 +702,24 @@ function createListQueryParams($strFunc, $strList, $startRow, $rowCount, $sort, } } - if (!getSetting('show_deleted_records') && $strDeletedField) { - $terms .= "$joinOp $strDeletedField=0"; + if (!getSetting('show_deleted_records') && $listConfig['deletedField']) { + $terms .= "$joinOp {$listConfig['deletedField']}=0"; $joinOp = ' AND'; } $filteredParams = $arrQueryParams; if ($filter) { $filteredTerms = "$terms $joinOp (" . - createWhereClause($astrSearchFields, $filter, $filteredParams) . ')'; + createWhereClause($listConfig['searchFields'], $filter, $filteredParams) . ')'; $joinOp = ' AND'; } - if (!isset($strCountJoin)) { - $strCountJoin = $strJoin; - } - // Sort options $orderBy = []; // Filter out hidden fields $shownFields = array_values( array_filter( - $astrShowFields, + $listConfig['fields'], function ($val) { return 'HIDDEN' !== $val['type']; } @@ -751,14 +744,14 @@ function ($val) { } $result = [ - 'table' => $strTable, - 'primaryKey' => $strPrimaryKey, + 'table' => $listConfig['table'], + 'primaryKey' => $listConfig['primaryKey'], 'terms' => $terms, 'params' => $arrQueryParams, 'order' => implode(',', $orderBy), - 'group' => $strGroupBy, - 'join' => $strJoin, - 'countJoin' => isset($strCountJoin) ? $strCountJoin : $strJoin + 'group' => $listConfig['groupBy'], + 'join' => $listConfig['displayJoin'], + 'countJoin' => $listConfig['countJoin'] ? $listConfig['countJoin'] : $listConfig['displayJoin'] ]; if (isset($filteredTerms)) { $result['filteredTerms'] = $filteredTerms; @@ -784,9 +777,9 @@ function createJSONSelectList($strList, $startRow, $rowCount, $filter, $sort, $id = null ) { global $dblink; - include "list_switch.php"; - if (empty($id) && !sesAccessLevel($levelsAllowed) && !sesAdminAccess()) { + $listConfig = getListConfig($strList); + if (empty($id) && !sesAccessLevel($listConfig['accessLevels']) && !sesAdminAccess()) { ?>
@@ -803,7 +796,7 @@ function createJSONSelectList($strList, $startRow, $rowCount, $filter, $sort, $sortValid = 0; $sortFields = explode(',', $sort); foreach ($sortFields as $sortField) { - foreach ($astrShowFields as $field) { + foreach ($listConfig['fields'] as $field) { if ($sortField === $field['name']) { ++$sortValid; break; @@ -815,7 +808,7 @@ function createJSONSelectList($strList, $startRow, $rowCount, $filter, $sort, die('Invalid sort type'); } } else { - foreach ($astrShowFields as $field) { + foreach ($listConfig['fields'] as $field) { if ($field['name'] == 'order_no') { $sort = 'order_no'; } @@ -831,14 +824,12 @@ function createJSONSelectList($strList, $startRow, $rowCount, $filter, $sort, $strWhereClause = ''; if (!getSetting('show_deleted_records') && empty($id) - && !empty($strDeletedField) + && !empty($listConfig['deletedField']) ) { - $strWhereClause = " WHERE $strDeletedField=0"; + $strWhereClause = " WHERE {$listConfig['deletedField']}=0"; } - if ($strGroupBy) { - $strGroupBy = " GROUP BY $strGroupBy"; - } + $strGroupBy = $listConfig['groupBy'] ? " GROUP BY {$listConfig['groupBy']}" : ''; // Add Filter if ($filter) { @@ -854,7 +845,7 @@ function createJSONSelectList($strList, $startRow, $rowCount, $filter, $sort, if ($filter) { $strWhereClause .= ($strWhereClause ? ' AND ' : ' WHERE ') . createWhereClause( - $astrSearchFields, $filter, $arrQueryParams, + $listConfig['searchFields'], $filter, $arrQueryParams, !getSetting('dynamic_select_search_in_middle') ); } @@ -873,9 +864,9 @@ function createJSONSelectList($strList, $startRow, $rowCount, $filter, $sort, } // Build the final select clause - $strSelectClause = !empty($strDeletedField) ? "$strPrimaryKey, $strDeletedField" - : $strPrimaryKey; - foreach ($astrShowFields as $field) { + $strSelectClause = $listConfig['deletedField'] ? "{$listConfig['primaryKey']}, {$listConfig['deletedField']}" + : $listConfig['primaryKey']; + foreach ($listConfig['fields'] as $field) { if (!empty($field['virtual'])) { continue; } @@ -884,9 +875,9 @@ function createJSONSelectList($strList, $startRow, $rowCount, $filter, $sort, } // Sort any exact matches first - if ($astrSearchFields && $filter) { + if ($listConfig['searchFields'] && $filter) { $fields = []; - foreach ($astrSearchFields as $searchField) { + foreach ($listConfig['searchFields'] as $searchField) { if (in_array($searchField['type'], ['TEXT', 'INT', 'PRIMARY'])) { $fields[] = $searchField['name']; } @@ -912,13 +903,13 @@ function createJSONSelectList($strList, $startRow, $rowCount, $filter, $sort, // Include any custom prices $strSelectClause .= << $row[$strPrimaryKey], + 'id' => $row[$listConfig['primaryKey']], 'descriptions' => $descriptions, 'text' => implode(' ', $resultValues) ]; diff --git a/list_config.php b/list_config.php new file mode 100644 index 00000000..95711e9d --- /dev/null +++ b/list_config.php @@ -0,0 +1,55 @@ + + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://labs.fi/mlinvoice.eng.php + */ + +/** + * Get list configuration + * + * @param string $list List name + * + * @return array + */ +function getListConfig($list) +{ + $strList = $list; + include 'list_switch.php'; + + return $strTable ? [ + 'title' => isset($locTitle) ? $locTitle : '', + 'accessLevels' => $levelsAllowed, + 'table' => $strTable, + 'displayJoin' => $strJoin, + 'countJoin' => isset($strCountJoin) ? $strCountJoin : null, + 'groupBy' => $strGroupBy, + 'listFilter' => $strListFilter, + 'primaryKey' => $strPrimaryKey, + 'deletedField' => $strDeletedField, + 'fields' => $astrShowFields, + 'searchFields' => isset($astrSearchFields) ? $astrSearchFields : null, + 'mainForm' => $strMainForm, + ] : []; +} diff --git a/list_switch.php b/list_switch.php index 02fc8044..8cc0d874 100755 --- a/list_switch.php +++ b/list_switch.php @@ -26,7 +26,7 @@ * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link http://labs.fi/mlinvoice.eng.php */ - $strTable = ''; +$strTable = ''; $strJoin = ''; $strListFilter = ''; $strGroupBy = ''; @@ -35,7 +35,7 @@ ROLE_USER, ROLE_BACKUPMGR ]; -switch ($strList ? $strList : $strFunc) { +switch ($strList) { /*********************************************************************** LISTS @@ -53,10 +53,6 @@ 'type' => 'TEXT' ] ]; - $astrHiddenSearchField = [ - 'name' => 'type_id', - 'type' => 'INT' - ]; $strPrimaryKey = 'id'; $strDeletedField = 'deleted'; $astrShowFields = [ @@ -128,7 +124,7 @@ case 'offer': $levelsAllowed[] = ROLE_READONLY; - $strListFilter = ($strFunc == 'archived_invoices') ? 'i.archived = 1' + $strListFilter = 'archived_invoices' === $strList ? 'i.archived = 1' : 'i.archived = 0'; $strTable = '{prefix}invoice i'; $strJoin = 'LEFT OUTER JOIN {prefix}base b on i.base_id=b.id ' . @@ -834,7 +830,7 @@ case 'user' : $levelsAllowed = [ - 99 + ROLE_ADMIN ]; $strTable = '{prefix}users'; $astrSearchFields = [ From 3cf5b17f6ead17b3102c15ac09fbed04cd2fbfd7 Mon Sep 17 00:00:00 2001 From: Ere Maijala Date: Wed, 5 Dec 2018 19:57:04 +0200 Subject: [PATCH 011/154] Display billing company properly in invoice report. --- abstract_report.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abstract_report.php b/abstract_report.php index 5b945594..a6d17243 100644 --- a/abstract_report.php +++ b/abstract_report.php @@ -65,7 +65,7 @@ protected function getParamsStr($html) 'payment_date' => ['name' => 'PaymentDateInterval'], 'base' => [ 'name' => 'Biller', - 'sql' => 'SELECT name FROM {prefix}base WHERE id = ?' + 'sql' => 'SELECT name as v FROM {prefix}base WHERE id = ?' ], 'company' => [ 'name' => 'Client', From 34f34895b6831ad47273868ba80b417d65fe4860 Mon Sep 17 00:00:00 2001 From: Ere Maijala Date: Thu, 6 Dec 2018 19:23:17 +0200 Subject: [PATCH 012/154] Switch on hard wrap in Markdown rendering. Fix several bugs with lists etc. --- form_funcs.php | 6 +++--- form_switch.php | 3 ++- invoice_printer_xslt.php | 5 ++--- js/mlinvoice.js | 9 --------- list.php | 24 +++++++++++++----------- list_config.php | 2 +- markdown.php | 40 ++++++++++++++++++++++++++++++++++++++++ pdf.php | 8 ++++++-- 8 files changed, 67 insertions(+), 30 deletions(-) create mode 100644 markdown.php diff --git a/form_funcs.php b/form_funcs.php index 2c1e3aa0..597dfd6b 100644 --- a/form_funcs.php +++ b/form_funcs.php @@ -38,7 +38,7 @@ * * @return array */ -function getFormDefaultValues(&$formElements, $parentKey = false) +function getFormDefaultValues($formElements, $parentKey = false) { $values = []; @@ -110,7 +110,7 @@ function getFormDefaultValue($elem, $parentKey) * * @return mixed */ -function saveFormData($table, &$primaryKey, &$formElements, &$values, &$warnings, +function saveFormData($table, &$primaryKey, $formElements, &$values, &$warnings, $parentKeyName = '', $parentKey = false, $onPrint = false, $partial = false ) { global $dblink; @@ -452,7 +452,7 @@ function saveFormData($table, &$primaryKey, &$formElements, &$values, &$warnings * * @return mixed */ -function fetchRecord($table, $primaryKey, &$formElements, &$values) +function fetchRecord($table, $primaryKey, $formElements, &$values) { $result = true; $strQuery = "SELECT * FROM $table WHERE id=?"; diff --git a/form_switch.php b/form_switch.php index 3df7be41..67a7194e 100755 --- a/form_switch.php +++ b/form_switch.php @@ -51,7 +51,8 @@ switch ($strForm) { -case 'company' : +case 'company': +case 'companies': $strTable = '{prefix}company'; $strJSONType = 'company'; $strParentKey = 'company_id'; diff --git a/invoice_printer_xslt.php b/invoice_printer_xslt.php index 094d1353..b139b1fc 100644 --- a/invoice_printer_xslt.php +++ b/invoice_printer_xslt.php @@ -29,8 +29,7 @@ require_once 'htmlfuncs.php'; require_once 'miscfuncs.php'; require_once 'pdf.php'; - -use Michelf\Markdown; +require_once 'markdown.php'; /** * XSLT invoice @@ -262,7 +261,7 @@ protected function getInvoiceRowData() { // Preprocess invoice rows if (getSetting('printout_markdown')) { - $markdown = new Markdown(); + $markdown = new MLMarkdown(); } else { $markdown = null; } diff --git a/js/mlinvoice.js b/js/mlinvoice.js index 22678d12..2ec2a4f8 100644 --- a/js/mlinvoice.js +++ b/js/mlinvoice.js @@ -1320,15 +1320,6 @@ var MLInvoice = (function MLInvoice() { } function _setupListMultiSelect() { - $('a.actionlink.update-selected-rows').click(function editSelectedClick() { - var list = $(this).data('list'); - var ids = $(this).closest('.list_container').find('.cb-select-row:checked').map(function mapChecked() { - return 'id[]=' + encodeURIComponent(this.value); - }).get(); - window.location.href = '?func=multiedit&list=' + encodeURIComponent(list) + '&' + ids.join('&'); - return false; - }); - $('.print-selected-rows .print-selected-item').click(function printSelectedClick() { var ids = $(this).closest('.list_container').find('.cb-select-row:checked').map(function mapChecked() { return 'id[]=' + encodeURIComponent(this.value); diff --git a/list.php b/list.php index a16db046..b5a5f3be 100755 --- a/list.php +++ b/list.php @@ -26,13 +26,12 @@ * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link http://labs.fi/mlinvoice.eng.php */ -require_once "sqlfuncs.php"; -require_once "miscfuncs.php"; -require_once "datefuncs.php"; -require_once "memory.php"; -require_once "list_config.php"; - -use Michelf\Markdown; +require_once 'sqlfuncs.php'; +require_once 'miscfuncs.php'; +require_once 'datefuncs.php'; +require_once 'memory.php'; +require_once 'list_config.php'; +require_once 'markdown.php'; /** * Create a list @@ -105,7 +104,7 @@ function createList($strFunc, $strList, $strTableName = '', $strTitleOverride = } $strTableName .= '_2'; - $strTitle = $listConfig['title']; + $strTitle = $strTitleOverride ? $strTitleOverride : $listConfig['title']; $params = [ 'listfunc' => $strFunc, @@ -408,7 +407,7 @@ className: '' ?>
: - +