Passed
Push — master ( 447a4c...2f567c )
by Julito
09:40
created

api_get_timezone()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 15
c 0
b 0
f 0
nc 7
nop 0
dl 0
loc 29
rs 8.8333
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Framework\Container;
5
use ChamiloSession as Session;
6
use Patchwork\Utf8;
7
use Westsworld\TimeAgo;
8
9
/**
10
 * File: internationalization.lib.php
11
 * Internationalization library for Chamilo 1.x LMS
12
 * A library implementing internationalization related functions.
13
 * License: GNU General Public License Version 3 (Free Software Foundation)ww.
14
 *
15
 * @author Ivan Tcholakov, <[email protected]>, 2009, 2010
16
 * @author More authors, mentioned in the correpsonding fragments of this source.
17
 *
18
 * @package chamilo.library
19
 */
20
21
// Special tags for marking untranslated variables.
22
define('SPECIAL_OPENING_TAG', '[=');
23
define('SPECIAL_CLOSING_TAG', '=]');
24
25
// Predefined date formats in Chamilo provided by the language sub-system.
26
// To be used as a parameter for the function api_format_date()
27
28
define('TIME_NO_SEC_FORMAT', 0); // 15:23
29
define('DATE_FORMAT_SHORT', 1); // Aug 25, 09
30
define('DATE_FORMAT_LONG', 2); // Monday August 25, 09
31
define('DATE_FORMAT_LONG_NO_DAY', 10); // August 25, 2009
32
define('DATE_TIME_FORMAT_LONG', 3); // Monday August 25, 2009 at 03:28 PM
33
34
define('DATE_FORMAT_NUMBER', 4); // 25.08.09
35
define('DATE_TIME_FORMAT_LONG_24H', 5); // August 25, 2009 at 15:28
36
define('DATE_TIME_FORMAT_SHORT', 6); // Aug 25, 2009 at 03:28 PM
37
define('DATE_TIME_FORMAT_SHORT_TIME_FIRST', 7); // 03:28 PM, Aug 25 2009
38
define('DATE_FORMAT_NUMBER_NO_YEAR', 8); // 25.08 dd-mm
39
define('DATE_FORMAT_ONLY_DAYNAME', 9); // Monday, Sunday, etc
40
41
// Formatting person's name.
42
// Formatting a person's name using the pattern as it has been
43
// configured in the internationalization database for every language.
44
// This (default) option would be the most used.
45
define('PERSON_NAME_COMMON_CONVENTION', 0);
46
// The following options may be used in limited number of places for overriding the common convention:
47
48
// Formatting a person's name in Western order: first_name last_name
49
define('PERSON_NAME_WESTERN_ORDER', 1);
50
// Formatting a person's name in Eastern order: last_name first_name
51
define('PERSON_NAME_EASTERN_ORDER', 2);
52
// Contextual: formatting person's name in library order: last_name, first_name
53
define('PERSON_NAME_LIBRARY_ORDER', 3);
54
// Contextual: formatting a person's name assotiated with an email-address.
55
// Ivan: I am not sure how seems email servers an clients would interpret name order, so I assign the Western order.
56
define('PERSON_NAME_EMAIL_ADDRESS', PERSON_NAME_WESTERN_ORDER);
57
// Contextual: formatting a person's name for data-exporting operations.
58
// For backward compatibility this format has been set to Eastern order.
59
define('PERSON_NAME_DATA_EXPORT', PERSON_NAME_EASTERN_ORDER);
60
61
/**
62
 * Returns a translated (localized) string.
63
 *
64
 * @param string $variable
65
 *
66
 * @return string
67
 */
68
function get_lang($variable)
69
{
70
    $translator = Container::getTranslator();
71
72
    if (!$translator) {
0 ignored issues
show
introduced by
$translator is of type Symfony\Contracts\Translation\TranslatorInterface, thus it always evaluated to true.
Loading history...
73
        return $variable;
74
    }
75
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
100
/**
101
 * Gets the current interface language.
102
 *
103
 * @param bool $purified              (optional)    When it is true, a purified (refined)
104
 *                                    language value will be returned, for example 'french' instead of 'french_unicode'
105
 * @param bool $setParentLanguageName
106
 *
107
 * @return string the current language of the interface
108
 */
109
function api_get_interface_language(
110
    $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

110
    /** @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...
111
    $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

111
    /** @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...
112
    $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

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

944
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...
945
{
946
    $system_encoding = api_get_system_encoding();
947
948
    return api_convert_encoding($string, $system_encoding, $from_encoding);
949
}
950
951
/**
952
 * Converts all applicable characters to HTML entities.
953
 *
954
 * @param string $string      the input string
955
 * @param int    $quote_style (optional)    The quote style - ENT_COMPAT (default), ENT_QUOTES, ENT_NOQUOTES
956
 * @param string $encoding    (optional)    The encoding (of the input string) used in conversion.
957
 *                            If it is omitted, the platform character set is assumed.
958
 *
959
 * @return string Returns the converted string.
960
 *                This function is aimed at replacing the function htmlentities() for human-language strings.
961
 *
962
 * @see http://php.net/manual/en/function.htmlentities
963
 */
964
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

964
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...
965
{
966
    switch ($quote_style) {
967
        case ENT_COMPAT:
968
            $string = str_replace(['&', '"', '<', '>'], ['&amp;', '&quot;', '&lt;', '&gt;'], $string);
969
            break;
970
        case ENT_QUOTES:
971
            $string = str_replace(['&', '\'', '"', '<', '>'], ['&amp;', '&#039;', '&quot;', '&lt;', '&gt;'], $string);
972
            break;
973
    }
974
975
    return mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8');
976
}
977
978
/**
979
 * Converts HTML entities into normal characters.
980
 *
981
 * @param string $string      the input string
982
 * @param int    $quote_style (optional)    The quote style - ENT_COMPAT (default), ENT_QUOTES, ENT_NOQUOTES
983
 * @param string $encoding    (optional)    The encoding (of the result) used in conversion.
984
 *                            If it is omitted, the platform character set is assumed.
985
 *
986
 * @return string Returns the converted string.
987
 *                This function is aimed at replacing the function html_entity_decode() for human-language strings.
988
 *
989
 * @see http://php.net/html_entity_decode
990
 */
991
function api_html_entity_decode($string, $quote_style = ENT_COMPAT, $encoding = 'UTF-8')
992
{
993
    if (empty($encoding)) {
994
        $encoding = _api_mb_internal_encoding();
995
    }
996
    if (api_is_encoding_supported($encoding)) {
997
        if (!api_is_utf8($encoding)) {
998
            $string = api_utf8_encode($string, $encoding);
999
        }
1000
        $string = html_entity_decode($string, $quote_style, 'UTF-8');
1001
        if (!api_is_utf8($encoding)) {
1002
            return api_utf8_decode($string, $encoding);
1003
        }
1004
1005
        return $string;
1006
    }
1007
1008
    return $string; // Here the function gives up.
1009
}
1010
1011
/**
1012
 * This function encodes (conditionally) a given string to UTF-8 if XmlHttp-request has been detected.
1013
 *
1014
 * @param string $string        the string being converted
1015
 * @param string $from_encoding (optional)    The encoding that $string is being converted from.
1016
 *                              If it is omitted, the platform character set is assumed.
1017
 *
1018
 * @return string returns the converted string
1019
 */
1020
function api_xml_http_response_encode($string, $from_encoding = 'UTF8')
1021
{
1022
    if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
1023
        if (empty($from_encoding)) {
1024
            $from_encoding = _api_mb_internal_encoding();
1025
        }
1026
        if (!api_is_utf8($from_encoding)) {
1027
            return api_utf8_encode($string, $from_encoding);
1028
        }
1029
    }
1030
1031
    return $string;
1032
}
1033
1034
/**
1035
 * Transliterates a string with arbitrary encoding into a plain ASCII string.
1036
 *
1037
 * Example:
1038
 * echo api_transliterate(api_html_entity_decode(
1039
 *    '&#1060;&#1105;&#1076;&#1086;&#1088; '.
1040
 *    '&#1052;&#1080;&#1093;&#1072;&#1081;&#1083;&#1086;&#1074;&#1080;&#1095; '.
1041
 *    '&#1044;&#1086;&#1089;&#1090;&#1086;&#1077;&#1074;&#1082;&#1080;&#1081;',
1042
 *    ENT_QUOTES, 'UTF-8'), 'X', 'UTF-8');
1043
 * The output should be: Fyodor Mihaylovich Dostoevkiy
1044
 *
1045
 * @param string $string        the input string
1046
 * @param string $unknown       (optional) Replacement character for unknown characters and illegal UTF-8 sequences
1047
 * @param string $from_encoding (optional) The encoding of the input string.
1048
 *                              If it is omitted, the platform character set is assumed.
1049
 *
1050
 * @return string plain ASCII output
1051
 */
1052
function api_transliterate($string, $unknown = '?', $from_encoding = null)
0 ignored issues
show
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

1052
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...
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

1052
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...
1053
{
1054
    return URLify::transliterate($string);
1055
}
1056
1057
/**
1058
 * Takes the first character in a string and returns its Unicode codepoint.
1059
 *
1060
 * @param string $character the input string
1061
 * @param string $encoding  (optional) The encoding of the input string.
1062
 *                          If it is omitted, the platform character set will be used by default.
1063
 *
1064
 * @return int Returns: the codepoint of the first character; or 0xFFFD (unknown character) when the input string is empty.
1065
 *             This is a multibyte aware version of the function ord().
1066
 *
1067
 * @see http://php.net/manual/en/function.ord.php
1068
 * Note the difference with the original funtion ord(): ord('') returns 0, api_ord('') returns 0xFFFD (unknown character).
1069
 */
1070
function api_ord($character, $encoding = 'UTF-8')
1071
{
1072
    return Utf8::ord(api_utf8_encode($character, $encoding));
1073
}
1074
1075
/**
1076
 * This function returns a string or an array with all occurrences of search
1077
 * in subject (ignoring case) replaced with the given replace value.
1078
 *
1079
 * @param mixed  $search   string or array of strings to be found
1080
 * @param mixed  $replace  string or array of strings used for replacement
1081
 * @param mixed  $subject  string or array of strings being searched
1082
 * @param int    $count    (optional) The number of matched and replaced needles
1083
 *                         will be returned in count, which is passed by reference
1084
 * @param string $encoding (optional) The used internally by this function character encoding.
1085
 *                         If it is omitted, the platform character set will be used by default.
1086
 *
1087
 * @return mixed String or array as a result.
1088
 *               Notes:
1089
 *               If $subject is an array, then the search and replace is performed with
1090
 *               every entry of subject, the return value is an array.
1091
 *               If $search and $replace are arrays, then the function takes a value from
1092
 *               each array and uses it to do search and replace on subject.
1093
 *               If $replace has fewer values than search, then an empty string is used for the rest of replacement values.
1094
 *               If $search is an array and $replace is a string, then this replacement string is used for every value of search.
1095
 *               This function is aimed at replacing the function str_ireplace() for human-language strings.
1096
 *
1097
 * @see http://php.net/manual/en/function.str-ireplace
1098
 *
1099
 * @author Henri Sivonen, mailto:[email protected]
1100
 *
1101
 * @see http://hsivonen.iki.fi/php-utf8/
1102
 * Adaptation for Chamilo 1.8.7, 2010
1103
 * Initial implementation Dokeos LMS, August 2009
1104
 *
1105
 * @author Ivan Tcholakov
1106
 */
1107
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

1107
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...
1108
{
1109
    return Utf8::str_ireplace($search, $replace, $subject, $count);
1110
}
1111
1112
/**
1113
 * Converts a string to an array.
1114
 *
1115
 * @param string $string       the input string
1116
 * @param int    $split_length maximum character-length of the chunk, one character by default
1117
 * @param string $encoding     (optional) The used internally by this function
1118
 *                             character encoding. If it is omitted, the platform character set will be used by default.
1119
 *
1120
 * @return array The result array of chunks with the spcified length.
1121
 *               Notes:
1122
 *               If the optional split_length parameter is specified, the returned array will be broken down into chunks
1123
 *               with each being split_length in length, otherwise each chunk will be one character in length.
1124
 *               FALSE is returned if split_length is less than 1.
1125
 *               If the split_length length exceeds the length of string, the entire string is returned as the first (and only) array element.
1126
 *               This function is aimed at replacing the function str_split() for human-language strings.
1127
 *
1128
 * @see http://php.net/str_split
1129
 */
1130
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

1130
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...
1131
{
1132
    return Utf8::str_split($string, $split_length);
1133
}
1134
1135
/**
1136
 * Finds position of first occurrence of a string within another, case insensitive.
1137
 *
1138
 * @param string $haystack the string from which to get the position of the first occurrence
1139
 * @param string $needle   the string to be found
1140
 * @param int    $offset   The position in $haystack to start searching from.
1141
 *                         If it is omitted, searching starts from the beginning.
1142
 * @param string $encoding (optional) The used internally by this function
1143
 *                         character encoding. If it is omitted, the platform character set will be used by default.
1144
 *
1145
 * @return mixed Returns the numeric position of the first occurrence of
1146
 *               $needle in the $haystack, or FALSE if $needle is not found.
1147
 *               Note: The first character's position is 0, the second character position is 1, and so on.
1148
 *               This function is aimed at replacing the functions stripos() and mb_stripos() for human-language strings.
1149
 *
1150
 * @see http://php.net/manual/en/function.stripos
1151
 * @see http://php.net/manual/en/function.mb-stripos
1152
 */
1153
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

1153
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...
1154
{
1155
    return Utf8::stripos($haystack, $needle, $offset);
1156
}
1157
1158
/**
1159
 * Finds first occurrence of a string within another, case insensitive.
1160
 *
1161
 * @param string $haystack      the string from which to get the first occurrence
1162
 * @param mixed  $needle        the string to be found
1163
 * @param bool   $before_needle (optional) Determines which portion of $haystack
1164
 *                              this function returns. The default value is FALSE.
1165
 * @param string $encoding      (optional) The used internally by this function
1166
 *                              character encoding. If it is omitted, the platform character set will be used by default.
1167
 *
1168
 * @return mixed Returns the portion of $haystack, or FALSE if $needle is not found.
1169
 *               Notes:
1170
 *               If $needle is not a string, it is converted to an integer and applied as the
1171
 *               ordinal value (codepoint if the encoding is UTF-8) of a character.
1172
 *               If $before_needle is set to TRUE, the function returns all of $haystack
1173
 *               from the beginning to the first occurrence of $needle.
1174
 *               If $before_needle is set to FALSE, the function returns all of $haystack f
1175
 *               rom the first occurrence of $needle to the end.
1176
 *               This function is aimed at replacing the functions stristr() and mb_stristr() for human-language strings.
1177
 *
1178
 * @see http://php.net/manual/en/function.stristr
1179
 * @see http://php.net/manual/en/function.mb-stristr
1180
 */
1181
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

1181
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...
1182
{
1183
    return Utf8::stristr($haystack, $needle, $before_needle);
1184
}
1185
1186
/**
1187
 * Returns length of the input string.
1188
 *
1189
 * @param string $string   the string which length is to be calculated
1190
 * @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.
1191
 *
1192
 * @return int Returns the number of characters within the string. A multi-byte character is counted as 1.
1193
 *             This function is aimed at replacing the functions strlen() and mb_strlen() for human-language strings.
1194
 *
1195
 * @see http://php.net/manual/en/function.strlen
1196
 * @see http://php.net/manual/en/function.mb-strlen
1197
 * Note: When you use strlen() to test for an empty string, you needn't change it to api_strlen().
1198
 * For example, in lines like the following:
1199
 * if (strlen($string) > 0)
1200
 * if (strlen($string) != 0)
1201
 * there is no need the original function strlen() to be changed, it works correctly and faster for these cases.
1202
 */
1203
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

1203
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...
1204
{
1205
    return Utf8::strlen($string);
1206
}
1207
1208
/**
1209
 * Finds position of first occurrence of a string within another.
1210
 *
1211
 * @param string $haystack the string from which to get the position of the first occurrence
1212
 * @param string $needle   the string to be found
1213
 * @param int    $offset   (optional) The position in $haystack to start searching from. If it is omitted, searching starts from the beginning.
1214
 * @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.
1215
 *
1216
 * @return mixed Returns the numeric position of the first occurrence of $needle in the $haystack, or FALSE if $needle is not found.
1217
 *               Note: The first character's position is 0, the second character position is 1, and so on.
1218
 *               This function is aimed at replacing the functions strpos() and mb_strpos() for human-language strings.
1219
 *
1220
 * @see http://php.net/manual/en/function.strpos
1221
 * @see http://php.net/manual/en/function.mb-strpos
1222
 */
1223
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

1223
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...
1224
{
1225
    return Utf8::strpos($haystack, $needle, $offset);
1226
}
1227
1228
/**
1229
 * Finds the last occurrence of a character in a string.
1230
 *
1231
 * @param string $haystack      the string from which to get the last occurrence
1232
 * @param mixed  $needle        the string which first character is to be found
1233
 * @param bool   $before_needle (optional) Determines which portion of $haystack this function returns. The default value is FALSE.
1234
 * @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.
1235
 *
1236
 * @return mixed Returns the portion of $haystack, or FALSE if the first character from $needle is not found.
1237
 *               Notes:
1238
 *               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.
1239
 *               If $before_needle is set to TRUE, the function returns all of $haystack from the beginning to the first occurrence.
1240
 *               If $before_needle is set to FALSE, the function returns all of $haystack from the first occurrence to the end.
1241
 *               This function is aimed at replacing the functions strrchr() and mb_strrchr() for human-language strings.
1242
 *
1243
 * @see http://php.net/manual/en/function.strrchr
1244
 * @see http://php.net/manual/en/function.mb-strrchr
1245
 */
1246
function api_strrchr($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

1246
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...
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

1246
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...
1247
{
1248
    return Utf8::strrchr($haystack, $needle);
1249
}
1250
1251
/**
1252
 * Reverses a string.
1253
 *
1254
 * @param string $string   the string to be reversed
1255
 * @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.
1256
 *
1257
 * @return string Returns the reversed string.
1258
 *                This function is aimed at replacing the function strrev() for human-language strings.
1259
 *
1260
 * @see http://php.net/manual/en/function.strrev
1261
 */
1262
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

1262
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...
1263
{
1264
    return Utf8::strrev($string);
1265
}
1266
1267
/**
1268
 * Finds the position of last occurrence (case insensitive) of a string in a string.
1269
 *
1270
 * @param string $haystack the string from which to get the position of the last occurrence
1271
 * @param string $needle   the string to be found
1272
 * @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.
1273
 * @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.
1274
 *
1275
 * @return mixed Returns the numeric position of the first occurrence (case insensitive) of $needle in the $haystack, or FALSE if $needle is not found.
1276
 *               Note: The first character's position is 0, the second character position is 1, and so on.
1277
 *               This function is aimed at replacing the functions strripos() and mb_strripos() for human-language strings.
1278
 *
1279
 * @see http://php.net/manual/en/function.strripos
1280
 * @see http://php.net/manual/en/function.mb-strripos
1281
 */
1282
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

1282
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...
1283
{
1284
    return Utf8::strripos($haystack, $needle, $offset);
1285
}
1286
1287
/**
1288
 * Finds the position of last occurrence of a string in a string.
1289
 *
1290
 * @param string $haystack the string from which to get the position of the last occurrence
1291
 * @param string $needle   the string to be found
1292
 * @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.
1293
 * @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.
1294
 *
1295
 * @return mixed Returns the numeric position of the first occurrence of $needle in the $haystack, or FALSE if $needle is not found.
1296
 *               Note: The first character's position is 0, the second character position is 1, and so on.
1297
 *               This function is aimed at replacing the functions strrpos() and mb_strrpos() for human-language strings.
1298
 *
1299
 * @see http://php.net/manual/en/function.strrpos
1300
 * @see http://php.net/manual/en/function.mb-strrpos
1301
 */
1302
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

1302
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...
1303
{
1304
    return Utf8::strrpos($haystack, $needle, $offset);
1305
}
1306
1307
/**
1308
 * Finds first occurrence of a string within another.
1309
 *
1310
 * @param string $haystack      the string from which to get the first occurrence
1311
 * @param mixed  $needle        the string to be found
1312
 * @param bool   $before_needle (optional) Determines which portion of $haystack this function returns. The default value is FALSE.
1313
 * @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.
1314
 *
1315
 * @return mixed Returns the portion of $haystack, or FALSE if $needle is not found.
1316
 *               Notes:
1317
 *               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.
1318
 *               If $before_needle is set to TRUE, the function returns all of $haystack from the beginning to the first occurrence of $needle.
1319
 *               If $before_needle is set to FALSE, the function returns all of $haystack from the first occurrence of $needle to the end.
1320
 *               This function is aimed at replacing the functions strstr() and mb_strstr() for human-language strings.
1321
 *
1322
 * @see http://php.net/manual/en/function.strstr
1323
 * @see http://php.net/manual/en/function.mb-strstr
1324
 */
1325
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

1325
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...
1326
{
1327
    return Utf8::strstr($haystack, $needle, $before_needle);
1328
}
1329
1330
/**
1331
 * Makes a string lowercase.
1332
 *
1333
 * @param string $string   the string being lowercased
1334
 * @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.
1335
 *
1336
 * @return string Returns the string with all alphabetic characters converted to lowercase.
1337
 *                This function is aimed at replacing the functions strtolower() and mb_strtolower() for human-language strings.
1338
 *
1339
 * @see http://php.net/manual/en/function.strtolower
1340
 * @see http://php.net/manual/en/function.mb-strtolower
1341
 */
1342
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

1342
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...
1343
{
1344
    return Utf8::strtolower($string);
1345
}
1346
1347
/**
1348
 * Makes a string uppercase.
1349
 *
1350
 * @param string $string   the string being uppercased
1351
 * @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.
1352
 *
1353
 * @return string Returns the string with all alphabetic characters converted to uppercase.
1354
 *                This function is aimed at replacing the functions strtoupper() and mb_strtoupper() for human-language strings.
1355
 *
1356
 * @see http://php.net/manual/en/function.strtoupper
1357
 * @see http://php.net/manual/en/function.mb-strtoupper
1358
 */
1359
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

1359
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...
1360
{
1361
    return Utf8::strtoupper($string);
1362
}
1363
1364
/**
1365
 * // Gets part of a string.
1366
 *
1367
 * @param string $string   the input string
1368
 * @param int    $start    the first position from which the extracted part begins
1369
 * @param int    $length   the length in character of the extracted part
1370
 * @param string $encoding (optional) The used internally by this function
1371
 *                         character encoding. If it is omitted, the platform character set will be used by default.
1372
 *
1373
 * @return string Returns the part of the string specified by the start and length parameters.
1374
 *                Note: First character's position is 0. Second character position is 1, and so on.
1375
 *                This function is aimed at replacing the functions substr() and mb_substr() for human-language strings.
1376
 *
1377
 * @see http://php.net/manual/en/function.substr
1378
 * @see http://php.net/manual/en/function.mb-substr
1379
 */
1380
function api_substr($string, $start, $length = null, $encoding = null)
1381
{
1382
    if (is_null($length)) {
1383
        $length = api_strlen($string, $encoding);
1384
    }
1385
1386
    return Utf8::substr($string, $start, $length);
1387
}
1388
1389
/**
1390
 * Counts the number of substring occurrences.
1391
 *
1392
 * @param string $haystack the string being checked
1393
 * @param string $needle   the string being found
1394
 * @param string $encoding (optional) The used internally by this function character encoding.
1395
 *                         If it is omitted, the platform character set will be used by default.
1396
 *
1397
 * @return int the number of times the needle substring occurs in the haystack string
1398
 *
1399
 * @see http://php.net/manual/en/function.mb-substr-count.php
1400
 */
1401
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

1401
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...
1402
{
1403
    return Utf8::substr_count($haystack, $needle);
1404
}
1405
1406
/**
1407
 * Replaces text within a portion of a string.
1408
 *
1409
 * @param string $string      the input string
1410
 * @param string $replacement the replacement string
1411
 * @param int    $start       The position from which replacing will begin.
1412
 *                            Notes:
1413
 *                            If $start is positive, the replacing will begin at the $start'th offset into the string.
1414
 *                            If $start is negative, the replacing will begin at the $start'th character from the end of the string.
1415
 * @param int    $length      (optional) The position where replacing will end.
1416
 *                            Notes:
1417
 *                            If given and is positive, it represents the length of the portion of the string which is to be replaced.
1418
 *                            If it is negative, it represents the number of characters from the end of string at which to stop replacing.
1419
 *                            If it is not given, then it will default to api_strlen($string); i.e. end the replacing at the end of string.
1420
 *                            If $length is zero, then this function will have the effect of inserting replacement into the string at the given start offset.
1421
 * @param string $encoding    (optional)    The used internally by this function character encoding.
1422
 *                            If it is omitted, the platform character set will be used by default.
1423
 *
1424
 * @return string The result string is returned.
1425
 *                This function is aimed at replacing the function substr_replace() for human-language strings.
1426
 *
1427
 * @see http://php.net/manual/function.substr-replace
1428
 */
1429
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

1429
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...
1430
{
1431
    if (is_null($length)) {
1432
        $length = api_strlen($string);
1433
    }
1434
1435
    return UTf8::substr_replace($string, $replacement, $start, $length);
1436
}
1437
1438
/**
1439
 * Makes a string's first character uppercase.
1440
 *
1441
 * @param string $string   the input string
1442
 * @param string $encoding (optional)    The used internally by this function character encoding.
1443
 *                         If it is omitted, the platform character set will be used by default.
1444
 *
1445
 * @return string Returns a string with the first character capitalized, if that character is alphabetic.
1446
 *                This function is aimed at replacing the function ucfirst() for human-language strings.
1447
 *
1448
 * @see http://php.net/manual/en/function.ucfirst
1449
 */
1450
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

1450
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...
1451
{
1452
    return Utf8::ucfirst($string);
1453
}
1454
1455
/**
1456
 * Uppercases the first character of each word in a string.
1457
 *
1458
 * @param string $string   the input string
1459
 * @param string $encoding (optional) The used internally by this function character encoding.
1460
 *                         If it is omitted, the platform character set will be used by default.
1461
 *
1462
 * @return string Returns the modified string.
1463
 *                This function is aimed at replacing the function ucwords() for human-language strings.
1464
 *
1465
 * @see http://php.net/manual/en/function.ucwords
1466
 */
1467
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

1467
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...
1468
{
1469
    return Utf8::ucwords($string);
1470
}
1471
1472
/**
1473
 * Performs a regular expression match, UTF-8 aware when it is applicable.
1474
 *
1475
 * @param string $pattern  the pattern to search for, as a string
1476
 * @param string $subject  the input string
1477
 * @param array  &$matches (optional) If matches is provided,
1478
 *                         then it is filled with the results of search (as an array).
1479
 *                         $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.
1480
 * @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.
1481
 *                         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.
1482
 * @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.
1483
 * @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.
1484
 *
1485
 * @return int|bool returns the number of times pattern matches or FALSE if an error occurred
1486
 *
1487
 * @see http://php.net/preg_match
1488
 */
1489
function api_preg_match(
1490
    $pattern,
1491
    $subject,
1492
    &$matches = null,
1493
    $flags = 0,
1494
    $offset = 0,
1495
    $encoding = null
1496
) {
1497
    if (empty($encoding)) {
1498
        $encoding = _api_mb_internal_encoding();
1499
    }
1500
1501
    return preg_match(api_is_utf8($encoding) ? $pattern.'u' : $pattern, $subject, $matches, $flags, $offset);
1502
}
1503
1504
/**
1505
 * Performs a global regular expression match, UTF-8 aware when it is applicable.
1506
 *
1507
 * @param string $pattern  the pattern to search for, as a string
1508
 * @param string $subject  the input string
1509
 * @param array  &$matches (optional)    Array of all matches in multi-dimensional array ordered according to $flags
1510
 * @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):
1511
 *                         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;
1512
 *                         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;
1513
 *                         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
1514
 *                         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.
1515
 *                         If no order flag is given, PREG_PATTERN_ORDER is assumed.
1516
 * @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.
1517
 * @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.
1518
 *
1519
 * @return int|bool returns the number of full pattern matches (which might be zero), or FALSE if an error occurred
1520
 *
1521
 * @see http://php.net/preg_match_all
1522
 */
1523
function api_preg_match_all($pattern, $subject, &$matches, $flags = PREG_PATTERN_ORDER, $offset = 0, $encoding = null)
1524
{
1525
    if (empty($encoding)) {
1526
        $encoding = _api_mb_internal_encoding();
1527
    }
1528
    if (is_null($flags)) {
1529
        $flags = PREG_PATTERN_ORDER;
1530
    }
1531
1532
    return preg_match_all(api_is_utf8($encoding) ? $pattern.'u' : $pattern, $subject, $matches, $flags, $offset);
1533
}
1534
1535
/**
1536
 * Performs a regular expression search and replace, UTF-8 aware when it is applicable.
1537
 *
1538
 * @param string|array $pattern     The pattern to search for. It can be either a string or an array with strings.
1539
 * @param string|array $replacement the string or an array with strings to replace
1540
 * @param string|array $subject     the string or an array with strings to search and replace
1541
 * @param int          $limit       The maximum possible replacements for each pattern in each subject string. Defaults to -1 (no limit).
1542
 * @param int          &$count      If specified, this variable will be filled with the number of replacements done
1543
 * @param string       $encoding    (optional)	The used internally by this function character encoding.
1544
 *                                  If it is omitted, the platform character set will be used by default.
1545
 *
1546
 * @return array|string|null returns an array if the subject parameter is an array, or a string otherwise.
1547
 *                           If matches are found, the new subject will be returned, otherwise subject will be returned unchanged or NULL if an error occurred.
1548
 *
1549
 * @see http://php.net/preg_replace
1550
 */
1551
function api_preg_replace($pattern, $replacement, $subject, $limit = -1, &$count = 0, $encoding = null)
1552
{
1553
    if (empty($encoding)) {
1554
        $encoding = _api_mb_internal_encoding();
1555
    }
1556
    $is_utf8 = api_is_utf8($encoding);
1557
    if (is_array($pattern)) {
1558
        foreach ($pattern as &$p) {
1559
            $p = $is_utf8 ? $p.'u' : $p;
1560
        }
1561
    } else {
1562
        $pattern = $is_utf8 ? $pattern.'u' : $pattern;
1563
    }
1564
1565
    return preg_replace($pattern, $replacement, $subject, $limit, $count);
1566
}
1567
1568
/**
1569
 * Splits a string by a regular expression, UTF-8 aware when it is applicable.
1570
 *
1571
 * @param string $pattern  the pattern to search for, as a string
1572
 * @param string $subject  the input string
1573
 * @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.
1574
 * @param int    $flags    (optional)			$flags can be any combination of the following flags (combined with bitwise | operator):
1575
 *                         PREG_SPLIT_NO_EMPTY - if this flag is set, only non-empty pieces will be returned;
1576
 *                         PREG_SPLIT_DELIM_CAPTURE - if this flag is set, parenthesized expression in the delimiter pattern will be captured and returned as well;
1577
 *                         PREG_SPLIT_OFFSET_CAPTURE - If this flag is set, for every occurring match the appendant string offset will also be returned.
1578
 *                         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.
1579
 * @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.
1580
 *
1581
 * @return array returns an array containing substrings of $subject split along boundaries matched by $pattern
1582
 *
1583
 * @see http://php.net/preg_split
1584
 */
1585
function api_preg_split($pattern, $subject, $limit = -1, $flags = 0, $encoding = null)
1586
{
1587
    if (empty($encoding)) {
1588
        $encoding = _api_mb_internal_encoding();
1589
    }
1590
1591
    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...
1592
}
1593
1594
/**
1595
 * String comparison.
1596
 */
1597
1598
/**
1599
 * Performs string comparison, case insensitive, language sensitive, with extended multibyte support.
1600
 *
1601
 * @param string $string1  the first string
1602
 * @param string $string2  the second string
1603
 * @param string $language (optional) The language in which comparison is to be made. If language is omitted, interface language is assumed then.
1604
 * @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.
1605
 *
1606
 * @return int Returns < 0 if $string1 is less than $string2; > 0 if $string1 is greater than $string2; and 0 if the strings are equal.
1607
 *             This function is aimed at replacing the function strcasecmp() for human-language strings.
1608
 *
1609
 * @see http://php.net/manual/en/function.strcasecmp
1610
 */
1611
function api_strcasecmp($string1, $string2, $language = null, $encoding = null)
1612
{
1613
    return api_strcmp(api_strtolower($string1, $encoding), api_strtolower($string2, $encoding), $language, $encoding);
1614
}
1615
1616
/**
1617
 * Performs string comparison, case sensitive, language sensitive, with extended multibyte support.
1618
 *
1619
 * @param string $string1  the first string
1620
 * @param string $string2  the second string
1621
 * @param string $language (optional)	The language in which comparison is to be made. If language is omitted, interface language is assumed then.
1622
 * @param string $encoding (optional)	The used internally by this function character encoding.
1623
 *                         If it is omitted, the platform character set will be used by default.
1624
 *
1625
 * @return int Returns < 0 if $string1 is less than $string2; > 0 if $string1 is greater than $string2; and 0 if the strings are equal.
1626
 *             This function is aimed at replacing the function strcmp() for human-language strings.
1627
 *
1628
 * @see http://php.net/manual/en/function.strcmp.php
1629
 * @see http://php.net/manual/en/collator.compare.php
1630
 */
1631
function api_strcmp($string1, $string2, $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

1631
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...
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

1631
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...
1632
{
1633
    return strcmp($string1, $string2);
1634
}
1635
1636
/**
1637
 * Performs string comparison in so called "natural order", case sensitive, language sensitive, with extended multibyte support.
1638
 *
1639
 * @param string $string1  the first string
1640
 * @param string $string2  the second string
1641
 * @param string $language (optional)	The language in which comparison is to be made. If language is omitted, interface language is assumed then.
1642
 * @param string $encoding (optional)	The used internally by this function character encoding.
1643
 *                         If it is omitted, the platform character set will be used by default.
1644
 *
1645
 * @return int Returns < 0 if $string1 is less than $string2; > 0 if $string1 is greater than $string2; and 0 if the strings are equal.
1646
 *             This function is aimed at replacing the function strnatcmp() for human-language strings.
1647
 *
1648
 * @see http://php.net/manual/en/function.strnatcmp.php
1649
 * @see http://php.net/manual/en/collator.compare.php
1650
 */
1651
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

1651
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

1651
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...
1652
{
1653
    return strnatcmp($string1, $string2);
1654
}
1655
1656
/**
1657
 * Sorting arrays.
1658
 */
1659
1660
/**
1661
 * Sorts an array using natural order algorithm.
1662
 *
1663
 * @param array  $array    the input array
1664
 * @param string $language (optional)	The language in which comparison is to be made. If language is omitted, interface language is assumed then.
1665
 * @param string $encoding (optional)	The used internally by this function character encoding.
1666
 *                         If it is omitted, the platform character set will be used by default.
1667
 *
1668
 * @return bool Returns TRUE on success, FALSE on error.
1669
 *              This function is aimed at replacing the function natsort() for sorting human-language strings.
1670
 *
1671
 * @see http://php.net/manual/en/function.natsort.php
1672
 */
1673
function api_natsort(&$array, $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

1673
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...
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

1673
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...
1674
{
1675
    return natsort($array);
1676
}
1677
1678
/**
1679
 * Sorts an array using natural order algorithm in reverse order.
1680
 *
1681
 * @param array  $array    the input array
1682
 * @param string $language (optional)	The language in which comparison is to be made. If language is omitted, interface language is assumed then.
1683
 * @param string $encoding (optional)	The used internally by this function character encoding.
1684
 *                         If it is omitted, the platform character set will be used by default.
1685
 *
1686
 * @return bool returns TRUE on success, FALSE on error
1687
 */
1688
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

1688
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

1688
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...
1689
{
1690
    return uasort($array, '_api_strnatrcmp');
1691
}
1692
1693
/**
1694
 * Encoding management functions.
1695
 */
1696
1697
/**
1698
 * This function unifies the encoding identificators, so they could be compared.
1699
 *
1700
 * @param string|array $encoding the specified encoding
1701
 *
1702
 * @return string returns the encoding identificator modified in suitable for comparison way
1703
 */
1704
function api_refine_encoding_id($encoding)
1705
{
1706
    if (is_array($encoding)) {
1707
        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...
1708
    }
1709
1710
    return strtoupper(str_replace('_', '-', $encoding));
1711
}
1712
1713
/**
1714
 * This function checks whether two $encoding are equal (same, equvalent).
1715
 *
1716
 * @param string|array $encoding1 The first encoding
1717
 * @param string|array $encoding2 The second encoding
1718
 * @param bool         $strict    When this parameter is TRUE the comparison ignores aliases of encodings.
1719
 *                                When the parameter is FALSE, aliases are taken into account.
1720
 *
1721
 * @return bool returns TRUE if the encodings are equal, FALSE otherwise
1722
 */
1723
function api_equal_encodings($encoding1, $encoding2, $strict = false)
1724
{
1725
    static $equal_encodings = [];
1726
    if (is_array($encoding1)) {
1727
        foreach ($encoding1 as $encoding) {
1728
            if (api_equal_encodings($encoding, $encoding2, $strict)) {
1729
                return true;
1730
            }
1731
        }
1732
1733
        return false;
1734
    } elseif (is_array($encoding2)) {
1735
        foreach ($encoding2 as $encoding) {
1736
            if (api_equal_encodings($encoding1, $encoding, $strict)) {
1737
                return true;
1738
            }
1739
        }
1740
1741
        return false;
1742
    }
1743
    if (!isset($equal_encodings[$encoding1][$encoding2][$strict])) {
1744
        $encoding_1 = api_refine_encoding_id($encoding1);
1745
        $encoding_2 = api_refine_encoding_id($encoding2);
1746
        if ($encoding_1 == $encoding_2) {
1747
            $result = true;
1748
        } else {
1749
            if ($strict) {
1750
                $result = false;
1751
            } else {
1752
                $alias1 = _api_get_character_map_name($encoding_1);
1753
                $alias2 = _api_get_character_map_name($encoding_2);
1754
                $result = !empty($alias1) && !empty($alias2) && $alias1 == $alias2;
1755
            }
1756
        }
1757
        $equal_encodings[$encoding1][$encoding2][$strict] = $result;
1758
    }
1759
1760
    return $equal_encodings[$encoding1][$encoding2][$strict];
1761
}
1762
1763
/**
1764
 * This function checks whether a given encoding is UTF-8.
1765
 *
1766
 * @param string $encoding the tested encoding
1767
 *
1768
 * @return bool returns TRUE if the given encoding id means UTF-8, otherwise returns false
1769
 */
1770
function api_is_utf8($encoding)
1771
{
1772
    static $result = [];
1773
    if (!isset($result[$encoding])) {
1774
        $result[$encoding] = api_equal_encodings($encoding, 'UTF-8');
1775
    }
1776
1777
    return $result[$encoding];
1778
}
1779
1780
/**
1781
 * This function returns the encoding, currently used by the system.
1782
 *
1783
 * @return string The system's encoding.
1784
 *                Note: The value of api_get_setting('platform_charset') is tried to be returned first,
1785
 *                on the second place the global variable $charset is tried to be returned. If for some
1786
 *                reason both attempts fail, then the libraly's internal value will be returned.
1787
 */
1788
function api_get_system_encoding()
1789
{
1790
    return 'UTF-8';
1791
}
1792
1793
/**
1794
 * Checks whether a specified encoding is supported by this API.
1795
 *
1796
 * @param string $encoding the specified encoding
1797
 *
1798
 * @return bool returns TRUE when the specified encoding is supported, FALSE othewise
1799
 */
1800
function api_is_encoding_supported($encoding)
1801
{
1802
    static $supported = [];
1803
    if (!isset($supported[$encoding])) {
1804
        $supported[$encoding] = _api_mb_supports($encoding) || _api_iconv_supports($encoding) || _api_convert_encoding_supports($encoding);
1805
    }
1806
1807
    return $supported[$encoding];
1808
}
1809
1810
/**
1811
 * Detects encoding of plain text.
1812
 *
1813
 * @param string $string   the input text
1814
 * @param string $language (optional) The language of the input text, provided if it is known
1815
 *
1816
 * @return string returns the detected encoding
1817
 */
1818
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

1818
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...
1819
{
1820
    // Testing against valid UTF-8 first.
1821
    if (api_is_valid_utf8($string)) {
1822
        return 'UTF-8';
1823
    }
1824
1825
    return mb_detect_encoding($string);
1826
}
1827
1828
/**
1829
 * String validation functions concerning certain encodings.
1830
 */
1831
1832
/**
1833
 * Checks a string for UTF-8 validity.
1834
 *
1835
 * @param string $string
1836
 *
1837
 * @return string
1838
 */
1839
function api_is_valid_utf8($string)
1840
{
1841
    return Utf8::isUtf8($string);
1842
}
1843
1844
/**
1845
 * Checks whether a string contains 7-bit ASCII characters only.
1846
 *
1847
 * @param string $string the string to be tested/validated
1848
 *
1849
 * @return bool returns TRUE when the tested string contains 7-bit
1850
 *              ASCII characters only, FALSE othewise
1851
 */
1852
function api_is_valid_ascii(&$string)
1853
{
1854
    return mb_detect_encoding($string, 'ASCII', true) == 'ASCII' ? true : false;
1855
}
1856
1857
/**
1858
 * Return true a date is valid.
1859
 *
1860
 * @param string $date   example: 2014-06-30 13:05:05
1861
 * @param string $format example: "Y-m-d H:i:s"
1862
 *
1863
 * @return bool
1864
 */
1865
function api_is_valid_date($date, $format = 'Y-m-d H:i:s')
1866
{
1867
    $d = DateTime::createFromFormat($format, $date);
1868
1869
    return $d && $d->format($format) == $date;
1870
}
1871
1872
/**
1873
 * Returns the variable translated.
1874
 *
1875
 * @param string $variable   the string to translate
1876
 * @param string $pluginName the Plugin name
1877
 *
1878
 * @return string the variable translated
1879
 */
1880
function get_plugin_lang($variable, $pluginName)
1881
{
1882
    $plugin = $pluginName::create();
1883
1884
    return $plugin->get_lang($variable);
1885
}
1886
1887
/**
1888
 * Returns an array of translated week days and months, short and normal names.
1889
 *
1890
 * @param string $language (optional Language id. If it is omitted,
1891
 *                         the current interface language is assumed.
1892
 *
1893
 * @return array returns a multidimensional array with translated week days and months
1894
 */
1895
function &_api_get_day_month_names($language = null)
1896
{
1897
    static $date_parts = [];
1898
    if (empty($language)) {
1899
        $language = api_get_interface_language();
1900
    }
1901
    if (!isset($date_parts[$language])) {
1902
        $week_day = [
1903
            'Sunday',
1904
            'Monday',
1905
            'Tuesday',
1906
            'Wednesday',
1907
            'Thursday',
1908
            'Friday',
1909
            'Saturday',
1910
        ];
1911
        $month = [
1912
            'January',
1913
            'February',
1914
            'March',
1915
            'April',
1916
            'May',
1917
            'June',
1918
            'July',
1919
            'August',
1920
            'September',
1921
            'October',
1922
            'November',
1923
            'December',
1924
        ];
1925
        for ($i = 0; $i < 7; $i++) {
1926
            $date_parts[$language]['days_short'][] = get_lang(
1927
                $week_day[$i].'Short',
1928
                '',
1929
                $language
1930
            );
1931
            $date_parts[$language]['days_long'][] = get_lang(
1932
                $week_day[$i].'Long',
1933
                '',
1934
                $language
1935
            );
1936
        }
1937
        for ($i = 0; $i < 12; $i++) {
1938
            $date_parts[$language]['months_short'][] = get_lang(
1939
                $month[$i].'Short',
1940
                '',
1941
                $language
1942
            );
1943
            $date_parts[$language]['months_long'][] = get_lang(
1944
                $month[$i].'Long',
1945
                '',
1946
                $language
1947
            );
1948
        }
1949
    }
1950
1951
    return $date_parts[$language];
1952
}
1953
1954
/**
1955
 * Returns returns person name convention for a given language.
1956
 *
1957
 * @param string $language the input language
1958
 * @param string $type     The type of the requested convention.
1959
 *                         It may be 'format' for name order convention or 'sort_by' for name sorting convention.
1960
 *
1961
 * @return mixed Depending of the requested type,
1962
 *               the returned result may be string or boolean; null is returned on error;
1963
 */
1964
function _api_get_person_name_convention($language, $type)
1965
{
1966
    static $conventions;
1967
1968
    $language = api_get_language_from_iso($language);
1969
    $languageName = 'english';
1970
    if (!empty($language)) {
1971
        $languageName = $language->getEnglishName();
1972
    }
1973
1974
    if (!isset($conventions)) {
1975
        $file = __DIR__.'/internationalization_database/name_order_conventions.php';
1976
        if (file_exists($file)) {
1977
            $conventions = include $file;
1978
        } else {
1979
            $conventions = [
1980
                'english' => [
1981
                    'format' => 'title first_name last_name',
1982
                    'sort_by' => 'first_name',
1983
                ],
1984
            ];
1985
        }
1986
        // Overwrite classic conventions
1987
        $customConventions = api_get_configuration_value('name_order_conventions');
1988
1989
        if (!empty($customConventions)) {
1990
            foreach ($customConventions as $key => $data) {
1991
                $conventions[$key] = $data;
1992
            }
1993
        }
1994
1995
        $search1 = ['FIRST_NAME', 'LAST_NAME', 'TITLE'];
1996
        $replacement1 = ['%F', '%L', '%T'];
1997
        $search2 = ['first_name', 'last_name', 'title'];
1998
        $replacement2 = ['%f', '%l', '%t'];
1999
        foreach (array_keys($conventions) as $key) {
2000
            $conventions[$key]['format'] = str_replace($search1, $replacement1, $conventions[$key]['format']);
2001
            $conventions[$key]['format'] = _api_validate_person_name_format(
2002
                _api_clean_person_name(
2003
                    str_replace(
2004
                        '%',
2005
                        ' %',
2006
                        str_ireplace(
2007
                            $search2,
2008
                            $replacement2,
2009
                            $conventions[$key]['format']
2010
                        )
2011
                    )
2012
                )
2013
            );
2014
            $conventions[$key]['sort_by'] = strtolower($conventions[$key]['sort_by']) != 'last_name' ? true : false;
2015
        }
2016
    }
2017
    switch ($type) {
2018
        case 'format':
2019
            return is_string($conventions[$languageName]['format']) ? $conventions[$languageName]['format'] : '%t %f %l';
2020
        case 'sort_by':
2021
            return is_bool($conventions[$languageName]['sort_by']) ? $conventions[$languageName]['sort_by'] : true;
2022
    }
2023
2024
    return null;
2025
}
2026
2027
/**
2028
 * Replaces non-valid formats for person names with the default (English) format.
2029
 *
2030
 * @param string $format the input format to be verified
2031
 *
2032
 * @return bool returns the same format if is is valid, otherwise returns a valid English format
2033
 */
2034
function _api_validate_person_name_format($format)
2035
{
2036
    if (empty($format) || stripos($format, '%f') === false || stripos($format, '%l') === false) {
2037
        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...
2038
    }
2039
2040
    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...
2041
}
2042
2043
/**
2044
 * Removes leading, trailing and duplicate whitespace and/or commas in a full person name.
2045
 * Cleaning is needed for the cases when not all parts of the name are available
2046
 * or when the name is constructed using a "dirty" pattern.
2047
 *
2048
 * @param string $person_name the input person name
2049
 *
2050
 * @return string returns cleaned person name
2051
 */
2052
function _api_clean_person_name($person_name)
2053
{
2054
    return preg_replace(['/\s+/', '/, ,/', '/,+/', '/^[ ,]/', '/[ ,]$/'], [' ', ', ', ',', '', ''], $person_name);
2055
}
2056
2057
/**
2058
 * Appendix to "Multibyte string conversion functions".
2059
 */
2060
2061
/**
2062
 * This is a php-implementation of a function that is similar to mb_convert_encoding() from mbstring extension.
2063
 * The function converts a given string from one to another character encoding.
2064
 *
2065
 * @param string $string        the string being converted
2066
 * @param string $to_encoding   the encoding that $string is being converted to
2067
 * @param string $from_encoding the encoding that $string is being converted from
2068
 *
2069
 * @return string returns the converted string
2070
 */
2071
function _api_convert_encoding(&$string, $to_encoding, $from_encoding)
2072
{
2073
    return mb_convert_encoding($string, $to_encoding, $from_encoding);
2074
}
2075
2076
/**
2077
 * This function determines the name of corresponding to a given encoding conversion table.
2078
 * It is able to deal with some aliases of the encoding.
2079
 *
2080
 * @param string $encoding the given encoding identificator, for example 'WINDOWS-1252'
2081
 *
2082
 * @return string returns the name of the corresponding conversion table, for the same example - 'CP1252'
2083
 */
2084
function _api_get_character_map_name($encoding)
2085
{
2086
    static $character_map_selector;
2087
    if (!isset($character_map_selector)) {
2088
        $file = __DIR__.'/internationalization_database/conversion/character_map_selector.php';
2089
        if (file_exists($file)) {
2090
            $character_map_selector = include $file;
2091
        } else {
2092
            $character_map_selector = [];
2093
        }
2094
    }
2095
2096
    return isset($character_map_selector[$encoding]) ? $character_map_selector[$encoding] : '';
2097
}
2098
2099
/**
2100
 * Appendix to "String comparison".
2101
 */
2102
2103
/**
2104
 * A reverse function from php-core function strnatcmp(),
2105
 * performs string comparison in reverse natural (alpha-numerical) order.
2106
 *
2107
 * @param string $string1 the first string
2108
 * @param string $string2 the second string
2109
 *
2110
 * @return int returns 0 if $string1 = $string2; >0 if $string1 < $string2; <0 if $string1 > $string2
2111
 */
2112
function _api_strnatrcmp($string1, $string2)
2113
{
2114
    return strnatcmp($string2, $string1);
2115
}
2116
2117
/**
2118
 * Sets/Gets internal character encoding of the common string functions within the PHP mbstring extension.
2119
 *
2120
 * @param string $encoding (optional)    When this parameter is given, the function sets the internal encoding
2121
 *
2122
 * @return string When $encoding parameter is not given, the function returns the internal encoding.
2123
 *                Note: This function is used in the global initialization script for setting the
2124
 *                internal encoding to the platform's character set.
2125
 *
2126
 * @see http://php.net/manual/en/function.mb-internal-encoding
2127
 */
2128
function _api_mb_internal_encoding($encoding = 'UTF-8')
2129
{
2130
    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...
2131
}
2132
2133
/**
2134
 * Checks whether the specified encoding is supported by the PHP mbstring extension.
2135
 *
2136
 * @param string $encoding the specified encoding
2137
 *
2138
 * @return bool returns TRUE when the specified encoding is supported, FALSE othewise
2139
 */
2140
function _api_mb_supports($encoding)
2141
{
2142
    static $supported = [];
2143
    if (!isset($supported[$encoding])) {
2144
        if (MBSTRING_INSTALLED) {
2145
            $supported[$encoding] = api_equal_encodings($encoding, mb_list_encodings(), true);
2146
        } else {
2147
            $supported[$encoding] = false;
2148
        }
2149
    }
2150
2151
    return $supported[$encoding];
2152
}
2153
2154
/**
2155
 * Checks whether the specified encoding is supported by the PHP iconv extension.
2156
 *
2157
 * @param string $encoding the specified encoding
2158
 *
2159
 * @return bool returns TRUE when the specified encoding is supported, FALSE othewise
2160
 */
2161
function _api_iconv_supports($encoding)
2162
{
2163
    static $supported = [];
2164
    if (!isset($supported[$encoding])) {
2165
        if (ICONV_INSTALLED) {
2166
            $enc = api_refine_encoding_id($encoding);
2167
            if ($enc != 'HTML-ENTITIES') {
2168
                $test_string = '';
2169
                for ($i = 32; $i < 128; $i++) {
2170
                    $test_string .= chr($i);
2171
                }
2172
                $supported[$encoding] = (@iconv_strlen($test_string, $enc)) ? true : false;
2173
            } else {
2174
                $supported[$encoding] = false;
2175
            }
2176
        } else {
2177
            $supported[$encoding] = false;
2178
        }
2179
    }
2180
2181
    return $supported[$encoding];
2182
}
2183
2184
// This function checks whether the function _api_convert_encoding() (the php-
2185
// implementation) is able to convert from/to a given encoding.
2186
function _api_convert_encoding_supports($encoding)
2187
{
2188
    static $supports = [];
2189
    if (!isset($supports[$encoding])) {
2190
        $supports[$encoding] = _api_get_character_map_name(api_refine_encoding_id($encoding)) != '';
2191
    }
2192
2193
    return $supports[$encoding];
2194
}
2195
2196
/**
2197
 * Given a date object, return a human or ISO format, with or without h:m:s.
2198
 *
2199
 * @param object $date      The Date object
2200
 * @param bool   $showTime  Whether to show the time and date (true) or only the date (false)
2201
 * @param bool   $humanForm Whether to show day-month-year (true) or year-month-day (false)
2202
 *
2203
 * @return string Formatted date
2204
 */
2205
function api_get_human_date_time($date, $showTime = true, $humanForm = false)
2206
{
2207
    if ($showTime) {
2208
        if ($humanForm) {
2209
            return $date->format('j M Y H:i:s');
2210
        } else {
2211
            return $date->format('Y-m-d H:i:s');
2212
        }
2213
    } else {
2214
        if ($humanForm) {
2215
            return $date->format('j M Y');
2216
        } else {
2217
            return $date->format('Y-m-d');
2218
        }
2219
    }
2220
}
2221