- HKEKA v3/v4/v5 Segmente fuer phpFinTS implementiert (VR Bank unterstuetzt kein HKEKP) - GetElectronicStatement Action mit Base64-Erkennung und Quittungscode - PDF-Deduplizierung per MD5 (Bank sendet identische Saldenmitteilungen) - Saldenmitteilungen ohne Auszugsnummer werden uebersprungen - Datums-Validierung: 30.02. (Bank-Konvention) wird auf 28.02. korrigiert - Numerische Sortierung fuer statement_number (CAST statt String-Sort) - Jahr-Filter: statement_year=0 ausgeschlossen - Menue/Button: "Kontoauszuege" -> "Umsaetze" (statements.php zeigt MT940, nicht PDFs) - Redirect nach FinTS-Abruf auf aktuelles Jahr statt year=0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
147 lines
4.8 KiB
PHP
Executable file
147 lines
4.8 KiB
PHP
Executable file
<?php
|
|
|
|
namespace Fhp\Segment;
|
|
|
|
use Fhp\Syntax\Parser;
|
|
use Fhp\Syntax\Serializer;
|
|
|
|
/**
|
|
* Base class for segments. Sub-classes names need to follow the format "<Kennung>v<Version>" where <Kennung> is the
|
|
* type of the segment (e.g. "HITANS") and <Version> is the numeric version. The *public* member fields of a sub-class
|
|
* determine the structure of the segment. The order matters for the wire format, whereas the field names are only used
|
|
* for documentation/readability purposes within this library. See {@link HITANSv6} for an example of a sub-class.
|
|
*/
|
|
abstract class BaseSegment implements SegmentInterface, \Serializable
|
|
{
|
|
/** Reference to the descriptor for this type of segment. */
|
|
private ?SegmentDescriptor $descriptor = null;
|
|
public Segmentkopf $segmentkopf;
|
|
|
|
/**
|
|
* @return SegmentDescriptor The descriptor for this segment's type.
|
|
*/
|
|
public function getDescriptor(): SegmentDescriptor
|
|
{
|
|
if ($this->descriptor === null) {
|
|
$this->descriptor = SegmentDescriptor::get(static::class);
|
|
}
|
|
return $this->descriptor;
|
|
}
|
|
|
|
public function getName(): string
|
|
{
|
|
return $this->segmentkopf->segmentkennung;
|
|
}
|
|
|
|
public function getVersion(): int
|
|
{
|
|
return $this->segmentkopf->segmentversion;
|
|
}
|
|
|
|
public function getSegmentNumber(): int
|
|
{
|
|
return $this->segmentkopf->segmentnummer;
|
|
}
|
|
|
|
/**
|
|
* @param int $segmentNumber The new segment number.
|
|
* @return $this The same instance.
|
|
*/
|
|
public function setSegmentNumber(int $segmentNumber): static
|
|
{
|
|
$this->segmentkopf->segmentnummer = $segmentNumber;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @throws \InvalidArgumentException If any element in this segment is invalid.
|
|
*/
|
|
public function validate()
|
|
{
|
|
$this->getDescriptor()->validateObject($this);
|
|
}
|
|
|
|
/**
|
|
* @deprecated Beginning from PHP7.4 __unserialize is used for new generated strings, then this method is only used for previously generated strings - remove after May 2023
|
|
*
|
|
* Short-hand for {@link Serializer::serializeSegment()}.
|
|
* @return string The HBCI wire format representation of this segment, in ISO-8859-1 encoding, terminated by the
|
|
* segment delimiter.
|
|
*/
|
|
public function serialize(): string
|
|
{
|
|
return $this->__serialize()[0];
|
|
}
|
|
|
|
/**
|
|
* @deprecated Beginning from PHP7.4 __unserialize is used for new generated strings, then this method is only used for previously generated strings - remove after May 2023
|
|
*
|
|
* @param string $serialized
|
|
* @return void
|
|
*/
|
|
public function unserialize($serialized)
|
|
{
|
|
self::__unserialize([$serialized]);
|
|
}
|
|
|
|
/**
|
|
* Short-hand for {@link Serializer::serializeSegment()}.
|
|
*
|
|
* @return array [0]: The HBCI wire format representation of this segment, in ISO-8859-1 encoding, terminated by the
|
|
* segment delimiter.
|
|
*/
|
|
public function __serialize(): array
|
|
{
|
|
return [Serializer::serializeSegment($this)];
|
|
}
|
|
|
|
public function __unserialize(array $serialized): void
|
|
{
|
|
Parser::parseSegment($serialized[0], $this);
|
|
}
|
|
|
|
public function __toString(): string
|
|
{
|
|
return $this->serialize();
|
|
}
|
|
|
|
public function __debugInfo()
|
|
{
|
|
$result = get_object_vars($this);
|
|
unset($result['descriptor']); // Don't include descriptor in debug output, to avoid clutter.
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Convenience function for {@link Parser::parseSegment()}.
|
|
* @param string $rawSegment The serialized wire format for a single segment (segment delimiter must be present at
|
|
* the end). This should be ISO-8859-1-encoded.
|
|
* @return static The parsed segment.
|
|
*/
|
|
public static function parse(string $rawSegment): static
|
|
{
|
|
if (static::class === BaseSegment::class) {
|
|
// Called as BaseSegment::parse(), so we need to determine the right segment type/class.
|
|
return Parser::detectAndParseSegment($rawSegment);
|
|
} else {
|
|
// The parse() function was called on the segment subclass itself.
|
|
return Parser::parseSegment($rawSegment, static::class);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return static A new segment of the type on which this function was called, with the Segmentkopf initialized.
|
|
*/
|
|
public static function createEmpty(): static
|
|
{
|
|
if (static::class === BaseSegment::class) {
|
|
throw new \InvalidArgumentException('Must not call BaseSegment::createEmpty() on the super class');
|
|
}
|
|
$result = new static();
|
|
$descriptor = $result->getDescriptor();
|
|
$result->segmentkopf = new Segmentkopf();
|
|
$result->segmentkopf->segmentkennung = $descriptor->kennung;
|
|
$result->segmentkopf->segmentversion = $descriptor->version;
|
|
return $result;
|
|
}
|
|
}
|