Proyectos de Subversion Moodle

Rev

Rev 11 | Rev 1327 | Ir a la última revisión | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 11 Rev 1326
Línea 378... Línea 378...
378
/** Get remote addr constant */
378
/** Get remote addr constant */
379
define('GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR', '2');
379
define('GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR', '2');
380
/**
380
/**
381
 * GETREMOTEADDR_SKIP_DEFAULT defines the default behavior remote IP address validation.
381
 * GETREMOTEADDR_SKIP_DEFAULT defines the default behavior remote IP address validation.
382
 */
382
 */
383
define('GETREMOTEADDR_SKIP_DEFAULT', GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR|GETREMOTEADDR_SKIP_HTTP_CLIENT_IP);
383
define('GETREMOTEADDR_SKIP_DEFAULT', GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR | GETREMOTEADDR_SKIP_HTTP_CLIENT_IP);
Línea 384... Línea 384...
384
 
384
 
385
// Blog access level constant declaration.
385
// Blog access level constant declaration.
386
define ('BLOG_USER_LEVEL', 1);
386
define('BLOG_USER_LEVEL', 1);
387
define ('BLOG_GROUP_LEVEL', 2);
387
define('BLOG_GROUP_LEVEL', 2);
388
define ('BLOG_COURSE_LEVEL', 3);
388
define('BLOG_COURSE_LEVEL', 3);
389
define ('BLOG_SITE_LEVEL', 4);
389
define('BLOG_SITE_LEVEL', 4);
Línea 390... Línea 390...
390
define ('BLOG_GLOBAL_LEVEL', 5);
390
define('BLOG_GLOBAL_LEVEL', 5);
391
 
391
 
392
 
392
 
Línea 399... Línea 399...
399
 * @todo define(TAG_MAX_LENGTH) this is not correct, varchar(255) are 255 unicode chars ;-)
399
 * @todo define(TAG_MAX_LENGTH) this is not correct, varchar(255) are 255 unicode chars ;-)
400
 */
400
 */
401
define('TAG_MAX_LENGTH', 50);
401
define('TAG_MAX_LENGTH', 50);
Línea 402... Línea 402...
402
 
402
 
403
// Password policy constants.
403
// Password policy constants.
404
define ('PASSWORD_LOWER', 'abcdefghijklmnopqrstuvwxyz');
404
define('PASSWORD_LOWER', 'abcdefghijklmnopqrstuvwxyz');
405
define ('PASSWORD_UPPER', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
405
define('PASSWORD_UPPER', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
406
define ('PASSWORD_DIGITS', '0123456789');
406
define('PASSWORD_DIGITS', '0123456789');
Línea 407... Línea 407...
407
define ('PASSWORD_NONALPHANUM', '.,;:!?_-+/*@#&$');
407
define('PASSWORD_NONALPHANUM', '.,;:!?_-+/*@#&$');
408
 
408
 
409
/**
409
/**
410
 * Required password pepper entropy.
410
 * Required password pepper entropy.
Línea 411... Línea 411...
411
 */
411
 */
412
define ('PEPPER_ENTROPY', 112);
412
define('PEPPER_ENTROPY', 112);
Línea 413... Línea 413...
413
 
413
 
Línea 495... Línea 495...
495
define('MOD_PURPOSE_OTHER', 'other');
495
define('MOD_PURPOSE_OTHER', 'other');
496
/**
496
/**
497
 * Module purpose interface
497
 * Module purpose interface
498
 * @deprecated since Moodle 4.4
498
 * @deprecated since Moodle 4.4
499
 * @todo MDL-80701 Remove in Moodle 4.8
499
 * @todo MDL-80701 Remove in Moodle 4.8
500
*/
500
 */
501
define('MOD_PURPOSE_INTERFACE', 'interface');
501
define('MOD_PURPOSE_INTERFACE', 'interface');
Línea 502... Línea 502...
502
 
502
 
503
/**
503
/**
504
 * Security token used for allowing access
504
 * Security token used for allowing access
Línea 640... Línea 640...
640
 * @param string $parname the name of the page parameter we want
640
 * @param string $parname the name of the page parameter we want
641
 * @param string $type expected type of parameter
641
 * @param string $type expected type of parameter
642
 * @return mixed
642
 * @return mixed
643
 * @throws coding_exception
643
 * @throws coding_exception
644
 */
644
 */
645
function required_param($parname, $type) {
645
function required_param($parname, $type)
-
 
646
{
646
    return \core\param::from_type($type)->required_param($parname);
647
    return \core\param::from_type($type)->required_param($parname);
647
}
648
}
Línea 648... Línea 649...
648
 
649
 
649
/**
650
/**
Línea 661... Línea 662...
661
 * @param string $parname the name of the page parameter we want
662
 * @param string $parname the name of the page parameter we want
662
 * @param string $type expected type of parameter
663
 * @param string $type expected type of parameter
663
 * @return array
664
 * @return array
664
 * @throws coding_exception
665
 * @throws coding_exception
665
 */
666
 */
666
function required_param_array($parname, $type) {
667
function required_param_array($parname, $type)
-
 
668
{
667
    return \core\param::from_type($type)->required_param_array($parname);
669
    return \core\param::from_type($type)->required_param_array($parname);
668
}
670
}
Línea 669... Línea 671...
669
 
671
 
670
/**
672
/**
Línea 682... Línea 684...
682
 * @param mixed  $default the default value to return if nothing is found
684
 * @param mixed  $default the default value to return if nothing is found
683
 * @param string $type expected type of parameter
685
 * @param string $type expected type of parameter
684
 * @return mixed
686
 * @return mixed
685
 * @throws coding_exception
687
 * @throws coding_exception
686
 */
688
 */
687
function optional_param($parname, $default, $type) {
689
function optional_param($parname, $default, $type)
-
 
690
{
688
    return \core\param::from_type($type)->optional_param(
691
    return \core\param::from_type($type)->optional_param(
689
        paramname: $parname,
692
        paramname: $parname,
690
        default: $default,
693
        default: $default,
691
    );
694
    );
692
}
695
}
Línea 706... Línea 709...
706
 * @param mixed $default the default value to return if nothing is found
709
 * @param mixed $default the default value to return if nothing is found
707
 * @param string $type expected type of parameter
710
 * @param string $type expected type of parameter
708
 * @return array
711
 * @return array
709
 * @throws coding_exception
712
 * @throws coding_exception
710
 */
713
 */
711
function optional_param_array($parname, $default, $type) {
714
function optional_param_array($parname, $default, $type)
-
 
715
{
712
    return \core\param::from_type($type)->optional_param_array(
716
    return \core\param::from_type($type)->optional_param_array(
713
        paramname: $parname,
717
        paramname: $parname,
714
        default: $default,
718
        default: $default,
715
    );
719
    );
716
}
720
}
Línea 727... Línea 731...
727
 * @param bool $allownull are nulls valid value?
731
 * @param bool $allownull are nulls valid value?
728
 * @param string $debuginfo optional debug information
732
 * @param string $debuginfo optional debug information
729
 * @return mixed the $param value converted to PHP type
733
 * @return mixed the $param value converted to PHP type
730
 * @throws invalid_parameter_exception if $param is not of given type
734
 * @throws invalid_parameter_exception if $param is not of given type
731
 */
735
 */
732
function validate_param($param, $type, $allownull = NULL_NOT_ALLOWED, $debuginfo = '') {
736
function validate_param($param, $type, $allownull = NULL_NOT_ALLOWED, $debuginfo = '')
-
 
737
{
733
    return \core\param::from_type($type)->validate_param(
738
    return \core\param::from_type($type)->validate_param(
734
        param: $param,
739
        param: $param,
735
        allownull: $allownull,
740
        allownull: $allownull,
736
        debuginfo: $debuginfo,
741
        debuginfo: $debuginfo,
737
    );
742
    );
Línea 748... Línea 753...
748
 * @param string $type expected format of param after cleaning.
753
 * @param string $type expected format of param after cleaning.
749
 * @param bool $recursive clean recursive arrays
754
 * @param bool $recursive clean recursive arrays
750
 * @return array
755
 * @return array
751
 * @throws coding_exception
756
 * @throws coding_exception
752
 */
757
 */
753
function clean_param_array(?array $param, $type, $recursive = false) {
758
function clean_param_array(?array $param, $type, $recursive = false)
-
 
759
{
754
    return \core\param::from_type($type)->clean_param_array(
760
    return \core\param::from_type($type)->clean_param_array(
755
        param: $param,
761
        param: $param,
756
        recursive: $recursive,
762
        recursive: $recursive,
757
    );
763
    );
758
}
764
}
Línea 769... Línea 775...
769
 * @param mixed $param the variable we are cleaning
775
 * @param mixed $param the variable we are cleaning
770
 * @param string $type expected format of param after cleaning.
776
 * @param string $type expected format of param after cleaning.
771
 * @return mixed
777
 * @return mixed
772
 * @throws coding_exception
778
 * @throws coding_exception
773
 */
779
 */
774
function clean_param($param, $type) {
780
function clean_param($param, $type)
-
 
781
{
775
    return \core\param::from_type($type)->clean($param);
782
    return \core\param::from_type($type)->clean($param);
776
}
783
}
Línea 777... Línea 784...
777
 
784
 
778
/**
785
/**
Línea 788... Línea 795...
788
 * This function tries to best guess which parameters can contain localised strings.
795
 * This function tries to best guess which parameters can contain localised strings.
789
 *
796
 *
790
 * @param string $paramtype Constant PARAM_*.
797
 * @param string $paramtype Constant PARAM_*.
791
 * @return bool
798
 * @return bool
792
 */
799
 */
793
function is_rtl_compatible($paramtype) {
800
function is_rtl_compatible($paramtype)
-
 
801
{
794
    return $paramtype == PARAM_TEXT || $paramtype == PARAM_NOTAGS;
802
    return $paramtype == PARAM_TEXT || $paramtype == PARAM_NOTAGS;
795
}
803
}
Línea 796... Línea 804...
796
 
804
 
797
/**
805
/**
Línea 800... Línea 808...
800
 * Note: this function is not intended for full objects with methods and private properties.
808
 * Note: this function is not intended for full objects with methods and private properties.
801
 *
809
 *
802
 * @param mixed $value
810
 * @param mixed $value
803
 * @return mixed with proper utf-8 encoding
811
 * @return mixed with proper utf-8 encoding
804
 */
812
 */
805
function fix_utf8($value) {
813
function fix_utf8($value)
-
 
814
{
806
    if (is_null($value) or $value === '') {
815
    if (is_null($value) or $value === '') {
807
        return $value;
816
        return $value;
808
 
-
 
809
    } else if (is_string($value)) {
817
    } else if (is_string($value)) {
810
        if ((string)(int)$value === $value) {
818
        if ((string)(int)$value === $value) {
811
            // Shortcut.
819
            // Shortcut.
812
            return $value;
820
            return $value;
813
        }
821
        }
Línea 816... Línea 824...
816
        $value = str_replace(["\0", "\xef\xbf\xbe", "\xef\xbf\xbf"], '', $value);
824
        $value = str_replace(["\0", "\xef\xbf\xbe", "\xef\xbf\xbf"], '', $value);
Línea 817... Línea 825...
817
 
825
 
818
        // Note: this duplicates min_fix_utf8() intentionally.
826
        // Note: this duplicates min_fix_utf8() intentionally.
819
        static $buggyiconv = null;
827
        static $buggyiconv = null;
820
        if ($buggyiconv === null) {
828
        if ($buggyiconv === null) {
821
            $buggyiconv = (!function_exists('iconv') or @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
829
            $buggyiconv = (!function_exists('iconv') or @iconv('UTF-8', 'UTF-8//IGNORE', '100' . chr(130) . '€') !== '100€');
Línea 822... Línea 830...
822
        }
830
        }
823
 
831
 
824
        if ($buggyiconv) {
832
        if ($buggyiconv) {
825
            if (function_exists('mb_convert_encoding')) {
833
            if (function_exists('mb_convert_encoding')) {
826
                $subst = mb_substitute_character();
834
                $subst = mb_substitute_character();
827
                mb_substitute_character('none');
835
                mb_substitute_character('none');
828
                $result = mb_convert_encoding($value, 'utf-8', 'utf-8');
-
 
829
                mb_substitute_character($subst);
836
                $result = mb_convert_encoding($value, 'utf-8', 'utf-8');
830
 
837
                mb_substitute_character($subst);
831
            } else {
838
            } else {
832
                // Warn admins on admin/index.php page.
839
                // Warn admins on admin/index.php page.
833
                $result = $value;
-
 
834
            }
840
                $result = $value;
835
 
841
            }
836
        } else {
842
        } else {
Línea 837... Línea 843...
837
            $result = @iconv('UTF-8', 'UTF-8//IGNORE', $value);
843
            $result = @iconv('UTF-8', 'UTF-8//IGNORE', $value);
838
        }
-
 
839
 
844
        }
840
        return $result;
845
 
841
 
846
        return $result;
842
    } else if (is_array($value)) {
847
    } else if (is_array($value)) {
843
        foreach ($value as $k => $v) {
848
        foreach ($value as $k => $v) {
844
            $value[$k] = fix_utf8($v);
-
 
845
        }
849
            $value[$k] = fix_utf8($v);
846
        return $value;
850
        }
847
 
851
        return $value;
848
    } else if (is_object($value)) {
852
    } else if (is_object($value)) {
849
        // Do not modify original.
853
        // Do not modify original.
850
        $value = clone($value);
854
        $value = clone ($value);
851
        foreach ($value as $k => $v) {
855
        foreach ($value as $k => $v) {
852
            $value->$k = fix_utf8($v);
-
 
853
        }
856
            $value->$k = fix_utf8($v);
854
        return $value;
857
        }
855
 
858
        return $value;
856
    } else {
859
    } else {
857
        // This is some other type, no utf-8 here.
860
        // This is some other type, no utf-8 here.
Línea 863... Línea 866...
863
 * Return true if given value is integer or string with integer value
866
 * Return true if given value is integer or string with integer value
864
 *
867
 *
865
 * @param mixed $value String or Int
868
 * @param mixed $value String or Int
866
 * @return bool true if number, false if not
869
 * @return bool true if number, false if not
867
 */
870
 */
868
function is_number($value) {
871
function is_number($value)
-
 
872
{
869
    if (is_int($value)) {
873
    if (is_int($value)) {
870
        return true;
874
        return true;
871
    } else if (is_string($value)) {
875
    } else if (is_string($value)) {
872
        return ((string)(int)$value) === $value;
876
        return ((string)(int)$value) === $value;
873
    } else {
877
    } else {
Línea 879... Línea 883...
879
 * Returns host part from url.
883
 * Returns host part from url.
880
 *
884
 *
881
 * @param string $url full url
885
 * @param string $url full url
882
 * @return string host, null if not found
886
 * @return string host, null if not found
883
 */
887
 */
884
function get_host_from_url($url) {
888
function get_host_from_url($url)
-
 
889
{
885
    preg_match('|^[a-z]+://([a-zA-Z0-9-.]+)|i', $url, $matches);
890
    preg_match('|^[a-z]+://([a-zA-Z0-9-.]+)|i', $url, $matches);
886
    if ($matches) {
891
    if ($matches) {
887
        return $matches[1];
892
        return $matches[1];
888
    }
893
    }
889
    return null;
894
    return null;
Línea 898... Línea 903...
898
 *
903
 *
899
 * @param string $string a string containing HTML.
904
 * @param string $string a string containing HTML.
900
 * @return boolean does the string contain any actual content - that is text,
905
 * @return boolean does the string contain any actual content - that is text,
901
 * images, objects, etc.
906
 * images, objects, etc.
902
 */
907
 */
903
function html_is_blank($string) {
908
function html_is_blank($string)
-
 
909
{
904
    return trim(strip_tags((string)$string, '<img><object><applet><input><select><textarea><hr>')) == '';
910
    return trim(strip_tags((string)$string, '<img><object><applet><input><select><textarea><hr>')) == '';
905
}
911
}
Línea 906... Línea 912...
906
 
912
 
907
/**
913
/**
Línea 921... Línea 927...
921
 * @param string|int|bool|null $value the value to set (without magic quotes),
927
 * @param string|int|bool|null $value the value to set (without magic quotes),
922
 *               null to unset the value
928
 *               null to unset the value
923
 * @param string $plugin (optional) the plugin scope, default null
929
 * @param string $plugin (optional) the plugin scope, default null
924
 * @return bool true or exception
930
 * @return bool true or exception
925
 */
931
 */
926
function set_config($name, $value, $plugin = null) {
932
function set_config($name, $value, $plugin = null)
-
 
933
{
927
    global $CFG, $DB;
934
    global $CFG, $DB;
Línea 928... Línea 935...
928
 
935
 
929
    // Redirect to appropriate handler when value is null.
936
    // Redirect to appropriate handler when value is null.
930
    if ($value === null) {
937
    if ($value === null) {
Línea 1004... Línea 1011...
1004
 * @param string $plugin full component name
1011
 * @param string $plugin full component name
1005
 * @param string $name default null
1012
 * @param string $name default null
1006
 * @return mixed hash-like object or single value, return false no config found
1013
 * @return mixed hash-like object or single value, return false no config found
1007
 * @throws dml_exception
1014
 * @throws dml_exception
1008
 */
1015
 */
1009
function get_config($plugin, $name = null) {
1016
function get_config($plugin, $name = null)
-
 
1017
{
1010
    global $CFG, $DB;
1018
    global $CFG, $DB;
Línea 1011... Línea 1019...
1011
 
1019
 
1012
    if ($plugin === 'moodle' || $plugin === 'core' || empty($plugin)) {
1020
    if ($plugin === 'moodle' || $plugin === 'core' || empty($plugin)) {
1013
        $forced =& $CFG->config_php_settings;
1021
        $forced = &$CFG->config_php_settings;
1014
        $iscore = true;
1022
        $iscore = true;
1015
        $plugin = 'core';
1023
        $plugin = 'core';
1016
    } else {
1024
    } else {
1017
        if (array_key_exists($plugin, $CFG->forced_plugin_settings)) {
1025
        if (array_key_exists($plugin, $CFG->forced_plugin_settings)) {
1018
            $forced =& $CFG->forced_plugin_settings[$plugin];
1026
            $forced = &$CFG->forced_plugin_settings[$plugin];
1019
        } else {
1027
        } else {
1020
            $forced = array();
1028
            $forced = array();
1021
        }
1029
        }
1022
        $iscore = false;
1030
        $iscore = false;
Línea 1086... Línea 1094...
1086
 *
1094
 *
1087
 * @param string $name the key to set
1095
 * @param string $name the key to set
1088
 * @param string $plugin (optional) the plugin scope
1096
 * @param string $plugin (optional) the plugin scope
1089
 * @return boolean whether the operation succeeded.
1097
 * @return boolean whether the operation succeeded.
1090
 */
1098
 */
1091
function unset_config($name, $plugin=null) {
1099
function unset_config($name, $plugin = null)
-
 
1100
{
1092
    global $CFG, $DB;
1101
    global $CFG, $DB;
Línea 1093... Línea 1102...
1093
 
1102
 
1094
    if (empty($plugin)) {
1103
    if (empty($plugin)) {
1095
        unset($CFG->$name);
1104
        unset($CFG->$name);
Línea 1109... Línea 1118...
1109
 * NOTE: this function is called from lib/db/upgrade.php
1118
 * NOTE: this function is called from lib/db/upgrade.php
1110
 *
1119
 *
1111
 * @param string $plugin a plugin, for example 'quiz' or 'qtype_multichoice';
1120
 * @param string $plugin a plugin, for example 'quiz' or 'qtype_multichoice';
1112
 * @return boolean whether the operation succeeded.
1121
 * @return boolean whether the operation succeeded.
1113
 */
1122
 */
1114
function unset_all_config_for_plugin($plugin) {
1123
function unset_all_config_for_plugin($plugin)
-
 
1124
{
1115
    global $DB;
1125
    global $DB;
1116
    // Delete from the obvious config_plugins first.
1126
    // Delete from the obvious config_plugins first.
1117
    $DB->delete_records('config_plugins', array('plugin' => $plugin));
1127
    $DB->delete_records('config_plugins', array('plugin' => $plugin));
1118
    // Next delete any suspect settings from config.
1128
    // Next delete any suspect settings from config.
1119
    $like = $DB->sql_like('name', '?', true, true, false, '|');
1129
    $like = $DB->sql_like('name', '?', true, true, false, '|');
1120
    $params = array($DB->sql_like_escape($plugin.'_', '|') . '%');
1130
    $params = array($DB->sql_like_escape($plugin . '_', '|') . '%');
1121
    $DB->delete_records_select('config', $like, $params);
1131
    $DB->delete_records_select('config', $like, $params);
1122
    // Finally clear both the plugin cache and the core cache (suspect settings now removed from core).
1132
    // Finally clear both the plugin cache and the core cache (suspect settings now removed from core).
1123
    cache_helper::invalidate_by_definition('core', 'config', array(), array('core', $plugin));
1133
    cache_helper::invalidate_by_definition('core', 'config', array(), array('core', $plugin));
Línea 1124... Línea 1134...
1124
 
1134
 
Línea 1133... Línea 1143...
1133
 * @param string $value the value of the config setting.
1143
 * @param string $value the value of the config setting.
1134
 * @param string $capability the capability - must match the one passed to the admin_setting_users_with_capability constructor.
1144
 * @param string $capability the capability - must match the one passed to the admin_setting_users_with_capability constructor.
1135
 * @param bool $includeadmins include administrators.
1145
 * @param bool $includeadmins include administrators.
1136
 * @return array of user objects.
1146
 * @return array of user objects.
1137
 */
1147
 */
1138
function get_users_from_config($value, $capability, $includeadmins = true) {
1148
function get_users_from_config($value, $capability, $includeadmins = true)
-
 
1149
{
1139
    if (empty($value) or $value === '$@NONE@$') {
1150
    if (empty($value) or $value === '$@NONE@$') {
1140
        return array();
1151
        return array();
1141
    }
1152
    }
Línea 1142... Línea 1153...
1142
 
1153
 
Línea 1171... Línea 1182...
1171
/**
1182
/**
1172
 * Invalidates browser caches and cached data in temp.
1183
 * Invalidates browser caches and cached data in temp.
1173
 *
1184
 *
1174
 * @return void
1185
 * @return void
1175
 */
1186
 */
1176
function purge_all_caches() {
1187
function purge_all_caches()
-
 
1188
{
1177
    purge_caches();
1189
    purge_caches();
1178
}
1190
}
Línea 1179... Línea 1191...
1179
 
1191
 
1180
/**
1192
/**
Línea 1190... Línea 1202...
1190
 *        'lang'   Purge language string cache?
1202
 *        'lang'   Purge language string cache?
1191
 *        'js'     Purge javascript cache?
1203
 *        'js'     Purge javascript cache?
1192
 *        'filter' Purge text filter cache?
1204
 *        'filter' Purge text filter cache?
1193
 *        'other'  Purge all other caches?
1205
 *        'other'  Purge all other caches?
1194
 */
1206
 */
1195
function purge_caches($options = []) {
1207
function purge_caches($options = [])
-
 
1208
{
1196
    $defaults = array_fill_keys(['muc', 'courses', 'theme', 'lang', 'js', 'template', 'filter', 'other'], false);
1209
    $defaults = array_fill_keys(['muc', 'courses', 'theme', 'lang', 'js', 'template', 'filter', 'other'], false);
1197
    if (empty(array_filter($options))) {
1210
    if (empty(array_filter($options))) {
1198
        $options = array_fill_keys(array_keys($defaults), true); // Set all options to true.
1211
        $options = array_fill_keys(array_keys($defaults), true); // Set all options to true.
1199
    } else {
1212
    } else {
1200
        $options = array_merge($defaults, array_intersect_key($options, $defaults)); // Override defaults with specified options.
1213
        $options = array_merge($defaults, array_intersect_key($options, $defaults)); // Override defaults with specified options.
Línea 1233... Línea 1246...
1233
 * Purge all non-MUC caches not otherwise purged in purge_caches.
1246
 * Purge all non-MUC caches not otherwise purged in purge_caches.
1234
 *
1247
 *
1235
 * IMPORTANT - If you are adding anything here to do with the cache directory you should also have a look at
1248
 * IMPORTANT - If you are adding anything here to do with the cache directory you should also have a look at
1236
 * {@link phpunit_util::reset_dataroot()}
1249
 * {@link phpunit_util::reset_dataroot()}
1237
 */
1250
 */
1238
function purge_other_caches() {
1251
function purge_other_caches()
-
 
1252
{
1239
    global $DB, $CFG;
1253
    global $DB, $CFG;
1240
    if (class_exists('core_plugin_manager')) {
1254
    if (class_exists('core_plugin_manager')) {
1241
        core_plugin_manager::reset_caches();
1255
        core_plugin_manager::reset_caches();
1242
    }
1256
    }
Línea 1250... Línea 1264...
1250
 
1264
 
Línea 1251... Línea 1265...
1251
    $DB->reset_caches();
1265
    $DB->reset_caches();
1252
 
1266
 
1253
    // Purge all other caches: rss, simplepie, etc.
1267
    // Purge all other caches: rss, simplepie, etc.
Línea 1254... Línea 1268...
1254
    clearstatcache();
1268
    clearstatcache();
1255
    remove_dir($CFG->cachedir.'', true);
1269
    remove_dir($CFG->cachedir . '', true);
Línea 1256... Línea 1270...
1256
 
1270
 
Línea 1273... Línea 1287...
1273
 *
1287
 *
1274
 * @param string $type
1288
 * @param string $type
1275
 * @param int $changedsince default null
1289
 * @param int $changedsince default null
1276
 * @return array records array
1290
 * @return array records array
1277
 */
1291
 */
1278
function get_cache_flags($type, $changedsince = null) {
1292
function get_cache_flags($type, $changedsince = null)
-
 
1293
{
1279
    global $DB;
1294
    global $DB;
Línea 1280... Línea 1295...
1280
 
1295
 
1281
    $params = array('type' => $type, 'expiry' => time());
1296
    $params = array('type' => $type, 'expiry' => time());
1282
    $sqlwhere = "flagtype = :type AND expiry >= :expiry";
1297
    $sqlwhere = "flagtype = :type AND expiry >= :expiry";
Línea 1299... Línea 1314...
1299
 * @param string $type
1314
 * @param string $type
1300
 * @param string $name
1315
 * @param string $name
1301
 * @param int $changedsince default null
1316
 * @param int $changedsince default null
1302
 * @return string|false The cache flag value or false
1317
 * @return string|false The cache flag value or false
1303
 */
1318
 */
1304
function get_cache_flag($type, $name, $changedsince=null) {
1319
function get_cache_flag($type, $name, $changedsince = null)
-
 
1320
{
1305
    global $DB;
1321
    global $DB;
Línea 1306... Línea 1322...
1306
 
1322
 
Línea 1307... Línea 1323...
1307
    $params = array('type' => $type, 'name' => $name, 'expiry' => time());
1323
    $params = array('type' => $type, 'name' => $name, 'expiry' => time());
Línea 1322... Línea 1338...
1322
 * @param string $name the key to set
1338
 * @param string $name the key to set
1323
 * @param string $value the value to set (without magic quotes) - null will remove the flag
1339
 * @param string $value the value to set (without magic quotes) - null will remove the flag
1324
 * @param int $expiry (optional) epoch indicating expiry - defaults to now()+ 24hs
1340
 * @param int $expiry (optional) epoch indicating expiry - defaults to now()+ 24hs
1325
 * @return bool Always returns true
1341
 * @return bool Always returns true
1326
 */
1342
 */
1327
function set_cache_flag($type, $name, $value, $expiry = null) {
1343
function set_cache_flag($type, $name, $value, $expiry = null)
-
 
1344
{
1328
    global $DB;
1345
    global $DB;
Línea 1329... Línea 1346...
1329
 
1346
 
1330
    $timemodified = time();
1347
    $timemodified = time();
1331
    if ($expiry === null || $expiry < $timemodified) {
1348
    if ($expiry === null || $expiry < $timemodified) {
Línea 1365... Línea 1382...
1365
 *
1382
 *
1366
 * @param string $type the "type" namespace for the key
1383
 * @param string $type the "type" namespace for the key
1367
 * @param string $name the key to set
1384
 * @param string $name the key to set
1368
 * @return bool
1385
 * @return bool
1369
 */
1386
 */
1370
function unset_cache_flag($type, $name) {
1387
function unset_cache_flag($type, $name)
-
 
1388
{
1371
    global $DB;
1389
    global $DB;
1372
    $DB->delete_records('cache_flags', array('name' => $name, 'flagtype' => $type));
1390
    $DB->delete_records('cache_flags', array('name' => $name, 'flagtype' => $type));
1373
    return true;
1391
    return true;
1374
}
1392
}
Línea 1375... Línea 1393...
1375
 
1393
 
1376
/**
1394
/**
1377
 * Garbage-collect volatile flags
1395
 * Garbage-collect volatile flags
1378
 *
1396
 *
1379
 * @return bool Always returns true
1397
 * @return bool Always returns true
1380
 */
1398
 */
-
 
1399
function gc_cache_flags()
1381
function gc_cache_flags() {
1400
{
1382
    global $DB;
1401
    global $DB;
1383
    $DB->delete_records_select('cache_flags', 'expiry < ?', array(time()));
1402
    $DB->delete_records_select('cache_flags', 'expiry < ?', array(time()));
1384
    return true;
1403
    return true;
Línea 1398... Línea 1417...
1398
 * @param    stdClass         $user          User object. Preferences are preloaded into 'preference' property
1417
 * @param    stdClass         $user          User object. Preferences are preloaded into 'preference' property
1399
 * @param    int              $cachelifetime Cache life time on the current page (in seconds)
1418
 * @param    int              $cachelifetime Cache life time on the current page (in seconds)
1400
 * @throws   coding_exception
1419
 * @throws   coding_exception
1401
 * @return   null
1420
 * @return   null
1402
 */
1421
 */
1403
function check_user_preferences_loaded(stdClass $user, $cachelifetime = 120) {
1422
function check_user_preferences_loaded(stdClass $user, $cachelifetime = 120)
-
 
1423
{
1404
    global $DB;
1424
    global $DB;
1405
    // Static cache, we need to check on each page load, not only every 2 minutes.
1425
    // Static cache, we need to check on each page load, not only every 2 minutes.
1406
    static $loadedusers = array();
1426
    static $loadedusers = array();
Línea 1407... Línea 1427...
1407
 
1427
 
Línea 1422... Línea 1442...
1422
    if (isset($loadedusers[$user->id]) and isset($user->preference) and isset($user->preference['_lastloaded'])) {
1442
    if (isset($loadedusers[$user->id]) and isset($user->preference) and isset($user->preference['_lastloaded'])) {
1423
        // Already loaded at least once on this page. Are we up to date?
1443
        // Already loaded at least once on this page. Are we up to date?
1424
        if ($user->preference['_lastloaded'] + $cachelifetime > $timenow) {
1444
        if ($user->preference['_lastloaded'] + $cachelifetime > $timenow) {
1425
            // No need to reload - we are on the same page and we loaded prefs just a moment ago.
1445
            // No need to reload - we are on the same page and we loaded prefs just a moment ago.
1426
            return;
1446
            return;
1427
 
-
 
1428
        } else if (!get_cache_flag('userpreferenceschanged', $user->id, $user->preference['_lastloaded'])) {
1447
        } else if (!get_cache_flag('userpreferenceschanged', $user->id, $user->preference['_lastloaded'])) {
1429
            // No change since the lastcheck on this page.
1448
            // No change since the lastcheck on this page.
1430
            $user->preference['_lastloaded'] = $timenow;
1449
            $user->preference['_lastloaded'] = $timenow;
1431
            return;
1450
            return;
1432
        }
1451
        }
Línea 1445... Línea 1464...
1445
 *
1464
 *
1446
 * @package core
1465
 * @package core
1447
 * @access private
1466
 * @access private
1448
 * @param integer $userid the user whose prefs were changed.
1467
 * @param integer $userid the user whose prefs were changed.
1449
 */
1468
 */
1450
function mark_user_preferences_changed($userid) {
1469
function mark_user_preferences_changed($userid)
-
 
1470
{
1451
    global $CFG;
1471
    global $CFG;
Línea 1452... Línea 1472...
1452
 
1472
 
1453
    if (empty($userid) or isguestuser($userid)) {
1473
    if (empty($userid) or isguestuser($userid)) {
1454
        // No cache flags for guest and not-logged-in users.
1474
        // No cache flags for guest and not-logged-in users.
Línea 1473... Línea 1493...
1473
 *                                    record, null means delete current value.
1493
 *                                    record, null means delete current value.
1474
 * @param    stdClass|int|null $user  A moodle user object or id, null means current user
1494
 * @param    stdClass|int|null $user  A moodle user object or id, null means current user
1475
 * @throws   coding_exception
1495
 * @throws   coding_exception
1476
 * @return   bool                     Always true or exception
1496
 * @return   bool                     Always true or exception
1477
 */
1497
 */
1478
function set_user_preference($name, $value, $user = null) {
1498
function set_user_preference($name, $value, $user = null)
-
 
1499
{
1479
    global $USER, $DB;
1500
    global $USER, $DB;
Línea 1480... Línea 1501...
1480
 
1501
 
1481
    if (empty($name) or is_numeric($name) or $name === '_lastloaded') {
1502
    if (empty($name) or is_numeric($name) or $name === '_lastloaded') {
1482
        throw new coding_exception('Invalid preference name in set_user_preference() call');
1503
        throw new coding_exception('Invalid preference name in set_user_preference() call');
Línea 1518... Línea 1539...
1518
        if ($preference->value === $value and isset($user->preference[$name]) and $user->preference[$name] === $value) {
1539
        if ($preference->value === $value and isset($user->preference[$name]) and $user->preference[$name] === $value) {
1519
            // Preference already set to this value.
1540
            // Preference already set to this value.
1520
            return true;
1541
            return true;
1521
        }
1542
        }
1522
        $DB->set_field('user_preferences', 'value', $value, array('id' => $preference->id));
1543
        $DB->set_field('user_preferences', 'value', $value, array('id' => $preference->id));
1523
 
-
 
1524
    } else {
1544
    } else {
1525
        $preference = new stdClass();
1545
        $preference = new stdClass();
1526
        $preference->userid = $user->id;
1546
        $preference->userid = $user->id;
1527
        $preference->name   = $name;
1547
        $preference->name   = $name;
1528
        $preference->value  = $value;
1548
        $preference->value  = $value;
Línea 1552... Línea 1572...
1552
 * @access   public
1572
 * @access   public
1553
 * @param    array             $prefarray An array of key/value pairs to be set
1573
 * @param    array             $prefarray An array of key/value pairs to be set
1554
 * @param    stdClass|int|null $user      A moodle user object or id, null means current user
1574
 * @param    stdClass|int|null $user      A moodle user object or id, null means current user
1555
 * @return   bool                         Always true or exception
1575
 * @return   bool                         Always true or exception
1556
 */
1576
 */
1557
function set_user_preferences(array $prefarray, $user = null) {
1577
function set_user_preferences(array $prefarray, $user = null)
-
 
1578
{
1558
    foreach ($prefarray as $name => $value) {
1579
    foreach ($prefarray as $name => $value) {
1559
        set_user_preference($name, $value, $user);
1580
        set_user_preference($name, $value, $user);
1560
    }
1581
    }
1561
    return true;
1582
    return true;
1562
}
1583
}
Línea 1572... Línea 1593...
1572
 * @param    string            $name The key to unset as preference for the specified user
1593
 * @param    string            $name The key to unset as preference for the specified user
1573
 * @param    stdClass|int|null $user A moodle user object or id, null means current user
1594
 * @param    stdClass|int|null $user A moodle user object or id, null means current user
1574
 * @throws   coding_exception
1595
 * @throws   coding_exception
1575
 * @return   bool                    Always true or exception
1596
 * @return   bool                    Always true or exception
1576
 */
1597
 */
1577
function unset_user_preference($name, $user = null) {
1598
function unset_user_preference($name, $user = null)
-
 
1599
{
1578
    global $USER, $DB;
1600
    global $USER, $DB;
Línea 1579... Línea 1601...
1579
 
1601
 
1580
    if (empty($name) or is_numeric($name) or $name === '_lastloaded') {
1602
    if (empty($name) or is_numeric($name) or $name === '_lastloaded') {
1581
        throw new coding_exception('Invalid preference name in unset_user_preference() call');
1603
        throw new coding_exception('Invalid preference name in unset_user_preference() call');
Línea 1636... Línea 1658...
1636
 * @param    stdClass|int|null $user    A moodle user object or id, null means current user
1658
 * @param    stdClass|int|null $user    A moodle user object or id, null means current user
1637
 * @throws   coding_exception
1659
 * @throws   coding_exception
1638
 * @return   string|mixed|null          A string containing the value of a single preference. An
1660
 * @return   string|mixed|null          A string containing the value of a single preference. An
1639
 *                                      array with all of the preferences or null
1661
 *                                      array with all of the preferences or null
1640
 */
1662
 */
1641
function get_user_preferences($name = null, $default = null, $user = null) {
1663
function get_user_preferences($name = null, $default = null, $user = null)
-
 
1664
{
1642
    global $USER;
1665
    global $USER;
Línea 1643... Línea 1666...
1643
 
1666
 
1644
    if (is_null($name)) {
1667
    if (is_null($name)) {
1645
        // All prefs.
1668
        // All prefs.
Línea 1692... Línea 1715...
1692
 *             if 99 then default user's timezone is used {@link https://moodledev.io/docs/apis/subsystems/time#timezone}
1715
 *             if 99 then default user's timezone is used {@link https://moodledev.io/docs/apis/subsystems/time#timezone}
1693
 * @param bool $applydst Toggle Daylight Saving Time, default true, will be
1716
 * @param bool $applydst Toggle Daylight Saving Time, default true, will be
1694
 *             applied only if timezone is 99 or string.
1717
 *             applied only if timezone is 99 or string.
1695
 * @return int GMT timestamp
1718
 * @return int GMT timestamp
1696
 */
1719
 */
1697
function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) {
1720
function make_timestamp($year, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $timezone = 99, $applydst = true)
-
 
1721
{
1698
    $date = new DateTime('now', core_date::get_user_timezone_object($timezone));
1722
    $date = new DateTime('now', core_date::get_user_timezone_object($timezone));
1699
    $date->setDate((int)$year, (int)$month, (int)$day);
1723
    $date->setDate((int)$year, (int)$month, (int)$day);
1700
    $date->setTime((int)$hour, (int)$minute, (int)$second);
1724
    $date->setTime((int)$hour, (int)$minute, (int)$second);
Línea 1701... Línea 1725...
1701
 
1725
 
Línea 1702... Línea 1726...
1702
    $time = $date->getTimestamp();
1726
    $time = $date->getTimestamp();
1703
 
1727
 
1704
    if ($time === false) {
1728
    if ($time === false) {
1705
        throw new coding_exception('getTimestamp() returned false, please ensure you have passed correct values.'.
1729
        throw new coding_exception('getTimestamp() returned false, please ensure you have passed correct values.' .
Línea 1706... Línea 1730...
1706
            ' This can fail if year is more than 2038 and OS is 32 bit windows');
1730
            ' This can fail if year is more than 2038 and OS is 32 bit windows');
1707
    }
1731
    }
1708
 
1732
 
1709
    // Moodle BC DST stuff.
1733
    // Moodle BC DST stuff.
Línea 1710... Línea 1734...
1710
    if (!$applydst) {
1734
    if (!$applydst) {
1711
        $time += dst_offset_on($time, $timezone);
-
 
1712
    }
1735
        $time += dst_offset_on($time, $timezone);
Línea 1713... Línea 1736...
1713
 
1736
    }
1714
    return $time;
1737
 
1715
 
1738
    return $time;
Línea 1729... Línea 1752...
1729
 * @uses YEARSECS
1752
 * @uses YEARSECS
1730
 * @param int $totalsecs Time in seconds
1753
 * @param int $totalsecs Time in seconds
1731
 * @param stdClass $str Should be a time object
1754
 * @param stdClass $str Should be a time object
1732
 * @return string A nicely formatted date/time string
1755
 * @return string A nicely formatted date/time string
1733
 */
1756
 */
1734
function format_time($totalsecs, $str = null) {
1757
function format_time($totalsecs, $str = null)
-
 
1758
{
Línea 1735... Línea 1759...
1735
 
1759
 
Línea 1736... Línea 1760...
1736
    $totalsecs = abs($totalsecs);
1760
    $totalsecs = abs($totalsecs);
1737
 
1761
 
Línea 1748... Línea 1772...
1748
        $str->secs  = get_string('secs');
1772
        $str->secs  = get_string('secs');
1749
        $str->year  = get_string('year');
1773
        $str->year  = get_string('year');
1750
        $str->years = get_string('years');
1774
        $str->years = get_string('years');
1751
    }
1775
    }
Línea 1752... Línea 1776...
1752
 
1776
 
1753
    $years     = floor($totalsecs/YEARSECS);
1777
    $years     = floor($totalsecs / YEARSECS);
1754
    $remainder = $totalsecs - ($years*YEARSECS);
1778
    $remainder = $totalsecs - ($years * YEARSECS);
1755
    $days      = floor($remainder/DAYSECS);
1779
    $days      = floor($remainder / DAYSECS);
1756
    $remainder = $totalsecs - ($days*DAYSECS);
1780
    $remainder = $totalsecs - ($days * DAYSECS);
1757
    $hours     = floor($remainder/HOURSECS);
1781
    $hours     = floor($remainder / HOURSECS);
1758
    $remainder = $remainder - ($hours*HOURSECS);
1782
    $remainder = $remainder - ($hours * HOURSECS);
1759
    $mins      = floor($remainder/MINSECS);
1783
    $mins      = floor($remainder / MINSECS);
Línea 1760... Línea 1784...
1760
    $secs      = $remainder - ($mins*MINSECS);
1784
    $secs      = $remainder - ($mins * MINSECS);
1761
 
1785
 
1762
    $ss = ($secs == 1)  ? $str->sec  : $str->secs;
1786
    $ss = ($secs == 1)  ? $str->sec  : $str->secs;
1763
    $sm = ($mins == 1)  ? $str->min  : $str->mins;
1787
    $sm = ($mins == 1)  ? $str->min  : $str->mins;
Línea 1770... Línea 1794...
1770
    $ohours = '';
1794
    $ohours = '';
1771
    $omins = '';
1795
    $omins = '';
1772
    $osecs = '';
1796
    $osecs = '';
Línea 1773... Línea 1797...
1773
 
1797
 
1774
    if ($years) {
1798
    if ($years) {
1775
        $oyears  = $years .' '. $sy;
1799
        $oyears  = $years . ' ' . $sy;
1776
    }
1800
    }
1777
    if ($days) {
1801
    if ($days) {
1778
        $odays  = $days .' '. $sd;
1802
        $odays  = $days . ' ' . $sd;
1779
    }
1803
    }
1780
    if ($hours) {
1804
    if ($hours) {
1781
        $ohours = $hours .' '. $sh;
1805
        $ohours = $hours . ' ' . $sh;
1782
    }
1806
    }
1783
    if ($mins) {
1807
    if ($mins) {
1784
        $omins  = $mins .' '. $sm;
1808
        $omins  = $mins . ' ' . $sm;
1785
    }
1809
    }
1786
    if ($secs) {
1810
    if ($secs) {
1787
        $osecs  = $secs .' '. $ss;
1811
        $osecs  = $secs . ' ' . $ss;
Línea 1788... Línea 1812...
1788
    }
1812
    }
1789
 
1813
 
1790
    if ($years) {
1814
    if ($years) {
1791
        return trim($oyears .' '. $odays);
1815
        return trim($oyears . ' ' . $odays);
1792
    }
1816
    }
1793
    if ($days) {
1817
    if ($days) {
1794
        return trim($odays .' '. $ohours);
1818
        return trim($odays . ' ' . $ohours);
1795
    }
1819
    }
1796
    if ($hours) {
1820
    if ($hours) {
1797
        return trim($ohours .' '. $omins);
1821
        return trim($ohours . ' ' . $omins);
1798
    }
1822
    }
1799
    if ($mins) {
1823
    if ($mins) {
1800
        return trim($omins .' '. $osecs);
1824
        return trim($omins . ' ' . $osecs);
1801
    }
1825
    }
1802
    if ($secs) {
1826
    if ($secs) {
1803
        return $osecs;
1827
        return $osecs;
Línea 1819... Línea 1843...
1819
 * @param bool $fixday If true (default) then the leading zero from %d is removed.
1843
 * @param bool $fixday If true (default) then the leading zero from %d is removed.
1820
 *        If false then the leading zero is maintained.
1844
 *        If false then the leading zero is maintained.
1821
 * @param bool $fixhour If true (default) then the leading zero from %I is removed.
1845
 * @param bool $fixhour If true (default) then the leading zero from %I is removed.
1822
 * @return string the formatted date/time.
1846
 * @return string the formatted date/time.
1823
 */
1847
 */
1824
function userdate($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true) {
1848
function userdate($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true)
-
 
1849
{
1825
    $calendartype = \core_calendar\type_factory::get_calendar_instance();
1850
    $calendartype = \core_calendar\type_factory::get_calendar_instance();
1826
    return $calendartype->timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour);
1851
    return $calendartype->timestamp_to_date_string($date, $format, $timezone, $fixday, $fixhour);
1827
}
1852
}
Línea 1828... Línea 1853...
1828
 
1853
 
Línea 1841... Línea 1866...
1841
 * @param bool $fixday If true (default) then the leading zero from %d is removed.
1866
 * @param bool $fixday If true (default) then the leading zero from %d is removed.
1842
 *        If false then the leading zero is maintained.
1867
 *        If false then the leading zero is maintained.
1843
 * @param bool $fixhour If true (default) then the leading zero from %I is removed.
1868
 * @param bool $fixhour If true (default) then the leading zero from %I is removed.
1844
 * @return string the formatted date/time.
1869
 * @return string the formatted date/time.
1845
 */
1870
 */
1846
function userdate_htmltime($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true) {
1871
function userdate_htmltime($date, $format = '', $timezone = 99, $fixday = true, $fixhour = true)
-
 
1872
{
1847
    $userdatestr = userdate($date, $format, $timezone, $fixday, $fixhour);
1873
    $userdatestr = userdate($date, $format, $timezone, $fixday, $fixhour);
1848
    if (CLI_SCRIPT && !PHPUNIT_TEST) {
1874
    if (CLI_SCRIPT && !PHPUNIT_TEST) {
1849
        return $userdatestr;
1875
        return $userdatestr;
1850
    }
1876
    }
1851
    $machinedate = new DateTime();
1877
    $machinedate = new DateTime();
Línea 1865... Línea 1891...
1865
 * @param string $format strftime format.
1891
 * @param string $format strftime format.
1866
 * @param int|float|string $tz the user timezone
1892
 * @param int|float|string $tz the user timezone
1867
 * @return string the formatted date/time.
1893
 * @return string the formatted date/time.
1868
 * @since Moodle 2.3.3
1894
 * @since Moodle 2.3.3
1869
 */
1895
 */
1870
function date_format_string($date, $format, $tz = 99) {
1896
function date_format_string($date, $format, $tz = 99)
-
 
1897
{
Línea 1871... Línea 1898...
1871
 
1898
 
Línea 1872... Línea 1899...
1872
    date_default_timezone_set(core_date::get_user_timezone($tz));
1899
    date_default_timezone_set(core_date::get_user_timezone($tz));
1873
 
1900
 
Línea 1896... Línea 1923...
1896
 * @category time
1923
 * @category time
1897
 * @param int $time Timestamp in GMT
1924
 * @param int $time Timestamp in GMT
1898
 * @param float|int|string $timezone user timezone
1925
 * @param float|int|string $timezone user timezone
1899
 * @return array An array that represents the date in user time
1926
 * @return array An array that represents the date in user time
1900
 */
1927
 */
1901
function usergetdate($time, $timezone=99) {
1928
function usergetdate($time, $timezone = 99)
-
 
1929
{
1902
    if ($time === null) {
1930
    if ($time === null) {
1903
        // PHP8 and PHP7 return different results when getdate(null) is called.
1931
        // PHP8 and PHP7 return different results when getdate(null) is called.
1904
        // Display warning and cast to 0 to make sure the usergetdate() behaves consistently on all versions of PHP.
1932
        // Display warning and cast to 0 to make sure the usergetdate() behaves consistently on all versions of PHP.
1905
        // In the future versions of Moodle we may consider adding a strict typehint.
1933
        // In the future versions of Moodle we may consider adding a strict typehint.
1906
        debugging('usergetdate() expects parameter $time to be int, null given', DEBUG_DEVELOPER);
1934
        debugging('usergetdate() expects parameter $time to be int, null given', DEBUG_DEVELOPER);
Línea 1925... Línea 1953...
1925
 * @category time
1953
 * @category time
1926
 * @param int $date Timestamp in GMT
1954
 * @param int $date Timestamp in GMT
1927
 * @param float|int|string $timezone user timezone
1955
 * @param float|int|string $timezone user timezone
1928
 * @return int
1956
 * @return int
1929
 */
1957
 */
1930
function usertime($date, $timezone=99) {
1958
function usertime($date, $timezone = 99)
-
 
1959
{
1931
    $userdate = new DateTime('@' . $date);
1960
    $userdate = new DateTime('@' . $date);
1932
    $userdate->setTimezone(core_date::get_user_timezone_object($timezone));
1961
    $userdate->setTimezone(core_date::get_user_timezone_object($timezone));
1933
    $dst = dst_offset_on($date, $timezone);
1962
    $dst = dst_offset_on($date, $timezone);
Línea 1934... Línea 1963...
1934
 
1963
 
Línea 1950... Línea 1979...
1950
 *                         e.g. a duration of 3 days and 2 hours will be displayed as '3d 2h' instead of '3d 2h 0s'
1979
 *                         e.g. a duration of 3 days and 2 hours will be displayed as '3d 2h' instead of '3d 2h 0s'
1951
 * @param bool $fullformat If format is not provided and this is set to true, display time units in full format.
1980
 * @param bool $fullformat If format is not provided and this is set to true, display time units in full format.
1952
 *                         e.g. instead of showing "3d", "3 days" will be returned.
1981
 *                         e.g. instead of showing "3d", "3 days" will be returned.
1953
 * @return string the formatted string describing the time difference, e.g. '10d 11h 45m'.
1982
 * @return string the formatted string describing the time difference, e.g. '10d 11h 45m'.
1954
 */
1983
 */
1955
function get_time_interval_string(int $time1, int $time2, string $format = '',
1984
function get_time_interval_string(
-
 
1985
    int $time1,
-
 
1986
    int $time2,
-
 
1987
    string $format = '',
1956
        bool $dropzeroes = false, bool $fullformat = false): string {
1988
    bool $dropzeroes = false,
-
 
1989
    bool $fullformat = false
-
 
1990
): string {
1957
    $dtdate = new DateTime();
1991
    $dtdate = new DateTime();
1958
    $dtdate->setTimeStamp($time1);
1992
    $dtdate->setTimeStamp($time1);
1959
    $dtdate2 = new DateTime();
1993
    $dtdate2 = new DateTime();
1960
    $dtdate2->setTimeStamp($time2);
1994
    $dtdate2->setTimeStamp($time2);
1961
    $interval = $dtdate2->diff($dtdate);
1995
    $interval = $dtdate2->diff($dtdate);
Línea 2001... Línea 2035...
2001
 * @category time
2035
 * @category time
2002
 * @param int $date Timestamp in GMT
2036
 * @param int $date Timestamp in GMT
2003
 * @param float|int|string $timezone user timezone
2037
 * @param float|int|string $timezone user timezone
2004
 * @return int Returns a GMT timestamp
2038
 * @return int Returns a GMT timestamp
2005
 */
2039
 */
2006
function usergetmidnight($date, $timezone=99) {
2040
function usergetmidnight($date, $timezone = 99)
-
 
2041
{
Línea 2007... Línea 2042...
2007
 
2042
 
Línea 2008... Línea 2043...
2008
    $userdate = usergetdate($date, $timezone);
2043
    $userdate = usergetdate($date, $timezone);
2009
 
2044
 
2010
    // Time of midnight of this user's day, in GMT.
-
 
2011
    return make_timestamp($userdate['year'], $userdate['mon'], $userdate['mday'], 0, 0, 0, $timezone);
2045
    // Time of midnight of this user's day, in GMT.
Línea 2012... Línea 2046...
2012
 
2046
    return make_timestamp($userdate['year'], $userdate['mon'], $userdate['mday'], 0, 0, 0, $timezone);
2013
}
2047
}
2014
 
2048
 
2015
/**
2049
/**
2016
 * Returns a string that prints the user's timezone
2050
 * Returns a string that prints the user's timezone
2017
 *
2051
 *
2018
 * @package core
2052
 * @package core
2019
 * @category time
2053
 * @category time
2020
 * @param float|int|string $timezone user timezone
2054
 * @param float|int|string $timezone user timezone
-
 
2055
 * @return string
2021
 * @return string
2056
 */
2022
 */
2057
function usertimezone($timezone = 99)
2023
function usertimezone($timezone=99) {
2058
{
Línea 2024... Línea 2059...
2024
    $tz = core_date::get_user_timezone($timezone);
2059
    $tz = core_date::get_user_timezone($timezone);
Línea 2036... Línea 2071...
2036
 * @param float|int|string $tz timezone to calculate GMT time offset before
2071
 * @param float|int|string $tz timezone to calculate GMT time offset before
2037
 *        calculating user timezone, 99 is default user timezone
2072
 *        calculating user timezone, 99 is default user timezone
2038
 *        {@link https://moodledev.io/docs/apis/subsystems/time#timezone}
2073
 *        {@link https://moodledev.io/docs/apis/subsystems/time#timezone}
2039
 * @return float|string
2074
 * @return float|string
2040
 */
2075
 */
2041
function get_user_timezone($tz = 99) {
2076
function get_user_timezone($tz = 99)
-
 
2077
{
2042
    global $USER, $CFG;
2078
    global $USER, $CFG;
Línea 2043... Línea 2079...
2043
 
2079
 
2044
    $timezones = array(
2080
    $timezones = array(
2045
        $tz,
2081
        $tz,
2046
        isset($CFG->forcetimezone) ? $CFG->forcetimezone : 99,
2082
        isset($CFG->forcetimezone) ? $CFG->forcetimezone : 99,
2047
        isset($USER->timezone) ? $USER->timezone : 99,
2083
        isset($USER->timezone) ? $USER->timezone : 99,
2048
        isset($CFG->timezone) ? $CFG->timezone : 99,
2084
        isset($CFG->timezone) ? $CFG->timezone : 99,
Línea 2049... Línea 2085...
2049
        );
2085
    );
Línea 2050... Línea 2086...
2050
 
2086
 
2051
    $tz = 99;
2087
    $tz = 99;
Línea 2067... Línea 2103...
2067
 * @category time
2103
 * @category time
2068
 * @param int $time must NOT be compensated at all, it has to be a pure timestamp
2104
 * @param int $time must NOT be compensated at all, it has to be a pure timestamp
2069
 * @param int|float|string $strtimezone user timezone
2105
 * @param int|float|string $strtimezone user timezone
2070
 * @return int
2106
 * @return int
2071
 */
2107
 */
2072
function dst_offset_on($time, $strtimezone = null) {
2108
function dst_offset_on($time, $strtimezone = null)
-
 
2109
{
2073
    $tz = core_date::get_user_timezone($strtimezone);
2110
    $tz = core_date::get_user_timezone($strtimezone);
2074
    $date = new DateTime('@' . $time);
2111
    $date = new DateTime('@' . $time);
2075
    $date->setTimezone(new DateTimeZone($tz));
2112
    $date->setTimezone(new DateTimeZone($tz));
2076
    if ($date->format('I') == '1') {
2113
    if ($date->format('I') == '1') {
2077
        if ($tz === 'Australia/Lord_Howe') {
2114
        if ($tz === 'Australia/Lord_Howe') {
Línea 2091... Línea 2128...
2091
 * @param int $weekday The day when week starts (normally taken from user preferences)
2128
 * @param int $weekday The day when week starts (normally taken from user preferences)
2092
 * @param int $month The month whose day is sought
2129
 * @param int $month The month whose day is sought
2093
 * @param int $year The year of the month whose day is sought
2130
 * @param int $year The year of the month whose day is sought
2094
 * @return int
2131
 * @return int
2095
 */
2132
 */
2096
function find_day_in_month($startday, $weekday, $month, $year) {
2133
function find_day_in_month($startday, $weekday, $month, $year)
-
 
2134
{
2097
    $calendartype = \core_calendar\type_factory::get_calendar_instance();
2135
    $calendartype = \core_calendar\type_factory::get_calendar_instance();
Línea 2098... Línea 2136...
2098
 
2136
 
2099
    $daysinmonth = days_in_month($month, $year);
2137
    $daysinmonth = days_in_month($month, $year);
Línea 2151... Línea 2189...
2151
 * @category time
2189
 * @category time
2152
 * @param int $month The month whose day count is sought
2190
 * @param int $month The month whose day count is sought
2153
 * @param int $year The year of the month whose day count is sought
2191
 * @param int $year The year of the month whose day count is sought
2154
 * @return int
2192
 * @return int
2155
 */
2193
 */
2156
function days_in_month($month, $year) {
2194
function days_in_month($month, $year)
-
 
2195
{
2157
    $calendartype = \core_calendar\type_factory::get_calendar_instance();
2196
    $calendartype = \core_calendar\type_factory::get_calendar_instance();
2158
    return $calendartype->get_num_days_in_month($year, $month);
2197
    return $calendartype->get_num_days_in_month($year, $month);
2159
}
2198
}
Línea 2160... Línea 2199...
2160
 
2199
 
Línea 2166... Línea 2205...
2166
 * @param int $day The day of the date whose position in the week is sought
2205
 * @param int $day The day of the date whose position in the week is sought
2167
 * @param int $month The month of the date whose position in the week is sought
2206
 * @param int $month The month of the date whose position in the week is sought
2168
 * @param int $year The year of the date whose position in the week is sought
2207
 * @param int $year The year of the date whose position in the week is sought
2169
 * @return int
2208
 * @return int
2170
 */
2209
 */
2171
function dayofweek($day, $month, $year) {
2210
function dayofweek($day, $month, $year)
-
 
2211
{
2172
    $calendartype = \core_calendar\type_factory::get_calendar_instance();
2212
    $calendartype = \core_calendar\type_factory::get_calendar_instance();
2173
    return $calendartype->get_weekday($year, $month, $day);
2213
    return $calendartype->get_weekday($year, $month, $day);
2174
}
2214
}
Línea 2175... Línea 2215...
2175
 
2215
 
Línea 2181... Línea 2221...
2181
 * Any form submissions for authentication to this URL must include username,
2221
 * Any form submissions for authentication to this URL must include username,
2182
 * password as well as a logintoken generated by \core\session\manager::get_login_token().
2222
 * password as well as a logintoken generated by \core\session\manager::get_login_token().
2183
 *
2223
 *
2184
 * @return string login url
2224
 * @return string login url
2185
 */
2225
 */
2186
function get_login_url() {
2226
function get_login_url()
-
 
2227
{
2187
    global $CFG;
2228
    global $CFG;
Línea 2188... Línea 2229...
2188
 
2229
 
2189
    return "$CFG->wwwroot/login/index.php";
2230
    return "$CFG->wwwroot/login/index.php";
Línea 2220... Línea 2261...
2220
 * @return mixed Void, exit, and die depending on path
2261
 * @return mixed Void, exit, and die depending on path
2221
 * @throws coding_exception
2262
 * @throws coding_exception
2222
 * @throws require_login_exception
2263
 * @throws require_login_exception
2223
 * @throws moodle_exception
2264
 * @throws moodle_exception
2224
 */
2265
 */
2225
function require_login($courseorid = null, $autologinguest = true, $cm = null, $setwantsurltome = true, $preventredirect = false) {
2266
function require_login($courseorid = null, $autologinguest = true, $cm = null, $setwantsurltome = true, $preventredirect = false)
-
 
2267
{
2226
    global $CFG, $SESSION, $USER, $PAGE, $SITE, $DB, $OUTPUT;
2268
    global $CFG, $SESSION, $USER, $PAGE, $SITE, $DB, $OUTPUT;
Línea 2227... Línea 2269...
2227
 
2269
 
2228
    // Must not redirect when byteserving already started.
2270
    // Must not redirect when byteserving already started.
2229
    if (!empty($_SERVER['HTTP_RANGE'])) {
2271
    if (!empty($_SERVER['HTTP_RANGE'])) {
Línea 2238... Línea 2280...
2238
    // Setup global $COURSE, themes, language and locale.
2280
    // Setup global $COURSE, themes, language and locale.
2239
    if (!empty($courseorid)) {
2281
    if (!empty($courseorid)) {
2240
        if (is_object($courseorid)) {
2282
        if (is_object($courseorid)) {
2241
            $course = $courseorid;
2283
            $course = $courseorid;
2242
        } else if ($courseorid == SITEID) {
2284
        } else if ($courseorid == SITEID) {
2243
            $course = clone($SITE);
2285
            $course = clone ($SITE);
2244
        } else {
2286
        } else {
2245
            $course = $DB->get_record('course', array('id' => $courseorid), '*', MUST_EXIST);
2287
            $course = $DB->get_record('course', array('id' => $courseorid), '*', MUST_EXIST);
2246
        }
2288
        }
2247
        if ($cm) {
2289
        if ($cm) {
2248
            if ($cm->course != $course->id) {
2290
            if ($cm->course != $course->id) {
Línea 2307... Línea 2349...
2307
                $SESSION->wantsurl = qualified_me();
2349
                $SESSION->wantsurl = qualified_me();
2308
            }
2350
            }
Línea 2309... Línea 2351...
2309
 
2351
 
2310
            // Give auth plugins an opportunity to authenticate or redirect to an external login page
2352
            // Give auth plugins an opportunity to authenticate or redirect to an external login page
2311
            $authsequence = get_enabled_auth_plugins(); // Auths, in sequence.
2353
            $authsequence = get_enabled_auth_plugins(); // Auths, in sequence.
2312
            foreach($authsequence as $authname) {
2354
            foreach ($authsequence as $authname) {
2313
                $authplugin = get_auth_plugin($authname);
2355
                $authplugin = get_auth_plugin($authname);
2314
                $authplugin->pre_loginpage_hook();
2356
                $authplugin->pre_loginpage_hook();
2315
                if (isloggedin()) {
2357
                if (isloggedin()) {
2316
                    if ($cm) {
2358
                    if ($cm) {
Línea 2332... Línea 2374...
2332
 
2374
 
2333
    // Loginas as redirection if needed.
2375
    // Loginas as redirection if needed.
2334
    if ($course->id != SITEID and \core\session\manager::is_loggedinas()) {
2376
    if ($course->id != SITEID and \core\session\manager::is_loggedinas()) {
2335
        if ($USER->loginascontext->contextlevel == CONTEXT_COURSE) {
2377
        if ($USER->loginascontext->contextlevel == CONTEXT_COURSE) {
2336
            if ($USER->loginascontext->instanceid != $course->id) {
2378
            if ($USER->loginascontext->instanceid != $course->id) {
-
 
2379
                throw new \moodle_exception(
-
 
2380
                    'loginasonecourse',
2337
                throw new \moodle_exception('loginasonecourse', '',
2381
                    '',
-
 
2382
                    $CFG->wwwroot . '/course/view.php?id=' . $USER->loginascontext->instanceid
2338
                    $CFG->wwwroot.'/course/view.php?id='.$USER->loginascontext->instanceid);
2383
                );
2339
            }
2384
            }
2340
        }
2385
        }
Línea 2341... Línea 2386...
2341
    }
2386
    }
Línea 2350... Línea 2395...
2350
            if ($changeurl = $userauth->change_password_url()) {
2395
            if ($changeurl = $userauth->change_password_url()) {
2351
                // Use plugin custom url.
2396
                // Use plugin custom url.
2352
                redirect($changeurl);
2397
                redirect($changeurl);
2353
            } else {
2398
            } else {
2354
                // Use moodle internal method.
2399
                // Use moodle internal method.
2355
                redirect($CFG->wwwroot .'/login/change_password.php');
2400
                redirect($CFG->wwwroot . '/login/change_password.php');
2356
            }
2401
            }
2357
        } else if ($userauth->can_change_password()) {
2402
        } else if ($userauth->can_change_password()) {
2358
            throw new moodle_exception('forcepasswordchangenotice');
2403
            throw new moodle_exception('forcepasswordchangenotice');
2359
        } else {
2404
        } else {
2360
            throw new moodle_exception('nopasswordchangeforced', 'auth');
2405
            throw new moodle_exception('nopasswordchangeforced', 'auth');
Línea 2376... Línea 2421...
2376
            throw new moodle_exception('usernotfullysetup');
2421
            throw new moodle_exception('usernotfullysetup');
2377
        }
2422
        }
2378
        if ($setwantsurltome) {
2423
        if ($setwantsurltome) {
2379
            $SESSION->wantsurl = qualified_me();
2424
            $SESSION->wantsurl = qualified_me();
2380
        }
2425
        }
2381
        redirect($CFG->wwwroot .'/user/edit.php?id='. $USER->id .'&amp;course='. SITEID);
2426
        redirect($CFG->wwwroot . '/user/edit.php?id=' . $USER->id . '&amp;course=' . SITEID);
2382
    }
2427
    }
Línea 2383... Línea 2428...
2383
 
2428
 
2384
    // Make sure the USER has a sesskey set up. Used for CSRF protection.
2429
    // Make sure the USER has a sesskey set up. Used for CSRF protection.
Línea 2471... Línea 2516...
2471
                }
2516
                }
2472
                $PAGE->set_context(null);
2517
                $PAGE->set_context(null);
2473
                // We need to override the navigation URL as the course won't have been added to the navigation and thus
2518
                // We need to override the navigation URL as the course won't have been added to the navigation and thus
2474
                // the navigation will mess up when trying to find it.
2519
                // the navigation will mess up when trying to find it.
2475
                navigation_node::override_active_url(new moodle_url('/'));
2520
                navigation_node::override_active_url(new moodle_url('/'));
2476
                notice(get_string('coursehidden'), $CFG->wwwroot .'/');
2521
                notice(get_string('coursehidden'), $CFG->wwwroot . '/');
2477
            }
2522
            }
2478
        }
2523
        }
2479
    }
2524
    }
Línea 2480... Línea 2525...
2480
 
2525
 
Línea 2483... Línea 2528...
2483
        // Everybody is enrolled on the frontpage.
2528
        // Everybody is enrolled on the frontpage.
2484
    } else {
2529
    } else {
2485
        if (\core\session\manager::is_loggedinas()) {
2530
        if (\core\session\manager::is_loggedinas()) {
2486
            // Make sure the REAL person can access this course first.
2531
            // Make sure the REAL person can access this course first.
2487
            $realuser = \core\session\manager::get_realuser();
2532
            $realuser = \core\session\manager::get_realuser();
-
 
2533
            if (
2488
            if (!is_enrolled($coursecontext, $realuser->id, '', true) and
2534
                !is_enrolled($coursecontext, $realuser->id, '', true) and
2489
                !is_viewing($coursecontext, $realuser->id) and !is_siteadmin($realuser->id)) {
2535
                !is_viewing($coursecontext, $realuser->id) and !is_siteadmin($realuser->id)
-
 
2536
            ) {
2490
                if ($preventredirect) {
2537
                if ($preventredirect) {
2491
                    throw new require_login_exception('Invalid course login-as access');
2538
                    throw new require_login_exception('Invalid course login-as access');
2492
                }
2539
                }
2493
                $PAGE->set_context(null);
2540
                $PAGE->set_context(null);
2494
                echo $OUTPUT->header();
2541
                echo $OUTPUT->header();
2495
                notice(get_string('studentnotallowed', '', fullname($USER, true)), $CFG->wwwroot .'/');
2542
                notice(get_string('studentnotallowed', '', fullname($USER, true)), $CFG->wwwroot . '/');
2496
            }
2543
            }
2497
        }
2544
        }
Línea 2498... Línea 2545...
2498
 
2545
 
Línea 2499... Línea 2546...
2499
        $access = false;
2546
        $access = false;
2500
 
2547
 
2501
        if (is_role_switched($course->id)) {
2548
        if (is_role_switched($course->id)) {
2502
            // Ok, user had to be inside this course before the switch.
-
 
2503
            $access = true;
2549
            // Ok, user had to be inside this course before the switch.
2504
 
2550
            $access = true;
2505
        } else if (is_viewing($coursecontext, $USER)) {
2551
        } else if (is_viewing($coursecontext, $USER)) {
2506
            // Ok, no need to mess with enrol.
-
 
2507
            $access = true;
2552
            // Ok, no need to mess with enrol.
2508
 
2553
            $access = true;
2509
        } else {
2554
        } else {
2510
            if (isset($USER->enrol['enrolled'][$course->id])) {
2555
            if (isset($USER->enrol['enrolled'][$course->id])) {
2511
                if ($USER->enrol['enrolled'][$course->id] > time()) {
2556
                if ($USER->enrol['enrolled'][$course->id] > time()) {
Línea 2539... Línea 2584...
2539
                    if ($until == 0) {
2584
                    if ($until == 0) {
2540
                        $until = ENROL_MAX_TIMESTAMP;
2585
                        $until = ENROL_MAX_TIMESTAMP;
2541
                    }
2586
                    }
2542
                    $USER->enrol['enrolled'][$course->id] = $until;
2587
                    $USER->enrol['enrolled'][$course->id] = $until;
2543
                    $access = true;
2588
                    $access = true;
2544
 
-
 
2545
                } else if (core_course_category::can_view_course_info($course)) {
2589
                } else if (core_course_category::can_view_course_info($course)) {
2546
                    $params = array('courseid' => $course->id, 'status' => ENROL_INSTANCE_ENABLED);
2590
                    $params = array('courseid' => $course->id, 'status' => ENROL_INSTANCE_ENABLED);
2547
                    $instances = $DB->get_records('enrol', $params, 'sortorder, id ASC');
2591
                    $instances = $DB->get_records('enrol', $params, 'sortorder, id ASC');
2548
                    $enrols = enrol_get_plugins(true);
2592
                    $enrols = enrol_get_plugins(true);
2549
                    // First ask all enabled enrol instances in course if they want to auto enrol user.
2593
                    // First ask all enabled enrol instances in course if they want to auto enrol user.
Línea 2584... Línea 2628...
2584
                    }
2628
                    }
2585
                    $PAGE->set_context(null);
2629
                    $PAGE->set_context(null);
2586
                    // We need to override the navigation URL as the course won't have been added to the navigation and thus
2630
                    // We need to override the navigation URL as the course won't have been added to the navigation and thus
2587
                    // the navigation will mess up when trying to find it.
2631
                    // the navigation will mess up when trying to find it.
2588
                    navigation_node::override_active_url(new moodle_url('/'));
2632
                    navigation_node::override_active_url(new moodle_url('/'));
2589
                    notice(get_string('coursehidden'), $CFG->wwwroot .'/');
2633
                    notice(get_string('coursehidden'), $CFG->wwwroot . '/');
2590
                }
2634
                }
2591
            }
2635
            }
2592
        }
2636
        }
Línea 2593... Línea 2637...
2593
 
2637
 
Línea 2596... Línea 2640...
2596
                throw new require_login_exception('Not enrolled');
2640
                throw new require_login_exception('Not enrolled');
2597
            }
2641
            }
2598
            if ($setwantsurltome) {
2642
            if ($setwantsurltome) {
2599
                $SESSION->wantsurl = qualified_me();
2643
                $SESSION->wantsurl = qualified_me();
2600
            }
2644
            }
2601
            redirect($CFG->wwwroot .'/enrol/index.php?id='. $course->id);
2645
            redirect($CFG->wwwroot . '/enrol/index.php?id=' . $course->id);
2602
        }
2646
        }
2603
    }
2647
    }
Línea 2604... Línea 2648...
2604
 
2648
 
2605
    // Check whether the activity has been scheduled for deletion. If so, then deny access, even for admins.
2649
    // Check whether the activity has been scheduled for deletion. If so, then deny access, even for admins.
Línea 2646... Línea 2690...
2646
 
2690
 
2647
/**
2691
/**
2648
 * A convenience function for where we must be logged in as admin
2692
 * A convenience function for where we must be logged in as admin
2649
 * @return void
2693
 * @return void
2650
 */
2694
 */
-
 
2695
function require_admin()
2651
function require_admin() {
2696
{
2652
    require_login(null, false);
2697
    require_login(null, false);
2653
    require_capability('moodle/site:config', context_system::instance());
2698
    require_capability('moodle/site:config', context_system::instance());
Línea 2654... Línea 2699...
2654
}
2699
}
2655
 
2700
 
2656
/**
2701
/**
2657
 * This function just makes sure a user is logged out.
2702
 * This function just makes sure a user is logged out.
2658
 *
2703
 *
2659
 * @package    core_access
2704
 * @package    core_access
2660
 * @category   access
2705
 * @category   access
-
 
2706
 */
2661
 */
2707
function require_logout()
Línea 2662... Línea 2708...
2662
function require_logout() {
2708
{
2663
    global $USER, $DB;
2709
    global $USER, $DB;
2664
 
2710
 
Línea 2683... Línea 2729...
2683
            'userid' => $USER->id,
2729
            'userid' => $USER->id,
2684
            'objectid' => $USER->id,
2730
            'objectid' => $USER->id,
2685
            'other' => array('sessionid' => $sid),
2731
            'other' => array('sessionid' => $sid),
2686
        )
2732
        )
2687
    );
2733
    );
2688
    if ($session = $DB->get_record('sessions', array('sid'=>$sid))) {
2734
    if ($session = $DB->get_record('sessions', array('sid' => $sid))) {
2689
        $event->add_record_snapshot('sessions', $session);
2735
        $event->add_record_snapshot('sessions', $session);
2690
    }
2736
    }
Línea 2691... Línea 2737...
2691
 
2737
 
2692
    // Clone of $USER object to be used by auth plugins.
2738
    // Clone of $USER object to be used by auth plugins.
Línea 2723... Línea 2769...
2723
 *             in order to keep redirects working properly. MDL-14495
2769
 *             in order to keep redirects working properly. MDL-14495
2724
 * @param bool $preventredirect set to true in scripts that can not redirect (CLI, rss feeds, etc.), throws exceptions
2770
 * @param bool $preventredirect set to true in scripts that can not redirect (CLI, rss feeds, etc.), throws exceptions
2725
 * @return void
2771
 * @return void
2726
 * @throws coding_exception
2772
 * @throws coding_exception
2727
 */
2773
 */
2728
function require_course_login($courseorid, $autologinguest = true, $cm = null, $setwantsurltome = true, $preventredirect = false) {
2774
function require_course_login($courseorid, $autologinguest = true, $cm = null, $setwantsurltome = true, $preventredirect = false)
-
 
2775
{
2729
    global $CFG, $PAGE, $SITE;
2776
    global $CFG, $PAGE, $SITE;
2730
    $issite = ((is_object($courseorid) and $courseorid->id == SITEID)
2777
    $issite = ((is_object($courseorid) and $courseorid->id == SITEID)
2731
          or (!is_object($courseorid) and $courseorid == SITEID));
2778
        or (!is_object($courseorid) and $courseorid == SITEID));
2732
    if ($issite && !empty($cm) && !($cm instanceof cm_info)) {
2779
    if ($issite && !empty($cm) && !($cm instanceof cm_info)) {
2733
        // Note: nearly all pages call get_fast_modinfo anyway and it does not make any
2780
        // Note: nearly all pages call get_fast_modinfo anyway and it does not make any
2734
        // db queries so this is not really a performance concern, however it is obviously
2781
        // db queries so this is not really a performance concern, however it is obviously
2735
        // better if you use get_fast_modinfo to get the cm before calling this.
2782
        // better if you use get_fast_modinfo to get the cm before calling this.
2736
        if (is_object($courseorid)) {
2783
        if (is_object($courseorid)) {
2737
            $course = $courseorid;
2784
            $course = $courseorid;
2738
        } else {
2785
        } else {
2739
            $course = clone($SITE);
2786
            $course = clone ($SITE);
2740
        }
2787
        }
2741
        $modinfo = get_fast_modinfo($course);
2788
        $modinfo = get_fast_modinfo($course);
2742
        $cm = $modinfo->get_cm($cm->id);
2789
        $cm = $modinfo->get_cm($cm->id);
2743
    }
2790
    }
2744
    if (!empty($CFG->forcelogin)) {
2791
    if (!empty($CFG->forcelogin)) {
2745
        // Login required for both SITE and courses.
2792
        // Login required for both SITE and courses.
2746
        require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect);
2793
        require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect);
2747
 
-
 
2748
    } else if ($issite && !empty($cm) and !$cm->uservisible) {
2794
    } else if ($issite && !empty($cm) and !$cm->uservisible) {
2749
        // Always login for hidden activities.
2795
        // Always login for hidden activities.
2750
        require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect);
2796
        require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect);
2751
 
-
 
2752
    } else if (isloggedin() && !isguestuser()) {
2797
    } else if (isloggedin() && !isguestuser()) {
2753
        // User is already logged in. Make sure the login is complete (user is fully setup, policies agreed).
2798
        // User is already logged in. Make sure the login is complete (user is fully setup, policies agreed).
2754
        require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect);
2799
        require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect);
2755
 
-
 
2756
    } else if ($issite) {
2800
    } else if ($issite) {
2757
        // Login for SITE not required.
2801
        // Login for SITE not required.
2758
        // We still need to instatiate PAGE vars properly so that things that rely on it like navigation function correctly.
2802
        // We still need to instatiate PAGE vars properly so that things that rely on it like navigation function correctly.
2759
        if (!empty($courseorid)) {
2803
        if (!empty($courseorid)) {
2760
            if (is_object($courseorid)) {
2804
            if (is_object($courseorid)) {
Línea 2778... Línea 2822...
2778
        // Do not update access time for webservice or ajax requests.
2822
        // Do not update access time for webservice or ajax requests.
2779
        if (!WS_SERVER && !AJAX_SCRIPT) {
2823
        if (!WS_SERVER && !AJAX_SCRIPT) {
2780
            user_accesstime_log(SITEID);
2824
            user_accesstime_log(SITEID);
2781
        }
2825
        }
2782
        return;
2826
        return;
2783
 
-
 
2784
    } else {
2827
    } else {
2785
        // Course login always required.
2828
        // Course login always required.
2786
        require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect);
2829
        require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect);
2787
    }
2830
    }
2788
}
2831
}
Línea 2795... Línea 2838...
2795
 * @param  int $instance    instance id
2838
 * @param  int $instance    instance id
2796
 * @return stdClass the key entry in the user_private_key table
2839
 * @return stdClass the key entry in the user_private_key table
2797
 * @since Moodle 3.2
2840
 * @since Moodle 3.2
2798
 * @throws moodle_exception
2841
 * @throws moodle_exception
2799
 */
2842
 */
2800
function validate_user_key($keyvalue, $script, $instance) {
2843
function validate_user_key($keyvalue, $script, $instance)
-
 
2844
{
2801
    global $DB;
2845
    global $DB;
Línea 2802... Línea 2846...
2802
 
2846
 
2803
    if (!$key = $DB->get_record('user_private_key', array('script' => $script, 'value' => $keyvalue, 'instance' => $instance))) {
2847
    if (!$key = $DB->get_record('user_private_key', array('script' => $script, 'value' => $keyvalue, 'instance' => $instance))) {
2804
        throw new \moodle_exception('invalidkey');
2848
        throw new \moodle_exception('invalidkey');
Línea 2825... Línea 2869...
2825
 * @param string $script unique script identifier
2869
 * @param string $script unique script identifier
2826
 * @param int $instance optional instance id
2870
 * @param int $instance optional instance id
2827
 * @param string $keyvalue The key. If not supplied, this will be fetched from the current session.
2871
 * @param string $keyvalue The key. If not supplied, this will be fetched from the current session.
2828
 * @return int Instance ID
2872
 * @return int Instance ID
2829
 */
2873
 */
2830
function require_user_key_login($script, $instance = null, $keyvalue = null) {
2874
function require_user_key_login($script, $instance = null, $keyvalue = null)
-
 
2875
{
2831
    global $DB;
2876
    global $DB;
Línea 2832... Línea 2877...
2832
 
2877
 
2833
    if (!NO_MOODLE_COOKIES) {
2878
    if (!NO_MOODLE_COOKIES) {
2834
        throw new \moodle_exception('sessioncookiesdisable');
2879
        throw new \moodle_exception('sessioncookiesdisable');
Línea 2870... Línea 2915...
2870
 * @param int $instance optional instance id
2915
 * @param int $instance optional instance id
2871
 * @param string $iprestriction optional ip restricted access
2916
 * @param string $iprestriction optional ip restricted access
2872
 * @param int $validuntil key valid only until given data
2917
 * @param int $validuntil key valid only until given data
2873
 * @return string access key value
2918
 * @return string access key value
2874
 */
2919
 */
2875
function create_user_key($script, $userid, $instance=null, $iprestriction=null, $validuntil=null) {
2920
function create_user_key($script, $userid, $instance = null, $iprestriction = null, $validuntil = null)
-
 
2921
{
2876
    global $DB;
2922
    global $DB;
Línea 2877... Línea 2923...
2877
 
2923
 
2878
    $key = new stdClass();
2924
    $key = new stdClass();
2879
    $key->script        = $script;
2925
    $key->script        = $script;
Línea 2882... Línea 2928...
2882
    $key->iprestriction = $iprestriction;
2928
    $key->iprestriction = $iprestriction;
2883
    $key->validuntil    = $validuntil;
2929
    $key->validuntil    = $validuntil;
2884
    $key->timecreated   = time();
2930
    $key->timecreated   = time();
Línea 2885... Línea 2931...
2885
 
2931
 
2886
    // Something long and unique.
2932
    // Something long and unique.
2887
    $key->value         = md5($userid.'_'.time().random_string(40));
2933
    $key->value         = md5($userid . '_' . time() . random_string(40));
2888
    while ($DB->record_exists('user_private_key', array('value' => $key->value))) {
2934
    while ($DB->record_exists('user_private_key', array('value' => $key->value))) {
2889
        // Must be unique.
2935
        // Must be unique.
2890
        $key->value     = md5($userid.'_'.time().random_string(40));
2936
        $key->value     = md5($userid . '_' . time() . random_string(40));
2891
    }
2937
    }
2892
    $DB->insert_record('user_private_key', $key);
2938
    $DB->insert_record('user_private_key', $key);
2893
    return $key->value;
2939
    return $key->value;
Línea 2898... Línea 2944...
2898
 *
2944
 *
2899
 * @param string $script unique target identifier
2945
 * @param string $script unique target identifier
2900
 * @param int $userid
2946
 * @param int $userid
2901
 * @return void
2947
 * @return void
2902
 */
2948
 */
2903
function delete_user_key($script, $userid) {
2949
function delete_user_key($script, $userid)
-
 
2950
{
2904
    global $DB;
2951
    global $DB;
2905
    $DB->delete_records('user_private_key', array('script' => $script, 'userid' => $userid));
2952
    $DB->delete_records('user_private_key', array('script' => $script, 'userid' => $userid));
2906
}
2953
}
Línea 2907... Línea 2954...
2907
 
2954
 
Línea 2913... Línea 2960...
2913
 * @param int $instance optional instance id
2960
 * @param int $instance optional instance id
2914
 * @param string $iprestriction optional ip restricted access
2961
 * @param string $iprestriction optional ip restricted access
2915
 * @param int $validuntil key valid only until given date
2962
 * @param int $validuntil key valid only until given date
2916
 * @return string access key value
2963
 * @return string access key value
2917
 */
2964
 */
2918
function get_user_key($script, $userid, $instance=null, $iprestriction=null, $validuntil=null) {
2965
function get_user_key($script, $userid, $instance = null, $iprestriction = null, $validuntil = null)
-
 
2966
{
2919
    global $DB;
2967
    global $DB;
Línea 2920... Línea 2968...
2920
 
2968
 
-
 
2969
    if ($key = $DB->get_record('user_private_key', array(
-
 
2970
        'script' => $script,
-
 
2971
        'userid' => $userid,
2921
    if ($key = $DB->get_record('user_private_key', array('script' => $script, 'userid' => $userid,
2972
        'instance' => $instance,
2922
                                                         'instance' => $instance, 'iprestriction' => $iprestriction,
2973
        'iprestriction' => $iprestriction,
-
 
2974
        'validuntil' => $validuntil
2923
                                                         'validuntil' => $validuntil))) {
2975
    ))) {
2924
        return $key->value;
2976
        return $key->value;
2925
    } else {
2977
    } else {
2926
        return create_user_key($script, $userid, $instance, $iprestriction, $validuntil);
2978
        return create_user_key($script, $userid, $instance, $iprestriction, $validuntil);
2927
    }
2979
    }
Línea 2931... Línea 2983...
2931
/**
2983
/**
2932
 * Modify the user table by setting the currently logged in user's last login to now.
2984
 * Modify the user table by setting the currently logged in user's last login to now.
2933
 *
2985
 *
2934
 * @return bool Always returns true
2986
 * @return bool Always returns true
2935
 */
2987
 */
2936
function update_user_login_times() {
2988
function update_user_login_times()
-
 
2989
{
2937
    global $USER, $DB, $SESSION;
2990
    global $USER, $DB, $SESSION;
Línea 2938... Línea 2991...
2938
 
2991
 
2939
    if (isguestuser()) {
2992
    if (isguestuser()) {
2940
        // Do not update guest access times/ips for performance.
2993
        // Do not update guest access times/ips for performance.
Línea 2983... Línea 3036...
2983
 *
3036
 *
2984
 * @param stdClass $user A {@link $USER} object to test for the existence of a valid name and email
3037
 * @param stdClass $user A {@link $USER} object to test for the existence of a valid name and email
2985
 * @param bool $strict Be more strict and assert id and custom profile fields set, too
3038
 * @param bool $strict Be more strict and assert id and custom profile fields set, too
2986
 * @return bool
3039
 * @return bool
2987
 */
3040
 */
2988
function user_not_fully_set_up($user, $strict = true) {
3041
function user_not_fully_set_up($user, $strict = true)
-
 
3042
{
2989
    global $CFG, $SESSION, $USER;
3043
    global $CFG, $SESSION, $USER;
2990
    require_once($CFG->dirroot.'/user/profile/lib.php');
3044
    require_once($CFG->dirroot . '/user/profile/lib.php');
Línea 2991... Línea 3045...
2991
 
3045
 
2992
    // If the user is setup then store this in the session to avoid re-checking.
3046
    // If the user is setup then store this in the session to avoid re-checking.
2993
    // Some edge cases are when the users email starts to bounce or the
3047
    // Some edge cases are when the users email starts to bounce or the
2994
    // configuration for custom fields has changed while they are logged in so
3048
    // configuration for custom fields has changed while they are logged in so
-
 
3049
    // we re-check this fully every hour for the rare cases it has changed.
2995
    // we re-check this fully every hour for the rare cases it has changed.
3050
    if (
2996
    if (isset($USER->id) && isset($user->id) && $USER->id === $user->id &&
3051
        isset($USER->id) && isset($user->id) && $USER->id === $user->id &&
-
 
3052
        isset($SESSION->fullysetupstrict) && (time() - $SESSION->fullysetupstrict) < HOURSECS
2997
         isset($SESSION->fullysetupstrict) && (time() - $SESSION->fullysetupstrict) < HOURSECS) {
3053
    ) {
2998
        return false;
3054
        return false;
Línea 2999... Línea 3055...
2999
    }
3055
    }
3000
 
3056
 
Línea 3026... Línea 3082...
3026
 * Check whether the user has exceeded the bounce threshold
3082
 * Check whether the user has exceeded the bounce threshold
3027
 *
3083
 *
3028
 * @param stdClass $user A {@link $USER} object
3084
 * @param stdClass $user A {@link $USER} object
3029
 * @return bool true => User has exceeded bounce threshold
3085
 * @return bool true => User has exceeded bounce threshold
3030
 */
3086
 */
3031
function over_bounce_threshold($user) {
3087
function over_bounce_threshold($user)
-
 
3088
{
3032
    global $CFG, $DB;
3089
    global $CFG, $DB;
Línea 3033... Línea 3090...
3033
 
3090
 
3034
    if (empty($CFG->handlebounces)) {
3091
    if (empty($CFG->handlebounces)) {
3035
        return false;
3092
        return false;
Línea 3047... Línea 3104...
3047
    if (empty($CFG->bounceratio)) {
3104
    if (empty($CFG->bounceratio)) {
3048
        $CFG->bounceratio = .20;
3105
        $CFG->bounceratio = .20;
3049
    }
3106
    }
3050
    $bouncecount = 0;
3107
    $bouncecount = 0;
3051
    $sendcount = 0;
3108
    $sendcount = 0;
3052
    if ($bounce = $DB->get_record('user_preferences', array ('userid' => $user->id, 'name' => 'email_bounce_count'))) {
3109
    if ($bounce = $DB->get_record('user_preferences', array('userid' => $user->id, 'name' => 'email_bounce_count'))) {
3053
        $bouncecount = $bounce->value;
3110
        $bouncecount = $bounce->value;
3054
    }
3111
    }
3055
    if ($send = $DB->get_record('user_preferences', array('userid' => $user->id, 'name' => 'email_send_count'))) {
3112
    if ($send = $DB->get_record('user_preferences', array('userid' => $user->id, 'name' => 'email_send_count'))) {
3056
        $sendcount = $send->value;
3113
        $sendcount = $send->value;
3057
    }
3114
    }
3058
    return ($bouncecount >= $CFG->minbounces && $bouncecount/$sendcount >= $CFG->bounceratio);
3115
    return ($bouncecount >= $CFG->minbounces && $bouncecount / $sendcount >= $CFG->bounceratio);
3059
}
3116
}
Línea 3060... Línea 3117...
3060
 
3117
 
3061
/**
3118
/**
3062
 * Used to increment or reset email sent count
3119
 * Used to increment or reset email sent count
3063
 *
3120
 *
3064
 * @param stdClass $user object containing an id
3121
 * @param stdClass $user object containing an id
3065
 * @param bool $reset will reset the count to 0
3122
 * @param bool $reset will reset the count to 0
3066
 * @return void
3123
 * @return void
3067
 */
3124
 */
-
 
3125
function set_send_count($user, $reset = false)
3068
function set_send_count($user, $reset=false) {
3126
{
Línea 3069... Línea 3127...
3069
    global $DB;
3127
    global $DB;
3070
 
3128
 
3071
    if (empty($user->id)) {
3129
    if (empty($user->id)) {
3072
        // No real (DB) user, nothing to do here.
3130
        // No real (DB) user, nothing to do here.
Línea 3073... Línea 3131...
3073
        return;
3131
        return;
3074
    }
3132
    }
3075
 
3133
 
3076
    if ($pref = $DB->get_record('user_preferences', array('userid' => $user->id, 'name' => 'email_send_count'))) {
3134
    if ($pref = $DB->get_record('user_preferences', array('userid' => $user->id, 'name' => 'email_send_count'))) {
3077
        $pref->value = (!empty($reset)) ? 0 : $pref->value+1;
3135
        $pref->value = (!empty($reset)) ? 0 : $pref->value + 1;
3078
        $DB->update_record('user_preferences', $pref);
3136
        $DB->update_record('user_preferences', $pref);
3079
    } else if (!empty($reset)) {
3137
    } else if (!empty($reset)) {
Línea 3090... Línea 3148...
3090
 * Increment or reset user's email bounce count
3148
 * Increment or reset user's email bounce count
3091
 *
3149
 *
3092
 * @param stdClass $user object containing an id
3150
 * @param stdClass $user object containing an id
3093
 * @param bool $reset will reset the count to 0
3151
 * @param bool $reset will reset the count to 0
3094
 */
3152
 */
3095
function set_bounce_count($user, $reset=false) {
3153
function set_bounce_count($user, $reset = false)
-
 
3154
{
3096
    global $DB;
3155
    global $DB;
Línea 3097... Línea 3156...
3097
 
3156
 
3098
    if ($pref = $DB->get_record('user_preferences', array('userid' => $user->id, 'name' => 'email_bounce_count'))) {
3157
    if ($pref = $DB->get_record('user_preferences', array('userid' => $user->id, 'name' => 'email_bounce_count'))) {
3099
        $pref->value = (!empty($reset)) ? 0 : $pref->value+1;
3158
        $pref->value = (!empty($reset)) ? 0 : $pref->value + 1;
3100
        $DB->update_record('user_preferences', $pref);
3159
        $DB->update_record('user_preferences', $pref);
3101
    } else if (!empty($reset)) {
3160
    } else if (!empty($reset)) {
3102
        // If it's not there and we're resetting, don't bother. Make a new one.
3161
        // If it's not there and we're resetting, don't bother. Make a new one.
3103
        $pref = new stdClass();
3162
        $pref = new stdClass();
Línea 3112... Línea 3171...
3112
 * Determines if the logged in user is currently moving an activity
3171
 * Determines if the logged in user is currently moving an activity
3113
 *
3172
 *
3114
 * @param int $courseid The id of the course being tested
3173
 * @param int $courseid The id of the course being tested
3115
 * @return bool
3174
 * @return bool
3116
 */
3175
 */
3117
function ismoving($courseid) {
3176
function ismoving($courseid)
-
 
3177
{
3118
    global $USER;
3178
    global $USER;
Línea 3119... Línea 3179...
3119
 
3179
 
3120
    if (!empty($USER->activitycopy)) {
3180
    if (!empty($USER->activitycopy)) {
3121
        return ($USER->activitycopycourse == $courseid);
3181
        return ($USER->activitycopycourse == $courseid);
Línea 3133... Línea 3193...
3133
 *
3193
 *
3134
 * @param stdClass $user A {@link $USER} object to get full name of.
3194
 * @param stdClass $user A {@link $USER} object to get full name of.
3135
 * @param bool $override If true then the alternativefullnameformat format rather than fullnamedisplay format will be used.
3195
 * @param bool $override If true then the alternativefullnameformat format rather than fullnamedisplay format will be used.
3136
 * @return string
3196
 * @return string
3137
 */
3197
 */
3138
function fullname($user, $override=false) {
3198
function fullname($user, $override = false)
-
 
3199
{
3139
    // Note: We do not intend to deprecate this function any time soon as it is too widely used at this time.
3200
    // Note: We do not intend to deprecate this function any time soon as it is too widely used at this time.
3140
    // Uses of it should be updated to use the new API and pass updated arguments.
3201
    // Uses of it should be updated to use the new API and pass updated arguments.
Línea 3141... Línea 3202...
3141
 
3202
 
3142
    // Return an empty string if there is no user.
3203
    // Return an empty string if there is no user.
Línea 3158... Línea 3219...
3158
 * @param string $prefix prefix to be added to all fields (including $additionalfields) e.g. authorfirstname.
3219
 * @param string $prefix prefix to be added to all fields (including $additionalfields) e.g. authorfirstname.
3159
 * @param array $additionalfields Additional fields to be matched with data in the second object.
3220
 * @param array $additionalfields Additional fields to be matched with data in the second object.
3160
 * The key can be set to the user table field name.
3221
 * The key can be set to the user table field name.
3161
 * @return object User name fields.
3222
 * @return object User name fields.
3162
 */
3223
 */
3163
function username_load_fields_from_object($addtoobject, $secondobject, $prefix = null, $additionalfields = null) {
3224
function username_load_fields_from_object($addtoobject, $secondobject, $prefix = null, $additionalfields = null)
-
 
3225
{
3164
    $fields = [];
3226
    $fields = [];
3165
    foreach (\core_user\fields::get_name_fields() as $field) {
3227
    foreach (\core_user\fields::get_name_fields() as $field) {
3166
        $fields[$field] = $prefix . $field;
3228
        $fields[$field] = $prefix . $field;
3167
    }
3229
    }
3168
    if ($additionalfields) {
3230
    if ($additionalfields) {
Línea 3194... Línea 3256...
3194
 *
3256
 *
3195
 * @param array $values Values to be found in the string format
3257
 * @param array $values Values to be found in the string format
3196
 * @param string $stringformat The string which may contain values being searched for.
3258
 * @param string $stringformat The string which may contain values being searched for.
3197
 * @return array An array of values in order according to placement in the string format.
3259
 * @return array An array of values in order according to placement in the string format.
3198
 */
3260
 */
3199
function order_in_string($values, $stringformat) {
3261
function order_in_string($values, $stringformat)
-
 
3262
{
3200
    $valuearray = array();
3263
    $valuearray = array();
3201
    foreach ($values as $value) {
3264
    foreach ($values as $value) {
3202
        $pattern = "/$value\b/";
3265
        $pattern = "/$value\b/";
3203
        // Using preg_match as strpos() may match values that are similar e.g. firstname and firstnamephonetic.
3266
        // Using preg_match as strpos() may match values that are similar e.g. firstname and firstnamephonetic.
3204
        if (preg_match($pattern, $stringformat)) {
3267
        if (preg_match($pattern, $stringformat)) {
Línea 3217... Línea 3280...
3217
 * Returns whether a given authentication plugin exists.
3280
 * Returns whether a given authentication plugin exists.
3218
 *
3281
 *
3219
 * @param string $auth Form of authentication to check for. Defaults to the global setting in {@link $CFG}.
3282
 * @param string $auth Form of authentication to check for. Defaults to the global setting in {@link $CFG}.
3220
 * @return boolean Whether the plugin is available.
3283
 * @return boolean Whether the plugin is available.
3221
 */
3284
 */
3222
function exists_auth_plugin($auth) {
3285
function exists_auth_plugin($auth)
-
 
3286
{
3223
    global $CFG;
3287
    global $CFG;
Línea 3224... Línea 3288...
3224
 
3288
 
3225
    if (file_exists("{$CFG->dirroot}/auth/$auth/auth.php")) {
3289
    if (file_exists("{$CFG->dirroot}/auth/$auth/auth.php")) {
3226
        return is_readable("{$CFG->dirroot}/auth/$auth/auth.php");
3290
        return is_readable("{$CFG->dirroot}/auth/$auth/auth.php");
Línea 3232... Línea 3296...
3232
 * Checks if a given plugin is in the list of enabled authentication plugins.
3296
 * Checks if a given plugin is in the list of enabled authentication plugins.
3233
 *
3297
 *
3234
 * @param string $auth Authentication plugin.
3298
 * @param string $auth Authentication plugin.
3235
 * @return boolean Whether the plugin is enabled.
3299
 * @return boolean Whether the plugin is enabled.
3236
 */
3300
 */
3237
function is_enabled_auth($auth) {
3301
function is_enabled_auth($auth)
-
 
3302
{
3238
    if (empty($auth)) {
3303
    if (empty($auth)) {
3239
        return false;
3304
        return false;
3240
    }
3305
    }
Línea 3241... Línea 3306...
3241
 
3306
 
Línea 3248... Línea 3313...
3248
 * Returns an authentication plugin instance.
3313
 * Returns an authentication plugin instance.
3249
 *
3314
 *
3250
 * @param string $auth name of authentication plugin
3315
 * @param string $auth name of authentication plugin
3251
 * @return auth_plugin_base An instance of the required authentication plugin.
3316
 * @return auth_plugin_base An instance of the required authentication plugin.
3252
 */
3317
 */
3253
function get_auth_plugin($auth) {
3318
function get_auth_plugin($auth)
-
 
3319
{
3254
    global $CFG;
3320
    global $CFG;
Línea 3255... Línea 3321...
3255
 
3321
 
3256
    // Check the plugin exists first.
3322
    // Check the plugin exists first.
3257
    if (! exists_auth_plugin($auth)) {
3323
    if (! exists_auth_plugin($auth)) {
Línea 3268... Línea 3334...
3268
 * Returns array of active auth plugins.
3334
 * Returns array of active auth plugins.
3269
 *
3335
 *
3270
 * @param bool $fix fix $CFG->auth if needed. Only set if logged in as admin.
3336
 * @param bool $fix fix $CFG->auth if needed. Only set if logged in as admin.
3271
 * @return array
3337
 * @return array
3272
 */
3338
 */
3273
function get_enabled_auth_plugins($fix=false) {
3339
function get_enabled_auth_plugins($fix = false)
-
 
3340
{
3274
    global $CFG;
3341
    global $CFG;
Línea 3275... Línea 3342...
3275
 
3342
 
Línea 3276... Línea 3343...
3276
    $default = array('manual', 'nologin');
3343
    $default = array('manual', 'nologin');
Línea 3311... Línea 3378...
3311
 * if method not specified then, global default is assumed
3378
 * if method not specified then, global default is assumed
3312
 *
3379
 *
3313
 * @param string $auth Form of authentication required
3380
 * @param string $auth Form of authentication required
3314
 * @return bool
3381
 * @return bool
3315
 */
3382
 */
3316
function is_internal_auth($auth) {
3383
function is_internal_auth($auth)
-
 
3384
{
3317
    // Throws error if bad $auth.
3385
    // Throws error if bad $auth.
3318
    $authplugin = get_auth_plugin($auth);
3386
    $authplugin = get_auth_plugin($auth);
3319
    return $authplugin->is_internal();
3387
    return $authplugin->is_internal();
3320
}
3388
}
Línea 3325... Línea 3393...
3325
 * Used in the login process to inform the user and allow him/her to reset the password
3393
 * Used in the login process to inform the user and allow him/her to reset the password
3326
 *
3394
 *
3327
 * @param string $username username to be checked
3395
 * @param string $username username to be checked
3328
 * @return bool
3396
 * @return bool
3329
 */
3397
 */
3330
function is_restored_user($username) {
3398
function is_restored_user($username)
-
 
3399
{
3331
    global $CFG, $DB;
3400
    global $CFG, $DB;
Línea 3332... Línea 3401...
3332
 
3401
 
3333
    return $DB->record_exists('user', array('username' => $username, 'mnethostid' => $CFG->mnet_localhost_id, 'password' => 'restored'));
3402
    return $DB->record_exists('user', array('username' => $username, 'mnethostid' => $CFG->mnet_localhost_id, 'password' => 'restored'));
Línea 3334... Línea 3403...
3334
}
3403
}
3335
 
3404
 
3336
/**
3405
/**
3337
 * Returns an array of user fields
3406
 * Returns an array of user fields
3338
 *
3407
 *
3339
 * @return array User field/column names
3408
 * @return array User field/column names
-
 
3409
 */
3340
 */
3410
function get_user_fieldnames()
Línea 3341... Línea 3411...
3341
function get_user_fieldnames() {
3411
{
3342
    global $DB;
3412
    global $DB;
3343
 
3413
 
Línea 3351... Línea 3421...
3351
/**
3421
/**
3352
 * Returns the string of the language for the new user.
3422
 * Returns the string of the language for the new user.
3353
 *
3423
 *
3354
 * @return string language for the new user
3424
 * @return string language for the new user
3355
 */
3425
 */
3356
function get_newuser_language() {
3426
function get_newuser_language()
-
 
3427
{
3357
    global $CFG, $SESSION;
3428
    global $CFG, $SESSION;
3358
    return (!empty($CFG->autolangusercreation) && !empty($SESSION->lang)) ? $SESSION->lang : $CFG->lang;
3429
    return (!empty($CFG->autolangusercreation) && !empty($SESSION->lang)) ? $SESSION->lang : $CFG->lang;
3359
}
3430
}
Línea 3360... Línea 3431...
3360
 
3431
 
Línea 3366... Línea 3437...
3366
 * @param string $username New user's username to add to record
3437
 * @param string $username New user's username to add to record
3367
 * @param string $password New user's password to add to record
3438
 * @param string $password New user's password to add to record
3368
 * @param string $auth Form of authentication required
3439
 * @param string $auth Form of authentication required
3369
 * @return stdClass A complete user object
3440
 * @return stdClass A complete user object
3370
 */
3441
 */
3371
function create_user_record($username, $password, $auth = 'manual') {
3442
function create_user_record($username, $password, $auth = 'manual')
-
 
3443
{
3372
    global $CFG, $DB, $SESSION;
3444
    global $CFG, $DB, $SESSION;
3373
    require_once($CFG->dirroot.'/user/profile/lib.php');
3445
    require_once($CFG->dirroot . '/user/profile/lib.php');
3374
    require_once($CFG->dirroot.'/user/lib.php');
3446
    require_once($CFG->dirroot . '/user/lib.php');
Línea 3375... Línea 3447...
3375
 
3447
 
3376
    // Just in case check text case.
3448
    // Just in case check text case.
Línea 3377... Línea 3449...
3377
    $username = trim(core_text::strtolower($username));
3449
    $username = trim(core_text::strtolower($username));
Línea 3413... Línea 3485...
3413
 
3485
 
3414
    // Save user profile data.
3486
    // Save user profile data.
Línea 3415... Línea 3487...
3415
    profile_save_data($newuser);
3487
    profile_save_data($newuser);
3416
 
3488
 
3417
    $user = get_complete_user_data('id', $newuser->id);
3489
    $user = get_complete_user_data('id', $newuser->id);
3418
    if (!empty($CFG->{'auth_'.$newuser->auth.'_forcechangepassword'})) {
3490
    if (!empty($CFG->{'auth_' . $newuser->auth . '_forcechangepassword'})) {
3419
        set_user_preference('auth_forcepasswordchange', 1, $user);
3491
        set_user_preference('auth_forcepasswordchange', 1, $user);
3420
    }
3492
    }
Línea 3431... Línea 3503...
3431
 * Will update a local user record from an external source (MNET users can not be updated using this method!).
3503
 * Will update a local user record from an external source (MNET users can not be updated using this method!).
3432
 *
3504
 *
3433
 * @param string $username user's username to update the record
3505
 * @param string $username user's username to update the record
3434
 * @return stdClass A complete user object
3506
 * @return stdClass A complete user object
3435
 */
3507
 */
3436
function update_user_record($username) {
3508
function update_user_record($username)
-
 
3509
{
3437
    global $DB, $CFG;
3510
    global $DB, $CFG;
3438
    // Just in case check text case.
3511
    // Just in case check text case.
3439
    $username = trim(core_text::strtolower($username));
3512
    $username = trim(core_text::strtolower($username));
Línea 3440... Línea 3513...
3440
 
3513
 
Línea 3446... Línea 3519...
3446
 * Will update a local user record from an external source (MNET users can not be updated using this method!).
3519
 * Will update a local user record from an external source (MNET users can not be updated using this method!).
3447
 *
3520
 *
3448
 * @param int $id user id
3521
 * @param int $id user id
3449
 * @return stdClass A complete user object
3522
 * @return stdClass A complete user object
3450
 */
3523
 */
3451
function update_user_record_by_id($id) {
3524
function update_user_record_by_id($id)
-
 
3525
{
3452
    global $DB, $CFG;
3526
    global $DB, $CFG;
3453
    require_once($CFG->dirroot."/user/profile/lib.php");
3527
    require_once($CFG->dirroot . "/user/profile/lib.php");
3454
    require_once($CFG->dirroot.'/user/lib.php');
3528
    require_once($CFG->dirroot . '/user/lib.php');
Línea 3455... Línea 3529...
3455
 
3529
 
3456
    $params = array('mnethostid' => $CFG->mnet_localhost_id, 'id' => $id, 'deleted' => 0);
3530
    $params = array('mnethostid' => $CFG->mnet_localhost_id, 'id' => $id, 'deleted' => 0);
Línea 3457... Línea 3531...
3457
    $oldinfo = $DB->get_record('user', $params, '*', MUST_EXIST);
3531
    $oldinfo = $DB->get_record('user', $params, '*', MUST_EXIST);
Línea 3467... Línea 3541...
3467
            $iscustom = in_array($key, $customfields);
3541
            $iscustom = in_array($key, $customfields);
3468
            if (!$iscustom) {
3542
            if (!$iscustom) {
3469
                $key = strtolower($key);
3543
                $key = strtolower($key);
3470
            }
3544
            }
3471
            if ((!property_exists($oldinfo, $key) && !$iscustom) or $key === 'username' or $key === 'id'
3545
            if ((!property_exists($oldinfo, $key) && !$iscustom) or $key === 'username' or $key === 'id'
3472
                    or $key === 'auth' or $key === 'mnethostid' or $key === 'deleted') {
3546
                or $key === 'auth' or $key === 'mnethostid' or $key === 'deleted'
-
 
3547
            ) {
3473
                // Unknown or must not be changed.
3548
                // Unknown or must not be changed.
3474
                continue;
3549
                continue;
3475
            }
3550
            }
3476
            if (empty($userauth->config->{'field_updatelocal_' . $key}) || empty($userauth->config->{'field_lock_' . $key})) {
3551
            if (empty($userauth->config->{'field_updatelocal_' . $key}) || empty($userauth->config->{'field_lock_' . $key})) {
3477
                continue;
3552
                continue;
Línea 3485... Línea 3560...
3485
                // in a value for the selected field _if LDAP is giving
3560
                // in a value for the selected field _if LDAP is giving
3486
                // nothing_ for this field. Thus it makes sense to let this value
3561
                // nothing_ for this field. Thus it makes sense to let this value
3487
                // stand in until LDAP is giving a value for this field.
3562
                // stand in until LDAP is giving a value for this field.
3488
                if (!(empty($value) && $lockval === 'unlockedifempty')) {
3563
                if (!(empty($value) && $lockval === 'unlockedifempty')) {
3489
                    if ($iscustom || (in_array($key, $userauth->userfields) &&
3564
                    if ($iscustom || (in_array($key, $userauth->userfields) &&
3490
                            ((string)$oldinfo->$key !== (string)$value))) {
3565
                        ((string)$oldinfo->$key !== (string)$value))) {
3491
                        $newuser[$key] = (string)$value;
3566
                        $newuser[$key] = (string)$value;
3492
                    }
3567
                    }
3493
                }
3568
                }
3494
            }
3569
            }
3495
        }
3570
        }
Línea 3513... Línea 3588...
3513
 * Will truncate userinfo as it comes from auth_get_userinfo (from external auth) which may have large fields.
3588
 * Will truncate userinfo as it comes from auth_get_userinfo (from external auth) which may have large fields.
3514
 *
3589
 *
3515
 * @param array $info Array of user properties to truncate if needed
3590
 * @param array $info Array of user properties to truncate if needed
3516
 * @return array The now truncated information that was passed in
3591
 * @return array The now truncated information that was passed in
3517
 */
3592
 */
3518
function truncate_userinfo(array $info) {
3593
function truncate_userinfo(array $info)
-
 
3594
{
3519
    // Define the limits.
3595
    // Define the limits.
3520
    $limit = array(
3596
    $limit = array(
3521
        'username'    => 100,
3597
        'username'    => 100,
3522
        'idnumber'    => 255,
3598
        'idnumber'    => 255,
3523
        'firstname'   => 100,
3599
        'firstname'   => 100,
Línea 3550... Línea 3626...
3550
 *
3626
 *
3551
 * @param stdClass $user full user object before delete
3627
 * @param stdClass $user full user object before delete
3552
 * @return boolean success
3628
 * @return boolean success
3553
 * @throws coding_exception if invalid $user parameter detected
3629
 * @throws coding_exception if invalid $user parameter detected
3554
 */
3630
 */
3555
function delete_user(stdClass $user) {
3631
function delete_user(stdClass $user)
-
 
3632
{
3556
    global $CFG, $DB, $SESSION;
3633
    global $CFG, $DB, $SESSION;
3557
    require_once($CFG->libdir.'/grouplib.php');
3634
    require_once($CFG->libdir . '/grouplib.php');
3558
    require_once($CFG->libdir.'/gradelib.php');
3635
    require_once($CFG->libdir . '/gradelib.php');
3559
    require_once($CFG->dirroot.'/message/lib.php');
3636
    require_once($CFG->dirroot . '/message/lib.php');
3560
    require_once($CFG->dirroot.'/user/lib.php');
3637
    require_once($CFG->dirroot . '/user/lib.php');
Línea 3561... Línea 3638...
3561
 
3638
 
3562
    // Make sure nobody sends bogus record type as parameter.
3639
    // Make sure nobody sends bogus record type as parameter.
3563
    if (!property_exists($user, 'id') or !property_exists($user, 'username')) {
3640
    if (!property_exists($user, 'id') or !property_exists($user, 'username')) {
3564
        throw new coding_exception('Invalid $user parameter in delete_user() detected');
3641
        throw new coding_exception('Invalid $user parameter in delete_user() detected');
Línea 3702... Línea 3779...
3702
    // Mark internal user record as "deleted".
3779
    // Mark internal user record as "deleted".
3703
    $updateuser = new stdClass();
3780
    $updateuser = new stdClass();
3704
    $updateuser->id           = $user->id;
3781
    $updateuser->id           = $user->id;
3705
    $updateuser->deleted      = 1;
3782
    $updateuser->deleted      = 1;
3706
    $updateuser->username     = $delname;            // Remember it just in case.
3783
    $updateuser->username     = $delname;            // Remember it just in case.
3707
    $updateuser->email        = md5($user->username);// Store hash of username, useful importing/restoring users.
3784
    $updateuser->email        = md5($user->username); // Store hash of username, useful importing/restoring users.
3708
    $updateuser->idnumber     = '';                  // Clear this field to free it up.
3785
    $updateuser->idnumber     = '';                  // Clear this field to free it up.
3709
    $updateuser->picture      = 0;
3786
    $updateuser->picture      = 0;
3710
    $updateuser->timemodified = $deltime;
3787
    $updateuser->timemodified = $deltime;
Línea 3711... Línea 3788...
3711
 
3788
 
Línea 3719... Línea 3796...
3719
    \core_search\manager::context_deleted($usercontext);
3796
    \core_search\manager::context_deleted($usercontext);
Línea 3720... Línea 3797...
3720
 
3797
 
3721
    // Any plugin that needs to cleanup should register this event.
3798
    // Any plugin that needs to cleanup should register this event.
3722
    // Trigger event.
3799
    // Trigger event.
3723
    $event = \core\event\user_deleted::create(
3800
    $event = \core\event\user_deleted::create(
3724
            array(
3801
        array(
3725
                'objectid' => $user->id,
3802
            'objectid' => $user->id,
3726
                'relateduserid' => $user->id,
3803
            'relateduserid' => $user->id,
3727
                'context' => $usercontext,
3804
            'context' => $usercontext,
3728
                'other' => array(
3805
            'other' => array(
3729
                    'username' => $user->username,
3806
                'username' => $user->username,
3730
                    'email' => $user->email,
3807
                'email' => $user->email,
3731
                    'idnumber' => $user->idnumber,
3808
                'idnumber' => $user->idnumber,
3732
                    'picture' => $user->picture,
3809
                'picture' => $user->picture,
3733
                    'mnethostid' => $user->mnethostid
3810
                'mnethostid' => $user->mnethostid
3734
                    )
3811
            )
3735
                )
3812
        )
3736
            );
3813
    );
3737
    $event->add_record_snapshot('user', $olduser);
3814
    $event->add_record_snapshot('user', $olduser);
Línea 3738... Línea 3815...
3738
    $event->trigger();
3815
    $event->trigger();
3739
 
3816
 
Línea 3751... Línea 3828...
3751
/**
3828
/**
3752
 * Retrieve the guest user object.
3829
 * Retrieve the guest user object.
3753
 *
3830
 *
3754
 * @return stdClass A {@link $USER} object
3831
 * @return stdClass A {@link $USER} object
3755
 */
3832
 */
3756
function guest_user() {
3833
function guest_user()
-
 
3834
{
3757
    global $CFG, $DB;
3835
    global $CFG, $DB;
Línea 3758... Línea 3836...
3758
 
3836
 
3759
    if ($newuser = $DB->get_record('user', array('id' => $CFG->siteguest))) {
3837
    if ($newuser = $DB->get_record('user', array('id' => $CFG->siteguest))) {
3760
        $newuser->confirmed = 1;
3838
        $newuser->confirmed = 1;
Línea 3829... Línea 3907...
3829
                'username' => $username,
3907
                'username' => $username,
3830
                'reason' => $failurereason,
3908
                'reason' => $failurereason,
3831
            ],
3909
            ],
3832
        ])->trigger();
3910
        ])->trigger();
Línea 3833... Línea 3911...
3833
 
3911
 
3834
        error_log('[client '.getremoteaddr()."]  $CFG->wwwroot  Invalid Login Token:  $username  ".$_SERVER['HTTP_USER_AGENT']);
3912
        error_log('[client ' . getremoteaddr() . "]  $CFG->wwwroot  Invalid Login Token:  $username  " . $_SERVER['HTTP_USER_AGENT']);
3835
        return false;
3913
        return false;
Línea 3836... Línea 3914...
3836
    }
3914
    }
3837
 
3915
 
Línea 3862... Línea 3940...
3862
 
3940
 
3863
        if (!empty($user->suspended)) {
3941
        if (!empty($user->suspended)) {
Línea 3864... Línea 3942...
3864
            $failurereason = AUTH_LOGIN_SUSPENDED;
3942
            $failurereason = AUTH_LOGIN_SUSPENDED;
3865
 
3943
 
-
 
3944
            // Trigger login failed event.
3866
            // Trigger login failed event.
3945
            $event = \core\event\user_login_failed::create(array(
-
 
3946
                'userid' => $user->id,
3867
            $event = \core\event\user_login_failed::create(array('userid' => $user->id,
3947
                'other' => array('username' => $username, 'reason' => $failurereason)
3868
                    'other' => array('username' => $username, 'reason' => $failurereason)));
3948
            ));
3869
            $event->trigger();
3949
            $event->trigger();
3870
            error_log('[client '.getremoteaddr()."]  $CFG->wwwroot  Suspended Login:  $username  ".$_SERVER['HTTP_USER_AGENT']);
3950
            error_log('[client ' . getremoteaddr() . "]  $CFG->wwwroot  Suspended Login:  $username  " . $_SERVER['HTTP_USER_AGENT']);
3871
            return false;
3951
            return false;
3872
        }
3952
        }
3873
        if ($auth=='nologin' or !is_enabled_auth($auth)) {
3953
        if ($auth == 'nologin' or !is_enabled_auth($auth)) {
Línea 3874... Línea 3954...
3874
            // Legacy way to suspend user.
3954
            // Legacy way to suspend user.
3875
            $failurereason = AUTH_LOGIN_SUSPENDED;
3955
            $failurereason = AUTH_LOGIN_SUSPENDED;
-
 
3956
 
3876
 
3957
            // Trigger login failed event.
-
 
3958
            $event = \core\event\user_login_failed::create(array(
3877
            // Trigger login failed event.
3959
                'userid' => $user->id,
3878
            $event = \core\event\user_login_failed::create(array('userid' => $user->id,
3960
                'other' => array('username' => $username, 'reason' => $failurereason)
3879
                    'other' => array('username' => $username, 'reason' => $failurereason)));
3961
            ));
3880
            $event->trigger();
3962
            $event->trigger();
3881
            error_log('[client '.getremoteaddr()."]  $CFG->wwwroot  Disabled Login:  $username  ".$_SERVER['HTTP_USER_AGENT']);
3963
            error_log('[client ' . getremoteaddr() . "]  $CFG->wwwroot  Disabled Login:  $username  " . $_SERVER['HTTP_USER_AGENT']);
3882
            return false;
-
 
3883
        }
3964
            return false;
3884
        $auths = array($auth);
3965
        }
3885
 
3966
        $auths = array($auth);
3886
    } else {
3967
    } else {
Línea 3887... Línea 3968...
3887
        // Check if there's a deleted record (cheaply), this should not happen because we mangle usernames in delete_user().
3968
        // Check if there's a deleted record (cheaply), this should not happen because we mangle usernames in delete_user().
3888
        if ($DB->get_field('user', 'id', array('username' => $username, 'mnethostid' => $CFG->mnet_localhost_id,  'deleted' => 1))) {
3969
        if ($DB->get_field('user', 'id', array('username' => $username, 'mnethostid' => $CFG->mnet_localhost_id,  'deleted' => 1))) {
-
 
3970
            $failurereason = AUTH_LOGIN_NOUSER;
3889
            $failurereason = AUTH_LOGIN_NOUSER;
3971
 
-
 
3972
            // Trigger login failed event.
3890
 
3973
            $event = \core\event\user_login_failed::create(array('other' => array(
3891
            // Trigger login failed event.
3974
                'username' => $username,
3892
            $event = \core\event\user_login_failed::create(array('other' => array('username' => $username,
3975
                'reason' => $failurereason
3893
                    'reason' => $failurereason)));
3976
            )));
Línea 3894... Línea 3977...
3894
            $event->trigger();
3977
            $event->trigger();
3895
            error_log('[client '.getremoteaddr()."]  $CFG->wwwroot  Deleted Login:  $username  ".$_SERVER['HTTP_USER_AGENT']);
3978
            error_log('[client ' . getremoteaddr() . "]  $CFG->wwwroot  Deleted Login:  $username  " . $_SERVER['HTTP_USER_AGENT']);
Línea 3909... Línea 3992...
3909
        // Verify login lockout after other ways that may prevent user login.
3992
        // Verify login lockout after other ways that may prevent user login.
3910
        if (login_is_lockedout($user)) {
3993
        if (login_is_lockedout($user)) {
3911
            $failurereason = AUTH_LOGIN_LOCKOUT;
3994
            $failurereason = AUTH_LOGIN_LOCKOUT;
Línea 3912... Línea 3995...
3912
 
3995
 
3913
            // Trigger login failed event.
3996
            // Trigger login failed event.
-
 
3997
            $event = \core\event\user_login_failed::create(array(
3914
            $event = \core\event\user_login_failed::create(array('userid' => $user->id,
3998
                'userid' => $user->id,
-
 
3999
                'other' => array('username' => $username, 'reason' => $failurereason)
3915
                    'other' => array('username' => $username, 'reason' => $failurereason)));
4000
            ));
Línea 3916... Línea 4001...
3916
            $event->trigger();
4001
            $event->trigger();
3917
 
4002
 
Línea 3918... Línea 4003...
3918
            error_log('[client '.getremoteaddr()."]  $CFG->wwwroot  Login lockout:  $username  ".$_SERVER['HTTP_USER_AGENT']);
4003
            error_log('[client ' . getremoteaddr() . "]  $CFG->wwwroot  Login lockout:  $username  " . $_SERVER['HTTP_USER_AGENT']);
3919
            $SESSION->loginerrormsg = get_string('accountlocked', 'admin');
4004
            $SESSION->loginerrormsg = get_string('accountlocked', 'admin');
3920
 
4005
 
Línea 3989... Línea 4074...
3989
            // The user is authenticated but user creation may be disabled.
4074
            // The user is authenticated but user creation may be disabled.
3990
            if (!empty($CFG->authpreventaccountcreation)) {
4075
            if (!empty($CFG->authpreventaccountcreation)) {
3991
                $failurereason = AUTH_LOGIN_UNAUTHORISED;
4076
                $failurereason = AUTH_LOGIN_UNAUTHORISED;
Línea 3992... Línea 4077...
3992
 
4077
 
3993
                // Trigger login failed event.
4078
                // Trigger login failed event.
-
 
4079
                $event = \core\event\user_login_failed::create(array('other' => array(
3994
                $event = \core\event\user_login_failed::create(array('other' => array('username' => $username,
4080
                    'username' => $username,
-
 
4081
                    'reason' => $failurereason
3995
                        'reason' => $failurereason)));
4082
                )));
Línea 3996... Línea 4083...
3996
                $event->trigger();
4083
                $event->trigger();
3997
 
4084
 
3998
                error_log('[client '.getremoteaddr()."]  $CFG->wwwroot  Unknown user, can not create new accounts:  $username  ".
4085
                error_log('[client ' . getremoteaddr() . "]  $CFG->wwwroot  Unknown user, can not create new accounts:  $username  " .
3999
                        $_SERVER['HTTP_USER_AGENT']);
4086
                    $_SERVER['HTTP_USER_AGENT']);
4000
                return false;
4087
                return false;
4001
            } else {
4088
            } else {
4002
                $user = create_user_record($username, $password, $auth);
4089
                $user = create_user_record($username, $password, $auth);
Línea 4011... Línea 4098...
4011
        }
4098
        }
Línea 4012... Línea 4099...
4012
 
4099
 
4013
        if (empty($user->id)) {
4100
        if (empty($user->id)) {
4014
            $failurereason = AUTH_LOGIN_NOUSER;
4101
            $failurereason = AUTH_LOGIN_NOUSER;
4015
            // Trigger login failed event.
4102
            // Trigger login failed event.
-
 
4103
            $event = \core\event\user_login_failed::create(array('other' => array(
4016
            $event = \core\event\user_login_failed::create(array('other' => array('username' => $username,
4104
                'username' => $username,
-
 
4105
                'reason' => $failurereason
4017
                    'reason' => $failurereason)));
4106
            )));
4018
            $event->trigger();
4107
            $event->trigger();
4019
            return false;
4108
            return false;
Línea 4020... Línea 4109...
4020
        }
4109
        }
4021
 
4110
 
4022
        if (!empty($user->suspended)) {
4111
        if (!empty($user->suspended)) {
4023
            // Just in case some auth plugin suspended account.
4112
            // Just in case some auth plugin suspended account.
4024
            $failurereason = AUTH_LOGIN_SUSPENDED;
4113
            $failurereason = AUTH_LOGIN_SUSPENDED;
-
 
4114
            // Trigger login failed event.
4025
            // Trigger login failed event.
4115
            $event = \core\event\user_login_failed::create(array(
-
 
4116
                'userid' => $user->id,
4026
            $event = \core\event\user_login_failed::create(array('userid' => $user->id,
4117
                'other' => array('username' => $username, 'reason' => $failurereason)
4027
                    'other' => array('username' => $username, 'reason' => $failurereason)));
4118
            ));
4028
            $event->trigger();
4119
            $event->trigger();
4029
            error_log('[client '.getremoteaddr()."]  $CFG->wwwroot  Suspended Login:  $username  ".$_SERVER['HTTP_USER_AGENT']);
4120
            error_log('[client ' . getremoteaddr() . "]  $CFG->wwwroot  Suspended Login:  $username  " . $_SERVER['HTTP_USER_AGENT']);
Línea 4030... Línea 4121...
4030
            return false;
4121
            return false;
4031
        }
4122
        }
4032
 
4123
 
4033
        login_attempt_valid($user);
4124
        login_attempt_valid($user);
Línea 4034... Línea 4125...
4034
        $failurereason = AUTH_LOGIN_OK;
4125
        $failurereason = AUTH_LOGIN_OK;
4035
        return $user;
4126
        return $user;
4036
    }
4127
    }
4037
 
4128
 
Línea 4038... Línea 4129...
4038
    // Failed if all the plugins have failed.
4129
    // Failed if all the plugins have failed.
4039
    if (debugging('', DEBUG_ALL)) {
4130
    if (debugging('', DEBUG_ALL)) {
4040
        error_log('[client '.getremoteaddr()."]  $CFG->wwwroot  Failed Login:  $username  ".$_SERVER['HTTP_USER_AGENT']);
4131
        error_log('[client ' . getremoteaddr() . "]  $CFG->wwwroot  Failed Login:  $username  " . $_SERVER['HTTP_USER_AGENT']);
4041
    }
4132
    }
4042
 
4133
 
-
 
4134
    if ($user->id) {
4043
    if ($user->id) {
4135
        login_attempt_failed($user);
-
 
4136
        $failurereason = AUTH_LOGIN_FAILED;
4044
        login_attempt_failed($user);
4137
        // Trigger login failed event.
4045
        $failurereason = AUTH_LOGIN_FAILED;
4138
        $event = \core\event\user_login_failed::create(array(
4046
        // Trigger login failed event.
4139
            'userid' => $user->id,
4047
        $event = \core\event\user_login_failed::create(array('userid' => $user->id,
4140
            'other' => array('username' => $username, 'reason' => $failurereason)
4048
                'other' => array('username' => $username, 'reason' => $failurereason)));
4141
        ));
-
 
4142
        $event->trigger();
4049
        $event->trigger();
4143
    } else {
-
 
4144
        $failurereason = AUTH_LOGIN_NOUSER;
4050
    } else {
4145
        // Trigger login failed event.
4051
        $failurereason = AUTH_LOGIN_NOUSER;
4146
        $event = \core\event\user_login_failed::create(array('other' => array(
Línea 4052... Línea 4147...
4052
        // Trigger login failed event.
4147
            'username' => $username,
4053
        $event = \core\event\user_login_failed::create(array('other' => array('username' => $username,
4148
            'reason' => $failurereason
Línea 4069... Línea 4164...
4069
 *
4164
 *
4070
 * @param stdClass $user
4165
 * @param stdClass $user
4071
 * @param array $extrauserinfo
4166
 * @param array $extrauserinfo
4072
 * @return stdClass A {@link $USER} object - BC only, do not use
4167
 * @return stdClass A {@link $USER} object - BC only, do not use
4073
 */
4168
 */
4074
function complete_user_login($user, array $extrauserinfo = []) {
4169
function complete_user_login($user, array $extrauserinfo = [])
-
 
4170
{
4075
    global $CFG, $DB, $USER, $SESSION;
4171
    global $CFG, $DB, $USER, $SESSION;
Línea 4076... Línea 4172...
4076
 
4172
 
Línea 4077... Línea 4173...
4077
    \core\session\manager::login_user($user);
4173
    \core\session\manager::login_user($user);
Línea 4166... Línea 4262...
4166
            if ($changeurl = $userauth->change_password_url()) {
4262
            if ($changeurl = $userauth->change_password_url()) {
4167
                redirect($changeurl);
4263
                redirect($changeurl);
4168
            } else {
4264
            } else {
4169
                require_once($CFG->dirroot . '/login/lib.php');
4265
                require_once($CFG->dirroot . '/login/lib.php');
4170
                $SESSION->wantsurl = core_login_get_return_url();
4266
                $SESSION->wantsurl = core_login_get_return_url();
4171
                redirect($CFG->wwwroot.'/login/change_password.php');
4267
                redirect($CFG->wwwroot . '/login/change_password.php');
4172
            }
4268
            }
4173
        } else {
4269
        } else {
4174
            throw new \moodle_exception('nopasswordchangeforced', 'auth');
4270
            throw new \moodle_exception('nopasswordchangeforced', 'auth');
4175
        }
4271
        }
4176
    }
4272
    }
Línea 4181... Línea 4277...
4181
 * Check a password hash to see if it was hashed using the legacy hash algorithm (bcrypt).
4277
 * Check a password hash to see if it was hashed using the legacy hash algorithm (bcrypt).
4182
 *
4278
 *
4183
 * @param string $password String to check.
4279
 * @param string $password String to check.
4184
 * @return bool True if the $password matches the format of a bcrypt hash.
4280
 * @return bool True if the $password matches the format of a bcrypt hash.
4185
 */
4281
 */
4186
function password_is_legacy_hash(#[\SensitiveParameter] string $password): bool {
4282
function password_is_legacy_hash(#[\SensitiveParameter] string $password): bool
-
 
4283
{
4187
    return (bool) preg_match('/^\$2y\$[\d]{2}\$[A-Za-z0-9\.\/]{53}$/', $password);
4284
    return (bool) preg_match('/^\$2y\$[\d]{2}\$[A-Za-z0-9\.\/]{53}$/', $password);
4188
}
4285
}
Línea 4189... Línea 4286...
4189
 
4286
 
4190
/**
4287
/**
4191
 * Calculate the Shannon entropy of a string.
4288
 * Calculate the Shannon entropy of a string.
4192
 *
4289
 *
4193
 * @param string $pepper The pepper to calculate the entropy of.
4290
 * @param string $pepper The pepper to calculate the entropy of.
4194
 * @return float The Shannon entropy of the string.
4291
 * @return float The Shannon entropy of the string.
4195
 */
4292
 */
-
 
4293
function calculate_entropy(#[\SensitiveParameter] string $pepper): float
4196
function calculate_entropy(#[\SensitiveParameter] string $pepper): float {
4294
{
4197
    // Initialize entropy.
4295
    // Initialize entropy.
Línea 4198... Línea 4296...
4198
    $h = 0;
4296
    $h = 0;
4199
 
4297
 
Línea 4224... Línea 4322...
4224
 * Also, we allow the latest pepper to be empty, to allow admins to migrate off peppers.
4322
 * Also, we allow the latest pepper to be empty, to allow admins to migrate off peppers.
4225
 *
4323
 *
4226
 * @return array The password peppers.
4324
 * @return array The password peppers.
4227
 * @throws coding_exception If the entropy of the password pepper is less than the recommended minimum.
4325
 * @throws coding_exception If the entropy of the password pepper is less than the recommended minimum.
4228
 */
4326
 */
4229
function get_password_peppers(): array {
4327
function get_password_peppers(): array
-
 
4328
{
4230
    global $CFG;
4329
    global $CFG;
Línea 4231... Línea 4330...
4231
 
4330
 
4232
    // Get all available peppers.
4331
    // Get all available peppers.
4233
    if (isset($CFG->passwordpeppers) && is_array($CFG->passwordpeppers)) {
4332
    if (isset($CFG->passwordpeppers) && is_array($CFG->passwordpeppers)) {
Línea 4241... Línea 4340...
4241
    // Check if the entropy of the most recent pepper is less than the minimum.
4340
    // Check if the entropy of the most recent pepper is less than the minimum.
4242
    // Also, we allow the most recent pepper to be empty, to allow admins to migrate off peppers.
4341
    // Also, we allow the most recent pepper to be empty, to allow admins to migrate off peppers.
4243
    $lastpepper = reset($peppers);
4342
    $lastpepper = reset($peppers);
4244
    if (!empty($peppers) && $lastpepper !== '' && calculate_entropy($lastpepper) < PEPPER_ENTROPY) {
4343
    if (!empty($peppers) && $lastpepper !== '' && calculate_entropy($lastpepper) < PEPPER_ENTROPY) {
4245
        throw new coding_exception(
4344
        throw new coding_exception(
4246
                'password pepper below minimum',
4345
            'password pepper below minimum',
4247
                'The entropy of the password pepper is less than the recommended minimum.');
4346
            'The entropy of the password pepper is less than the recommended minimum.'
-
 
4347
        );
4248
    }
4348
    }
4249
    return $peppers;
4349
    return $peppers;
4250
}
4350
}
Línea 4251... Línea 4351...
4251
 
4351
 
Línea 4256... Línea 4356...
4256
 *
4356
 *
4257
 * @param stdClass $user (Password property may be updated).
4357
 * @param stdClass $user (Password property may be updated).
4258
 * @param string $password Plain text password.
4358
 * @param string $password Plain text password.
4259
 * @return bool True if password is valid.
4359
 * @return bool True if password is valid.
4260
 */
4360
 */
4261
function validate_internal_user_password(stdClass $user, #[\SensitiveParameter] string $password): bool {
4361
function validate_internal_user_password(stdClass $user, #[\SensitiveParameter] string $password): bool
-
 
4362
{
Línea 4262... Línea 4363...
4262
 
4363
 
4263
    if (exceeds_password_length($password)) {
4364
    if (exceeds_password_length($password)) {
4264
        // Password cannot be more than MAX_PASSWORD_CHARACTERS characters.
4365
        // Password cannot be more than MAX_PASSWORD_CHARACTERS characters.
4265
        return false;
4366
        return false;
Línea 4310... Línea 4411...
4310
 * @param int $pepperlength Lenght of the peppers
4411
 * @param int $pepperlength Lenght of the peppers
4311
 * @return string The hashed password.
4412
 * @return string The hashed password.
4312
 *
4413
 *
4313
 * @throws moodle_exception If a problem occurs while generating the hash.
4414
 * @throws moodle_exception If a problem occurs while generating the hash.
4314
 */
4415
 */
4315
function hash_internal_user_password(#[\SensitiveParameter] string $password, $fasthash = false, $pepperlength = 0): string {
4416
function hash_internal_user_password(#[\SensitiveParameter] string $password, $fasthash = false, $pepperlength = 0): string
-
 
4417
{
4316
    if (exceeds_password_length($password, $pepperlength)) {
4418
    if (exceeds_password_length($password, $pepperlength)) {
4317
        // Password cannot be more than MAX_PASSWORD_CHARACTERS.
4419
        // Password cannot be more than MAX_PASSWORD_CHARACTERS.
4318
        throw new \moodle_exception(get_string("passwordexceeded", 'error', MAX_PASSWORD_CHARACTERS));
4420
        throw new \moodle_exception(get_string("passwordexceeded", 'error', MAX_PASSWORD_CHARACTERS));
4319
    }
4421
    }
Línea 4365... Línea 4467...
4365
 *                       less secure. It is used when lots of hashes need to
4467
 *                       less secure. It is used when lots of hashes need to
4366
 *                       be generated quickly.
4468
 *                       be generated quickly.
4367
 * @return bool Always returns true.
4469
 * @return bool Always returns true.
4368
 */
4470
 */
4369
function update_internal_user_password(
4471
function update_internal_user_password(
4370
        stdClass $user,
4472
    stdClass $user,
4371
        #[\SensitiveParameter] ?string $password,
4473
    #[\SensitiveParameter] ?string $password,
4372
        bool $fasthash = false
4474
    bool $fasthash = false
4373
): bool {
4475
): bool {
4374
    global $CFG, $DB;
4476
    global $CFG, $DB;
Línea 4375... Línea 4477...
4375
 
4477
 
4376
    // Add the latest password pepper to the password before further processing.
4478
    // Add the latest password pepper to the password before further processing.
Línea 4379... Línea 4481...
4379
        $password = $password . reset($peppers);
4481
        $password = $password . reset($peppers);
4380
    }
4482
    }
Línea 4381... Línea 4483...
4381
 
4483
 
4382
    // Figure out what the hashed password should be.
4484
    // Figure out what the hashed password should be.
-
 
4485
    if (!isset($user->auth)) {
4383
    if (!isset($user->auth)) {
4486
        debugging(
4384
        debugging('User record in update_internal_user_password() must include field auth',
4487
            'User record in update_internal_user_password() must include field auth',
-
 
4488
            DEBUG_DEVELOPER
4385
                DEBUG_DEVELOPER);
4489
        );
4386
        $user->auth = $DB->get_field('user', 'auth', array('id' => $user->id));
4490
        $user->auth = $DB->get_field('user', 'auth', array('id' => $user->id));
4387
    }
4491
    }
4388
    $authplugin = get_auth_plugin($user->auth);
4492
    $authplugin = get_auth_plugin($user->auth);
4389
    if ($authplugin->prevent_local_passwords()) {
4493
    if ($authplugin->prevent_local_passwords()) {
Línea 4395... Línea 4499...
4395
    $algorithmchanged = false;
4499
    $algorithmchanged = false;
Línea 4396... Línea 4500...
4396
 
4500
 
4397
    if ($hashedpassword === AUTH_PASSWORD_NOT_CACHED) {
4501
    if ($hashedpassword === AUTH_PASSWORD_NOT_CACHED) {
4398
        // Password is not cached, update it if not set to AUTH_PASSWORD_NOT_CACHED.
4502
        // Password is not cached, update it if not set to AUTH_PASSWORD_NOT_CACHED.
4399
        $passwordchanged = ($user->password !== $hashedpassword);
-
 
4400
 
4503
        $passwordchanged = ($user->password !== $hashedpassword);
4401
    } else if (isset($user->password)) {
4504
    } else if (isset($user->password)) {
4402
        // If verification fails then it means the password has changed.
4505
        // If verification fails then it means the password has changed.
4403
        $passwordchanged = !password_verify($password, $user->password);
4506
        $passwordchanged = !password_verify($password, $user->password);
4404
        $algorithmchanged = password_is_legacy_hash($user->password);
4507
        $algorithmchanged = password_is_legacy_hash($user->password);
Línea 4416... Línea 4519...
4416
        $user = $DB->get_record('user', array('id' => $user->id));
4519
        $user = $DB->get_record('user', array('id' => $user->id));
4417
        \core\event\user_password_updated::create_from_user($user)->trigger();
4520
        \core\event\user_password_updated::create_from_user($user)->trigger();
Línea 4418... Línea 4521...
4418
 
4521
 
4419
        // Remove WS user tokens.
4522
        // Remove WS user tokens.
4420
        if (!empty($CFG->passwordchangetokendeletion)) {
4523
        if (!empty($CFG->passwordchangetokendeletion)) {
4421
            require_once($CFG->dirroot.'/webservice/lib.php');
4524
            require_once($CFG->dirroot . '/webservice/lib.php');
4422
            webservice::delete_user_ws_tokens($user->id);
4525
            webservice::delete_user_ws_tokens($user->id);
4423
        }
4526
        }
Línea 4424... Línea 4527...
4424
    }
4527
    }
Línea 4436... Línea 4539...
4436
 * @param int $mnethostid
4539
 * @param int $mnethostid
4437
 * @param bool $throwexception If true, it will throw an exception when there's no record found or when there are multiple records
4540
 * @param bool $throwexception If true, it will throw an exception when there's no record found or when there are multiple records
4438
 *                              found. Otherwise, it will just return false.
4541
 *                              found. Otherwise, it will just return false.
4439
 * @return mixed False, or A {@link $USER} object.
4542
 * @return mixed False, or A {@link $USER} object.
4440
 */
4543
 */
4441
function get_complete_user_data($field, $value, $mnethostid = null, $throwexception = false) {
4544
function get_complete_user_data($field, $value, $mnethostid = null, $throwexception = false)
-
 
4545
{
4442
    global $CFG, $DB;
4546
    global $CFG, $DB;
Línea 4443... Línea 4547...
4443
 
4547
 
4444
    if (!$field || !$value) {
4548
    if (!$field || !$value) {
4445
        return false;
4549
        return false;
Línea 4526... Línea 4630...
4526
    }
4630
    }
Línea 4527... Línea 4631...
4527
 
4631
 
4528
    // Add the custom profile fields to the user record.
4632
    // Add the custom profile fields to the user record.
4529
    $user->profile = array();
4633
    $user->profile = array();
4530
    if (!isguestuser($user)) {
4634
    if (!isguestuser($user)) {
4531
        require_once($CFG->dirroot.'/user/profile/lib.php');
4635
        require_once($CFG->dirroot . '/user/profile/lib.php');
4532
        profile_load_custom_fields($user);
4636
        profile_load_custom_fields($user);
Línea 4533... Línea 4637...
4533
    }
4637
    }
4534
 
4638
 
Línea 4555... Línea 4659...
4555
 * @param string|null $errmsg the error message to display when the password doesn't comply with the policy.
4659
 * @param string|null $errmsg the error message to display when the password doesn't comply with the policy.
4556
 * @param stdClass|null $user the user object to perform password validation against. Defaults to null if not provided.
4660
 * @param stdClass|null $user the user object to perform password validation against. Defaults to null if not provided.
4557
 *
4661
 *
4558
 * @return bool true if the password is valid according to the policy. false otherwise.
4662
 * @return bool true if the password is valid according to the policy. false otherwise.
4559
 */
4663
 */
4560
function check_password_policy(string $password, ?string &$errmsg, ?stdClass $user = null) {
4664
function check_password_policy(string $password, ?string &$errmsg, ?stdClass $user = null)
-
 
4665
{
4561
    global $CFG;
4666
    global $CFG;
4562
    if (!empty($CFG->passwordpolicy) && !isguestuser($user)) {
4667
    if (!empty($CFG->passwordpolicy) && !isguestuser($user)) {
4563
        $errors = get_password_policy_errors($password, $user);
4668
        $errors = get_password_policy_errors($password, $user);
Línea 4564... Línea 4669...
4564
 
4669
 
Línea 4577... Línea 4682...
4577
 * @param string $password the password to be checked against the password policy
4682
 * @param string $password the password to be checked against the password policy
4578
 * @param stdClass|null $user the user object to perform password validation against. Defaults to null if not provided.
4683
 * @param stdClass|null $user the user object to perform password validation against. Defaults to null if not provided.
4579
 *
4684
 *
4580
 * @return string[] Array of error messages.
4685
 * @return string[] Array of error messages.
4581
 */
4686
 */
4582
function get_password_policy_errors(string $password, ?stdClass $user = null) : array {
4687
function get_password_policy_errors(string $password, ?stdClass $user = null): array
-
 
4688
{
4583
    global $CFG;
4689
    global $CFG;
Línea 4584... Línea 4690...
4584
 
4690
 
Línea 4585... Línea 4691...
4585
    $errors = [];
4691
    $errors = [];
Línea 4619... Línea 4725...
4619
}
4725
}
Línea 4620... Línea 4726...
4620
 
4726
 
4621
/**
4727
/**
4622
 * When logging in, this function is run to set certain preferences for the current SESSION.
4728
 * When logging in, this function is run to set certain preferences for the current SESSION.
4623
 */
4729
 */
-
 
4730
function set_login_session_preferences()
4624
function set_login_session_preferences() {
4731
{
Línea 4625... Línea 4732...
4625
    global $SESSION;
4732
    global $SESSION;
Línea 4626... Línea 4733...
4626
 
4733
 
Línea 4639... Línea 4746...
4639
 * @param bool $showfeedback Whether to display notifications of each action the function performs.
4746
 * @param bool $showfeedback Whether to display notifications of each action the function performs.
4640
 * @return bool true if all the removals succeeded. false if there were any failures. If this
4747
 * @return bool true if all the removals succeeded. false if there were any failures. If this
4641
 *             method returns false, some of the removals will probably have succeeded, and others
4748
 *             method returns false, some of the removals will probably have succeeded, and others
4642
 *             failed, but you have no way of knowing which.
4749
 *             failed, but you have no way of knowing which.
4643
 */
4750
 */
4644
function delete_course($courseorid, $showfeedback = true) {
4751
function delete_course($courseorid, $showfeedback = true)
-
 
4752
{
4645
    global $DB, $CFG;
4753
    global $DB, $CFG;
Línea 4646... Línea 4754...
4646
 
4754
 
4647
    if (is_object($courseorid)) {
4755
    if (is_object($courseorid)) {
4648
        $courseid = $courseorid->id;
4756
        $courseid = $courseorid->id;
Línea 4703... Línea 4811...
4703
        'context' => $context,
4811
        'context' => $context,
4704
        'other' => array(
4812
        'other' => array(
4705
            'shortname' => $course->shortname,
4813
            'shortname' => $course->shortname,
4706
            'fullname' => $course->fullname,
4814
            'fullname' => $course->fullname,
4707
            'idnumber' => $course->idnumber
4815
            'idnumber' => $course->idnumber
4708
            )
4816
        )
4709
    ));
4817
    ));
4710
    $event->add_record_snapshot('course', $course);
4818
    $event->add_record_snapshot('course', $course);
4711
    $event->trigger();
4819
    $event->trigger();
Línea 4712... Línea 4820...
4712
 
4820
 
Línea 4730... Línea 4838...
4730
 * @param array $options extra options
4838
 * @param array $options extra options
4731
 * @return bool true if all the removals succeeded. false if there were any failures. If this
4839
 * @return bool true if all the removals succeeded. false if there were any failures. If this
4732
 *             method returns false, some of the removals will probably have succeeded, and others
4840
 *             method returns false, some of the removals will probably have succeeded, and others
4733
 *             failed, but you have no way of knowing which.
4841
 *             failed, but you have no way of knowing which.
4734
 */
4842
 */
4735
function remove_course_contents($courseid, $showfeedback = true, array $options = null) {
4843
function remove_course_contents($courseid, $showfeedback = true, array $options = null)
-
 
4844
{
4736
    global $CFG, $DB, $OUTPUT;
4845
    global $CFG, $DB, $OUTPUT;
Línea 4737... Línea 4846...
4737
 
4846
 
4738
    require_once($CFG->libdir.'/badgeslib.php');
4847
    require_once($CFG->libdir . '/badgeslib.php');
4739
    require_once($CFG->libdir.'/completionlib.php');
4848
    require_once($CFG->libdir . '/completionlib.php');
4740
    require_once($CFG->libdir.'/questionlib.php');
4849
    require_once($CFG->libdir . '/questionlib.php');
4741
    require_once($CFG->libdir.'/gradelib.php');
4850
    require_once($CFG->libdir . '/gradelib.php');
4742
    require_once($CFG->dirroot.'/group/lib.php');
4851
    require_once($CFG->dirroot . '/group/lib.php');
4743
    require_once($CFG->dirroot.'/comment/lib.php');
4852
    require_once($CFG->dirroot . '/comment/lib.php');
4744
    require_once($CFG->dirroot.'/rating/lib.php');
4853
    require_once($CFG->dirroot . '/rating/lib.php');
Línea 4745... Línea 4854...
4745
    require_once($CFG->dirroot.'/notes/lib.php');
4854
    require_once($CFG->dirroot . '/notes/lib.php');
4746
 
4855
 
Línea 4747... Línea 4856...
4747
    // Handle course badges.
4856
    // Handle course badges.
4748
    badges_handle_course_deletion($courseid);
4857
    badges_handle_course_deletion($courseid);
Línea 4749... Línea 4858...
4749
 
4858
 
4750
    // NOTE: these concatenated strings are suboptimal, but it is just extra info...
4859
    // NOTE: these concatenated strings are suboptimal, but it is just extra info...
Línea 4751... Línea 4860...
4751
    $strdeleted = get_string('deleted').' - ';
4860
    $strdeleted = get_string('deleted') . ' - ';
Línea 4759... Línea 4868...
4759
 
4868
 
4760
    // Delete course completion information, this has to be done before grades and enrols.
4869
    // Delete course completion information, this has to be done before grades and enrols.
4761
    $cc = new completion_info($course);
4870
    $cc = new completion_info($course);
4762
    $cc->clear_criteria();
4871
    $cc->clear_criteria();
4763
    if ($showfeedback) {
4872
    if ($showfeedback) {
4764
        echo $OUTPUT->notification($strdeleted.get_string('completion', 'completion'), 'notifysuccess');
4873
        echo $OUTPUT->notification($strdeleted . get_string('completion', 'completion'), 'notifysuccess');
Línea 4765... Línea 4874...
4765
    }
4874
    }
4766
 
4875
 
4767
    // Remove all data from gradebook - this needs to be done before course modules
4876
    // Remove all data from gradebook - this needs to be done before course modules
Línea 4777... Línea 4886...
4777
        blocks_delete_all_for_context($childcontext->id);
4886
        blocks_delete_all_for_context($childcontext->id);
4778
    }
4887
    }
4779
    unset($childcontexts);
4888
    unset($childcontexts);
4780
    blocks_delete_all_for_context($coursecontext->id);
4889
    blocks_delete_all_for_context($coursecontext->id);
4781
    if ($showfeedback) {
4890
    if ($showfeedback) {
4782
        echo $OUTPUT->notification($strdeleted.get_string('type_block_plural', 'plugin'), 'notifysuccess');
4891
        echo $OUTPUT->notification($strdeleted . get_string('type_block_plural', 'plugin'), 'notifysuccess');
4783
    }
4892
    }
Línea 4784... Línea 4893...
4784
 
4893
 
4785
    $DB->set_field('course_modules', 'deletioninprogress', '1', ['course' => $courseid]);
4894
    $DB->set_field('course_modules', 'deletioninprogress', '1', ['course' => $courseid]);
Línea 4795... Línea 4904...
4795
        if ($modname === 'NEWMODULE') {
4904
        if ($modname === 'NEWMODULE') {
4796
            continue;
4905
            continue;
4797
        }
4906
        }
4798
        if (array_key_exists($modname, $allmodules)) {
4907
        if (array_key_exists($modname, $allmodules)) {
4799
            $sql = "SELECT cm.*, m.id AS modinstance, m.name, '$modname' AS modname
4908
            $sql = "SELECT cm.*, m.id AS modinstance, m.name, '$modname' AS modname
4800
              FROM {".$modname."} m
4909
              FROM {" . $modname . "} m
4801
                   LEFT JOIN {course_modules} cm ON cm.instance = m.id AND cm.module = :moduleid
4910
                   LEFT JOIN {course_modules} cm ON cm.instance = m.id AND cm.module = :moduleid
4802
             WHERE m.course = :courseid";
4911
             WHERE m.course = :courseid";
4803
            $instances = $DB->get_records_sql($sql, array('courseid' => $course->id,
4912
            $instances = $DB->get_records_sql($sql, array(
-
 
4913
                'courseid' => $course->id,
-
 
4914
                'modulename' => $modname,
4804
                'modulename' => $modname, 'moduleid' => $allmodules[$modname]));
4915
                'moduleid' => $allmodules[$modname]
-
 
4916
            ));
Línea 4805... Línea 4917...
4805
 
4917
 
4806
            include_once("$moddir/lib.php");                 // Shows php warning only if plugin defective.
4918
            include_once("$moddir/lib.php");                 // Shows php warning only if plugin defective.
Línea 4807... Línea 4919...
4807
            $moddelete = $modname .'_delete_instance';       // Delete everything connected to an instance.
4919
            $moddelete = $modname . '_delete_instance';       // Delete everything connected to an instance.
4808
 
4920
 
4809
            if ($instances) {
4921
            if ($instances) {
4810
                foreach ($instances as $cm) {
4922
                foreach ($instances as $cm) {
Línea 4836... Línea 4948...
4836
                        rebuild_course_cache($cm->course, true);
4948
                        rebuild_course_cache($cm->course, true);
4837
                    }
4949
                    }
4838
                }
4950
                }
4839
            }
4951
            }
4840
            if ($instances and $showfeedback) {
4952
            if ($instances and $showfeedback) {
4841
                echo $OUTPUT->notification($strdeleted.get_string('pluginname', $modname), 'notifysuccess');
4953
                echo $OUTPUT->notification($strdeleted . get_string('pluginname', $modname), 'notifysuccess');
4842
            }
4954
            }
4843
        } else {
4955
        } else {
4844
            // Ooops, this module is not properly installed, force-delete it in the next block.
4956
            // Ooops, this module is not properly installed, force-delete it in the next block.
4845
        }
4957
        }
4846
    }
4958
    }
Línea 4851... Línea 4963...
4851
    $DB->delete_records("course_completion_defaults", array("course" => $courseid));
4963
    $DB->delete_records("course_completion_defaults", array("course" => $courseid));
Línea 4852... Línea 4964...
4852
 
4964
 
4853
    // Remove all data from availability and completion tables that is associated
4965
    // Remove all data from availability and completion tables that is associated
4854
    // with course-modules belonging to this course. Note this is done even if the
4966
    // with course-modules belonging to this course. Note this is done even if the
-
 
4967
    // features are not enabled now, in case they were enabled previously.
4855
    // features are not enabled now, in case they were enabled previously.
4968
    $DB->delete_records_subquery(
-
 
4969
        'course_modules_completion',
-
 
4970
        'coursemoduleid',
4856
    $DB->delete_records_subquery('course_modules_completion', 'coursemoduleid', 'id',
4971
        'id',
-
 
4972
        'SELECT id from {course_modules} WHERE course = ?',
-
 
4973
        [$courseid]
4857
            'SELECT id from {course_modules} WHERE course = ?', [$courseid]);
4974
    );
-
 
4975
    $DB->delete_records_subquery(
-
 
4976
        'course_modules_viewed',
-
 
4977
        'coursemoduleid',
4858
    $DB->delete_records_subquery('course_modules_viewed', 'coursemoduleid', 'id',
4978
        'id',
-
 
4979
        'SELECT id from {course_modules} WHERE course = ?',
-
 
4980
        [$courseid]
Línea 4859... Línea 4981...
4859
        'SELECT id from {course_modules} WHERE course = ?', [$courseid]);
4981
    );
4860
 
4982
 
4861
    // Remove course-module data that has not been removed in modules' _delete_instance callbacks.
4983
    // Remove course-module data that has not been removed in modules' _delete_instance callbacks.
4862
    $cms = $DB->get_records('course_modules', array('course' => $course->id));
4984
    $cms = $DB->get_records('course_modules', array('course' => $course->id));
Línea 4873... Línea 4995...
4873
        $DB->delete_records('course_modules', array('id' => $cm->id));
4995
        $DB->delete_records('course_modules', array('id' => $cm->id));
4874
        rebuild_course_cache($cm->course, true);
4996
        rebuild_course_cache($cm->course, true);
4875
    }
4997
    }
Línea 4876... Línea 4998...
4876
 
4998
 
4877
    if ($showfeedback) {
4999
    if ($showfeedback) {
4878
        echo $OUTPUT->notification($strdeleted.get_string('type_mod_plural', 'plugin'), 'notifysuccess');
5000
        echo $OUTPUT->notification($strdeleted . get_string('type_mod_plural', 'plugin'), 'notifysuccess');
Línea 4879... Línea 5001...
4879
    }
5001
    }
4880
 
5002
 
4881
    // Delete questions and question categories.
5003
    // Delete questions and question categories.
4882
    question_delete_course($course);
5004
    question_delete_course($course);
4883
    if ($showfeedback) {
5005
    if ($showfeedback) {
Línea 4884... Línea 5006...
4884
        echo $OUTPUT->notification($strdeleted.get_string('questions', 'question'), 'notifysuccess');
5006
        echo $OUTPUT->notification($strdeleted . get_string('questions', 'question'), 'notifysuccess');
4885
    }
5007
    }
4886
 
5008
 
4887
    // Delete content bank contents.
5009
    // Delete content bank contents.
4888
    $cb = new \core_contentbank\contentbank();
5010
    $cb = new \core_contentbank\contentbank();
4889
    $cbdeleted = $cb->delete_contents($coursecontext);
5011
    $cbdeleted = $cb->delete_contents($coursecontext);
Línea 4890... Línea 5012...
4890
    if ($showfeedback && $cbdeleted) {
5012
    if ($showfeedback && $cbdeleted) {
4891
        echo $OUTPUT->notification($strdeleted.get_string('contentbank', 'contentbank'), 'notifysuccess');
5013
        echo $OUTPUT->notification($strdeleted . get_string('contentbank', 'contentbank'), 'notifysuccess');
4892
    }
5014
    }
Línea 4905... Línea 5027...
4905
        // permission to remove.
5027
        // permission to remove.
4906
        $userid = $options['userid'] ?? null;
5028
        $userid = $options['userid'] ?? null;
4907
        enrol_course_delete($course, $userid);
5029
        enrol_course_delete($course, $userid);
4908
        role_unassign_all(array('contextid' => $coursecontext->id, 'component' => ''), true);
5030
        role_unassign_all(array('contextid' => $coursecontext->id, 'component' => ''), true);
4909
        if ($showfeedback) {
5031
        if ($showfeedback) {
4910
            echo $OUTPUT->notification($strdeleted.get_string('type_enrol_plural', 'plugin'), 'notifysuccess');
5032
            echo $OUTPUT->notification($strdeleted . get_string('type_enrol_plural', 'plugin'), 'notifysuccess');
4911
        }
5033
        }
4912
    }
5034
    }
Línea 4913... Línea 5035...
4913
 
5035
 
4914
    // Delete any groups, removing members and grouping/course links first.
5036
    // Delete any groups, removing members and grouping/course links first.
Línea 4988... Línea 5110...
4988
        // there might be also files used by enrol plugins...
5110
        // there might be also files used by enrol plugins...
4989
    }
5111
    }
Línea 4990... Línea 5112...
4990
 
5112
 
4991
    // Delete legacy files - just in case some files are still left there after conversion to new file api,
5113
    // Delete legacy files - just in case some files are still left there after conversion to new file api,
4992
    // also some non-standard unsupported plugins may try to store something there.
5114
    // also some non-standard unsupported plugins may try to store something there.
Línea 4993... Línea 5115...
4993
    fulldelete($CFG->dataroot.'/'.$course->id);
5115
    fulldelete($CFG->dataroot . '/' . $course->id);
4994
 
5116
 
Línea 4995... Línea 5117...
4995
    // Delete from cache to reduce the cache size especially makes sense in case of bulk course deletion.
5117
    // Delete from cache to reduce the cache size especially makes sense in case of bulk course deletion.
4996
    course_modinfo::purge_course_cache($courseid);
5118
    course_modinfo::purge_course_cache($courseid);
4997
 
5119
 
4998
    // Trigger a course content deleted event.
5120
    // Trigger a course content deleted event.
-
 
5121
    $event = \core\event\course_content_deleted::create(array(
4999
    $event = \core\event\course_content_deleted::create(array(
5122
        'objectid' => $course->id,
5000
        'objectid' => $course->id,
5123
        'context' => $coursecontext,
-
 
5124
        'other' => array(
5001
        'context' => $coursecontext,
5125
            'shortname' => $course->shortname,
5002
        'other' => array('shortname' => $course->shortname,
5126
            'fullname' => $course->fullname,
5003
                         'fullname' => $course->fullname,
5127
            'options' => $options
5004
                         'options' => $options) // Passing this for legacy reasons.
5128
        ) // Passing this for legacy reasons.
Línea 5005... Línea 5129...
5005
    ));
5129
    ));
Línea 5017... Línea 5141...
5017
 * @param int $timeshift time difference
5141
 * @param int $timeshift time difference
5018
 * @param int $courseid
5142
 * @param int $courseid
5019
 * @param int $modid (Optional) passed if specific mod instance in course needs to be updated.
5143
 * @param int $modid (Optional) passed if specific mod instance in course needs to be updated.
5020
 * @return bool success
5144
 * @return bool success
5021
 */
5145
 */
5022
function shift_course_mod_dates($modname, $fields, $timeshift, $courseid, $modid = 0) {
5146
function shift_course_mod_dates($modname, $fields, $timeshift, $courseid, $modid = 0)
-
 
5147
{
5023
    global $CFG, $DB;
5148
    global $CFG, $DB;
5024
    include_once($CFG->dirroot.'/mod/'.$modname.'/lib.php');
5149
    include_once($CFG->dirroot . '/mod/' . $modname . '/lib.php');
Línea 5025... Línea 5150...
5025
 
5150
 
5026
    $return = true;
5151
    $return = true;
5027
    $params = array($timeshift, $courseid);
5152
    $params = array($timeshift, $courseid);
5028
    foreach ($fields as $field) {
5153
    foreach ($fields as $field) {
5029
        $updatesql = "UPDATE {".$modname."}
5154
        $updatesql = "UPDATE {" . $modname . "}
5030
                          SET $field = $field + ?
5155
                          SET $field = $field + ?
5031
                        WHERE course=? AND $field<>0";
5156
                        WHERE course=? AND $field<>0";
5032
        if ($modid) {
5157
        if ($modid) {
5033
            $updatesql .= ' AND id=?';
5158
            $updatesql .= ' AND id=?';
Línea 5044... Línea 5169...
5044
 * It will retain the activities and the structure of the course.
5169
 * It will retain the activities and the structure of the course.
5045
 *
5170
 *
5046
 * @param object $data an object containing all the settings including courseid (without magic quotes)
5171
 * @param object $data an object containing all the settings including courseid (without magic quotes)
5047
 * @return array status array of array component, item, error
5172
 * @return array status array of array component, item, error
5048
 */
5173
 */
5049
function reset_course_userdata($data) {
5174
function reset_course_userdata($data)
-
 
5175
{
5050
    global $CFG, $DB;
5176
    global $CFG, $DB;
5051
    require_once($CFG->libdir.'/gradelib.php');
5177
    require_once($CFG->libdir . '/gradelib.php');
5052
    require_once($CFG->libdir.'/completionlib.php');
5178
    require_once($CFG->libdir . '/completionlib.php');
5053
    require_once($CFG->dirroot.'/completion/criteria/completion_criteria_date.php');
5179
    require_once($CFG->dirroot . '/completion/criteria/completion_criteria_date.php');
5054
    require_once($CFG->dirroot.'/group/lib.php');
5180
    require_once($CFG->dirroot . '/group/lib.php');
Línea 5055... Línea 5181...
5055
 
5181
 
5056
    $data->courseid = $data->id;
5182
    $data->courseid = $data->id;
Línea 5057... Línea 5183...
5057
    $context = context_course::instance($data->courseid);
5183
    $context = context_course::instance($data->courseid);
Línea 5099... Línea 5225...
5099
        if ($CFG->enablecompletion) {
5225
        if ($CFG->enablecompletion) {
5100
            $modinfo = get_fast_modinfo($data->courseid);
5226
            $modinfo = get_fast_modinfo($data->courseid);
5101
            $changed = false;
5227
            $changed = false;
5102
            foreach ($modinfo->get_cms() as $cm) {
5228
            foreach ($modinfo->get_cms() as $cm) {
5103
                if ($cm->completion && !empty($cm->completionexpected)) {
5229
                if ($cm->completion && !empty($cm->completionexpected)) {
-
 
5230
                    $DB->set_field(
-
 
5231
                        'course_modules',
-
 
5232
                        'completionexpected',
5104
                    $DB->set_field('course_modules', 'completionexpected', $cm->completionexpected + $data->timeshift,
5233
                        $cm->completionexpected + $data->timeshift,
5105
                        array('id' => $cm->id));
5234
                        array('id' => $cm->id)
-
 
5235
                    );
5106
                    $changed = true;
5236
                    $changed = true;
5107
                }
5237
                }
5108
            }
5238
            }
Línea 5109... Línea 5239...
5109
 
5239
 
Línea 5132... Línea 5262...
5132
        $DB->delete_records('event', array('courseid' => $data->courseid));
5262
        $DB->delete_records('event', array('courseid' => $data->courseid));
5133
        $status[] = array('component' => $componentstr, 'item' => get_string('deleteevents', 'calendar'), 'error' => false);
5263
        $status[] = array('component' => $componentstr, 'item' => get_string('deleteevents', 'calendar'), 'error' => false);
5134
    }
5264
    }
Línea 5135... Línea 5265...
5135
 
5265
 
5136
    if (!empty($data->reset_notes)) {
5266
    if (!empty($data->reset_notes)) {
5137
        require_once($CFG->dirroot.'/notes/lib.php');
5267
        require_once($CFG->dirroot . '/notes/lib.php');
5138
        note_delete_all($data->courseid);
5268
        note_delete_all($data->courseid);
5139
        $status[] = array('component' => $componentstr, 'item' => get_string('deletenotes', 'notes'), 'error' => false);
5269
        $status[] = array('component' => $componentstr, 'item' => get_string('deletenotes', 'notes'), 'error' => false);
Línea 5140... Línea 5270...
5140
    }
5270
    }
5141
 
5271
 
5142
    if (!empty($data->delete_blog_associations)) {
5272
    if (!empty($data->delete_blog_associations)) {
5143
        require_once($CFG->dirroot.'/blog/lib.php');
5273
        require_once($CFG->dirroot . '/blog/lib.php');
5144
        blog_remove_associations_for_course($data->courseid);
5274
        blog_remove_associations_for_course($data->courseid);
Línea 5145... Línea 5275...
5145
        $status[] = array('component' => $componentstr, 'item' => get_string('deleteblogassociations', 'blog'), 'error' => false);
5275
        $status[] = array('component' => $componentstr, 'item' => get_string('deleteblogassociations', 'blog'), 'error' => false);
5146
    }
5276
    }
5147
 
5277
 
5148
    if (!empty($data->reset_completion)) {
5278
    if (!empty($data->reset_completion)) {
5149
        // Delete course and activity completion information.
5279
        // Delete course and activity completion information.
-
 
5280
        $course = $DB->get_record('course', array('id' => $data->courseid));
5150
        $course = $DB->get_record('course', array('id' => $data->courseid));
5281
        $cc = new completion_info($course);
5151
        $cc = new completion_info($course);
5282
        $cc->delete_all_completion_data();
-
 
5283
        $status[] = array(
-
 
5284
            'component' => $componentstr,
5152
        $cc->delete_all_completion_data();
5285
            'item' => get_string('deletecompletiondata', 'completion'),
Línea 5153... Línea 5286...
5153
        $status[] = array('component' => $componentstr,
5286
            'error' => false
5154
                'item' => get_string('deletecompletiondata', 'completion'), 'error' => false);
5287
        );
-
 
5288
    }
5155
    }
5289
 
5156
 
5290
    if (!empty($data->reset_competency_ratings)) {
-
 
5291
        \core_competency\api::hook_course_reset_competency_ratings($data->courseid);
-
 
5292
        $status[] = array(
5157
    if (!empty($data->reset_competency_ratings)) {
5293
            'component' => $componentstr,
Línea 5158... Línea 5294...
5158
        \core_competency\api::hook_course_reset_competency_ratings($data->courseid);
5294
            'item' => get_string('deletecompetencyratings', 'core_competency'),
Línea 5159... Línea 5295...
5159
        $status[] = array('component' => $componentstr,
5295
            'error' => false
Línea 5198... Línea 5334...
5198
                          FROM {user_enrolments} ue
5334
                          FROM {user_enrolments} ue
5199
                          JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)
5335
                          JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)
5200
                          JOIN {context} c ON (c.contextlevel = :courselevel AND c.instanceid = e.courseid)
5336
                          JOIN {context} c ON (c.contextlevel = :courselevel AND c.instanceid = e.courseid)
5201
                          JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.roleid = :roleid AND ra.userid = ue.userid)";
5337
                          JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.roleid = :roleid AND ra.userid = ue.userid)";
5202
                $params = array('courseid' => $data->courseid, 'roleid' => $withroleid, 'courselevel' => CONTEXT_COURSE);
5338
                $params = array('courseid' => $data->courseid, 'roleid' => $withroleid, 'courselevel' => CONTEXT_COURSE);
5203
 
-
 
5204
            } else {
5339
            } else {
5205
                // Without any role assigned at course context.
5340
                // Without any role assigned at course context.
5206
                $sql = "SELECT ue.*
5341
                $sql = "SELECT ue.*
5207
                          FROM {user_enrolments} ue
5342
                          FROM {user_enrolments} ue
5208
                          JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)
5343
                          JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)
Línea 5238... Línea 5373...
5238
        }
5373
        }
5239
    }
5374
    }
5240
    if (!empty($data->unenrolled)) {
5375
    if (!empty($data->unenrolled)) {
5241
        $status[] = array(
5376
        $status[] = array(
5242
            'component' => $componentstr,
5377
            'component' => $componentstr,
5243
            'item' => get_string('unenrol', 'enrol').' ('.count($data->unenrolled).')',
5378
            'item' => get_string('unenrol', 'enrol') . ' (' . count($data->unenrolled) . ')',
5244
            'error' => false
5379
            'error' => false
5245
        );
5380
        );
5246
    }
5381
    }
Línea 5247... Línea 5382...
5247
 
5382
 
Línea 5271... Línea 5406...
5271
        $status[] = array('component' => $componentstr, 'item' => get_string('deleteallgroupings', 'group'), 'error' => false);
5406
        $status[] = array('component' => $componentstr, 'item' => get_string('deleteallgroupings', 'group'), 'error' => false);
5272
    }
5407
    }
Línea 5273... Línea 5408...
5273
 
5408
 
5274
    // Look in every instance of every module for data to delete.
5409
    // Look in every instance of every module for data to delete.
5275
    $unsupportedmods = array();
5410
    $unsupportedmods = array();
5276
    if ($allmods = $DB->get_records('modules') ) {
5411
    if ($allmods = $DB->get_records('modules')) {
5277
        foreach ($allmods as $mod) {
5412
        foreach ($allmods as $mod) {
5278
            $modname = $mod->name;
5413
            $modname = $mod->name;
5279
            $modfile = $CFG->dirroot.'/mod/'. $modname.'/lib.php';
5414
            $modfile = $CFG->dirroot . '/mod/' . $modname . '/lib.php';
5280
            $moddeleteuserdata = $modname.'_reset_userdata';   // Function to delete user data.
5415
            $moddeleteuserdata = $modname . '_reset_userdata';   // Function to delete user data.
5281
            if (file_exists($modfile)) {
5416
            if (file_exists($modfile)) {
5282
                if (!$DB->count_records($modname, array('course' => $data->courseid))) {
5417
                if (!$DB->count_records($modname, array('course' => $data->courseid))) {
5283
                    continue; // Skip mods with no instances.
5418
                    continue; // Skip mods with no instances.
5284
                }
5419
                }
5285
                include_once($modfile);
5420
                include_once($modfile);
5286
                if (function_exists($moddeleteuserdata)) {
5421
                if (function_exists($moddeleteuserdata)) {
5287
                    $modstatus = $moddeleteuserdata($data);
5422
                    $modstatus = $moddeleteuserdata($data);
5288
                    if (is_array($modstatus)) {
5423
                    if (is_array($modstatus)) {
5289
                        $status = array_merge($status, $modstatus);
5424
                        $status = array_merge($status, $modstatus);
5290
                    } else {
5425
                    } else {
5291
                        debugging('Module '.$modname.' returned incorrect staus - must be an array!');
5426
                        debugging('Module ' . $modname . ' returned incorrect staus - must be an array!');
5292
                    }
5427
                    }
5293
                } else {
5428
                } else {
5294
                    $unsupportedmods[] = $mod;
5429
                    $unsupportedmods[] = $mod;
5295
                }
5430
                }
5296
            } else {
5431
            } else {
5297
                debugging('Missing lib.php in '.$modname.' module!');
5432
                debugging('Missing lib.php in ' . $modname . ' module!');
5298
            }
5433
            }
5299
            // Update calendar events for all modules.
5434
            // Update calendar events for all modules.
5300
            course_module_bulk_update_calendar_events($modname, $data->courseid);
5435
            course_module_bulk_update_calendar_events($modname, $data->courseid);
5301
        }
5436
        }
Línea 5321... Línea 5456...
5321
    if (!empty($data->reset_gradebook_items)) {
5456
    if (!empty($data->reset_gradebook_items)) {
5322
        remove_course_grades($data->courseid, false);
5457
        remove_course_grades($data->courseid, false);
5323
        grade_grab_course_grades($data->courseid);
5458
        grade_grab_course_grades($data->courseid);
5324
        grade_regrade_final_grades($data->courseid);
5459
        grade_regrade_final_grades($data->courseid);
5325
        $status[] = array('component' => $componentstr, 'item' => get_string('removeallcourseitems', 'grades'), 'error' => false);
5460
        $status[] = array('component' => $componentstr, 'item' => get_string('removeallcourseitems', 'grades'), 'error' => false);
5326
 
-
 
5327
    } else if (!empty($data->reset_gradebook_grades)) {
5461
    } else if (!empty($data->reset_gradebook_grades)) {
5328
        grade_course_reset($data->courseid);
5462
        grade_course_reset($data->courseid);
5329
        $status[] = array('component' => $componentstr, 'item' => get_string('removeallcoursegrades', 'grades'), 'error' => false);
5463
        $status[] = array('component' => $componentstr, 'item' => get_string('removeallcoursegrades', 'grades'), 'error' => false);
5330
    }
5464
    }
5331
    // Reset comments.
5465
    // Reset comments.
5332
    if (!empty($data->reset_comments)) {
5466
    if (!empty($data->reset_comments)) {
5333
        require_once($CFG->dirroot.'/comment/lib.php');
5467
        require_once($CFG->dirroot . '/comment/lib.php');
5334
        comment::reset_course_page_comments($context);
5468
        comment::reset_course_page_comments($context);
5335
    }
5469
    }
Línea 5336... Línea 5470...
5336
 
5470
 
5337
    $event = \core\event\course_reset_ended::create($eventparams);
5471
    $event = \core\event\course_reset_ended::create($eventparams);
Línea 5345... Línea 5479...
5345
 *
5479
 *
5346
 * @param int $modid
5480
 * @param int $modid
5347
 * @param string $modargs
5481
 * @param string $modargs
5348
 * @return string Returns email processing address
5482
 * @return string Returns email processing address
5349
 */
5483
 */
5350
function generate_email_processing_address($modid, $modargs) {
5484
function generate_email_processing_address($modid, $modargs)
-
 
5485
{
5351
    global $CFG;
5486
    global $CFG;
Línea 5352... Línea 5487...
5352
 
5487
 
5353
    $header = $CFG->mailprefix . substr(base64_encode(pack('C', $modid)), 0, 2).$modargs;
5488
    $header = $CFG->mailprefix . substr(base64_encode(pack('C', $modid)), 0, 2) . $modargs;
5354
    return $header . substr(md5($header.get_site_identifier()), 0, 16).'@'.$CFG->maildomain;
5489
    return $header . substr(md5($header . get_site_identifier()), 0, 16) . '@' . $CFG->maildomain;
Línea 5355... Línea 5490...
5355
}
5490
}
5356
 
5491
 
5357
/**
5492
/**
5358
 * ?
5493
 * ?
5359
 *
5494
 *
5360
 * @todo Finish documenting this function
5495
 * @todo Finish documenting this function
5361
 *
5496
 *
5362
 * @param string $modargs
5497
 * @param string $modargs
5363
 * @param string $body Currently unused
5498
 * @param string $body Currently unused
-
 
5499
 */
5364
 */
5500
function moodle_process_email($modargs, $body)
Línea 5365... Línea 5501...
5365
function moodle_process_email($modargs, $body) {
5501
{
5366
    global $DB;
5502
    global $DB;
5367
 
5503
 
5368
    // The first char should be an unencoded letter. We'll take this as an action.
5504
    // The first char should be an unencoded letter. We'll take this as an action.
5369
    switch ($modargs[0]) {
5505
    switch ($modargs[0]) {
5370
        case 'B': { // Bounce.
5506
        case 'B': { // Bounce.
5371
            list(, $userid) = unpack('V', base64_decode(substr($modargs, 1, 8)));
5507
                list(, $userid) = unpack('V', base64_decode(substr($modargs, 1, 8)));
5372
            if ($user = $DB->get_record("user", array('id' => $userid), "id,email")) {
5508
                if ($user = $DB->get_record("user", array('id' => $userid), "id,email")) {
5373
                // Check the half md5 of their email.
5509
                    // Check the half md5 of their email.
-
 
5510
                    $md5check = substr(md5($user->email), 0, 16);
-
 
5511
                    if ($md5check == substr($modargs, -16)) {
5374
                $md5check = substr(md5($user->email), 0, 16);
5512
                        set_bounce_count($user);
5375
                if ($md5check == substr($modargs, -16)) {
-
 
5376
                    set_bounce_count($user);
5513
                    }
5377
                }
-
 
5378
                // Else maybe they've already changed it?
5514
                    // Else maybe they've already changed it?
5379
            }
5515
                }
5380
        }
5516
            }
5381
        break;
5517
            break;
Línea 5382... Línea 5518...
5382
        // Maybe more later?
5518
            // Maybe more later?
Línea 5389... Línea 5525...
5389
 * Get mailer instance, enable buffering, flush buffer or disable buffering.
5525
 * Get mailer instance, enable buffering, flush buffer or disable buffering.
5390
 *
5526
 *
5391
 * @param string $action 'get', 'buffer', 'close' or 'flush'
5527
 * @param string $action 'get', 'buffer', 'close' or 'flush'
5392
 * @return moodle_phpmailer|null mailer instance if 'get' used or nothing
5528
 * @return moodle_phpmailer|null mailer instance if 'get' used or nothing
5393
 */
5529
 */
5394
function get_mailer($action='get') {
5530
function get_mailer($action = 'get')
-
 
5531
{
5395
    global $CFG;
5532
    global $CFG;
Línea 5396... Línea 5533...
5396
 
5533
 
5397
    /** @var moodle_phpmailer $mailer */
5534
    /** @var moodle_phpmailer $mailer */
5398
    static $mailer  = null;
5535
    static $mailer  = null;
Línea 5430... Línea 5567...
5430
 
5567
 
5431
            $prevkeepalive = $mailer->SMTPKeepAlive;
5568
            $prevkeepalive = $mailer->SMTPKeepAlive;
5432
            get_mailer('flush');
5569
            get_mailer('flush');
Línea 5433... Línea 5570...
5433
        }
5570
        }
5434
 
5571
 
Línea 5435... Línea 5572...
5435
        require_once($CFG->libdir.'/phpmailer/moodle_phpmailer.php');
5572
        require_once($CFG->libdir . '/phpmailer/moodle_phpmailer.php');
Línea 5436... Línea 5573...
5436
        $mailer = new moodle_phpmailer();
5573
        $mailer = new moodle_phpmailer();
5437
 
5574
 
5438
        $counter = 1;
5575
        $counter = 1;
5439
 
-
 
5440
        if ($CFG->smtphosts == 'qmail') {
5576
 
5441
            // Use Qmail system.
5577
        if ($CFG->smtphosts == 'qmail') {
5442
            $mailer->isQmail();
5578
            // Use Qmail system.
5443
 
-
 
5444
        } else if (empty($CFG->smtphosts)) {
5579
            $mailer->isQmail();
5445
            // Use PHP mail() = sendmail.
5580
        } else if (empty($CFG->smtphosts)) {
5446
            $mailer->isMail();
5581
            // Use PHP mail() = sendmail.
5447
 
5582
            $mailer->isMail();
5448
        } else {
5583
        } else {
Línea 5485... Línea 5620...
5485
 
5620
 
5486
    // Close smtp session, but continue buffering.
5621
    // Close smtp session, but continue buffering.
5487
    if ($action == 'flush') {
5622
    if ($action == 'flush') {
5488
        if (isset($mailer) and $mailer->Mailer == 'smtp') {
5623
        if (isset($mailer) and $mailer->Mailer == 'smtp') {
5489
            if (!empty($mailer->SMTPDebug)) {
5624
            if (!empty($mailer->SMTPDebug)) {
5490
                echo '<pre>'."\n";
5625
                echo '<pre>' . "\n";
5491
            }
5626
            }
5492
            $mailer->SmtpClose();
5627
            $mailer->SmtpClose();
5493
            if (!empty($mailer->SMTPDebug)) {
5628
            if (!empty($mailer->SMTPDebug)) {
5494
                echo '</pre>';
5629
                echo '</pre>';
Línea 5512... Línea 5647...
5512
 * A helper function to test for email diversion
5647
 * A helper function to test for email diversion
5513
 *
5648
 *
5514
 * @param string $email
5649
 * @param string $email
5515
 * @return bool Returns true if the email should be diverted
5650
 * @return bool Returns true if the email should be diverted
5516
 */
5651
 */
5517
function email_should_be_diverted($email) {
5652
function email_should_be_diverted($email)
-
 
5653
{
5518
    global $CFG;
5654
    global $CFG;
Línea 5519... Línea 5655...
5519
 
5655
 
5520
    if (empty($CFG->divertallemailsto)) {
5656
    if (empty($CFG->divertallemailsto)) {
5521
        return false;
5657
        return false;
Línea 5539... Línea 5675...
5539
 * Generate a unique email Message-ID using the moodle domain and install path
5675
 * Generate a unique email Message-ID using the moodle domain and install path
5540
 *
5676
 *
5541
 * @param string $localpart An optional unique message id prefix.
5677
 * @param string $localpart An optional unique message id prefix.
5542
 * @return string The formatted ID ready for appending to the email headers.
5678
 * @return string The formatted ID ready for appending to the email headers.
5543
 */
5679
 */
5544
function generate_email_messageid($localpart = null) {
5680
function generate_email_messageid($localpart = null)
-
 
5681
{
5545
    global $CFG;
5682
    global $CFG;
Línea 5546... Línea 5683...
5546
 
5683
 
5547
    $urlinfo = parse_url($CFG->wwwroot);
5684
    $urlinfo = parse_url($CFG->wwwroot);
Línea 5582... Línea 5719...
5582
 * @param string $replyto Email address to reply to
5719
 * @param string $replyto Email address to reply to
5583
 * @param string $replytoname Name of reply to recipient
5720
 * @param string $replytoname Name of reply to recipient
5584
 * @param int $wordwrapwidth custom word wrap width, default 79
5721
 * @param int $wordwrapwidth custom word wrap width, default 79
5585
 * @return bool Returns true if mail was sent OK and false if there was an error.
5722
 * @return bool Returns true if mail was sent OK and false if there was an error.
5586
 */
5723
 */
5587
function email_to_user($user, $from, $subject, $messagetext, $messagehtml = '', $attachment = '', $attachname = '',
5724
function email_to_user(
-
 
5725
    $user,
-
 
5726
    $from,
-
 
5727
    $subject,
-
 
5728
    $messagetext,
-
 
5729
    $messagehtml = '',
-
 
5730
    $attachment = '',
-
 
5731
    $attachname = '',
5588
                       $usetrueaddress = true, $replyto = '', $replytoname = '', $wordwrapwidth = 79) {
5732
    $usetrueaddress = true,
-
 
5733
    $replyto = '',
-
 
5734
    $replytoname = '',
-
 
5735
    $wordwrapwidth = 79
-
 
5736
) {
Línea 5589... Línea 5737...
5589
 
5737
 
Línea 5590... Línea 5738...
5590
    global $CFG, $PAGE, $SITE;
5738
    global $CFG, $PAGE, $SITE;
5591
 
5739
 
5592
    if (empty($user) or empty($user->id)) {
5740
    if (empty($user) or empty($user->id)) {
5593
        debugging('Can not send email to null user', DEBUG_DEVELOPER);
5741
        debugging('Can not send email to null user', DEBUG_DEVELOPER);
Línea 5594... Línea 5742...
5594
        return false;
5742
        return false;
5595
    }
5743
    }
5596
 
5744
 
5597
    if (empty($user->email)) {
5745
    if (empty($user->email)) {
Línea 5598... Línea 5746...
5598
        debugging('Can not send email to user without email: '.$user->id, DEBUG_DEVELOPER);
5746
        debugging('Can not send email to user without email: ' . $user->id, DEBUG_DEVELOPER);
5599
        return false;
5747
        return false;
5600
    }
5748
    }
5601
 
5749
 
Línea 5602... Línea 5750...
5602
    if (!empty($user->deleted)) {
5750
    if (!empty($user->deleted)) {
5603
        debugging('Can not send email to deleted user: '.$user->id, DEBUG_DEVELOPER);
5751
        debugging('Can not send email to deleted user: ' . $user->id, DEBUG_DEVELOPER);
Línea 5615... Línea 5763...
5615
        return true;
5763
        return true;
5616
    }
5764
    }
Línea 5617... Línea 5765...
5617
 
5765
 
5618
    if (email_should_be_diverted($user->email)) {
5766
    if (email_should_be_diverted($user->email)) {
5619
        $subject = "[DIVERTED {$user->email}] $subject";
5767
        $subject = "[DIVERTED {$user->email}] $subject";
5620
        $user = clone($user);
5768
        $user = clone ($user);
5621
        $user->email = $CFG->divertallemailsto;
5769
        $user->email = $CFG->divertallemailsto;
Línea 5622... Línea 5770...
5622
    }
5770
    }
5623
 
5771
 
5624
    // Skip mail to suspended users.
5772
    // Skip mail to suspended users.
5625
    if ((isset($user->auth) && $user->auth=='nologin') or (isset($user->suspended) && $user->suspended)) {
5773
    if ((isset($user->auth) && $user->auth == 'nologin') or (isset($user->suspended) && $user->suspended)) {
Línea 5626... Línea 5774...
5626
        return true;
5774
        return true;
5627
    }
5775
    }
5628
 
5776
 
5629
    if (!validate_email($user->email)) {
5777
    if (!validate_email($user->email)) {
5630
        // We can not send emails to invalid addresses - it might create security issue or confuse the mailer.
5778
        // We can not send emails to invalid addresses - it might create security issue or confuse the mailer.
Línea 5631... Línea 5779...
5631
        debugging("email_to_user: User $user->id (".fullname($user).") email ($user->email) is invalid! Not sending.");
5779
        debugging("email_to_user: User $user->id (" . fullname($user) . ") email ($user->email) is invalid! Not sending.");
5632
        return false;
5780
        return false;
5633
    }
5781
    }
5634
 
5782
 
Línea 5635... Línea 5783...
5635
    if (over_bounce_threshold($user)) {
5783
    if (over_bounce_threshold($user)) {
5636
        debugging("email_to_user: User $user->id (".fullname($user).") is over bounce threshold! Not sending.");
5784
        debugging("email_to_user: User $user->id (" . fullname($user) . ") is over bounce threshold! Not sending.");
5637
        return false;
5785
        return false;
5638
    }
5786
    }
5639
 
5787
 
5640
    // TLD .invalid  is specifically reserved for invalid domain names.
5788
    // TLD .invalid  is specifically reserved for invalid domain names.
Línea 5641... Línea 5789...
5641
    // For More information, see {@link http://tools.ietf.org/html/rfc2606#section-2}.
5789
    // For More information, see {@link http://tools.ietf.org/html/rfc2606#section-2}.
5642
    if (substr($user->email, -8) == '.invalid') {
5790
    if (substr($user->email, -8) == '.invalid') {
5643
        debugging("email_to_user: User $user->id (".fullname($user).") email domain ($user->email) is invalid! Not sending.");
5791
        debugging("email_to_user: User $user->id (" . fullname($user) . ") email domain ($user->email) is invalid! Not sending.");
5644
        return true; // This is not an error.
5792
        return true; // This is not an error.
5645
    }
5793
    }
Línea 5646... Línea 5794...
5646
 
5794
 
5647
    // If the user is a remote mnet user, parse the email text for URL to the
5795
    // If the user is a remote mnet user, parse the email text for URL to the
Línea 5648... Línea 5796...
5648
    // wwwroot and modify the url to direct the user's browser to login at their
5796
    // wwwroot and modify the url to direct the user's browser to login at their
-
 
5797
    // home site (identity provider - idp) before hitting the link itself.
5649
    // home site (identity provider - idp) before hitting the link itself.
5798
    if (is_mnet_remote_user($user)) {
5650
    if (is_mnet_remote_user($user)) {
5799
        require_once($CFG->dirroot . '/mnet/lib.php');
-
 
5800
 
-
 
5801
        $jumpurl = mnet_get_idp_jump_url($user);
5651
        require_once($CFG->dirroot.'/mnet/lib.php');
5802
        $callback = partial('mnet_sso_apply_indirection', $jumpurl);
5652
 
5803
 
5653
        $jumpurl = mnet_get_idp_jump_url($user);
5804
        $messagetext = preg_replace_callback(
-
 
5805
            "%($CFG->wwwroot[^[:space:]]*)%",
5654
        $callback = partial('mnet_sso_apply_indirection', $jumpurl);
5806
            $callback,
5655
 
5807
            $messagetext
Línea 5656... Línea 5808...
5656
        $messagetext = preg_replace_callback("%($CFG->wwwroot[^[:space:]]*)%",
5808
        );
5657
                $callback,
5809
        $messagehtml = preg_replace_callback(
Línea 5672... Línea 5824...
5672
    // Make sure that we fall back onto some reasonable no-reply address.
5824
    // Make sure that we fall back onto some reasonable no-reply address.
5673
    $noreplyaddressdefault = 'noreply@' . get_host_from_url($CFG->wwwroot);
5825
    $noreplyaddressdefault = 'noreply@' . get_host_from_url($CFG->wwwroot);
5674
    $noreplyaddress = empty($CFG->noreplyaddress) ? $noreplyaddressdefault : $CFG->noreplyaddress;
5826
    $noreplyaddress = empty($CFG->noreplyaddress) ? $noreplyaddressdefault : $CFG->noreplyaddress;
Línea 5675... Línea 5827...
5675
 
5827
 
5676
    if (!validate_email($noreplyaddress)) {
5828
    if (!validate_email($noreplyaddress)) {
5677
        debugging('email_to_user: Invalid noreply-email '.s($noreplyaddress));
5829
        debugging('email_to_user: Invalid noreply-email ' . s($noreplyaddress));
5678
        $noreplyaddress = $noreplyaddressdefault;
5830
        $noreplyaddress = $noreplyaddressdefault;
Línea 5679... Línea 5831...
5679
    }
5831
    }
5680
 
5832
 
5681
    // Make up an email address for handling bounces.
5833
    // Make up an email address for handling bounces.
5682
    if (!empty($CFG->handlebounces)) {
5834
    if (!empty($CFG->handlebounces)) {
5683
        $modargs = 'B'.base64_encode(pack('V', $user->id)).substr(md5($user->email), 0, 16);
5835
        $modargs = 'B' . base64_encode(pack('V', $user->id)) . substr(md5($user->email), 0, 16);
5684
        $mail->Sender = generate_email_processing_address(0, $modargs);
5836
        $mail->Sender = generate_email_processing_address(0, $modargs);
5685
    } else {
5837
    } else {
Línea 5686... Línea 5838...
5686
        $mail->Sender = $noreplyaddress;
5838
        $mail->Sender = $noreplyaddress;
5687
    }
5839
    }
5688
 
5840
 
5689
    // Make sure that the explicit replyto is valid, fall back to the implicit one.
5841
    // Make sure that the explicit replyto is valid, fall back to the implicit one.
5690
    if (!empty($replyto) && !validate_email($replyto)) {
5842
    if (!empty($replyto) && !validate_email($replyto)) {
Línea 5691... Línea 5843...
5691
        debugging('email_to_user: Invalid replyto-email '.s($replyto));
5843
        debugging('email_to_user: Invalid replyto-email ' . s($replyto));
5692
        $replyto = $noreplyaddress;
5844
        $replyto = $noreplyaddress;
5693
    }
5845
    }
5694
 
5846
 
5695
    if (is_string($from)) { // So we can pass whatever we want if there is need.
5847
    if (is_string($from)) { // So we can pass whatever we want if there is need.
5696
        $mail->From     = $noreplyaddress;
5848
        $mail->From     = $noreplyaddress;
5697
        $mail->FromName = $from;
5849
        $mail->FromName = $from;
5698
    // Check if using the true address is true, and the email is in the list of allowed domains for sending email,
5850
        // Check if using the true address is true, and the email is in the list of allowed domains for sending email,
5699
    // and that the senders email setting is either displayed to everyone, or display to only other users that are enrolled
5851
        // and that the senders email setting is either displayed to everyone, or display to only other users that are enrolled
5700
    // in a course with the sender.
5852
        // in a course with the sender.
5701
    } else if ($usetrueaddress && can_send_from_real_email_address($from, $user)) {
5853
    } else if ($usetrueaddress && can_send_from_real_email_address($from, $user)) {
5702
        if (!validate_email($from->email)) {
5854
        if (!validate_email($from->email)) {
5703
            debugging('email_to_user: Invalid from-email '.s($from->email).' - not sending');
5855
            debugging('email_to_user: Invalid from-email ' . s($from->email) . ' - not sending');
5704
            // Better not to use $noreplyaddress in this case.
5856
            // Better not to use $noreplyaddress in this case.
Línea 5766... Línea 5918...
5766
                $origin = $call;
5918
                $origin = $call;
5767
            }
5919
            }
5768
        }
5920
        }
Línea 5769... Línea 5921...
5769
 
5921
 
5770
        $originheader = $CFG->wwwroot . ' => ' . gethostname() . ':'
5922
        $originheader = $CFG->wwwroot . ' => ' . gethostname() . ':'
5771
             . str_replace($CFG->dirroot . '/', '', $origin['file']) . ':' . $origin['line'];
5923
            . str_replace($CFG->dirroot . '/', '', $origin['file']) . ':' . $origin['line'];
5772
        $mail->addCustomHeader('X-Moodle-Originating-Script: ' . $originheader);
5924
        $mail->addCustomHeader('X-Moodle-Originating-Script: ' . $originheader);
Línea 5773... Línea 5925...
5773
    }
5925
    }
5774
 
5926
 
Línea 5828... Línea 5980...
5828
        $mail->MessageID = generate_email_messageid();
5980
        $mail->MessageID = generate_email_messageid();
5829
    }
5981
    }
Línea 5830... Línea 5982...
5830
 
5982
 
5831
    if ($messagehtml && !empty($user->mailformat) && $user->mailformat == 1) {
5983
    if ($messagehtml && !empty($user->mailformat) && $user->mailformat == 1) {
-
 
5984
        // Don't ever send HTML to users who don't want it.
-
 
5985
        // Agregar HEADER y FOOTER con imágenes al messagehtml
-
 
5986
 
-
 
5987
        // Rutas de las imágenes
-
 
5988
        $header_image_url = $CFG->wwwroot . '/theme/universe/pix/logo-horizontal-cesa.png'; // 👉 Imagen del Header
-
 
5989
        $footer_image_url = $CFG->wwwroot . '/theme/universe/pix/email-footer.jpg'; // 👉 Imagen del Footer
5832
        // Don't ever send HTML to users who don't want it.
5990
 
-
 
5991
        // HTML del Header
-
 
5992
        $header_html = '<div style="text-align:center; margin-bottom:20px;">'
-
 
5993
            . '<img src="' . $header_image_url . '" alt="Header Image" style="max-width:100%; height:auto;">'
-
 
5994
            . '</div>';
5833
        $mail->isHTML(true);
5995
 
-
 
5996
        // HTML del Footer
-
 
5997
        $footer_html = '<div style="text-align:center; margin-top:40px;">'
5834
        $mail->Encoding = 'quoted-printable';
5998
            . '<img src="' . $footer_image_url . '" alt="Footer Image" style="max-width:100%; height:auto;">'
-
 
5999
            . '</div>';
-
 
6000
 
5835
        $mail->Body    =  $messagehtml;
6001
        // Unir: Header + Contenido original + Footer
5836
        $mail->AltBody =  "\n$messagetext\n";
6002
        $messagehtml = $header_html . $messagehtml . $footer_html;
5837
    } else {
6003
    } else {
5838
        $mail->IsHTML(false);
6004
        $mail->IsHTML(false);
5839
        $mail->Body =  "\n$messagetext\n";
6005
        $mail->Body =  "\n$messagetext\n";
Línea 5840... Línea 6006...
5840
    }
6006
    }
5841
 
6007
 
5842
    if ($attachment && $attachname) {
6008
    if ($attachment && $attachname) {
5843
        if (preg_match( "~\\.\\.~" , $attachment )) {
6009
        if (preg_match("~\\.\\.~", $attachment)) {
5844
            // Security check for ".." in dir path.
6010
            // Security check for ".." in dir path.
5845
            $supportuser = core_user::get_support_user();
6011
            $supportuser = core_user::get_support_user();
5846
            $temprecipients[] = array($supportuser->email, fullname($supportuser, true));
6012
            $temprecipients[] = array($supportuser->email, fullname($supportuser, true));
5847
            $mail->addStringAttachment('Error in attachment.  User attempted to attach a filename with a unsafe name.', 'error.txt', '8bit', 'text/plain');
6013
            $mail->addStringAttachment('Error in attachment.  User attempted to attach a filename with a unsafe name.', 'error.txt', '8bit', 'text/plain');
5848
        } else {
6014
        } else {
Línea 5849... Línea 6015...
5849
            require_once($CFG->libdir.'/filelib.php');
6015
            require_once($CFG->libdir . '/filelib.php');
5850
            $mimetype = mimeinfo('type', $attachname);
6016
            $mimetype = mimeinfo('type', $attachname);
5851
 
6017
 
Línea 5852... Línea 6018...
5852
            // Before doing the comparison, make sure that the paths are correct (Windows uses slashes in the other direction).
6018
            // Before doing the comparison, make sure that the paths are correct (Windows uses slashes in the other direction).
5853
            // The absolute (real) path is also fetched to ensure that comparisons to allowed paths are compared equally.
6019
            // The absolute (real) path is also fetched to ensure that comparisons to allowed paths are compared equally.
5854
            $attachpath = str_replace('\\', '/', realpath($attachment));
6020
            $attachpath = str_replace('\\', '/', realpath($attachment));
5855
 
6021
 
5856
            // Build an array of all filepaths from which attachments can be added (normalised slashes, absolute/real path).
6022
            // Build an array of all filepaths from which attachments can be added (normalised slashes, absolute/real path).
5857
            $allowedpaths = array_map(function(string $path): string {
6023
            $allowedpaths = array_map(function (string $path): string {
5858
                return str_replace('\\', '/', realpath($path));
6024
                return str_replace('\\', '/', realpath($path));
Línea 5955... Línea 6121...
5955
                'errorinfo' => $mail->ErrorInfo
6121
                'errorinfo' => $mail->ErrorInfo
5956
            )
6122
            )
5957
        ));
6123
        ));
5958
        $event->trigger();
6124
        $event->trigger();
5959
        if (CLI_SCRIPT) {
6125
        if (CLI_SCRIPT) {
5960
            mtrace('Error: lib/moodlelib.php email_to_user(): '.$mail->ErrorInfo);
6126
            mtrace('Error: lib/moodlelib.php email_to_user(): ' . $mail->ErrorInfo);
5961
        }
6127
        }
5962
        if (!empty($mail->SMTPDebug)) {
6128
        if (!empty($mail->SMTPDebug)) {
5963
            echo '</pre>';
6129
            echo '</pre>';
5964
        }
6130
        }
5965
        return false;
6131
        return false;
Línea 5972... Línea 6138...
5972
 * @param  object $from The user object for the user we are sending the email from.
6138
 * @param  object $from The user object for the user we are sending the email from.
5973
 * @param  object $user The user object that we are sending the email to.
6139
 * @param  object $user The user object that we are sending the email to.
5974
 * @param  array $unused No longer used.
6140
 * @param  array $unused No longer used.
5975
 * @return bool Returns true if we can use the from user's email adress in the "From" field.
6141
 * @return bool Returns true if we can use the from user's email adress in the "From" field.
5976
 */
6142
 */
5977
function can_send_from_real_email_address($from, $user, $unused = null) {
6143
function can_send_from_real_email_address($from, $user, $unused = null)
-
 
6144
{
5978
    global $CFG;
6145
    global $CFG;
5979
    if (!isset($CFG->allowedemaildomains) || empty(trim($CFG->allowedemaildomains))) {
6146
    if (!isset($CFG->allowedemaildomains) || empty(trim($CFG->allowedemaildomains))) {
5980
        return false;
6147
        return false;
5981
    }
6148
    }
5982
    $alloweddomains = array_map('trim', explode("\n", $CFG->allowedemaildomains));
6149
    $alloweddomains = array_map('trim', explode("\n", $CFG->allowedemaildomains));
5983
    // Email is in the list of allowed domains for sending email,
6150
    // Email is in the list of allowed domains for sending email,
5984
    // and the senders email setting is either displayed to everyone, or display to only other users that are enrolled
6151
    // and the senders email setting is either displayed to everyone, or display to only other users that are enrolled
5985
    // in a course with the sender.
6152
    // in a course with the sender.
-
 
6153
    if (
5986
    if (\core\ip_utils::is_domain_in_allowed_list(substr($from->email, strpos($from->email, '@') + 1), $alloweddomains)
6154
        \core\ip_utils::is_domain_in_allowed_list(substr($from->email, strpos($from->email, '@') + 1), $alloweddomains)
5987
                && ($from->maildisplay == core_user::MAILDISPLAY_EVERYONE
6155
        && ($from->maildisplay == core_user::MAILDISPLAY_EVERYONE
5988
                || ($from->maildisplay == core_user::MAILDISPLAY_COURSE_MEMBERS_ONLY
6156
            || ($from->maildisplay == core_user::MAILDISPLAY_COURSE_MEMBERS_ONLY
5989
                && enrol_get_shared_courses($user, $from, false, true)))) {
6157
                && enrol_get_shared_courses($user, $from, false, true)))
-
 
6158
    ) {
5990
        return true;
6159
        return true;
5991
    }
6160
    }
5992
    return false;
6161
    return false;
5993
}
6162
}
Línea 5994... Línea 6163...
5994
 
6163
 
5995
/**
6164
/**
5996
 * Generate a signoff for emails based on support settings
6165
 * Generate a signoff for emails based on support settings
5997
 *
6166
 *
5998
 * @return string
6167
 * @return string
5999
 */
6168
 */
-
 
6169
function generate_email_signoff()
6000
function generate_email_signoff() {
6170
{
Línea 6001... Línea 6171...
6001
    global $CFG, $OUTPUT;
6171
    global $CFG, $OUTPUT;
6002
 
6172
 
6003
    $signoff = "\n";
6173
    $signoff = "\n";
6004
    if (!empty($CFG->supportname)) {
6174
    if (!empty($CFG->supportname)) {
Línea 6005... Línea 6175...
6005
        $signoff .= $CFG->supportname."\n";
6175
        $signoff .= $CFG->supportname . "\n";
Línea 6006... Línea 6176...
6006
    }
6176
    }
Línea 6019... Línea 6189...
6019
 *
6189
 *
6020
 * @param stdClass $user A {@link $USER} object
6190
 * @param stdClass $user A {@link $USER} object
6021
 * @param bool $fasthash If true, use a low cost factor when generating the hash for speed.
6191
 * @param bool $fasthash If true, use a low cost factor when generating the hash for speed.
6022
 * @return bool|string Returns "true" if mail was sent OK and "false" if there was an error
6192
 * @return bool|string Returns "true" if mail was sent OK and "false" if there was an error
6023
 */
6193
 */
6024
function setnew_password_and_mail($user, $fasthash = false) {
6194
function setnew_password_and_mail($user, $fasthash = false)
-
 
6195
{
6025
    global $CFG, $DB;
6196
    global $CFG, $DB;
Línea 6026... Línea 6197...
6026
 
6197
 
6027
    // We try to send the mail in language the user understands,
6198
    // We try to send the mail in language the user understands,
6028
    // unfortunately the filter_string() does not support alternative langs yet
6199
    // unfortunately the filter_string() does not support alternative langs yet
Línea 6040... Línea 6211...
6040
    $a = new stdClass();
6211
    $a = new stdClass();
6041
    $a->firstname   = fullname($user, true);
6212
    $a->firstname   = fullname($user, true);
6042
    $a->sitename    = format_string($site->fullname);
6213
    $a->sitename    = format_string($site->fullname);
6043
    $a->username    = $user->username;
6214
    $a->username    = $user->username;
6044
    $a->newpassword = $newpassword;
6215
    $a->newpassword = $newpassword;
6045
    $a->link        = $CFG->wwwroot .'/login/?lang='.$lang;
6216
    $a->link        = $CFG->wwwroot . '/login/?lang=' . $lang;
6046
    $a->signoff     = generate_email_signoff();
6217
    $a->signoff     = generate_email_signoff();
Línea 6047... Línea 6218...
6047
 
6218
 
Línea 6048... Línea 6219...
6048
    $message = (string)new lang_string('newusernewpasswordtext', '', $a, $lang);
6219
    $message = (string)new lang_string('newusernewpasswordtext', '', $a, $lang);
Línea 6049... Línea 6220...
6049
 
6220
 
6050
    $subject = format_string($site->fullname) .': '. (string)new lang_string('newusernewpasswordsubj', '', $a, $lang);
6221
    $subject = format_string($site->fullname) . ': ' . (string)new lang_string('newusernewpasswordsubj', '', $a, $lang);
6051
 
-
 
6052
    // Directly email rather than using the messaging system to ensure its not routed to a popup or jabber.
6222
 
Línea 6053... Línea 6223...
6053
    return email_to_user($user, $supportuser, $subject, $message);
6223
    // Directly email rather than using the messaging system to ensure its not routed to a popup or jabber.
6054
 
6224
    return email_to_user($user, $supportuser, $subject, $message);
6055
}
6225
}
6056
 
6226
 
6057
/**
6227
/**
6058
 * Resets specified user's password and send the new password to the user via email.
6228
 * Resets specified user's password and send the new password to the user via email.
6059
 *
6229
 *
-
 
6230
 * @param stdClass $user A {@link $USER} object
6060
 * @param stdClass $user A {@link $USER} object
6231
 * @return bool Returns true if mail was sent OK and false if there was an error.
Línea 6061... Línea 6232...
6061
 * @return bool Returns true if mail was sent OK and false if there was an error.
6232
 */
6062
 */
6233
function reset_password_and_mail($user)
Línea 6082... Línea 6253...
6082
    $a->firstname   = $user->firstname;
6253
    $a->firstname   = $user->firstname;
6083
    $a->lastname    = $user->lastname;
6254
    $a->lastname    = $user->lastname;
6084
    $a->sitename    = format_string($site->fullname);
6255
    $a->sitename    = format_string($site->fullname);
6085
    $a->username    = $user->username;
6256
    $a->username    = $user->username;
6086
    $a->newpassword = $newpassword;
6257
    $a->newpassword = $newpassword;
6087
    $a->link        = $CFG->wwwroot .'/login/change_password.php';
6258
    $a->link        = $CFG->wwwroot . '/login/change_password.php';
6088
    $a->signoff     = generate_email_signoff();
6259
    $a->signoff     = generate_email_signoff();
Línea 6089... Línea 6260...
6089
 
6260
 
Línea 6090... Línea 6261...
6090
    $message = get_string('newpasswordtext', '', $a);
6261
    $message = get_string('newpasswordtext', '', $a);
Línea 6091... Línea 6262...
6091
 
6262
 
Línea 6092... Línea 6263...
6092
    $subject  = format_string($site->fullname) .': '. get_string('changedpassword');
6263
    $subject  = format_string($site->fullname) . ': ' . get_string('changedpassword');
6093
 
6264
 
Línea 6102... Línea 6273...
6102
 *
6273
 *
6103
 * @param stdClass $user A {@link $USER} object
6274
 * @param stdClass $user A {@link $USER} object
6104
 * @param string $confirmationurl user confirmation URL
6275
 * @param string $confirmationurl user confirmation URL
6105
 * @return bool Returns true if mail was sent OK and false if there was an error.
6276
 * @return bool Returns true if mail was sent OK and false if there was an error.
6106
 */
6277
 */
6107
function send_confirmation_email($user, $confirmationurl = null) {
6278
function send_confirmation_email($user, $confirmationurl = null)
-
 
6279
{
6108
    global $CFG;
6280
    global $CFG;
Línea 6109... Línea 6281...
6109
 
6281
 
6110
    $site = get_site();
6282
    $site = get_site();
Línea 6132... Línea 6304...
6132
    // Perform normal url encoding of the username first.
6304
    // Perform normal url encoding of the username first.
6133
    $username = urlencode($user->username);
6305
    $username = urlencode($user->username);
6134
    // Prevent problems with trailing dots not being included as part of link in some mail clients.
6306
    // Prevent problems with trailing dots not being included as part of link in some mail clients.
6135
    $username = str_replace('.', '%2E', $username);
6307
    $username = str_replace('.', '%2E', $username);
Línea 6136... Línea 6308...
6136
 
6308
 
Línea 6137... Línea 6309...
6137
    $data->link = $confirmationpath . ( $hasquerystring ? '&' : '?') . 'data='. $user->secret .'/'. $username;
6309
    $data->link = $confirmationpath . ($hasquerystring ? '&' : '?') . 'data=' . $user->secret . '/' . $username;
6138
 
6310
 
Línea 6139... Línea 6311...
6139
    $message     = get_string('emailconfirmation', '', $data);
6311
    $message     = get_string('emailconfirmation', '', $data);
Línea 6148... Línea 6320...
6148
 *
6320
 *
6149
 * @param stdClass $user A {@link $USER} object
6321
 * @param stdClass $user A {@link $USER} object
6150
 * @param stdClass $resetrecord An object tracking metadata regarding password reset request
6322
 * @param stdClass $resetrecord An object tracking metadata regarding password reset request
6151
 * @return bool Returns true if mail was sent OK and false if there was an error.
6323
 * @return bool Returns true if mail was sent OK and false if there was an error.
6152
 */
6324
 */
6153
function send_password_change_confirmation_email($user, $resetrecord) {
6325
function send_password_change_confirmation_email($user, $resetrecord)
-
 
6326
{
6154
    global $CFG;
6327
    global $CFG;
Línea 6155... Línea 6328...
6155
 
6328
 
6156
    $site = get_site();
6329
    $site = get_site();
6157
    $supportuser = core_user::get_support_user();
6330
    $supportuser = core_user::get_support_user();
Línea 6160... Línea 6333...
6160
    $data = new stdClass();
6333
    $data = new stdClass();
6161
    $data->firstname = $user->firstname;
6334
    $data->firstname = $user->firstname;
6162
    $data->lastname  = $user->lastname;
6335
    $data->lastname  = $user->lastname;
6163
    $data->username  = $user->username;
6336
    $data->username  = $user->username;
6164
    $data->sitename  = format_string($site->fullname);
6337
    $data->sitename  = format_string($site->fullname);
6165
    $data->link      = $CFG->wwwroot .'/login/forgot_password.php?token='. $resetrecord->token;
6338
    $data->link      = $CFG->wwwroot . '/login/forgot_password.php?token=' . $resetrecord->token;
6166
    $data->admin     = generate_email_signoff();
6339
    $data->admin     = generate_email_signoff();
6167
    $data->resetminutes = $pwresetmins;
6340
    $data->resetminutes = $pwresetmins;
Línea 6168... Línea 6341...
6168
 
6341
 
6169
    $message = get_string('emailresetconfirmation', '', $data);
6342
    $message = get_string('emailresetconfirmation', '', $data);
Línea 6170... Línea 6343...
6170
    $subject = get_string('emailresetconfirmationsubject', '', format_string($site->fullname));
6343
    $subject = get_string('emailresetconfirmationsubject', '', format_string($site->fullname));
6171
 
6344
 
6172
    // Directly email rather than using the messaging system to ensure its not routed to a popup or jabber.
-
 
6173
    return email_to_user($user, $supportuser, $subject, $message);
6345
    // Directly email rather than using the messaging system to ensure its not routed to a popup or jabber.
Línea 6174... Línea 6346...
6174
 
6346
    return email_to_user($user, $supportuser, $subject, $message);
6175
}
6347
}
6176
 
6348
 
6177
/**
6349
/**
6178
 * Sends an email containing information on how to change your password.
6350
 * Sends an email containing information on how to change your password.
6179
 *
6351
 *
6180
 * @param stdClass $user A {@link $USER} object
6352
 * @param stdClass $user A {@link $USER} object
-
 
6353
 * @return bool Returns true if mail was sent OK and false if there was an error.
6181
 * @return bool Returns true if mail was sent OK and false if there was an error.
6354
 */
6182
 */
6355
function send_password_change_info($user)
Línea 6183... Línea 6356...
6183
function send_password_change_info($user) {
6356
{
6184
    $site = get_site();
6357
    $site = get_site();
Línea 6209... Línea 6382...
6209
 * Check that an email is allowed.  It returns an error message if there was a problem.
6382
 * Check that an email is allowed.  It returns an error message if there was a problem.
6210
 *
6383
 *
6211
 * @param string $email Content of email
6384
 * @param string $email Content of email
6212
 * @return string|false
6385
 * @return string|false
6213
 */
6386
 */
6214
function email_is_not_allowed($email) {
6387
function email_is_not_allowed($email)
-
 
6388
{
6215
    global $CFG;
6389
    global $CFG;
Línea 6216... Línea 6390...
6216
 
6390
 
6217
    // Comparing lowercase domains.
6391
    // Comparing lowercase domains.
6218
    $email = strtolower($email);
6392
    $email = strtolower($email);
Línea 6226... Línea 6400...
6226
            if (strpos($allowedpattern, '.') === 0) {
6400
            if (strpos($allowedpattern, '.') === 0) {
6227
                if (strpos(strrev($email), strrev($allowedpattern)) === 0) {
6401
                if (strpos(strrev($email), strrev($allowedpattern)) === 0) {
6228
                    // Subdomains are in a form ".example.com" - matches "xxx@anything.example.com".
6402
                    // Subdomains are in a form ".example.com" - matches "xxx@anything.example.com".
6229
                    return false;
6403
                    return false;
6230
                }
6404
                }
6231
 
-
 
6232
            } else if (strpos(strrev($email), strrev('@'.$allowedpattern)) === 0) {
6405
            } else if (strpos(strrev($email), strrev('@' . $allowedpattern)) === 0) {
6233
                return false;
6406
                return false;
6234
            }
6407
            }
6235
        }
6408
        }
6236
        return get_string('emailonlyallowed', '', $CFG->allowemailaddresses);
6409
        return get_string('emailonlyallowed', '', $CFG->allowemailaddresses);
6237
 
-
 
6238
    } else if (!empty($CFG->denyemailaddresses)) {
6410
    } else if (!empty($CFG->denyemailaddresses)) {
6239
        $denied = explode(' ', strtolower($CFG->denyemailaddresses));
6411
        $denied = explode(' ', strtolower($CFG->denyemailaddresses));
6240
        foreach ($denied as $deniedpattern) {
6412
        foreach ($denied as $deniedpattern) {
6241
            $deniedpattern = trim($deniedpattern);
6413
            $deniedpattern = trim($deniedpattern);
6242
            if (!$deniedpattern) {
6414
            if (!$deniedpattern) {
Línea 6245... Línea 6417...
6245
            if (strpos($deniedpattern, '.') === 0) {
6417
            if (strpos($deniedpattern, '.') === 0) {
6246
                if (strpos(strrev($email), strrev($deniedpattern)) === 0) {
6418
                if (strpos(strrev($email), strrev($deniedpattern)) === 0) {
6247
                    // Subdomains are in a form ".example.com" - matches "xxx@anything.example.com".
6419
                    // Subdomains are in a form ".example.com" - matches "xxx@anything.example.com".
6248
                    return get_string('emailnotallowed', '', $CFG->denyemailaddresses);
6420
                    return get_string('emailnotallowed', '', $CFG->denyemailaddresses);
6249
                }
6421
                }
6250
 
-
 
6251
            } else if (strpos(strrev($email), strrev('@'.$deniedpattern)) === 0) {
6422
            } else if (strpos(strrev($email), strrev('@' . $deniedpattern)) === 0) {
6252
                return get_string('emailnotallowed', '', $CFG->denyemailaddresses);
6423
                return get_string('emailnotallowed', '', $CFG->denyemailaddresses);
6253
            }
6424
            }
6254
        }
6425
        }
6255
    }
6426
    }
Línea 6262... Línea 6433...
6262
/**
6433
/**
6263
 * Returns local file storage instance
6434
 * Returns local file storage instance
6264
 *
6435
 *
6265
 * @return ?file_storage
6436
 * @return ?file_storage
6266
 */
6437
 */
6267
function get_file_storage($reset = false) {
6438
function get_file_storage($reset = false)
-
 
6439
{
6268
    global $CFG;
6440
    global $CFG;
Línea 6269... Línea 6441...
6269
 
6441
 
Línea 6270... Línea 6442...
6270
    static $fs = null;
6442
    static $fs = null;
Línea 6288... Línea 6460...
6288
/**
6460
/**
6289
 * Returns local file storage instance
6461
 * Returns local file storage instance
6290
 *
6462
 *
6291
 * @return file_browser
6463
 * @return file_browser
6292
 */
6464
 */
6293
function get_file_browser() {
6465
function get_file_browser()
-
 
6466
{
6294
    global $CFG;
6467
    global $CFG;
Línea 6295... Línea 6468...
6295
 
6468
 
Línea 6296... Línea 6469...
6296
    static $fb = null;
6469
    static $fb = null;
Línea 6310... Línea 6483...
6310
 * Returns file packer
6483
 * Returns file packer
6311
 *
6484
 *
6312
 * @param string $mimetype default application/zip
6485
 * @param string $mimetype default application/zip
6313
 * @return file_packer|false
6486
 * @return file_packer|false
6314
 */
6487
 */
6315
function get_file_packer($mimetype='application/zip') {
6488
function get_file_packer($mimetype = 'application/zip')
-
 
6489
{
6316
    global $CFG;
6490
    global $CFG;
Línea 6317... Línea 6491...
6317
 
6491
 
Línea 6318... Línea 6492...
6318
    static $fp = array();
6492
    static $fp = array();
Línea 6325... Línea 6499...
6325
        case 'application/zip':
6499
        case 'application/zip':
6326
        case 'application/vnd.moodle.profiling':
6500
        case 'application/vnd.moodle.profiling':
6327
            $classname = 'zip_packer';
6501
            $classname = 'zip_packer';
6328
            break;
6502
            break;
Línea 6329... Línea 6503...
6329
 
6503
 
6330
        case 'application/x-gzip' :
6504
        case 'application/x-gzip':
6331
            $classname = 'tgz_packer';
6505
            $classname = 'tgz_packer';
Línea 6332... Línea 6506...
6332
            break;
6506
            break;
6333
 
6507
 
Línea 6349... Línea 6523...
6349
 * Returns current name of file on disk if it exists.
6523
 * Returns current name of file on disk if it exists.
6350
 *
6524
 *
6351
 * @param string $newfile File to be verified
6525
 * @param string $newfile File to be verified
6352
 * @return string Current name of file on disk if true
6526
 * @return string Current name of file on disk if true
6353
 */
6527
 */
6354
function valid_uploaded_file($newfile) {
6528
function valid_uploaded_file($newfile)
-
 
6529
{
6355
    if (empty($newfile)) {
6530
    if (empty($newfile)) {
6356
        return '';
6531
        return '';
6357
    }
6532
    }
6358
    if (is_uploaded_file($newfile['tmp_name']) and $newfile['size'] > 0) {
6533
    if (is_uploaded_file($newfile['tmp_name']) and $newfile['size'] > 0) {
6359
        return $newfile['tmp_name'];
6534
        return $newfile['tmp_name'];
Línea 6384... Línea 6559...
6384
 * @param int $coursebytes Current course $course->maxbytes (in bytes)
6559
 * @param int $coursebytes Current course $course->maxbytes (in bytes)
6385
 * @param int $modulebytes Current module ->maxbytes (in bytes)
6560
 * @param int $modulebytes Current module ->maxbytes (in bytes)
6386
 * @param bool $unused This parameter has been deprecated and is not used any more.
6561
 * @param bool $unused This parameter has been deprecated and is not used any more.
6387
 * @return int The maximum size for uploading files.
6562
 * @return int The maximum size for uploading files.
6388
 */
6563
 */
6389
function get_max_upload_file_size($sitebytes=0, $coursebytes=0, $modulebytes=0, $unused = false) {
6564
function get_max_upload_file_size($sitebytes = 0, $coursebytes = 0, $modulebytes = 0, $unused = false)
-
 
6565
{
Línea 6390... Línea 6566...
6390
 
6566
 
6391
    if (! $filesize = ini_get('upload_max_filesize')) {
6567
    if (! $filesize = ini_get('upload_max_filesize')) {
6392
        $filesize = '5M';
6568
        $filesize = '5M';
6393
    }
6569
    }
Línea 6426... Línea 6602...
6426
 * @param int $modulebytes Current module ->maxbytes (in bytes)
6602
 * @param int $modulebytes Current module ->maxbytes (in bytes)
6427
 * @param stdClass|int|null $user The user
6603
 * @param stdClass|int|null $user The user
6428
 * @param bool $unused This parameter has been deprecated and is not used any more.
6604
 * @param bool $unused This parameter has been deprecated and is not used any more.
6429
 * @return int The maximum size for uploading files.
6605
 * @return int The maximum size for uploading files.
6430
 */
6606
 */
6431
function get_user_max_upload_file_size($context, $sitebytes = 0, $coursebytes = 0, $modulebytes = 0, $user = null,
6607
function get_user_max_upload_file_size(
-
 
6608
    $context,
-
 
6609
    $sitebytes = 0,
-
 
6610
    $coursebytes = 0,
-
 
6611
    $modulebytes = 0,
-
 
6612
    $user = null,
6432
        $unused = false) {
6613
    $unused = false
-
 
6614
) {
6433
    global $USER;
6615
    global $USER;
Línea 6434... Línea 6616...
6434
 
6616
 
6435
    if (empty($user)) {
6617
    if (empty($user)) {
6436
        $user = $USER;
6618
        $user = $USER;
Línea 6461... Línea 6643...
6461
 * @param int $modulebytes Current module ->maxbytes (in bytes)
6643
 * @param int $modulebytes Current module ->maxbytes (in bytes)
6462
 * @param int|array $custombytes custom upload size/s which will be added to list,
6644
 * @param int|array $custombytes custom upload size/s which will be added to list,
6463
 *        Only value/s smaller then maxsize will be added to list.
6645
 *        Only value/s smaller then maxsize will be added to list.
6464
 * @return array
6646
 * @return array
6465
 */
6647
 */
6466
function get_max_upload_sizes($sitebytes = 0, $coursebytes = 0, $modulebytes = 0, $custombytes = null) {
6648
function get_max_upload_sizes($sitebytes = 0, $coursebytes = 0, $modulebytes = 0, $custombytes = null)
-
 
6649
{
6467
    global $CFG;
6650
    global $CFG;
Línea 6468... Línea 6651...
6468
 
6651
 
6469
    if (!$maxsize = get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes)) {
6652
    if (!$maxsize = get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes)) {
6470
        return array();
6653
        return array();
Línea 6474... Línea 6657...
6474
        // Will get the minimum of upload_max_filesize or post_max_size.
6657
        // Will get the minimum of upload_max_filesize or post_max_size.
6475
        $sitebytes = get_max_upload_file_size();
6658
        $sitebytes = get_max_upload_file_size();
6476
    }
6659
    }
Línea 6477... Línea 6660...
6477
 
6660
 
6478
    $filesize = array();
6661
    $filesize = array();
-
 
6662
    $sizelist = array(
-
 
6663
        10240,
-
 
6664
        51200,
-
 
6665
        102400,
-
 
6666
        512000,
-
 
6667
        1048576,
-
 
6668
        2097152,
-
 
6669
        5242880,
-
 
6670
        10485760,
-
 
6671
        20971520,
-
 
6672
        52428800,
-
 
6673
        104857600,
6479
    $sizelist = array(10240, 51200, 102400, 512000, 1048576, 2097152,
6674
        262144000,
-
 
6675
        524288000,
6480
                      5242880, 10485760, 20971520, 52428800, 104857600,
6676
        786432000,
-
 
6677
        1073741824,
6481
                      262144000, 524288000, 786432000, 1073741824,
6678
        2147483648,
-
 
6679
        4294967296,
-
 
6680
        8589934592
Línea 6482... Línea 6681...
6482
                      2147483648, 4294967296, 8589934592);
6681
    );
6483
 
6682
 
6484
    // If custombytes is given and is valid then add it to the list.
6683
    // If custombytes is given and is valid then add it to the list.
6485
    if (is_number($custombytes) and $custombytes > 0) {
6684
    if (is_number($custombytes) and $custombytes > 0) {
Línea 6503... Línea 6702...
6503
        }
6702
        }
6504
    }
6703
    }
Línea 6505... Línea 6704...
6505
 
6704
 
6506
    $limitlevel = '';
6705
    $limitlevel = '';
-
 
6706
    $displaysize = '';
6507
    $displaysize = '';
6707
    if (
6508
    if ($modulebytes &&
6708
        $modulebytes &&
6509
        (($modulebytes < $coursebytes || $coursebytes == 0) &&
6709
        (($modulebytes < $coursebytes || $coursebytes == 0) &&
-
 
6710
            ($modulebytes < $sitebytes || $sitebytes == 0))
6510
         ($modulebytes < $sitebytes || $sitebytes == 0))) {
6711
    ) {
6511
        $limitlevel = get_string('activity', 'core');
6712
        $limitlevel = get_string('activity', 'core');
6512
        $displaysize = display_size($modulebytes, 0);
6713
        $displaysize = display_size($modulebytes, 0);
Línea 6513... Línea 6714...
6513
        $filesize[$modulebytes] = $displaysize; // Make sure the limit is also included in the list.
6714
        $filesize[$modulebytes] = $displaysize; // Make sure the limit is also included in the list.
Línea 6547... Línea 6748...
6547
 * @param bool $descend If true then subdirectories are recursed as well
6748
 * @param bool $descend If true then subdirectories are recursed as well
6548
 * @param bool $getdirs If true then (sub)directories are included in the output
6749
 * @param bool $getdirs If true then (sub)directories are included in the output
6549
 * @param bool $getfiles  If true then files are included in the output
6750
 * @param bool $getfiles  If true then files are included in the output
6550
 * @return array An array with all the filenames in all subdirectories, relative to the given rootdir
6751
 * @return array An array with all the filenames in all subdirectories, relative to the given rootdir
6551
 */
6752
 */
6552
function get_directory_list($rootdir, $excludefiles='', $descend=true, $getdirs=false, $getfiles=true) {
6753
function get_directory_list($rootdir, $excludefiles = '', $descend = true, $getdirs = false, $getfiles = true)
-
 
6754
{
Línea 6553... Línea 6755...
6553
 
6755
 
Línea 6554... Línea 6756...
6554
    $dirs = array();
6756
    $dirs = array();
6555
 
6757
 
Línea 6572... Línea 6774...
6572
    while (false !== ($file = readdir($dir))) {
6774
    while (false !== ($file = readdir($dir))) {
6573
        $firstchar = substr($file, 0, 1);
6775
        $firstchar = substr($file, 0, 1);
6574
        if ($firstchar == '.' or $file == 'CVS' or in_array($file, $excludefiles)) {
6776
        if ($firstchar == '.' or $file == 'CVS' or in_array($file, $excludefiles)) {
6575
            continue;
6777
            continue;
6576
        }
6778
        }
6577
        $fullfile = $rootdir .'/'. $file;
6779
        $fullfile = $rootdir . '/' . $file;
6578
        if (filetype($fullfile) == 'dir') {
6780
        if (filetype($fullfile) == 'dir') {
6579
            if ($getdirs) {
6781
            if ($getdirs) {
6580
                $dirs[] = $file;
6782
                $dirs[] = $file;
6581
            }
6783
            }
6582
            if ($descend) {
6784
            if ($descend) {
6583
                $subdirs = get_directory_list($fullfile, $excludefiles, $descend, $getdirs, $getfiles);
6785
                $subdirs = get_directory_list($fullfile, $excludefiles, $descend, $getdirs, $getfiles);
6584
                foreach ($subdirs as $subdir) {
6786
                foreach ($subdirs as $subdir) {
6585
                    $dirs[] = $file .'/'. $subdir;
6787
                    $dirs[] = $file . '/' . $subdir;
6586
                }
6788
                }
6587
            }
6789
            }
6588
        } else if ($getfiles) {
6790
        } else if ($getfiles) {
6589
            $dirs[] = $file;
6791
            $dirs[] = $file;
6590
        }
6792
        }
Línea 6602... Línea 6804...
6602
 *
6804
 *
6603
 * @param string $rootdir  The directory to start from
6805
 * @param string $rootdir  The directory to start from
6604
 * @param string $excludefile A file to exclude when summing directory size
6806
 * @param string $excludefile A file to exclude when summing directory size
6605
 * @return int The summed size of all files and subfiles within the root directory
6807
 * @return int The summed size of all files and subfiles within the root directory
6606
 */
6808
 */
6607
function get_directory_size($rootdir, $excludefile='') {
6809
function get_directory_size($rootdir, $excludefile = '')
-
 
6810
{
6608
    global $CFG;
6811
    global $CFG;
Línea 6609... Línea 6812...
6609
 
6812
 
6610
    // Do it this way if we can, it's much faster.
6813
    // Do it this way if we can, it's much faster.
6611
    if (!empty($CFG->pathtodu) && is_executable(trim($CFG->pathtodu))) {
6814
    if (!empty($CFG->pathtodu) && is_executable(trim($CFG->pathtodu))) {
6612
        $command = trim($CFG->pathtodu).' -sk '.escapeshellarg($rootdir);
6815
        $command = trim($CFG->pathtodu) . ' -sk ' . escapeshellarg($rootdir);
6613
        $output = null;
6816
        $output = null;
6614
        $return = null;
6817
        $return = null;
6615
        exec($command, $output, $return);
6818
        exec($command, $output, $return);
6616
        if (is_array($output)) {
6819
        if (is_array($output)) {
6617
            // We told it to return k.
6820
            // We told it to return k.
6618
            return get_real_size(intval($output[0]).'k');
6821
            return get_real_size(intval($output[0]) . 'k');
6619
        }
6822
        }
Línea 6620... Línea 6823...
6620
    }
6823
    }
6621
 
6824
 
Línea 6634... Línea 6837...
6634
    while (false !== ($file = readdir($dir))) {
6837
    while (false !== ($file = readdir($dir))) {
6635
        $firstchar = substr($file, 0, 1);
6838
        $firstchar = substr($file, 0, 1);
6636
        if ($firstchar == '.' or $file == 'CVS' or $file == $excludefile) {
6839
        if ($firstchar == '.' or $file == 'CVS' or $file == $excludefile) {
6637
            continue;
6840
            continue;
6638
        }
6841
        }
6639
        $fullfile = $rootdir .'/'. $file;
6842
        $fullfile = $rootdir . '/' . $file;
6640
        if (filetype($fullfile) == 'dir') {
6843
        if (filetype($fullfile) == 'dir') {
6641
            $size += get_directory_size($fullfile, $excludefile);
6844
            $size += get_directory_size($fullfile, $excludefile);
6642
        } else {
6845
        } else {
6643
            $size += filesize($fullfile);
6846
            $size += filesize($fullfile);
6644
        }
6847
        }
Línea 6654... Línea 6857...
6654
 * @param int $size  The size to convert to human readable form
6857
 * @param int $size  The size to convert to human readable form
6655
 * @param int $decimalplaces If specified, uses fixed number of decimal places
6858
 * @param int $decimalplaces If specified, uses fixed number of decimal places
6656
 * @param string $fixedunits If specified, uses fixed units (e.g. 'KB')
6859
 * @param string $fixedunits If specified, uses fixed units (e.g. 'KB')
6657
 * @return string Display version of size
6860
 * @return string Display version of size
6658
 */
6861
 */
6659
function display_size($size, int $decimalplaces = 1, string $fixedunits = ''): string {
6862
function display_size($size, int $decimalplaces = 1, string $fixedunits = ''): string
-
 
6863
{
Línea 6660... Línea 6864...
6660
 
6864
 
Línea 6661... Línea 6865...
6661
    static $units;
6865
    static $units;
6662
 
6866
 
Línea 6672... Línea 6876...
6672
        $units[] = get_string('sizetb');
6876
        $units[] = get_string('sizetb');
6673
        $units[] = get_string('sizepb');
6877
        $units[] = get_string('sizepb');
6674
    }
6878
    }
Línea 6675... Línea 6879...
6675
 
6879
 
6676
    switch ($fixedunits) {
6880
    switch ($fixedunits) {
6677
        case 'PB' :
6881
        case 'PB':
6678
            $magnitude = 5;
6882
            $magnitude = 5;
6679
            break;
6883
            break;
6680
        case 'TB' :
6884
        case 'TB':
6681
            $magnitude = 4;
6885
            $magnitude = 4;
6682
            break;
6886
            break;
6683
        case 'GB' :
6887
        case 'GB':
6684
            $magnitude = 3;
6888
            $magnitude = 3;
6685
            break;
6889
            break;
6686
        case 'MB' :
6890
        case 'MB':
6687
            $magnitude = 2;
6891
            $magnitude = 2;
6688
            break;
6892
            break;
6689
        case 'KB' :
6893
        case 'KB':
6690
            $magnitude = 1;
6894
            $magnitude = 1;
6691
            break;
6895
            break;
6692
        case 'B' :
6896
        case 'B':
6693
            $magnitude = 0;
6897
            $magnitude = 0;
6694
            break;
6898
            break;
6695
        case '':
6899
        case '':
6696
            $magnitude = floor(log($size, 1024));
6900
            $magnitude = floor(log($size, 1024));
Línea 6718... Línea 6922...
6718
 *
6922
 *
6719
 * @see clean_param()
6923
 * @see clean_param()
6720
 * @param string $string file name
6924
 * @param string $string file name
6721
 * @return string cleaned file name
6925
 * @return string cleaned file name
6722
 */
6926
 */
6723
function clean_filename($string) {
6927
function clean_filename($string)
-
 
6928
{
6724
    return clean_param($string, PARAM_FILE);
6929
    return clean_param($string, PARAM_FILE);
6725
}
6930
}
Línea 6726... Línea 6931...
6726
 
6931
 
Línea 6730... Línea 6935...
6730
 * Returns the code for the current language
6935
 * Returns the code for the current language
6731
 *
6936
 *
6732
 * @category string
6937
 * @category string
6733
 * @return string
6938
 * @return string
6734
 */
6939
 */
6735
function current_language() {
6940
function current_language()
-
 
6941
{
6736
    global $CFG, $PAGE, $SESSION, $USER;
6942
    global $CFG, $PAGE, $SESSION, $USER;
Línea 6737... Línea 6943...
6737
 
6943
 
6738
    if (!empty($SESSION->forcelang)) {
6944
    if (!empty($SESSION->forcelang)) {
6739
        // Allows overriding course-forced language (useful for admins to check
6945
        // Allows overriding course-forced language (useful for admins to check
6740
        // issues in courses whose language they don't understand).
6946
        // issues in courses whose language they don't understand).
6741
        // Also used by some code to temporarily get language-related information in a
6947
        // Also used by some code to temporarily get language-related information in a
6742
        // specific language (see force_current_language()).
6948
        // specific language (see force_current_language()).
6743
        $return = $SESSION->forcelang;
-
 
6744
 
6949
        $return = $SESSION->forcelang;
6745
    } else if (!empty($PAGE->cm->lang)) {
6950
    } else if (!empty($PAGE->cm->lang)) {
6746
        // Activity language, if set.
6951
        // Activity language, if set.
6747
        $return = $PAGE->cm->lang;
-
 
6748
 
6952
        $return = $PAGE->cm->lang;
6749
    } else if (!empty($PAGE->course->id) && $PAGE->course->id != SITEID && !empty($PAGE->course->lang)) {
6953
    } else if (!empty($PAGE->course->id) && $PAGE->course->id != SITEID && !empty($PAGE->course->lang)) {
6750
        // Course language can override all other settings for this page.
6954
        // Course language can override all other settings for this page.
6751
        $return = $PAGE->course->lang;
-
 
6752
 
6955
        $return = $PAGE->course->lang;
6753
    } else if (!empty($SESSION->lang)) {
6956
    } else if (!empty($SESSION->lang)) {
6754
        // Session language can override other settings.
6957
        // Session language can override other settings.
6755
        $return = $SESSION->lang;
-
 
6756
 
6958
        $return = $SESSION->lang;
6757
    } else if (!empty($USER->lang)) {
6959
    } else if (!empty($USER->lang)) {
6758
        $return = $USER->lang;
-
 
6759
 
6960
        $return = $USER->lang;
6760
    } else if (isset($CFG->lang)) {
6961
    } else if (isset($CFG->lang)) {
6761
        $return = $CFG->lang;
-
 
6762
 
6962
        $return = $CFG->lang;
6763
    } else {
6963
    } else {
6764
        $return = 'en';
6964
        $return = 'en';
Línea 6765... Línea 6965...
6765
    }
6965
    }
Línea 6774... Línea 6974...
6774
 * Fix the current language to the given language code.
6974
 * Fix the current language to the given language code.
6775
 *
6975
 *
6776
 * @param string $lang The language code to use.
6976
 * @param string $lang The language code to use.
6777
 * @return void
6977
 * @return void
6778
 */
6978
 */
6779
function fix_current_language(string $lang): void {
6979
function fix_current_language(string $lang): void
-
 
6980
{
6780
    global $CFG, $COURSE, $SESSION, $USER;
6981
    global $CFG, $COURSE, $SESSION, $USER;
Línea 6781... Línea 6982...
6781
 
6982
 
6782
    if (!get_string_manager()->translation_exists($lang)) {
6983
    if (!get_string_manager()->translation_exists($lang)) {
6783
        throw new coding_exception("The language pack for $lang is not available");
6984
        throw new coding_exception("The language pack for $lang is not available");
Línea 6808... Línea 7009...
6808
 *
7009
 *
6809
 * @category string
7010
 * @category string
6810
 * @param string $lang null means current language
7011
 * @param string $lang null means current language
6811
 * @return string
7012
 * @return string
6812
 */
7013
 */
6813
function get_parent_language($lang=null) {
7014
function get_parent_language($lang = null)
-
 
7015
{
Línea 6814... Línea 7016...
6814
 
7016
 
Línea 6815... Línea 7017...
6815
    $parentlang = get_string_manager()->get_string('parentlanguage', 'langconfig', null, $lang);
7017
    $parentlang = get_string_manager()->get_string('parentlanguage', 'langconfig', null, $lang);
6816
 
7018
 
Línea 6828... Línea 7030...
6828
 * until this function is called again, or equivalent code is run.
7030
 * until this function is called again, or equivalent code is run.
6829
 *
7031
 *
6830
 * @param string $language
7032
 * @param string $language
6831
 * @return string previous $SESSION->forcelang value
7033
 * @return string previous $SESSION->forcelang value
6832
 */
7034
 */
6833
function force_current_language($language) {
7035
function force_current_language($language)
-
 
7036
{
6834
    global $SESSION;
7037
    global $SESSION;
6835
    $sessionforcelang = isset($SESSION->forcelang) ? $SESSION->forcelang : '';
7038
    $sessionforcelang = isset($SESSION->forcelang) ? $SESSION->forcelang : '';
6836
    if ($language !== $sessionforcelang) {
7039
    if ($language !== $sessionforcelang) {
6837
        // Setting forcelang to null or an empty string disables its effect.
7040
        // Setting forcelang to null or an empty string disables its effect.
6838
        if (empty($language) || get_string_manager()->translation_exists($language, false)) {
7041
        if (empty($language) || get_string_manager()->translation_exists($language, false)) {
Línea 6851... Línea 7054...
6851
 *
7054
 *
6852
 * @category string
7055
 * @category string
6853
 * @param bool $forcereload shall the singleton be released and new instance created instead?
7056
 * @param bool $forcereload shall the singleton be released and new instance created instead?
6854
 * @return core_string_manager
7057
 * @return core_string_manager
6855
 */
7058
 */
6856
function get_string_manager($forcereload=false) {
7059
function get_string_manager($forcereload = false)
-
 
7060
{
6857
    global $CFG;
7061
    global $CFG;
Línea 6858... Línea 7062...
6858
 
7062
 
Línea 6859... Línea 7063...
6859
    static $singleton = null;
7063
    static $singleton = null;
Línea 6864... Línea 7068...
6864
    if ($singleton === null) {
7068
    if ($singleton === null) {
6865
        if (empty($CFG->early_install_lang)) {
7069
        if (empty($CFG->early_install_lang)) {
Línea 6866... Línea 7070...
6866
 
7070
 
6867
            $transaliases = array();
7071
            $transaliases = array();
6868
            if (empty($CFG->langlist)) {
7072
            if (empty($CFG->langlist)) {
6869
                 $translist = array();
7073
                $translist = array();
6870
            } else {
7074
            } else {
6871
                $translist = explode(',', $CFG->langlist);
7075
                $translist = explode(',', $CFG->langlist);
6872
                $translist = array_map('trim', $translist);
7076
                $translist = array_map('trim', $translist);
6873
                // Each language in the $CFG->langlist can has an "alias" that would substitute the default language name.
7077
                // Each language in the $CFG->langlist can has an "alias" that would substitute the default language name.
Línea 6887... Línea 7091...
6887
                    $implements = class_implements($classname);
7091
                    $implements = class_implements($classname);
Línea 6888... Línea 7092...
6888
 
7092
 
6889
                    if (isset($implements['core_string_manager'])) {
7093
                    if (isset($implements['core_string_manager'])) {
6890
                        $singleton = new $classname($CFG->langotherroot, $CFG->langlocalroot, $translist, $transaliases);
7094
                        $singleton = new $classname($CFG->langotherroot, $CFG->langlocalroot, $translist, $transaliases);
6891
                        return $singleton;
-
 
6892
 
7095
                        return $singleton;
6893
                    } else {
7096
                    } else {
6894
                        debugging('Unable to instantiate custom string manager: class '.$classname.
7097
                        debugging('Unable to instantiate custom string manager: class ' . $classname .
6895
                            ' does not implement the core_string_manager interface.');
7098
                            ' does not implement the core_string_manager interface.');
6896
                    }
-
 
6897
 
7099
                    }
6898
                } else {
7100
                } else {
6899
                    debugging('Unable to instantiate custom string manager: class '.$classname.' can not be found.');
7101
                    debugging('Unable to instantiate custom string manager: class ' . $classname . ' can not be found.');
6900
                }
7102
                }
Línea 6901... Línea 7103...
6901
            }
7103
            }
6902
 
-
 
6903
            $singleton = new core_string_manager_standard($CFG->langotherroot, $CFG->langlocalroot, $translist, $transaliases);
7104
 
6904
 
7105
            $singleton = new core_string_manager_standard($CFG->langotherroot, $CFG->langlocalroot, $translist, $transaliases);
6905
        } else {
7106
        } else {
6906
            $singleton = new core_string_manager_install();
7107
            $singleton = new core_string_manager_install();
Línea 6980... Línea 7181...
6980
 * @param bool $lazyload If set to true a string object is returned instead of
7181
 * @param bool $lazyload If set to true a string object is returned instead of
6981
 *      the string itself. The string then isn't calculated until it is first used.
7182
 *      the string itself. The string then isn't calculated until it is first used.
6982
 * @return string The localized string.
7183
 * @return string The localized string.
6983
 * @throws coding_exception
7184
 * @throws coding_exception
6984
 */
7185
 */
6985
function get_string($identifier, $component = '', $a = null, $lazyload = false) {
7186
function get_string($identifier, $component = '', $a = null, $lazyload = false)
-
 
7187
{
6986
    global $CFG;
7188
    global $CFG;
Línea 6987... Línea 7189...
6987
 
7189
 
6988
    // If the lazy load argument has been supplied return a lang_string object
7190
    // If the lazy load argument has been supplied return a lang_string object
6989
    // instead.
7191
    // instead.
Línea 7003... Línea 7205...
7003
        debugging('extralocations parameter in get_string() is not supported any more, please use standard lang locations only.');
7205
        debugging('extralocations parameter in get_string() is not supported any more, please use standard lang locations only.');
7004
    }
7206
    }
Línea 7005... Línea 7207...
7005
 
7207
 
7006
    if (strpos((string)$component, '/') !== false) {
7208
    if (strpos((string)$component, '/') !== false) {
7007
        debugging('The module name you passed to get_string is the deprecated format ' .
7209
        debugging('The module name you passed to get_string is the deprecated format ' .
7008
                'like mod/mymod or block/myblock. The correct form looks like mymod, or block_myblock.' , DEBUG_DEVELOPER);
7210
            'like mod/mymod or block/myblock. The correct form looks like mymod, or block_myblock.', DEBUG_DEVELOPER);
Línea 7009... Línea 7211...
7009
        $componentpath = explode('/', $component);
7211
        $componentpath = explode('/', $component);
7010
 
7212
 
7011
        switch ($componentpath[0]) {
7213
        switch ($componentpath[0]) {
7012
            case 'mod':
7214
            case 'mod':
7013
                $component = $componentpath[1];
7215
                $component = $componentpath[1];
7014
                break;
7216
                break;
7015
            case 'blocks':
7217
            case 'blocks':
7016
            case 'block':
7218
            case 'block':
7017
                $component = 'block_'.$componentpath[1];
7219
                $component = 'block_' . $componentpath[1];
7018
                break;
7220
                break;
7019
            case 'enrol':
7221
            case 'enrol':
7020
                $component = 'enrol_'.$componentpath[1];
7222
                $component = 'enrol_' . $componentpath[1];
7021
                break;
7223
                break;
7022
            case 'format':
7224
            case 'format':
7023
                $component = 'format_'.$componentpath[1];
7225
                $component = 'format_' . $componentpath[1];
7024
                break;
7226
                break;
7025
            case 'grade':
7227
            case 'grade':
7026
                $component = 'grade'.$componentpath[1].'_'.$componentpath[2];
7228
                $component = 'grade' . $componentpath[1] . '_' . $componentpath[2];
7027
                break;
7229
                break;
Línea 7028... Línea 7230...
7028
        }
7230
        }
Línea 7042... Línea 7244...
7042
 *
7244
 *
7043
 * @param array $array An array of strings
7245
 * @param array $array An array of strings
7044
 * @param string $component The language module that these strings can be found in.
7246
 * @param string $component The language module that these strings can be found in.
7045
 * @return stdClass translated strings.
7247
 * @return stdClass translated strings.
7046
 */
7248
 */
7047
function get_strings($array, $component = '') {
7249
function get_strings($array, $component = '')
-
 
7250
{
7048
    $string = new stdClass;
7251
    $string = new stdClass;
7049
    foreach ($array as $item) {
7252
    foreach ($array as $item) {
7050
        $string->$item = get_string($item, $component);
7253
        $string->$item = get_string($item, $component);
7051
    }
7254
    }
7052
    return $string;
7255
    return $string;
Línea 7074... Línea 7277...
7074
 * @category string
7277
 * @category string
7075
 * @param string $identifier The key identifier for the localized string
7278
 * @param string $identifier The key identifier for the localized string
7076
 * @param string $component The module where the key identifier is stored. If none is specified then moodle.php is used.
7279
 * @param string $component The module where the key identifier is stored. If none is specified then moodle.php is used.
7077
 * @param string|object|array $a An object, string or number that can be used within translation strings
7280
 * @param string|object|array $a An object, string or number that can be used within translation strings
7078
 */
7281
 */
7079
function print_string($identifier, $component = '', $a = null) {
7282
function print_string($identifier, $component = '', $a = null)
-
 
7283
{
7080
    echo get_string($identifier, $component, $a);
7284
    echo get_string($identifier, $component, $a);
7081
}
7285
}
Línea 7082... Línea 7286...
7082
 
7286
 
7083
/**
7287
/**
Línea 7086... Línea 7290...
7086
 * Returns a list of charset codes. It's hardcoded, so they should be added manually
7290
 * Returns a list of charset codes. It's hardcoded, so they should be added manually
7087
 * (checking that such charset is supported by the texlib library!)
7291
 * (checking that such charset is supported by the texlib library!)
7088
 *
7292
 *
7089
 * @return array And associative array with contents in the form of charset => charset
7293
 * @return array And associative array with contents in the form of charset => charset
7090
 */
7294
 */
7091
function get_list_of_charsets() {
7295
function get_list_of_charsets()
-
 
7296
{
Línea 7092... Línea 7297...
7092
 
7297
 
7093
    $charsets = array(
7298
    $charsets = array(
7094
        'EUC-JP'     => 'EUC-JP',
7299
        'EUC-JP'     => 'EUC-JP',
7095
        'ISO-2022-JP'=> 'ISO-2022-JP',
7300
        'ISO-2022-JP' => 'ISO-2022-JP',
7096
        'ISO-8859-1' => 'ISO-8859-1',
7301
        'ISO-8859-1' => 'ISO-8859-1',
7097
        'SHIFT-JIS'  => 'SHIFT-JIS',
7302
        'SHIFT-JIS'  => 'SHIFT-JIS',
7098
        'GB2312'     => 'GB2312',
7303
        'GB2312'     => 'GB2312',
7099
        'GB18030'    => 'GB18030', // GB18030 not supported by typo and mbstring.
7304
        'GB18030'    => 'GB18030', // GB18030 not supported by typo and mbstring.
-
 
7305
        'UTF-8'      => 'UTF-8'
Línea 7100... Línea 7306...
7100
        'UTF-8'      => 'UTF-8');
7306
    );
Línea 7101... Línea 7307...
7101
 
7307
 
7102
    asort($charsets);
7308
    asort($charsets);
Línea 7107... Línea 7313...
7107
/**
7313
/**
7108
 * Returns a list of valid and compatible themes
7314
 * Returns a list of valid and compatible themes
7109
 *
7315
 *
7110
 * @return array
7316
 * @return array
7111
 */
7317
 */
7112
function get_list_of_themes() {
7318
function get_list_of_themes()
-
 
7319
{
7113
    global $CFG;
7320
    global $CFG;
Línea 7114... Línea 7321...
7114
 
7321
 
Línea 7115... Línea 7322...
7115
    $themes = array();
7322
    $themes = array();
Línea 7133... Línea 7340...
7133
/**
7340
/**
7134
 * Factory function for emoticon_manager
7341
 * Factory function for emoticon_manager
7135
 *
7342
 *
7136
 * @return emoticon_manager singleton
7343
 * @return emoticon_manager singleton
7137
 */
7344
 */
7138
function get_emoticon_manager() {
7345
function get_emoticon_manager()
-
 
7346
{
7139
    static $singleton = null;
7347
    static $singleton = null;
Línea 7140... Línea 7348...
7140
 
7348
 
7141
    if (is_null($singleton)) {
7349
    if (is_null($singleton)) {
7142
        $singleton = new emoticon_manager();
7350
        $singleton = new emoticon_manager();
Línea 7155... Línea 7363...
7155
 * @see admin_setting_emoticons
7363
 * @see admin_setting_emoticons
7156
 *
7364
 *
7157
 * @copyright 2010 David Mudrak
7365
 * @copyright 2010 David Mudrak
7158
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7366
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7159
 */
7367
 */
7160
class emoticon_manager {
7368
class emoticon_manager
-
 
7369
{
Línea 7161... Línea 7370...
7161
 
7370
 
7162
    /**
7371
    /**
7163
     * Returns the currently enabled emoticons
7372
     * Returns the currently enabled emoticons
7164
     *
7373
     *
7165
     * @param boolean $selectable - If true, only return emoticons that should be selectable from a list.
7374
     * @param boolean $selectable - If true, only return emoticons that should be selectable from a list.
7166
     * @return array of emoticon objects
7375
     * @return array of emoticon objects
7167
     */
7376
     */
-
 
7377
    public function get_emoticons($selectable = false)
7168
    public function get_emoticons($selectable = false) {
7378
    {
7169
        global $CFG;
7379
        global $CFG;
Línea 7170... Línea 7380...
7170
        $notselectable = ['martin', 'egg'];
7380
        $notselectable = ['martin', 'egg'];
7171
 
7381
 
Línea 7197... Línea 7407...
7197
     *
7407
     *
7198
     * @param stdClass $emoticon emoticon object
7408
     * @param stdClass $emoticon emoticon object
7199
     * @param array $attributes explicit HTML attributes to set
7409
     * @param array $attributes explicit HTML attributes to set
7200
     * @return pix_emoticon
7410
     * @return pix_emoticon
7201
     */
7411
     */
7202
    public function prepare_renderable_emoticon(stdClass $emoticon, array $attributes = array()) {
7412
    public function prepare_renderable_emoticon(stdClass $emoticon, array $attributes = array())
-
 
7413
    {
7203
        $stringmanager = get_string_manager();
7414
        $stringmanager = get_string_manager();
7204
        if ($stringmanager->string_exists($emoticon->altidentifier, $emoticon->altcomponent)) {
7415
        if ($stringmanager->string_exists($emoticon->altidentifier, $emoticon->altcomponent)) {
7205
            $alt = get_string($emoticon->altidentifier, $emoticon->altcomponent);
7416
            $alt = get_string($emoticon->altidentifier, $emoticon->altcomponent);
7206
        } else {
7417
        } else {
7207
            $alt = s($emoticon->text);
7418
            $alt = s($emoticon->text);
Línea 7214... Línea 7425...
7214
     *
7425
     *
7215
     * @see self::decode_stored_config()
7426
     * @see self::decode_stored_config()
7216
     * @param array $emoticons array of emtocion objects
7427
     * @param array $emoticons array of emtocion objects
7217
     * @return string
7428
     * @return string
7218
     */
7429
     */
7219
    public function encode_stored_config(array $emoticons) {
7430
    public function encode_stored_config(array $emoticons)
-
 
7431
    {
7220
        return json_encode($emoticons);
7432
        return json_encode($emoticons);
7221
    }
7433
    }
Línea 7222... Línea 7434...
7222
 
7434
 
7223
    /**
7435
    /**
7224
     * Decodes the string into an array of emoticon objects
7436
     * Decodes the string into an array of emoticon objects
7225
     *
7437
     *
7226
     * @see self::encode_stored_config()
7438
     * @see self::encode_stored_config()
7227
     * @param string $encoded
7439
     * @param string $encoded
7228
     * @return array|null
7440
     * @return array|null
7229
     */
7441
     */
-
 
7442
    public function decode_stored_config($encoded)
7230
    public function decode_stored_config($encoded) {
7443
    {
7231
        $decoded = json_decode($encoded);
7444
        $decoded = json_decode($encoded);
7232
        if (!is_array($decoded)) {
7445
        if (!is_array($decoded)) {
7233
            return null;
7446
            return null;
7234
        }
7447
        }
Línea 7238... Línea 7451...
7238
    /**
7451
    /**
7239
     * Returns default set of emoticons supported by Moodle
7452
     * Returns default set of emoticons supported by Moodle
7240
     *
7453
     *
7241
     * @return array of sdtClasses
7454
     * @return array of sdtClasses
7242
     */
7455
     */
7243
    public function default_emoticons() {
7456
    public function default_emoticons()
-
 
7457
    {
7244
        return array(
7458
        return array(
7245
            $this->prepare_emoticon_object(":-)", 's/smiley', 'smiley'),
7459
            $this->prepare_emoticon_object(":-)", 's/smiley', 'smiley'),
7246
            $this->prepare_emoticon_object(":)", 's/smiley', 'smiley'),
7460
            $this->prepare_emoticon_object(":)", 's/smiley', 'smiley'),
7247
            $this->prepare_emoticon_object(":-D", 's/biggrin', 'biggrin'),
7461
            $this->prepare_emoticon_object(":-D", 's/biggrin', 'biggrin'),
7248
            $this->prepare_emoticon_object(";-)", 's/wink', 'wink'),
7462
            $this->prepare_emoticon_object(";-)", 's/wink', 'wink'),
Línea 7283... Línea 7497...
7283
     * @param string $altidentifier alternative string identifier, null for no alt
7497
     * @param string $altidentifier alternative string identifier, null for no alt
7284
     * @param string $altcomponent where the alternative string is defined
7498
     * @param string $altcomponent where the alternative string is defined
7285
     * @param string $imagecomponent to be used by {@link pix_emoticon}
7499
     * @param string $imagecomponent to be used by {@link pix_emoticon}
7286
     * @return stdClass
7500
     * @return stdClass
7287
     */
7501
     */
7288
    protected function prepare_emoticon_object($text, $imagename, $altidentifier = null,
7502
    protected function prepare_emoticon_object(
-
 
7503
        $text,
-
 
7504
        $imagename,
-
 
7505
        $altidentifier = null,
7289
                                               $altcomponent = 'core_pix', $imagecomponent = 'core') {
7506
        $altcomponent = 'core_pix',
-
 
7507
        $imagecomponent = 'core'
-
 
7508
    ) {
7290
        return (object)array(
7509
        return (object)array(
7291
            'text'           => $text,
7510
            'text'           => $text,
7292
            'imagename'      => $imagename,
7511
            'imagename'      => $imagename,
7293
            'imagecomponent' => $imagecomponent,
7512
            'imagecomponent' => $imagecomponent,
7294
            'altidentifier'  => $altidentifier,
7513
            'altidentifier'  => $altidentifier,
Línea 7303... Línea 7522...
7303
 * rc4encrypt
7522
 * rc4encrypt
7304
 *
7523
 *
7305
 * @param string $data        Data to encrypt.
7524
 * @param string $data        Data to encrypt.
7306
 * @return string             The now encrypted data.
7525
 * @return string             The now encrypted data.
7307
 */
7526
 */
7308
function rc4encrypt($data) {
7527
function rc4encrypt($data)
-
 
7528
{
7309
    return endecrypt(get_site_identifier(), $data, '');
7529
    return endecrypt(get_site_identifier(), $data, '');
7310
}
7530
}
Línea 7311... Línea 7531...
7311
 
7531
 
7312
/**
7532
/**
7313
 * rc4decrypt
7533
 * rc4decrypt
7314
 *
7534
 *
7315
 * @param string $data        Data to decrypt.
7535
 * @param string $data        Data to decrypt.
7316
 * @return string             The now decrypted data.
7536
 * @return string             The now decrypted data.
7317
 */
7537
 */
-
 
7538
function rc4decrypt($data)
7318
function rc4decrypt($data) {
7539
{
7319
    return endecrypt(get_site_identifier(), $data, 'de');
7540
    return endecrypt(get_site_identifier(), $data, 'de');
Línea 7320... Línea 7541...
7320
}
7541
}
7321
 
7542
 
Línea 7327... Línea 7548...
7327
 * @param string $pwd The password to use when encrypting or decrypting
7548
 * @param string $pwd The password to use when encrypting or decrypting
7328
 * @param string $data The data to be decrypted/encrypted
7549
 * @param string $data The data to be decrypted/encrypted
7329
 * @param string $case Either 'de' for decrypt or '' for encrypt
7550
 * @param string $case Either 'de' for decrypt or '' for encrypt
7330
 * @return string
7551
 * @return string
7331
 */
7552
 */
7332
function endecrypt ($pwd, $data, $case) {
7553
function endecrypt($pwd, $data, $case)
-
 
7554
{
Línea 7333... Línea 7555...
7333
 
7555
 
7334
    if ($case == 'de') {
7556
    if ($case == 'de') {
7335
        $data = urldecode($data);
7557
        $data = urldecode($data);
Línea 7384... Línea 7606...
7384
 * This method validates a plug name. It is much faster than calling clean_param.
7606
 * This method validates a plug name. It is much faster than calling clean_param.
7385
 *
7607
 *
7386
 * @param string $name a string that might be a plugin name.
7608
 * @param string $name a string that might be a plugin name.
7387
 * @return bool if this string is a valid plugin name.
7609
 * @return bool if this string is a valid plugin name.
7388
 */
7610
 */
7389
function is_valid_plugin_name($name) {
7611
function is_valid_plugin_name($name)
-
 
7612
{
7390
    // This does not work for 'mod', bad luck, use any other type.
7613
    // This does not work for 'mod', bad luck, use any other type.
7391
    return core_component::is_valid_plugin_name('tool', $name);
7614
    return core_component::is_valid_plugin_name('tool', $name);
7392
}
7615
}
Línea 7393... Línea 7616...
7393
 
7616
 
Línea 7402... Línea 7625...
7402
 * @param string $file the name of file within the plugin that defines the
7625
 * @param string $file the name of file within the plugin that defines the
7403
 *      function. Defaults to lib.php.
7626
 *      function. Defaults to lib.php.
7404
 * @return array with frankenstyle plugin names as keys (e.g. 'report_courselist', 'mod_forum')
7627
 * @return array with frankenstyle plugin names as keys (e.g. 'report_courselist', 'mod_forum')
7405
 *      and the function names as values (e.g. 'report_courselist_hook', 'forum_hook').
7628
 *      and the function names as values (e.g. 'report_courselist_hook', 'forum_hook').
7406
 */
7629
 */
7407
function get_plugin_list_with_function($plugintype, $function, $file = 'lib.php') {
7630
function get_plugin_list_with_function($plugintype, $function, $file = 'lib.php')
-
 
7631
{
7408
    global $CFG;
7632
    global $CFG;
Línea 7409... Línea 7633...
7409
 
7633
 
7410
    // We don't include here as all plugin types files would be included.
7634
    // We don't include here as all plugin types files would be included.
Línea 7451... Línea 7675...
7451
 *      function. Defaults to lib.php.
7675
 *      function. Defaults to lib.php.
7452
 * @param bool $include Whether to include the files that contain the functions or not.
7676
 * @param bool $include Whether to include the files that contain the functions or not.
7453
 * @param bool $migratedtohook if true this is a deprecated lib.php callback, if hook callback is present then do nothing
7677
 * @param bool $migratedtohook if true this is a deprecated lib.php callback, if hook callback is present then do nothing
7454
 * @return array with [plugintype][plugin] = functionname
7678
 * @return array with [plugintype][plugin] = functionname
7455
 */
7679
 */
7456
function get_plugins_with_function($function, $file = 'lib.php', $include = true, bool $migratedtohook = false) {
7680
function get_plugins_with_function($function, $file = 'lib.php', $include = true, bool $migratedtohook = false)
-
 
7681
{
7457
    global $CFG;
7682
    global $CFG;
Línea 7458... Línea 7683...
7458
 
7683
 
7459
    if (during_initial_install() || isset($CFG->upgraderunning)) {
7684
    if (during_initial_install() || isset($CFG->upgraderunning)) {
7460
        // API functions _must not_ be called during an installation or upgrade.
7685
        // API functions _must not_ be called during an installation or upgrade.
7461
        return [];
7686
        return [];
Línea 7462... Línea 7687...
7462
    }
7687
    }
7463
 
7688
 
7464
    $plugincallback = $function;
7689
    $plugincallback = $function;
7465
    $filtermigrated = function($plugincallback, $pluginfunctions): array {
7690
    $filtermigrated = function ($plugincallback, $pluginfunctions): array {
7466
        foreach ($pluginfunctions as $plugintype => $plugins) {
7691
        foreach ($pluginfunctions as $plugintype => $plugins) {
7467
            foreach ($plugins as $plugin => $unusedfunction) {
7692
            foreach ($plugins as $plugin => $unusedfunction) {
7468
                $component = $plugintype . '_' . $plugin;
7693
                $component = $plugintype . '_' . $plugin;
Línea 7564... Línea 7789...
7564
 
7789
 
7565
            $pluginfunction = false;
7790
            $pluginfunction = false;
7566
            if (function_exists($fullfunction)) {
7791
            if (function_exists($fullfunction)) {
7567
                // Function exists with standard name. Store, indexed by frankenstyle name of plugin.
7792
                // Function exists with standard name. Store, indexed by frankenstyle name of plugin.
7568
                $pluginfunction = $fullfunction;
-
 
7569
 
7793
                $pluginfunction = $fullfunction;
7570
            } else if ($plugintype === 'mod') {
7794
            } else if ($plugintype === 'mod') {
7571
                // For modules, we also allow plugin without full frankenstyle but just starting with the module name.
7795
                // For modules, we also allow plugin without full frankenstyle but just starting with the module name.
7572
                $shortfunction = $plugin . '_' . $function;
7796
                $shortfunction = $plugin . '_' . $function;
7573
                if (function_exists($shortfunction)) {
7797
                if (function_exists($shortfunction)) {
Línea 7579... Línea 7803...
7579
                if (empty($pluginfunctions[$plugintype])) {
7803
                if (empty($pluginfunctions[$plugintype])) {
7580
                    $pluginfunctions[$plugintype] = array();
7804
                    $pluginfunctions[$plugintype] = array();
7581
                }
7805
                }
7582
                $pluginfunctions[$plugintype][$plugin] = $pluginfunction;
7806
                $pluginfunctions[$plugintype][$plugin] = $pluginfunction;
7583
            }
7807
            }
7584
 
-
 
7585
        }
7808
        }
7586
    }
7809
    }
7587
    if (!empty($CFG->allversionshash)) {
7810
    if (!empty($CFG->allversionshash)) {
7588
        $cache->set($key, $pluginfunctions);
7811
        $cache->set($key, $pluginfunctions);
7589
    }
7812
    }
Línea 7591... Línea 7814...
7591
    if ($migratedtohook && $file === 'lib.php') {
7814
    if ($migratedtohook && $file === 'lib.php') {
7592
        $pluginfunctions = $filtermigrated($plugincallback, $pluginfunctions);
7815
        $pluginfunctions = $filtermigrated($plugincallback, $pluginfunctions);
7593
    }
7816
    }
Línea 7594... Línea 7817...
7594
 
7817
 
7595
    return $pluginfunctions;
-
 
7596
 
7818
    return $pluginfunctions;
Línea 7597... Línea 7819...
7597
}
7819
}
7598
 
7820
 
7599
/**
7821
/**
Línea 7607... Línea 7829...
7607
 * @param string $directory relative directory from root
7829
 * @param string $directory relative directory from root
7608
 * @param string $exclude dir name to exclude from the list (defaults to none)
7830
 * @param string $exclude dir name to exclude from the list (defaults to none)
7609
 * @param string $basedir full path to the base dir where $plugin resides (defaults to $CFG->dirroot)
7831
 * @param string $basedir full path to the base dir where $plugin resides (defaults to $CFG->dirroot)
7610
 * @return array Sorted array of directory names found under the requested parameters
7832
 * @return array Sorted array of directory names found under the requested parameters
7611
 */
7833
 */
7612
function get_list_of_plugins($directory='mod', $exclude='', $basedir='') {
7834
function get_list_of_plugins($directory = 'mod', $exclude = '', $basedir = '')
-
 
7835
{
7613
    global $CFG;
7836
    global $CFG;
Línea 7614... Línea 7837...
7614
 
7837
 
Línea 7615... Línea 7838...
7615
    $plugins = array();
7838
    $plugins = array();
7616
 
7839
 
7617
    if (empty($basedir)) {
-
 
7618
        $basedir = $CFG->dirroot .'/'. $directory;
7840
    if (empty($basedir)) {
7619
 
7841
        $basedir = $CFG->dirroot . '/' . $directory;
7620
    } else {
7842
    } else {
Línea 7621... Línea 7843...
7621
        $basedir = $basedir .'/'. $directory;
7843
        $basedir = $basedir . '/' . $directory;
7622
    }
7844
    }
7623
 
7845
 
Línea 7657... Línea 7879...
7657
            }
7879
            }
7658
            if (array_key_exists($dir, $ignorelist)) {
7880
            if (array_key_exists($dir, $ignorelist)) {
7659
                // This directory features on the ignore list.
7881
                // This directory features on the ignore list.
7660
                continue;
7882
                continue;
7661
            }
7883
            }
7662
            if (filetype($basedir .'/'. $dir) != 'dir') {
7884
            if (filetype($basedir . '/' . $dir) != 'dir') {
7663
                continue;
7885
                continue;
7664
            }
7886
            }
7665
            $plugins[] = $dir;
7887
            $plugins[] = $dir;
7666
        }
7888
        }
7667
        closedir($dirhandle);
7889
        closedir($dirhandle);
Línea 7684... Línea 7906...
7684
 * @param bool $migratedtohook if true this is a deprecated callback, if hook callback is present then do nothing
7906
 * @param bool $migratedtohook if true this is a deprecated callback, if hook callback is present then do nothing
7685
 * @return mixed
7907
 * @return mixed
7686
 *
7908
 *
7687
 * @todo Decide about to deprecate and drop plugin_callback() - MDL-30743
7909
 * @todo Decide about to deprecate and drop plugin_callback() - MDL-30743
7688
 */
7910
 */
7689
function plugin_callback($type, $name, $feature, $action, $params = null, $default = null, bool $migratedtohook = false) {
7911
function plugin_callback($type, $name, $feature, $action, $params = null, $default = null, bool $migratedtohook = false)
-
 
7912
{
7690
    return component_callback($type . '_' . $name, $feature . '_' . $action, (array) $params, $default, $migratedtohook);
7913
    return component_callback($type . '_' . $name, $feature . '_' . $action, (array) $params, $default, $migratedtohook);
7691
}
7914
}
Línea 7692... Línea 7915...
7692
 
7915
 
7693
/**
7916
/**
Línea 7698... Línea 7921...
7698
 * @param array $params parameters of callback function
7921
 * @param array $params parameters of callback function
7699
 * @param mixed $default default value if callback function hasn't been defined, or if it retursn null.
7922
 * @param mixed $default default value if callback function hasn't been defined, or if it retursn null.
7700
 * @param bool $migratedtohook if true this is a deprecated callback, if hook callback is present then do nothing
7923
 * @param bool $migratedtohook if true this is a deprecated callback, if hook callback is present then do nothing
7701
 * @return mixed
7924
 * @return mixed
7702
 */
7925
 */
7703
function component_callback($component, $function, array $params = array(), $default = null, bool $migratedtohook = false) {
7926
function component_callback($component, $function, array $params = array(), $default = null, bool $migratedtohook = false)
-
 
7927
{
7704
    $functionname = component_callback_exists($component, $function);
7928
    $functionname = component_callback_exists($component, $function);
Línea 7705... Línea 7929...
7705
 
7929
 
7706
    if ($functionname) {
7930
    if ($functionname) {
7707
        if ($migratedtohook) {
7931
        if ($migratedtohook) {
Línea 7713... Línea 7937...
7713
                    return null;
7937
                    return null;
7714
                } else {
7938
                } else {
7715
                    $hookmessage = count($hooks) == 1 ? reset($hooks) : 'one of  ' . implode(', ', $hooks);
7939
                    $hookmessage = count($hooks) == 1 ? reset($hooks) : 'one of  ' . implode(', ', $hooks);
7716
                    debugging(
7940
                    debugging(
7717
                        "Callback $function in $component component should be migrated to new hook callback for $hookmessage",
7941
                        "Callback $function in $component component should be migrated to new hook callback for $hookmessage",
7718
                        DEBUG_DEVELOPER);
7942
                        DEBUG_DEVELOPER
-
 
7943
                    );
7719
                }
7944
                }
7720
            }
7945
            }
7721
        }
7946
        }
Línea 7722... Línea 7947...
7722
 
7947
 
Línea 7739... Línea 7964...
7739
 * @param string $component frankenstyle component name, e.g. 'mod_quiz'
7964
 * @param string $component frankenstyle component name, e.g. 'mod_quiz'
7740
 * @param string $function the rest of the function name, e.g. 'cron' will end up calling 'mod_quiz_cron'
7965
 * @param string $function the rest of the function name, e.g. 'cron' will end up calling 'mod_quiz_cron'
7741
 * @return mixed Complete function name to call if the callback exists or false if it doesn't.
7966
 * @return mixed Complete function name to call if the callback exists or false if it doesn't.
7742
 * @throws coding_exception if invalid component specfied
7967
 * @throws coding_exception if invalid component specfied
7743
 */
7968
 */
7744
function component_callback_exists($component, $function) {
7969
function component_callback_exists($component, $function)
-
 
7970
{
7745
    global $CFG; // This is needed for the inclusions.
7971
    global $CFG; // This is needed for the inclusions.
Línea 7746... Línea 7972...
7746
 
7972
 
7747
    $cleancomponent = clean_param($component, PARAM_COMPONENT);
7973
    $cleancomponent = clean_param($component, PARAM_COMPONENT);
7748
    if (empty($cleancomponent)) {
7974
    if (empty($cleancomponent)) {
Línea 7751... Línea 7977...
7751
    $component = $cleancomponent;
7977
    $component = $cleancomponent;
Línea 7752... Línea 7978...
7752
 
7978
 
7753
    list($type, $name) = core_component::normalize_component($component);
7979
    list($type, $name) = core_component::normalize_component($component);
Línea 7754... Línea 7980...
7754
    $component = $type . '_' . $name;
7980
    $component = $type . '_' . $name;
7755
 
7981
 
Línea 7756... Línea 7982...
7756
    $oldfunction = $name.'_'.$function;
7982
    $oldfunction = $name . '_' . $function;
7757
    $function = $component.'_'.$function;
7983
    $function = $component . '_' . $function;
7758
 
7984
 
7759
    $dir = core_component::get_component_directory($component);
7985
    $dir = core_component::get_component_directory($component);
Línea 7760... Línea 7986...
7760
    if (empty($dir)) {
7986
    if (empty($dir)) {
7761
        throw new coding_exception('Invalid component used in plugin/component_callback():' . $component);
7987
        throw new coding_exception('Invalid component used in plugin/component_callback():' . $component);
7762
    }
7988
    }
7763
 
7989
 
Línea 7764... Línea 7990...
7764
    // Load library and look for function.
7990
    // Load library and look for function.
7765
    if (file_exists($dir.'/lib.php')) {
7991
    if (file_exists($dir . '/lib.php')) {
7766
        require_once($dir.'/lib.php');
7992
        require_once($dir . '/lib.php');
Línea 7790... Línea 8016...
7790
 * @param   array       $params The arguments to pass into the method.
8016
 * @param   array       $params The arguments to pass into the method.
7791
 * @param   mixed       $default The default value.
8017
 * @param   mixed       $default The default value.
7792
 * @param   bool        $migratedtohook True if the callback has been migrated to a hook.
8018
 * @param   bool        $migratedtohook True if the callback has been migrated to a hook.
7793
 * @return  mixed       The return value.
8019
 * @return  mixed       The return value.
7794
 */
8020
 */
7795
function component_class_callback($classname, $methodname, array $params, $default = null, bool $migratedtohook = false) {
8021
function component_class_callback($classname, $methodname, array $params, $default = null, bool $migratedtohook = false)
-
 
8022
{
7796
    if (!class_exists($classname)) {
8023
    if (!class_exists($classname)) {
7797
        return $default;
8024
        return $default;
7798
    }
8025
    }
Línea 7799... Línea 8026...
7799
 
8026
 
Línea 7813... Línea 8040...
7813
                // Do not call the old class callback,
8040
                // Do not call the old class callback,
7814
                // it is there for compatibility with older Moodle versions only.
8041
                // it is there for compatibility with older Moodle versions only.
7815
                return null;
8042
                return null;
7816
            } else {
8043
            } else {
7817
                $hookmessage = count($hooks) == 1 ? reset($hooks) : 'one of  ' . implode(', ', $hooks);
8044
                $hookmessage = count($hooks) == 1 ? reset($hooks) : 'one of  ' . implode(', ', $hooks);
-
 
8045
                debugging(
7818
                debugging("Callback $callback in $component component should be migrated to new hook callback for $hookmessage",
8046
                    "Callback $callback in $component component should be migrated to new hook callback for $hookmessage",
7819
                        DEBUG_DEVELOPER);
8047
                    DEBUG_DEVELOPER
-
 
8048
                );
7820
            }
8049
            }
7821
        }
8050
        }
7822
    }
8051
    }
Línea 7823... Línea 8052...
7823
 
8052
 
Línea 7839... Línea 8068...
7839
 * @param mixed $default default value if feature support unknown
8068
 * @param mixed $default default value if feature support unknown
7840
 * @return mixed Feature result (false if not supported, null if feature is unknown,
8069
 * @return mixed Feature result (false if not supported, null if feature is unknown,
7841
 *         otherwise usually true but may have other feature-specific value such as array)
8070
 *         otherwise usually true but may have other feature-specific value such as array)
7842
 * @throws coding_exception
8071
 * @throws coding_exception
7843
 */
8072
 */
7844
function plugin_supports($type, $name, $feature, $default = null) {
8073
function plugin_supports($type, $name, $feature, $default = null)
-
 
8074
{
7845
    global $CFG;
8075
    global $CFG;
Línea 7846... Línea 8076...
7846
 
8076
 
7847
    if ($type === 'mod' and $name === 'NEWMODULE') {
8077
    if ($type === 'mod' and $name === 'NEWMODULE') {
7848
        // Somebody forgot to rename the module template.
8078
        // Somebody forgot to rename the module template.
Línea 7859... Línea 8089...
7859
    if ($type === 'mod') {
8089
    if ($type === 'mod') {
7860
        // We need this special case because we support subplugins in modules,
8090
        // We need this special case because we support subplugins in modules,
7861
        // otherwise it would end up in infinite loop.
8091
        // otherwise it would end up in infinite loop.
7862
        if (file_exists("$CFG->dirroot/mod/$name/lib.php")) {
8092
        if (file_exists("$CFG->dirroot/mod/$name/lib.php")) {
7863
            include_once("$CFG->dirroot/mod/$name/lib.php");
8093
            include_once("$CFG->dirroot/mod/$name/lib.php");
7864
            $function = $component.'_supports';
8094
            $function = $component . '_supports';
7865
            if (!function_exists($function)) {
8095
            if (!function_exists($function)) {
7866
                // Legacy non-frankenstyle function name.
8096
                // Legacy non-frankenstyle function name.
7867
                $function = $name.'_supports';
8097
                $function = $name . '_supports';
7868
            }
8098
            }
7869
        }
8099
        }
7870
 
-
 
7871
    } else {
8100
    } else {
7872
        if (!$path = core_component::get_plugin_directory($type, $name)) {
8101
        if (!$path = core_component::get_plugin_directory($type, $name)) {
7873
            // Non existent plugin type.
8102
            // Non existent plugin type.
7874
            return false;
8103
            return false;
7875
        }
8104
        }
7876
        if (file_exists("$path/lib.php")) {
8105
        if (file_exists("$path/lib.php")) {
7877
            include_once("$path/lib.php");
8106
            include_once("$path/lib.php");
7878
            $function = $component.'_supports';
8107
            $function = $component . '_supports';
7879
        }
8108
        }
7880
    }
8109
    }
Línea 7881... Línea 8110...
7881
 
8110
 
7882
    if ($function and function_exists($function)) {
8111
    if ($function and function_exists($function)) {
Línea 7899... Línea 8128...
7899
 * @todo Check PHP version being required here is it too low?
8128
 * @todo Check PHP version being required here is it too low?
7900
 *
8129
 *
7901
 * @param string $version The version of php being tested.
8130
 * @param string $version The version of php being tested.
7902
 * @return bool
8131
 * @return bool
7903
 */
8132
 */
7904
function check_php_version($version='5.2.4') {
8133
function check_php_version($version = '5.2.4')
-
 
8134
{
7905
    return (version_compare(phpversion(), $version) >= 0);
8135
    return (version_compare(phpversion(), $version) >= 0);
7906
}
8136
}
Línea 7907... Línea 8137...
7907
 
8137
 
7908
/**
8138
/**
Línea 7912... Línea 8142...
7912
 * if there are any mismatches.
8142
 * if there are any mismatches.
7913
 *
8143
 *
7914
 * @param bool $checkupgradeflag check the outagelessupgrade flag to see if an upgrade is running.
8144
 * @param bool $checkupgradeflag check the outagelessupgrade flag to see if an upgrade is running.
7915
 * @return bool
8145
 * @return bool
7916
 */
8146
 */
7917
function moodle_needs_upgrading($checkupgradeflag = true) {
8147
function moodle_needs_upgrading($checkupgradeflag = true)
-
 
8148
{
7918
    global $CFG, $DB;
8149
    global $CFG, $DB;
Línea 7919... Línea 8150...
7919
 
8150
 
7920
    // Say no if there is already an upgrade running.
8151
    // Say no if there is already an upgrade running.
7921
    if ($checkupgradeflag) {
8152
    if ($checkupgradeflag) {
Línea 7956... Línea 8187...
7956
 * the main version.php.
8187
 * the main version.php.
7957
 *
8188
 *
7958
 * @param bool $fromdisk should the version if source code files be used
8189
 * @param bool $fromdisk should the version if source code files be used
7959
 * @return string|false the major version like '2.3', false if could not be determined
8190
 * @return string|false the major version like '2.3', false if could not be determined
7960
 */
8191
 */
7961
function moodle_major_version($fromdisk = false) {
8192
function moodle_major_version($fromdisk = false)
-
 
8193
{
7962
    global $CFG;
8194
    global $CFG;
Línea 7963... Línea 8195...
7963
 
8195
 
7964
    if ($fromdisk) {
8196
    if ($fromdisk) {
7965
        $release = null;
8197
        $release = null;
7966
        require($CFG->dirroot.'/version.php');
8198
        require($CFG->dirroot . '/version.php');
7967
        if (empty($release)) {
8199
        if (empty($release)) {
7968
            return false;
8200
            return false;
7969
        }
-
 
7970
 
8201
        }
7971
    } else {
8202
    } else {
7972
        if (empty($CFG->release)) {
8203
        if (empty($CFG->release)) {
7973
            return false;
8204
            return false;
7974
        }
8205
        }
Línea 7987... Línea 8218...
7987
/**
8218
/**
7988
 * Gets the system locale
8219
 * Gets the system locale
7989
 *
8220
 *
7990
 * @return string Retuns the current locale.
8221
 * @return string Retuns the current locale.
7991
 */
8222
 */
7992
function moodle_getlocale() {
8223
function moodle_getlocale()
-
 
8224
{
7993
    global $CFG;
8225
    global $CFG;
Línea 7994... Línea 8226...
7994
 
8226
 
7995
    // Fetch the correct locale based on ostype.
8227
    // Fetch the correct locale based on ostype.
7996
    if ($CFG->ostype == 'WINDOWS') {
8228
    if ($CFG->ostype == 'WINDOWS') {
Línea 8010... Línea 8242...
8010
 * Sets the system locale
8242
 * Sets the system locale
8011
 *
8243
 *
8012
 * @category string
8244
 * @category string
8013
 * @param string $locale Can be used to force a locale
8245
 * @param string $locale Can be used to force a locale
8014
 */
8246
 */
8015
function moodle_setlocale($locale='') {
8247
function moodle_setlocale($locale = '')
-
 
8248
{
8016
    global $CFG;
8249
    global $CFG;
Línea 8017... Línea 8250...
8017
 
8250
 
Línea 8018... Línea 8251...
8018
    static $currentlocale = ''; // Last locale caching.
8251
    static $currentlocale = ''; // Last locale caching.
Línea 8034... Línea 8267...
8034
    // Due to some strange BUG we cannot set the LC_TIME directly, so we fetch current values,
8267
    // Due to some strange BUG we cannot set the LC_TIME directly, so we fetch current values,
8035
    // set LC_ALL and then set values again. Just wondering why we cannot set LC_ALL only??? - stronk7
8268
    // set LC_ALL and then set values again. Just wondering why we cannot set LC_ALL only??? - stronk7
8036
    // Some day, numeric, monetary and other categories should be set too, I think. :-/.
8269
    // Some day, numeric, monetary and other categories should be set too, I think. :-/.
Línea 8037... Línea 8270...
8037
 
8270
 
8038
    // Get current values.
8271
    // Get current values.
8039
    $monetary= setlocale (LC_MONETARY, 0);
8272
    $monetary = setlocale(LC_MONETARY, 0);
8040
    $numeric = setlocale (LC_NUMERIC, 0);
8273
    $numeric = setlocale(LC_NUMERIC, 0);
8041
    $ctype   = setlocale (LC_CTYPE, 0);
8274
    $ctype   = setlocale(LC_CTYPE, 0);
8042
    if ($CFG->ostype != 'WINDOWS') {
8275
    if ($CFG->ostype != 'WINDOWS') {
8043
        $messages= setlocale (LC_MESSAGES, 0);
8276
        $messages = setlocale(LC_MESSAGES, 0);
8044
    }
8277
    }
8045
    // Set locale to all.
8278
    // Set locale to all.
8046
    $result = setlocale (LC_ALL, $currentlocale);
8279
    $result = setlocale(LC_ALL, $currentlocale);
8047
    // If setting of locale fails try the other utf8 or utf-8 variant,
8280
    // If setting of locale fails try the other utf8 or utf-8 variant,
8048
    // some operating systems support both (Debian), others just one (OSX).
8281
    // some operating systems support both (Debian), others just one (OSX).
8049
    if ($result === false) {
8282
    if ($result === false) {
8050
        if (stripos($currentlocale, '.UTF-8') !== false) {
8283
        if (stripos($currentlocale, '.UTF-8') !== false) {
8051
            $newlocale = str_ireplace('.UTF-8', '.UTF8', $currentlocale);
8284
            $newlocale = str_ireplace('.UTF-8', '.UTF8', $currentlocale);
8052
            setlocale (LC_ALL, $newlocale);
8285
            setlocale(LC_ALL, $newlocale);
8053
        } else if (stripos($currentlocale, '.UTF8') !== false) {
8286
        } else if (stripos($currentlocale, '.UTF8') !== false) {
8054
            $newlocale = str_ireplace('.UTF8', '.UTF-8', $currentlocale);
8287
            $newlocale = str_ireplace('.UTF8', '.UTF-8', $currentlocale);
8055
            setlocale (LC_ALL, $newlocale);
8288
            setlocale(LC_ALL, $newlocale);
8056
        }
8289
        }
8057
    }
8290
    }
8058
    // Set old values.
8291
    // Set old values.
8059
    setlocale (LC_MONETARY, $monetary);
8292
    setlocale(LC_MONETARY, $monetary);
8060
    setlocale (LC_NUMERIC, $numeric);
8293
    setlocale(LC_NUMERIC, $numeric);
8061
    if ($CFG->ostype != 'WINDOWS') {
8294
    if ($CFG->ostype != 'WINDOWS') {
8062
        setlocale (LC_MESSAGES, $messages);
8295
        setlocale(LC_MESSAGES, $messages);
8063
    }
8296
    }
8064
    if ($currentlocale == 'tr_TR' or $currentlocale == 'tr_TR.UTF-8') {
8297
    if ($currentlocale == 'tr_TR' or $currentlocale == 'tr_TR.UTF-8') {
8065
        // To workaround a well-known PHP problem with Turkish letter Ii.
8298
        // To workaround a well-known PHP problem with Turkish letter Ii.
8066
        setlocale (LC_CTYPE, $ctype);
8299
        setlocale(LC_CTYPE, $ctype);
8067
    }
8300
    }
Línea 8068... Línea 8301...
8068
}
8301
}
8069
 
8302
 
Línea 8075... Línea 8308...
8075
 * @category string
8308
 * @category string
8076
 * @param string $string The text to be searched for words. May be HTML.
8309
 * @param string $string The text to be searched for words. May be HTML.
8077
 * @param int|null $format
8310
 * @param int|null $format
8078
 * @return int The count of words in the specified string
8311
 * @return int The count of words in the specified string
8079
 */
8312
 */
8080
function count_words($string, $format = null) {
8313
function count_words($string, $format = null)
-
 
8314
{
8081
    // Before stripping tags, add a space after the close tag of anything that is not obviously inline.
8315
    // Before stripping tags, add a space after the close tag of anything that is not obviously inline.
8082
    // Also, br is a special case because it definitely delimits a word, but has no close tag.
8316
    // Also, br is a special case because it definitely delimits a word, but has no close tag.
8083
    $string = preg_replace('~
8317
    $string = preg_replace('~
8084
            (                                   # Capture the tag we match.
8318
            (                                   # Capture the tag we match.
8085
                </                              # Start of close tag.
8319
                </                              # Start of close tag.
Línea 8121... Línea 8355...
8121
 * @category string
8355
 * @category string
8122
 * @param string $string The text to be searched for letters. May be HTML.
8356
 * @param string $string The text to be searched for letters. May be HTML.
8123
 * @param int|null $format
8357
 * @param int|null $format
8124
 * @return int The count of letters in the specified text.
8358
 * @return int The count of letters in the specified text.
8125
 */
8359
 */
8126
function count_letters($string, $format = null) {
8360
function count_letters($string, $format = null)
-
 
8361
{
8127
    if ($format !== null && $format != FORMAT_PLAIN) {
8362
    if ($format !== null && $format != FORMAT_PLAIN) {
8128
        // Match the usual text cleaning before display.
8363
        // Match the usual text cleaning before display.
8129
        // Ideally we should apply multilang filter only here, other filters might add extra text.
8364
        // Ideally we should apply multilang filter only here, other filters might add extra text.
8130
        $string = format_text($string, $format, ['filter' => false, 'noclean' => false, 'para' => false]);
8365
        $string = format_text($string, $format, ['filter' => false, 'noclean' => false, 'para' => false]);
8131
    }
8366
    }
Línea 8140... Línea 8375...
8140
 * Generate and return a random string of the specified length.
8375
 * Generate and return a random string of the specified length.
8141
 *
8376
 *
8142
 * @param int $length The length of the string to be created.
8377
 * @param int $length The length of the string to be created.
8143
 * @return string
8378
 * @return string
8144
 */
8379
 */
8145
function random_string($length=15) {
8380
function random_string($length = 15)
-
 
8381
{
8146
    $randombytes = random_bytes($length);
8382
    $randombytes = random_bytes($length);
8147
    $pool  = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
8383
    $pool  = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
8148
    $pool .= 'abcdefghijklmnopqrstuvwxyz';
8384
    $pool .= 'abcdefghijklmnopqrstuvwxyz';
8149
    $pool .= '0123456789';
8385
    $pool .= '0123456789';
8150
    $poollen = strlen($pool);
8386
    $poollen = strlen($pool);
8151
    $string = '';
8387
    $string = '';
8152
    for ($i = 0; $i < $length; $i++) {
8388
    for ($i = 0; $i < $length; $i++) {
8153
        $rand = ord($randombytes[$i]);
8389
        $rand = ord($randombytes[$i]);
8154
        $string .= substr($pool, ($rand%($poollen)), 1);
8390
        $string .= substr($pool, ($rand % ($poollen)), 1);
8155
    }
8391
    }
8156
    return $string;
8392
    return $string;
8157
}
8393
}
Línea 8158... Línea 8394...
8158
 
8394
 
Línea 8163... Línea 8399...
8163
 * larger pool of characters and generates a string between 24 and 32 characters
8399
 * larger pool of characters and generates a string between 24 and 32 characters
8164
 *
8400
 *
8165
 * @param int $length Optional if set generates a string to exactly this length
8401
 * @param int $length Optional if set generates a string to exactly this length
8166
 * @return string
8402
 * @return string
8167
 */
8403
 */
8168
function complex_random_string($length=null) {
8404
function complex_random_string($length = null)
-
 
8405
{
8169
    $pool  = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
8406
    $pool  = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
8170
    $pool .= '`~!@#%^&*()_+-=[];,./<>?:{} ';
8407
    $pool .= '`~!@#%^&*()_+-=[];,./<>?:{} ';
8171
    $poollen = strlen($pool);
8408
    $poollen = strlen($pool);
8172
    if ($length===null) {
8409
    if ($length === null) {
8173
        $length = floor(rand(24, 32));
8410
        $length = floor(rand(24, 32));
8174
    }
8411
    }
8175
    $randombytes = random_bytes($length);
8412
    $randombytes = random_bytes($length);
8176
    $string = '';
8413
    $string = '';
8177
    for ($i = 0; $i < $length; $i++) {
8414
    for ($i = 0; $i < $length; $i++) {
8178
        $rand = ord($randombytes[$i]);
8415
        $rand = ord($randombytes[$i]);
8179
        $string .= $pool[($rand%$poollen)];
8416
        $string .= $pool[($rand % $poollen)];
8180
    }
8417
    }
8181
    return $string;
8418
    return $string;
8182
}
8419
}
Línea 8183... Línea 8420...
8183
 
8420
 
Línea 8190... Línea 8427...
8190
 * @param int $ideal ideal string length
8427
 * @param int $ideal ideal string length
8191
 * @param boolean $exact if false, $text will not be cut mid-word
8428
 * @param boolean $exact if false, $text will not be cut mid-word
8192
 * @param string $ending The string to append if the passed string is truncated
8429
 * @param string $ending The string to append if the passed string is truncated
8193
 * @return string $truncate shortened string
8430
 * @return string $truncate shortened string
8194
 */
8431
 */
8195
function shorten_text($text, $ideal=30, $exact = false, $ending='...') {
8432
function shorten_text($text, $ideal = 30, $exact = false, $ending = '...')
-
 
8433
{
8196
    // If the plain text is shorter than the maximum length, return the whole text.
8434
    // If the plain text is shorter than the maximum length, return the whole text.
8197
    if (core_text::strlen(preg_replace('/<.*?>/', '', $text)) <= $ideal) {
8435
    if (core_text::strlen(preg_replace('/<.*?>/', '', $text)) <= $ideal) {
8198
        return $text;
8436
        return $text;
8199
    }
8437
    }
Línea 8217... Línea 8455...
8217
            // If it's an "empty element" with or without xhtml-conform closing slash (f.e. <br/>).
8455
            // If it's an "empty element" with or without xhtml-conform closing slash (f.e. <br/>).
8218
            if (!preg_match('/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is', $linematchings[1])) {
8456
            if (!preg_match('/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is', $linematchings[1])) {
8219
                if (preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $linematchings[1], $tagmatchings)) {
8457
                if (preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $linematchings[1], $tagmatchings)) {
8220
                    // Record closing tag.
8458
                    // Record closing tag.
8221
                    $tagdetails[] = (object) array(
8459
                    $tagdetails[] = (object) array(
8222
                            'open' => false,
8460
                        'open' => false,
8223
                            'tag'  => core_text::strtolower($tagmatchings[1]),
8461
                        'tag'  => core_text::strtolower($tagmatchings[1]),
8224
                            'pos'  => core_text::strlen($truncate),
8462
                        'pos'  => core_text::strlen($truncate),
8225
                        );
8463
                    );
8226
 
-
 
8227
                } else if (preg_match('/^<\s*([^\s>!]+).*?>$/s', $linematchings[1], $tagmatchings)) {
8464
                } else if (preg_match('/^<\s*([^\s>!]+).*?>$/s', $linematchings[1], $tagmatchings)) {
8228
                    // Record opening tag.
8465
                    // Record opening tag.
8229
                    $tagdetails[] = (object) array(
8466
                    $tagdetails[] = (object) array(
8230
                            'open' => true,
8467
                        'open' => true,
8231
                            'tag'  => core_text::strtolower($tagmatchings[1]),
8468
                        'tag'  => core_text::strtolower($tagmatchings[1]),
8232
                            'pos'  => core_text::strlen($truncate),
8469
                        'pos'  => core_text::strlen($truncate),
8233
                        );
8470
                    );
8234
                } else if (preg_match('/^<!--\[if\s.*?\]>$/s', $linematchings[1], $tagmatchings)) {
8471
                } else if (preg_match('/^<!--\[if\s.*?\]>$/s', $linematchings[1], $tagmatchings)) {
8235
                    $tagdetails[] = (object) array(
8472
                    $tagdetails[] = (object) array(
8236
                            'open' => true,
8473
                        'open' => true,
8237
                            'tag'  => core_text::strtolower('if'),
8474
                        'tag'  => core_text::strtolower('if'),
8238
                            'pos'  => core_text::strlen($truncate),
8475
                        'pos'  => core_text::strlen($truncate),
8239
                    );
8476
                    );
8240
                } else if (preg_match('/^<!--<!\[endif\]-->$/s', $linematchings[1], $tagmatchings)) {
8477
                } else if (preg_match('/^<!--<!\[endif\]-->$/s', $linematchings[1], $tagmatchings)) {
8241
                    $tagdetails[] = (object) array(
8478
                    $tagdetails[] = (object) array(
8242
                            'open' => false,
8479
                        'open' => false,
8243
                            'tag'  => core_text::strtolower('if'),
8480
                        'tag'  => core_text::strtolower('if'),
8244
                            'pos'  => core_text::strlen($truncate),
8481
                        'pos'  => core_text::strlen($truncate),
8245
                    );
8482
                    );
8246
                }
8483
                }
8247
            }
8484
            }
8248
            // Add html-tag to $truncate'd text.
8485
            // Add html-tag to $truncate'd text.
8249
            $truncate .= $linematchings[1];
8486
            $truncate .= $linematchings[1];
Línea 8257... Línea 8494...
8257
            $entitieslength = 0;
8494
            $entitieslength = 0;
8258
            // Search for html entities.
8495
            // Search for html entities.
8259
            if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $linematchings[2], $entities, PREG_OFFSET_CAPTURE)) {
8496
            if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $linematchings[2], $entities, PREG_OFFSET_CAPTURE)) {
8260
                // Calculate the real length of all entities in the legal range.
8497
                // Calculate the real length of all entities in the legal range.
8261
                foreach ($entities[0] as $entity) {
8498
                foreach ($entities[0] as $entity) {
8262
                    if ($entity[1]+1-$entitieslength <= $left) {
8499
                    if ($entity[1] + 1 - $entitieslength <= $left) {
8263
                        $left--;
8500
                        $left--;
8264
                        $entitieslength += core_text::strlen($entity[0]);
8501
                        $entitieslength += core_text::strlen($entity[0]);
8265
                    } else {
8502
                    } else {
8266
                        // No more characters left.
8503
                        // No more characters left.
8267
                        break;
8504
                        break;
Línea 8346... Línea 8583...
8346
 * @param string $filename file name
8583
 * @param string $filename file name
8347
 * @param int $length ideal string length
8584
 * @param int $length ideal string length
8348
 * @param bool $includehash Whether to include a file hash in the shortened version. This ensures uniqueness.
8585
 * @param bool $includehash Whether to include a file hash in the shortened version. This ensures uniqueness.
8349
 * @return string $shortened shortened file name
8586
 * @return string $shortened shortened file name
8350
 */
8587
 */
8351
function shorten_filename($filename, $length = MAX_FILENAME_SIZE, $includehash = false) {
8588
function shorten_filename($filename, $length = MAX_FILENAME_SIZE, $includehash = false)
-
 
8589
{
8352
    $shortened = $filename;
8590
    $shortened = $filename;
8353
    // Extract a part of the filename if it's char size exceeds the ideal string length.
8591
    // Extract a part of the filename if it's char size exceeds the ideal string length.
8354
    if (core_text::strlen($filename) > $length) {
8592
    if (core_text::strlen($filename) > $length) {
8355
        // Exclude extension if present in filename.
8593
        // Exclude extension if present in filename.
8356
        $mimetypes = get_mimetypes_array();
8594
        $mimetypes = get_mimetypes_array();
Línea 8374... Línea 8612...
8374
 * @param array $path The paths to reduce the length.
8612
 * @param array $path The paths to reduce the length.
8375
 * @param int $length Ideal string length
8613
 * @param int $length Ideal string length
8376
 * @param bool $includehash Whether to include a file hash in the shortened version. This ensures uniqueness.
8614
 * @param bool $includehash Whether to include a file hash in the shortened version. This ensures uniqueness.
8377
 * @return array $result Shortened paths in array.
8615
 * @return array $result Shortened paths in array.
8378
 */
8616
 */
8379
function shorten_filenames(array $path, $length = MAX_FILENAME_SIZE, $includehash = false) {
8617
function shorten_filenames(array $path, $length = MAX_FILENAME_SIZE, $includehash = false)
-
 
8618
{
8380
    $result = null;
8619
    $result = null;
Línea 8381... Línea 8620...
8381
 
8620
 
8382
    $result = array_reduce($path, function($carry, $singlepath) use ($length, $includehash) {
8621
    $result = array_reduce($path, function ($carry, $singlepath) use ($length, $includehash) {
8383
        $carry[] = shorten_filename($singlepath, $length, $includehash);
8622
        $carry[] = shorten_filename($singlepath, $length, $includehash);
8384
        return $carry;
8623
        return $carry;
Línea 8385... Línea 8624...
8385
    }, []);
8624
    }, []);
Línea 8393... Línea 8632...
8393
 *
8632
 *
8394
 * @param int $startdate Timestamp for the start date
8633
 * @param int $startdate Timestamp for the start date
8395
 * @param int $thedate Timestamp for the end date
8634
 * @param int $thedate Timestamp for the end date
8396
 * @return string
8635
 * @return string
8397
 */
8636
 */
8398
function getweek ($startdate, $thedate) {
8637
function getweek($startdate, $thedate)
-
 
8638
{
8399
    if ($thedate < $startdate) {
8639
    if ($thedate < $startdate) {
8400
        return 0;
8640
        return 0;
8401
    }
8641
    }
Línea 8402... Línea 8642...
8402
 
8642
 
Línea 8410... Línea 8650...
8410
 * {@link http://es2.php.net/manual/en/function.str-shuffle.php#73254}
8650
 * {@link http://es2.php.net/manual/en/function.str-shuffle.php#73254}
8411
 *
8651
 *
8412
 * @param int $maxlen  The maximum size of the password being generated.
8652
 * @param int $maxlen  The maximum size of the password being generated.
8413
 * @return string
8653
 * @return string
8414
 */
8654
 */
8415
function generate_password($maxlen=10) {
8655
function generate_password($maxlen = 10)
-
 
8656
{
8416
    global $CFG;
8657
    global $CFG;
Línea 8417... Línea 8658...
8417
 
8658
 
8418
    if (empty($CFG->passwordpolicy)) {
8659
    if (empty($CFG->passwordpolicy)) {
8419
        $fillers = PASSWORD_DIGITS;
8660
        $fillers = PASSWORD_DIGITS;
Línea 8453... Línea 8694...
8453
        while ($nonalphanum > strlen($passwordnonalphanum)) {
8694
        while ($nonalphanum > strlen($passwordnonalphanum)) {
8454
            $passwordnonalphanum .= PASSWORD_NONALPHANUM;
8695
            $passwordnonalphanum .= PASSWORD_NONALPHANUM;
8455
        }
8696
        }
Línea 8456... Línea 8697...
8456
 
8697
 
8457
        // Now mix and shuffle it all.
8698
        // Now mix and shuffle it all.
8458
        $password = str_shuffle (substr(str_shuffle ($passwordlower), 0, $lower) .
8699
        $password = str_shuffle(substr(str_shuffle($passwordlower), 0, $lower) .
8459
                                 substr(str_shuffle ($passwordupper), 0, $upper) .
8700
            substr(str_shuffle($passwordupper), 0, $upper) .
8460
                                 substr(str_shuffle ($passworddigits), 0, $digits) .
8701
            substr(str_shuffle($passworddigits), 0, $digits) .
8461
                                 substr(str_shuffle ($passwordnonalphanum), 0 , $nonalphanum) .
8702
            substr(str_shuffle($passwordnonalphanum), 0, $nonalphanum) .
8462
                                 substr(str_shuffle ($passwordlower .
8703
            substr(str_shuffle($passwordlower .
8463
                                                     $passwordupper .
8704
                $passwordupper .
8464
                                                     $passworddigits .
8705
                $passworddigits .
8465
                                                     $passwordnonalphanum), 0 , $additional));
8706
                $passwordnonalphanum), 0, $additional));
Línea 8466... Línea 8707...
8466
    }
8707
    }
8467
 
8708
 
Línea 8468... Línea 8709...
8468
    return substr ($password, 0, $maxlen);
8709
    return substr($password, 0, $maxlen);
8469
}
8710
}
8470
 
8711
 
Línea 8482... Línea 8723...
8482
 * @param bool $localized use localized decimal separator
8723
 * @param bool $localized use localized decimal separator
8483
 * @param bool $stripzeros If true, removes final zeros after decimal point. It will be ignored and the trailing zeros after
8724
 * @param bool $stripzeros If true, removes final zeros after decimal point. It will be ignored and the trailing zeros after
8484
 *                         the decimal point are always striped if $decimalpoints is -1.
8725
 *                         the decimal point are always striped if $decimalpoints is -1.
8485
 * @return string locale float
8726
 * @return string locale float
8486
 */
8727
 */
8487
function format_float($float, $decimalpoints=1, $localized=true, $stripzeros=false) {
8728
function format_float($float, $decimalpoints = 1, $localized = true, $stripzeros = false)
-
 
8729
{
8488
    if (is_null($float)) {
8730
    if (is_null($float)) {
8489
        return '';
8731
        return '';
8490
    }
8732
    }
8491
    if ($localized) {
8733
    if ($localized) {
8492
        $separator = get_string('decsep', 'langconfig');
8734
        $separator = get_string('decsep', 'langconfig');
Línea 8515... Línea 8757...
8515
 *
8757
 *
8516
 * @param string $localefloat locale aware float representation
8758
 * @param string $localefloat locale aware float representation
8517
 * @param bool $strict If true, then check the input and return false if it is not a valid number.
8759
 * @param bool $strict If true, then check the input and return false if it is not a valid number.
8518
 * @return mixed float|bool - false or the parsed float.
8760
 * @return mixed float|bool - false or the parsed float.
8519
 */
8761
 */
8520
function unformat_float($localefloat, $strict = false) {
8762
function unformat_float($localefloat, $strict = false)
-
 
8763
{
8521
    $localefloat = trim((string)$localefloat);
8764
    $localefloat = trim((string)$localefloat);
Línea 8522... Línea 8765...
8522
 
8765
 
8523
    if ($localefloat == '') {
8766
    if ($localefloat == '') {
8524
        return null;
8767
        return null;
Línea 8539... Línea 8782...
8539
 * Unlike PHP's shuffle() this function works on any machine.
8782
 * Unlike PHP's shuffle() this function works on any machine.
8540
 *
8783
 *
8541
 * @param array $array The array to be rearranged
8784
 * @param array $array The array to be rearranged
8542
 * @return array
8785
 * @return array
8543
 */
8786
 */
8544
function swapshuffle($array) {
8787
function swapshuffle($array)
-
 
8788
{
Línea 8545... Línea 8789...
8545
 
8789
 
8546
    $last = count($array) - 1;
8790
    $last = count($array) - 1;
8547
    for ($i = 0; $i <= $last; $i++) {
8791
    for ($i = 0; $i <= $last; $i++) {
8548
        $from = rand(0, $last);
8792
        $from = rand(0, $last);
Línea 8557... Línea 8801...
8557
 * Like {@link swapshuffle()}, but works on associative arrays
8801
 * Like {@link swapshuffle()}, but works on associative arrays
8558
 *
8802
 *
8559
 * @param array $array The associative array to be rearranged
8803
 * @param array $array The associative array to be rearranged
8560
 * @return array
8804
 * @return array
8561
 */
8805
 */
8562
function swapshuffle_assoc($array) {
8806
function swapshuffle_assoc($array)
-
 
8807
{
Línea 8563... Línea 8808...
8563
 
8808
 
8564
    $newarray = array();
8809
    $newarray = array();
Línea 8565... Línea 8810...
8565
    $newkeys = swapshuffle(array_keys($array));
8810
    $newkeys = swapshuffle(array_keys($array));
Línea 8579... Línea 8824...
8579
 *
8824
 *
8580
 * @param array $array
8825
 * @param array $array
8581
 * @param int $draws
8826
 * @param int $draws
8582
 * @return array
8827
 * @return array
8583
 */
8828
 */
8584
function draw_rand_array($array, $draws) {
8829
function draw_rand_array($array, $draws)
-
 
8830
{
Línea 8585... Línea 8831...
8585
 
8831
 
Línea 8586... Línea 8832...
8586
    $return = array();
8832
    $return = array();
Línea 8611... Línea 8857...
8611
 *
8857
 *
8612
 * @param string $a The first Microtime
8858
 * @param string $a The first Microtime
8613
 * @param string $b The second Microtime
8859
 * @param string $b The second Microtime
8614
 * @return string
8860
 * @return string
8615
 */
8861
 */
8616
function microtime_diff($a, $b) {
8862
function microtime_diff($a, $b)
-
 
8863
{
8617
    list($adec, $asec) = explode(' ', $a);
8864
    list($adec, $asec) = explode(' ', $a);
8618
    list($bdec, $bsec) = explode(' ', $b);
8865
    list($bdec, $bsec) = explode(' ', $b);
8619
    return $bsec - $asec + $bdec - $adec;
8866
    return $bsec - $asec + $bdec - $adec;
8620
}
8867
}
Línea 8625... Línea 8872...
8625
 *
8872
 *
8626
 * @param string $list The string to explode into array bits
8873
 * @param string $list The string to explode into array bits
8627
 * @param string $separator The separator used within the list string
8874
 * @param string $separator The separator used within the list string
8628
 * @return array The now assembled array
8875
 * @return array The now assembled array
8629
 */
8876
 */
8630
function make_menu_from_list($list, $separator=',') {
8877
function make_menu_from_list($list, $separator = ',')
-
 
8878
{
Línea 8631... Línea 8879...
8631
 
8879
 
8632
    $array = array_reverse(explode($separator, $list), true);
8880
    $array = array_reverse(explode($separator, $list), true);
8633
    foreach ($array as $key => $item) {
8881
    foreach ($array as $key => $item) {
8634
        $outarray[$key+1] = trim($item);
8882
        $outarray[$key + 1] = trim($item);
8635
    }
8883
    }
8636
    return $outarray;
8884
    return $outarray;
Línea 8637... Línea 8885...
8637
}
8885
}
Línea 8647... Línea 8895...
8647
 * @todo Finish documenting this function or better deprecated this completely!
8895
 * @todo Finish documenting this function or better deprecated this completely!
8648
 *
8896
 *
8649
 * @param int $gradingtype
8897
 * @param int $gradingtype
8650
 * @return array
8898
 * @return array
8651
 */
8899
 */
8652
function make_grades_menu($gradingtype) {
8900
function make_grades_menu($gradingtype)
-
 
8901
{
8653
    global $DB;
8902
    global $DB;
Línea 8654... Línea 8903...
8654
 
8903
 
8655
    $grades = array();
8904
    $grades = array();
8656
    if ($gradingtype < 0) {
8905
    if ($gradingtype < 0) {
8657
        if ($scale = $DB->get_record('scale', array('id'=> (-$gradingtype)))) {
8906
        if ($scale = $DB->get_record('scale', array('id' => (-$gradingtype)))) {
8658
            return make_menu_from_list($scale->scale);
8907
            return make_menu_from_list($scale->scale);
8659
        }
8908
        }
8660
    } else if ($gradingtype > 0) {
8909
    } else if ($gradingtype > 0) {
8661
        for ($i=$gradingtype; $i>=0; $i--) {
8910
        for ($i = $gradingtype; $i >= 0; $i--) {
8662
            $grades[$i] = $i .' / '. $gradingtype;
8911
            $grades[$i] = $i . ' / ' . $gradingtype;
8663
        }
8912
        }
8664
        return $grades;
8913
        return $grades;
8665
    }
8914
    }
8666
    return $grades;
8915
    return $grades;
Línea 8673... Línea 8922...
8673
 *
8922
 *
8674
 * @uses $_SERVER
8923
 * @uses $_SERVER
8675
 * @param string $extra Extra string to append to the end of the code
8924
 * @param string $extra Extra string to append to the end of the code
8676
 * @return string
8925
 * @return string
8677
 */
8926
 */
8678
function make_unique_id_code($extra = '') {
8927
function make_unique_id_code($extra = '')
-
 
8928
{
Línea 8679... Línea 8929...
8679
 
8929
 
8680
    $hostname = 'unknownhost';
8930
    $hostname = 'unknownhost';
8681
    if (!empty($_SERVER['HTTP_HOST'])) {
8931
    if (!empty($_SERVER['HTTP_HOST'])) {
8682
        $hostname = $_SERVER['HTTP_HOST'];
8932
        $hostname = $_SERVER['HTTP_HOST'];
Línea 8691... Línea 8941...
8691
    $date = gmdate("ymdHis");
8941
    $date = gmdate("ymdHis");
Línea 8692... Línea 8942...
8692
 
8942
 
Línea 8693... Línea 8943...
8693
    $random =  random_string(6);
8943
    $random =  random_string(6);
8694
 
8944
 
8695
    if ($extra) {
8945
    if ($extra) {
8696
        return $hostname .'+'. $date .'+'. $random .'+'. $extra;
8946
        return $hostname . '+' . $date . '+' . $random . '+' . $extra;
8697
    } else {
8947
    } else {
8698
        return $hostname .'+'. $date .'+'. $random;
8948
        return $hostname . '+' . $date . '+' . $random;
Línea 8699... Línea 8949...
8699
    }
8949
    }
Línea 8714... Línea 8964...
8714
 * @param string $addr    The address you are checking
8964
 * @param string $addr    The address you are checking
8715
 * @param string $subnetstr    The string of subnet addresses
8965
 * @param string $subnetstr    The string of subnet addresses
8716
 * @param bool $checkallzeros    The state to whether check for 0.0.0.0
8966
 * @param bool $checkallzeros    The state to whether check for 0.0.0.0
8717
 * @return bool
8967
 * @return bool
8718
 */
8968
 */
8719
function address_in_subnet($addr, $subnetstr, $checkallzeros = false) {
8969
function address_in_subnet($addr, $subnetstr, $checkallzeros = false)
-
 
8970
{
Línea 8720... Línea 8971...
8720
 
8971
 
8721
    if ($addr == '0.0.0.0' && !$checkallzeros) {
8972
    if ($addr == '0.0.0.0' && !$checkallzeros) {
8722
        return false;
8973
        return false;
8723
    }
8974
    }
Línea 8766... Línea 9017...
8766
                    }
9017
                    }
8767
                    continue;
9018
                    continue;
8768
                }
9019
                }
8769
                $ipparts = explode(':', $ip);
9020
                $ipparts = explode(':', $ip);
8770
                $modulo  = $mask % 16;
9021
                $modulo  = $mask % 16;
8771
                $ipnet   = array_slice($ipparts, 0, ($mask-$modulo)/16);
9022
                $ipnet   = array_slice($ipparts, 0, ($mask - $modulo) / 16);
8772
                $addrnet = array_slice($addrparts, 0, ($mask-$modulo)/16);
9023
                $addrnet = array_slice($addrparts, 0, ($mask - $modulo) / 16);
8773
                if (implode(':', $ipnet) === implode(':', $addrnet)) {
9024
                if (implode(':', $ipnet) === implode(':', $addrnet)) {
8774
                    if ($modulo == 0) {
9025
                    if ($modulo == 0) {
8775
                        return true;
9026
                        return true;
8776
                    }
9027
                    }
8777
                    $pos     = ($mask-$modulo)/16;
9028
                    $pos     = ($mask - $modulo) / 16;
8778
                    $ipnet   = hexdec($ipparts[$pos]);
9029
                    $ipnet   = hexdec($ipparts[$pos]);
8779
                    $addrnet = hexdec($addrparts[$pos]);
9030
                    $addrnet = hexdec($addrparts[$pos]);
8780
                    $mask    = 0xffff << (16 - $modulo);
9031
                    $mask    = 0xffff << (16 - $modulo);
8781
                    if (($addrnet & $mask) == ($ipnet & $mask)) {
9032
                    if (($addrnet & $mask) == ($ipnet & $mask)) {
8782
                        return true;
9033
                        return true;
8783
                    }
9034
                    }
8784
                }
9035
                }
8785
 
-
 
8786
            } else {
9036
            } else {
8787
                // IPv4.
9037
                // IPv4.
8788
                if ($ipv6) {
9038
                if ($ipv6) {
8789
                    continue;
9039
                    continue;
8790
                }
9040
                }
Línea 8803... Línea 9053...
8803
                $mask = 0xffffffff << (32 - $mask);
9053
                $mask = 0xffffffff << (32 - $mask);
8804
                if (((ip2long($addr) & $mask) == (ip2long($ip) & $mask))) {
9054
                if (((ip2long($addr) & $mask) == (ip2long($ip) & $mask))) {
8805
                    return true;
9055
                    return true;
8806
                }
9056
                }
8807
            }
9057
            }
8808
 
-
 
8809
        } else if (strpos($subnet, '-') !== false) {
9058
        } else if (strpos($subnet, '-') !== false) {
8810
            // 2: xxx.xxx.xxx.xxx-yyy or  xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx::xxxx-yyyy. A range of IP addresses in the last group.
9059
            // 2: xxx.xxx.xxx.xxx-yyy or  xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx::xxxx-yyyy. A range of IP addresses in the last group.
8811
            $parts = explode('-', $subnet);
9060
            $parts = explode('-', $subnet);
8812
            if (count($parts) != 2) {
9061
            if (count($parts) != 2) {
8813
                continue;
9062
                continue;
Línea 8840... Línea 9089...
8840
                $addrend = hexdec($addrparts[7]);
9089
                $addrend = hexdec($addrparts[7]);
Línea 8841... Línea 9090...
8841
 
9090
 
8842
                if (($addrend >= $start) and ($addrend <= $end)) {
9091
                if (($addrend >= $start) and ($addrend <= $end)) {
8843
                    return true;
9092
                    return true;
8844
                }
-
 
8845
 
9093
                }
8846
            } else {
9094
            } else {
8847
                // IPv4.
9095
                // IPv4.
8848
                if ($ipv6) {
9096
                if ($ipv6) {
8849
                    continue;
9097
                    continue;
Línea 8861... Línea 9109...
8861
 
9109
 
8862
                if ((ip2long($addr) >= ip2long($ipstart)) and (ip2long($addr) <= ip2long($ipend))) {
9110
                if ((ip2long($addr) >= ip2long($ipstart)) and (ip2long($addr) <= ip2long($ipend))) {
8863
                    return true;
9111
                    return true;
8864
                }
9112
                }
8865
            }
-
 
8866
 
9113
            }
8867
        } else {
9114
        } else {
8868
            // 3: xxx.xxx or xxx.xxx. or xxx:xxx:xxxx or xxx:xxx:xxxx.
9115
            // 3: xxx.xxx or xxx.xxx. or xxx:xxx:xxxx or xxx:xxx:xxxx.
8869
            if (strpos($subnet, ':') !== false) {
9116
            if (strpos($subnet, ':') !== false) {
8870
                // IPv6.
9117
                // IPv6.
8871
                if (!$ipv6) {
9118
                if (!$ipv6) {
8872
                    continue;
9119
                    continue;
8873
                }
9120
                }
8874
                $parts = explode(':', $subnet);
9121
                $parts = explode(':', $subnet);
8875
                $count = count($parts);
9122
                $count = count($parts);
8876
                if ($parts[$count-1] === '') {
9123
                if ($parts[$count - 1] === '') {
8877
                    unset($parts[$count-1]); // Trim trailing :'s.
9124
                    unset($parts[$count - 1]); // Trim trailing :'s.
8878
                    $count--;
9125
                    $count--;
8879
                    $subnet = implode('.', $parts);
9126
                    $subnet = implode('.', $parts);
8880
                }
9127
                }
8881
                $isip = cleanremoteaddr($subnet, false); // Normalise.
9128
                $isip = cleanremoteaddr($subnet, false); // Normalise.
Línea 8885... Línea 9132...
8885
                    }
9132
                    }
8886
                    continue;
9133
                    continue;
8887
                } else if ($count > 8) {
9134
                } else if ($count > 8) {
8888
                    continue;
9135
                    continue;
8889
                }
9136
                }
8890
                $zeros = array_fill(0, 8-$count, '0');
9137
                $zeros = array_fill(0, 8 - $count, '0');
8891
                $subnet = $subnet.':'.implode(':', $zeros).'/'.($count*16);
9138
                $subnet = $subnet . ':' . implode(':', $zeros) . '/' . ($count * 16);
8892
                if (address_in_subnet($addr, $subnet)) {
9139
                if (address_in_subnet($addr, $subnet)) {
8893
                    return true;
9140
                    return true;
8894
                }
9141
                }
8895
 
-
 
8896
            } else {
9142
            } else {
8897
                // IPv4.
9143
                // IPv4.
8898
                if ($ipv6) {
9144
                if ($ipv6) {
8899
                    continue;
9145
                    continue;
8900
                }
9146
                }
8901
                $parts = explode('.', $subnet);
9147
                $parts = explode('.', $subnet);
8902
                $count = count($parts);
9148
                $count = count($parts);
8903
                if ($parts[$count-1] === '') {
9149
                if ($parts[$count - 1] === '') {
8904
                    unset($parts[$count-1]); // Trim trailing .
9150
                    unset($parts[$count - 1]); // Trim trailing .
8905
                    $count--;
9151
                    $count--;
8906
                    $subnet = implode('.', $parts);
9152
                    $subnet = implode('.', $parts);
8907
                }
9153
                }
8908
                if ($count == 4) {
9154
                if ($count == 4) {
8909
                    $subnet = cleanremoteaddr($subnet, false); // Normalise.
9155
                    $subnet = cleanremoteaddr($subnet, false); // Normalise.
Línea 8912... Línea 9158...
8912
                    }
9158
                    }
8913
                    continue;
9159
                    continue;
8914
                } else if ($count > 4) {
9160
                } else if ($count > 4) {
8915
                    continue;
9161
                    continue;
8916
                }
9162
                }
8917
                $zeros = array_fill(0, 4-$count, '0');
9163
                $zeros = array_fill(0, 4 - $count, '0');
8918
                $subnet = $subnet.'.'.implode('.', $zeros).'/'.($count*8);
9164
                $subnet = $subnet . '.' . implode('.', $zeros) . '/' . ($count * 8);
8919
                if (address_in_subnet($addr, $subnet)) {
9165
                if (address_in_subnet($addr, $subnet)) {
8920
                    return true;
9166
                    return true;
8921
                }
9167
                }
8922
            }
9168
            }
8923
        }
9169
        }
Línea 8932... Línea 9178...
8932
 * @param string $string The string to write
9178
 * @param string $string The string to write
8933
 * @param string $eol The end of line char(s) to use
9179
 * @param string $eol The end of line char(s) to use
8934
 * @param string $sleep Period to make the application sleep
9180
 * @param string $sleep Period to make the application sleep
8935
 *                      This ensures any messages have time to display before redirect
9181
 *                      This ensures any messages have time to display before redirect
8936
 */
9182
 */
8937
function mtrace($string, $eol="\n", $sleep=0) {
9183
function mtrace($string, $eol = "\n", $sleep = 0)
-
 
9184
{
8938
    global $CFG;
9185
    global $CFG;
Línea 8939... Línea 9186...
8939
 
9186
 
8940
    if (isset($CFG->mtrace_wrapper) && function_exists($CFG->mtrace_wrapper)) {
9187
    if (isset($CFG->mtrace_wrapper) && function_exists($CFG->mtrace_wrapper)) {
8941
        $fn = $CFG->mtrace_wrapper;
9188
        $fn = $CFG->mtrace_wrapper;
Línea 8963... Línea 9210...
8963
/**
9210
/**
8964
 * Helper to {@see mtrace()} an exception or throwable, including all relevant information.
9211
 * Helper to {@see mtrace()} an exception or throwable, including all relevant information.
8965
 *
9212
 *
8966
 * @param Throwable $e the error to ouptput.
9213
 * @param Throwable $e the error to ouptput.
8967
 */
9214
 */
8968
function mtrace_exception(Throwable $e): void {
9215
function mtrace_exception(Throwable $e): void
-
 
9216
{
8969
    $info = get_exception_info($e);
9217
    $info = get_exception_info($e);
Línea 8970... Línea 9218...
8970
 
9218
 
8971
    $message = $info->message;
9219
    $message = $info->message;
8972
    if ($info->debuginfo) {
9220
    if ($info->debuginfo) {
Línea 8983... Línea 9231...
8983
 * Replace 1 or more slashes or backslashes to 1 slash
9231
 * Replace 1 or more slashes or backslashes to 1 slash
8984
 *
9232
 *
8985
 * @param string $path The path to strip
9233
 * @param string $path The path to strip
8986
 * @return string the path with double slashes removed
9234
 * @return string the path with double slashes removed
8987
 */
9235
 */
8988
function cleardoubleslashes ($path) {
9236
function cleardoubleslashes($path)
-
 
9237
{
8989
    return preg_replace('/(\/|\\\){1,}/', '/', $path);
9238
    return preg_replace('/(\/|\\\){1,}/', '/', $path);
8990
}
9239
}
Línea 8991... Línea 9240...
8991
 
9240
 
8992
/**
9241
/**
8993
 * Is the current ip in a given list?
9242
 * Is the current ip in a given list?
8994
 *
9243
 *
8995
 * @param string $list
9244
 * @param string $list
8996
 * @return bool
9245
 * @return bool
8997
 */
9246
 */
-
 
9247
function remoteip_in_list($list)
8998
function remoteip_in_list($list) {
9248
{
Línea 8999... Línea 9249...
8999
    $clientip = getremoteaddr(null);
9249
    $clientip = getremoteaddr(null);
9000
 
9250
 
9001
    if (!$clientip) {
9251
    if (!$clientip) {
Línea 9009... Línea 9259...
9009
 * Returns most reliable client address
9259
 * Returns most reliable client address
9010
 *
9260
 *
9011
 * @param string $default If an address can't be determined, then return this
9261
 * @param string $default If an address can't be determined, then return this
9012
 * @return string The remote IP address
9262
 * @return string The remote IP address
9013
 */
9263
 */
9014
function getremoteaddr($default='0.0.0.0') {
9264
function getremoteaddr($default = '0.0.0.0')
-
 
9265
{
9015
    global $CFG;
9266
    global $CFG;
Línea 9016... Línea 9267...
9016
 
9267
 
9017
    if (!isset($CFG->getremoteaddrconf)) {
9268
    if (!isset($CFG->getremoteaddrconf)) {
9018
        // This will happen, for example, before just after the upgrade, as the
9269
        // This will happen, for example, before just after the upgrade, as the
Línea 9029... Línea 9280...
9029
    }
9280
    }
9030
    if (!($variablestoskip & GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR)) {
9281
    if (!($variablestoskip & GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR)) {
9031
        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
9282
        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
9032
            $forwardedaddresses = explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']);
9283
            $forwardedaddresses = explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']);
Línea 9033... Línea 9284...
9033
 
9284
 
9034
            $forwardedaddresses = array_filter($forwardedaddresses, function($ip) {
9285
            $forwardedaddresses = array_filter($forwardedaddresses, function ($ip) {
9035
                global $CFG;
9286
                global $CFG;
9036
                return !\core\ip_utils::is_ip_in_subnet_list($ip, $CFG->reverseproxyignore ?? '', ',');
9287
                return !\core\ip_utils::is_ip_in_subnet_list($ip, $CFG->reverseproxyignore ?? '', ',');
Línea 9037... Línea 9288...
9037
            });
9288
            });
Línea 9071... Línea 9322...
9071
 *
9322
 *
9072
 * @param string $addr IPv4 or IPv6 address
9323
 * @param string $addr IPv4 or IPv6 address
9073
 * @param bool $compress use IPv6 address compression
9324
 * @param bool $compress use IPv6 address compression
9074
 * @return string normalised ip address string, null if error
9325
 * @return string normalised ip address string, null if error
9075
 */
9326
 */
9076
function cleanremoteaddr($addr, $compress=false) {
9327
function cleanremoteaddr($addr, $compress = false)
-
 
9328
{
9077
    $addr = trim($addr);
9329
    $addr = trim($addr);
Línea 9078... Línea 9330...
9078
 
9330
 
9079
    if (strpos($addr, ':') !== false) {
9331
    if (strpos($addr, ':') !== false) {
9080
        // Can be only IPv6.
9332
        // Can be only IPv6.
9081
        $parts = explode(':', $addr);
9333
        $parts = explode(':', $addr);
Línea 9082... Línea 9334...
9082
        $count = count($parts);
9334
        $count = count($parts);
9083
 
9335
 
9084
        if (strpos($parts[$count-1], '.') !== false) {
9336
        if (strpos($parts[$count - 1], '.') !== false) {
9085
            // Legacy ipv4 notation.
9337
            // Legacy ipv4 notation.
9086
            $last = array_pop($parts);
9338
            $last = array_pop($parts);
9087
            $ipv4 = cleanremoteaddr($last, true);
9339
            $ipv4 = cleanremoteaddr($last, true);
9088
            if ($ipv4 === null) {
9340
            if ($ipv4 === null) {
9089
                return null;
9341
                return null;
9090
            }
9342
            }
9091
            $bits = explode('.', $ipv4);
9343
            $bits = explode('.', $ipv4);
9092
            $parts[] = dechex($bits[0]).dechex($bits[1]);
9344
            $parts[] = dechex($bits[0]) . dechex($bits[1]);
9093
            $parts[] = dechex($bits[2]).dechex($bits[3]);
9345
            $parts[] = dechex($bits[2]) . dechex($bits[3]);
9094
            $count = count($parts);
9346
            $count = count($parts);
Línea 9095... Línea 9347...
9095
            $addr = implode(':', $parts);
9347
            $addr = implode(':', $parts);
Línea 9173... Línea 9425...
9173
 * Is IP address a public address?
9425
 * Is IP address a public address?
9174
 *
9426
 *
9175
 * @param string $ip The ip to check
9427
 * @param string $ip The ip to check
9176
 * @return bool true if the ip is public
9428
 * @return bool true if the ip is public
9177
 */
9429
 */
9178
function ip_is_public($ip) {
9430
function ip_is_public($ip)
-
 
9431
{
9179
    return (bool) filter_var($ip, FILTER_VALIDATE_IP, (FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE));
9432
    return (bool) filter_var($ip, FILTER_VALIDATE_IP, (FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE));
9180
}
9433
}
Línea 9181... Línea 9434...
9181
 
9434
 
9182
/**
9435
/**
9183
 * This function will make a complete copy of anything it's given,
9436
 * This function will make a complete copy of anything it's given,
9184
 * regardless of whether it's an object or not.
9437
 * regardless of whether it's an object or not.
9185
 *
9438
 *
9186
 * @param mixed $thing Something you want cloned
9439
 * @param mixed $thing Something you want cloned
9187
 * @return mixed What ever it is you passed it
9440
 * @return mixed What ever it is you passed it
9188
 */
9441
 */
-
 
9442
function fullclone($thing)
9189
function fullclone($thing) {
9443
{
9190
    return unserialize(serialize($thing));
9444
    return unserialize(serialize($thing));
Línea 9191... Línea 9445...
9191
}
9445
}
9192
 
9446
 
Línea 9198... Línea 9452...
9198
 * @param int $min The minimum value
9452
 * @param int $min The minimum value
9199
 * @param int $value The value to check
9453
 * @param int $value The value to check
9200
 * @param int $max The maximum value
9454
 * @param int $max The maximum value
9201
 * @return int
9455
 * @return int
9202
 */
9456
 */
9203
function bounded_number($min, $value, $max) {
9457
function bounded_number($min, $value, $max)
-
 
9458
{
9204
    if ($value < $min) {
9459
    if ($value < $min) {
9205
        return $min;
9460
        return $min;
9206
    }
9461
    }
9207
    if ($value > $max) {
9462
    if ($value > $max) {
9208
        return $max;
9463
        return $max;
Línea 9214... Línea 9469...
9214
 * Check if there is a nested array within the passed array
9469
 * Check if there is a nested array within the passed array
9215
 *
9470
 *
9216
 * @param array $array
9471
 * @param array $array
9217
 * @return bool true if there is a nested array false otherwise
9472
 * @return bool true if there is a nested array false otherwise
9218
 */
9473
 */
9219
function array_is_nested($array) {
9474
function array_is_nested($array)
-
 
9475
{
9220
    foreach ($array as $value) {
9476
    foreach ($array as $value) {
9221
        if (is_array($value)) {
9477
        if (is_array($value)) {
9222
            return true;
9478
            return true;
9223
        }
9479
        }
9224
    }
9480
    }
Línea 9231... Línea 9487...
9231
 * values ready for use, and each of the individual stats provided
9487
 * values ready for use, and each of the individual stats provided
9232
 * separately as well.
9488
 * separately as well.
9233
 *
9489
 *
9234
 * @return array
9490
 * @return array
9235
 */
9491
 */
9236
function get_performance_info() {
9492
function get_performance_info()
-
 
9493
{
9237
    global $CFG, $PERF, $DB, $PAGE;
9494
    global $CFG, $PERF, $DB, $PAGE;
Línea 9238... Línea 9495...
9238
 
9495
 
9239
    $info = array();
9496
    $info = array();
Línea 9246... Línea 9503...
9246
    }
9503
    }
9247
    $info['html'] .= '<ul class="list-unstyled row mx-md-0">';         // Holds userfriendly HTML representation.
9504
    $info['html'] .= '<ul class="list-unstyled row mx-md-0">';         // Holds userfriendly HTML representation.
Línea 9248... Línea 9505...
9248
 
9505
 
Línea 9249... Línea 9506...
9249
    $info['realtime'] = microtime_diff($PERF->starttime, microtime());
9506
    $info['realtime'] = microtime_diff($PERF->starttime, microtime());
9250
 
9507
 
Línea 9251... Línea 9508...
9251
    $info['html'] .= '<li class="timeused col-sm-4">'.$info['realtime'].' secs</li> ';
9508
    $info['html'] .= '<li class="timeused col-sm-4">' . $info['realtime'] . ' secs</li> ';
9252
    $info['txt'] .= 'time: '.$info['realtime'].'s ';
9509
    $info['txt'] .= 'time: ' . $info['realtime'] . 's ';
Línea 9253... Línea 9510...
9253
 
9510
 
9254
    // GET/POST (or NULL if $_SERVER['REQUEST_METHOD'] is undefined) is useful for txt logged information.
9511
    // GET/POST (or NULL if $_SERVER['REQUEST_METHOD'] is undefined) is useful for txt logged information.
9255
    $info['txt'] .= 'method: ' . ($_SERVER['REQUEST_METHOD'] ?? "NULL") . ' ';
9512
    $info['txt'] .= 'method: ' . ($_SERVER['REQUEST_METHOD'] ?? "NULL") . ' ';
9256
 
9513
 
9257
    if (function_exists('memory_get_usage')) {
9514
    if (function_exists('memory_get_usage')) {
9258
        $info['memory_total'] = memory_get_usage();
9515
        $info['memory_total'] = memory_get_usage();
9259
        $info['memory_growth'] = memory_get_usage() - $PERF->startmemory;
9516
        $info['memory_growth'] = memory_get_usage() - $PERF->startmemory;
Línea 9260... Línea 9517...
9260
        $info['html'] .= '<li class="memoryused col-sm-4">RAM: '.display_size($info['memory_total']).'</li> ';
9517
        $info['html'] .= '<li class="memoryused col-sm-4">RAM: ' . display_size($info['memory_total']) . '</li> ';
9261
        $info['txt']  .= 'memory_total: '.$info['memory_total'].'B (' . display_size($info['memory_total']).') memory_growth: '.
9518
        $info['txt']  .= 'memory_total: ' . $info['memory_total'] . 'B (' . display_size($info['memory_total']) . ') memory_growth: ' .
9262
            $info['memory_growth'].'B ('.display_size($info['memory_growth']).') ';
9519
            $info['memory_growth'] . 'B (' . display_size($info['memory_growth']) . ') ';
9263
    }
9520
    }
9264
 
9521
 
Línea 9265... Línea 9522...
9265
    if (function_exists('memory_get_peak_usage')) {
9522
    if (function_exists('memory_get_peak_usage')) {
9266
        $info['memory_peak'] = memory_get_peak_usage();
9523
        $info['memory_peak'] = memory_get_peak_usage();
9267
        $info['html'] .= '<li class="memoryused col-sm-4">RAM peak: '.display_size($info['memory_peak']).'</li> ';
9524
        $info['html'] .= '<li class="memoryused col-sm-4">RAM peak: ' . display_size($info['memory_peak']) . '</li> ';
9268
        $info['txt']  .= 'memory_peak: '.$info['memory_peak'].'B (' . display_size($info['memory_peak']).') ';
9525
        $info['txt']  .= 'memory_peak: ' . $info['memory_peak'] . 'B (' . display_size($info['memory_peak']) . ') ';
9269
    }
9526
    }
Línea 9270... Línea 9527...
9270
 
9527
 
9271
    $info['html'] .= '</ul><ul class="list-unstyled row mx-md-0">';
9528
    $info['html'] .= '</ul><ul class="list-unstyled row mx-md-0">';
9272
    $inc = get_included_files();
9529
    $inc = get_included_files();
9273
    $info['includecount'] = count($inc);
9530
    $info['includecount'] = count($inc);
Línea 9297... Línea 9554...
9297
            $info['html'] .= "<li class='$key col-sm-4'>$nicenames[$key]: $value </li> ";
9554
            $info['html'] .= "<li class='$key col-sm-4'>$nicenames[$key]: $value </li> ";
9298
            $info['txt'] .= "$key: $value ";
9555
            $info['txt'] .= "$key: $value ";
9299
        }
9556
        }
9300
    }
9557
    }
Línea 9301... Línea 9558...
9301
 
9558
 
9302
    $info['dbqueries'] = $DB->perf_get_reads().'/'.$DB->perf_get_writes();
9559
    $info['dbqueries'] = $DB->perf_get_reads() . '/' . $DB->perf_get_writes();
9303
    $info['html'] .= '<li class="dbqueries col-sm-4">DB reads/writes: '.$info['dbqueries'].'</li> ';
9560
    $info['html'] .= '<li class="dbqueries col-sm-4">DB reads/writes: ' . $info['dbqueries'] . '</li> ';
Línea 9304... Línea 9561...
9304
    $info['txt'] .= 'db reads/writes: '.$info['dbqueries'].' ';
9561
    $info['txt'] .= 'db reads/writes: ' . $info['dbqueries'] . ' ';
9305
 
9562
 
9306
    if ($DB->want_read_slave()) {
9563
    if ($DB->want_read_slave()) {
9307
        $info['dbreads_slave'] = $DB->perf_get_reads_slave();
9564
        $info['dbreads_slave'] = $DB->perf_get_reads_slave();
9308
        $info['html'] .= '<li class="dbqueries col-sm-4">DB reads from slave: '.$info['dbreads_slave'].'</li> ';
9565
        $info['html'] .= '<li class="dbqueries col-sm-4">DB reads from slave: ' . $info['dbreads_slave'] . '</li> ';
Línea 9309... Línea 9566...
9309
        $info['txt'] .= 'db reads from slave: '.$info['dbreads_slave'].' ';
9566
        $info['txt'] .= 'db reads from slave: ' . $info['dbreads_slave'] . ' ';
9310
    }
9567
    }
9311
 
9568
 
Línea 9312... Línea 9569...
9312
    $info['dbtime'] = round($DB->perf_get_queries_time(), 5);
9569
    $info['dbtime'] = round($DB->perf_get_queries_time(), 5);
9313
    $info['html'] .= '<li class="dbtime col-sm-4">DB queries time: '.$info['dbtime'].' secs</li> ';
9570
    $info['html'] .= '<li class="dbtime col-sm-4">DB queries time: ' . $info['dbtime'] . ' secs</li> ';
9314
    $info['txt'] .= 'db queries time: ' . $info['dbtime'] . 's ';
9571
    $info['txt'] .= 'db queries time: ' . $info['dbtime'] . 's ';
Línea 9329... Línea 9586...
9329
    // /proc will only work under some linux configurations
9586
    // /proc will only work under some linux configurations
9330
    // while uptime is there under MacOSX/Darwin and other unices.
9587
    // while uptime is there under MacOSX/Darwin and other unices.
9331
    if (is_readable('/proc/loadavg') && $loadavg = @file('/proc/loadavg')) {
9588
    if (is_readable('/proc/loadavg') && $loadavg = @file('/proc/loadavg')) {
9332
        list($serverload) = explode(' ', $loadavg[0]);
9589
        list($serverload) = explode(' ', $loadavg[0]);
9333
        unset($loadavg);
9590
        unset($loadavg);
9334
    } else if ( function_exists('is_executable') && is_executable('/usr/bin/uptime') && $loadavg = `/usr/bin/uptime` ) {
9591
    } else if (function_exists('is_executable') && is_executable('/usr/bin/uptime') && $loadavg = `/usr/bin/uptime`) {
9335
        if (preg_match('/load averages?: (\d+[\.,:]\d+)/', $loadavg, $matches)) {
9592
        if (preg_match('/load averages?: (\d+[\.,:]\d+)/', $loadavg, $matches)) {
9336
            $serverload = $matches[1];
9593
            $serverload = $matches[1];
9337
        } else {
9594
        } else {
9338
            trigger_error('Could not parse uptime output!');
9595
            trigger_error('Could not parse uptime output!');
9339
        }
9596
        }
9340
    }
9597
    }
9341
    if (!empty($serverload)) {
9598
    if (!empty($serverload)) {
9342
        $info['serverload'] = $serverload;
9599
        $info['serverload'] = $serverload;
9343
        $info['html'] .= '<li class="serverload col-sm-4">Load average: '.$info['serverload'].'</li> ';
9600
        $info['html'] .= '<li class="serverload col-sm-4">Load average: ' . $info['serverload'] . '</li> ';
9344
        $info['txt'] .= "serverload: {$info['serverload']} ";
9601
        $info['txt'] .= "serverload: {$info['serverload']} ";
9345
    }
9602
    }
Línea 9346... Línea 9603...
9346
 
9603
 
9347
    // Display size of session if session started.
9604
    // Display size of session if session started.
Línea 9583... Línea 9840...
9583
 
9840
 
Línea 9584... Línea 9841...
9584
        $html .= html_writer::table($table);
9841
        $html .= html_writer::table($table);
9585
 
9842
 
9586
        $info['cachesused'] = "$hits / $misses / $sets";
9843
        $info['cachesused'] = "$hits / $misses / $sets";
9587
        $info['html'] .= $html;
9844
        $info['html'] .= $html;
9588
        $info['txt'] .= $text.'. ';
9845
        $info['txt'] .= $text . '. ';
9589
    } else {
9846
    } else {
9590
        $info['cachesused'] = '0 / 0 / 0';
9847
        $info['cachesused'] = '0 / 0 / 0';
9591
        $info['html'] .= '<div class="cachesused">Caches used (hits/misses/sets): 0/0/0</div>';
9848
        $info['html'] .= '<div class="cachesused">Caches used (hits/misses/sets): 0/0/0</div>';
Línea 9637... Línea 9894...
9637
        }
9894
        }
9638
        $info['html'] .= html_writer::table($table);
9895
        $info['html'] .= html_writer::table($table);
9639
        $info['txt'] .= $text . '. ';
9896
        $info['txt'] .= $text . '. ';
9640
    }
9897
    }
Línea 9641... Línea 9898...
9641
 
9898
 
9642
    $info['html'] = '<div class="performanceinfo siteinfo container-fluid px-md-0 overflow-auto pt-3">'.$info['html'].'</div>';
9899
    $info['html'] = '<div class="performanceinfo siteinfo container-fluid px-md-0 overflow-auto pt-3">' . $info['html'] . '</div>';
9643
    return $info;
9900
    return $info;
Línea 9644... Línea 9901...
9644
}
9901
}
9645
 
9902
 
Línea 9651... Línea 9908...
9651
 * @param string $filepath Original filepath
9908
 * @param string $filepath Original filepath
9652
 * @param string $prefix Prefix to use for the temporary name
9909
 * @param string $prefix Prefix to use for the temporary name
9653
 * @return string|bool New file path or false if failed
9910
 * @return string|bool New file path or false if failed
9654
 * @since Moodle 3.10
9911
 * @since Moodle 3.10
9655
 */
9912
 */
9656
function rename_to_unused_name(string $filepath, string $prefix = '_temp_') {
9913
function rename_to_unused_name(string $filepath, string $prefix = '_temp_')
-
 
9914
{
9657
    $dir = dirname($filepath);
9915
    $dir = dirname($filepath);
9658
    $basename = $dir . '/' . $prefix;
9916
    $basename = $dir . '/' . $prefix;
9659
    $limit = 0;
9917
    $limit = 0;
9660
    while ($limit < 100) {
9918
    while ($limit < 100) {
9661
        // Select a new name based on a random number.
9919
        // Select a new name based on a random number.
Línea 9681... Línea 9939...
9681
 *
9939
 *
9682
 * @param string $dir directory path
9940
 * @param string $dir directory path
9683
 * @param bool $contentonly
9941
 * @param bool $contentonly
9684
 * @return bool success, true also if dir does not exist
9942
 * @return bool success, true also if dir does not exist
9685
 */
9943
 */
9686
function remove_dir($dir, $contentonly=false) {
9944
function remove_dir($dir, $contentonly = false)
-
 
9945
{
9687
    if (!is_dir($dir)) {
9946
    if (!is_dir($dir)) {
9688
        // Nothing to do.
9947
        // Nothing to do.
9689
        return true;
9948
        return true;
9690
    }
9949
    }
Línea 9703... Línea 9962...
9703
 
9962
 
9704
    if (!$handle = opendir($dir)) {
9963
    if (!$handle = opendir($dir)) {
9705
        return false;
9964
        return false;
9706
    }
9965
    }
9707
    $result = true;
9966
    $result = true;
9708
    while (false!==($item = readdir($handle))) {
9967
    while (false !== ($item = readdir($handle))) {
9709
        if ($item != '.' && $item != '..') {
9968
        if ($item != '.' && $item != '..') {
9710
            if (is_dir($dir.'/'.$item)) {
9969
            if (is_dir($dir . '/' . $item)) {
9711
                $result = remove_dir($dir.'/'.$item) && $result;
9970
                $result = remove_dir($dir . '/' . $item) && $result;
9712
            } else {
9971
            } else {
9713
                $result = unlink($dir.'/'.$item) && $result;
9972
                $result = unlink($dir . '/' . $item) && $result;
9714
            }
9973
            }
9715
        }
9974
        }
9716
    }
9975
    }
9717
    closedir($handle);
9976
    closedir($handle);
Línea 9730... Línea 9989...
9730
 *
9989
 *
9731
 * @param mixed $obj Name of class or real object to test
9990
 * @param mixed $obj Name of class or real object to test
9732
 * @param string $property name of property to find
9991
 * @param string $property name of property to find
9733
 * @return bool true if property exists
9992
 * @return bool true if property exists
9734
 */
9993
 */
9735
function object_property_exists( $obj, $property ) {
9994
function object_property_exists($obj, $property)
-
 
9995
{
9736
    if (is_string( $obj )) {
9996
    if (is_string($obj)) {
9737
        $properties = get_class_vars( $obj );
9997
        $properties = get_class_vars($obj);
9738
    } else {
9998
    } else {
9739
        $properties = get_object_vars( $obj );
9999
        $properties = get_object_vars($obj);
9740
    }
10000
    }
9741
    return array_key_exists( $property, $properties );
10001
    return array_key_exists($property, $properties);
9742
}
10002
}
Línea 9743... Línea 10003...
9743
 
10003
 
9744
/**
10004
/**
9745
 * Converts an object into an associative array
10005
 * Converts an object into an associative array
Línea 9753... Línea 10013...
9753
 * and return all available properties in getIterator()
10013
 * and return all available properties in getIterator()
9754
 *
10014
 *
9755
 * @param mixed $var
10015
 * @param mixed $var
9756
 * @return array
10016
 * @return array
9757
 */
10017
 */
9758
function convert_to_array($var) {
10018
function convert_to_array($var)
-
 
10019
{
9759
    $result = array();
10020
    $result = array();
Línea 9760... Línea 10021...
9760
 
10021
 
9761
    // Loop over elements/properties.
10022
    // Loop over elements/properties.
9762
    foreach ($var as $key => $value) {
10023
    foreach ($var as $key => $value) {
Línea 9775... Línea 10036...
9775
 * Detect a custom script replacement in the data directory that will
10036
 * Detect a custom script replacement in the data directory that will
9776
 * replace an existing moodle script
10037
 * replace an existing moodle script
9777
 *
10038
 *
9778
 * @return string|bool full path name if a custom script exists, false if no custom script exists
10039
 * @return string|bool full path name if a custom script exists, false if no custom script exists
9779
 */
10040
 */
9780
function custom_script_path() {
10041
function custom_script_path()
-
 
10042
{
9781
    global $CFG, $SCRIPT;
10043
    global $CFG, $SCRIPT;
Línea 9782... Línea 10044...
9782
 
10044
 
9783
    if ($SCRIPT === null) {
10045
    if ($SCRIPT === null) {
9784
        // Probably some weird external script.
10046
        // Probably some weird external script.
Línea 9800... Línea 10062...
9800
 * is in moodlelib because it does not rely on loading any of the MNET code.
10062
 * is in moodlelib because it does not rely on loading any of the MNET code.
9801
 *
10063
 *
9802
 * @param object $user A valid user object
10064
 * @param object $user A valid user object
9803
 * @return bool        True if the user is from a remote Moodle.
10065
 * @return bool        True if the user is from a remote Moodle.
9804
 */
10066
 */
9805
function is_mnet_remote_user($user) {
10067
function is_mnet_remote_user($user)
-
 
10068
{
9806
    global $CFG;
10069
    global $CFG;
Línea 9807... Línea 10070...
9807
 
10070
 
9808
    if (!isset($CFG->mnet_localhost_id)) {
10071
    if (!isset($CFG->mnet_localhost_id)) {
9809
        include_once($CFG->dirroot . '/mnet/lib.php');
10072
        include_once($CFG->dirroot . '/mnet/lib.php');
Línea 9817... Línea 10080...
9817
 
10080
 
9818
/**
10081
/**
9819
 * This function will search for browser prefereed languages, setting Moodle
10082
 * This function will search for browser prefereed languages, setting Moodle
9820
 * to use the best one available if $SESSION->lang is undefined
10083
 * to use the best one available if $SESSION->lang is undefined
9821
 */
10084
 */
-
 
10085
function setup_lang_from_browser()
9822
function setup_lang_from_browser() {
10086
{
Línea 9823... Línea 10087...
9823
    global $CFG, $SESSION, $USER;
10087
    global $CFG, $SESSION, $USER;
9824
 
10088
 
9825
    if (!empty($SESSION->lang) or !empty($USER->lang) or empty($CFG->autolang)) {
10089
    if (!empty($SESSION->lang) or !empty($USER->lang) or empty($CFG->autolang)) {
Línea 9839... Línea 10103...
9839
 
10103
 
9840
    $order = 1.0;
10104
    $order = 1.0;
9841
    foreach ($rawlangs as $lang) {
10105
    foreach ($rawlangs as $lang) {
9842
        if (strpos($lang, ';') === false) {
10106
        if (strpos($lang, ';') === false) {
9843
            $langs[(string)$order] = $lang;
10107
            $langs[(string)$order] = $lang;
9844
            $order = $order-0.01;
10108
            $order = $order - 0.01;
9845
        } else {
10109
        } else {
9846
            $parts = explode(';', $lang);
10110
            $parts = explode(';', $lang);
9847
            $pos = strpos($parts[1], '=');
10111
            $pos = strpos($parts[1], '=');
9848
            $langs[substr($parts[1], $pos+1)] = $parts[0];
10112
            $langs[substr($parts[1], $pos + 1)] = $parts[0];
9849
        }
10113
        }
9850
    }
10114
    }
Línea 9851... Línea 10115...
9851
    krsort($langs, SORT_NUMERIC);
10115
    krsort($langs, SORT_NUMERIC);
Línea 9876... Línea 10140...
9876
 * Any errors just result in the proxy being used (least bad)
10140
 * Any errors just result in the proxy being used (least bad)
9877
 *
10141
 *
9878
 * @param string $url url to check
10142
 * @param string $url url to check
9879
 * @return boolean true if we should bypass the proxy
10143
 * @return boolean true if we should bypass the proxy
9880
 */
10144
 */
9881
function is_proxybypass( $url ) {
10145
function is_proxybypass($url)
-
 
10146
{
9882
    global $CFG;
10147
    global $CFG;
Línea 9883... Línea 10148...
9883
 
10148
 
9884
    // Sanity check.
10149
    // Sanity check.
9885
    if (empty($CFG->proxyhost) or empty($CFG->proxybypass)) {
10150
    if (empty($CFG->proxyhost) or empty($CFG->proxybypass)) {
9886
        return false;
10151
        return false;
Línea 9887... Línea 10152...
9887
    }
10152
    }
9888
 
10153
 
9889
    // Get the host part out of the url.
10154
    // Get the host part out of the url.
9890
    if (!$host = parse_url( $url, PHP_URL_HOST )) {
10155
    if (!$host = parse_url($url, PHP_URL_HOST)) {
Línea 9891... Línea 10156...
9891
        return false;
10156
        return false;
9892
    }
10157
    }
Línea 9893... Línea 10158...
9893
 
10158
 
9894
    // Get the possible bypass hosts into an array.
10159
    // Get the possible bypass hosts into an array.
9895
    $matches = explode( ',', $CFG->proxybypass );
10160
    $matches = explode(',', $CFG->proxybypass);
Línea 9910... Línea 10175...
9910
 * Check if the passed navigation is of the new style
10175
 * Check if the passed navigation is of the new style
9911
 *
10176
 *
9912
 * @param mixed $navigation
10177
 * @param mixed $navigation
9913
 * @return bool true for yes false for no
10178
 * @return bool true for yes false for no
9914
 */
10179
 */
9915
function is_newnav($navigation) {
10180
function is_newnav($navigation)
-
 
10181
{
9916
    if (is_array($navigation) && !empty($navigation['newnav'])) {
10182
    if (is_array($navigation) && !empty($navigation['newnav'])) {
9917
        return true;
10183
        return true;
9918
    } else {
10184
    } else {
9919
        return false;
10185
        return false;
9920
    }
10186
    }
Línea 9927... Línea 10193...
9927
 *
10193
 *
9928
 * @param string $var The variable name
10194
 * @param string $var The variable name
9929
 * @param object $object The object to check
10195
 * @param object $object The object to check
9930
 * @return boolean
10196
 * @return boolean
9931
 */
10197
 */
9932
function in_object_vars($var, $object) {
10198
function in_object_vars($var, $object)
-
 
10199
{
9933
    $classvars = get_class_vars(get_class($object));
10200
    $classvars = get_class_vars(get_class($object));
9934
    $classvars = array_keys($classvars);
10201
    $classvars = array_keys($classvars);
9935
    return in_array($var, $classvars);
10202
    return in_array($var, $classvars);
9936
}
10203
}
Línea 9941... Línea 10208...
9941
 *
10208
 *
9942
 * @param array $array
10209
 * @param array $array
9943
 * @param bool $keepkeyassoc
10210
 * @param bool $keepkeyassoc
9944
 * @return array
10211
 * @return array
9945
 */
10212
 */
9946
function object_array_unique($array, $keepkeyassoc = true) {
10213
function object_array_unique($array, $keepkeyassoc = true)
-
 
10214
{
9947
    $duplicatekeys = array();
10215
    $duplicatekeys = array();
9948
    $tmp         = array();
10216
    $tmp         = array();
Línea 9949... Línea 10217...
9949
 
10217
 
9950
    foreach ($array as $key => $val) {
10218
    foreach ($array as $key => $val) {
Línea 9971... Línea 10239...
9971
 * Is a userid the primary administrator?
10239
 * Is a userid the primary administrator?
9972
 *
10240
 *
9973
 * @param int $userid int id of user to check
10241
 * @param int $userid int id of user to check
9974
 * @return boolean
10242
 * @return boolean
9975
 */
10243
 */
9976
function is_primary_admin($userid) {
10244
function is_primary_admin($userid)
-
 
10245
{
9977
    $primaryadmin =  get_admin();
10246
    $primaryadmin =  get_admin();
Línea 9978... Línea 10247...
9978
 
10247
 
9979
    if ($userid == $primaryadmin->id) {
10248
    if ($userid == $primaryadmin->id) {
9980
        return true;
10249
        return true;
Línea 9986... Línea 10255...
9986
/**
10255
/**
9987
 * Returns the site identifier
10256
 * Returns the site identifier
9988
 *
10257
 *
9989
 * @return string $CFG->siteidentifier, first making sure it is properly initialised.
10258
 * @return string $CFG->siteidentifier, first making sure it is properly initialised.
9990
 */
10259
 */
9991
function get_site_identifier() {
10260
function get_site_identifier()
-
 
10261
{
9992
    global $CFG;
10262
    global $CFG;
9993
    // Check to see if it is missing. If so, initialise it.
10263
    // Check to see if it is missing. If so, initialise it.
9994
    if (empty($CFG->siteidentifier)) {
10264
    if (empty($CFG->siteidentifier)) {
9995
        set_config('siteidentifier', random_string(32) . $_SERVER['HTTP_HOST']);
10265
        set_config('siteidentifier', random_string(32) . $_SERVER['HTTP_HOST']);
9996
    }
10266
    }
Línea 10004... Línea 10274...
10004
 *
10274
 *
10005
 * @param string $password   password to be checked against the password policy
10275
 * @param string $password   password to be checked against the password policy
10006
 * @param integer $maxchars  maximum number of consecutive identical characters
10276
 * @param integer $maxchars  maximum number of consecutive identical characters
10007
 * @return bool
10277
 * @return bool
10008
 */
10278
 */
10009
function check_consecutive_identical_characters($password, $maxchars) {
10279
function check_consecutive_identical_characters($password, $maxchars)
-
 
10280
{
Línea 10010... Línea 10281...
10010
 
10281
 
10011
    if ($maxchars < 1) {
10282
    if ($maxchars < 1) {
10012
        return true; // Zero 0 is to disable this check.
10283
        return true; // Zero 0 is to disable this check.
10013
    }
10284
    }
Línea 10050... Línea 10321...
10050
 *
10321
 *
10051
 * @param mixed $function a php callback
10322
 * @param mixed $function a php callback
10052
 * @param mixed $arg1,... $argv arguments to partially bind with
10323
 * @param mixed $arg1,... $argv arguments to partially bind with
10053
 * @return array Array callback
10324
 * @return array Array callback
10054
 */
10325
 */
10055
function partial() {
10326
function partial()
-
 
10327
{
10056
    if (!class_exists('partial')) {
10328
    if (!class_exists('partial')) {
10057
        /**
10329
        /**
10058
         * Used to manage function binding.
10330
         * Used to manage function binding.
10059
         * @copyright  2009 Penny Leach
10331
         * @copyright  2009 Penny Leach
10060
         * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10332
         * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10061
         */
10333
         */
10062
        class partial{
10334
        class partial
-
 
10335
        {
10063
            /** @var array */
10336
            /** @var array */
10064
            public $values = array();
10337
            public $values = array();
10065
            /** @var string The function to call as a callback. */
10338
            /** @var string The function to call as a callback. */
10066
            public $func;
10339
            public $func;
10067
            /**
10340
            /**
10068
             * Constructor
10341
             * Constructor
10069
             * @param string $func
10342
             * @param string $func
10070
             * @param array $args
10343
             * @param array $args
10071
             */
10344
             */
10072
            public function __construct($func, $args) {
10345
            public function __construct($func, $args)
-
 
10346
            {
10073
                $this->values = $args;
10347
                $this->values = $args;
10074
                $this->func = $func;
10348
                $this->func = $func;
10075
            }
10349
            }
10076
            /**
10350
            /**
10077
             * Calls the callback function.
10351
             * Calls the callback function.
10078
             * @return mixed
10352
             * @return mixed
10079
             */
10353
             */
10080
            public function method() {
10354
            public function method()
-
 
10355
            {
10081
                $args = func_get_args();
10356
                $args = func_get_args();
10082
                return call_user_func_array($this->func, array_merge($this->values, $args));
10357
                return call_user_func_array($this->func, array_merge($this->values, $args));
10083
            }
10358
            }
10084
        }
10359
        }
10085
    }
10360
    }
Línea 10093... Línea 10368...
10093
 * helper function to load up and initialise the mnet environment
10368
 * helper function to load up and initialise the mnet environment
10094
 * this must be called before you use mnet functions.
10369
 * this must be called before you use mnet functions.
10095
 *
10370
 *
10096
 * @return mnet_environment the equivalent of old $MNET global
10371
 * @return mnet_environment the equivalent of old $MNET global
10097
 */
10372
 */
10098
function get_mnet_environment() {
10373
function get_mnet_environment()
-
 
10374
{
10099
    global $CFG;
10375
    global $CFG;
10100
    require_once($CFG->dirroot . '/mnet/lib.php');
10376
    require_once($CFG->dirroot . '/mnet/lib.php');
10101
    static $instance = null;
10377
    static $instance = null;
10102
    if (empty($instance)) {
10378
    if (empty($instance)) {
10103
        $instance = new mnet_environment();
10379
        $instance = new mnet_environment();
Línea 10110... Línea 10386...
10110
 * during xmlrpc server code execution, any code wishing to access
10386
 * during xmlrpc server code execution, any code wishing to access
10111
 * information about the remote peer must use this to get it.
10387
 * information about the remote peer must use this to get it.
10112
 *
10388
 *
10113
 * @return mnet_remote_client|false the equivalent of old $MNETREMOTE_CLIENT global
10389
 * @return mnet_remote_client|false the equivalent of old $MNETREMOTE_CLIENT global
10114
 */
10390
 */
10115
function get_mnet_remote_client() {
10391
function get_mnet_remote_client()
-
 
10392
{
10116
    if (!defined('MNET_SERVER')) {
10393
    if (!defined('MNET_SERVER')) {
10117
        debugging(get_string('notinxmlrpcserver', 'mnet'));
10394
        debugging(get_string('notinxmlrpcserver', 'mnet'));
10118
        return false;
10395
        return false;
10119
    }
10396
    }
10120
    global $MNET_REMOTE_CLIENT;
10397
    global $MNET_REMOTE_CLIENT;
Línea 10129... Línea 10406...
10129
 * to setup the object returned by {@link get_mnet_remote_client}
10406
 * to setup the object returned by {@link get_mnet_remote_client}
10130
 *
10407
 *
10131
 * @param mnet_remote_client $client the client to set up
10408
 * @param mnet_remote_client $client the client to set up
10132
 * @throws moodle_exception
10409
 * @throws moodle_exception
10133
 */
10410
 */
10134
function set_mnet_remote_client($client) {
10411
function set_mnet_remote_client($client)
-
 
10412
{
10135
    if (!defined('MNET_SERVER')) {
10413
    if (!defined('MNET_SERVER')) {
10136
        throw new moodle_exception('notinxmlrpcserver', 'mnet');
10414
        throw new moodle_exception('notinxmlrpcserver', 'mnet');
10137
    }
10415
    }
10138
    global $MNET_REMOTE_CLIENT;
10416
    global $MNET_REMOTE_CLIENT;
10139
    $MNET_REMOTE_CLIENT = $client;
10417
    $MNET_REMOTE_CLIENT = $client;
Línea 10143... Línea 10421...
10143
 * return the jump url for a given remote user
10421
 * return the jump url for a given remote user
10144
 * this is used for rewriting forum post links in emails, etc
10422
 * this is used for rewriting forum post links in emails, etc
10145
 *
10423
 *
10146
 * @param stdclass $user the user to get the idp url for
10424
 * @param stdclass $user the user to get the idp url for
10147
 */
10425
 */
10148
function mnet_get_idp_jump_url($user) {
10426
function mnet_get_idp_jump_url($user)
-
 
10427
{
10149
    global $CFG;
10428
    global $CFG;
Línea 10150... Línea 10429...
10150
 
10429
 
10151
    static $mnetjumps = array();
10430
    static $mnetjumps = array();
10152
    if (!array_key_exists($user->mnethostid, $mnetjumps)) {
10431
    if (!array_key_exists($user->mnethostid, $mnetjumps)) {
Línea 10160... Línea 10439...
10160
/**
10439
/**
10161
 * Gets the homepage to use for the current user
10440
 * Gets the homepage to use for the current user
10162
 *
10441
 *
10163
 * @return int One of HOMEPAGE_*
10442
 * @return int One of HOMEPAGE_*
10164
 */
10443
 */
10165
function get_home_page() {
10444
function get_home_page()
-
 
10445
{
10166
    global $CFG;
10446
    global $CFG;
Línea 10167... Línea 10447...
10167
 
10447
 
10168
    if (isloggedin() && !isguestuser() && !empty($CFG->defaulthomepage)) {
10448
    if (isloggedin() && !isguestuser() && !empty($CFG->defaulthomepage)) {
10169
        // If dashboard is disabled, home will be set to default page.
10449
        // If dashboard is disabled, home will be set to default page.
Línea 10192... Línea 10472...
10192
 * Returns the default home page to display if current one is not defined or can't be applied.
10472
 * Returns the default home page to display if current one is not defined or can't be applied.
10193
 * The default behaviour is to return Dashboard if it's enabled or My courses page if it isn't.
10473
 * The default behaviour is to return Dashboard if it's enabled or My courses page if it isn't.
10194
 *
10474
 *
10195
 * @return int The default home page.
10475
 * @return int The default home page.
10196
 */
10476
 */
10197
function get_default_home_page(): int {
10477
function get_default_home_page(): int
-
 
10478
{
10198
    global $CFG;
10479
    global $CFG;
Línea 10199... Línea 10480...
10199
 
10480
 
10200
    return (!isset($CFG->enabledashboard) || $CFG->enabledashboard) ? HOMEPAGE_MY : HOMEPAGE_MYCOURSES;
10481
    return (!isset($CFG->enabledashboard) || $CFG->enabledashboard) ? HOMEPAGE_MY : HOMEPAGE_MYCOURSES;
Línea 10205... Línea 10486...
10205
 * By default this is just $course->fullname but user can configure it. The
10486
 * By default this is just $course->fullname but user can configure it. The
10206
 * result of this function should be passed through print_string.
10487
 * result of this function should be passed through print_string.
10207
 * @param stdClass|core_course_list_element $course Moodle course object
10488
 * @param stdClass|core_course_list_element $course Moodle course object
10208
 * @return string Display name of course (either fullname or short + fullname)
10489
 * @return string Display name of course (either fullname or short + fullname)
10209
 */
10490
 */
10210
function get_course_display_name_for_list($course) {
10491
function get_course_display_name_for_list($course)
-
 
10492
{
10211
    global $CFG;
10493
    global $CFG;
10212
    if (!empty($CFG->courselistshortnames)) {
10494
    if (!empty($CFG->courselistshortnames)) {
10213
        if (!($course instanceof stdClass)) {
10495
        if (!($course instanceof stdClass)) {
10214
            $course = (object)convert_to_array($course);
10496
            $course = (object)convert_to_array($course);
10215
        }
10497
        }
Línea 10225... Línea 10507...
10225
 * Arrays may contain only integers or strings as both keys and values. Nested arrays are allowed.
10507
 * Arrays may contain only integers or strings as both keys and values. Nested arrays are allowed.
10226
 *
10508
 *
10227
 * @param string $expression
10509
 * @param string $expression
10228
 * @return array|bool either parsed array or false if parsing was impossible.
10510
 * @return array|bool either parsed array or false if parsing was impossible.
10229
 */
10511
 */
10230
function unserialize_array($expression) {
10512
function unserialize_array($expression)
-
 
10513
{
Línea 10231... Línea 10514...
10231
 
10514
 
10232
    // Check the expression is an array.
10515
    // Check the expression is an array.
10233
    if (!preg_match('/^a:(\d+):/', $expression)) {
10516
    if (!preg_match('/^a:(\d+):/', $expression)) {
10234
        return false;
10517
        return false;
Línea 10235... Línea 10518...
10235
    }
10518
    }
Línea 10236... Línea 10519...
10236
 
10519
 
10237
    $values = (array) unserialize_object($expression);
10520
    $values = (array) unserialize_object($expression);
10238
 
10521
 
10239
    // Callback that returns true if the given value is an unserialized object, executes recursively.
10522
    // Callback that returns true if the given value is an unserialized object, executes recursively.
10240
    $invalidvaluecallback = static function($value) use (&$invalidvaluecallback): bool {
10523
    $invalidvaluecallback = static function ($value) use (&$invalidvaluecallback): bool {
10241
        if (is_array($value)) {
10524
        if (is_array($value)) {
10242
            return (bool) array_filter($value, $invalidvaluecallback);
10525
            return (bool) array_filter($value, $invalidvaluecallback);
Línea 10260... Línea 10543...
10260
 * otherwise we would return an instances of {@see __PHP_Incomplete_class} for malformed strings
10543
 * otherwise we would return an instances of {@see __PHP_Incomplete_class} for malformed strings
10261
 *
10544
 *
10262
 * @param string $input
10545
 * @param string $input
10263
 * @return stdClass
10546
 * @return stdClass
10264
 */
10547
 */
10265
function unserialize_object(string $input): stdClass {
10548
function unserialize_object(string $input): stdClass
-
 
10549
{
10266
    $instance = (array) unserialize($input, ['allowed_classes' => [stdClass::class]]);
10550
    $instance = (array) unserialize($input, ['allowed_classes' => [stdClass::class]]);
10267
    return (object) $instance;
10551
    return (object) $instance;
10268
}
10552
}
Línea 10269... Línea 10553...
10269
 
10553
 
Línea 10325... Línea 10609...
10325
 * @package    core
10609
 * @package    core
10326
 * @category   string
10610
 * @category   string
10327
 * @copyright  2011 Sam Hemelryk
10611
 * @copyright  2011 Sam Hemelryk
10328
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10612
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10329
 */
10613
 */
10330
class lang_string {
10614
class lang_string
-
 
10615
{
Línea 10331... Línea 10616...
10331
 
10616
 
10332
    /** @var string The strings identifier */
10617
    /** @var string The strings identifier */
10333
    protected $identifier;
10618
    protected $identifier;
10334
    /** @var string The strings component. Default '' */
10619
    /** @var string The strings component. Default '' */
Línea 10358... Línea 10643...
10358
     * @param string $component The strings component
10643
     * @param string $component The strings component
10359
     * @param stdClass|array|mixed $a Any arguments the string requires
10644
     * @param stdClass|array|mixed $a Any arguments the string requires
10360
     * @param string $lang The language to use when processing the string.
10645
     * @param string $lang The language to use when processing the string.
10361
     * @throws coding_exception
10646
     * @throws coding_exception
10362
     */
10647
     */
10363
    public function __construct($identifier, $component = '', $a = null, $lang = null) {
10648
    public function __construct($identifier, $component = '', $a = null, $lang = null)
-
 
10649
    {
10364
        if (empty($component)) {
10650
        if (empty($component)) {
10365
            $component = 'moodle';
10651
            $component = 'moodle';
10366
        }
10652
        }
Línea 10367... Línea 10653...
10367
 
10653
 
Línea 10404... Línea 10690...
10404
            }
10690
            }
10405
            if (!empty($this->component) && clean_param($this->component, PARAM_COMPONENT) == '') {
10691
            if (!empty($this->component) && clean_param($this->component, PARAM_COMPONENT) == '') {
10406
                throw new coding_exception('Invalid string compontent. Please check your string definition');
10692
                throw new coding_exception('Invalid string compontent. Please check your string definition');
10407
            }
10693
            }
10408
            if (!get_string_manager()->string_exists($this->identifier, $this->component)) {
10694
            if (!get_string_manager()->string_exists($this->identifier, $this->component)) {
10409
                debugging('String does not exist. Please check your string definition for '.$this->identifier.'/'.$this->component, DEBUG_DEVELOPER);
10695
                debugging('String does not exist. Please check your string definition for ' . $this->identifier . '/' . $this->component, DEBUG_DEVELOPER);
10410
            }
10696
            }
10411
        }
10697
        }
10412
    }
10698
    }
Línea 10413... Línea 10699...
10413
 
10699
 
Línea 10422... Línea 10708...
10422
     * compatibility.
10708
     * compatibility.
10423
     *
10709
     *
10424
     * @return string
10710
     * @return string
10425
     * @throws coding_exception
10711
     * @throws coding_exception
10426
     */
10712
     */
10427
    protected function get_string() {
10713
    protected function get_string()
-
 
10714
    {
10428
        global $CFG;
10715
        global $CFG;
Línea 10429... Línea 10716...
10429
 
10716
 
10430
        // Check if we need to process the string.
10717
        // Check if we need to process the string.
10431
        if ($this->string === null) {
10718
        if ($this->string === null) {
Línea 10449... Línea 10736...
10449
     * Returns the string
10736
     * Returns the string
10450
     *
10737
     *
10451
     * @param string $lang The langauge to use when processing the string
10738
     * @param string $lang The langauge to use when processing the string
10452
     * @return string
10739
     * @return string
10453
     */
10740
     */
10454
    public function out($lang = null) {
10741
    public function out($lang = null)
-
 
10742
    {
10455
        if ($lang !== null && $lang != $this->lang && ($this->lang == null && $lang != current_language())) {
10743
        if ($lang !== null && $lang != $this->lang && ($this->lang == null && $lang != current_language())) {
10456
            if ($this->forcedstring) {
10744
            if ($this->forcedstring) {
10457
                debugging('lang_string objects that have been used cannot be printed in another language. ('.$this->lang.' used)', DEBUG_DEVELOPER);
10745
                debugging('lang_string objects that have been used cannot be printed in another language. (' . $this->lang . ' used)', DEBUG_DEVELOPER);
10458
                return $this->get_string();
10746
                return $this->get_string();
10459
            }
10747
            }
10460
            $translatedstring = new lang_string($this->identifier, $this->component, $this->a, $lang);
10748
            $translatedstring = new lang_string($this->identifier, $this->component, $this->a, $lang);
10461
            return $translatedstring->out();
10749
            return $translatedstring->out();
10462
        }
10750
        }
Línea 10466... Línea 10754...
10466
    /**
10754
    /**
10467
     * Magic __toString method for printing a string
10755
     * Magic __toString method for printing a string
10468
     *
10756
     *
10469
     * @return string
10757
     * @return string
10470
     */
10758
     */
10471
    public function __toString() {
10759
    public function __toString()
-
 
10760
    {
10472
        return $this->get_string();
10761
        return $this->get_string();
10473
    }
10762
    }
Línea 10474... Línea 10763...
10474
 
10763
 
10475
    /**
10764
    /**
10476
     * Magic __set_state method used for var_export
10765
     * Magic __set_state method used for var_export
10477
     *
10766
     *
10478
     * @param array $array
10767
     * @param array $array
10479
     * @return self
10768
     * @return self
10480
     */
10769
     */
-
 
10770
    public static function __set_state(array $array): self
10481
    public static function __set_state(array $array): self {
10771
    {
10482
        $tmp = new lang_string($array['identifier'], $array['component'], $array['a'], $array['lang']);
10772
        $tmp = new lang_string($array['identifier'], $array['component'], $array['a'], $array['lang']);
10483
        $tmp->string = $array['string'];
10773
        $tmp->string = $array['string'];
10484
        $tmp->forcedstring = $array['forcedstring'];
10774
        $tmp->forcedstring = $array['forcedstring'];
10485
        return $tmp;
10775
        return $tmp;
Línea 10490... Línea 10780...
10490
     * string properties... the string cannot be regenerated so we need to ensure
10780
     * string properties... the string cannot be regenerated so we need to ensure
10491
     * it is generated for this.
10781
     * it is generated for this.
10492
     *
10782
     *
10493
     * @return array
10783
     * @return array
10494
     */
10784
     */
10495
    public function __sleep() {
10785
    public function __sleep()
-
 
10786
    {
10496
        $this->get_string();
10787
        $this->get_string();
10497
        $this->forcedstring = true;
10788
        $this->forcedstring = true;
10498
        return array('forcedstring', 'string', 'lang');
10789
        return array('forcedstring', 'string', 'lang');
10499
    }
10790
    }
Línea 10500... Línea 10791...
10500
 
10791
 
10501
    /**
10792
    /**
10502
     * Returns the identifier.
10793
     * Returns the identifier.
10503
     *
10794
     *
10504
     * @return string
10795
     * @return string
10505
     */
10796
     */
-
 
10797
    public function get_identifier()
10506
    public function get_identifier() {
10798
    {
10507
        return $this->identifier;
10799
        return $this->identifier;
Línea 10508... Línea 10800...
10508
    }
10800
    }
10509
 
10801
 
10510
    /**
10802
    /**
10511
     * Returns the component.
10803
     * Returns the component.
10512
     *
10804
     *
10513
     * @return string
10805
     * @return string
-
 
10806
     */
10514
     */
10807
    public function get_component()
10515
    public function get_component() {
10808
    {
10516
        return $this->component;
10809
        return $this->component;
Línea 10517... Línea 10810...
10517
    }
10810
    }
Línea 10524... Línea 10817...
10524
 * It does not check if the callable actually exists.
10817
 * It does not check if the callable actually exists.
10525
 *
10818
 *
10526
 * @param callable|string|array $callable
10819
 * @param callable|string|array $callable
10527
 * @return string|bool Human readable name of callable, or false if not a valid callable.
10820
 * @return string|bool Human readable name of callable, or false if not a valid callable.
10528
 */
10821
 */
10529
function get_callable_name($callable) {
10822
function get_callable_name($callable)
-
 
10823
{
Línea 10530... Línea 10824...
10530
 
10824
 
10531
    if (!is_callable($callable, true, $name)) {
10825
    if (!is_callable($callable, true, $name)) {
10532
        return false;
-
 
10533
 
10826
        return false;
10534
    } else {
10827
    } else {
10535
        return $name;
10828
        return $name;
10536
    }
10829
    }
Línea 10544... Línea 10837...
10544
 * Good thing is there is no false negative.
10837
 * Good thing is there is no false negative.
10545
 * Note that it's possible to force the result of this check by specifying $CFG->site_is_public in config.php
10838
 * Note that it's possible to force the result of this check by specifying $CFG->site_is_public in config.php
10546
 *
10839
 *
10547
 * @return bool
10840
 * @return bool
10548
 */
10841
 */
10549
function site_is_public() {
10842
function site_is_public()
-
 
10843
{
10550
    global $CFG;
10844
    global $CFG;
Línea 10551... Línea 10845...
10551
 
10845
 
10552
    // Return early if site admin has forced this setting.
10846
    // Return early if site admin has forced this setting.
10553
    if (isset($CFG->site_is_public)) {
10847
    if (isset($CFG->site_is_public)) {
Línea 10574... Línea 10868...
10574
 *
10868
 *
10575
 * @param string $password
10869
 * @param string $password
10576
 * @param int $pepperlength The length of the used peppers
10870
 * @param int $pepperlength The length of the used peppers
10577
 * @return bool
10871
 * @return bool
10578
 */
10872
 */
10579
function exceeds_password_length(string $password, int $pepperlength = 0): bool {
10873
function exceeds_password_length(string $password, int $pepperlength = 0): bool
-
 
10874
{
10580
    return (strlen($password) > (MAX_PASSWORD_CHARACTERS + $pepperlength));
10875
    return (strlen($password) > (MAX_PASSWORD_CHARACTERS + $pepperlength));
10581
}
10876
}
Línea 10582... Línea 10877...
10582
 
10877
 
10583
/**
10878
/**
Línea 10592... Línea 10887...
10592
 * @param array $array
10887
 * @param array $array
10593
 * @param mixed $filter The value to filter on
10888
 * @param mixed $filter The value to filter on
10594
 * @param bool $strict Whether to apply a strit test with the filter
10889
 * @param bool $strict Whether to apply a strit test with the filter
10595
 * @return array
10890
 * @return array
10596
 */
10891
 */
10597
function moodle_array_keys_filter(array $array, mixed $filter, bool $strict = false): array {
10892
function moodle_array_keys_filter(array $array, mixed $filter, bool $strict = false): array
-
 
10893
{
10598
    return array_keys(array_filter(
10894
    return array_keys(array_filter(
10599
        $array,
10895
        $array,
10600
        function($value, $key) use ($filter, $strict): bool {
10896
        function ($value, $key) use ($filter, $strict): bool {
10601
            if ($strict) {
10897
            if ($strict) {
10602
                return $value === $filter;
10898
                return $value === $filter;
10603
            }
10899
            }
10604
            return $value == $filter;
10900
            return $value == $filter;
10605
        },
10901
        },