Completed
Push — master ( 21f90a...53ff33 )
by Paul
02:26
created

SIP2Request::resetSequence()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace lordelph\SIP2\Request;
4
5
use lordelph\SIP2\SIP2Message;
6
7
/**
8
 * Class SIP2Request extends SIP2Message with methods for building SIP2 message strings
9
 *
10
 * @licence    https://opensource.org/licenses/MIT
11
 * @copyright  John Wohlers <[email protected]>
12
 * @copyright  Paul Dixon <[email protected]>
13
 */
14
abstract class SIP2Request extends SIP2Message
15
{
16
    // can use these constants for getVariable/setVariable/setDefault etc
17
    
18
    const CANCEL = 'Cancel';
19
    const END = 'End';
20
    const EXPIRY_DATE = 'ExpiryDate';
21
    const FEE_ACKNOWLEDGED = 'FeeAcknowledged';
22
    const FEE_IDENTIFIER = 'FeeIdentifier';
23
    const HOLD_TYPE = 'HoldType';
24
    const INSTITUTION_ID = 'InstitutionID';
25
    const ITEM_IDENTIFIER = 'ItemIdentifier';
26
    const ITEM_LOCATION = 'ItemLocation';
27
    const ITEM_PROPERTIES = 'ItemProperties';
28
    const ITEM_TITLE = 'ItemTitle';
29
    const LOCATION = 'Location';
30
    const MESSAGE = 'Message';
31
    const NB_DATEDUE = 'NBDateDue';
32
    const NO_BLOCK = 'NoBlock';
33
    const PASSWORD_ALGORITHM = 'PasswordAlgorithm';
34
    const PATRON_IDENTIFIER = 'PatronIdentifier';
35
    const PATRON_PASSWORD = 'PatronPassword';
36
    const PAYMENT_AMOUNT = 'PaymentAmount';
37
    const PICKUP_LOCATION = 'PickupLocation';
38
    const SIP_LOGIN = 'SIPLogin';
39
    const SIP_PASSWORD = 'SIPPassword';
40
    const START = 'Start';
41
    const STATUS = 'Status';
42
    const TERMINAL_PASSWORD = 'TerminalPassword';
43
    const THIRD_PARTY = 'ThirdParty';
44
    const TRANSACTION_IDENTIFIER = 'TransactionIdentifier';
45
    const USERID_ALGORITHM = 'UserIdAlgorithm';
46
    const VERSION = 'Version';
47
    const WIDTH = 'Width';
48
49
    /** @var string request is built up here */
50
    private $msgBuild = '';
51
52
    /** @var bool tracks when a variable field is used to prevent further fixed fields */
53
    private $noFixed = false;
54
55
    /**
56
     * @var string terminator for requests. This should be just \r (0x0d) according to docs, but some vendors
57
     * require \r\n
58
     */
59
    private $msgTerminator = "\r\n";
60
61
    /** @var string variable length field terminator */
62
    private $fldTerminator = '|';
63
64
65
    private static $seq = -1;
66
67
    /**
68
     * This class automatically increments a static sequence number, but for testing its useful to have this
69
     * start at 0. This method allows it to be reset
70
     */
71 44
    public static function resetSequence()
72
    {
73 44
        self::$seq = -1;
74 44
    }
75
76
    /**
77
     * Derived class must implement this to build its SIP2 request
78
     */
79
    abstract public function getMessageString($withSeq = true, $withCrc = true): string;
80
81
82
    /**
83
     * Start building a new message
84
     * @param string $code
85
     */
86 20
    protected function newMessage($code)
87
    {
88
        /* resets the msgBuild variable to the value of $code, and clears the flag for fixed messages */
89 20
        $this->noFixed = false;
90 20
        $this->msgBuild = $code;
91 20
    }
92
93 18
    protected function addFixedOption($value, $len)
94
    {
95
        /* adds a fixed length option to the msgBuild IF no variable options have been added. */
96 18
        if ($this->noFixed) {
97
            //@codeCoverageIgnoreStart
98
            throw new \LogicException('Cannot add fixed options after variable options');
99
            //@codeCoverageIgnoreEnd
100
        }
101
102 18
        $this->msgBuild .= sprintf("%{$len}s", substr($value, 0, $len));
103 18
        return true;
104
    }
105
106 18
    protected function addVarOption($field, $value, $optional = false)
107
    {
108
        /* adds a variable length option to the message, and also prevents adding additional fixed fields */
109 18
        if ($optional == true && $value == '') {
110
            /* skipped */
111
            //$this->logger->debug("SIP2: Skipping optional field {$field}");
112
        } else {
113 18
            $this->noFixed = true; /* no more fixed for this message */
114 18
            $this->msgBuild .= $field . substr($value, 0, 255) . $this->fldTerminator;
115
        }
116 18
        return true;
117
    }
118
119 20
    protected function returnMessage($withSeq = true, $withCrc = true): string
120
    {
121
        /* Finalizes the message and returns it.  Message will remain in msgBuild until newMessage is called */
122 20
        if ($withSeq) {
123 20
            $this->msgBuild .= 'AY' . self::getSeqNumber();
124
        }
125 20
        if ($withCrc) {
126 20
            $this->msgBuild .= 'AZ';
127 20
            $this->msgBuild .= self::crc($this->msgBuild);
128
        }
129 20
        $this->msgBuild .= $this->msgTerminator;
130
131 20
        return $this->msgBuild;
132
    }
133
134
    /* Core local utility functions */
135
136 20
    protected static function getSeqNumber()
137
    {
138
        /* Get a sequence number for the AY field */
139
        /* valid numbers range 0-9 */
140 20
        self::$seq++;
141 20
        if (self::$seq > 9) {
142 1
            self::$seq = 0;
143
        }
144 20
        return self::$seq;
145
    }
146
}
147