Passed
Push — master ( 6e6484...b0e8a3 )
by
unknown
39s
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(), $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
     * @throws \Exception XML Parsing Exception
102
     * @date   2017-01-12
103
     * @param  \SimpleXMLElement         $root      Root XML Node
104
     * @param  array                    $arguments Array of Arguments to be added to XML Node
105
     * @return \SimpleXMLElement                    Resulting XML Tree
106
     */
107 5
    private function sxmlAddChildrenRecursive(\SimpleXMLElement $root, array $arguments) : \SimpleXMLElement
108
    {
109 5
        foreach ($arguments as $key => $value) {
110 4
            if (is_array($value)) {
111 2
                $child = new \SimpleXMLElement(sprintf('<%s></%s>', $key, $key));
112 2
                $this->sxmlAddChildrenRecursive($child, $value);
113 2
                $this->sxmlAppend($root, $child);
114
            } else {
115 4
                $root->addChild($key, $value);
116
            }
117
118
        }
119 5
        return $root;
120
    }
121
    /**
122
     * Builds The XML Request Body for the Your Membership API Call
123
     * @method buildXMLBody
124
     * @author PA
125
     * @date   2017-01-10
126
     * @param  string            $method    Your Membership API Function Name
127
     * @param  array             $arguments Your Membership Arguments
128
     * @return \SimpleXMLElement
129
     */
130 3
    public function buildXMLBody(string $method, array $arguments) : \SimpleXMLElement
131
    {
132 3
        $xml = $this->buildBasePayload(); // Common Envelope
133
134 3
        if ($this->isSessionRequiredForMethod($method)) {
135 3
            $xml = $this->addSessionIdToRequest($xml);
136
        }
137
138 3
        $callPayload = $this->createCallPayload($method, $arguments); // Specific API Call Envelope
139
140
        // Put Api call into common envelope
141 3
        $this->sxmlAppend($xml, $callPayload);
142
143 3
        return $xml;
144
    }
145
    /**
146
     * Builds a Guzzle Request Object
147
     * @method buildRequest
148
     * @author PA
149
     * @date   2017-01-11
150
     * @param  string        $method    YourMembership API Method
151
     * @param  array         $arguments YourMembership API Method Call Arguments
152
     * @return \GuzzleHttp\Psr7\Request            Guzzle Request Object
153
     */
154 2
    public function buildRequest(string $method, array $arguments) : \GuzzleHttp\Psr7\Request
155
    {
156 2
        $requestBody = $this->buildXMLBody($method, $arguments)->asXML();
157 2
        return new GuzzleRequest('POST', self::BASE_URL, ['Content-Type' => 'application/x-www-form-urlencoded; charset=UTF8'], $requestBody);
158
    }
159
160
    /**
161
     * Checks if Request Requires Session ID
162
     * @method isSessionRequiredForMethod
163
     * @author PA
164
     * @date   2017-01-10
165
     * @param  string                     $method YourMembership API Method
166
     * @return bool
167
     */
168 3
    public function isSessionRequiredForMethod(string $method) : bool
169
    {
170
        //TODO Add config Logic for what API Methods require Session ID
171 3
        return ($method != 'Session.Create');
172
    }
173
174
    /**
175
     * Helper for Deep Copy for of $from element into $to element for SimpleXML
176
     * @method sxmlAppend
177
     * @author PA
178
     * @date   2017-01-09
179
     * @param  \SimpleXMLElement $to
180
     * @param  \SimpleXMLElement $from
181
     * @return void
182
     */
183 5
    private function sxmlAppend(\SimpleXMLElement $to, \SimpleXMLElement $from)
184
    {
185 5
        $toDom = dom_import_simplexml($to);
186 5
        $fromDom = dom_import_simplexml($from);
187 5
        $toDom->appendChild($toDom->ownerDocument->importNode($fromDom, true));
188 5
    }
189
190
    /**
191
     * Adds the Session Variable to the given XML Request Payload
192
     * @method addSessionIdToRequest
193
     * @author PA
194
     * @date   2017-01-10
195
     * @param  \SimpleXMLElement                $requestXML Base Request XML Payload
196
     */
197 3
    private function addSessionIdToRequest(\SimpleXMLElement $requestXML) : \SimpleXMLElement
198
    {
199 3
        $requestXML->addChild('SessionID', self::$sessionId);
200 3
        return $requestXML;
201
    }
202
203
204
    /**
205
     * Setter Method for SessionID
206
     * @method setSessionId
207
     * @author PA
208
     * @date   2017-01-10
209
     * @param  string       $sessionId YourMembership Session ID
210
     */
211 2
    public static function setSessionId(string $sessionId)
212
    {
213 2
        self::$sessionId = $sessionId;
214 2
    }
215
216
    /**
217
     * Checks if we have an active session available
218
     * @method hasSession
219
     * @author PA
220
     * @date   2017-01-11
221
     * @return boolean
222
     */
223 1
    public function hasSession()
224
    {
225 1
        return !is_null(self::$sessionId);
226
    }
227
228
}
229