Proyectos de Subversion Moodle

Rev

Rev 1 | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 1 Rev 1441
Línea 115... Línea 115...
115
     * @param string $restoreid Restore id
115
     * @param string $restoreid Restore id
116
     * @param string $inforeffile File path
116
     * @param string $inforeffile File path
117
     * @param \core\progress\base $progress Progress tracker
117
     * @param \core\progress\base $progress Progress tracker
118
     */
118
     */
119
    public static function load_inforef_to_tempids($restoreid, $inforeffile,
119
    public static function load_inforef_to_tempids($restoreid, $inforeffile,
120
            \core\progress\base $progress = null) {
120
            ?\core\progress\base $progress = null) {
Línea 121... Línea 121...
121
 
121
 
122
        if (!file_exists($inforeffile)) { // Shouldn't happen ever, but...
122
        if (!file_exists($inforeffile)) { // Shouldn't happen ever, but...
123
            throw new backup_helper_exception('missing_inforef_xml_file', $inforeffile);
123
            throw new backup_helper_exception('missing_inforef_xml_file', $inforeffile);
Línea 422... Línea 422...
422
     * @param string $restoreid Restore id
422
     * @param string $restoreid Restore id
423
     * @param string $usersfile File path
423
     * @param string $usersfile File path
424
     * @param \core\progress\base $progress Progress tracker
424
     * @param \core\progress\base $progress Progress tracker
425
     */
425
     */
426
    public static function load_users_to_tempids($restoreid, $usersfile,
426
    public static function load_users_to_tempids($restoreid, $usersfile,
427
            \core\progress\base $progress = null) {
427
            ?\core\progress\base $progress = null) {
Línea 428... Línea 428...
428
 
428
 
429
        if (!file_exists($usersfile)) { // Shouldn't happen ever, but...
429
        if (!file_exists($usersfile)) { // Shouldn't happen ever, but...
430
            throw new backup_helper_exception('missing_users_xml_file', $usersfile);
430
            throw new backup_helper_exception('missing_users_xml_file', $usersfile);
Línea 536... Línea 536...
536
     * This function will process all the question banks present in restore
536
     * This function will process all the question banks present in restore
537
     * at some contextlevel (from CONTEXT_SYSTEM to CONTEXT_MODULE), finding
537
     * at some contextlevel (from CONTEXT_SYSTEM to CONTEXT_MODULE), finding
538
     * the target contexts where each bank will be restored and returning
538
     * the target contexts where each bank will be restored and returning
539
     * warnings/errors as needed.
539
     * warnings/errors as needed.
540
     *
540
     *
-
 
541
     * Question categories at CONTEXT_SYSTEM, CONTEXT_COURSE, and CONTEXT_COURSECAT
541
     * Some contextlevels (system, coursecat), will delegate process to
542
     * are now deprecated, but we still have to account for them in backup files
542
     * course level if any problem is found (lack of permissions, non-matching
543
     * made with pre-deprecated code. As such, any categories in backup files that used
543
     * target context...). Other contextlevels (course, module) will
544
     * to target these contexts will now be attached to a 'fallback' qbank
544
     * cause return error if some problem is found.
545
     * instance on the course being restored.
545
     *
546
     *
546
     * At the end, if no errors were found, all the categories in backup_temp_ids
547
     * At the end, if no errors were found, all the categories in backup_temp_ids
547
     * will be pointing (parentitemid) to the target context where they must be
548
     * will be pointing (parentitemid) to the target context where they must be
548
     * created later in the restore process.
549
     * created later in the restore process.
549
     *
550
     *
Línea 565... Línea 566...
565
     * @param bool $samesite True if restore is to same site
566
     * @param bool $samesite True if restore is to same site
566
     * @param int $contextlevel (CONTEXT_SYSTEM, etc.)
567
     * @param int $contextlevel (CONTEXT_SYSTEM, etc.)
567
     * @return array A separate list of all error and warnings detected
568
     * @return array A separate list of all error and warnings detected
568
     */
569
     */
569
    public static function prechek_precheck_qbanks_by_level($restoreid, $courseid, $userid, $samesite, $contextlevel) {
570
    public static function prechek_precheck_qbanks_by_level($restoreid, $courseid, $userid, $samesite, $contextlevel) {
570
        global $DB;
571
        global $DB, $CFG;
Línea 571... Línea 572...
571
 
572
 
572
        // To return any errors and warnings found
573
        // To return any errors and warnings found
573
        $errors   = array();
574
        $errors = [];
574
        $warnings = array();
-
 
575
 
-
 
576
        // Specify which fallbacks must be performed
-
 
577
        $fallbacks = array(
-
 
578
            CONTEXT_SYSTEM => CONTEXT_COURSE,
-
 
Línea 579... Línea 575...
579
            CONTEXT_COURSECAT => CONTEXT_COURSE);
575
        $warnings = [];
580
 
576
 
581
        /** @var restore_controller $rc */
577
        /** @var restore_controller $rc */
582
        $rc = restore_controller_dbops::load_controller($restoreid);
578
        $rc = restore_controller_dbops::load_controller($restoreid);
583
        $plan = $rc->get_plan();
579
        $plan = $rc->get_plan();
Línea -... Línea 580...
-
 
580
        $after35 = $plan->backup_release_compare('3.5', '>=') && $plan->backup_version_compare(20180205, '>');
584
        $after35 = $plan->backup_release_compare('3.5', '>=') && $plan->backup_version_compare(20180205, '>');
581
        $rc->destroy(); // Always need to destroy.
585
        $rc->destroy(); // Always need to destroy.
582
 
586
 
583
        /*
587
        // For any contextlevel, follow this process logic:
584
          For any contextlevel, follow this process logic:
588
        //
585
 
589
        // 0) Iterate over each context (qbank)
586
          0) Iterate over each context (qbank)
590
        // 1) Iterate over each qcat in the context, matching by stamp for the found target context
-
 
591
        //     2a) No match, check if user can create qcat and q
587
          1) Iterate over each qcat in the context, matching by stamp for the found target context
592
        //         3a) User can, mark the qcat and all dependent qs to be created in that target context
-
 
593
        //         3b) User cannot, check if we are in some contextlevel with fallback
588
              2a) No match, check if user can create qcat and q
594
        //             4a) There is fallback, move ALL the qcats to fallback, warn. End qcat loop
589
                  3a) User can, mark the qcat and all dependent qs to be created in that target context
595
        //             4b) No fallback, error. End qcat loop.
590
                  3b) User cannot. Move ALL the qcats to a default qbank instance, warn. End qcat loop
596
        //     2b) Match, mark qcat to be mapped and iterate over each q, matching by stamp and version
-
 
597
        //         5a) No match, check if user can add q
591
              2b) Match, mark qcat to be mapped and iterate over each q, matching by stamp and version
598
        //             6a) User can, mark the q to be created
-
 
599
        //             6b) User cannot, check if we are in some contextlevel with fallback
592
                  4a) No match, check if user can add q
600
        //                 7a) There is fallback, move ALL the qcats to fallback, warn. End qcat loop
593
                      5a) User can, mark the q to be created
601
        //                 7b) No fallback, error. End qcat loop
594
                      5b) User cannot. Move ALL the qcats to a default qbank instance, warn. End qcat loop
-
 
595
                  4b) Random question, must always create new.
Línea 602... Línea 596...
602
        //         5b) Random question, must always create new.
596
                  4c) Match, mark q to be mapped
603
        //         5c) Match, mark q to be mapped
597
          6) Check if backup is from Moodle >= 3.5 and error if more than one top-level category in the context.
Línea 604... Línea 598...
604
        // 8) Check if backup is from Moodle >= 3.5 and error if more than one top-level category in the context.
598
         */
605
 
599
 
606
        // Get all the contexts (question banks) in restore for the given contextlevel
600
        // Get all the contexts (question banks) in restore for the given contextlevel
607
        $contexts = self::restore_get_question_banks($restoreid, $contextlevel);
601
        $contexts = self::restore_get_question_banks($restoreid, $contextlevel);
608
 
602
 
609
        // 0) Iterate over each context (qbank)
603
        // 0) Iterate over each context (qbank)
610
        foreach ($contexts as $contextid => $contextlevel) {
604
        foreach ($contexts as $contextid => $contextlevel) {
611
            // Init some perms
605
            // Init some perms
612
            $canmanagecategory = false;
606
            $canmanagecategory = false;
Línea 613... Línea 607...
613
            $canadd            = false;
607
            $canadd = false;
614
            // Top-level category counter.
608
            // Top-level category counter.
615
            $topcats = 0;
609
            $topcats = 0;
616
            // get categories in context (bank)
610
            // get categories in context (bank)
617
            $categories = self::restore_get_question_categories($restoreid, $contextid, $contextlevel);
611
            $categories = self::restore_get_question_categories($restoreid, $contextid, $contextlevel);
618
 
612
 
619
            // cache permissions if $targetcontext is found
613
            // cache permissions if $targetcontext is found
620
            if ($targetcontext = self::restore_find_best_target_context($categories, $courseid, $contextlevel)) {
614
            if ($targetcontext = self::restore_find_best_target_context($categories, $courseid, $contextlevel)) {
621
                $canmanagecategory = has_capability('moodle/question:managecategory', $targetcontext, $userid);
615
                $canmanagecategory = has_capability('moodle/question:managecategory', $targetcontext, $userid);
622
                $canadd            = has_capability('moodle/question:add', $targetcontext, $userid);
616
                $canadd = has_capability('moodle/question:add', $targetcontext, $userid);
Línea 623... Línea 617...
623
            }
617
            }
624
            // 1) Iterate over each qcat in the context, matching by stamp for the found target context
618
            // 1) Iterate over each qcat in the context, matching by stamp for the found target context
625
            foreach ($categories as $category) {
619
            foreach ($categories as $category) {
626
                if ($category->parent == 0) {
620
                if ($category->parent == 0) {
627
                    $topcats++;
621
                    $topcats++;
-
 
622
                }
628
                }
623
 
629
 
624
                $matchcat = false;
630
                $matchcat = false;
625
                if ($targetcontext) {
631
                if ($targetcontext) {
626
                    $matchcat = $DB->get_record('question_categories', [
632
                    $matchcat = $DB->get_record('question_categories', array(
627
                            'contextid' => $targetcontext->id,
Línea 644... Línea 639...
644
                        if ($contextlevel == CONTEXT_MODULE) {
639
                        if ($contextlevel == CONTEXT_MODULE) {
645
                            $parentitemid = null; // null means "not modify" a.k.a. leave original contextid
640
                            $parentitemid = null; // null means "not modify" a.k.a. leave original contextid
646
                        }
641
                        }
647
                        self::set_backup_ids_record($restoreid, 'question_category', $category->id, 0, $parentitemid);
642
                        self::set_backup_ids_record($restoreid, 'question_category', $category->id, 0, $parentitemid);
648
                        // Nothing else to mark, newitemid = 0 means create
643
                        // Nothing else to mark, newitemid = 0 means create
649
 
-
 
650
                    // 3b) User cannot, check if we are in some contextlevel with fallback
-
 
651
                    } else {
644
                    } else {
652
                        // 4a) There is fallback, move ALL the qcats to fallback, warn. End qcat loop
645
                        // 3b) User cannot. Move ALL the qcats to the fallback i.e. a default qbank instance, warn. End qcat loop.
-
 
646
                        $course = get_course($courseid);
-
 
647
                        $course->fullname = get_string('courserestore', 'question');
-
 
648
                        $module =
-
 
649
                            core_question\local\bank\question_bank_helper::get_default_open_instance_system_type($course, true);
653
                        if (array_key_exists($contextlevel, $fallbacks)) {
650
                        $fallbackcontext = $module->context;
654
                            foreach ($categories as $movedcat) {
651
                        foreach ($categories as $movedcat) {
655
                                $movedcat->contextlevel = $fallbacks[$contextlevel];
652
                            $movedcat->contextlevel = $contextlevel;
656
                                self::set_backup_ids_record($restoreid, 'question_category', $movedcat->id, 0, $contextid, $movedcat);
653
                            self::set_backup_ids_record($restoreid,
657
                                // Warn about the performed fallback
654
                                'question_category',
658
                                $warnings[] = get_string('qcategory2coursefallback', 'backup', $movedcat);
655
                                $movedcat->id,
659
                            }
656
                                0,
660
 
-
 
661
                        // 4b) No fallback, error. End qcat loop.
657
                                $fallbackcontext->id,
-
 
658
                                $movedcat
662
                        } else {
659
                            );
-
 
660
                            // Warn about the performed fallback.
663
                            $errors[] = get_string('qcategorycannotberestored', 'backup', $category);
661
                            $warnings[] = get_string('qcategory2coursefallback', 'backup', $movedcat);
664
                        }
662
                        }
665
                        break; // out from qcat loop (both 4a and 4b), we have decided about ALL categories in context (bank)
663
                        break; // Out from qcat loop (both 3a and 3b), we have decided about ALL categories in context (bank).
666
                    }
664
                    }
Línea 667... Línea 665...
667
 
665
 
668
                // 2b) Match, mark qcat to be mapped and iterate over each q, matching by stamp and version
666
                    // 2b) Match, mark qcat to be mapped and iterate over each q, matching by stamp and version
669
                } else {
667
                } else {
670
                    self::set_backup_ids_record($restoreid, 'question_category', $category->id, $matchcat->id, $targetcontext->id);
668
                    self::set_backup_ids_record($restoreid, 'question_category', $category->id, $matchcat->id, $targetcontext->id);
-
 
669
                    $questions = self::restore_get_questions($restoreid, $category->id);
Línea 671... Línea 670...
671
                    $questions = self::restore_get_questions($restoreid, $category->id);
670
                    $transformer = self::get_backup_xml_transformer($courseid);
672
 
671
 
673
                    // Collect all the questions for this category into memory so we only talk to the DB once.
672
                    // Collect all the questions for this category into memory so we only talk to the DB once.
674
                    $questioncache = $DB->get_records_sql_menu('SELECT q.id,
673
                    $recordset = $DB->get_recordset_sql(
675
                                                                       q.stamp
674
                        "SELECT q.*
676
                                                                  FROM {question} q
675
                           FROM {question} q
677
                                                                  JOIN {question_versions} qv
676
                           JOIN {question_versions} qv ON qv.questionid = q.id
-
 
677
                           JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
-
 
678
                           JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid
-
 
679
                          WHERE qc.id = ?",
-
 
680
                        [$matchcat->id],
-
 
681
                    );
-
 
682
 
-
 
683
                    // Compute a hash of question and answer fields to differentiate between identical stamp-version questions.
678
                                                                    ON qv.questionid = q.id
684
                    $questioncache = [];
-
 
685
                    foreach ($recordset as $question) {
-
 
686
                        $question->export_process = true; // Include all question options required for export.
679
                                                                  JOIN {question_bank_entries} qbe
687
                        get_question_options($question);
-
 
688
                        unset($question->export_process);
-
 
689
                        // Remove some additional properties from get_question_options() that isn't included in backups
680
                                                                    ON qbe.id = qv.questionbankentryid
690
                        // before we produce the identity hash.
681
                                                                  JOIN {question_categories} qc
691
                        unset($question->categoryobject);
-
 
692
                        unset($question->questioncategoryid);
-
 
693
                        $cachekey = restore_questions_parser_processor::generate_question_identity_hash($question, $transformer);
-
 
694
                        $questioncache[$cachekey] = $question->id;
Línea 682... Línea 695...
682
                                                                    ON qc.id = qbe.questioncategoryid
695
                    }
683
                                                                 WHERE qc.id = ?', array($matchcat->id));
696
                    $recordset->close();
684
 
697
 
685
                    foreach ($questions as $question) {
698
                    foreach ($questions as $question) {
686
                        if (isset($questioncache[$question->stamp." ".$question->version])) {
699
                        if (isset($questioncache[$question->questionhash])) {
687
                            $matchqid = $questioncache[$question->stamp." ".$question->version];
700
                            $matchqid = $questioncache[$question->questionhash];
688
                        } else {
701
                        } else {
689
                            $matchqid = false;
702
                            $matchqid = false;
690
                        }
703
                        }
691
                        // 5a) No match, check if user can add q
704
                        // 4a) No match, check if user can add q
692
                        if (!$matchqid) {
705
                        if (!$matchqid) {
693
                            // 6a) User can, mark the q to be created
-
 
694
                            if ($canadd) {
-
 
695
                                // Nothing to mark, newitemid means create
706
                            // 5a) User can, mark the q to be created
-
 
707
                            if ($canadd) {
696
 
708
                                // Nothing to mark, newitemid means create
-
 
709
                            } else {
-
 
710
                                // 5b) User cannot.
-
 
711
                                // Move ALL the qcats to the fallback i.e. a default qbank instance, warn. End qcat loop.
-
 
712
                                $course = get_course($courseid);
-
 
713
                                $course->fullname = get_string('courserestore', 'question');
-
 
714
                                $module = core_question\local\bank\question_bank_helper::get_default_open_instance_system_type(
697
                             // 6b) User cannot, check if we are in some contextlevel with fallback
715
                                    $course,
698
                            } else {
716
                                    true
699
                                // 7a) There is fallback, move ALL the qcats to fallback, warn. End qcat loo
717
                                );
700
                                if (array_key_exists($contextlevel, $fallbacks)) {
718
                                $fallbackcontext = $module->context;
701
                                    foreach ($categories as $movedcat) {
719
                                foreach ($categories as $movedcat) {
702
                                        $movedcat->contextlevel = $fallbacks[$contextlevel];
720
                                    $movedcat->contextlevel = $contextlevel;
703
                                        self::set_backup_ids_record($restoreid, 'question_category', $movedcat->id, 0, $contextid, $movedcat);
721
                                    self::set_backup_ids_record($restoreid,
704
                                        // Warn about the performed fallback
-
 
705
                                        $warnings[] = get_string('question2coursefallback', 'backup', $movedcat);
722
                                        'question_category',
-
 
723
                                        $movedcat->id,
706
                                    }
724
                                        0,
-
 
725
                                        $fallbackcontext->id,
707
 
726
                                        $movedcat
708
                                // 7b) No fallback, error. End qcat loop
727
                                    );
709
                                } else {
728
                                    // Warn about the performed fallback.
-
 
729
                                    $warnings[] = get_string('question2coursefallback', 'backup', $movedcat);
710
                                    $errors[] = get_string('questioncannotberestored', 'backup', $question);
730
                                }
Línea 711... Línea 731...
711
                                }
731
                                // Out from qcat loop (both 5a and 5b), we have decided about ALL categories in context (bank).
712
                                break 2; // out from qcat loop (both 7a and 7b), we have decided about ALL categories in context (bank)
732
                                break 2;
713
                            }
733
                            }
Línea 714... Línea 734...
714
 
734
 
715
                        // 5b) Random questions must always be newly created.
735
                            // 4b) Random questions must always be newly created.
716
                        } else if ($question->qtype == 'random') {
736
                        } else if ($question->qtype == 'random') {
717
                            // Nothing to mark, newitemid means create
737
                            // Nothing to mark, newitemid means create
718
 
738
 
719
                        // 5c) Match, mark q to be mapped.
739
                            // 4c) Match, mark q to be mapped.
720
                        } else {
740
                        } else {
Línea 721... Línea 741...
721
                            self::set_backup_ids_record($restoreid, 'question', $question->id, $matchqid);
741
                            self::set_backup_ids_record($restoreid, 'question', $question->id, $matchqid);
722
                        }
742
                        }
723
                    }
743
                    }
724
                }
744
                }
Línea 725... Línea 745...
725
            }
745
            }
Línea 726... Línea 746...
726
 
746
 
727
            // 8) Check if backup is made on Moodle >= 3.5 and there are more than one top-level category in the context.
747
            // 6) Check if backup is made on Moodle >= 3.5 and there are more than one top-level category in the context.
Línea 728... Línea 748...
728
            if ($after35 && $topcats > 1) {
748
            if ($after35 && $topcats > 1) {
729
                $errors[] = get_string('restoremultipletopcats', 'question', $contextid);
749
                $errors[] = get_string('restoremultipletopcats', 'question', $contextid);
730
            }
750
            }
Línea 797... Línea 817...
797
 
817
 
798
        return $results;
818
        return $results;
Línea 799... Línea 819...
799
    }
819
    }
800
 
820
 
-
 
821
    /**
801
    /**
822
     * Calculates the best existing context to restore one collection of qcats.
-
 
823
     * Uses the backup category stamp to match the target category stamp
-
 
824
     * and categories must all belong to the same context (question bank).
802
     * Calculates the best context found to restore one collection of qcats,
825
     *
-
 
826
     * @param array $categories categories to find target context for
-
 
827
     * @param int $courseid course to restore to
803
     * al them belonging to the same context (question bank), returning the
828
     * @param int $contextlevel contextlevel to search for the target context
804
     * target context found (object) or false
829
     * @return bool|\core\context target context or false if no target context found
805
     */
830
     */
Línea 806... Línea 831...
806
    public static function restore_find_best_target_context($categories, $courseid, $contextlevel) {
831
    public static function restore_find_best_target_context($categories, $courseid, $contextlevel) {
Línea 807... Línea -...
807
        global $DB;
-
 
808
 
-
 
809
        $targetcontext = false;
-
 
810
 
-
 
811
        // Depending of $contextlevel, we perform different actions
-
 
812
        switch ($contextlevel) {
-
 
813
             // For system is easy, the best context is the system context
-
 
814
             case CONTEXT_SYSTEM:
-
 
815
                 $targetcontext = context_system::instance();
-
 
816
                 break;
832
        global $DB;
817
 
-
 
818
             // For coursecat, we are going to look for stamps in all the
-
 
819
             // course categories between CONTEXT_SYSTEM and CONTEXT_COURSE
-
 
820
             // (i.e. in all the course categories in the path)
833
 
821
             //
834
        $targetcontext = false;
822
             // And only will return one "best" target context if all the
835
 
823
             // matches belong to ONE and ONLY ONE context. If multiple
836
        // If context module we need to find any existing module instances with categories matching the category stamps
824
             // matches are found, that means that there is some annoying
-
 
825
             // qbank "fragmentation" in the categories, so we'll fallback
837
        // from the backup. If multiple matches are found, that means that there is some annoying
826
             // to create the qbank at course level
838
        // qbank "fragmentation" in the categories, so we'll fall back
827
             case CONTEXT_COURSECAT:
839
        // to creating a qbank instance at course level and putting the categories there.
828
                 // Build the array of stamps we are going to match
840
        if ($contextlevel == CONTEXT_MODULE) {
829
                 $stamps = array();
841
            $stamps = [];
-
 
842
            foreach ($categories as $category) {
830
                 foreach ($categories as $category) {
843
                $stamps[] = $category->stamp;
831
                     $stamps[] = $category->stamp;
844
            }
832
                 }
-
 
833
                 $contexts = array();
-
 
834
                 // Build the array of contexts we are going to look
845
            $modinfo = get_fast_modinfo($courseid);
835
                 $systemctx = context_system::instance();
846
 
836
                 $coursectx = context_course::instance($courseid);
847
            // Get contextids of modules from the course that support publishing questions.
837
                 $parentctxs = $coursectx->get_parent_context_ids();
-
 
838
                 foreach ($parentctxs as $parentctx) {
848
            $supportedcontextids = [];
839
                     // Exclude system context
-
 
840
                     if ($parentctx == $systemctx->id) {
849
            foreach ($modinfo->get_cms() as $cm) {
-
 
850
                if (plugin_supports('mod', $cm->modname, FEATURE_PUBLISHES_QUESTIONS, false)) {
841
                         continue;
851
                    $supportedcontextids[] = $cm->context->id;
842
                     }
-
 
843
                     $contexts[] = $parentctx;
852
                }
844
                 }
853
            }
845
                 if (!empty($stamps) && !empty($contexts)) {
854
 
846
                     // Prepare the query
855
            if (!empty($stamps) && !empty($supportedcontextids)) {
847
                     list($stamp_sql, $stamp_params) = $DB->get_in_or_equal($stamps);
856
                [$stampsql, $stampparams] = $DB->get_in_or_equal($stamps);
848
                     list($context_sql, $context_params) = $DB->get_in_or_equal($contexts);
857
                [$contextsql, $contextparams] = $DB->get_in_or_equal($supportedcontextids);
849
                     $sql = "SELECT DISTINCT contextid
858
                $sql = "SELECT DISTINCT contextid
850
                               FROM {question_categories}
859
                          FROM {question_categories}
851
                              WHERE stamp $stamp_sql
860
                         WHERE stamp {$stampsql}
852
                                AND contextid $context_sql";
861
                           AND contextid {$contextsql}";
853
                     $params = array_merge($stamp_params, $context_params);
862
                $params = array_merge($stampparams, $contextparams);
854
                     $matchingcontexts = $DB->get_records_sql($sql, $params);
863
                $matchingcontexts = $DB->get_records_sql($sql, $params);
855
                     // Only if ONE and ONLY ONE context is found, use it as valid target
864
                // Only if ONE and ONLY ONE context is found, use it as valid target.
856
                     if (count($matchingcontexts) == 1) {
-
 
857
                         $targetcontext = context::instance_by_id(reset($matchingcontexts)->contextid);
-
 
858
                     }
865
                if (count($matchingcontexts) === 1) {
859
                 }
-
 
860
                 break;
-
 
861
 
-
 
862
             // For course is easy, the best context is the course context
-
 
863
             case CONTEXT_COURSE:
-
 
864
                 $targetcontext = context_course::instance($courseid);
-
 
865
                 break;
-
 
866
 
-
 
867
             // For module is easy, there is not best context, as far as the
-
 
868
             // activity hasn't been created yet. So we return context course
-
 
869
             // for them, so permission checks and friends will work. Note this
866
                    $targetcontext = context::instance_by_id(reset($matchingcontexts)->contextid);
870
             // case is handled by {@link prechek_precheck_qbanks_by_level}
-
 
871
             // in an special way
867
                }
-
 
868
            }
872
             case CONTEXT_MODULE:
869
            // We don't have a target so set as course context until the module is created and then assign to the module context.
873
                 $targetcontext = context_course::instance($courseid);
870
            $targetcontext = $targetcontext ?: context_course::instance($courseid);
Línea 874... Línea 871...
874
                 break;
871
        }
875
        }
872
 
Línea 918... Línea 915...
918
     * @return array of result object
915
     * @return array of result object
919
     */
916
     */
920
    public static function send_files_to_pool($basepath, $restoreid, $component, $filearea,
917
    public static function send_files_to_pool($basepath, $restoreid, $component, $filearea,
921
            $oldcontextid, $dfltuserid, $itemname = null, $olditemid = null,
918
            $oldcontextid, $dfltuserid, $itemname = null, $olditemid = null,
922
            $forcenewcontextid = null, $skipparentitemidctxmatch = false,
919
            $forcenewcontextid = null, $skipparentitemidctxmatch = false,
923
            \core\progress\base $progress = null) {
920
            ?\core\progress\base $progress = null) {
924
        global $DB, $CFG;
921
        global $DB, $CFG;
Línea 925... Línea 922...
925
 
922
 
926
        $backupinfo = backup_general_helper::get_backup_information(basename($basepath));
923
        $backupinfo = backup_general_helper::get_backup_information(basename($basepath));
Línea 1736... Línea 1733...
1736
     * @param int $userid User id
1733
     * @param int $userid User id
1737
     * @param bool $samesite True if restore is to same site
1734
     * @param bool $samesite True if restore is to same site
1738
     * @param \core\progress\base $progress Optional progress tracker
1735
     * @param \core\progress\base $progress Optional progress tracker
1739
     */
1736
     */
1740
    public static function process_included_users($restoreid, $courseid, $userid, $samesite,
1737
    public static function process_included_users($restoreid, $courseid, $userid, $samesite,
1741
            \core\progress\base $progress = null) {
1738
            ?\core\progress\base $progress = null) {
1742
        global $DB;
1739
        global $DB;
Línea 1743... Línea 1740...
1743
 
1740
 
1744
        // Just let precheck_included_users() to do all the hard work
1741
        // Just let precheck_included_users() to do all the hard work
Línea 1825... Línea 1822...
1825
                $suffixfull  = '';
1822
                $suffixfull  = '';
1826
                $suffixshort = '';
1823
                $suffixshort = '';
1827
            }
1824
            }
Línea 1828... Línea 1825...
1828
 
1825
 
-
 
1826
            // Ensure we don't overflow maximum length of name fields, in multi-byte safe manner.
1829
            // Ensure we don't overflow maximum length of name fields, in multi-byte safe manner.
1827
            $currentfullname = core_text::substr($fullname, 0,
-
 
1828
                    \core_course\constants::FULLNAME_MAXIMUM_LENGTH - strlen($suffixfull)) . $suffixfull;
1830
            $currentfullname = core_text::substr($fullname, 0, 254 - strlen($suffixfull)) . $suffixfull;
1829
            $currentshortname = core_text::substr($shortname, 0,
Línea 1831... Línea 1830...
1831
            $currentshortname = core_text::substr($shortname, 0, 100 - strlen($suffixshort)) . $suffixshort;
1830
                    \core_course\constants::SHORTNAME_MAXIMUM_LENGTH - strlen($suffixshort)) . $suffixshort;
1832
 
1831
 
1833
            $coursefull  = $DB->get_record_select('course', 'fullname = ? AND id != ?',
1832
            $coursefull  = $DB->get_record_select('course', 'fullname = ? AND id != ?',
1834
                    array($currentfullname, $courseid), '*', IGNORE_MULTIPLE);
1833
                    array($currentfullname, $courseid), '*', IGNORE_MULTIPLE);
Línea 1903... Línea 1902...
1903
     * Deletes all of the content associated with the given course (courseid)
1902
     * Deletes all of the content associated with the given course (courseid)
1904
     * @param int $courseid
1903
     * @param int $courseid
1905
     * @param array $options
1904
     * @param array $options
1906
     * @return bool True for success
1905
     * @return bool True for success
1907
     */
1906
     */
1908
    public static function delete_course_content($courseid, array $options = null) {
1907
    public static function delete_course_content($courseid, ?array $options = null) {
1909
        return remove_course_contents($courseid, false, $options);
1908
        return remove_course_contents($courseid, false, $options);
1910
    }
1909
    }
Línea 1911... Línea 1910...
1911
 
1910
 
1912
    /**
1911
    /**
Línea 1917... Línea 1916...
1917
     * @return bool
1916
     * @return bool
1918
     */
1917
     */
1919
    private static function password_should_be_discarded(#[\SensitiveParameter] string $password): bool {
1918
    private static function password_should_be_discarded(#[\SensitiveParameter] string $password): bool {
1920
        return (bool) preg_match('/^[0-9a-f]{32}$/', $password);
1919
        return (bool) preg_match('/^[0-9a-f]{32}$/', $password);
1921
    }
1920
    }
-
 
1921
 
-
 
1922
    /**
-
 
1923
     * Load required classes and return a backup XML transformer for the specified course.
-
 
1924
     *
-
 
1925
     * These classes may not have been loaded if we're only doing a restore in the current process,
-
 
1926
     * so make sure we have them here.
-
 
1927
     *
-
 
1928
     * @param int $courseid
-
 
1929
     * @return backup_xml_transformer
-
 
1930
     */
-
 
1931
    protected static function get_backup_xml_transformer(int $courseid): backup_xml_transformer {
-
 
1932
        global $CFG;
-
 
1933
        require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
-
 
1934
        require_once($CFG->dirroot . '/backup/moodle2/backup_plan_builder.class.php');
-
 
1935
        return new backup_xml_transformer($courseid);
-
 
1936
    }
1922
}
1937
}
Línea 1923... Línea 1938...
1923
 
1938
 
1924
/*
1939
/*
1925
 * Exception class used by all the @dbops stuff
1940
 * Exception class used by all the @dbops stuff