Completed
Push — master ( b57115...36326e )
by rugk
07:27
created

ThreemaGateway_Option_Status::queryCredits()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 51
Code Lines 27

Duplication

Lines 8
Ratio 15.69 %

Importance

Changes 0
Metric Value
dl 8
loc 51
rs 8.6588
c 0
b 0
f 0
cc 5
eloc 27
nc 6
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Status managment for Threema Gateway.
4
 *
5
 * @package ThreemaGateway
6
 * @author rugk
7
 * @copyright Copyright (c) 2015-2016 rugk
8
 * @license MIT
9
 */
10
11
class ThreemaGateway_Option_Status
12
{
13
    /**
14
     * @var int Below this amount of credits a warning is shown.
15
     */
16
    const CREDITS_WARN = 100;
17
18
    /**
19
     * Renders the status "option".
20
     *
21
     * @param XenForo_View $view           View object
22
     * @param string       $fieldPrefix    Prefix for the HTML form field name
23
     * @param array        $preparedOption Prepared option info
24
     * @param bool         $canEdit        True if an "edit" link should appear
25
     *
26
     * @return XenForo_Template_Abstract Template object
27
     */
28
    public static function renderHtml(XenForo_View $view, $fieldPrefix, array $preparedOption, $canEdit)
29
    {
30
        /** @var array $status */
31
        $status = ['libsodium', 'libsodiumphp', 'phpsdk', 'credits'];
32
        /** @var string $extraError */
33
        $extraError = '';
34
35
        /** @var bool $technSuccess */
36
        $technSuccess = self::checkTecRequire($status, $extraError);
0 ignored issues
show
Documentation introduced by
$extraError is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
37
38
        /** @var ThreemaGateway_Handler_Settings $gwSettings */
39
        $gwSettings = new ThreemaGateway_Handler_Settings;
40
41
        // only go on if technically everything is okay to prevent PHP errors when accessing the SDK
42
        if ($technSuccess) {
43
            /** @var bool $phpSdkSuccess */
44
            $phpSdkSuccess = self::checkPhpSdk($status, $extraError, $gwSettings);
45
46
            // Only continue if there are no errors in the PHP SDK.
47
            // We could try it anyway, but this would be useless as it certainly
48
            // fails anyway and if you have a broken setup, you also have bigger
49
            // issues than your credits count.
50
            if ($phpSdkSuccess) {
51
                self::queryCredits($status, $extraError);
52
            }
53
        }
54
55
        if ($gwSettings->isDebug()) {
56
            if (XenForo_Application::debugMode()) {
57
                $extraError[] = [
58
                    'text' => new XenForo_Phrase('option_threema_gateway_status_debug_mode_active'),
59
                    'descclass' => 'warning'
60
                ];
61
            } else {
62
                $extraError[] = [
63
                    'text' => new XenForo_Phrase('option_threema_gateway_status_debug_mode_potentially_active'),
64
                    'descclass' => 'warning'
65
                ];
66
            }
67
        }
68
69
        $editLink = $view->createTemplateObject('option_list_option_editlink', [
70
            'preparedOption' => $preparedOption,
71
            'canEditOptionDefinition' => $canEdit
72
        ]);
73
74
        return $view->createTemplateObject('threemagw_option_list_status', [
75
            'fieldPrefix' => $fieldPrefix,
76
            'listedFieldName' => $fieldPrefix . '_listed[]',
77
            'preparedOption' => $preparedOption,
78
            'editLink' => $editLink,
79
            'status' => $status,
80
            'additionalerror' => $extraError,
81
            'isConfError' => (!$technSuccess),
82
            'isPhpSdkError' => (!$phpSdkSuccess),
0 ignored issues
show
Bug introduced by
The variable $phpSdkSuccess does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
83
        ]);
84
    }
85
86
    /**
87
     * Checks whether all technical requirements of the add-on installation
88
     * are fullfilled.
89
     *
90
     * Mostly only checks for Libsodium and Libsodium-PHP.
91
     * Return false when a serious error happens, which indicates that the
92
     * requirements are not fullfilled.
93
     *
94
     * @param  array $status     Will be filled with required statuses (sic)
95
     * @param  array $extraError Optional other errors may be added here
96
     * @return bool
97
     */
98
    protected static function checkTecRequire(&$status, &$extraError)
99
    {
100
        // optional check: HTTPS
101
        if (!XenForo_Application::$secure) {
102
            $extraError[]['text'] = new XenForo_Phrase('option_threema_gateway_status_no_https');
103
        }
104
105
        //libsodium
106
        if (extension_loaded('libsodium')) {
107
            if (method_exists('Sodium', 'sodium_version_string')) {
108
                $status['libsodium']['text']      = new XenForo_Phrase('option_threema_gateway_status_libsodium_version', ['version' => Sodium::sodium_version_string()]);
109
                $status['libsodium']['descr']     = new XenForo_Phrase('option_threema_gateway_status_libsodium_outdated');
110
                $status['libsodium']['descclass'] = 'warning';
111
            } else {
112
                $status['libsodium']['text'] = new XenForo_Phrase('option_threema_gateway_status_libsodium_version', ['version' => \Sodium\version_string()]);
113
            }
114
115
            // & libsodium-php
116
            $status['libsodiumphp']['text'] = new XenForo_Phrase('option_threema_gateway_status_libsodiumphp_version', ['version' => phpversion('libsodium')]);
117
            if (version_compare(phpversion('libsodium'), '1.0.1', '<')) {
118
                $status['libsodiumphp']['descr']     = new XenForo_Phrase('option_threema_gateway_status_libsodiumphp_outdated');
119
                $status['libsodiumphp']['descclass'] = 'warning';
120
            }
121
        } else {
122
            $status['libsodium']['text'] = new XenForo_Phrase('option_threema_gateway_status_libsodium_not_installed');
123 View Code Duplication
            if (PHP_INT_SIZE < 8) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
                $status['libsodium']['descr']         = new XenForo_Phrase('option_threema_gateway_status_libsodium_not_installed_required_64bit');
125
                $status['libsodium']['descclass']     = 'error';
126
                return false;
127
            } else {
128
                $status['libsodium']['descr']     = new XenForo_Phrase('option_threema_gateway_status_libsodium_not_installed_recommend');
129
                $status['libsodium']['descclass'] = 'warning';
130
            }
131
        }
132
133
        // there may be warnings, but apart from that all is okay
134
        return true;
135
    }
136
137
    /**
138
     * Checks whether the add-on/PHP-SDK is correctly configured and this ready
139
     * to use.
140
     *
141
     * It also automatically includes status indicators from the SDK.
142
     * Return false when a serious error happens, which indicates that the
143
     * requirements are not fullfilled.
144
     *
145
     * @param  array                           $status     Will be filled with required statuses (sic)
146
     * @param  array                           $extraError Optional other errors may be added here
147
     * @param  ThreemaGateway_Handler_Settings $gwSettings
148
     * @return bool
149
     */
150
    protected static function checkPhpSdk(&$status, &$extraError, ThreemaGateway_Handler_Settings $gwSettings = null)
151
    {
152
        // auto-create Gateway settings if not given
153
        if ($gwSettings == null) {
154
            $gwSettings = new ThreemaGateway_Handler_Settings;
155
        }
156
157
        //show PHP SDK version, checks if PHP-SDK is correctly setup
158
        try {
159
            $sdk = ThreemaGateway_Handler_PhpSdk::getInstance($gwSettings);
160
            //Note: When the SDK throws an exception the two lines below cannot be executed, so the version number cannot be determinated
161
            $status['phpsdk']['text']     = new XenForo_Phrase('option_threema_gateway_status_phpsdk_version', ['version' => $sdk->getVersion()]);
162
            $status['phpsdk']['addition'] = new XenForo_Phrase('option_threema_gateway_status_phpsdk_featurelevel', ['level' => $sdk->getFeatureLevel()]);
163
        } catch (Exception $e) {
164
            $extraError[]['text'] = new XenForo_Phrase('option_threema_gateway_status_custom_phpsdk_error') . $e->getMessage();
165
            return false;
166
        }
167
168
        // check whether Gateway is ready to use
169
        if (!$gwSettings->isReady()) {
170
            // If SDK is not ready, check whether it is at least available
171
            if ($gwSettings->isAvaliable()) {
172
                // presumambly an error in setup
173
                $extraError[]['text'] = new XenForo_Phrase('option_threema_gateway_status_phpsdk_not_ready');
174
            } else {
175
                // presumambly not yet setup (default settings or so)
176
                $extraError[] = [
177
                    'text' => new XenForo_Phrase('option_threema_gateway_status_phpsdk_not_ready_yet'),
178
                    'descclass' => 'warning'
179
                ];
180
            }
181
182
            return false;
183
        }
184
185
        // there may be warnings, but apart from that all is okay
186
        return true;
187
    }
188
189
    /**
190
     * When the user is allowed to view the credits, this queries them and adds
191
     * the result as a status message.
192
     *
193
     * Return false when the permissions could not be fetched.
194
     * When the user has not enough permissions to do so, this method returns
195
     * true anyway.
196
     *
197
     * @param  array $status     Will be filled with required statuses (sic)
198
     * @param  array $extraError Optional other errors may be added here
199
     * @return bool
200
     */
201
    protected static function queryCredits(&$status, &$extraError)
202
    {
203
        /** @var ThreemaGateway_Handler_Permissions $permissions */
204
        $permissions = ThreemaGateway_Handler_Permissions::getInstance();
205
206
        // check permissions for accessing credits
207
        if (!$permissions->hasPermission('credits')) {
208
            $status['credits']['text']      = new XenForo_Phrase('option_threema_gateway_status_credits', ['credits' => 'No permission']);
209
            $status['credits']['descr']     = new XenForo_Phrase('option_threema_gateway_status_credits_permission');
210
            $status['credits']['descclass'] = 'warning';
211
212
            return true;
213
        }
214
215
        // always there credit text
216
        $status['credits']['addition'] = new XenForo_Phrase('option_threema_gateway_status_credits_recharge');
217
218
        // try to fetch credits
219
        try {
220
            $gwServer = new ThreemaGateway_Handler_Action_GatewayServer;
221
            /** @var int|string $credits */
222
            $credits = $gwServer->getCredits();
223
        } catch (Exception $e) {
224
            // special error handling
225
            $extraError[]['text'] = new XenForo_Phrase('option_threema_gateway_status_custom_gwserver_error') . $e->getMessage();
226
            $credits              = 'N/A';
227
228
            // add (general) status error
229
            $status['credits']['descr']     = new XenForo_Phrase('option_threema_gateway_status_credits_error');
230
            $status['credits']['descclass'] = 'error';
231
232
            // wanna use finally block here, but is only available in PHP >= 5.5 :(
233
            // so duplicate code…
234
            $status['credits']['text'] = new XenForo_Phrase('option_threema_gateway_status_credits', ['credits' => $credits]);
235
            return false;
236
        }
237
238
        // when no error happens, check whether credits are "enough"
239
        $status['credits']['text'] = new XenForo_Phrase('option_threema_gateway_status_credits', ['credits' => $credits]);
240 View Code Duplication
        if ($credits == 0) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
241
            $status['credits']['descr']     = new XenForo_Phrase('option_threema_gateway_status_credits_out');
242
            $status['credits']['descclass'] = 'error';
243
            return false;
244
        } elseif ($credits < self::CREDITS_WARN) {
245
            $status['credits']['descr']     = new XenForo_Phrase('option_threema_gateway_status_credits_low');
246
            $status['credits']['descclass'] = 'warning';
247
        }
248
249
        // there may be warnings, but apart from that all is okay
250
        return true;
251
    }
252
}
253