Issues (41)

lib/OfxParser/Ofx.php (4 issues)

1
<?php declare(strict_types=1);
2
3
namespace OfxParser;
4
5
use SimpleXMLElement;
6
use OfxParser\Utils;
7
use OfxParser\Entities\AccountInfo;
8
use OfxParser\Entities\BankAccount;
9
use OfxParser\Entities\Institute;
10
use OfxParser\Entities\SignOn;
11
use OfxParser\Entities\Statement;
12
use OfxParser\Entities\Status;
13
use OfxParser\Entities\Transaction;
14
15
/**
16
 * The OFX object
17
 *
18
 * Heavily refactored from Guillaume Bailleul's grimfor/ofxparser
19
 *
20
 * Second refactor by Oliver Lowe to unify the API across all
21
 * OFX data-types.
22
 *
23
 * Based on Andrew A Smith's Ruby ofx-parser
24
 *
25
 * @author Guillaume BAILLEUL <[email protected]>
26
 * @author James Titcumb <[email protected]>
27
 * @author Oliver Lowe <[email protected]>
28
 */
29
class Ofx
30
{
31
    /**
32
     * @var Header[]
33
     */
34
    public $header = [];
35
36
    /**
37
     * @var SignOn
38
     */
39
    public $signOn;
40
41
    /**
42
     * @var AccountInfo[]
43
     */
44
    public $signupAccountInfo;
45
46
    /**
47
     * @var BankAccount[]
48
     */
49
    public $bankAccounts = [];
50
51
    /**
52
     * Only populated if there is only one bank account
53
     * @var BankAccount|null
54
     * @deprecated This will be removed in future versions
55
     */
56
    public $bankAccount;
57
58
    /**
59
     * @param SimpleXMLElement $xml
60
     * @throws \Exception
61
     */
62 3
    public function __construct(SimpleXMLElement $xml)
63
    {
64 3
        $this->signOn = $this->buildSignOn($xml->SIGNONMSGSRSV1->SONRS);
65 3
        $this->signupAccountInfo = $this->buildAccountInfo($xml->SIGNUPMSGSRSV1->ACCTINFOTRNRS);
66
67 3
        if (property_exists($xml, 'BANKMSGSRSV1') && $xml->BANKMSGSRSV1 !== null) {
68 3
            $this->bankAccounts = $this->buildBankAccounts($xml);
69
        } elseif (property_exists($xml, 'CREDITCARDMSGSRSV1') && $xml->CREDITCARDMSGSRSV1 !== null) {
70
            $this->bankAccounts = $this->buildCreditAccounts($xml);
71
        }
72
73
        // Set a helper if only one bank account
74 3
        if (count($this->bankAccounts) === 1) {
75 2
            $this->bankAccount = $this->bankAccounts[0];
0 ignored issues
show
Deprecated Code introduced by
The property OfxParser\Ofx::$bankAccount has been deprecated: This will be removed in future versions ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

75
            /** @scrutinizer ignore-deprecated */ $this->bankAccount = $this->bankAccounts[0];

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
76
        }
77 3
    }
78
79
    /**
80
     * Get the transactions that have been processed
81
     *
82
     * @return \OfxParser\Entities\Transaction[]
83
     * @deprecated This will be removed in future versions
84
     */
85
    public function getTransactions(): array
86
    {
87
        return $this->bankAccount->statement->transactions;
0 ignored issues
show
Deprecated Code introduced by
The property OfxParser\Ofx::$bankAccount has been deprecated: This will be removed in future versions ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

87
        return /** @scrutinizer ignore-deprecated */ $this->bankAccount->statement->transactions;

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
88
    }
89
90
    /**
91
     * @param array $header
92
     * @return Ofx
93
     */
94
    public function buildHeader(array $header): self
95
    {
96
        $this->header = $header;
97
98
        return $this;
99
    }
100
101
    /**
102
     * @param SimpleXMLElement $xml
103
     * @return \OfxParser\Entities\SignOn
104
     * @throws \Exception
105
     */
106 3
    protected function buildSignOn(SimpleXMLElement $xml): \OfxParser\Entities\SignOn
107
    {
108 3
        $signOn = new SignOn();
109 3
        $signOn->status = $this->buildStatus($xml->STATUS);
110 3
        $signOn->date = Utils::createDateTimeFromStr($xml->DTSERVER, true);
111 3
        $signOn->language = $xml->LANGUAGE;
112
113 3
        $signOn->institute = new Institute();
114 3
        $signOn->institute->name = $xml->FI->ORG;
115 3
        $signOn->institute->id = $xml->FI->FID;
116
117 3
        return $signOn;
118
    }
119
120
    /**
121
     * @param SimpleXMLElement|null $xml
122
     * @return array AccountInfo
123
     */
124 3
    private function buildAccountInfo(SimpleXMLElement $xml = null): array
125
    {
126 3
        if (null === $xml) {
127 3
            return [];
128
        }
129
130
        if (!(property_exists($xml, 'ACCTINFO') && $xml->ACCTINFO !== null)) {
131
            return [];
132
        }
133
134
        $accounts = [];
135
        foreach ($xml->ACCTINFO as $account) {
136
            $accountInfo = new AccountInfo();
137
            $accountInfo->desc = $account->DESC;
138
            $accountInfo->number = $account->ACCTID;
139
            $accounts[] = $accountInfo;
140
        }
141
142
        return $accounts;
143
    }
144
145
    /**
146
     * @param SimpleXMLElement $xml
147
     * @throws \Exception
148
     * @return \OfxParser\Entities\BankAccount[]
149
     */
150
    private function buildCreditAccounts(SimpleXMLElement $xml): array
151
    {
152
        // Loop through the bank accounts
153
        $bankAccounts = [];
154
155
        foreach ($xml->CREDITCARDMSGSRSV1->CCSTMTTRNRS as $accountStatement) {
156
            $bankAccounts[] = $this->buildCreditAccount($accountStatement);
0 ignored issues
show
It seems like $accountStatement can also be of type null; however, parameter $xml of OfxParser\Ofx::buildCreditAccount() does only seem to accept SimpleXMLElement, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

156
            $bankAccounts[] = $this->buildCreditAccount(/** @scrutinizer ignore-type */ $accountStatement);
Loading history...
157
        }
158
        return $bankAccounts;
159
    }
160
161
    /**
162 3
     * @param SimpleXMLElement $xml
163
     * @throws \Exception
164
     * @return \OfxParser\Entities\BankAccount[]
165 3
     */
166 3
    private function buildBankAccounts(SimpleXMLElement $xml): array
167 3
    {
168 3
        // Loop through the bank accounts
169
        $bankAccounts = [];
170
        foreach ($xml->BANKMSGSRSV1->STMTTRNRS as $accountStatement) {
171 3
            foreach ($accountStatement->STMTRS as $statementResponse) {
172
                $bankAccounts[] = $this->buildBankAccount($accountStatement->TRNUID, $statementResponse);
0 ignored issues
show
It seems like $statementResponse can also be of type null; however, parameter $statementResponse of OfxParser\Ofx::buildBankAccount() does only seem to accept SimpleXMLElement, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

172
                $bankAccounts[] = $this->buildBankAccount($accountStatement->TRNUID, /** @scrutinizer ignore-type */ $statementResponse);
Loading history...
173
            }
174
        }
175
        return $bankAccounts;
176
    }
177
178
    /**
179
     * @param string $transactionUid
180 3
     * @param SimpleXMLElement $statementResponse
181
     * @throws \Exception
182 3
     * @return \OfxParser\Entities\BankAccount
183 3
     */
184 3
    private function buildBankAccount(?\SimpleXMLElement $transactionUid, SimpleXMLElement $statementResponse): \OfxParser\Entities\BankAccount
185 3
    {
186 3
        $bankAccount = new BankAccount();
187 3
        $bankAccount->transactionUid = $transactionUid;
188 3
        $bankAccount->agencyNumber = $statementResponse->BANKACCTFROM->BRANCHID;
189 3
        $bankAccount->accountNumber = $statementResponse->BANKACCTFROM->ACCTID;
190 3
        $bankAccount->routingNumber = $statementResponse->BANKACCTFROM->BANKID;
191 3
        $bankAccount->accountType = $statementResponse->BANKACCTFROM->ACCTTYPE;
192
        $bankAccount->balance = $statementResponse->LEDGERBAL->BALAMT;
193
        $bankAccount->balanceDate = Utils::createDateTimeFromStr(
194 3
            $statementResponse->LEDGERBAL->DTASOF,
195 3
            true
196
        );
197 3
198 3
        $bankAccount->statement = new Statement();
199
        $bankAccount->statement->currency = $statementResponse->CURDEF;
200
201 3
        $bankAccount->statement->startDate = Utils::createDateTimeFromStr(
202 3
            $statementResponse->BANKTRANLIST->DTSTART
203
        );
204
205 3
        $bankAccount->statement->endDate = Utils::createDateTimeFromStr(
206 3
            $statementResponse->BANKTRANLIST->DTEND
207
        );
208
209 3
        $bankAccount->statement->transactions = $this->buildTransactions(
210
            $statementResponse->BANKTRANLIST->STMTTRN
211
        );
212
213
        return $bankAccount;
214
    }
215
216
    /**
217
     * @param SimpleXMLElement $xml
218
     * @throws \Exception
219
     * @return \OfxParser\Entities\BankAccount
220
     */
221
    private function buildCreditAccount(SimpleXMLElement $xml): \OfxParser\Entities\BankAccount
222
    {
223
        $nodeName = 'CCACCTFROM';
224
        if (!isset($xml->CCSTMTRS->$nodeName)) {
225
            $nodeName = 'BANKACCTFROM';
226
        }
227
228
        $creditAccount = new BankAccount();
229
        $creditAccount->transactionUid = $xml->TRNUID;
230
        $creditAccount->agencyNumber = $xml->CCSTMTRS->$nodeName->BRANCHID;
231
        $creditAccount->accountNumber = $xml->CCSTMTRS->$nodeName->ACCTID;
232
        $creditAccount->routingNumber = $xml->CCSTMTRS->$nodeName->BANKID;
233
        $creditAccount->accountType = $xml->CCSTMTRS->$nodeName->ACCTTYPE;
234
        $creditAccount->balance = $xml->CCSTMTRS->LEDGERBAL->BALAMT;
235
        $creditAccount->balanceDate = Utils::createDateTimeFromStr($xml->CCSTMTRS->LEDGERBAL->DTASOF, true);
236
237
        $creditAccount->statement = new Statement();
238
        $creditAccount->statement->currency = $xml->CCSTMTRS->CURDEF;
239
        $creditAccount->statement->startDate = Utils::createDateTimeFromStr($xml->CCSTMTRS->BANKTRANLIST->DTSTART);
240
        $creditAccount->statement->endDate = Utils::createDateTimeFromStr($xml->CCSTMTRS->BANKTRANLIST->DTEND);
241
        $creditAccount->statement->transactions = $this->buildTransactions($xml->CCSTMTRS->BANKTRANLIST->STMTTRN);
242
243
        return $creditAccount;
244
    }
245
246
    /**
247 3
     * @param SimpleXMLElement $transactions
248
     * @throws \Exception
249 3
     * @return \OfxParser\Entities\Transaction[]
250 3
     */
251 3
    private function buildTransactions(SimpleXMLElement $transactions): array
252 3
    {
253 3
        $return = [];
254 3
        foreach ($transactions as $t) {
255 2
            $transaction = new Transaction();
256
            $transaction->type = (string)$t->TRNTYPE;
257 3
            $transaction->date = Utils::createDateTimeFromStr($t->DTPOSTED);
258 3
            if ('' !== (string)$t->DTUSER) {
259 3
                $transaction->userInitiatedDate = Utils::createDateTimeFromStr($t->DTUSER);
260 3
            }
261 3
            $transaction->amount = Utils::createAmountFromStr($t->TRNAMT);
262 3
            $transaction->uniqueId = (string)$t->FITID;
263 3
            $transaction->name = (string)$t->NAME;
264
            $transaction->memo = (string)$t->MEMO;
265
            $transaction->sic = $t->SIC;
266 3
            $transaction->checkNumber = $t->CHECKNUM;
267
            $return[] = $transaction;
268
        }
269
270
        return $return;
271
    }
272
273 3
    /**
274
     * @param SimpleXMLElement $xml
275 3
     * @return \OfxParser\Entities\Status
276 3
     */
277 3
    private function buildStatus(SimpleXMLElement $xml): \OfxParser\Entities\Status
278 3
    {
279
        $status = new Status();
280 3
        $status->code = $xml->CODE;
281
        $status->severity = $xml->SEVERITY;
282
        $status->message = $xml->MESSAGE;
283
284
        return $status;
285
    }
286
}
287