Passed
Pull Request — master (#5)
by Petr
04:44 queued 02:20
created

Request::sxmlAddChildrenRecursive()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 9
nc 3
nop 2
crap 3
1
<?php
2
3
namespace P2A\YourMembership\Core;
4
5
use GuzzleHttp\Psr7\Request as GuzzleRequest;
6
use P2A\YourMembership\Exceptions\YourMembershipRequestException;
7
8
class Request
9
{
10
11
    /**
12
     * Base URL
13
     * @var string
14
     */
15
    const BASE_URL = 'https://api.yourmembership.com';
16
    const API_VERSION = '2.25';
17
18
    /**
19
     * Session ID use for YourMembership API
20
     * @var string
21
     */
22
    private static $sessionId = null;
23
    /**
24
     * Call Counter for Your Membership for a given session
25
     * @var integer
26
     */
27
    public static $callId = 0;
28
    /**
29
     * API Key Used for YourMembership API
30
     * @var string
31
     */
32
    private $apiKey;
33
    /**
34
     * Sa Passcode is a supplementary API key used for YourMembership API
35
     * @var string
36
     */
37
    private $saPasscode;
38
39
40 6
    public function __construct(string $apiKey, string $saPasscode)
41
    {
42 6
        $this->apiKey = $apiKey;
43 6
        $this->saPasscode = $saPasscode;
44 6
    }
45
46
    /**
47
     * Create the Base Envelope for an API call to YourMembership
48
     * @method buildBasePayload
49
     * @author PA
50
     * @date   2017-01-09
51
     * @return \SimpleXMLElement  XML Envelope with necessary credential parameters
52
     */
53 4
    public function buildBasePayload() : \SimpleXMLElement
54
    {
55
        /*
56
            <YourMembership>
57
            <Version>2.25</Version>
58
            <ApiKey>3D638C5F-CCE2-4638-A2C1-355FA7BBC917</ApiKey>
59
            <CallID>001</CallID>
60
            <SaPasscode>************</SaPasscode>
61
            </YourMembership>
62
        */
63 4
        $xml = new \SimpleXMLElement('<YourMembership></YourMembership>');
64 4
        $xml->addChild('Version', self::API_VERSION);
65 4
        $xml->addChild('ApiKey', $this->apiKey);
66 4
        $xml->addChild('CallID', self::$callId);
67 4
        $xml->addChild('SaPasscode', $this->saPasscode);
68
69 4
        return $xml;
70
    }
71
72
    /**
73
     * Generates the XML for a API method call within
74
     * @method createCallPayload
75
     * @author PA
76
     * @throws YourMembershipRequestException
77
     * @date   2017-01-09
78
     * @param  string            $method    YourMembership API Function Name
79
     * @param  array             $arguments Array of Arguments to be passed as part of the YourMembership "Call"
80
     * @return \SimpleXMLElement
81
     */
82 5
    public function createCallPayload(string $method, array $arguments) : \SimpleXMLElement
83
    {
84
        //Create Call Node
85 5
        $call = new \SimpleXMLElement('<Call> </Call>');
86 5
        $call->addAttribute('Method', $method);
87
88
        //Add Arguments to the Call Node
89
        try {
90 5
            $call = $this->sxmlAddChildrenRecursive($call,$arguments);
91 1
        } catch(\Exception $e) {
92 1
            throw new YourMembershipRequestException($e->getMessage(), $e->getCode(), $method, $arguments, $e);
93
        }
94 4
        return $call;
95
    }
96
    /**
97
     * Recursively builds the array into a XML Tree
98
     * //NOTE Child arrays must be associative
99
     * @method sxmlAddChildrenRecursive
100
     * @author PA
101
     * @date   2017-01-12
102
     * @param  SimpleXMLElement         $root      Root XML Node
103
     * @param  array                    $arguments Array of Arguments to be added to XML Node
104
     * @return SimpleXMLElement                    Resulting XML Tree
105
     */
106 5
    private function sxmlAddChildrenRecursive(\SimpleXMLElement $root, array $arguments) : \SimpleXMLElement
107
    {
108 5
        foreach ($arguments as $key => $value) {
109 4
            if (is_array($value)) {
110 2
                $child = new \SimpleXMLElement(sprintf('<%s></%s>',$key, $key));
111 2
                $this->sxmlAddChildrenRecursive($child, $value);
112 2
                $this->sxmlAppend($root,$child);
113
            } else {
114 4
                $root->addChild($key, $value);
115
            }
116
117
        }
118 5
        return $root;
119
    }
120
    /**
121
     * Builds The XML Request Body for the Your Membership API Call
122
     * @method buildXMLBody
123
     * @author PA
124
     * @date   2017-01-10
125
     * @param  string            $method    Your Membership API Function Name
126
     * @param  array             $arguments Your Membership Arguments
127
     * @return \SimpleXMLElement
128
     */
129 3
    public function buildXMLBody(string $method, array $arguments) : \SimpleXMLElement
130
    {
131 3
        $xml = $this->buildBasePayload(); // Common Envelope
132
133 3
        if ($this->isSessionRequiredForMethod($method)) {
134 3
            $xml = $this->addSessionIdToRequest($xml);
135
        }
136
137 3
        $callPayload = $this->createCallPayload($method, $arguments); // Specific API Call Envelope
138
139
        // Put Api call into common envelope
140 3
        $this->sxmlAppend($xml, $callPayload);
141
142 3
        return $xml;
143
    }
144
    /**
145
     * Builds a Guzzle Request Object
146
     * @method buildRequest
147
     * @author PA
148
     * @date   2017-01-11
149
     * @param  string        $method    YourMembership API Method
150
     * @param  array         $arguments YourMembership API Method Call Arguments
151
     * @return \GuzzleHttp\Psr7\Request            Guzzle Request Object
152
     */
153 2
    public function buildRequest(string $method, array $arguments) : \GuzzleHttp\Psr7\Request
154
    {
155 2
        $requestBody = $this->buildXMLBody($method, $arguments)->asXML();
156 2
        return new GuzzleRequest('POST', self::BASE_URL, ['Content-Type' => 'application/x-www-form-urlencoded; charset=UTF8'], $requestBody);
157
    }
158
159
    /**
160
     * Checks if Request Requires Session ID
161
     * @method isSessionRequiredForMethod
162
     * @author PA
163
     * @date   2017-01-10
164
     * @param  string                     $method YourMembership API Method
165
     * @return bool
166
     */
167 3
    public function isSessionRequiredForMethod(string $method) : bool
168
    {
169
        //TODO Add config Logic for what API Methods require Session ID
170 3
        return ($method != 'Session.Create');
171
    }
172
173
    /**
174
     * Helper for Deep Copy for of $from element into $to element for SimpleXML
175
     * @method sxmlAppend
176
     * @author PA
177
     * @date   2017-01-09
178
     * @param  \SimpleXMLElement $to
179
     * @param  \SimpleXMLElement $from
180
     * @return void
181
     */
182 5
    private function sxmlAppend(\SimpleXMLElement $to, \SimpleXMLElement $from) {
183 5
        $toDom = dom_import_simplexml($to);
184 5
        $fromDom = dom_import_simplexml($from);
185 5
        $toDom->appendChild($toDom->ownerDocument->importNode($fromDom, true));
186 5
    }
187
188
    /**
189
     * Adds the Session Variable to the given XML Request Payload
190
     * @method addSessionIdToRequest
191
     * @author PA
192
     * @date   2017-01-10
193
     * @param  \SimpleXMLElement                $requestXML Base Request XML Payload
194
     */
195 3
    private function addSessionIdToRequest(\SimpleXMLElement $requestXML) : \SimpleXMLElement
196
    {
197 3
        $requestXML->addChild('SessionID', self::$sessionId);
198 3
        return $requestXML;
199
    }
200
201
202
    /**
203
     * Setter Method for SessionID
204
     * @method setSessionId
205
     * @author PA
206
     * @date   2017-01-10
207
     * @param  string       $sessionId YourMembership Session ID
208
     */
209 2
    public static function setSessionId(string $sessionId)
210
    {
211 2
        self::$sessionId = $sessionId;
212 2
    }
213
214
    /**
215
     * Checks if we have an active session available
216
     * @method hasSession
217
     * @author PA
218
     * @date   2017-01-11
219
     * @return boolean
220
     */
221 1
    public function hasSession()
222
    {
223 1
        return !is_null(self::$sessionId);
224
    }
225
226
}
227