Completed
Pull Request — master (#40)
by Indy
09:33
created

FederatedAddress::isValid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
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
        parent::__construct();
92
93
        $xpath = new DOMXPath($identity);
94
        $xpath->registerNamespace('p', 'urn:oasis:names:tc:ciq:xpil:3');
95
        $xpath->registerNamespace('a', 'urn:oasis:names:tc:ciq:xal:3');
96
97
        // Record info
98
        $this->DataQuality = $this->getNamedItemNodeValue($xpath, '/p:Party/a:Addresses/a:Address', 'DataQualityType');
99
        $this->VerificationDate = $this->getNamedItemNodeValue($xpath, '/p:Party/a:Addresses/a:Address', 'ValidFrom');
100
101
        // Address info
102
        $this->AddressType = $this->getNamedItemNodeValue($xpath, '/p:Party/a:Addresses/a:Address', 'Type');
103
        $this->NZNumberStreet = $this->getNodeValue(
104
            $xpath,
105
            "/p:Party/a:Addresses/a:Address/a:Thoroughfare/a:NameElement[@a:NameType='NZNumberStreet']"
106
        );
107
        $this->NZRuralDelivery = $this->getNodeValue(
108
            $xpath,
109
            "/p:Party/a:Addresses/a:Address/a:RuralDelivery/a:Identifier[@Type='NZRuralDelivery']"
110
        );
111
        $this->NZSuburb = $this->getNodeValue(
112
            $xpath,
113
            "/p:Party/a:Addresses/a:Address/a:Locality/a:NameElement[@a:NameType='NZSuburb']"
114
        );
115
        $this->NZTownOrCity = $this->getNodeValue(
116
            $xpath,
117
            "/p:Party/a:Addresses/a:Address/a:Locality/a:NameElement[@a:NameType='NZTownCity']"
118
        );
119
        $this->NZPostCode = $this->getNodeValue(
120
            $xpath,
121
            "/p:Party/a:Addresses/a:Address/a:PostCode/a:Identifier[@Type='NZPostCode']"
122
        );
123
    }
124
125
    /**
126
     * @return bool
127
     */
128
    public function isRuralDeliveryAddress()
129
    {
130
        return $this->AddressType === self::TYPE_RURAL_DELIVERY;
131
    }
132
133
    /**
134
     * @return bool
135
     */
136
    public function isValid()
137
    {
138
        return true;
139
    }
140
141
    /**
142
     * @param DOMXPath $xpath The DOMXPath object to carry out the query on
143
     * @param string $query The XPath query to find the relevant node
144
     * @param string $namedAttr The named attribute to retrieve from the XPath query
145
     * @return string|null Either the value from the named item, or null if no item exists
146
     */
147
    private function getNamedItemNodeValue(DOMXPath $xpath, $query, $namedAttr)
148
    {
149
        $query = $xpath->query($query);
150
        $value = null;
151
152
        if ($query->length > 0) {
153
            $item = $query->item(0);
154
155
            if ($item->hasAttributes()) {
156
                $value = $item->attributes->getNamedItem($namedAttr);
157
158
                if (strlen($value->nodeValue) > 0) {
159
                    $value = $value->nodeValue;
160
                }
161
            }
162
        }
163
164
        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...
165
    }
166
167
    /**
168
     * @param DOMXPath $xpath The DOMXPath object to carry out the query on
169
     * @param string $query The XPath query to find the relevant node
170
     * @return string|null Either the first matching node's value (there should only ever be one), or null if none found
171
     */
172
    private function getNodeValue(DOMXPath $xpath, $query)
173
    {
174
        $query = $xpath->query($query);
175
        return ($query->length > 0 ? $query->item(0)->nodeValue : null);
176
    }
177
}
178