@@ -282,11 +282,10 @@ public function importpreprocess() {
282
282
/**
283
283
* Process the file
284
284
* This method should not normally be overidden
285
- * @param object $category
286
285
* @return bool success
287
286
*/
288
- public function importprocess ($ category ) {
289
- global $ USER , $ CFG , $ DB , $ OUTPUT ;
287
+ public function importprocess () {
288
+ global $ USER , $ DB , $ OUTPUT ;
290
289
291
290
// Raise time and memory, as importing can be quite intensive.
292
291
core_php_time_limit::raise ();
@@ -543,10 +542,14 @@ protected function create_category_path($catpath) {
543
542
} else if ($ category = $ DB ->get_record ('question_categories ' ,
544
543
array ('name ' => $ catname , 'contextid ' => $ context ->id , 'parent ' => $ parent ))) {
545
544
$ parent = $ category ->id ;
546
- } else if ($ parent == 0 ) {
547
- $ category = question_get_top_category ($ context ->id , true );
548
- $ parent = $ category ->id ;
549
545
} else {
546
+ if ($ catname == 'top ' ) {
547
+ // Should not happen, but if it does just move on.
548
+ // Occurs when there has been some import/export that has created
549
+ // multiple nested 'top' categories (due to old bug solved by MDL-63165).
550
+ // Not throwing an error here helps clean up old errors (silently).
551
+ continue ;
552
+ }
550
553
require_capability ('moodle/question:managecategory ' , $ context );
551
554
// create the new category
552
555
$ category = new stdClass ();
@@ -556,9 +559,8 @@ protected function create_category_path($catpath) {
556
559
$ category ->parent = $ parent ;
557
560
$ category ->sortorder = 999 ;
558
561
$ category ->stamp = make_unique_id_code ();
559
- $ id = $ DB ->insert_record ('question_categories ' , $ category );
560
- $ category ->id = $ id ;
561
- $ parent = $ id ;
562
+ $ category ->id = $ DB ->insert_record ('question_categories ' , $ category );
563
+ $ parent = $ category ->id ;
562
564
}
563
565
}
564
566
return $ category ;
@@ -800,7 +802,13 @@ protected function presave_process($content) {
800
802
* @return string The content of the export.
801
803
*/
802
804
public function exportprocess ($ checkcapabilities = true ) {
803
- global $ CFG , $ OUTPUT , $ DB , $ USER ;
805
+ global $ CFG , $ DB ;
806
+
807
+ // Get the parents (from database) for this category.
808
+ $ parents = [];
809
+ if ($ this ->category ) {
810
+ $ parents = question_categorylist_parents ($ this ->category ->id );
811
+ }
804
812
805
813
// get the questions (from database) in this category
806
814
// only get q's with no parents (no cloze subquestions specifically)
@@ -821,7 +829,17 @@ public function exportprocess($checkcapabilities = true) {
821
829
// file if selected. 0 means that it will get printed before the 1st question
822
830
$ trackcategory = 0 ;
823
831
824
- // iterate through questions
832
+ // Array of categories written to file.
833
+ $ writtencategories = [];
834
+
835
+ foreach ($ parents as $ parent ) {
836
+ $ categoryname = $ this ->get_category_path ($ parent , $ this ->contexttofile );
837
+ // Create 'dummy' question for category export.
838
+ $ dummyquestion = $ this ->create_dummy_question_representing_category ($ categoryname );
839
+ $ expout .= $ this ->writequestion ($ dummyquestion ) . "\n" ;
840
+ $ writtencategories [] = $ parent ;
841
+ }
842
+
825
843
foreach ($ questions as $ question ) {
826
844
// used by file api
827
845
$ contextid = $ DB ->get_field ('question_categories ' , 'contextid ' ,
@@ -840,19 +858,33 @@ public function exportprocess($checkcapabilities = true) {
840
858
841
859
// check if we need to record category change
842
860
if ($ this ->cattofile ) {
861
+ $ addnewcat = false ;
843
862
if ($ question ->category != $ trackcategory ) {
863
+ $ addnewcat = true ;
844
864
$ trackcategory = $ question ->category ;
845
865
$ categoryname = $ this ->get_category_path ($ trackcategory , $ this ->contexttofile );
846
-
847
- // create 'dummy' question for category export
848
- $ dummyquestion = new stdClass ();
849
- $ dummyquestion ->qtype = 'category ' ;
850
- $ dummyquestion ->category = $ categoryname ;
851
- $ dummyquestion ->name = 'Switch category to ' . $ categoryname ;
852
- $ dummyquestion ->id = 0 ;
853
- $ dummyquestion ->questiontextformat = '' ;
854
- $ dummyquestion ->contextid = 0 ;
866
+ }
867
+ $ trackcategoryparents = question_categorylist_parents ($ trackcategory );
868
+ // Check if we need to record empty parents categories.
869
+ foreach ($ trackcategoryparents as $ trackcategoryparent ) {
870
+ // If parent wasn't written.
871
+ if (!in_array ($ trackcategoryparent , $ writtencategories )) {
872
+ // If parent is empty.
873
+ if (!count ($ DB ->get_records ('question ' , array ('category ' => $ trackcategoryparent )))) {
874
+ $ categoryname = $ this ->get_category_path ($ trackcategoryparent , $ this ->contexttofile );
875
+ // Create 'dummy' question for parent category.
876
+ $ dummyquestion = $ this ->create_dummy_question_representing_category ($ categoryname );
877
+ $ expout .= $ this ->writequestion ($ dummyquestion ) . "\n" ;
878
+ $ writtencategories [] = $ trackcategoryparent ;
879
+ }
880
+ }
881
+ }
882
+ if ($ addnewcat && !in_array ($ trackcategory , $ writtencategories )) {
883
+ $ categoryname = $ this ->get_category_path ($ trackcategory , $ this ->contexttofile );
884
+ // Create 'dummy' question for category.
885
+ $ dummyquestion = $ this ->create_dummy_question_representing_category ($ categoryname );
855
886
$ expout .= $ this ->writequestion ($ dummyquestion ) . "\n" ;
887
+ $ writtencategories [] = $ trackcategory ;
856
888
}
857
889
}
858
890
@@ -878,6 +910,22 @@ public function exportprocess($checkcapabilities = true) {
878
910
return $ expout ;
879
911
}
880
912
913
+ /**
914
+ * Create 'dummy' question for category export.
915
+ * @param string $categoryname the name of the category
916
+ * @return stdClass 'dummy' question for category
917
+ */
918
+ protected function create_dummy_question_representing_category (string $ categoryname ) {
919
+ $ dummyquestion = new stdClass ();
920
+ $ dummyquestion ->qtype = 'category ' ;
921
+ $ dummyquestion ->category = $ categoryname ;
922
+ $ dummyquestion ->id = 0 ;
923
+ $ dummyquestion ->questiontextformat = '' ;
924
+ $ dummyquestion ->contextid = 0 ;
925
+ $ dummyquestion ->name = 'Switch category to ' . $ categoryname ;
926
+ return $ dummyquestion ;
927
+ }
928
+
881
929
/**
882
930
* get the category as a path (e.g., tom/dick/harry)
883
931
* @param int id the id of the most nested catgory
0 commit comments