Passed
Push — master ( 0759bd...698c48 )
by Julito
18:41
created

_api_get_person_name_convention()   C

Complexity

Conditions 12
Paths 50

Size

Total Lines 61
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 12
eloc 40
nc 50
nop 2
dl 0
loc 61
rs 6.9666
c 2
b 1
f 0

How to fix   Long Method    Complexity   

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
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Framework\Container;
5
use Patchwork\Utf8;
6
use Westsworld\TimeAgo;
7
8
/**
9
 * File: internationalization.lib.php
10
 * Internationalization library for Chamilo 1.x LMS
11
 * A library implementing internationalization related functions.
12
 * License: GNU General Public License Version 3 (Free Software Foundation)ww.
13
 *
14
 * @author Ivan Tcholakov, <[email protected]>, 2009, 2010
15
 * @author More authors, mentioned in the correpsonding fragments of this source.
16
 *
17
 * @package chamilo.library
18
 */
19
20
// Special tags for marking untranslated variables.
21
define('SPECIAL_OPENING_TAG', '[=');
22
define('SPECIAL_CLOSING_TAG', '=]');
23
24
// Predefined date formats in Chamilo provided by the language sub-system.
25
// To be used as a parameter for the function api_format_date()
26
27
define('TIME_NO_SEC_FORMAT', 0); // 15:23
28
define('DATE_FORMAT_SHORT', 1); // Aug 25, 09
29
define('DATE_FORMAT_LONG', 2); // Monday August 25, 09
30
define('DATE_FORMAT_LONG_NO_DAY', 10); // August 25, 2009
31
define('DATE_TIME_FORMAT_LONG', 3); // Monday August 25, 2009 at 03:28 PM
32
33
define('DATE_FORMAT_NUMBER', 4); // 25.08.09
34
define('DATE_TIME_FORMAT_LONG_24H', 5); // August 25, 2009 at 15:28
35
define('DATE_TIME_FORMAT_SHORT', 6); // Aug 25, 2009 at 03:28 PM
36
define('DATE_TIME_FORMAT_SHORT_TIME_FIRST', 7); // 03:28 PM, Aug 25 2009
37
define('DATE_FORMAT_NUMBER_NO_YEAR', 8); // 25.08 dd-mm
38
define('DATE_FORMAT_ONLY_DAYNAME', 9); // Monday, Sunday, etc
39
40
// Formatting person's name.
41
// Formatting a person's name using the pattern as it has been
42
// configured in the internationalization database for every language.
43
// This (default) option would be the most used.
44
define('PERSON_NAME_COMMON_CONVENTION', 0);
45
// The following options may be used in limited number of places for overriding the common convention:
46
47
// Formatting a person's name in Western order: first_name last_name
48
define('PERSON_NAME_WESTERN_ORDER', 1);
49
// Formatting a person's name in Eastern order: last_name first_name
50
define('PERSON_NAME_EASTERN_ORDER', 2);
51
// Contextual: formatting person's name in library order: last_name, first_name
52
define('PERSON_NAME_LIBRARY_ORDER', 3);
53
// Contextual: formatting a person's name assotiated with an email-address.
54
// Ivan: I am not sure how seems email servers an clients would interpret name order, so I assign the Western order.
55
define('PERSON_NAME_EMAIL_ADDRESS', PERSON_NAME_WESTERN_ORDER);
56
// Contextual: formatting a person's name for data-exporting operations.
57
// For backward compatibility this format has been set to Eastern order.
58
define('PERSON_NAME_DATA_EXPORT', PERSON_NAME_EASTERN_ORDER);
59
60
/**
61
 * Returns a translated (localized) string.
62
 *
63
 * @param string $variable
64
 *
65
 * @return string
66
 */
67
function get_lang($variable)
68
{
69
    $translator = Container::getTranslator();
70
71
    if (!$translator) {
0 ignored issues
show
introduced by
$translator is of type Symfony\Component\Translation\TranslatorInterface, thus it always evaluated to true.
Loading history...
72
        return $variable;
73
    }
74
75
    //return $variable;
76
    // Using symfony
77
    $defaultDomain = 'messages';
78
    $translated = Container::getTranslator()->trans(
79
        $variable,
80
        [],
81
        $defaultDomain
82
    );
83
84
    if ($translated == $variable) {
85
        // Check the langVariable for BC
86
        $translated = Container::getTranslator()->trans(
87
            "lang$variable",
88
            [],
89
            $defaultDomain
90
        );
91
92
        if ($translated == "lang$variable") {
93
            return $variable;
94
        }
95
    }
96
97
    return $translated;
98
99
    // For serving some old hacks:
100
    // By manipulating this global variable the translation may
101
    // be done in different languages too (not the elegant way).
102
    global $language_interface;
0 ignored issues
show
Unused Code introduced by
GlobalNode is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
103
    // Because of possibility for manipulations of the global
104
    // variable $language_interface, we need its initial value.
105
    global $language_interface_initial_value;
106
    global $used_lang_vars, $_configuration;
107
    // add language_measure_frequency to your main/inc/conf/configuration.php in order to generate language
108
    // variables frequency measurements (you can then see them trhough main/cron/lang/langstats.php)
109
    // The $langstats object is instanciated at the end of main/inc/global.inc.php
110
    if (isset($_configuration['language_measure_frequency']) &&
111
        $_configuration['language_measure_frequency'] == 1
112
    ) {
113
        require_once api_get_path(SYS_CODE_PATH).'/cron/lang/langstats.class.php';
114
        global $langstats;
115
        $langstats->add_use($variable, '');
116
    }
117
118
    if (!isset($used_lang_vars)) {
119
        $used_lang_vars = [];
120
    }
121
122
    // Caching results from some API functions, for speed.
123
    static $initialized, $show_special_markup;
124
    if (!isset($initialized)) {
125
        $test_server_mode = api_get_setting('server_type') === 'test';
126
        $show_special_markup = api_get_setting('hide_dltt_markup') != 'true' || $test_server_mode;
127
        $initialized = true;
128
    }
129
130
    // Combining both ways for requesting specific language.
131
    if (empty($language)) {
132
        $language = $language_interface;
133
    }
134
    $lang_postfix = isset($is_interface_language) && $is_interface_language ? '' : '('.$language.')';
135
136
    $is_interface_language = $language == $language_interface_initial_value;
137
138
    // This is a cache for already translated language variables. By using it, we avoid repetitive translations, gaining speed.
139
    static $cache;
140
141
    // Looking up into the cache for existing translation.
142
    if (isset($cache[$language][$variable])) {
143
        // There is a previously saved translation, returning it.
144
        //return $cache[$language][$variable];
145
        $ret = $cache[$language][$variable];
146
        $used_lang_vars[$variable.$lang_postfix] = $ret;
147
148
        return $ret;
149
    }
150
151
    // There is no cached translation, we have to retrieve it:
152
    // - from a global variable (the faster way) - on production server mode;
153
    // - from a local variable after reloading the language files - on test server mode or when requested language
154
    // is different than the genuine interface language.
155
    $read_global_variables = $is_interface_language;
156
157
    if ($read_global_variables) {
158
        if (isset($GLOBALS[$variable])) {
159
            $langvar = $GLOBALS[$variable];
160
        } elseif (isset($GLOBALS["lang$variable"])) {
161
            $langvar = $GLOBALS["lang$variable"];
162
        } else {
163
            $langvar = $show_special_markup ? SPECIAL_OPENING_TAG.$variable.SPECIAL_CLOSING_TAG : $variable;
164
        }
165
    }
166
    if (empty($langvar) || !is_string($langvar)) {
167
        $langvar = $show_special_markup ? SPECIAL_OPENING_TAG.$variable.SPECIAL_CLOSING_TAG : $variable;
168
    }
169
    $ret = $cache[$language][$variable] = $langvar;
170
    $used_lang_vars[$variable.$lang_postfix] = $ret;
171
172
    return $ret;
173
}
174
175
/**
176
 * Gets the current interface language.
177
 *
178
 * @param bool $purified              (optional)    When it is true, a purified (refined)
179
 *                                    language value will be returned, for example 'french' instead of 'french_unicode'
180
 * @param bool $setParentLanguageName
181
 *
182
 * @return string the current language of the interface
183
 */
184
function api_get_interface_language(
185
    $purified = false,
0 ignored issues
show
Unused Code introduced by
The parameter $purified is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

185
    /** @scrutinizer ignore-unused */ $purified = false,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
186
    $check_sub_language = false,
0 ignored issues
show
Unused Code introduced by
The parameter $check_sub_language is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

186
    /** @scrutinizer ignore-unused */ $check_sub_language = false,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
187
    $setParentLanguageName = true
0 ignored issues
show
Unused Code introduced by
The parameter $setParentLanguageName is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

187
    /** @scrutinizer ignore-unused */ $setParentLanguageName = true

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
188
) {
189
    return api_get_language_isocode();
190
}
191
192
/**
193
 * Returns a purified language id, without possible suffixes that will disturb language identification in certain cases.
194
 *
195
 * @param string $language the input language identificator, for example 'french_unicode'
196
 * @param string the same purified or filtered language id, for example 'french'
197
 *
198
 * @return string
199
 */
200
function api_purify_language_id($language)
201
{
202
    static $purified = [];
203
    if (!isset($purified[$language])) {
204
        $purified[$language] = trim(
205
            str_replace(
206
                ['_unicode', '_latin', '_corporate', '_org', '_km'],
207
                '',
208
                strtolower($language)
209
            )
210
        );
211
    }
212
213
    return $purified[$language];
214
}
215
216
/**
217
 * Gets language isocode.
218
 */
219
function api_get_language_isocode()
220
{
221
    return Container::getTranslator()->getLocale();
222
}
223
224
/**
225
 * Gets language iso code column from the language table.
226
 *
227
 * @return array An array with the current isocodes
228
 *
229
 * */
230
function api_get_platform_isocodes()
231
{
232
    $iso_code = [];
233
    $sql = "SELECT isocode 
234
            FROM ".Database::get_main_table(TABLE_MAIN_LANGUAGE)." 
235
            ORDER BY isocode ";
236
    $sql_result = Database::query($sql);
237
    if (Database::num_rows($sql_result)) {
238
        while ($row = Database::fetch_array($sql_result)) {
239
            $iso_code[] = trim($row['isocode']);
240
        }
241
    }
242
243
    return $iso_code;
244
}
245
246
/**
247
 * Gets text direction according to the given language.
248
 *
249
 * @param string $language This is the name of the
250
 *                         folder containing translations for the corresponding language (e.g 'arabic', 'english', ...).
251
 *                         ISO-codes are acceptable too ('ar', 'en', ...).
252
 *                         If $language is omitted, interface language is assumed then.
253
 *
254
 * @return string the correspondent to the language text direction ('ltr' or 'rtl')
255
 */
256
function api_get_text_direction($language = null)
257
{
258
    static $text_direction = [];
259
260
    if (empty($language)) {
261
        $language = api_get_interface_language();
262
    }
263
    if (!isset($text_direction[$language])) {
264
        $text_direction[$language] = in_array(
265
            api_purify_language_id($language),
266
            [
267
                'arabic',
268
                'ar',
269
                'dari',
270
                'prs',
271
                'hebrew',
272
                'he',
273
                'iw',
274
                'pashto',
275
                'ps',
276
                'persian',
277
                'fa',
278
                'ur',
279
                'yiddish',
280
                'yid',
281
            ]
282
        ) ? 'rtl' : 'ltr';
283
    }
284
285
    return $text_direction[$language];
286
}
287
288
/**
289
 * Returns an alphabetized list of timezones in an associative array
290
 * that can be used to populate a select.
291
 *
292
 * @return array List of timezone identifiers
293
 *
294
 * @author Guillaume Viguier <[email protected]>
295
 */
296
function api_get_timezones()
297
{
298
    $timezone_identifiers = DateTimeZone::listIdentifiers();
299
    sort($timezone_identifiers);
300
    $out = [];
301
    foreach ($timezone_identifiers as $tz) {
302
        $out[$tz] = $tz;
303
    }
304
    $null_option = ['' => ''];
305
    $result = array_merge($null_option, $out);
306
307
    return $result;
308
}
309
310
/**
311
 * Returns the timezone to be converted to/from, based on user or admin preferences.
312
 *
313
 * @return string The timezone chosen
314
 */
315
function api_get_timezone()
316
{
317
    // First, get the default timezone of the server
318
    $to_timezone = date_default_timezone_get();
319
    // Second, see if a timezone has been chosen for the platform
320
    $timezone_value = api_get_setting('timezone_value');
321
322
    if ($timezone_value != null) {
323
        $to_timezone = $timezone_value;
324
    }
325
326
    // If allowed by the administrator
327
    $useUsersTimezone = api_get_setting('use_users_timezone');
328
329
    if ($useUsersTimezone === 'true') {
330
        if (!api_is_anonymous()) {
331
            $userId = api_get_user_id();
332
            // Get the timezone based on user preference, if it exists
333
            $userTimezone = UserManager::get_extra_user_data_by_field(
334
                $userId,
335
                'timezone'
336
            );
337
            if (isset($userTimezone['timezone']) && $userTimezone['timezone'] != null) {
338
                $to_timezone = $userTimezone['timezone'];
339
            }
340
        }
341
    }
342
343
    return $to_timezone;
344
}
345
346
/**
347
 * Returns the given date as a DATETIME in UTC timezone.
348
 * This function should be used before entering any date in the DB.
349
 *
350
 * @param mixed $time                    date to be converted (can be a string supported by date() or a timestamp)
351
 * @param bool  $returnNullIfInvalidDate if the date is not correct return null instead of the current date
352
 * @param bool  $returnObj
353
 *
354
 * @return string|DateTime The DATETIME in UTC to be inserted in the DB,
355
 *                         or null if the format of the argument is not supported
356
 *                         or datetime
357
 *
358
 * @author Julio Montoya - Adding the 2nd parameter
359
 * @author Guillaume Viguier <[email protected]>
360
 */
361
function api_get_utc_datetime(
362
    $time = null,
363
    $returnNullIfInvalidDate = false,
364
    $returnObj = false
365
) {
366
    if (is_null($time) || empty($time) || $time === '0000-00-00 00:00:00') {
367
        if ($returnNullIfInvalidDate) {
368
            return null;
369
        }
370
        if ($returnObj) {
371
            return new DateTime(gmdate('Y-m-d H:i:s'), new DateTimeZone('UTC'));
372
        }
373
374
        return gmdate('Y-m-d H:i:s');
375
    }
376
377
    // If time is a timestamp, return directly in utc
378
    if (is_numeric($time)) {
379
        $time = (int) $time;
380
381
        return gmdate('Y-m-d H:i:s', $time);
382
    }
383
    try {
384
        $fromTimezone = api_get_timezone();
385
        $date = new DateTime($time, new DateTimezone($fromTimezone));
386
        $date->setTimezone(new DateTimeZone('UTC'));
387
        if ($returnObj) {
388
            return $date;
389
        } else {
390
            return $date->format('Y-m-d H:i:s');
391
        }
392
    } catch (Exception $e) {
393
        error_log($e->getMessage());
394
395
        return null;
396
    }
397
}
398
399
/**
400
 * Returns a DATETIME string converted to the right timezone.
401
 *
402
 * @param mixed The time to be converted
403
 * @param string The timezone to be converted to.
404
 * If null, the timezone will be determined based on user preference,
405
 * or timezone chosen by the admin for the platform.
406
 * @param string The timezone to be converted from. If null, UTC will be assumed.
407
 *
408
 * @return string The converted time formatted as Y-m-d H:i:s
409
 *
410
 * @author Guillaume Viguier <[email protected]>
411
 */
412
function api_get_local_time(
413
    $time = null,
414
    $to_timezone = null,
415
    $from_timezone = null,
416
    $return_null_if_invalid_date = false,
417
    $showTime = true,
418
    $humanForm = false
419
) {
420
    // Determining the timezone to be converted from
421
    if (is_null($from_timezone)) {
422
        $from_timezone = 'UTC';
423
    }
424
425
    // If time is a timestamp, convert it to a string
426
    if (is_null($time) || empty($time) || $time == '0000-00-00 00:00:00') {
427
        if ($return_null_if_invalid_date) {
428
            return null;
429
        }
430
        $from_timezone = 'UTC';
431
        $time = gmdate('Y-m-d H:i:s');
432
    }
433
434
    if (is_numeric($time)) {
435
        $time = (int) $time;
436
        if ($return_null_if_invalid_date) {
437
            if (strtotime(date('d-m-Y H:i:s', $time)) !== (int) $time) {
438
                return null;
439
            }
440
        }
441
442
        $from_timezone = 'UTC';
443
        $time = gmdate('Y-m-d H:i:s', $time);
444
    }
445
    if ($time instanceof DateTime) {
446
        $time = $time->format('Y-m-d H:i:s');
447
        $from_timezone = 'UTC';
448
    }
449
450
    try {
451
        // Determining the timezone to be converted to
452
        if (is_null($to_timezone)) {
453
            $to_timezone = api_get_timezone();
454
        }
455
456
        $date = new DateTime($time, new DateTimezone($from_timezone));
457
        $date->setTimezone(new DateTimeZone($to_timezone));
458
459
        return api_get_human_date_time($date, $showTime, $humanForm);
460
    } catch (Exception $e) {
461
        return '';
462
    }
463
}
464
465
/**
466
 * Converts a string into a timestamp safely (handling timezones), using strtotime.
467
 *
468
 * @param string $time     to be converted
469
 * @param string $timezone (if null, the timezone will be determined based
470
 *                         on user preference, or timezone chosen by the admin for the platform)
471
 *
472
 * @return int Timestamp
473
 *
474
 * @author Guillaume Viguier <[email protected]>
475
 */
476
function api_strtotime($time, $timezone = null)
477
{
478
    $system_timezone = date_default_timezone_get();
479
    if (!empty($timezone)) {
480
        date_default_timezone_set($timezone);
481
    }
482
    $timestamp = strtotime($time);
483
    if (!empty($timezone)) {
484
        // only reset timezone if it was changed
485
        date_default_timezone_set($system_timezone);
486
    }
487
488
    return $timestamp;
489
}
490
491
/**
492
 * Returns formatted date/time, correspondent to a given language.
493
 * The given date should be in the timezone chosen by the administrator
494
 * and/or user. Use api_get_local_time to get it.
495
 *
496
 * @author Patrick Cool <[email protected]>, Ghent University
497
 * @author Christophe Gesche<[email protected]>
498
 *         originally inspired from from PhpMyAdmin
499
 * @author Ivan Tcholakov, 2009, code refactoring, adding support for predefined date/time formats.
500
 * @author Guillaume Viguier <[email protected]>
501
 *
502
 * @param mixed $time Timestamp or datetime string
503
 * @param string|int Date format (see date formats in the Chamilo system:
504
 * TIME_NO_SEC_FORMAT,
505
 * DATE_FORMAT_SHORT,
506
 * DATE_FORMAT_LONG,
507
 * DATE_TIME_FORMAT_LONG
508
 * @param string $language (optional) Language id
509
 *                         If it is omitted, the current interface language is assumed
510
 *
511
 * @return string returns the formatted date
512
 *
513
 * @see http://php.net/manual/en/function.strftime.php
514
 */
515
function api_format_date($time, $format = null, $language = null)
516
{
517
    if (empty($time)) {
518
        return '';
519
    }
520
521
    $system_timezone = date_default_timezone_get();
522
    date_default_timezone_set(api_get_timezone());
523
524
    if (is_string($time)) {
525
        $time = strtotime($time);
526
    }
527
528
    if (is_null($format)) {
529
        $format = DATE_TIME_FORMAT_LONG;
530
    }
531
532
    $datetype = null;
533
    $timetype = null;
534
535
    if (is_int($format)) {
536
        switch ($format) {
537
            case DATE_FORMAT_ONLY_DAYNAME:
538
                $date_format = get_lang('dateFormatOnlyDayName', '', $language);
539
                if (INTL_INSTALLED) {
540
                    $datetype = IntlDateFormatter::SHORT;
541
                    $timetype = IntlDateFormatter::NONE;
542
                }
543
                break;
544
            case DATE_FORMAT_NUMBER_NO_YEAR:
545
                $date_format = get_lang('dateFormatShortNumberNoYear', '', $language);
546
                if (INTL_INSTALLED) {
547
                    $datetype = IntlDateFormatter::SHORT;
548
                    $timetype = IntlDateFormatter::NONE;
549
                }
550
                break;
551
            case DATE_FORMAT_NUMBER:
552
                $date_format = get_lang('dateFormatShortNumber', '', $language);
553
                if (INTL_INSTALLED) {
554
                    $datetype = IntlDateFormatter::SHORT;
555
                    $timetype = IntlDateFormatter::NONE;
556
                }
557
                break;
558
            case TIME_NO_SEC_FORMAT:
559
                $date_format = get_lang('timeNoSecFormat', '', $language);
560
                if (INTL_INSTALLED) {
561
                    $datetype = IntlDateFormatter::NONE;
562
                    $timetype = IntlDateFormatter::SHORT;
563
                }
564
                break;
565
            case DATE_FORMAT_SHORT:
566
                $date_format = get_lang('dateFormatShort', '', $language);
567
                if (INTL_INSTALLED) {
568
                    $datetype = IntlDateFormatter::LONG;
569
                    $timetype = IntlDateFormatter::NONE;
570
                }
571
                break;
572
            case DATE_FORMAT_LONG:
573
                $date_format = get_lang('dateFormatLong', '', $language);
574
                if (INTL_INSTALLED) {
575
                    $datetype = IntlDateFormatter::FULL;
576
                    $timetype = IntlDateFormatter::NONE;
577
                }
578
                break;
579
            case DATE_TIME_FORMAT_LONG:
580
                $date_format = get_lang('dateTimeFormatLong', '', $language);
581
                if (INTL_INSTALLED) {
582
                    $datetype = IntlDateFormatter::FULL;
583
                    $timetype = IntlDateFormatter::SHORT;
584
                }
585
                break;
586
            case DATE_FORMAT_LONG_NO_DAY:
587
                $date_format = get_lang('dateFormatLongNoDay', '', $language);
588
                if (INTL_INSTALLED) {
589
                    $datetype = IntlDateFormatter::FULL;
590
                    $timetype = IntlDateFormatter::SHORT;
591
                }
592
                break;
593
            case DATE_TIME_FORMAT_SHORT:
594
                $date_format = get_lang('dateTimeFormatShort', '', $language);
595
                if (INTL_INSTALLED) {
596
                    $datetype = IntlDateFormatter::FULL;
597
                    $timetype = IntlDateFormatter::SHORT;
598
                }
599
                break;
600
            case DATE_TIME_FORMAT_SHORT_TIME_FIRST:
601
                $date_format = get_lang('dateTimeFormatShortTimeFirst', '', $language);
602
                if (INTL_INSTALLED) {
603
                    $datetype = IntlDateFormatter::FULL;
604
                    $timetype = IntlDateFormatter::SHORT;
605
                }
606
                break;
607
            case DATE_TIME_FORMAT_LONG_24H:
608
                $date_format = get_lang('dateTimeFormatLong24H', '', $language);
609
                if (INTL_INSTALLED) {
610
                    $datetype = IntlDateFormatter::FULL;
611
                    $timetype = IntlDateFormatter::SHORT;
612
                }
613
                break;
614
            default:
615
                $date_format = get_lang('dateTimeFormatLong', '', $language);
616
                if (INTL_INSTALLED) {
617
                    $datetype = IntlDateFormatter::FULL;
618
                    $timetype = IntlDateFormatter::SHORT;
619
                }
620
        }
621
    } else {
622
        $date_format = $format;
623
    }
624
625
    if (0) {
626
        //if using PHP 5.3 format dates like: $dateFormatShortNumber, can't be used
627
        //
628
        // Use ICU
629
        if (is_null($language)) {
630
            $language = api_get_language_isocode();
631
        }
632
        $date_formatter = new IntlDateFormatter($language, $datetype, $timetype, date_default_timezone_get());
633
        //$date_formatter->setPattern($date_format);
634
        $formatted_date = api_to_system_encoding($date_formatter->format($time), 'UTF-8');
635
    } else {
636
        // We replace %a %A %b %B masks of date format with translated strings
637
        $translated = &_api_get_day_month_names($language);
638
        $date_format = str_replace(
639
            ['%A', '%a', '%B', '%b'],
640
            [
641
                $translated['days_long'][(int) strftime('%w', $time)],
642
                $translated['days_short'][(int) strftime('%w', $time)],
643
                $translated['months_long'][(int) strftime('%m', $time) - 1],
644
                $translated['months_short'][(int) strftime('%m', $time) - 1],
645
            ],
646
            $date_format
647
        );
648
        $formatted_date = api_to_system_encoding(strftime($date_format, $time), 'UTF-8');
649
    }
650
    date_default_timezone_set($system_timezone);
651
652
    return $formatted_date;
653
}
654
655
/**
656
 * Returns the difference between the current date (date(now)) with the parameter
657
 * $date in a string format like "2 days ago, 1 hour ago".
658
 * You can use it like this:
659
 * Display::dateToStringAgoAndLongDate($dateInUtc);.
660
 *
661
 * @param string $date     Result of a date function in this format -> date('Y-m-d H:i:s', time());
662
 * @param string $timeZone
663
 *
664
 * @return string
665
 *
666
 * @author Julio Montoya
667
 */
668
function date_to_str_ago($date, $timeZone = 'UTC')
669
{
670
    if ($date === '0000-00-00 00:00:00') {
671
        return '';
672
    }
673
674
    $getOldTimezone = api_get_timezone();
675
    $isoCode = api_get_language_isocode();
676
    if ($isoCode == 'pt') {
677
        $isoCode = 'pt-BR';
678
    }
679
    $checkFile = api_get_path(SYS_PATH).'vendor/jimmiw/php-time-ago/translations/'.$isoCode.'.php';
680
    if (!file_exists($checkFile)) {
681
        $isoCode = 'en';
682
    }
683
    $timeAgo = new TimeAgo($timeZone, $isoCode);
684
    $value = $timeAgo->inWords($date);
685
686
    date_default_timezone_set($getOldTimezone);
687
688
    return $value;
689
}
690
691
/**
692
 * Converts a date to the right timezone and localizes it in the format given as an argument.
693
 *
694
 * @param mixed The time to be converted
695
 * @param mixed Format to be used (TIME_NO_SEC_FORMAT, DATE_FORMAT_SHORT, DATE_FORMAT_LONG, DATE_TIME_FORMAT_LONG)
696
 * @param string Timezone to be converted from. If null, UTC will be assumed.
697
 *
698
 * @return string Converted and localized date
699
 *
700
 * @author Guillaume Viguier <[email protected]>
701
 */
702
function api_convert_and_format_date($time = null, $format = null, $from_timezone = null)
703
{
704
    // First, convert the datetime to the right timezone
705
    $time = api_get_local_time($time, null, $from_timezone, true);
706
    // Second, localize the date
707
    return api_format_date($time, $format);
708
}
709
710
/**
711
 * Returns an array of translated week days in short names.
712
 *
713
 * @param string $language (optional) Language id. If it is omitted, the current interface language is assumed.
714
 *
715
 * @return string Returns an array of week days (short names).
716
 *                Example: api_get_week_days_short('english') means array('Sun', 'Mon', ... 'Sat').
717
 *                Note: For all languges returned days are in the English order.
718
 */
719
function api_get_week_days_short($language = null)
720
{
721
    $days = &_api_get_day_month_names($language);
722
723
    return $days['days_short'];
724
}
725
726
/**
727
 * Returns an array of translated week days.
728
 *
729
 * @param string $language (optional) Language id. If it is omitted,
730
 *                         the current interface language is assumed.
731
 *
732
 * @return string Returns an array of week days.
733
 *                Example: api_get_week_days_long('english') means array('Sunday, 'Monday', ... 'Saturday').
734
 *                Note: For all languges returned days are in the English order.
735
 */
736
function api_get_week_days_long($language = null)
737
{
738
    $days = &_api_get_day_month_names($language);
739
740
    return $days['days_long'];
741
}
742
743
/**
744
 * Returns an array of translated months in short names.
745
 *
746
 * @param string $language (optional)    Language id.
747
 *                         If it is omitted, the current interface language is assumed.
748
 *
749
 * @return string Returns an array of months (short names).
750
 *                Example: api_get_months_short('english') means array('Jan', 'Feb', ... 'Dec').
751
 */
752
function api_get_months_short($language = null)
753
{
754
    $months = &_api_get_day_month_names($language);
755
756
    return $months['months_short'];
757
}
758
759
/**
760
 * Returns an array of translated months.
761
 *
762
 * @param string $language (optional)    Language id.
763
 *                         If it is omitted, the current interface language is assumed.
764
 *
765
 * @return string Returns an array of months.
766
 *                Example: api_get_months_long('english') means array('January, 'February' ... 'December').
767
 */
768
function api_get_months_long($language = null)
769
{
770
    $months = &_api_get_day_month_names($language);
771
772
    return $months['months_long'];
773
}
774
775
/**
776
 * Name order conventions.
777
 */
778
779
/**
780
 * Builds a person (full) name depending on the convention for a given language.
781
 *
782
 * @param string     $first_name the first name of the person
783
 * @param string     $last_name  the last name of the person
784
 * @param string     $title      the title of the person
785
 * @param int|string $format     (optional) The person name format.
786
 *                               It may be a pattern-string (for example '%t %l, %f' or '%T %F %L', ...) or
787
 *                               some of the constants
788
 *                               PERSON_NAME_COMMON_CONVENTION (default),
789
 *                               PERSON_NAME_WESTERN_ORDER,
790
 *                               PERSON_NAME_EASTERN_ORDER,
791
 *                               PERSON_NAME_LIBRARY_ORDER.
792
 * @param string     $language   (optional)
793
 *                               The language id. If it is omitted, the current interface language is assumed.
794
 *                               This parameter has meaning with the format PERSON_NAME_COMMON_CONVENTION only.
795
 * @param string     $username
796
 *
797
 * @return string The result is sort of full name of the person.
798
 *                Sample results:
799
 *                Peter Ustinoff or Dr. Peter Ustinoff     - the Western order
800
 *                Ustinoff Peter or Dr. Ustinoff Peter     - the Eastern order
801
 *                Ustinoff, Peter or - Dr. Ustinoff, Peter - the library order
802
 *                Note: See the file main/inc/lib/internationalization_database/name_order_conventions.php
803
 *                where you can check the convention for your language.
804
 *
805
 * @author Carlos Vargas <[email protected]> - initial implementation.
806
 * @author Ivan Tcholakov
807
 */
808
function api_get_person_name(
809
    $first_name,
810
    $last_name,
811
    $title = null,
812
    $format = null,
813
    $language = null,
814
    $username = null
815
) {
816
    static $valid = [];
817
    if (empty($format)) {
818
        $format = PERSON_NAME_COMMON_CONVENTION;
819
    }
820
    // We check if the language is supported, otherwise we check the
821
    // interface language of the parent language of sublanguage
822
    if (empty($language)) {
823
        // Do not set $setParentLanguageName because this function is called before
824
        // the main language is loaded in global.inc.php
825
        $language = api_get_interface_language(false, true, false);
826
    }
827
828
    if (!isset($valid[$format][$language])) {
829
        if (is_int($format)) {
830
            switch ($format) {
831
                case PERSON_NAME_COMMON_CONVENTION:
832
                    $valid[$format][$language] = _api_get_person_name_convention($language, 'format');
833
                    $usernameOrderFromDatabase = api_get_setting('user_name_order');
834
                    if (isset($usernameOrderFromDatabase) && !empty($usernameOrderFromDatabase)) {
835
                        $valid[$format][$language] = $usernameOrderFromDatabase;
836
                    }
837
                    break;
838
                case PERSON_NAME_WESTERN_ORDER:
839
                    $valid[$format][$language] = '%t %f %l';
840
                    break;
841
                case PERSON_NAME_EASTERN_ORDER:
842
                    $valid[$format][$language] = '%t %l %f';
843
                    break;
844
                case PERSON_NAME_LIBRARY_ORDER:
845
                    $valid[$format][$language] = '%t %l, %f';
846
                    break;
847
                default:
848
                    $valid[$format][$language] = '%t %f %l';
849
                    break;
850
            }
851
        } else {
852
            $valid[$format][$language] = _api_validate_person_name_format($format);
853
        }
854
    }
855
856
    $format = $valid[$format][$language];
857
858
    $keywords = [
859
        '%firstname',
860
        '%f',
861
        '%F',
862
        '%lastname',
863
        '%l',
864
        '%L',
865
        '%title',
866
        '%t',
867
        '%T',
868
        '%username',
869
        '%u',
870
        '%U',
871
    ];
872
873
    $values = [
874
        $first_name,
875
        $first_name,
876
        api_strtoupper($first_name),
877
        $last_name,
878
        $last_name,
879
        api_strtoupper($last_name),
880
        $title,
881
        $title,
882
        api_strtoupper($title),
883
        $username,
884
        $username,
885
        api_strtoupper($username),
886
    ];
887
    $person_name = str_replace($keywords, $values, $format);
888
889
    return _api_clean_person_name($person_name);
890
}
891
892
/**
893
 * Checks whether a given format represents person name in Western order (for which first name is first).
894
 *
895
 * @param int|string $format   (optional)    The person name format.
896
 *                             It may be a pattern-string (for example '%t. %l, %f') or some of the constants
897
 *                             PERSON_NAME_COMMON_CONVENTION (default),
898
 *                             PERSON_NAME_WESTERN_ORDER,
899
 *                             PERSON_NAME_EASTERN_ORDER,
900
 *                             PERSON_NAME_LIBRARY_ORDER.
901
 * @param string     $language (optional) The language id. If it is omitted,
902
 *                             the current interface language is assumed. This parameter has meaning with the
903
 *                             format PERSON_NAME_COMMON_CONVENTION only.
904
 *
905
 * @return bool The result TRUE means that the order is first_name last_name,
906
 *              FALSE means last_name first_name.
907
 *              Note: You may use this function for determining the order of the fields or
908
 *              columns "First name" and "Last name" in forms, tables and reports.
909
 *
910
 * @author Ivan Tcholakov
911
 */
912
function api_is_western_name_order($format = null, $language = null)
913
{
914
    static $order = [];
915
    if (empty($format)) {
916
        $format = PERSON_NAME_COMMON_CONVENTION;
917
    }
918
919
    if (empty($language)) {
920
        $language = api_get_interface_language(false, true);
921
    }
922
    if (!isset($order[$format][$language])) {
923
        $test_name = api_get_person_name('%f', '%l', '%t', $format, $language);
924
        $order[$format][$language] = stripos($test_name, '%f') <= stripos($test_name, '%l');
925
    }
926
927
    return $order[$format][$language];
928
}
929
930
/**
931
 * Returns a directive for sorting person names depending on a given language
932
 * and based on the options in the internationalization "database".
933
 *
934
 * @param string $language (optional) The input language.
935
 *                         If it is omitted, the current interface language is assumed.
936
 *
937
 * @return bool Returns boolean value. TRUE means ORDER BY first_name, last_name
938
 *              FALSE means ORDER BY last_name, first_name.
939
 *              Note: You may use this function:
940
 *              2. for constructing the ORDER clause of SQL queries, related to first_name and last_name;
941
 *              3. for adjusting php-implemented sorting in tables and reports.
942
 *
943
 * @author Ivan Tcholakov
944
 */
945
function api_sort_by_first_name($language = null)
946
{
947
    static $sort_by_first_name = [];
948
949
    if (empty($language)) {
950
        $language = api_get_interface_language(false, true);
951
    }
952
    if (!isset($sort_by_first_name[$language])) {
953
        $sort_by_first_name[$language] = _api_get_person_name_convention($language, 'sort_by');
954
    }
955
956
    return $sort_by_first_name[$language];
957
}
958
959
/**
960
 * Multibyte string conversion functions.
961
 */
962
963
/**
964
 * Converts character encoding of a given string.
965
 *
966
 * @param string $string        the string being converted
967
 * @param string $to_encoding   the encoding that $string is being converted to
968
 * @param string $from_encoding (optional)    The encoding that $string is being converted from.
969
 *                              If it is omitted, the platform character set is assumed.
970
 *
971
 * @return string Returns the converted string.
972
 *                This function is aimed at replacing the function mb_convert_encoding() for human-language strings.
973
 *
974
 * @see http://php.net/manual/en/function.mb-convert-encoding
975
 */
976
function api_convert_encoding($string, $to_encoding, $from_encoding = 'UTF-8')
977
{
978
    if (strtoupper($to_encoding) === strtoupper($from_encoding)) {
979
        return $string;
980
    }
981
982
    return mb_convert_encoding($string, $to_encoding, $from_encoding);
983
}
984
985
/**
986
 * Converts a given string into UTF-8 encoded string.
987
 *
988
 * @param string $string        the string being converted
989
 * @param string $from_encoding (optional) The encoding that $string is being converted from.
990
 *                              If it is omitted, the platform character set is assumed.
991
 *
992
 * @return string Returns the converted string.
993
 *                This function is aimed at replacing the function utf8_encode() for human-language strings.
994
 *
995
 * @see http://php.net/manual/en/function.utf8-encode
996
 */
997
function api_utf8_encode($string, $from_encoding = 'UTF-8')
998
{
999
    return mb_convert_encoding($string, 'UTF-8', $from_encoding);
1000
}
1001
1002
/**
1003
 * Converts a given string from UTF-8 encoding to a specified encoding.
1004
 *
1005
 * @param string $string      the string being converted
1006
 * @param string $to_encoding (optional)    The encoding that $string is being converted to.
1007
 *                            If it is omitted, the platform character set is assumed.
1008
 *
1009
 * @return string Returns the converted string.
1010
 *                This function is aimed at replacing the function utf8_decode() for human-language strings.
1011
 *
1012
 * @see http://php.net/manual/en/function.utf8-decode
1013
 */
1014
function api_utf8_decode($string, $to_encoding = null)
1015
{
1016
    return mb_convert_encoding($string, $to_encoding, 'UTF-8');
1017
}
1018
1019
/**
1020
 * Converts a given string into the system encoding (or platform character set).
1021
 * When $from encoding is omitted on UTF-8 platforms then language dependent encoding
1022
 * is guessed/assumed. On non-UTF-8 platforms omitted $from encoding is assumed as UTF-8.
1023
 * When the parameter $check_utf8_validity is true the function checks string's
1024
 * UTF-8 validity and decides whether to try to convert it or not.
1025
 * This function is useful for problem detection or making workarounds.
1026
 *
1027
 * @param string $string              the string being converted
1028
 * @param string $from_encoding       (optional) The encoding that $string is being converted from.
1029
 *                                    It is guessed when it is omitted.
1030
 * @param bool   $check_utf8_validity (optional)    A flag for UTF-8 validity check as condition for making conversion
1031
 *
1032
 * @return string returns the converted string
1033
 */
1034
function api_to_system_encoding($string, $from_encoding = null, $check_utf8_validity = false)
0 ignored issues
show
Unused Code introduced by
The parameter $check_utf8_validity is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1034
function api_to_system_encoding($string, $from_encoding = null, /** @scrutinizer ignore-unused */ $check_utf8_validity = false)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1035
{
1036
    $system_encoding = api_get_system_encoding();
1037
1038
    return api_convert_encoding($string, $system_encoding, $from_encoding);
1039
}
1040
1041
/**
1042
 * Converts all applicable characters to HTML entities.
1043
 *
1044
 * @param string $string      the input string
1045
 * @param int    $quote_style (optional)    The quote style - ENT_COMPAT (default), ENT_QUOTES, ENT_NOQUOTES
1046
 * @param string $encoding    (optional)    The encoding (of the input string) used in conversion.
1047
 *                            If it is omitted, the platform character set is assumed.
1048
 *
1049
 * @return string Returns the converted string.
1050
 *                This function is aimed at replacing the function htmlentities() for human-language strings.
1051
 *
1052
 * @see http://php.net/manual/en/function.htmlentities
1053
 */
1054
function api_htmlentities($string, $quote_style = ENT_COMPAT, $encoding = 'UTF-8')
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1054
function api_htmlentities($string, $quote_style = ENT_COMPAT, /** @scrutinizer ignore-unused */ $encoding = 'UTF-8')

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1055
{
1056
    switch ($quote_style) {
1057
        case ENT_COMPAT:
1058
            $string = str_replace(['&', '"', '<', '>'], ['&amp;', '&quot;', '&lt;', '&gt;'], $string);
1059
            break;
1060
        case ENT_QUOTES:
1061
            $string = str_replace(['&', '\'', '"', '<', '>'], ['&amp;', '&#039;', '&quot;', '&lt;', '&gt;'], $string);
1062
            break;
1063
    }
1064
1065
    return mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8');
1066
}
1067
1068
/**
1069
 * Converts HTML entities into normal characters.
1070
 *
1071
 * @param string $string      the input string
1072
 * @param int    $quote_style (optional)    The quote style - ENT_COMPAT (default), ENT_QUOTES, ENT_NOQUOTES
1073
 * @param string $encoding    (optional)    The encoding (of the result) used in conversion.
1074
 *                            If it is omitted, the platform character set is assumed.
1075
 *
1076
 * @return string Returns the converted string.
1077
 *                This function is aimed at replacing the function html_entity_decode() for human-language strings.
1078
 *
1079
 * @see http://php.net/html_entity_decode
1080
 */
1081
function api_html_entity_decode($string, $quote_style = ENT_COMPAT, $encoding = 'UTF-8')
1082
{
1083
    if (empty($encoding)) {
1084
        $encoding = _api_mb_internal_encoding();
1085
    }
1086
    if (api_is_encoding_supported($encoding)) {
1087
        if (!api_is_utf8($encoding)) {
1088
            $string = api_utf8_encode($string, $encoding);
1089
        }
1090
        $string = html_entity_decode($string, $quote_style, 'UTF-8');
1091
        if (!api_is_utf8($encoding)) {
1092
            return api_utf8_decode($string, $encoding);
1093
        }
1094
1095
        return $string;
1096
    }
1097
1098
    return $string; // Here the function gives up.
1099
}
1100
1101
/**
1102
 * This function encodes (conditionally) a given string to UTF-8 if XmlHttp-request has been detected.
1103
 *
1104
 * @param string $string        the string being converted
1105
 * @param string $from_encoding (optional)    The encoding that $string is being converted from.
1106
 *                              If it is omitted, the platform character set is assumed.
1107
 *
1108
 * @return string returns the converted string
1109
 */
1110
function api_xml_http_response_encode($string, $from_encoding = 'UTF8')
1111
{
1112
    if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
1113
        if (empty($from_encoding)) {
1114
            $from_encoding = _api_mb_internal_encoding();
1115
        }
1116
        if (!api_is_utf8($from_encoding)) {
1117
            return api_utf8_encode($string, $from_encoding);
1118
        }
1119
    }
1120
1121
    return $string;
1122
}
1123
1124
/**
1125
 * Transliterates a string with arbitrary encoding into a plain ASCII string.
1126
 *
1127
 * Example:
1128
 * echo api_transliterate(api_html_entity_decode(
1129
 *    '&#1060;&#1105;&#1076;&#1086;&#1088; '.
1130
 *    '&#1052;&#1080;&#1093;&#1072;&#1081;&#1083;&#1086;&#1074;&#1080;&#1095; '.
1131
 *    '&#1044;&#1086;&#1089;&#1090;&#1086;&#1077;&#1074;&#1082;&#1080;&#1081;',
1132
 *    ENT_QUOTES, 'UTF-8'), 'X', 'UTF-8');
1133
 * The output should be: Fyodor Mihaylovich Dostoevkiy
1134
 *
1135
 * @param string $string        the input string
1136
 * @param string $unknown       (optional) Replacement character for unknown characters and illegal UTF-8 sequences
1137
 * @param string $from_encoding (optional) The encoding of the input string.
1138
 *                              If it is omitted, the platform character set is assumed.
1139
 *
1140
 * @return string plain ASCII output
1141
 */
1142
function api_transliterate($string, $unknown = '?', $from_encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $unknown is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1142
function api_transliterate($string, /** @scrutinizer ignore-unused */ $unknown = '?', $from_encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $from_encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1142
function api_transliterate($string, $unknown = '?', /** @scrutinizer ignore-unused */ $from_encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1143
{
1144
    return URLify::transliterate($string);
1145
}
1146
1147
/**
1148
 * Takes the first character in a string and returns its Unicode codepoint.
1149
 *
1150
 * @param string $character the input string
1151
 * @param string $encoding  (optional) The encoding of the input string.
1152
 *                          If it is omitted, the platform character set will be used by default.
1153
 *
1154
 * @return int Returns: the codepoint of the first character; or 0xFFFD (unknown character) when the input string is empty.
1155
 *             This is a multibyte aware version of the function ord().
1156
 *
1157
 * @see http://php.net/manual/en/function.ord.php
1158
 * Note the difference with the original funtion ord(): ord('') returns 0, api_ord('') returns 0xFFFD (unknown character).
1159
 */
1160
function api_ord($character, $encoding = 'UTF-8')
1161
{
1162
    return Utf8::ord(api_utf8_encode($character, $encoding));
1163
}
1164
1165
/**
1166
 * This function returns a string or an array with all occurrences of search
1167
 * in subject (ignoring case) replaced with the given replace value.
1168
 *
1169
 * @param mixed  $search   string or array of strings to be found
1170
 * @param mixed  $replace  string or array of strings used for replacement
1171
 * @param mixed  $subject  string or array of strings being searched
1172
 * @param int    $count    (optional) The number of matched and replaced needles
1173
 *                         will be returned in count, which is passed by reference
1174
 * @param string $encoding (optional) The used internally by this function character encoding.
1175
 *                         If it is omitted, the platform character set will be used by default.
1176
 *
1177
 * @return mixed String or array as a result.
1178
 *               Notes:
1179
 *               If $subject is an array, then the search and replace is performed with
1180
 *               every entry of subject, the return value is an array.
1181
 *               If $search and $replace are arrays, then the function takes a value from
1182
 *               each array and uses it to do search and replace on subject.
1183
 *               If $replace has fewer values than search, then an empty string is used for the rest of replacement values.
1184
 *               If $search is an array and $replace is a string, then this replacement string is used for every value of search.
1185
 *               This function is aimed at replacing the function str_ireplace() for human-language strings.
1186
 *
1187
 * @see http://php.net/manual/en/function.str-ireplace
1188
 *
1189
 * @author Henri Sivonen, mailto:[email protected]
1190
 *
1191
 * @see http://hsivonen.iki.fi/php-utf8/
1192
 * Adaptation for Chamilo 1.8.7, 2010
1193
 * Initial implementation Dokeos LMS, August 2009
1194
 *
1195
 * @author Ivan Tcholakov
1196
 */
1197
function api_str_ireplace($search, $replace, $subject, &$count = null, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1197
function api_str_ireplace($search, $replace, $subject, &$count = null, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1198
{
1199
    return Utf8::str_ireplace($search, $replace, $subject, $count);
1200
}
1201
1202
/**
1203
 * Converts a string to an array.
1204
 *
1205
 * @param string $string       the input string
1206
 * @param int    $split_length maximum character-length of the chunk, one character by default
1207
 * @param string $encoding     (optional) The used internally by this function
1208
 *                             character encoding. If it is omitted, the platform character set will be used by default.
1209
 *
1210
 * @return array The result array of chunks with the spcified length.
1211
 *               Notes:
1212
 *               If the optional split_length parameter is specified, the returned array will be broken down into chunks
1213
 *               with each being split_length in length, otherwise each chunk will be one character in length.
1214
 *               FALSE is returned if split_length is less than 1.
1215
 *               If the split_length length exceeds the length of string, the entire string is returned as the first (and only) array element.
1216
 *               This function is aimed at replacing the function str_split() for human-language strings.
1217
 *
1218
 * @see http://php.net/str_split
1219
 */
1220
function api_str_split($string, $split_length = 1, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1220
function api_str_split($string, $split_length = 1, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1221
{
1222
    return Utf8::str_split($string, $split_length);
1223
}
1224
1225
/**
1226
 * Finds position of first occurrence of a string within another, case insensitive.
1227
 *
1228
 * @param string $haystack the string from which to get the position of the first occurrence
1229
 * @param string $needle   the string to be found
1230
 * @param int    $offset   The position in $haystack to start searching from.
1231
 *                         If it is omitted, searching starts from the beginning.
1232
 * @param string $encoding (optional) The used internally by this function
1233
 *                         character encoding. If it is omitted, the platform character set will be used by default.
1234
 *
1235
 * @return mixed Returns the numeric position of the first occurrence of
1236
 *               $needle in the $haystack, or FALSE if $needle is not found.
1237
 *               Note: The first character's position is 0, the second character position is 1, and so on.
1238
 *               This function is aimed at replacing the functions stripos() and mb_stripos() for human-language strings.
1239
 *
1240
 * @see http://php.net/manual/en/function.stripos
1241
 * @see http://php.net/manual/en/function.mb-stripos
1242
 */
1243
function api_stripos($haystack, $needle, $offset = 0, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1243
function api_stripos($haystack, $needle, $offset = 0, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1244
{
1245
    return Utf8::stripos($haystack, $needle, $offset);
1246
}
1247
1248
/**
1249
 * Finds first occurrence of a string within another, case insensitive.
1250
 *
1251
 * @param string $haystack      the string from which to get the first occurrence
1252
 * @param mixed  $needle        the string to be found
1253
 * @param bool   $before_needle (optional) Determines which portion of $haystack
1254
 *                              this function returns. The default value is FALSE.
1255
 * @param string $encoding      (optional) The used internally by this function
1256
 *                              character encoding. If it is omitted, the platform character set will be used by default.
1257
 *
1258
 * @return mixed Returns the portion of $haystack, or FALSE if $needle is not found.
1259
 *               Notes:
1260
 *               If $needle is not a string, it is converted to an integer and applied as the
1261
 *               ordinal value (codepoint if the encoding is UTF-8) of a character.
1262
 *               If $before_needle is set to TRUE, the function returns all of $haystack
1263
 *               from the beginning to the first occurrence of $needle.
1264
 *               If $before_needle is set to FALSE, the function returns all of $haystack f
1265
 *               rom the first occurrence of $needle to the end.
1266
 *               This function is aimed at replacing the functions stristr() and mb_stristr() for human-language strings.
1267
 *
1268
 * @see http://php.net/manual/en/function.stristr
1269
 * @see http://php.net/manual/en/function.mb-stristr
1270
 */
1271
function api_stristr($haystack, $needle, $before_needle = false, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1271
function api_stristr($haystack, $needle, $before_needle = false, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1272
{
1273
    return Utf8::stristr($haystack, $needle, $before_needle);
1274
}
1275
1276
/**
1277
 * Returns length of the input string.
1278
 *
1279
 * @param string $string   the string which length is to be calculated
1280
 * @param string $encoding (optional) The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1281
 *
1282
 * @return int Returns the number of characters within the string. A multi-byte character is counted as 1.
1283
 *             This function is aimed at replacing the functions strlen() and mb_strlen() for human-language strings.
1284
 *
1285
 * @see http://php.net/manual/en/function.strlen
1286
 * @see http://php.net/manual/en/function.mb-strlen
1287
 * Note: When you use strlen() to test for an empty string, you needn't change it to api_strlen().
1288
 * For example, in lines like the following:
1289
 * if (strlen($string) > 0)
1290
 * if (strlen($string) != 0)
1291
 * there is no need the original function strlen() to be changed, it works correctly and faster for these cases.
1292
 */
1293
function api_strlen($string, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1293
function api_strlen($string, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1294
{
1295
    return Utf8::strlen($string);
1296
}
1297
1298
/**
1299
 * Finds position of first occurrence of a string within another.
1300
 *
1301
 * @param string $haystack the string from which to get the position of the first occurrence
1302
 * @param string $needle   the string to be found
1303
 * @param int    $offset   (optional) The position in $haystack to start searching from. If it is omitted, searching starts from the beginning.
1304
 * @param string $encoding (optional)    The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1305
 *
1306
 * @return mixed Returns the numeric position of the first occurrence of $needle in the $haystack, or FALSE if $needle is not found.
1307
 *               Note: The first character's position is 0, the second character position is 1, and so on.
1308
 *               This function is aimed at replacing the functions strpos() and mb_strpos() for human-language strings.
1309
 *
1310
 * @see http://php.net/manual/en/function.strpos
1311
 * @see http://php.net/manual/en/function.mb-strpos
1312
 */
1313
function api_strpos($haystack, $needle, $offset = 0, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1313
function api_strpos($haystack, $needle, $offset = 0, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1314
{
1315
    return Utf8::strpos($haystack, $needle, $offset);
1316
}
1317
1318
/**
1319
 * Finds the last occurrence of a character in a string.
1320
 *
1321
 * @param string $haystack      the string from which to get the last occurrence
1322
 * @param mixed  $needle        the string which first character is to be found
1323
 * @param bool   $before_needle (optional) Determines which portion of $haystack this function returns. The default value is FALSE.
1324
 * @param string $encoding      (optional) The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1325
 *
1326
 * @return mixed Returns the portion of $haystack, or FALSE if the first character from $needle is not found.
1327
 *               Notes:
1328
 *               If $needle is not a string, it is converted to an integer and applied as the ordinal value (codepoint if the encoding is UTF-8) of a character.
1329
 *               If $before_needle is set to TRUE, the function returns all of $haystack from the beginning to the first occurrence.
1330
 *               If $before_needle is set to FALSE, the function returns all of $haystack from the first occurrence to the end.
1331
 *               This function is aimed at replacing the functions strrchr() and mb_strrchr() for human-language strings.
1332
 *
1333
 * @see http://php.net/manual/en/function.strrchr
1334
 * @see http://php.net/manual/en/function.mb-strrchr
1335
 */
1336
function api_strrchr($haystack, $needle, $before_needle = false, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $before_needle is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1336
function api_strrchr($haystack, $needle, /** @scrutinizer ignore-unused */ $before_needle = false, $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1336
function api_strrchr($haystack, $needle, $before_needle = false, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1337
{
1338
    return Utf8::strrchr($haystack, $needle);
1339
}
1340
1341
/**
1342
 * Reverses a string.
1343
 *
1344
 * @param string $string   the string to be reversed
1345
 * @param string $encoding (optional)    The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1346
 *
1347
 * @return string Returns the reversed string.
1348
 *                This function is aimed at replacing the function strrev() for human-language strings.
1349
 *
1350
 * @see http://php.net/manual/en/function.strrev
1351
 */
1352
function api_strrev($string, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1352
function api_strrev($string, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1353
{
1354
    return Utf8::strrev($string);
1355
}
1356
1357
/**
1358
 * Finds the position of last occurrence (case insensitive) of a string in a string.
1359
 *
1360
 * @param string $haystack the string from which to get the position of the last occurrence
1361
 * @param string $needle   the string to be found
1362
 * @param int    $offset   (optional) $offset may be specified to begin searching an arbitrary position. Negative values will stop searching at an arbitrary point prior to the end of the string.
1363
 * @param string $encoding (optional) The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1364
 *
1365
 * @return mixed Returns the numeric position of the first occurrence (case insensitive) of $needle in the $haystack, or FALSE if $needle is not found.
1366
 *               Note: The first character's position is 0, the second character position is 1, and so on.
1367
 *               This function is aimed at replacing the functions strripos() and mb_strripos() for human-language strings.
1368
 *
1369
 * @see http://php.net/manual/en/function.strripos
1370
 * @see http://php.net/manual/en/function.mb-strripos
1371
 */
1372
function api_strripos($haystack, $needle, $offset = 0, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1372
function api_strripos($haystack, $needle, $offset = 0, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1373
{
1374
    return Utf8::strripos($haystack, $needle, $offset);
1375
}
1376
1377
/**
1378
 * Finds the position of last occurrence of a string in a string.
1379
 *
1380
 * @param string $haystack the string from which to get the position of the last occurrence
1381
 * @param string $needle   the string to be found
1382
 * @param int    $offset   (optional) $offset may be specified to begin searching an arbitrary position. Negative values will stop searching at an arbitrary point prior to the end of the string.
1383
 * @param string $encoding (optional) The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1384
 *
1385
 * @return mixed Returns the numeric position of the first occurrence of $needle in the $haystack, or FALSE if $needle is not found.
1386
 *               Note: The first character's position is 0, the second character position is 1, and so on.
1387
 *               This function is aimed at replacing the functions strrpos() and mb_strrpos() for human-language strings.
1388
 *
1389
 * @see http://php.net/manual/en/function.strrpos
1390
 * @see http://php.net/manual/en/function.mb-strrpos
1391
 */
1392
function api_strrpos($haystack, $needle, $offset = 0, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1392
function api_strrpos($haystack, $needle, $offset = 0, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1393
{
1394
    return Utf8::strrpos($haystack, $needle, $offset);
1395
}
1396
1397
/**
1398
 * Finds first occurrence of a string within another.
1399
 *
1400
 * @param string $haystack      the string from which to get the first occurrence
1401
 * @param mixed  $needle        the string to be found
1402
 * @param bool   $before_needle (optional) Determines which portion of $haystack this function returns. The default value is FALSE.
1403
 * @param string $encoding      (optional) The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1404
 *
1405
 * @return mixed Returns the portion of $haystack, or FALSE if $needle is not found.
1406
 *               Notes:
1407
 *               If $needle is not a string, it is converted to an integer and applied as the ordinal value (codepoint if the encoding is UTF-8) of a character.
1408
 *               If $before_needle is set to TRUE, the function returns all of $haystack from the beginning to the first occurrence of $needle.
1409
 *               If $before_needle is set to FALSE, the function returns all of $haystack from the first occurrence of $needle to the end.
1410
 *               This function is aimed at replacing the functions strstr() and mb_strstr() for human-language strings.
1411
 *
1412
 * @see http://php.net/manual/en/function.strstr
1413
 * @see http://php.net/manual/en/function.mb-strstr
1414
 */
1415
function api_strstr($haystack, $needle, $before_needle = false, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1415
function api_strstr($haystack, $needle, $before_needle = false, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1416
{
1417
    return Utf8::strstr($haystack, $needle, $before_needle);
1418
}
1419
1420
/**
1421
 * Makes a string lowercase.
1422
 *
1423
 * @param string $string   the string being lowercased
1424
 * @param string $encoding (optional)	The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1425
 *
1426
 * @return string Returns the string with all alphabetic characters converted to lowercase.
1427
 *                This function is aimed at replacing the functions strtolower() and mb_strtolower() for human-language strings.
1428
 *
1429
 * @see http://php.net/manual/en/function.strtolower
1430
 * @see http://php.net/manual/en/function.mb-strtolower
1431
 */
1432
function api_strtolower($string, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1432
function api_strtolower($string, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1433
{
1434
    return Utf8::strtolower($string);
1435
}
1436
1437
/**
1438
 * Makes a string uppercase.
1439
 *
1440
 * @param string $string   the string being uppercased
1441
 * @param string $encoding (optional)	The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1442
 *
1443
 * @return string Returns the string with all alphabetic characters converted to uppercase.
1444
 *                This function is aimed at replacing the functions strtoupper() and mb_strtoupper() for human-language strings.
1445
 *
1446
 * @see http://php.net/manual/en/function.strtoupper
1447
 * @see http://php.net/manual/en/function.mb-strtoupper
1448
 */
1449
function api_strtoupper($string, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1449
function api_strtoupper($string, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1450
{
1451
    return Utf8::strtoupper($string);
1452
}
1453
1454
/**
1455
 * // Gets part of a string.
1456
 *
1457
 * @param string $string   the input string
1458
 * @param int    $start    the first position from which the extracted part begins
1459
 * @param int    $length   the length in character of the extracted part
1460
 * @param string $encoding (optional) The used internally by this function
1461
 *                         character encoding. If it is omitted, the platform character set will be used by default.
1462
 *
1463
 * @return string Returns the part of the string specified by the start and length parameters.
1464
 *                Note: First character's position is 0. Second character position is 1, and so on.
1465
 *                This function is aimed at replacing the functions substr() and mb_substr() for human-language strings.
1466
 *
1467
 * @see http://php.net/manual/en/function.substr
1468
 * @see http://php.net/manual/en/function.mb-substr
1469
 */
1470
function api_substr($string, $start, $length = null, $encoding = null)
1471
{
1472
    if (is_null($length)) {
1473
        $length = api_strlen($string, $encoding);
1474
    }
1475
1476
    return Utf8::substr($string, $start, $length);
1477
}
1478
1479
/**
1480
 * Counts the number of substring occurrences.
1481
 *
1482
 * @param string $haystack the string being checked
1483
 * @param string $needle   the string being found
1484
 * @param string $encoding (optional) The used internally by this function character encoding.
1485
 *                         If it is omitted, the platform character set will be used by default.
1486
 *
1487
 * @return int the number of times the needle substring occurs in the haystack string
1488
 *
1489
 * @see http://php.net/manual/en/function.mb-substr-count.php
1490
 */
1491
function api_substr_count($haystack, $needle, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1491
function api_substr_count($haystack, $needle, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1492
{
1493
    return Utf8::substr_count($haystack, $needle);
1494
}
1495
1496
/**
1497
 * Replaces text within a portion of a string.
1498
 *
1499
 * @param string $string      the input string
1500
 * @param string $replacement the replacement string
1501
 * @param int    $start       The position from which replacing will begin.
1502
 *                            Notes:
1503
 *                            If $start is positive, the replacing will begin at the $start'th offset into the string.
1504
 *                            If $start is negative, the replacing will begin at the $start'th character from the end of the string.
1505
 * @param int    $length      (optional) The position where replacing will end.
1506
 *                            Notes:
1507
 *                            If given and is positive, it represents the length of the portion of the string which is to be replaced.
1508
 *                            If it is negative, it represents the number of characters from the end of string at which to stop replacing.
1509
 *                            If it is not given, then it will default to api_strlen($string); i.e. end the replacing at the end of string.
1510
 *                            If $length is zero, then this function will have the effect of inserting replacement into the string at the given start offset.
1511
 * @param string $encoding    (optional)    The used internally by this function character encoding.
1512
 *                            If it is omitted, the platform character set will be used by default.
1513
 *
1514
 * @return string The result string is returned.
1515
 *                This function is aimed at replacing the function substr_replace() for human-language strings.
1516
 *
1517
 * @see http://php.net/manual/function.substr-replace
1518
 */
1519
function api_substr_replace($string, $replacement, $start, $length = null, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1519
function api_substr_replace($string, $replacement, $start, $length = null, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1520
{
1521
    if (is_null($length)) {
1522
        $length = api_strlen($string);
1523
    }
1524
1525
    return UTf8::substr_replace($string, $replacement, $start, $length);
1526
}
1527
1528
/**
1529
 * Makes a string's first character uppercase.
1530
 *
1531
 * @param string $string   the input string
1532
 * @param string $encoding (optional)    The used internally by this function character encoding.
1533
 *                         If it is omitted, the platform character set will be used by default.
1534
 *
1535
 * @return string Returns a string with the first character capitalized, if that character is alphabetic.
1536
 *                This function is aimed at replacing the function ucfirst() for human-language strings.
1537
 *
1538
 * @see http://php.net/manual/en/function.ucfirst
1539
 */
1540
function api_ucfirst($string, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1540
function api_ucfirst($string, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1541
{
1542
    return Utf8::ucfirst($string);
1543
}
1544
1545
/**
1546
 * Uppercases the first character of each word in a string.
1547
 *
1548
 * @param string $string   the input string
1549
 * @param string $encoding (optional) The used internally by this function character encoding.
1550
 *                         If it is omitted, the platform character set will be used by default.
1551
 *
1552
 * @return string Returns the modified string.
1553
 *                This function is aimed at replacing the function ucwords() for human-language strings.
1554
 *
1555
 * @see http://php.net/manual/en/function.ucwords
1556
 */
1557
function api_ucwords($string, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1557
function api_ucwords($string, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1558
{
1559
    return Utf8::ucwords($string);
1560
}
1561
1562
/**
1563
 * Performs a regular expression match, UTF-8 aware when it is applicable.
1564
 *
1565
 * @param string $pattern  the pattern to search for, as a string
1566
 * @param string $subject  the input string
1567
 * @param array  &$matches (optional) If matches is provided,
1568
 *                         then it is filled with the results of search (as an array).
1569
 *                         $matches[0] will contain the text that matched the full pattern, $matches[1] will have the text that matched the first captured parenthesized subpattern, and so on.
1570
 * @param int    $flags    (optional) Could be PREG_OFFSET_CAPTURE. If this flag is passed, for every occurring match the appendant string offset will also be returned.
1571
 *                         Note that this changes the return value in an array where every element is an array consisting of the matched string at index 0 and its string offset into subject at index 1.
1572
 * @param int    $offset   (optional)        Normally, the search starts from the beginning of the subject string. The optional parameter offset can be used to specify the alternate place from which to start the search.
1573
 * @param string $encoding (optional)    The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1574
 *
1575
 * @return int|bool returns the number of times pattern matches or FALSE if an error occurred
1576
 *
1577
 * @see http://php.net/preg_match
1578
 */
1579
function api_preg_match(
1580
    $pattern,
1581
    $subject,
1582
    &$matches = null,
1583
    $flags = 0,
1584
    $offset = 0,
1585
    $encoding = null
1586
) {
1587
    if (empty($encoding)) {
1588
        $encoding = _api_mb_internal_encoding();
1589
    }
1590
1591
    return preg_match(api_is_utf8($encoding) ? $pattern.'u' : $pattern, $subject, $matches, $flags, $offset);
1592
}
1593
1594
/**
1595
 * Performs a global regular expression match, UTF-8 aware when it is applicable.
1596
 *
1597
 * @param string $pattern  the pattern to search for, as a string
1598
 * @param string $subject  the input string
1599
 * @param array  &$matches (optional)    Array of all matches in multi-dimensional array ordered according to $flags
1600
 * @param int    $flags    (optional)            Can be a combination of the following flags (note that it doesn't make sense to use PREG_PATTERN_ORDER together with PREG_SET_ORDER):
1601
 *                         PREG_PATTERN_ORDER - orders results so that $matches[0] is an array of full pattern matches, $matches[1] is an array of strings matched by the first parenthesized subpattern, and so on;
1602
 *                         PREG_SET_ORDER - orders results so that $matches[0] is an array of first set of matches, $matches[1] is an array of second set of matches, and so on;
1603
 *                         PREG_OFFSET_CAPTURE - If this flag is passed, for every occurring match the appendant string offset will also be returned. Note that this changes the value of matches
1604
 *                         in an array where every element is an array consisting of the matched string at offset 0 and its string offset into subject at offset 1.
1605
 *                         If no order flag is given, PREG_PATTERN_ORDER is assumed.
1606
 * @param int    $offset   (optional)		Normally, the search starts from the beginning of the subject string. The optional parameter offset can be used to specify the alternate place from which to start the search.
1607
 * @param string $encoding (optional)	The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1608
 *
1609
 * @return int|bool returns the number of full pattern matches (which might be zero), or FALSE if an error occurred
1610
 *
1611
 * @see http://php.net/preg_match_all
1612
 */
1613
function api_preg_match_all($pattern, $subject, &$matches, $flags = PREG_PATTERN_ORDER, $offset = 0, $encoding = null)
1614
{
1615
    if (empty($encoding)) {
1616
        $encoding = _api_mb_internal_encoding();
1617
    }
1618
    if (is_null($flags)) {
1619
        $flags = PREG_PATTERN_ORDER;
1620
    }
1621
1622
    return preg_match_all(api_is_utf8($encoding) ? $pattern.'u' : $pattern, $subject, $matches, $flags, $offset);
1623
}
1624
1625
/**
1626
 * Performs a regular expression search and replace, UTF-8 aware when it is applicable.
1627
 *
1628
 * @param string|array $pattern     The pattern to search for. It can be either a string or an array with strings.
1629
 * @param string|array $replacement the string or an array with strings to replace
1630
 * @param string|array $subject     the string or an array with strings to search and replace
1631
 * @param int          $limit       The maximum possible replacements for each pattern in each subject string. Defaults to -1 (no limit).
1632
 * @param int          &$count      If specified, this variable will be filled with the number of replacements done
1633
 * @param string       $encoding    (optional)	The used internally by this function character encoding.
1634
 *                                  If it is omitted, the platform character set will be used by default.
1635
 *
1636
 * @return array|string|null returns an array if the subject parameter is an array, or a string otherwise.
1637
 *                           If matches are found, the new subject will be returned, otherwise subject will be returned unchanged or NULL if an error occurred.
1638
 *
1639
 * @see http://php.net/preg_replace
1640
 */
1641
function api_preg_replace($pattern, $replacement, $subject, $limit = -1, &$count = 0, $encoding = null)
1642
{
1643
    if (empty($encoding)) {
1644
        $encoding = _api_mb_internal_encoding();
1645
    }
1646
    $is_utf8 = api_is_utf8($encoding);
1647
    if (is_array($pattern)) {
1648
        foreach ($pattern as &$p) {
1649
            $p = $is_utf8 ? $p.'u' : $p;
1650
        }
1651
    } else {
1652
        $pattern = $is_utf8 ? $pattern.'u' : $pattern;
1653
    }
1654
1655
    return preg_replace($pattern, $replacement, $subject, $limit, $count);
1656
}
1657
1658
/**
1659
 * Splits a string by a regular expression, UTF-8 aware when it is applicable.
1660
 *
1661
 * @param string $pattern  the pattern to search for, as a string
1662
 * @param string $subject  the input string
1663
 * @param int    $limit    (optional)			If specified, then only substrings up to $limit are returned with the rest of the string being placed in the last substring. A limit of -1, 0 or null means "no limit" and, as is standard across PHP.
1664
 * @param int    $flags    (optional)			$flags can be any combination of the following flags (combined with bitwise | operator):
1665
 *                         PREG_SPLIT_NO_EMPTY - if this flag is set, only non-empty pieces will be returned;
1666
 *                         PREG_SPLIT_DELIM_CAPTURE - if this flag is set, parenthesized expression in the delimiter pattern will be captured and returned as well;
1667
 *                         PREG_SPLIT_OFFSET_CAPTURE - If this flag is set, for every occurring match the appendant string offset will also be returned.
1668
 *                         Note that this changes the return value in an array where every element is an array consisting of the matched string at offset 0 and its string offset into subject at offset 1.
1669
 * @param string $encoding (optional)	The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1670
 *
1671
 * @return array returns an array containing substrings of $subject split along boundaries matched by $pattern
1672
 *
1673
 * @see http://php.net/preg_split
1674
 */
1675
function api_preg_split($pattern, $subject, $limit = -1, $flags = 0, $encoding = null)
1676
{
1677
    if (empty($encoding)) {
1678
        $encoding = _api_mb_internal_encoding();
1679
    }
1680
1681
    return preg_split(api_is_utf8($encoding) ? $pattern.'u' : $pattern, $subject, $limit, $flags);
0 ignored issues
show
Bug Best Practice introduced by
The expression return preg_split(api_is...ubject, $limit, $flags) could also return false which is incompatible with the documented return type array. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
1682
}
1683
1684
/**
1685
 * String comparison.
1686
 */
1687
1688
/**
1689
 * Performs string comparison, case insensitive, language sensitive, with extended multibyte support.
1690
 *
1691
 * @param string $string1  the first string
1692
 * @param string $string2  the second string
1693
 * @param string $language (optional) The language in which comparison is to be made. If language is omitted, interface language is assumed then.
1694
 * @param string $encoding (optional) The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1695
 *
1696
 * @return int Returns < 0 if $string1 is less than $string2; > 0 if $string1 is greater than $string2; and 0 if the strings are equal.
1697
 *             This function is aimed at replacing the function strcasecmp() for human-language strings.
1698
 *
1699
 * @see http://php.net/manual/en/function.strcasecmp
1700
 */
1701
function api_strcasecmp($string1, $string2, $language = null, $encoding = null)
1702
{
1703
    return api_strcmp(api_strtolower($string1, $encoding), api_strtolower($string2, $encoding), $language, $encoding);
1704
}
1705
1706
/**
1707
 * Performs string comparison, case sensitive, language sensitive, with extended multibyte support.
1708
 *
1709
 * @param string $string1  the first string
1710
 * @param string $string2  the second string
1711
 * @param string $language (optional)	The language in which comparison is to be made. If language is omitted, interface language is assumed then.
1712
 * @param string $encoding (optional)	The used internally by this function character encoding.
1713
 *                         If it is omitted, the platform character set will be used by default.
1714
 *
1715
 * @return int Returns < 0 if $string1 is less than $string2; > 0 if $string1 is greater than $string2; and 0 if the strings are equal.
1716
 *             This function is aimed at replacing the function strcmp() for human-language strings.
1717
 *
1718
 * @see http://php.net/manual/en/function.strcmp.php
1719
 * @see http://php.net/manual/en/collator.compare.php
1720
 */
1721
function api_strcmp($string1, $string2, $language = null, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $language is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1721
function api_strcmp($string1, $string2, /** @scrutinizer ignore-unused */ $language = null, $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1721
function api_strcmp($string1, $string2, $language = null, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1722
{
1723
    return strcmp($string1, $string2);
1724
}
1725
1726
/**
1727
 * Performs string comparison in so called "natural order", case sensitive, language sensitive, with extended multibyte support.
1728
 *
1729
 * @param string $string1  the first string
1730
 * @param string $string2  the second string
1731
 * @param string $language (optional)	The language in which comparison is to be made. If language is omitted, interface language is assumed then.
1732
 * @param string $encoding (optional)	The used internally by this function character encoding.
1733
 *                         If it is omitted, the platform character set will be used by default.
1734
 *
1735
 * @return int Returns < 0 if $string1 is less than $string2; > 0 if $string1 is greater than $string2; and 0 if the strings are equal.
1736
 *             This function is aimed at replacing the function strnatcmp() for human-language strings.
1737
 *
1738
 * @see http://php.net/manual/en/function.strnatcmp.php
1739
 * @see http://php.net/manual/en/collator.compare.php
1740
 */
1741
function api_strnatcmp($string1, $string2, $language = null, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $language is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1741
function api_strnatcmp($string1, $string2, /** @scrutinizer ignore-unused */ $language = null, $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1741
function api_strnatcmp($string1, $string2, $language = null, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1742
{
1743
    return strnatcmp($string1, $string2);
1744
}
1745
1746
/**
1747
 * Sorting arrays.
1748
 */
1749
1750
/**
1751
 * Sorts an array using natural order algorithm.
1752
 *
1753
 * @param array  $array    the input array
1754
 * @param string $language (optional)	The language in which comparison is to be made. If language is omitted, interface language is assumed then.
1755
 * @param string $encoding (optional)	The used internally by this function character encoding.
1756
 *                         If it is omitted, the platform character set will be used by default.
1757
 *
1758
 * @return bool Returns TRUE on success, FALSE on error.
1759
 *              This function is aimed at replacing the function natsort() for sorting human-language strings.
1760
 *
1761
 * @see http://php.net/manual/en/function.natsort.php
1762
 */
1763
function api_natsort(&$array, $language = null, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1763
function api_natsort(&$array, $language = null, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $language is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1763
function api_natsort(&$array, /** @scrutinizer ignore-unused */ $language = null, $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1764
{
1765
    return natsort($array);
1766
}
1767
1768
/**
1769
 * Sorts an array using natural order algorithm in reverse order.
1770
 *
1771
 * @param array  $array    the input array
1772
 * @param string $language (optional)	The language in which comparison is to be made. If language is omitted, interface language is assumed then.
1773
 * @param string $encoding (optional)	The used internally by this function character encoding.
1774
 *                         If it is omitted, the platform character set will be used by default.
1775
 *
1776
 * @return bool returns TRUE on success, FALSE on error
1777
 */
1778
function api_natrsort(&$array, $language = null, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1778
function api_natrsort(&$array, $language = null, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $language is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1778
function api_natrsort(&$array, /** @scrutinizer ignore-unused */ $language = null, $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1779
{
1780
    return uasort($array, '_api_strnatrcmp');
1781
}
1782
1783
/**
1784
 * Encoding management functions.
1785
 */
1786
1787
/**
1788
 * This function unifies the encoding identificators, so they could be compared.
1789
 *
1790
 * @param string|array $encoding the specified encoding
1791
 *
1792
 * @return string returns the encoding identificator modified in suitable for comparison way
1793
 */
1794
function api_refine_encoding_id($encoding)
1795
{
1796
    if (is_array($encoding)) {
1797
        return array_map('api_refine_encoding_id', $encoding);
0 ignored issues
show
Bug Best Practice introduced by
The expression return array_map('api_re...ncoding_id', $encoding) returns the type array which is incompatible with the documented return type string.
Loading history...
1798
    }
1799
1800
    return strtoupper(str_replace('_', '-', $encoding));
1801
}
1802
1803
/**
1804
 * This function checks whether two $encoding are equal (same, equvalent).
1805
 *
1806
 * @param string|array $encoding1 The first encoding
1807
 * @param string|array $encoding2 The second encoding
1808
 * @param bool         $strict    When this parameter is TRUE the comparison ignores aliases of encodings.
1809
 *                                When the parameter is FALSE, aliases are taken into account.
1810
 *
1811
 * @return bool returns TRUE if the encodings are equal, FALSE otherwise
1812
 */
1813
function api_equal_encodings($encoding1, $encoding2, $strict = false)
1814
{
1815
    static $equal_encodings = [];
1816
    if (is_array($encoding1)) {
1817
        foreach ($encoding1 as $encoding) {
1818
            if (api_equal_encodings($encoding, $encoding2, $strict)) {
1819
                return true;
1820
            }
1821
        }
1822
1823
        return false;
1824
    } elseif (is_array($encoding2)) {
1825
        foreach ($encoding2 as $encoding) {
1826
            if (api_equal_encodings($encoding1, $encoding, $strict)) {
1827
                return true;
1828
            }
1829
        }
1830
1831
        return false;
1832
    }
1833
    if (!isset($equal_encodings[$encoding1][$encoding2][$strict])) {
1834
        $encoding_1 = api_refine_encoding_id($encoding1);
1835
        $encoding_2 = api_refine_encoding_id($encoding2);
1836
        if ($encoding_1 == $encoding_2) {
1837
            $result = true;
1838
        } else {
1839
            if ($strict) {
1840
                $result = false;
1841
            } else {
1842
                $alias1 = _api_get_character_map_name($encoding_1);
1843
                $alias2 = _api_get_character_map_name($encoding_2);
1844
                $result = !empty($alias1) && !empty($alias2) && $alias1 == $alias2;
1845
            }
1846
        }
1847
        $equal_encodings[$encoding1][$encoding2][$strict] = $result;
1848
    }
1849
1850
    return $equal_encodings[$encoding1][$encoding2][$strict];
1851
}
1852
1853
/**
1854
 * This function checks whether a given encoding is UTF-8.
1855
 *
1856
 * @param string $encoding the tested encoding
1857
 *
1858
 * @return bool returns TRUE if the given encoding id means UTF-8, otherwise returns false
1859
 */
1860
function api_is_utf8($encoding)
1861
{
1862
    static $result = [];
1863
    if (!isset($result[$encoding])) {
1864
        $result[$encoding] = api_equal_encodings($encoding, 'UTF-8');
1865
    }
1866
1867
    return $result[$encoding];
1868
}
1869
1870
/**
1871
 * This function returns the encoding, currently used by the system.
1872
 *
1873
 * @return string The system's encoding.
1874
 *                Note: The value of api_get_setting('platform_charset') is tried to be returned first,
1875
 *                on the second place the global variable $charset is tried to be returned. If for some
1876
 *                reason both attempts fail, then the libraly's internal value will be returned.
1877
 */
1878
function api_get_system_encoding()
1879
{
1880
    return 'UTF-8';
1881
}
1882
1883
/**
1884
 * Checks whether a specified encoding is supported by this API.
1885
 *
1886
 * @param string $encoding the specified encoding
1887
 *
1888
 * @return bool returns TRUE when the specified encoding is supported, FALSE othewise
1889
 */
1890
function api_is_encoding_supported($encoding)
1891
{
1892
    static $supported = [];
1893
    if (!isset($supported[$encoding])) {
1894
        $supported[$encoding] = _api_mb_supports($encoding) || _api_iconv_supports($encoding) || _api_convert_encoding_supports($encoding);
1895
    }
1896
1897
    return $supported[$encoding];
1898
}
1899
1900
/**
1901
 * Detects encoding of plain text.
1902
 *
1903
 * @param string $string   the input text
1904
 * @param string $language (optional) The language of the input text, provided if it is known
1905
 *
1906
 * @return string returns the detected encoding
1907
 */
1908
function api_detect_encoding($string, $language = null)
0 ignored issues
show
Unused Code introduced by
The parameter $language is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1908
function api_detect_encoding($string, /** @scrutinizer ignore-unused */ $language = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1909
{
1910
    // Testing against valid UTF-8 first.
1911
    if (api_is_valid_utf8($string)) {
1912
        return 'UTF-8';
1913
    }
1914
1915
    return mb_detect_encoding($string);
1916
}
1917
1918
/**
1919
 * String validation functions concerning certain encodings.
1920
 */
1921
1922
/**
1923
 * Checks a string for UTF-8 validity.
1924
 *
1925
 * @param string $string
1926
 *
1927
 * @return string
1928
 */
1929
function api_is_valid_utf8($string)
1930
{
1931
    return Utf8::isUtf8($string);
1932
}
1933
1934
/**
1935
 * Checks whether a string contains 7-bit ASCII characters only.
1936
 *
1937
 * @param string $string the string to be tested/validated
1938
 *
1939
 * @return bool returns TRUE when the tested string contains 7-bit
1940
 *              ASCII characters only, FALSE othewise
1941
 */
1942
function api_is_valid_ascii(&$string)
1943
{
1944
    return mb_detect_encoding($string, 'ASCII', true) == 'ASCII' ? true : false;
1945
}
1946
1947
/**
1948
 * Return true a date is valid.
1949
 *
1950
 * @param string $date   example: 2014-06-30 13:05:05
1951
 * @param string $format example: "Y-m-d H:i:s"
1952
 *
1953
 * @return bool
1954
 */
1955
function api_is_valid_date($date, $format = 'Y-m-d H:i:s')
1956
{
1957
    $d = DateTime::createFromFormat($format, $date);
1958
1959
    return $d && $d->format($format) == $date;
1960
}
1961
1962
/**
1963
 * Returns the variable translated.
1964
 *
1965
 * @param string $variable   the string to translate
1966
 * @param string $pluginName the Plugin name
1967
 *
1968
 * @return string the variable translated
1969
 */
1970
function get_plugin_lang($variable, $pluginName)
1971
{
1972
    $plugin = $pluginName::create();
1973
1974
    return $plugin->get_lang($variable);
1975
}
1976
1977
/**
1978
 * Returns an array of translated week days and months, short and normal names.
1979
 *
1980
 * @param string $language (optional Language id. If it is omitted,
1981
 *                         the current interface language is assumed.
1982
 *
1983
 * @return array returns a multidimensional array with translated week days and months
1984
 */
1985
function &_api_get_day_month_names($language = null)
1986
{
1987
    static $date_parts = [];
1988
    if (empty($language)) {
1989
        $language = api_get_interface_language();
1990
    }
1991
    if (!isset($date_parts[$language])) {
1992
        $week_day = [
1993
            'Sunday',
1994
            'Monday',
1995
            'Tuesday',
1996
            'Wednesday',
1997
            'Thursday',
1998
            'Friday',
1999
            'Saturday',
2000
        ];
2001
        $month = [
2002
            'January',
2003
            'February',
2004
            'March',
2005
            'April',
2006
            'May',
2007
            'June',
2008
            'July',
2009
            'August',
2010
            'September',
2011
            'October',
2012
            'November',
2013
            'December',
2014
        ];
2015
        for ($i = 0; $i < 7; $i++) {
2016
            $date_parts[$language]['days_short'][] = get_lang(
2017
                $week_day[$i].'Short',
2018
                '',
2019
                $language
2020
            );
2021
            $date_parts[$language]['days_long'][] = get_lang(
2022
                $week_day[$i].'Long',
2023
                '',
2024
                $language
2025
            );
2026
        }
2027
        for ($i = 0; $i < 12; $i++) {
2028
            $date_parts[$language]['months_short'][] = get_lang(
2029
                $month[$i].'Short',
2030
                '',
2031
                $language
2032
            );
2033
            $date_parts[$language]['months_long'][] = get_lang(
2034
                $month[$i].'Long',
2035
                '',
2036
                $language
2037
            );
2038
        }
2039
    }
2040
2041
    return $date_parts[$language];
2042
}
2043
2044
/**
2045
 * Returns returns person name convention for a given language.
2046
 *
2047
 * @param string $language the input language
2048
 * @param string $type     The type of the requested convention.
2049
 *                         It may be 'format' for name order convention or 'sort_by' for name sorting convention.
2050
 *
2051
 * @return mixed Depending of the requested type,
2052
 *               the returned result may be string or boolean; null is returned on error;
2053
 */
2054
function _api_get_person_name_convention($language, $type)
2055
{
2056
    static $conventions;
2057
2058
    $language = api_get_language_from_iso($language);
2059
    $languageName = 'english';
2060
    if (!empty($language)) {
2061
        $languageName = $language->getEnglishName();
2062
    }
2063
2064
    if (!isset($conventions)) {
2065
        $file = __DIR__.'/internationalization_database/name_order_conventions.php';
2066
        if (file_exists($file)) {
2067
            $conventions = include $file;
2068
        } else {
2069
            $conventions = [
2070
                'english' => [
2071
                    'format' => 'title first_name last_name',
2072
                    'sort_by' => 'first_name',
2073
                ],
2074
            ];
2075
        }
2076
        // Overwrite classic conventions
2077
        $customConventions = api_get_configuration_value('name_order_conventions');
2078
2079
        if (!empty($customConventions)) {
2080
            foreach ($customConventions as $key => $data) {
2081
                $conventions[$key] = $data;
2082
            }
2083
        }
2084
2085
        $search1 = ['FIRST_NAME', 'LAST_NAME', 'TITLE'];
2086
        $replacement1 = ['%F', '%L', '%T'];
2087
        $search2 = ['first_name', 'last_name', 'title'];
2088
        $replacement2 = ['%f', '%l', '%t'];
2089
        foreach (array_keys($conventions) as $key) {
2090
            $conventions[$key]['format'] = str_replace($search1, $replacement1, $conventions[$key]['format']);
2091
            $conventions[$key]['format'] = _api_validate_person_name_format(
2092
                _api_clean_person_name(
2093
                    str_replace(
2094
                        '%',
2095
                        ' %',
2096
                        str_ireplace(
2097
                            $search2,
2098
                            $replacement2,
2099
                            $conventions[$key]['format']
2100
                        )
2101
                    )
2102
                )
2103
            );
2104
            $conventions[$key]['sort_by'] = strtolower($conventions[$key]['sort_by']) != 'last_name' ? true : false;
2105
        }
2106
    }
2107
    switch ($type) {
2108
        case 'format':
2109
            return is_string($conventions[$languageName]['format']) ? $conventions[$languageName]['format'] : '%t %f %l';
2110
        case 'sort_by':
2111
            return is_bool($conventions[$languageName]['sort_by']) ? $conventions[$languageName]['sort_by'] : true;
2112
    }
2113
2114
    return null;
2115
}
2116
2117
/**
2118
 * Replaces non-valid formats for person names with the default (English) format.
2119
 *
2120
 * @param string $format the input format to be verified
2121
 *
2122
 * @return bool returns the same format if is is valid, otherwise returns a valid English format
2123
 */
2124
function _api_validate_person_name_format($format)
2125
{
2126
    if (empty($format) || stripos($format, '%f') === false || stripos($format, '%l') === false) {
2127
        return '%t %f %l';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '%t %f %l' returns the type string which is incompatible with the documented return type boolean.
Loading history...
2128
    }
2129
2130
    return $format;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $format returns the type string which is incompatible with the documented return type boolean.
Loading history...
2131
}
2132
2133
/**
2134
 * Removes leading, trailing and duplicate whitespace and/or commas in a full person name.
2135
 * Cleaning is needed for the cases when not all parts of the name are available
2136
 * or when the name is constructed using a "dirty" pattern.
2137
 *
2138
 * @param string $person_name the input person name
2139
 *
2140
 * @return string returns cleaned person name
2141
 */
2142
function _api_clean_person_name($person_name)
2143
{
2144
    return preg_replace(['/\s+/', '/, ,/', '/,+/', '/^[ ,]/', '/[ ,]$/'], [' ', ', ', ',', '', ''], $person_name);
2145
}
2146
2147
/**
2148
 * Appendix to "Multibyte string conversion functions".
2149
 */
2150
2151
/**
2152
 * This is a php-implementation of a function that is similar to mb_convert_encoding() from mbstring extension.
2153
 * The function converts a given string from one to another character encoding.
2154
 *
2155
 * @param string $string        the string being converted
2156
 * @param string $to_encoding   the encoding that $string is being converted to
2157
 * @param string $from_encoding the encoding that $string is being converted from
2158
 *
2159
 * @return string returns the converted string
2160
 */
2161
function _api_convert_encoding(&$string, $to_encoding, $from_encoding)
2162
{
2163
    return mb_convert_encoding($string, $to_encoding, $from_encoding);
2164
}
2165
2166
/**
2167
 * This function determines the name of corresponding to a given encoding conversion table.
2168
 * It is able to deal with some aliases of the encoding.
2169
 *
2170
 * @param string $encoding the given encoding identificator, for example 'WINDOWS-1252'
2171
 *
2172
 * @return string returns the name of the corresponding conversion table, for the same example - 'CP1252'
2173
 */
2174
function _api_get_character_map_name($encoding)
2175
{
2176
    static $character_map_selector;
2177
    if (!isset($character_map_selector)) {
2178
        $file = __DIR__.'/internationalization_database/conversion/character_map_selector.php';
2179
        if (file_exists($file)) {
2180
            $character_map_selector = include $file;
2181
        } else {
2182
            $character_map_selector = [];
2183
        }
2184
    }
2185
2186
    return isset($character_map_selector[$encoding]) ? $character_map_selector[$encoding] : '';
2187
}
2188
2189
/**
2190
 * Appendix to "String comparison".
2191
 */
2192
2193
/**
2194
 * A reverse function from php-core function strnatcmp(),
2195
 * performs string comparison in reverse natural (alpha-numerical) order.
2196
 *
2197
 * @param string $string1 the first string
2198
 * @param string $string2 the second string
2199
 *
2200
 * @return int returns 0 if $string1 = $string2; >0 if $string1 < $string2; <0 if $string1 > $string2
2201
 */
2202
function _api_strnatrcmp($string1, $string2)
2203
{
2204
    return strnatcmp($string2, $string1);
2205
}
2206
2207
/**
2208
 * Sets/Gets internal character encoding of the common string functions within the PHP mbstring extension.
2209
 *
2210
 * @param string $encoding (optional)    When this parameter is given, the function sets the internal encoding
2211
 *
2212
 * @return string When $encoding parameter is not given, the function returns the internal encoding.
2213
 *                Note: This function is used in the global initialization script for setting the
2214
 *                internal encoding to the platform's character set.
2215
 *
2216
 * @see http://php.net/manual/en/function.mb-internal-encoding
2217
 */
2218
function _api_mb_internal_encoding($encoding = 'UTF-8')
2219
{
2220
    return mb_internal_encoding($encoding);
0 ignored issues
show
Bug Best Practice introduced by
The expression return mb_internal_encoding($encoding) also could return the type boolean which is incompatible with the documented return type string.
Loading history...
2221
}
2222
2223
/**
2224
 * Checks whether the specified encoding is supported by the PHP mbstring extension.
2225
 *
2226
 * @param string $encoding the specified encoding
2227
 *
2228
 * @return bool returns TRUE when the specified encoding is supported, FALSE othewise
2229
 */
2230
function _api_mb_supports($encoding)
2231
{
2232
    static $supported = [];
2233
    if (!isset($supported[$encoding])) {
2234
        if (MBSTRING_INSTALLED) {
2235
            $supported[$encoding] = api_equal_encodings($encoding, mb_list_encodings(), true);
2236
        } else {
2237
            $supported[$encoding] = false;
2238
        }
2239
    }
2240
2241
    return $supported[$encoding];
2242
}
2243
2244
/**
2245
 * Checks whether the specified encoding is supported by the PHP iconv extension.
2246
 *
2247
 * @param string $encoding the specified encoding
2248
 *
2249
 * @return bool returns TRUE when the specified encoding is supported, FALSE othewise
2250
 */
2251
function _api_iconv_supports($encoding)
2252
{
2253
    static $supported = [];
2254
    if (!isset($supported[$encoding])) {
2255
        if (ICONV_INSTALLED) {
2256
            $enc = api_refine_encoding_id($encoding);
2257
            if ($enc != 'HTML-ENTITIES') {
2258
                $test_string = '';
2259
                for ($i = 32; $i < 128; $i++) {
2260
                    $test_string .= chr($i);
2261
                }
2262
                $supported[$encoding] = (@iconv_strlen($test_string, $enc)) ? true : false;
2263
            } else {
2264
                $supported[$encoding] = false;
2265
            }
2266
        } else {
2267
            $supported[$encoding] = false;
2268
        }
2269
    }
2270
2271
    return $supported[$encoding];
2272
}
2273
2274
// This function checks whether the function _api_convert_encoding() (the php-
2275
// implementation) is able to convert from/to a given encoding.
2276
function _api_convert_encoding_supports($encoding)
2277
{
2278
    static $supports = [];
2279
    if (!isset($supports[$encoding])) {
2280
        $supports[$encoding] = _api_get_character_map_name(api_refine_encoding_id($encoding)) != '';
2281
    }
2282
2283
    return $supports[$encoding];
2284
}
2285
2286
/**
2287
 * Given a date object, return a human or ISO format, with or without h:m:s.
2288
 *
2289
 * @param object $date      The Date object
2290
 * @param bool   $showTime  Whether to show the time and date (true) or only the date (false)
2291
 * @param bool   $humanForm Whether to show day-month-year (true) or year-month-day (false)
2292
 *
2293
 * @return string Formatted date
2294
 */
2295
function api_get_human_date_time($date, $showTime = true, $humanForm = false)
2296
{
2297
    if ($showTime) {
2298
        if ($humanForm) {
2299
            return $date->format('j M Y H:i:s');
2300
        } else {
2301
            return $date->format('Y-m-d H:i:s');
2302
        }
2303
    } else {
2304
        if ($humanForm) {
2305
            return $date->format('j M Y');
2306
        } else {
2307
            return $date->format('Y-m-d');
2308
        }
2309
    }
2310
}
2311