Completed
Push — master ( cc628c...ce99fc )
by ARCANEDEV
09:04
created

Util::secureCompare()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 9.0581

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 8
nop 2
dl 0
loc 22
ccs 5
cts 11
cp 0.4545
crap 9.0581
rs 8.6737
c 0
b 0
f 0
1
<?php namespace Arcanedev\Stripe\Utilities;
2
3
use Arcanedev\Stripe\Collection;
4
use Arcanedev\Stripe\Contracts\Utilities\Util as UtilContract;
5
use Arcanedev\Stripe\Resources;
6
use Arcanedev\Stripe\StripeObject;
7
8
/**
9
 * Class     Util
10
 *
11
 * @package  Arcanedev\Stripe\Utilities
12
 * @author   ARCANEDEV <[email protected]>
13
 */
14
abstract class Util implements UtilContract
15
{
16
    /* -----------------------------------------------------------------
17
     |  Properties
18
     | -----------------------------------------------------------------
19
     */
20
21
    /**
22
     * Available Resources.
23
     *
24
     * @var array
25
     */
26
    private static $resources = [
27
        'account'             => Resources\Account::class,
28
        'alipay_account'      => Resources\AlipayAccount::class,
29
        'apple_pay_domain'    => Resources\ApplePayDomain::class,
30
        'balance_transaction' => Resources\BalanceTransaction::class,
31
        'bank_account'        => Resources\BankAccount::class,
32
        'bitcoin_transaction' => Resources\BitcoinTransaction::class,
33
        'card'                => Resources\Card::class,
34
        'charge'              => Resources\Charge::class,
35
        'country_spec'        => Resources\CountrySpec::class,
36
        'coupon'              => Resources\Coupon::class,
37
        'customer'            => Resources\Customer::class,
38
        'discount'            => Resources\Discount::class,
39
        'dispute'             => Resources\Dispute::class,
40
        'event'               => Resources\Event::class,
41
        'ephemeral_key'       => Resources\EphemeralKey::class,
42
        'exchange_rate'       => Resources\ExchangeRate::class,
43
        'fee_refund'          => Resources\ApplicationFeeRefund::class,
44
        'file_upload'         => Resources\FileUpload::class,
45
        'invoice'             => Resources\Invoice::class,
46
        'invoiceitem'         => Resources\InvoiceItem::class,
47
        'list'                => Collection::class,                      // List Object
48
        'login_link'          => Resources\LoginLink::class,
49
        'order'               => Resources\Order::class,
50
        'order_item'          => Resources\OrderItem::class,
51
        'order_return'        => Resources\OrderReturn::class,
52
        'payout'              => Resources\Payout::class,
53
        'plan'                => Resources\Plan::class,
54
        'product'             => Resources\Product::class,
55
        'recipient'           => Resources\Recipient::class,
56
        'recipient_transfer'  => Resources\RecipientTransfer::class,
57
        'refund'              => Resources\Refund::class,
58
        'sku'                 => Resources\Sku::class,
59
        'source'              => Resources\Source::class,
60
        'source_transaction'  => Resources\SourceTransaction::class,
61
        'subscription'        => Resources\Subscription::class,
62
        'subscription_item'   => Resources\SubscriptionItem::class,
63
        'three_d_secure'      => Resources\ThreeDSecure::class,
64
        'token'               => Resources\Token::class,
65
        'transfer'            => Resources\Transfer::class,
66
        'transfer_reversal'   => Resources\TransferReversal::class,
67
    ];
68
69
    private static $isHashEqualsAvailable = null;
70
71
    /* -----------------------------------------------------------------
72
     |  Main Methods
73
     | -----------------------------------------------------------------
74
     */
75
76
    /**
77
     * Recursively converts the PHP Stripe object to an array.
78
     *
79
     * @param  array  $values
80
     *
81
     * @return array
82
     */
83 8
    public static function convertStripeObjectToArray($values)
84
    {
85 8
        $results = [];
86
87 8
        foreach ($values as $k => $v) {
88
            // TODO: Fix the encapsulation violation
89 8
            if ($k[0] == '_') continue;
90
91 8
            if ($v instanceof StripeObject) {
92 4
                $results[$k] = $v->toArray(true);
93
            }
94 8
            elseif (is_array($v)) {
95 2
                $results[$k] = self::convertStripeObjectToArray($v);
96
            }
97
            else {
98 8
                $results[$k] = $v;
99
            }
100
        }
101
102 8
        return $results;
103
    }
104
105
    /**
106
     * Converts a response from the Stripe API to the corresponding PHP object.
107
     *
108
     * @param  array  $response
109
     * @param  array  $options
110
     *
111
     * @return \Arcanedev\Stripe\StripeObject|\Arcanedev\Stripe\StripeResource|\Arcanedev\Stripe\Collection|array
112
     */
113 394
    public static function convertToStripeObject($response, $options)
114
    {
115 394
        if (self::isList($response)) {
116 296
            return array_map(function($i) use ($options) {
117 212
                return self::convertToStripeObject($i, $options);
118 296
            }, $response);
119
        }
120 394
        elseif (is_array($response)) {
121 372
            $class = self::getClassTypeObject($response);
122
123 372
            return $class::scopedConstructFrom(
124 372
                $response,
125 372
                $options
126
            );
127
        }
128
129 394
        return $response;
130
    }
131
132
    /**
133
     * Get Class Type.
134
     *
135
     * @param  array  $response
136
     *
137
     * @return string
138
     */
139 372
    private static function getClassTypeObject($response)
140
    {
141 372
        return self::isClassTypeObjectExist($response)
142 352
            ? self::$resources[ $response['object'] ]
143 372
            : StripeObject::class;
144
    }
145
146
    /**
147
     * Compares two strings for equality. The time taken is independent of the
148
     * number of characters that match.
149
     *
150
     * @param  string  $one
151
     * @param  string  $two
152
     *
153
     * @return bool
154
     */
155 12
    public static function secureCompare($one, $two)
156
    {
157 12
        if (self::$isHashEqualsAvailable === null) {
158 2
            self::$isHashEqualsAvailable = function_exists('hash_equals');
159
        }
160
161 12
        if (self::$isHashEqualsAvailable) {
162 12
            return hash_equals($one, $two);
163
        }
164
165
        if (strlen($one) != strlen($two)) {
166
            return false;
167
        }
168
169
        $result = 0;
170
171
        for ($i = 0; $i < strlen($one); $i++) {
172
            $result |= ord($one[$i]) ^ ord($two[$i]);
173
        }
174
175
        return ($result == 0);
176
    }
177
178
    /* -----------------------------------------------------------------
179
     |  Check Methods
180
     | -----------------------------------------------------------------
181
     */
182
183
    /**
184
     * Whether the provided array (or other) is a list rather than a dictionary.
185
     *
186
     * @param  mixed  $array
187
     *
188
     * @return bool
189
     */
190 396
    public static function isList($array)
191
    {
192 396
        if ( ! is_array($array)) return false;
193
194
        // TODO: generally incorrect, but it's correct given Stripe's response
195 374
        foreach (array_keys($array) as $k) {
196 374
            if ( ! is_numeric($k)) return false;
197
        }
198
199 298
        return true;
200
    }
201
202
    /**
203
     * Check if the object is a resource.
204
     *
205
     * @param  array  $response
206
     *
207
     * @return bool
208
     */
209 372
    private static function isClassTypeObjectExist($response)
210
    {
211 372
        if (isset($response['object']) && is_string($response['object'])) {
212 354
            return array_key_exists($response['object'], self::$resources);
213
        }
214
215 144
        return false;
216
    }
217
}
218