mirror of
https://github.com/itflow-org/itflow
synced 2026-03-05 21:34:51 +00:00
Bunch of changes including mpdf library for creating pdf of invoices. It now attaches a PDF invoice when marked sent. Don't mark invoice_status sent if it partial or paid, removed green text from balance under clients only use red if the client has a balance and some other cleanups were done
This commit is contained in:
196
vendor/setasign/fpdi/src/PdfParser/CrossReference/FixedReader.php
vendored
Normal file
196
vendor/setasign/fpdi/src/PdfParser/CrossReference/FixedReader.php
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of FPDI
|
||||
*
|
||||
* @package setasign\Fpdi
|
||||
* @copyright Copyright (c) 2019 Setasign - Jan Slabon (https://www.setasign.com)
|
||||
* @license http://opensource.org/licenses/mit-license The MIT License
|
||||
*/
|
||||
|
||||
namespace setasign\Fpdi\PdfParser\CrossReference;
|
||||
|
||||
use setasign\Fpdi\PdfParser\PdfParser;
|
||||
use setasign\Fpdi\PdfParser\StreamReader;
|
||||
|
||||
/**
|
||||
* Class FixedReader
|
||||
*
|
||||
* This reader allows a very less overhead parsing of single entries of the cross-reference, because the main entries
|
||||
* are only read when needed and not in a single run.
|
||||
*
|
||||
* @package setasign\Fpdi\PdfParser\CrossReference
|
||||
*/
|
||||
class FixedReader extends AbstractReader implements ReaderInterface
|
||||
{
|
||||
/**
|
||||
* @var StreamReader
|
||||
*/
|
||||
protected $reader;
|
||||
|
||||
/**
|
||||
* Data of subsections.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $subSections;
|
||||
|
||||
/**
|
||||
* FixedReader constructor.
|
||||
*
|
||||
* @param PdfParser $parser
|
||||
* @throws CrossReferenceException
|
||||
*/
|
||||
public function __construct(PdfParser $parser)
|
||||
{
|
||||
$this->reader = $parser->getStreamReader();
|
||||
$this->read();
|
||||
parent::__construct($parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all subsection data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSubSections()
|
||||
{
|
||||
return $this->subSections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getOffsetFor($objectNumber)
|
||||
{
|
||||
foreach ($this->subSections as $offset => list($startObject, $objectCount)) {
|
||||
if ($objectNumber >= $startObject && $objectNumber < ($startObject + $objectCount)) {
|
||||
$position = $offset + 20 * ($objectNumber - $startObject);
|
||||
$this->reader->ensure($position, 20);
|
||||
$line = $this->reader->readBytes(20);
|
||||
if ($line[17] === 'f') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (int) \substr($line, 0, 10);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the cross-reference.
|
||||
*
|
||||
* This reader will only read the subsections in this method. The offsets were resolved individually by this
|
||||
* information.
|
||||
*
|
||||
* @throws CrossReferenceException
|
||||
*/
|
||||
protected function read()
|
||||
{
|
||||
$subSections = [];
|
||||
|
||||
$startObject = $entryCount = $lastLineStart = null;
|
||||
$validityChecked = false;
|
||||
while (($line = $this->reader->readLine(20)) !== false) {
|
||||
if (\strpos($line, 'trailer') !== false) {
|
||||
$this->reader->reset($lastLineStart);
|
||||
break;
|
||||
}
|
||||
|
||||
// jump over if line content doesn't match the expected string
|
||||
if (\sscanf($line, '%d %d', $startObject, $entryCount) !== 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$oldPosition = $this->reader->getPosition();
|
||||
$position = $oldPosition + $this->reader->getOffset();
|
||||
|
||||
if (!$validityChecked && $entryCount > 0) {
|
||||
$nextLine = $this->reader->readBytes(21);
|
||||
/* Check the next line for maximum of 20 bytes and not longer
|
||||
* By catching 21 bytes and trimming the length should be still 21.
|
||||
*/
|
||||
if (\strlen(\trim($nextLine)) !== 21) {
|
||||
throw new CrossReferenceException(
|
||||
'Cross-reference entries are larger than 20 bytes.',
|
||||
CrossReferenceException::ENTRIES_TOO_LARGE
|
||||
);
|
||||
}
|
||||
|
||||
/* Check for less than 20 bytes: cut the line to 20 bytes and trim; have to result in exactly 18 bytes.
|
||||
* If it would have less bytes the substring would get the first bytes of the next line which would
|
||||
* evaluate to a 20 bytes long string after trimming.
|
||||
*/
|
||||
if (\strlen(\trim(\substr($nextLine, 0, 20))) !== 18) {
|
||||
throw new CrossReferenceException(
|
||||
'Cross-reference entries are less than 20 bytes.',
|
||||
CrossReferenceException::ENTRIES_TOO_SHORT
|
||||
);
|
||||
}
|
||||
|
||||
$validityChecked = true;
|
||||
}
|
||||
|
||||
$subSections[$position] = [$startObject, $entryCount];
|
||||
|
||||
$lastLineStart = $position + $entryCount * 20;
|
||||
$this->reader->reset($lastLineStart);
|
||||
}
|
||||
|
||||
// reset after the last correct parsed line
|
||||
$this->reader->reset($lastLineStart);
|
||||
|
||||
if (\count($subSections) === 0) {
|
||||
throw new CrossReferenceException(
|
||||
'No entries found in cross-reference.',
|
||||
CrossReferenceException::NO_ENTRIES
|
||||
);
|
||||
}
|
||||
|
||||
$this->subSections = $subSections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes an invalid object number shift.
|
||||
*
|
||||
* This method can be used to repair documents with an invalid subsection header:
|
||||
*
|
||||
* <code>
|
||||
* xref
|
||||
* 1 7
|
||||
* 0000000000 65535 f
|
||||
* 0000000009 00000 n
|
||||
* 0000412075 00000 n
|
||||
* 0000412172 00000 n
|
||||
* 0000412359 00000 n
|
||||
* 0000412417 00000 n
|
||||
* 0000412468 00000 n
|
||||
* </code>
|
||||
*
|
||||
* It shall only be called on the first table.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function fixFaultySubSectionShift()
|
||||
{
|
||||
$subSections = $this->getSubSections();
|
||||
if (\count($subSections) > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$subSection = \current($subSections);
|
||||
if ($subSection[0] != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->getOffsetFor(1) === false) {
|
||||
foreach ($subSections as $offset => list($startObject, $objectCount)) {
|
||||
$this->subSections[$offset] = [$startObject - 1, $objectCount];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user