0.9) { $value /= 1024; ++$idx; } return round($value, 2) . ' ' . $suffixes[$idx]; } function xml_encode($str) { $str = str_replace('&', '&', $str); $str = str_replace('<', '<', $str); $str = str_replace('>', '>', $str); $str = str_replace('"', '"', $str); return $str; } if (!function_exists('str_getcsv')) { function str_getcsv($input, $delimiter = ',', $enclosure = '"', $escape = null, $eol = null) { $temp = fopen('php://memory', 'rw'); fwrite($temp, $input); fseek($temp, 0); $r = fgetcsv($temp, 4096, $delimiter, $enclosure); fclose($temp); return $r; } } function fgets_charset($handle, $charset, $line_ending = "\n") { if (strncmp($charset, 'UTF-16', 6) == 0) { $be = $charset == 'UTF-16' || $charset == 'UTF-16BE'; $str = ''; $le_pos = 0; $le_len = strlen($line_ending); while (!feof($handle)) { $c1 = fgetc($handle); $c2 = fgetc($handle); if ($c1 === false || $c2 === false) { break; } $str .= $c1 . $c2; if (($be && ord($c1) == 0 && $c2 == $line_ending[$le_pos]) || (!$be && ord($c2) == 0 && $c1 == $line_ending[$le_pos]) ) { if (++$le_pos >= $le_len) break; } else { $le_pos = 0; } } $str = iconv($charset, _CHARSET_, $str); } else { $str = ''; $le_pos = 0; $le_len = strlen($line_ending); while (!feof($handle)) { $c1 = fgetc($handle); if ($c1 === false) { break; } $str .= $c1; if ($c1 == $line_ending[$le_pos]) { if (++$le_pos >= $le_len) { break; } } else { $le_pos = 0; } } $conv_str = iconv($charset, _CHARSET_, $str); if ($str && !$conv_str) { error_log( "Conversion from '$charset' to '" . _CHARSET_ . "' failed for string '$str'" ); } else { $str = $conv_str; } } return $str; } function iconvErrorHandler($errno, $errstr, $errfile, $errline) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline); } function try_iconv($from, $to, $str) { set_error_handler('iconvErrorHandler'); try { $str = iconv($from, $to, $str); } catch (ErrorException $e) { restore_error_handler(); return false; } restore_error_handler(); return $str; } function sanitize($str) { return preg_replace('/[^\w\d]/', '', $str); } function calculateRowSum($row) { $price = $row['price']; $count = $row['pcs']; $VAT = $row['vat']; $VATIncluded = $row['vat_included']; $discount = $row['discount']; $discountAmount = $row['discount_amount']; if ($discount) { $price *= (1 - $discount / 100); } if ($discountAmount) { $price -= $discountAmount; } if ($VATIncluded) { $rowSumVAT = round($count * $price, 2); $rowSum = round(($rowSumVAT / (1 + $VAT / 100)), 2); $rowVAT = $rowSumVAT - $rowSum; } else { $rowSum = round($count * $price, 2); $rowVAT = round(($rowSum * ($VAT / 100)), 2); $rowSumVAT = $rowSum + $rowVAT; } return [ $rowSum, $rowVAT, $rowSumVAT ]; } function createVATID($id) { $id = strtoupper(str_replace('-', '', $id)); if (!preg_match('/^[A-Z]{2}/', $id)) { $id = "FI$id"; } return $id; } function getSelfPath() { return _PROTOCOL_ . $_SERVER['HTTP_HOST'] . getSelfDirectory(); } function getSelfDirectory() { $path = $_SERVER['SCRIPT_NAME']; $path = str_replace('\\', '/', $path); $p = strrpos($path, '/'); if ($p > 0) { $path = substr($path, 0, $p); } else { $path = ''; } return $path; } function instantiateInvoicePrinter($printTemplateFile) { $className = $printTemplateFile; $className = str_replace('.php', '', $className); $className = str_replace('_', ' ', $className); $className = ucwords($className); $className = str_replace(' ', '', $className); require_once $printTemplateFile; return new $className(); } function formatRefNumber($refNumber) { if (strncasecmp($refNumber, 'RF', 2) == 0) { return strtoupper(trim(chunk_split($refNumber, 4, ' '))); } return trim(strrev(chunk_split(strrev($refNumber), 5, ' '))); } function addFileTimestamp($filename) { if (!file_exists($filename)) { return $filename; } $mtime = filemtime($filename); if (false !== $mtime) { $filename .= strstr($filename, '?') ? '&_=' : '?_='; $filename .= $mtime; } return $filename; } function getInvoiceDefaults($invoiceId, $baseId, $companyId, $invoiceDate, $intervalType, $invoiceNumber ) { $perYear = getSetting('invoice_numbering_per_year'); // If the invoice already has an invoice number, verify that it's not in use in another invoice if ($invoiceNumber) { $query = 'SELECT ID FROM {prefix}invoice where deleted=0 AND id!=? AND invoice_no=?'; $params = [ $invoiceId, $invoiceNumber ]; if (getSetting('invoice_numbering_per_base') && $baseId) { $query .= ' AND base_id=?'; $params[] = $baseId; } if ($perYear) { $query .= ' AND invoice_date >= ' . dateConvDate2DBDate($invoiceDate); } $rows = db_param_query($query, $params); if ($rows) { $invoiceNumber = 0; } } if (!$invoiceNumber) { $maxNr = get_max_invoice_number( $invoiceId, getSetting('invoice_numbering_per_base') && $baseId ? $baseId : null, $perYear ); if ($maxNr === null && $perYear) { $maxNr = get_max_invoice_number( $invoiceId, getSetting('invoice_numbering_per_base') && $baseId ? $baseId : null, false ); } $invoiceNumber = $maxNr + 1; } if ($invoiceNumber < 100) $invoiceNumber = 100; // min ref number length is 3 + check digit, make sure invoice number matches that $refNr = $invoiceNumber . miscCalcCheckNo($invoiceNumber); $strDate = date(Translator::translate('DateFormat')); $strDueDate = date( Translator::translate('DateFormat'), mktime(0, 0, 0, date('m'), date('d') + getPaymentDays($companyId), date('Y')) ); switch ($intervalType) { case 2: $nextIntervalDate = date( Translator::translate('DateFormat'), mktime(0, 0, 0, date('m') + 1, date('d'), date('Y')) ); break; case 3: $nextIntervalDate = date( Translator::translate('DateFormat'), mktime(0, 0, 0, date('m'), date('d'), date('Y') + 1) ); break; case 4: case 5: case 6: case 7: case 8: $nextIntervalDate = date( Translator::translate('DateFormat'), mktime(0, 0, 0, date('m') + $intervalType - 2, date('d'), date('Y')) ); break; default : $nextIntervalDate = ''; } return [ 'invoice_no' => $invoiceNumber, 'ref_no' => $refNr, 'date' => $strDate, 'due_date' => $strDueDate, 'next_interval_date' => $nextIntervalDate ]; }