Completed
Pull Request — master (#40)
by Indy
06:50 queued 04:59
created

FederatedAddress::getNamedItemNodeValue()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 4
nop 3
dl 0
loc 18
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\RealMe\Model;
4
5
use DOMDocument;
6
use DOMXPath;
7
use SilverStripe\View\ViewableData;
8
9
/**
10
 * Class FederatedAddress
11
 *
12
 * Contains data to describe the address returned as part of an identity.
13
 *
14
 * @see https://developers.realme.govt.nz/how-realme-works/verified-address-data/
15
 */
16
class FederatedAddress extends ViewableData
17
{
18
    /**
19
     * Types of addresses
20
     */
21
    const TYPE_STANDARD = 'NZStandard';
22
    const TYPE_RURAL_DELIVERY = 'NZRuralDelivery';
23
24
    /**
25
     * @var string The type of address, either NZStandard or NZRuralDelivery
26
     */
27
    public $AddressType;
28
29
    /**
30
     * @var string Date when this address was marked as verified
31
     */
32
    public $VerificationDate;
33
34
    /**
35
     * @var string Undocumented in RealMe messaging spec, generally describes the quality of the address information
36
     */
37
    public $DataQuality;
38
39
    /**
40
     * @var string Street number, suffix, and the name of the street, e.g 103 Courtenay Place
41
     */
42
    public $NZNumberStreet;
43
44
    /**
45
     * @var string String representing the RD number of this address, e.g RD 123. Required if the address type is rural
46
     */
47
    public $NZRuralDelivery;
48
49
    /**
50
     * @var string Optional name of the suburb for this city, e.g Te Aro
51
     */
52
    public $NZSuburb;
53
54
    /**
55
     * @var string Name of the town or city for this address, e.g Wellington
56
     */
57
    public $NZTownOrCity;
58
59
    /**
60
     * @var string Alphanumeric 4 digit string representing a postcode with leading zeroes, e.g 6011 or 0002
61
     */
62
    public $NZPostCode;
63
64
    /**
65
     * Constructor that sets the expected federated identity details based on a provided DOMDocument. The expected XML
66
     * structure for the DOMDocument is the following:
67
     *
68
     * <?xml version="1.0" encoding="UTF-8"?>
69
     * <p:Party
70
     *  xmlns:p="urn:oasis:names:tc:ciq:xpil:3"
71
     *  xmlns:a="urn:oasis:names:tc:ciq:xal:3">
72
     *     <a:Addresses>
73
     *          <a:Address Type="NZStandard" Usage="Residential" DataQualityType="Valid" ValidFrom="13/11/2012">
74
     *              <a:Locality>
75
     *                  <a:NameElement a:NameType="NZTownCity">Wellington</a:NameElement>
76
     *                  <a:NameElement a:NameType="NZSuburb">Kelburn</a:NameElement>
77
     *              </a:Locality>
78
     *              <a:Thoroughfare>
79
     *                  <a:NameElement a:NameType="NZNumberStreet">1 Main St</a:NameElement>
80
     *              </a:Thoroughfare>
81
     *              <a:PostCode>
82
     *                  <a:Identifier Type="NZPostCode">1111</a:Identifier>
83
     *              </a:PostCode>
84
     *         </a:Address>
85
     *     </a:Addresses>
86
     * </p:Party>
87
     *
88
     * @param DOMDocument $identity
89
     */
90
    public function __construct(DOMDocument $identity)
91
    {
92
        parent::__construct();
93
94
        $xpath = new DOMXPath($identity);
95
        $xpath->registerNamespace('p', 'urn:oasis:names:tc:ciq:xpil:3');
96
        $xpath->registerNamespace('a', 'urn:oasis:names:tc:ciq:xal:3');
97
98
        // Record info
99
        $this->DataQuality = $this->getNamedItemNodeValue($xpath, '/p:Party/a:Addresses/a:Address', 'DataQualityType');
100
        $this->VerificationDate = $this->getNamedItemNodeValue($xpath, '/p:Party/a:Addresses/a:Address', 'ValidFrom');
101
102
        // Address info
103
        $this->AddressType = $this->getNamedItemNodeValue($xpath, '/p:Party/a:Addresses/a:Address', 'Type');
104
        $this->NZNumberStreet = $this->getNodeValue(
105
            $xpath,
106
            "/p:Party/a:Addresses/a:Address/a:Thoroughfare/a:NameElement[@a:NameType='NZNumberStreet']"
107
        );
108
        $this->NZRuralDelivery = $this->getNodeValue(
109
            $xpath,
110
            "/p:Party/a:Addresses/a:Address/a:RuralDelivery/a:Identifier[@Type='NZRuralDelivery']"
111
        );
112
        $this->NZSuburb = $this->getNodeValue(
113
            $xpath,
114
            "/p:Party/a:Addresses/a:Address/a:Locality/a:NameElement[@a:NameType='NZSuburb']"
115
        );
116
        $this->NZTownOrCity = $this->getNodeValue(
117
            $xpath,
118
            "/p:Party/a:Addresses/a:Address/a:Locality/a:NameElement[@a:NameType='NZTownCity']"
119
        );
120
        $this->NZPostCode = $this->getNodeValue(
121
            $xpath,
122
            "/p:Party/a:Addresses/a:Address/a:PostCode/a:Identifier[@Type='NZPostCode']"
123
        );
124
    }
125
126
    /**
127
     * @return bool
128
     */
129
    public function isRuralDeliveryAddress()
130
    {
131
        return $this->AddressType === self::TYPE_RURAL_DELIVERY;
132
    }
133
134
    /**
135
     * @return bool
136
     */
137
    public function isValid()
138
    {
139
        return true;
140
    }
141
142
    /**
143
     * @param DOMXPath $xpath The DOMXPath object to carry out the query on
144
     * @param string $query The XPath query to find the relevant node
145
     * @param string $namedAttr The named attribute to retrieve from the XPath query
146
     * @return string|null Either the value from the named item, or null if no item exists
147
     */
148
    private function getNamedItemNodeValue(DOMXPath $xpath, $query, $namedAttr)
149
    {
150
        $query = $xpath->query($query);
151
        $value = null;
152
153
        if ($query->length > 0) {
154
            $item = $query->item(0);
155
156
            if ($item->hasAttributes()) {
157
                $value = $item->attributes->getNamedItem($namedAttr);
158
159
                if (strlen($value->nodeValue) > 0) {
160
                    $value = $value->nodeValue;
161
                }
162
            }
163
        }
164
165
        return $value;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $value also could return the type DOMNode which is incompatible with the documented return type null|string.
Loading history...
166
    }
167
168
    /**
169
     * @param DOMXPath $xpath The DOMXPath object to carry out the query on
170
     * @param string $query The XPath query to find the relevant node
171
     * @return string|null Either the first matching node's value (there should only ever be one), or null if none found
172
     */
173
    private function getNodeValue(DOMXPath $xpath, $query)
174
    {
175
        $query = $xpath->query($query);
176
        return ($query->length > 0 ? $query->item(0)->nodeValue : null);
177
    }
178
}
179