Completed
Push — master ( 556987...94c24e )
by ARCANEDEV
9s
created

Util::secureCompare()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 8.9038

Importance

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