| 1 | <?php |
||
| 2 | |||
| 3 | namespace Dynamic\Foxy\Parser\Foxy; |
||
| 4 | |||
| 5 | use Dynamic\Foxy\Model\FoxyHelper; |
||
| 6 | use SilverStripe\Core\Config\Configurable; |
||
| 7 | use SilverStripe\Core\Injector\Injectable; |
||
| 8 | use SilverStripe\ORM\ArrayList; |
||
| 9 | use SilverStripe\ORM\ValidationException; |
||
| 10 | use SilverStripe\View\ArrayData; |
||
| 11 | |||
| 12 | /** |
||
| 13 | * Class Transaction |
||
| 14 | * @package Dynamic\Foxy\Parser\Foxy |
||
| 15 | */ |
||
| 16 | class Transaction |
||
| 17 | { |
||
| 18 | use Injectable; |
||
| 19 | use Configurable; |
||
| 20 | |||
| 21 | /** |
||
| 22 | * @var string Encrypted response from Foxy |
||
| 23 | */ |
||
| 24 | private $encrypted_data; |
||
| 25 | |||
| 26 | /** |
||
| 27 | * @var "Foxy.io transaction xml record" |
||
|
0 ignored issues
–
show
Documentation
Bug
introduced
by
Loading history...
|
|||
| 28 | */ |
||
| 29 | private $transaction; |
||
| 30 | |||
| 31 | /** |
||
| 32 | * @var ArrayData |
||
| 33 | */ |
||
| 34 | private $transaction_data; |
||
| 35 | |||
| 36 | /** |
||
| 37 | * @var ArrayList |
||
| 38 | */ |
||
| 39 | private $discount_data; |
||
| 40 | |||
| 41 | /** |
||
| 42 | * @var ArrayList |
||
| 43 | */ |
||
| 44 | private $product_data; |
||
| 45 | |||
| 46 | /** |
||
| 47 | * @var ArrayList |
||
| 48 | */ |
||
| 49 | private $custom_fields_data; |
||
| 50 | |||
| 51 | /** |
||
| 52 | * Transaction constructor. |
||
| 53 | * @param $data string encrypted foxy response data from the xml data feed |
||
| 54 | * @throws ValidationException |
||
| 55 | */ |
||
| 56 | public function __construct($data) |
||
| 57 | { |
||
| 58 | $this->setEncryptedData($data); |
||
| 59 | $this->setTransaction($data); |
||
| 60 | } |
||
| 61 | |||
| 62 | /** |
||
| 63 | * @param $data |
||
| 64 | * @return $this |
||
| 65 | */ |
||
| 66 | public function setEncryptedData($data) |
||
| 67 | { |
||
| 68 | $this->encrypted_data = $data; |
||
| 69 | |||
| 70 | return $this; |
||
| 71 | } |
||
| 72 | |||
| 73 | /** |
||
| 74 | * @return string |
||
| 75 | */ |
||
| 76 | public function getEncryptedData() |
||
| 77 | { |
||
| 78 | return $this->encrypted_data; |
||
| 79 | } |
||
| 80 | |||
| 81 | /** |
||
| 82 | * Set the decrypted transaction data to use. |
||
| 83 | * |
||
| 84 | * @param $data |
||
| 85 | * @return $this |
||
| 86 | * @throws ValidationException |
||
| 87 | */ |
||
| 88 | public function setTransaction($data) |
||
| 89 | { |
||
| 90 | $decryptedData = $this->getDecryptedData($data); |
||
| 91 | |||
| 92 | foreach ($decryptedData->transactions->transaction as $transaction) { |
||
| 93 | if ($this->hasID($transaction)) { |
||
| 94 | $this->transaction = $transaction; |
||
| 95 | break; |
||
| 96 | } |
||
| 97 | } |
||
| 98 | |||
| 99 | if (!$this->transaction) { |
||
| 100 | $this->transaction = false; |
||
| 101 | } |
||
| 102 | |||
| 103 | return $this; |
||
| 104 | } |
||
| 105 | |||
| 106 | /** |
||
| 107 | * Check if there is a transaction ID for the given decrypted transaction data. |
||
| 108 | * |
||
| 109 | * @param $transaction |
||
| 110 | * @return bool |
||
| 111 | */ |
||
| 112 | protected function hasID($transaction) |
||
| 113 | { |
||
| 114 | return (int)$transaction->id > 0; |
||
| 115 | } |
||
| 116 | |||
| 117 | /** |
||
| 118 | * Return the decrypted transaction xml data. |
||
| 119 | * |
||
| 120 | * @return mixed |
||
| 121 | */ |
||
| 122 | protected function getTransaction() |
||
| 123 | { |
||
| 124 | return $this->transaction; |
||
| 125 | } |
||
| 126 | |||
| 127 | /** |
||
| 128 | * Return an ArrayData containing transaction, products and discounts data. |
||
| 129 | * |
||
| 130 | * @return ArrayData |
||
| 131 | */ |
||
| 132 | public function getParsedTransactionData() |
||
| 133 | { |
||
| 134 | /** |
||
| 135 | * |
||
| 136 | */ |
||
| 137 | return ArrayData::create([ |
||
| 138 | 'transaction' => $this->getTransactionData(), |
||
| 139 | 'products' => $this->getProductData(), |
||
| 140 | 'discounts' => $this->getDiscountData(), |
||
| 141 | 'custom_fields' => $this->getCustomFieldsData(), |
||
| 142 | ]); |
||
| 143 | } |
||
| 144 | |||
| 145 | /** |
||
| 146 | * Set the base transaction data in an ArrayData object. |
||
| 147 | * |
||
| 148 | * @return $this |
||
| 149 | */ |
||
| 150 | private function setTransactionData() |
||
| 151 | { |
||
| 152 | $this->transaction_data = $this->getObject( |
||
| 153 | $this->getTransaction(), |
||
| 154 | $this->config()->get('transaction_mapping') |
||
| 155 | ); |
||
| 156 | |||
| 157 | return $this; |
||
| 158 | } |
||
| 159 | |||
| 160 | /** |
||
| 161 | * Return base transaction data. |
||
| 162 | * |
||
| 163 | * @return ArrayData |
||
| 164 | */ |
||
| 165 | protected function getTransactionData() |
||
| 166 | { |
||
| 167 | if (!$this->transaction_data instanceof ArrayData) { |
||
|
0 ignored issues
–
show
|
|||
| 168 | $this->setTransactionData(); |
||
| 169 | } |
||
| 170 | |||
| 171 | return $this->transaction_data; |
||
| 172 | } |
||
| 173 | |||
| 174 | /** |
||
| 175 | * Return discounts data from Foxy.io xml data feed if any. |
||
| 176 | * |
||
| 177 | * @return ArrayList |
||
| 178 | */ |
||
| 179 | protected function getDiscountData() |
||
| 180 | { |
||
| 181 | if (!$this->discount_data instanceof ArrayList) { |
||
|
0 ignored issues
–
show
|
|||
| 182 | $this->setDiscountData(); |
||
| 183 | } |
||
| 184 | |||
| 185 | return $this->discount_data; |
||
| 186 | } |
||
| 187 | |||
| 188 | /** |
||
| 189 | * Set an ArrayList with possible discount data as ArrayData objects. |
||
| 190 | * |
||
| 191 | * @return $this |
||
| 192 | */ |
||
| 193 | protected function setDiscountData() |
||
| 194 | { |
||
| 195 | $discounts = $this->getTransaction()->discounts; |
||
| 196 | $discountsList = ArrayList::create(); |
||
| 197 | |||
| 198 | foreach ($discounts as $discount) { |
||
| 199 | $discountsList->push($this->getObject($discount->discount, $this->config()->get('discounts_mapping'))); |
||
| 200 | } |
||
| 201 | |||
| 202 | $this->discount_data = $discountsList; |
||
| 203 | |||
| 204 | return $this; |
||
| 205 | } |
||
| 206 | |||
| 207 | /** |
||
| 208 | * Return transaction_details data from Foxy.io xml data feed if any. |
||
| 209 | * |
||
| 210 | * @return ArrayList |
||
| 211 | */ |
||
| 212 | protected function getProductData() |
||
| 213 | { |
||
| 214 | if (!$this->product_data instanceof ArrayList) { |
||
|
0 ignored issues
–
show
|
|||
| 215 | $this->setProductData(); |
||
| 216 | } |
||
| 217 | |||
| 218 | return $this->product_data; |
||
| 219 | } |
||
| 220 | |||
| 221 | /** |
||
| 222 | * Set an ArrayList with possible transaction_detail data as ArrayData objects. |
||
| 223 | * |
||
| 224 | * @return $this |
||
| 225 | */ |
||
| 226 | protected function setProductData() |
||
| 227 | { |
||
| 228 | $details = $this->getTransaction()->transaction_details->transaction_detail; |
||
| 229 | $detailsList = ArrayList::create(); |
||
| 230 | |||
| 231 | foreach ($details as $detail) { |
||
| 232 | $product = $this->getObject($detail, $this->config()->get('transaction_detail_mapping')); |
||
| 233 | |||
| 234 | $product->transaction_detail_options = |
||
| 235 | $this->getProductOptions($detail->transaction_detail_options->transaction_detail_option); |
||
| 236 | |||
| 237 | $detailsList->push($product); |
||
| 238 | } |
||
| 239 | |||
| 240 | $this->product_data = $detailsList; |
||
| 241 | |||
| 242 | return $this; |
||
| 243 | } |
||
| 244 | |||
| 245 | /** |
||
| 246 | * Returns an ArrayList containing possible transaction_detail_option data as ArrayData objects. |
||
| 247 | * |
||
| 248 | * @param $data |
||
| 249 | * @return ArrayList |
||
| 250 | */ |
||
| 251 | protected function getProductOptions($data) |
||
| 252 | { |
||
| 253 | $options = ArrayList::create(); |
||
| 254 | |||
| 255 | foreach ($data as $option) { |
||
| 256 | $options->push($this->getObject($option, $this->config()->get('transaction_detail_option_mapping'))); |
||
| 257 | } |
||
| 258 | |||
| 259 | return $options; |
||
| 260 | } |
||
| 261 | |||
| 262 | /** |
||
| 263 | * @return ArrayList |
||
| 264 | */ |
||
| 265 | protected function getCustomFieldsData() |
||
| 266 | { |
||
| 267 | if (!$this->custom_fields_data instanceof ArrayList) { |
||
|
0 ignored issues
–
show
|
|||
| 268 | $this->setCustomFieldsData(); |
||
| 269 | } |
||
| 270 | |||
| 271 | return $this->custom_fields_data; |
||
| 272 | } |
||
| 273 | |||
| 274 | /** |
||
| 275 | * @return $this |
||
| 276 | */ |
||
| 277 | protected function setCustomFieldsData() |
||
| 278 | { |
||
| 279 | $customFields = $this->getTransaction()->custom_fields; |
||
| 280 | $customFieldsList = ArrayList::create(); |
||
| 281 | |||
| 282 | foreach ($customFields as $customFieldArray) { |
||
| 283 | foreach ($customFieldArray as $customField) { |
||
| 284 | $customFieldsList->push($this->getObject( |
||
| 285 | $customField, |
||
| 286 | $this->config()->get('custom_fields_mapping') |
||
| 287 | )); |
||
| 288 | } |
||
| 289 | } |
||
| 290 | |||
| 291 | $this->custom_fields_data = $customFieldsList; |
||
| 292 | return $this; |
||
| 293 | } |
||
| 294 | |||
| 295 | /** |
||
| 296 | * Returns an ArrayData object based on the given iterable data and a key/val config array. Used |
||
| 297 | * to type hint data from the Foxy.io xml data feed. |
||
| 298 | * |
||
| 299 | * @param $data |
||
| 300 | * @param array $config |
||
| 301 | * @return ArrayData |
||
| 302 | */ |
||
| 303 | protected function getObject($data, $config = []) |
||
| 304 | { |
||
| 305 | $dataArray = []; |
||
| 306 | |||
| 307 | foreach ($config as $name => $type) { |
||
| 308 | switch ($type) { |
||
| 309 | case 'int': |
||
| 310 | $dataArray[$name] = (int)$data->{$name}; |
||
| 311 | break; |
||
| 312 | case 'float': |
||
| 313 | $dataArray[$name] = (float)$data->{$name}; |
||
| 314 | break; |
||
| 315 | case 'bool': |
||
| 316 | case 'boolean': |
||
| 317 | $dataArray[$name] = (bool)$data->{$name}; |
||
| 318 | break; |
||
| 319 | case 'string': |
||
| 320 | default: |
||
| 321 | $dataArray[$name] = (string)$data->{$name}; |
||
| 322 | break; |
||
| 323 | } |
||
| 324 | } |
||
| 325 | |||
| 326 | return ArrayData::create($dataArray); |
||
| 327 | } |
||
| 328 | |||
| 329 | /** |
||
| 330 | * @return bool |
||
| 331 | */ |
||
| 332 | public function exists() |
||
| 333 | { |
||
| 334 | return $this->getTransaction() != false && !empty($this->getTransaction()); |
||
| 335 | } |
||
| 336 | |||
| 337 | /** |
||
| 338 | * @param $data |
||
| 339 | * @return \SimpleXMLElement |
||
| 340 | * @throws \SilverStripe\ORM\ValidationException |
||
| 341 | */ |
||
| 342 | private function getDecryptedData($data) |
||
| 343 | { |
||
| 344 | $helper = new FoxyHelper(); |
||
| 345 | |||
| 346 | return new \SimpleXMLElement(\rc4crypt::decrypt($helper->config()->get('secret'), $data)); |
||
| 347 | } |
||
| 348 | } |
||
| 349 |