Issues (2811)

public/htdocs/admin/multicurrency.php (2 issues)

1
<?php
2
3
/* Copyright (C) 2015       ATM Consulting              <[email protected]>
4
 * Copyright (C) 2024       Rafael San José             <[email protected]>
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
use Dolibarr\Code\Core\Classes\Form;
21
use Dolibarr\Code\MultiCurrency\Classes\MultiCurrency;
22
use Dolibarr\Lib\ViewMain;
23
24
/**
25
 *  \file       admin/multicurrency.php
26
 *  \ingroup    multicurrency
27
 *  \brief      Page to setup multicurrency module
28
 */
29
30
// Dolibarr environment
31
require constant('DOL_DOCUMENT_ROOT') . '/main.inc.php';
32
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/admin.lib.php';
33
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/multicurrency.lib.php';
34
35
36
// Load translation files required by the page
37
$langs->loadLangs(array('admin', 'multicurrency'));
38
39
// Access control
40
if (!$user->admin || !isModEnabled('multicurrency')) {
41
    accessforbidden();
42
}
43
44
// Parameters
45
$action = GETPOST('action', 'aZ09');
46
47
/*
48
 * Actions
49
 */
50
51
$reg = array();
52
if (preg_match('/set_([a-z0-9_\-]+)/i', $action, $reg)) {
53
    $code = $reg[1];
54
    $value = GETPOST($code, 'alpha');
55
    if (dolibarr_set_const($db, $code, $value, 'chaine', 0, '', $conf->entity) > 0) {
56
        setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
57
    } else {
58
        setEventMessages($langs->trans("Error"), null, 'errors');
59
    }
60
}
61
62
if (preg_match('/del_([a-z0-9_\-]+)/i', $action, $reg)) {
63
    $code = $reg[1];
64
    if (dolibarr_del_const($db, $code, 0) > 0) {
65
        setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
66
    } else {
67
        setEventMessages($langs->trans("Error"), null, 'errors');
68
    }
69
}
70
71
if ($action == 'add_currency') {
72
    $error = 0;
73
74
    $langs->loadCacheCurrencies('');
75
76
    $code = GETPOST('code', 'alpha');
77
    $rate = price2num(GETPOST('rate', 'alpha'));
78
    $currency = new MultiCurrency($db);
79
    $currency->code = $code;
0 ignored issues
show
Documentation Bug introduced by
It seems like $code can also be of type array or array or array. However, the property $code is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
80
    $currency->name = !empty($langs->cache_currencies[$code]['label']) ? $langs->cache_currencies[$code]['label'] . ' (' . $langs->getCurrencySymbol($code) . ')' : $code;
0 ignored issues
show
Documentation Bug introduced by
It seems like ! empty($langs->cache_cu...ol($code) . ')' : $code can also be of type array or array or array. However, the property $name is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
81
82
    if (empty($currency->code) || $currency->code == '-1') {
83
        setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Currency")), null, 'errors');
84
        $error++;
85
    }
86
    if (empty($rate)) {
87
        setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Rate")), null, 'errors');
88
        $error++;
89
    }
90
91
    if (!$error) {
92
        if ($currency->create($user) > 0) {
93
            if ($currency->addRate($rate)) {
94
                setEventMessages($langs->trans('RecordSaved'), array());
95
            } else {
96
                setEventMessages($langs->trans('ErrorAddRateFail'), array(), 'errors');
97
            }
98
        } else {
99
            setEventMessages($langs->trans('ErrorAddCurrencyFail'), $currency->errors, 'errors');
100
        }
101
    }
102
} elseif ($action == 'update_currency') {
103
    $error = 0;
104
105
    if (GETPOST('updatecurrency', 'alpha')) {
106
        $fk_multicurrency = GETPOSTINT('fk_multicurrency');
107
        $rate = price2num(GETPOST('rate', 'alpha'));
108
        $currency = new MultiCurrency($db);
109
110
        if (empty($rate)) {
111
            setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Rate")), null, 'errors');
112
            $error++;
113
        }
114
        if (!$error) {
115
            if ($currency->fetch($fk_multicurrency) > 0) {
116
                $result = $currency->updateRate($rate);
117
                if ($result < 0) {
118
                    setEventMessages(null, $currency->errors, 'errors');
119
                }
120
            }
121
        }
122
    } elseif (GETPOST('deletecurrency', 'alpha')) {
123
        $fk_multicurrency = GETPOSTINT('fk_multicurrency');
124
        $currency = new MultiCurrency($db);
125
126
        if ($currency->fetch($fk_multicurrency) > 0) {
127
            if ($currency->delete($user) > 0) {
128
                setEventMessages($langs->trans('RecordDeleted'), array());
129
            } else {
130
                setEventMessages($langs->trans('ErrorDeleteCurrencyFail'), array(), 'errors');
131
            }
132
        }
133
    }
134
} elseif ($action == 'setapilayer') {
135
    if (GETPOSTISSET('modify_apilayer')) {
136
        dolibarr_set_const($db, 'MULTICURRENCY_APP_ID', GETPOST('MULTICURRENCY_APP_ID', 'alpha'));
137
        dolibarr_set_const($db, 'MULTICURRENCY_APP_SOURCE', GETPOST('MULTICURRENCY_APP_SOURCE', 'alpha'));
138
        //dolibarr_set_const($db, 'MULTICURRENCY_ALTERNATE_SOURCE', GETPOST('MULTICURRENCY_ALTERNATE_SOURCE', 'alpha'));
139
    } else {
140
        $multiurrency = new MultiCurrency($db);
141
        $result = $multiurrency->syncRates(getDolGlobalString('MULTICURRENCY_APP_ID'));
142
        if ($result > 0) {
143
            setEventMessages($langs->trans("CurrencyRateSyncSucceed"), null, "mesgs");
144
        }
145
    }
146
}
147
148
149
$TAvailableCurrency = array();
150
$sql = "SELECT code_iso, label, unicode, active FROM " . MAIN_DB_PREFIX . "c_currencies";
151
$resql = $db->query($sql);
152
if ($resql) {
153
    while ($obj = $db->fetch_object($resql)) {
154
        $TAvailableCurrency[$obj->code_iso] = array('code' => $obj->code_iso, 'active' => $obj->active);
155
    }
156
}
157
158
$TCurrency = array();
159
$sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "multicurrency WHERE entity = " . ((int)$conf->entity);
160
$resql = $db->query($sql);
161
if ($resql) {
162
    while ($obj = $db->fetch_object($resql)) {
163
        $currency = new MultiCurrency($db);
164
        $currency->fetch($obj->rowid);
165
        $TCurrency[] = $currency;
166
    }
167
}
168
169
/*
170
 * View
171
 */
172
173
$form = new Form($db);
174
175
$page_name = "MultiCurrencySetup";
176
$help_url = '';
177
178
ViewMain::llxHeader('', $langs->trans($page_name), $help_url, '', 0, 0, '', '', '', 'mod-admin page-multicurrency');
179
180
// Subheader
181
$linkback = '<a href="' . constant('BASE_URL') . '/admin/modules.php?restore_lastsearch_values=1">' . $langs->trans("BackToModuleList") . '</a>';
182
print load_fiche_titre($langs->trans($page_name), $linkback);
183
184
// Configuration header
185
$head = multicurrencyAdminPrepareHead();
186
print dol_get_fiche_head($head, 'settings', $langs->trans($page_name), -1, "multicurrency");
187
188
189
print '<div class="div-table-responsive-no-min">';
190
print '<table class="noborder centpercent">';
191
print '<tr class="liste_titre">';
192
print '<td>' . $langs->trans("Parameters") . '</td>' . "\n";
193
print '<td class="center">' . $langs->trans("Status") . '</td>' . "\n";
194
print '</tr>';
195
196
print '<tr class="oddeven">';
197
print '<td>' . $langs->transnoentitiesnoconv("MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE") . '</td>';
198
print '<td class="center">';
199
if ($conf->use_javascript_ajax) {
200
    print ajax_constantonoff('MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE');
201
} else {
202
    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
203
    print $form->selectarray("MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE", $arrval, $conf->global->MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE);
204
}
205
print '</td></tr>';
206
207
208
print '<tr class="oddeven">';
209
print '<td>' . $langs->transnoentitiesnoconv("multicurrency_useOriginTx") . '</td>';
210
print '<td class="center">';
211
if ($conf->use_javascript_ajax) {
212
    print ajax_constantonoff('MULTICURRENCY_USE_ORIGIN_TX', null, null, 0, 0, 0, 2, 0, 1);
213
} else {
214
    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
215
    print $form->selectarray("MULTICURRENCY_USE_ORIGIN_TX", $arrval, $conf->global->MULTICURRENCY_USE_ORIGIN_TX);
216
}
217
print '</td></tr>';
218
219
// Online payment with currency on document. This option should be on by default.
220
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
221
    print '<tr class="oddeven">';
222
    print '<td>' . $langs->transnoentitiesnoconv("MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT") . '</td>';
223
    print '<td class="center">';
224
    if ($conf->use_javascript_ajax) {
225
        print ajax_constantonoff('MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT');
226
    } else {
227
        $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
228
        print $form->selectarray("MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT", $arrval, $conf->global->MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT);
229
    }
230
    print '</td></tr>';
231
}
232
233
/* TODO uncomment when the functionality will integrated
234
235
print '<tr class="oddeven">';
236
print '<td>'.$langs->transnoentitiesnoconv("multicurrency_buyPriceInCurrency").'</td>';
237
print '<td class="right">';
238
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
239
print '<input type="hidden" name="token" value="'.newToken().'">';
240
print '<input type="hidden" name="action" value="set_MULTICURRENCY_BUY_PRICE_IN_CURRENCY">';
241
print $form->selectyesno("MULTICURRENCY_BUY_PRICE_IN_CURRENCY",$conf->global->MULTICURRENCY_BUY_PRICE_IN_CURRENCY,1);
242
print '<input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'">';
243
print '</form>';
244
print '</td></tr>';
245
*/
246
247
/* TODO uncomment when the functionality will integrated
248
249
print '<tr class="oddeven">';
250
print '<td>'.$langs->transnoentitiesnoconv("multicurrency_modifyRateApplication").'</td>';
251
print '<td class="right">';
252
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
253
print '<input type="hidden" name="token" value="'.newToken().'">';
254
print '<input type="hidden" name="action" value="set_MULTICURRENCY_MODIFY_RATE_APPLICATION">';
255
print $form->selectarray('MULTICURRENCY_MODIFY_RATE_APPLICATION', array('PU_DOLIBARR' => 'PU_DOLIBARR', 'PU_CURRENCY' => 'PU_CURRENCY'), $conf->global->MULTICURRENCY_MODIFY_RATE_APPLICATION);
256
print '<input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'">';
257
print '</form>';
258
print '</td></tr>';
259
260
*/
261
262
print '</table>';
263
print '</div>';
264
265
266
print '<div class="div-table-responsive-no-min">';
267
print '<table class="noborder centpercent nomarginbottom">';
268
269
print '<tr class="liste_titre">';
270
print '<td>' . $form->textwithpicto($langs->trans("CurrenciesUsed"), $langs->transnoentitiesnoconv("CurrenciesUsed_help_to_add")) . '</td>' . "\n";
271
print '<td class="right">' . $langs->trans("Rate") . ' / ' . $langs->getCurrencySymbol($conf->currency) . '</td>' . "\n";
272
print '</tr>';
273
274
print '<form method="POST" action="' . $_SERVER['PHP_SELF'] . '">';
275
print '<input type="hidden" name="token" value="' . newToken() . '">';
276
print '<input type="hidden" name="action" value="add_currency">';
277
278
print '<tr class="oddeven">';
279
print '<td>' . $form->selectCurrency('', 'code', 1, '1') . '</td>';
280
print '<td class="right">';
281
print '<input type="text" name="rate" value="" class="width75 right" placeholder="' . $langs->trans('Rate') . '" />&nbsp;';
282
print '<input type="submit" class="button button-add smallpaddingimp" value="' . $langs->trans("Add") . '">';
283
print '</td>';
284
print '</tr>';
285
286
print '</form>';
287
288
// Main currency
289
print '<tr class="oddeven">';
290
print '<td>' . $conf->currency;
291
print ' (' . $langs->getCurrencySymbol($conf->currency) . ')';
292
print $form->textwithpicto(' ', $langs->trans("BaseCurrency"));
293
if (!empty($TAvailableCurrency[$conf->currency]) && empty($TAvailableCurrency[$conf->currency]['active'])) {
294
    print img_warning('Warning: This code has been disabled into Home - Setup - Dictionaries - Currencies');
295
}
296
print '</td>';
297
print '<td class="right">1</td>';
298
print '</tr>';
299
300
foreach ($TCurrency as &$currency) {
301
    if ($currency->code == $conf->currency) {
302
        continue;
303
    }
304
305
    print '<tr class="oddeven">';
306
    print '<td>' . $currency->code . ' - ' . $currency->name;
307
    if (!empty($TAvailableCurrency[$currency->code]) && empty($TAvailableCurrency[$currency->code]['active'])) {
308
        print img_warning('Warning: The code ' . $currency->code . ' has been disabled into Home - Setup - Dictionaries - Currencies');
309
    }
310
    print '</td>';
311
    print '<td class="right">';
312
    print '<form method="POST" action="' . $_SERVER['PHP_SELF'] . '">';
313
    print '<input type="hidden" name="token" value="' . newToken() . '">';
314
    print '<input type="hidden" name="action" value="update_currency">';
315
    print '<input type="hidden" name="fk_multicurrency" value="' . $currency->id . '">';
316
    print '1 ' . $conf->currency . ' = ';
317
    print '<input type="text" name="rate" class="width75 right" value="' . ($currency->rate->rate ? $currency->rate->rate : '') . '" size="13">&nbsp;' . $currency->code . '&nbsp;';
318
    print '<input type="submit" name="updatecurrency" class="button button-edit smallpaddingimp" value="' . $langs->trans("Modify") . '">&nbsp;';
319
    print '<input type="submit" name="deletecurrency" class="button smallpaddingimp" value="' . $langs->trans("Delete") . '">';
320
    print '</form>';
321
    print '</td></tr>';
322
}
323
324
print '</table>';
325
print '</div>';
326
327
print '
328
	<script type="text/javascript">
329
 		function getRates()
330
		{
331
			$("#bt_sync").attr("disabled", true);
332
            return true;
333
		}
334
	</script>
335
';
336
337
338
print '<br>';
339
340
if (!getDolGlobalString('MULTICURRENCY_DISABLE_SYNC_CURRENCYLAYER')) {
341
    print '<form method="POST" action="' . $_SERVER['PHP_SELF'] . '" id="form_sync">';
342
    print '<input type="hidden" name="token" value="' . newToken() . '">';
343
    print '<input type="hidden" name="action" value="setapilayer">';
344
345
    print '<div class="div-table-responsive-no-min">';
346
    print '<table class="noborder centpercent">';
347
348
    $urlforapilayer = 'https://currencylayer.com'; //https://apilayer.net
349
350
    print '<tr class="liste_titre">';
351
    print '<td>' . $form->textwithpicto($langs->trans("CurrencyLayerAccount"), $langs->trans("CurrencyLayerAccount_help_to_synchronize", $urlforapilayer)) . '</td>' . "\n";
352
    print '<td class="right">';
353
    print '<textarea id="response" class="hideobject" name="response"></textarea>';
354
    print '<input type="submit" name="modify_apilayer" class="button buttongen" value="' . $langs->trans("Modify") . '">';
355
    print '<input type="submit" id="bt_sync" name="bt_sync_apilayer" class="button buttongen" value="' . $langs->trans('Synchronize') . '" />';
356
    print '</td></tr>';
357
358
    print '<tr class="oddeven">';
359
    print '<td class="fieldrequired"><a target="_blank" rel="noopener noreferrer external" href="' . $urlforapilayer . '">' . $langs->transnoentitiesnoconv("multicurrency_appId") . '</a></td>';
360
    print '<td class="right">';
361
    print '<input type="text" name="MULTICURRENCY_APP_ID" value="' . getDolGlobalString('MULTICURRENCY_APP_ID') . '" size="28" />&nbsp;';
362
    print '</td></tr>';
363
364
    print '<tr class="oddeven">';
365
    print '<td>' . $langs->transnoentitiesnoconv("multicurrency_appCurrencySource") . '</td>';
366
    print '<td class="right">';
367
    print '<input type="text" name="MULTICURRENCY_APP_SOURCE" value="' . getDolGlobalString('MULTICURRENCY_APP_SOURCE') . '" size="10" placeholder="USD" />&nbsp;'; // Default: USD
368
    print '</td></tr>';
369
370
    /*print '<tr class="oddeven">';
371
     print '<td>'.$langs->transnoentitiesnoconv("multicurrency_alternateCurrencySource").'</td>';
372
     print '<td class="right">';
373
     print '<input type="text" name="MULTICURRENCY_ALTERNATE_SOURCE" value="'.$conf->global->MULTICURRENCY_ALTERNATE_SOURCE.'" size="10" placeholder="EUR" />&nbsp;'; // Example: EUR
374
     print '</td></tr>';*/
375
376
    print '</table>';
377
    print '</div>';
378
    print '<br>';
379
380
    print '</form>';
381
}
382
383
384
// End of page
385
ViewMain::llxFooter();
386
$db->close();
387