Passed
Push — master ( 15378b...a2dd4f )
by Julito
09:24
created

api_get_local_time()   D

Complexity

Conditions 13
Paths 342

Size

Total Lines 56
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 27
c 0
b 0
f 0
nc 342
nop 7
dl 0
loc 56
rs 4.0083

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Framework\Container;
5
use 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               Returns a DateTime object
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
 *
282
 * @author Julio Montoya - Adding the 2nd parameter
283
 * @author Guillaume Viguier <[email protected]>
284
 */
285
function api_get_utc_datetime(
286
    $time = null,
287
    $returnNullIfInvalidDate = false,
288
    $returnObj = false
289
) {
290
    if (is_null($time) || empty($time) || $time === '0000-00-00 00:00:00') {
291
        if ($returnNullIfInvalidDate) {
292
            return null;
293
        }
294
        if ($returnObj) {
295
            return new DateTime(gmdate('Y-m-d H:i:s'), new DateTimeZone('UTC'));
296
        }
297
298
        return gmdate('Y-m-d H:i:s');
299
    }
300
301
    // If time is a timestamp, return directly in utc
302
    if (is_numeric($time)) {
303
        $time = (int) $time;
304
305
        return gmdate('Y-m-d H:i:s', $time);
306
    }
307
    try {
308
        $fromTimezone = api_get_timezone();
309
        $date = new DateTime($time, new DateTimezone($fromTimezone));
310
        $date->setTimezone(new DateTimeZone('UTC'));
311
        if ($returnObj) {
312
            return $date;
313
        } else {
314
            return $date->format('Y-m-d H:i:s');
315
        }
316
    } catch (Exception $e) {
317
        return null;
318
    }
319
}
320
321
/**
322
 * Returns a DATETIME string converted to the right timezone.
323
 *
324
 * @param mixed  $time                    The time to be converted
325
 * @param string $to_timezone             The timezone to be converted to.
326
 *                                        If null, the timezone will be determined based on user preference,
327
 *                                        or timezone chosen by the admin for the platform.
328
 * @param string $from_timezone           The timezone to be converted from. If null, UTC will be assumed.
329
 * @param bool   $returnNullIfInvalidDate
330
 * @param bool   $showTime
331
 * @param bool   $humanForm
332
 * @param string $format
333
 *
334
 * @return string The converted time formatted as Y-m-d H:i:s
335
 *
336
 * @author Guillaume Viguier <[email protected]>
337
 */
338
function api_get_local_time(
339
    $time = null,
340
    $to_timezone = null,
341
    $from_timezone = null,
342
    $returnNullIfInvalidDate = false,
343
    $showTime = true,
344
    $humanForm = false,
345
    $format = ''
346
) {
347
    // Determining the timezone to be converted from
348
    if (is_null($from_timezone)) {
349
        $from_timezone = 'UTC';
350
    }
351
352
    // If time is a timestamp, convert it to a string
353
    if (is_null($time) || empty($time) || $time == '0000-00-00 00:00:00') {
354
        if ($returnNullIfInvalidDate) {
355
            return null;
356
        }
357
        $from_timezone = 'UTC';
358
        $time = gmdate('Y-m-d H:i:s');
359
    }
360
361
    if (is_numeric($time)) {
362
        $time = (int) $time;
363
        if ($returnNullIfInvalidDate) {
364
            if (strtotime(date('d-m-Y H:i:s', $time)) !== (int) $time) {
365
                return null;
366
            }
367
        }
368
369
        $from_timezone = 'UTC';
370
        $time = gmdate('Y-m-d H:i:s', $time);
371
    }
372
373
    if ($time instanceof DateTime) {
374
        $time = $time->format('Y-m-d H:i:s');
375
        $from_timezone = 'UTC';
376
    }
377
378
    try {
379
        // Determining the timezone to be converted to
380
        if (is_null($to_timezone)) {
381
            $to_timezone = api_get_timezone();
382
        }
383
384
        $date = new DateTime($time, new DateTimezone($from_timezone));
385
        $date->setTimezone(new DateTimeZone($to_timezone));
386
387
        if (!empty($format)) {
388
            return $date->format($format);
389
        }
390
391
        return api_get_human_date_time($date, $showTime, $humanForm);
392
    } catch (Exception $e) {
393
        return '';
394
    }
395
}
396
397
/**
398
 * Converts a string into a timestamp safely (handling timezones), using strtotime.
399
 *
400
 * @param string $time     to be converted
401
 * @param string $timezone (if null, the timezone will be determined based
402
 *                         on user preference, or timezone chosen by the admin for the platform)
403
 *
404
 * @return int Timestamp
405
 *
406
 * @author Guillaume Viguier <[email protected]>
407
 */
408
function api_strtotime($time, $timezone = null)
409
{
410
    $system_timezone = date_default_timezone_get();
411
    if (!empty($timezone)) {
412
        date_default_timezone_set($timezone);
413
    }
414
    $timestamp = strtotime($time);
415
    if (!empty($timezone)) {
416
        // only reset timezone if it was changed
417
        date_default_timezone_set($system_timezone);
418
    }
419
420
    return $timestamp;
421
}
422
423
/**
424
 * Returns formatted date/time, correspondent to a given language.
425
 * The given date should be in the timezone chosen by the administrator
426
 * and/or user. Use api_get_local_time to get it.
427
 *
428
 * @author Patrick Cool <[email protected]>, Ghent University
429
 * @author Christophe Gesche<[email protected]>
430
 *         originally inspired from from PhpMyAdmin
431
 * @author Ivan Tcholakov, 2009, code refactoring, adding support for predefined date/time formats.
432
 * @author Guillaume Viguier <[email protected]>
433
 *
434
 * @param mixed $time Timestamp or datetime string
435
 * @param string|int Date format (see date formats in the Chamilo system:
436
 * TIME_NO_SEC_FORMAT,
437
 * DATE_FORMAT_SHORT,
438
 * DATE_FORMAT_LONG,
439
 * DATE_TIME_FORMAT_LONG
440
 * @param string $language (optional) Language id
441
 *                         If it is omitted, the current interface language is assumed
442
 *
443
 * @return string returns the formatted date
444
 *
445
 * @see http://php.net/manual/en/function.strftime.php
446
 */
447
function api_format_date($time, $format = null, $language = null)
448
{
449
    if (empty($time)) {
450
        return '';
451
    }
452
453
    $system_timezone = date_default_timezone_get();
454
    date_default_timezone_set(api_get_timezone());
455
456
    if (is_string($time)) {
457
        $time = strtotime($time);
458
    }
459
460
    if (is_null($format)) {
461
        $format = DATE_TIME_FORMAT_LONG;
462
    }
463
464
    $datetype = null;
465
    $timetype = null;
466
467
    if (is_int($format)) {
468
        switch ($format) {
469
            case DATE_FORMAT_ONLY_DAYNAME:
470
                $date_format = get_lang('dateFormatOnlyDayName', '', $language);
471
472
                $datetype = IntlDateFormatter::SHORT;
473
                $timetype = IntlDateFormatter::NONE;
474
475
                break;
476
            case DATE_FORMAT_NUMBER_NO_YEAR:
477
                $date_format = get_lang('dateFormatShortNumberNoYear', '', $language);
478
479
                $datetype = IntlDateFormatter::SHORT;
480
                $timetype = IntlDateFormatter::NONE;
481
482
                break;
483
            case DATE_FORMAT_NUMBER:
484
                $date_format = get_lang('dateFormatShortNumber', '', $language);
485
486
                $datetype = IntlDateFormatter::SHORT;
487
                $timetype = IntlDateFormatter::NONE;
488
489
                break;
490
            case TIME_NO_SEC_FORMAT:
491
                $date_format = get_lang('timeNoSecFormat', '', $language);
492
493
                $datetype = IntlDateFormatter::NONE;
494
                $timetype = IntlDateFormatter::SHORT;
495
496
                break;
497
            case DATE_FORMAT_SHORT:
498
                $date_format = get_lang('dateFormatShort', '', $language);
499
500
                $datetype = IntlDateFormatter::LONG;
501
                $timetype = IntlDateFormatter::NONE;
502
503
                break;
504
            case DATE_FORMAT_LONG:
505
                $date_format = get_lang('dateFormatLong', '', $language);
506
507
                $datetype = IntlDateFormatter::FULL;
508
                $timetype = IntlDateFormatter::NONE;
509
510
                break;
511
            case DATE_TIME_FORMAT_LONG:
512
                $date_format = get_lang('dateTimeFormatLong', '', $language);
513
514
                $datetype = IntlDateFormatter::FULL;
515
                $timetype = IntlDateFormatter::SHORT;
516
517
                break;
518
            case DATE_FORMAT_LONG_NO_DAY:
519
                $date_format = get_lang('dateFormatLongNoDay', '', $language);
520
521
                $datetype = IntlDateFormatter::FULL;
522
                $timetype = IntlDateFormatter::SHORT;
523
524
                break;
525
            case DATE_TIME_FORMAT_SHORT:
526
                $date_format = get_lang('dateTimeFormatShort', '', $language);
527
528
                $datetype = IntlDateFormatter::FULL;
529
                $timetype = IntlDateFormatter::SHORT;
530
531
                break;
532
            case DATE_TIME_FORMAT_SHORT_TIME_FIRST:
533
                $date_format = get_lang('dateTimeFormatShortTimeFirst', '', $language);
534
535
                $datetype = IntlDateFormatter::FULL;
536
                $timetype = IntlDateFormatter::SHORT;
537
538
                break;
539
            case DATE_TIME_FORMAT_LONG_24H:
540
                $date_format = get_lang('dateTimeFormatLong24H', '', $language);
541
542
                $datetype = IntlDateFormatter::FULL;
543
                $timetype = IntlDateFormatter::SHORT;
544
545
                break;
546
            default:
547
                $date_format = get_lang('dateTimeFormatLong', '', $language);
548
549
                $datetype = IntlDateFormatter::FULL;
550
                $timetype = IntlDateFormatter::SHORT;
551
        }
552
    }
553
554
    // Use ICU
555
    if (is_null($language)) {
556
        $language = api_get_language_isocode();
557
    }
558
    $date_formatter = new IntlDateFormatter($language, $datetype, $timetype, date_default_timezone_get());
559
    //$date_formatter->setPattern($date_format);
560
    $formatted_date = api_to_system_encoding($date_formatter->format($time), 'UTF-8');
561
562
    date_default_timezone_set($system_timezone);
563
564
    return $formatted_date;
565
}
566
567
/**
568
 * Returns the difference between the current date (date(now)) with the parameter
569
 * $date in a string format like "2 days ago, 1 hour ago".
570
 * You can use it like this:
571
 * Display::dateToStringAgoAndLongDate($dateInUtc);.
572
 *
573
 * @param string $date                 Result of a date function in this format -> date('Y-m-d H:i:s', time());
574
 * @param string $timeZone
575
 * @param bool   $returnDateDifference
576
 *
577
 * @return string
578
 *
579
 * @author Julio Montoya
580
 */
581
function date_to_str_ago($date, $timeZone = 'UTC', $returnDateDifference = false)
582
{
583
    if ($date === '0000-00-00 00:00:00') {
584
        return '';
585
    }
586
587
    $getOldTimezone = api_get_timezone();
588
    $isoCode = api_get_language_isocode();
589
    if ($isoCode == 'pt') {
590
        $isoCode = 'pt-BR';
591
    }
592
    $checkFile = api_get_path(SYS_PATH).'vendor/jimmiw/php-time-ago/translations/'.$isoCode.'.php';
593
    if (!file_exists($checkFile)) {
594
        $isoCode = 'en';
595
    }
596
    $timeAgo = new TimeAgo($timeZone, $isoCode);
597
    $value = $timeAgo->inWords($date);
598
599
    date_default_timezone_set($getOldTimezone);
600
601
    if ($returnDateDifference) {
602
        $value = $timeAgo->dateDifference($date);
603
    }
604
605
    return $value;
606
}
607
608
/**
609
 * Converts a date to the right timezone and localizes it in the format given as an argument.
610
 *
611
 * @param mixed The time to be converted
612
 * @param mixed Format to be used (TIME_NO_SEC_FORMAT, DATE_FORMAT_SHORT, DATE_FORMAT_LONG, DATE_TIME_FORMAT_LONG)
613
 * @param string Timezone to be converted from. If null, UTC will be assumed.
614
 *
615
 * @return string Converted and localized date
616
 *
617
 * @author Guillaume Viguier <[email protected]>
618
 */
619
function api_convert_and_format_date($time = null, $format = null, $from_timezone = null)
620
{
621
    // First, convert the datetime to the right timezone
622
    $time = api_get_local_time($time, null, $from_timezone, true);
623
    // Second, localize the date
624
    return api_format_date($time, $format);
625
}
626
627
/**
628
 * Returns an array of translated week days in short names.
629
 *
630
 * @param string $language (optional) Language id. If it is omitted, the current interface language is assumed.
631
 *
632
 * @return string Returns an array of week days (short names).
633
 *                Example: api_get_week_days_short('english') means array('Sun', 'Mon', ... 'Sat').
634
 *                Note: For all languges returned days are in the English order.
635
 */
636
function api_get_week_days_short($language = null)
637
{
638
    $days = &_api_get_day_month_names($language);
639
640
    return $days['days_short'];
641
}
642
643
/**
644
 * Returns an array of translated week days.
645
 *
646
 * @param string $language (optional) Language id. If it is omitted,
647
 *                         the current interface language is assumed.
648
 *
649
 * @return string Returns an array of week days.
650
 *                Example: api_get_week_days_long('english') means array('Sunday, 'Monday', ... 'Saturday').
651
 *                Note: For all languges returned days are in the English order.
652
 */
653
function api_get_week_days_long($language = null)
654
{
655
    $days = &_api_get_day_month_names($language);
656
657
    return $days['days_long'];
658
}
659
660
/**
661
 * Returns an array of translated months in short names.
662
 *
663
 * @param string $language (optional)    Language id.
664
 *                         If it is omitted, the current interface language is assumed.
665
 *
666
 * @return string Returns an array of months (short names).
667
 *                Example: api_get_months_short('english') means array('Jan', 'Feb', ... 'Dec').
668
 */
669
function api_get_months_short($language = null)
670
{
671
    $months = &_api_get_day_month_names($language);
672
673
    return $months['months_short'];
674
}
675
676
/**
677
 * Returns an array of translated months.
678
 *
679
 * @param string $language (optional)    Language id.
680
 *                         If it is omitted, the current interface language is assumed.
681
 *
682
 * @return string Returns an array of months.
683
 *                Example: api_get_months_long('english') means array('January, 'February' ... 'December').
684
 */
685
function api_get_months_long($language = null)
686
{
687
    $months = &_api_get_day_month_names($language);
688
689
    return $months['months_long'];
690
}
691
692
/**
693
 * Name order conventions.
694
 */
695
696
/**
697
 * Builds a person (full) name depending on the convention for a given language.
698
 *
699
 * @param string     $first_name the first name of the person
700
 * @param string     $last_name  the last name of the person
701
 * @param string     $title      the title of the person
702
 * @param int|string $format     (optional) The person name format.
703
 *                               It may be a pattern-string (for example '%t %l, %f' or '%T %F %L', ...) or
704
 *                               some of the constants
705
 *                               PERSON_NAME_COMMON_CONVENTION (default),
706
 *                               PERSON_NAME_WESTERN_ORDER,
707
 *                               PERSON_NAME_EASTERN_ORDER,
708
 *                               PERSON_NAME_LIBRARY_ORDER.
709
 * @param string     $language   (optional)
710
 *                               The language id. If it is omitted, the current interface language is assumed.
711
 *                               This parameter has meaning with the format PERSON_NAME_COMMON_CONVENTION only.
712
 * @param string     $username
713
 *
714
 * @return string The result is sort of full name of the person.
715
 *                Sample results:
716
 *                Peter Ustinoff or Dr. Peter Ustinoff     - the Western order
717
 *                Ustinoff Peter or Dr. Ustinoff Peter     - the Eastern order
718
 *                Ustinoff, Peter or - Dr. Ustinoff, Peter - the library order
719
 *                Note: See the file main/inc/lib/internationalization_database/name_order_conventions.php
720
 *                where you can check the convention for your language.
721
 *
722
 * @author Carlos Vargas <[email protected]> - initial implementation.
723
 * @author Ivan Tcholakov
724
 */
725
function api_get_person_name(
726
    $first_name,
727
    $last_name,
728
    $title = null,
729
    $format = null,
730
    $language = null,
731
    $username = null
732
) {
733
    static $valid = [];
734
    if (empty($format)) {
735
        $format = PERSON_NAME_COMMON_CONVENTION;
736
    }
737
    // We check if the language is supported, otherwise we check the
738
    // interface language of the parent language of sublanguage
739
    if (empty($language)) {
740
        // Do not set $setParentLanguageName because this function is called before
741
        // the main language is loaded in global.inc.php
742
        $language = api_get_interface_language(false, true, false);
743
    }
744
745
    if (!isset($valid[$format][$language])) {
746
        if (is_int($format)) {
747
            switch ($format) {
748
                case PERSON_NAME_COMMON_CONVENTION:
749
                    $valid[$format][$language] = _api_get_person_name_convention($language, 'format');
750
                    $usernameOrderFromDatabase = api_get_setting('user_name_order');
751
                    if (isset($usernameOrderFromDatabase) && !empty($usernameOrderFromDatabase)) {
752
                        $valid[$format][$language] = $usernameOrderFromDatabase;
753
                    }
754
                    break;
755
                case PERSON_NAME_WESTERN_ORDER:
756
                    $valid[$format][$language] = '%t %f %l';
757
                    break;
758
                case PERSON_NAME_EASTERN_ORDER:
759
                    $valid[$format][$language] = '%t %l %f';
760
                    break;
761
                case PERSON_NAME_LIBRARY_ORDER:
762
                    $valid[$format][$language] = '%t %l, %f';
763
                    break;
764
                default:
765
                    $valid[$format][$language] = '%t %f %l';
766
                    break;
767
            }
768
        } else {
769
            $valid[$format][$language] = _api_validate_person_name_format($format);
770
        }
771
    }
772
773
    $format = $valid[$format][$language];
774
775
    $keywords = [
776
        '%firstname',
777
        '%f',
778
        '%F',
779
        '%lastname',
780
        '%l',
781
        '%L',
782
        '%title',
783
        '%t',
784
        '%T',
785
        '%username',
786
        '%u',
787
        '%U',
788
    ];
789
790
    $values = [
791
        $first_name,
792
        $first_name,
793
        api_strtoupper($first_name),
794
        $last_name,
795
        $last_name,
796
        api_strtoupper($last_name),
797
        $title,
798
        $title,
799
        api_strtoupper($title),
800
        $username,
801
        $username,
802
        api_strtoupper($username),
803
    ];
804
    $person_name = str_replace($keywords, $values, $format);
805
806
    return _api_clean_person_name($person_name);
807
}
808
809
/**
810
 * Checks whether a given format represents person name in Western order (for which first name is first).
811
 *
812
 * @param int|string $format   (optional)    The person name format.
813
 *                             It may be a pattern-string (for example '%t. %l, %f') or some of the constants
814
 *                             PERSON_NAME_COMMON_CONVENTION (default),
815
 *                             PERSON_NAME_WESTERN_ORDER,
816
 *                             PERSON_NAME_EASTERN_ORDER,
817
 *                             PERSON_NAME_LIBRARY_ORDER.
818
 * @param string     $language (optional) The language id. If it is omitted,
819
 *                             the current interface language is assumed. This parameter has meaning with the
820
 *                             format PERSON_NAME_COMMON_CONVENTION only.
821
 *
822
 * @return bool The result TRUE means that the order is first_name last_name,
823
 *              FALSE means last_name first_name.
824
 *              Note: You may use this function for determining the order of the fields or
825
 *              columns "First name" and "Last name" in forms, tables and reports.
826
 *
827
 * @author Ivan Tcholakov
828
 */
829
function api_is_western_name_order($format = null, $language = null)
830
{
831
    static $order = [];
832
    if (empty($format)) {
833
        $format = PERSON_NAME_COMMON_CONVENTION;
834
    }
835
836
    if (empty($language)) {
837
        $language = api_get_interface_language(false, true);
838
    }
839
    if (!isset($order[$format][$language])) {
840
        $test_name = api_get_person_name('%f', '%l', '%t', $format, $language);
841
        $order[$format][$language] = stripos($test_name, '%f') <= stripos($test_name, '%l');
842
    }
843
844
    return $order[$format][$language];
845
}
846
847
/**
848
 * Returns a directive for sorting person names depending on a given language
849
 * and based on the options in the internationalization "database".
850
 *
851
 * @param string $language (optional) The input language.
852
 *                         If it is omitted, the current interface language is assumed.
853
 *
854
 * @return bool Returns boolean value. TRUE means ORDER BY first_name, last_name
855
 *              FALSE means ORDER BY last_name, first_name.
856
 *              Note: You may use this function:
857
 *              2. for constructing the ORDER clause of SQL queries, related to first_name and last_name;
858
 *              3. for adjusting php-implemented sorting in tables and reports.
859
 *
860
 * @author Ivan Tcholakov
861
 */
862
function api_sort_by_first_name($language = null)
863
{
864
    static $sort_by_first_name = [];
865
866
    if (empty($language)) {
867
        $language = api_get_interface_language(false, true);
868
    }
869
    if (!isset($sort_by_first_name[$language])) {
870
        $sort_by_first_name[$language] = _api_get_person_name_convention($language, 'sort_by');
871
    }
872
873
    return $sort_by_first_name[$language];
874
}
875
876
/**
877
 * Multibyte string conversion functions.
878
 */
879
880
/**
881
 * Converts character encoding of a given string.
882
 *
883
 * @param string $string        the string being converted
884
 * @param string $to_encoding   the encoding that $string is being converted to
885
 * @param string $from_encoding (optional)    The encoding that $string is being converted from.
886
 *                              If it is omitted, the platform character set is assumed.
887
 *
888
 * @return string Returns the converted string.
889
 *                This function is aimed at replacing the function mb_convert_encoding() for human-language strings.
890
 *
891
 * @see http://php.net/manual/en/function.mb-convert-encoding
892
 */
893
function api_convert_encoding($string, $to_encoding, $from_encoding = 'UTF-8')
894
{
895
    if (strtoupper($to_encoding) === strtoupper($from_encoding)) {
896
        return $string;
897
    }
898
899
    return mb_convert_encoding($string, $to_encoding, $from_encoding);
900
}
901
902
/**
903
 * Converts a given string into UTF-8 encoded string.
904
 *
905
 * @param string $string        the string being converted
906
 * @param string $from_encoding (optional) The encoding that $string is being converted from.
907
 *                              If it is omitted, the platform character set is assumed.
908
 *
909
 * @return string Returns the converted string.
910
 *                This function is aimed at replacing the function utf8_encode() for human-language strings.
911
 *
912
 * @see http://php.net/manual/en/function.utf8-encode
913
 */
914
function api_utf8_encode($string, $from_encoding = 'UTF-8')
915
{
916
    return mb_convert_encoding($string, 'UTF-8', $from_encoding);
917
}
918
919
/**
920
 * Converts a given string from UTF-8 encoding to a specified encoding.
921
 *
922
 * @param string $string      the string being converted
923
 * @param string $to_encoding (optional)    The encoding that $string is being converted to.
924
 *                            If it is omitted, the platform character set is assumed.
925
 *
926
 * @return string Returns the converted string.
927
 *                This function is aimed at replacing the function utf8_decode() for human-language strings.
928
 *
929
 * @see http://php.net/manual/en/function.utf8-decode
930
 */
931
function api_utf8_decode($string, $to_encoding = null)
932
{
933
    return mb_convert_encoding($string, $to_encoding, 'UTF-8');
934
}
935
936
/**
937
 * Converts a given string into the system encoding (or platform character set).
938
 * When $from encoding is omitted on UTF-8 platforms then language dependent encoding
939
 * is guessed/assumed. On non-UTF-8 platforms omitted $from encoding is assumed as UTF-8.
940
 * When the parameter $check_utf8_validity is true the function checks string's
941
 * UTF-8 validity and decides whether to try to convert it or not.
942
 * This function is useful for problem detection or making workarounds.
943
 *
944
 * @param string $string              the string being converted
945
 * @param string $from_encoding       (optional) The encoding that $string is being converted from.
946
 *                                    It is guessed when it is omitted.
947
 * @param bool   $check_utf8_validity (optional)    A flag for UTF-8 validity check as condition for making conversion
948
 *
949
 * @return string returns the converted string
950
 */
951
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

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

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

1059
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

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

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

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

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

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

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

1230
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...
1231
{
1232
    return Utf8::strpos($haystack, $needle, $offset);
1233
}
1234
1235
/**
1236
 * Finds the last occurrence of a character in a string.
1237
 *
1238
 * @param string $haystack      the string from which to get the last occurrence
1239
 * @param mixed  $needle        the string which first character is to be found
1240
 * @param bool   $before_needle (optional) Determines which portion of $haystack this function returns. The default value is FALSE.
1241
 * @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.
1242
 *
1243
 * @return mixed Returns the portion of $haystack, or FALSE if the first character from $needle is not found.
1244
 *               Notes:
1245
 *               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.
1246
 *               If $before_needle is set to TRUE, the function returns all of $haystack from the beginning to the first occurrence.
1247
 *               If $before_needle is set to FALSE, the function returns all of $haystack from the first occurrence to the end.
1248
 *               This function is aimed at replacing the functions strrchr() and mb_strrchr() for human-language strings.
1249
 *
1250
 * @see http://php.net/manual/en/function.strrchr
1251
 * @see http://php.net/manual/en/function.mb-strrchr
1252
 */
1253
function api_strrchr($haystack, $needle, $before_needle = false, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $before_needle is not used and could be removed. ( Ignorable by Annotation )

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

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

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

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

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

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

1269
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...
1270
{
1271
    return Utf8::strrev($string);
1272
}
1273
1274
/**
1275
 * Finds the position of last occurrence (case insensitive) of a string in a string.
1276
 *
1277
 * @param string $haystack the string from which to get the position of the last occurrence
1278
 * @param string $needle   the string to be found
1279
 * @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.
1280
 * @param string $encoding (optional) The used internally by this function character encoding. If it is omitted, the platform character set will be used by default.
1281
 *
1282
 * @return mixed Returns the numeric position of the first occurrence (case insensitive) of $needle in the $haystack, or FALSE if $needle is not found.
1283
 *               Note: The first character's position is 0, the second character position is 1, and so on.
1284
 *               This function is aimed at replacing the functions strripos() and mb_strripos() for human-language strings.
1285
 *
1286
 * @see http://php.net/manual/en/function.strripos
1287
 * @see http://php.net/manual/en/function.mb-strripos
1288
 */
1289
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

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

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

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

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

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

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

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

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

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

1638
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

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

1658
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

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

1680
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

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

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

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

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