Passed
Pull Request — master (#40)
by Indy
01:55
created

FederatedAddress   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 173
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 50
dl 0
loc 173
rs 10
c 0
b 0
f 0
wmc 9

5 Methods

Rating   Name   Duplication   Size   Complexity  
A isValid() 0 3 1
A __construct() 0 37 1
A getNamedItemNodeValue() 0 18 4
A getNodeValue() 0 4 2
A isRuralDeliveryAddress() 0 3 1
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 Unit number for the address
46
     */
47
    public $NZUnit;
48
49
    /**
50
     * @var string String representing the RD number of this address, e.g RD 123. Required if the address type is rural
51
     */
52
    public $NZRuralDelivery;
53
54
    /**
55
     * @var string Optional name of the suburb for this city, e.g Te Aro
56
     */
57
    public $NZSuburb;
58
59
    /**
60
     * @var string Name of the town or city for this address, e.g Wellington
61
     */
62
    public $NZTownOrCity;
63
64
    /**
65
     * @var string Alphanumeric 4 digit string representing a postcode with leading zeroes, e.g 6011 or 0002
66
     */
67
    public $NZPostCode;
68
69
    /**
70
     * Constructor that sets the expected federated identity details based on a provided DOMDocument. The expected XML
71
     * structure for the DOMDocument is the following:
72
     *
73
     * <?xml version="1.0" encoding="UTF-8"?>
74
     * <p:Party
75
     *  xmlns:p="urn:oasis:names:tc:ciq:xpil:3"
76
     *  xmlns:a="urn:oasis:names:tc:ciq:xal:3">
77
     *     <a:Addresses>
78
     *          <a:Address Type="NZStandard" Usage="Residential" DataQualityType="Valid" ValidFrom="13/11/2012">
79
     *              <a:Locality>
80
     *                  <a:NameElement a:NameType="NZTownCity">Wellington</a:NameElement>
81
     *                  <a:NameElement a:NameType="NZSuburb">Kelburn</a:NameElement>
82
     *              </a:Locality>
83
     *              <a:Thoroughfare>
84
     *                  <a:NameElement a:NameType="NZNumberStreet">1 Main St</a:NameElement>
85
     *              </a:Thoroughfare>
86
     *              <a:Premises>
87
     *                  <a:NameElement a:NameType="NZUnit">14</a:NameElement>
88
     *              </a:Premises>
89
     *              <a:PostCode>
90
     *                  <a:Identifier Type="NZPostCode">1111</a:Identifier>
91
     *              </a:PostCode>
92
     *         </a:Address>
93
     *     </a:Addresses>
94
     * </p:Party>
95
     *
96
     * @param DOMDocument $identity
97
     */
98
    public function __construct(DOMDocument $identity)
99
    {
100
        parent::__construct();
101
102
        $xpath = new DOMXPath($identity);
103
        $xpath->registerNamespace('p', 'urn:oasis:names:tc:ciq:xpil:3');
104
        $xpath->registerNamespace('a', 'urn:oasis:names:tc:ciq:xal:3');
105
106
        // Record info
107
        $this->DataQuality = $this->getNamedItemNodeValue($xpath, '/p:Party/a:Addresses/a:Address', 'DataQualityType');
108
        $this->VerificationDate = $this->getNamedItemNodeValue($xpath, '/p:Party/a:Addresses/a:Address', 'ValidFrom');
109
110
        // Address info
111
        $this->AddressType = $this->getNamedItemNodeValue($xpath, '/p:Party/a:Addresses/a:Address', 'Type');
112
        $this->NZNumberStreet = $this->getNodeValue(
113
            $xpath,
114
            "/p:Party/a:Addresses/a:Address/a:Thoroughfare/a:NameElement[@a:NameType='NZNumberStreet']"
115
        );
116
        $this->NZUnit = $this->getNodeValue(
117
            $xpath,
118
            "/p:Party/a:Addresses/a:Address/a:Premises/a:NameElement[@a:NameType='NZUnit']"
119
        );
120
        $this->NZRuralDelivery = $this->getNodeValue(
121
            $xpath,
122
            "/p:Party/a:Addresses/a:Address/a:RuralDelivery/a:Identifier[@Type='NZRuralDelivery']"
123
        );
124
        $this->NZSuburb = $this->getNodeValue(
125
            $xpath,
126
            "/p:Party/a:Addresses/a:Address/a:Locality/a:NameElement[@a:NameType='NZSuburb']"
127
        );
128
        $this->NZTownOrCity = $this->getNodeValue(
129
            $xpath,
130
            "/p:Party/a:Addresses/a:Address/a:Locality/a:NameElement[@a:NameType='NZTownCity']"
131
        );
132
        $this->NZPostCode = $this->getNodeValue(
133
            $xpath,
134
            "/p:Party/a:Addresses/a:Address/a:PostCode/a:Identifier[@Type='NZPostCode']"
135
        );
136
    }
137
138
    /**
139
     * @return bool
140
     */
141
    public function isRuralDeliveryAddress()
142
    {
143
        return $this->AddressType === self::TYPE_RURAL_DELIVERY;
144
    }
145
146
    /**
147
     * @return bool
148
     */
149
    public function isValid()
150
    {
151
        return true;
152
    }
153
154
    /**
155
     * @param DOMXPath $xpath The DOMXPath object to carry out the query on
156
     * @param string $query The XPath query to find the relevant node
157
     * @param string $namedAttr The named attribute to retrieve from the XPath query
158
     * @return string|null Either the value from the named item, or null if no item exists
159
     */
160
    private function getNamedItemNodeValue(DOMXPath $xpath, $query, $namedAttr)
161
    {
162
        $query = $xpath->query($query);
163
        $value = null;
164
165
        if ($query->length > 0) {
166
            $item = $query->item(0);
167
168
            if ($item->hasAttributes()) {
169
                $value = $item->attributes->getNamedItem($namedAttr);
170
171
                if (strlen($value->nodeValue) > 0) {
172
                    $value = $value->nodeValue;
173
                }
174
            }
175
        }
176
177
        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...
178
    }
179
180
    /**
181
     * @param DOMXPath $xpath The DOMXPath object to carry out the query on
182
     * @param string $query The XPath query to find the relevant node
183
     * @return string|null Either the first matching node's value (there should only ever be one), or null if none found
184
     */
185
    private function getNodeValue(DOMXPath $xpath, $query)
186
    {
187
        $query = $xpath->query($query);
188
        return ($query->length > 0 ? $query->item(0)->nodeValue : null);
189
    }
190
}
191