Merge branch 'w13_MDL-37742_m25_dirtyoracle' of git://github.com/skodak/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Tue, 26 Mar 2013 22:04:48 +0000 (23:04 +0100)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Tue, 26 Mar 2013 22:04:48 +0000 (23:04 +0100)
Conflicts:
lib/upgrade.txt

1  2 
cohort/lib.php
lib/datalib.php
lib/upgrade.txt

diff --combined cohort/lib.php
@@@ -40,7 -40,6 +40,6 @@@ function cohort_add_cohort($cohort) 
          $cohort->idnumber = NULL;
      }
      if (!isset($cohort->description)) {
-         // sql_empty() does not belong here, this crazy Oracle hack is implemented in insert_record()!
          $cohort->description = '';
      }
      if (!isset($cohort->descriptionformat)) {
@@@ -102,7 -101,7 +101,7 @@@ function cohort_delete_cohort($cohort) 
   * Somehow deal with cohorts when deleting course category,
   * we can not just delete them because they might be used in enrol
   * plugins or referenced in external systems.
 - * @param  stdClass $category
 + * @param  stdClass|coursecat $category
   * @return void
   */
  function cohort_delete_category($category) {
diff --combined lib/datalib.php
@@@ -837,7 -837,7 +837,7 @@@ function get_courses_wmanagers($categor
   * @param int $totalcount Passed in by reference.
   * @return object {@link $COURSE} records
   */
 -function get_courses_search($searchterms, $sort='fullname ASC', $page=0, $recordsperpage=50, &$totalcount) {
 +function get_courses_search($searchterms, $sort, $page, $recordsperpage, &$totalcount) {
      global $CFG, $DB;
  
      if ($DB->sql_regex_supported()) {
      if ($DB->get_dbfamily() == 'oracle') {
          $concat = $DB->sql_concat('c.summary', "' '", 'c.fullname', "' '", 'c.idnumber', "' '", 'c.shortname');
      } else {
-         $concat = $DB->sql_concat("COALESCE(c.summary, '". $DB->sql_empty() ."')", "' '", 'c.fullname', "' '", 'c.idnumber', "' '", 'c.shortname');
+         $concat = $DB->sql_concat("COALESCE(c.summary, :empty)", "' '", 'c.fullname', "' '", 'c.idnumber', "' '", 'c.shortname');
+         $params['empty'] = '';
      }
  
      foreach ($searchterms as $searchterm) {
      $limitto   = $limitfrom + $recordsperpage;
  
      list($ccselect, $ccjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
 -    $sql = "SELECT c.* $ccselect
 +    $fields = array_diff(array_keys($DB->get_columns('course')), array('modinfo', 'sectioncache'));
 +    $sql = "SELECT c.".join(',c.',$fields)." $ccselect
                FROM {course} c
             $ccjoin
               WHERE $searchcond AND c.id <> ".SITEID."
  
      $rs = $DB->get_recordset_sql($sql, $params);
      foreach($rs as $course) {
 -        context_instance_preload($course);
 -        $coursecontext = context_course::instance($course->id);
 -        if ($course->visible || has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
 -            // Don't exit this loop till the end
 -            // we need to count all the visible courses
 -            // to update $totalcount
 -            if ($c >= $limitfrom && $c < $limitto) {
 -                $courses[$course->id] = $course;
 +        if (!$course->visible) {
 +            // preload contexts only for hidden courses or courses we need to return
 +            context_instance_preload($course);
 +            $coursecontext = context_course::instance($course->id);
 +            if (!has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
 +                continue;
              }
 -            $c++;
          }
 +        // Don't exit this loop till the end
 +        // we need to count all the visible courses
 +        // to update $totalcount
 +        if ($c >= $limitfrom && $c < $limitto) {
 +            $courses[$course->id] = $course;
 +        }
 +        $c++;
      }
      $rs->close();
  
      return $courses;
  }
  
 -
 -/**
 - * Returns a sorted list of categories. Each category object has a context
 - * property that is a context object.
 - *
 - * When asking for $parent='none' it will return all the categories, regardless
 - * of depth. Wheen asking for a specific parent, the default is to return
 - * a "shallow" resultset. Pass false to $shallow and it will return all
 - * the child categories as well.
 - *
 - * @global object
 - * @uses CONTEXT_COURSECAT
 - * @param string $parent The parent category if any
 - * @param string $sort the sortorder
 - * @param bool   $shallow - set to false to get the children too
 - * @return array of categories
 - */
 -function get_categories($parent='none', $sort=NULL, $shallow=true) {
 -    global $DB;
 -
 -    if ($sort === NULL) {
 -        $sort = 'ORDER BY cc.sortorder ASC';
 -    } elseif ($sort ==='') {
 -        // leave it as empty
 -    } else {
 -        $sort = "ORDER BY $sort";
 -    }
 -
 -    list($ccselect, $ccjoin) = context_instance_preload_sql('cc.id', CONTEXT_COURSECAT, 'ctx');
 -
 -    if ($parent === 'none') {
 -        $sql = "SELECT cc.* $ccselect
 -                  FROM {course_categories} cc
 -               $ccjoin
 -                $sort";
 -        $params = array();
 -
 -    } elseif ($shallow) {
 -        $sql = "SELECT cc.* $ccselect
 -                  FROM {course_categories} cc
 -               $ccjoin
 -                 WHERE cc.parent=?
 -                $sort";
 -        $params = array($parent);
 -
 -    } else {
 -        $sql = "SELECT cc.* $ccselect
 -                  FROM {course_categories} cc
 -               $ccjoin
 -                  JOIN {course_categories} ccp
 -                       ON ((cc.parent = ccp.id) OR (cc.path LIKE ".$DB->sql_concat('ccp.path',"'/%'")."))
 -                 WHERE ccp.id=?
 -                $sort";
 -        $params = array($parent);
 -    }
 -    $categories = array();
 -
 -    $rs = $DB->get_recordset_sql($sql, $params);
 -    foreach($rs as $cat) {
 -        context_instance_preload($cat);
 -        $catcontext = context_coursecat::instance($cat->id);
 -        if ($cat->visible || has_capability('moodle/category:viewhiddencategories', $catcontext)) {
 -            $categories[$cat->id] = $cat;
 -        }
 -    }
 -    $rs->close();
 -    return $categories;
 -}
 -
 -
 -/**
 - * Returns an array of category ids of all the subcategories for a given
 - * category.
 - *
 - * @global object
 - * @param int $catid - The id of the category whose subcategories we want to find.
 - * @return array of category ids.
 - */
 -function get_all_subcategories($catid) {
 -    global $DB;
 -
 -    $subcats = array();
 -
 -    if ($categories = $DB->get_records('course_categories', array('parent'=>$catid))) {
 -        foreach ($categories as $cat) {
 -            array_push($subcats, $cat->id);
 -            $subcats = array_merge($subcats, get_all_subcategories($cat->id));
 -        }
 -    }
 -    return $subcats;
 -}
 -
 -/**
 - * Return specified category, default if given does not exist
 - *
 - * @global object
 - * @uses MAX_COURSES_IN_CATEGORY
 - * @uses CONTEXT_COURSECAT
 - * @uses SYSCONTEXTID
 - * @param int $catid course category id
 - * @return object caregory
 - */
 -function get_course_category($catid=0) {
 -    global $DB;
 -
 -    $category = false;
 -
 -    if (!empty($catid)) {
 -        $category = $DB->get_record('course_categories', array('id'=>$catid));
 -    }
 -
 -    if (!$category) {
 -        // the first category is considered default for now
 -        if ($category = $DB->get_records('course_categories', null, 'sortorder', '*', 0, 1)) {
 -            $category = reset($category);
 -
 -        } else {
 -            $cat = new stdClass();
 -            $cat->name         = get_string('miscellaneous');
 -            $cat->depth        = 1;
 -            $cat->sortorder    = MAX_COURSES_IN_CATEGORY;
 -            $cat->timemodified = time();
 -            $catid = $DB->insert_record('course_categories', $cat);
 -            // make sure category context exists
 -            context_coursecat::instance($catid);
 -            mark_context_dirty('/'.SYSCONTEXTID);
 -            fix_course_sortorder(); // Required to build course_categories.depth and .path.
 -            $category = $DB->get_record('course_categories', array('id'=>$catid));
 -        }
 -    }
 -
 -    return $category;
 -}
 -
  /**
   * Fixes course category and course sortorder, also verifies category and course parents and paths.
   * (circular references are not fixed)
@@@ -956,14 -1086,9 +957,14 @@@ function fix_course_sortorder() 
  
      //WARNING: this is PHP5 only code!
  
 +    // if there are any changes made to courses or categories we will trigger
 +    // the cache events to purge all cached courses/categories data
 +    $cacheevents = array();
 +
      if ($unsorted = $DB->get_records('course_categories', array('sortorder'=>0))) {
          //move all categories that are not sorted yet to the end
          $DB->set_field('course_categories', 'sortorder', MAX_COURSES_IN_CATEGORY*MAX_COURSE_CATEGORIES, array('sortorder'=>0));
 +        $cacheevents['changesincoursecat'] = true;
      }
  
      $allcats = $DB->get_records('course_categories', null, 'sortorder, id', 'id, sortorder, parent, depth, path');
      // now walk recursively the tree and fix any problems found
      $sortorder = 0;
      $fixcontexts = array();
 -    _fix_course_cats($topcats, $sortorder, 0, 0, '', $fixcontexts);
 +    if (_fix_course_cats($topcats, $sortorder, 0, 0, '', $fixcontexts)) {
 +        $cacheevents['changesincoursecat'] = true;
 +    }
  
      // detect if there are "multiple" frontpage courses and fix them if needed
      $frontcourses = $DB->get_records('course', array('category'=>0), 'id');
              $DB->set_field('course', 'category', $defaultcat->id, array('id'=>$course->id));
              $context = context_course::instance($course->id);
              $fixcontexts[$context->id] = $context;
 +            $cacheevents['changesincourse'] = true;
          }
          unset($frontcourses);
      } else {
          }
          context_helper::build_all_paths(false);
          unset($fixcontexts);
 +        $cacheevents['changesincourse'] = true;
 +        $cacheevents['changesincoursecat'] = true;
      }
  
      // release memory
      // fix frontpage course sortorder
      if ($frontcourse->sortorder != 1) {
          $DB->set_field('course', 'sortorder', 1, array('id'=>$frontcourse->id));
 +        $cacheevents['changesincourse'] = true;
      }
  
      // now fix the course counts in category records if needed
              $str = implode(', ', $categories);
              debugging("The number of courses (category id: $str) has reached MAX_COURSES_IN_CATEGORY (" . MAX_COURSES_IN_CATEGORY . "), it will cause a sorting performance issue, please increase the value of MAX_COURSES_IN_CATEGORY in lib/datalib.php file. See tracker issue: MDL-25669", DEBUG_DEVELOPER);
          }
 +        $cacheevents['changesincoursecat'] = true;
      }
  
      // now make sure that sortorders in course table are withing the category sortorder ranges
                       WHERE category = ?";
              $DB->execute($sql, array($cat->sortorder, $cat->id));
          }
 +        $cacheevents['changesincoursecat'] = true;
      }
      unset($fixcategories);
  
              // it needs full resorting
              $fixcategories[$cat->id] = $cat;
          }
 +        $cacheevents['changesincourse'] = true;
      }
      unset($gapcategories);
  
              if ($course->sortorder != $cat->sortorder + $i) {
                  $course->sortorder = $cat->sortorder + $i;
                  $DB->update_record_raw('course', $course, true);
 +                $cacheevents['changesincourse'] = true;
              }
              $i++;
          }
      }
 +
 +    // advise all caches that need to be rebuilt
 +    foreach (array_keys($cacheevents) as $event) {
 +        cache_helper::purge_by_event($event);
 +    }
  }
  
  /**
   * @param int $depth
   * @param string $path
   * @param array $fixcontexts
 - * @return void
 + * @return bool if changes were made
   */
  function _fix_course_cats($children, &$sortorder, $parent, $depth, $path, &$fixcontexts) {
      global $DB;
  
      $depth++;
 +    $changesmade = false;
  
      foreach ($children as $cat) {
          $sortorder = $sortorder + MAX_COURSES_IN_CATEGORY;
          }
          if ($update) {
              $DB->update_record('course_categories', $cat, true);
 +            $changesmade = true;
          }
          if (isset($cat->children)) {
 -            _fix_course_cats($cat->children, $sortorder, $cat->id, $cat->depth, $cat->path, $fixcontexts);
 +            if (_fix_course_cats($cat->children, $sortorder, $cat->id, $cat->depth, $cat->path, $fixcontexts)) {
 +                $changesmade = true;
 +            }
          }
      }
 +    return $changesmade;
  }
  
  /**
diff --combined lib/upgrade.txt
@@@ -34,15 -34,9 +34,19 @@@ information provided here is intended e
  * condition_info:get_condition_user_fields($formatoptions) now accepts the optional
    param $formatoptions, that will determine if the field names are processed by
    format_string() with the passed options.
 +* remove all references to $CFG->gdversion, GD PHP extension is now required
 +* Formslib will now throw a developer warning if a PARAM_ type hasn't been set for elements which
 +  need it. Please set PARAM_RAW explicitly if you do not want any cleaning.
 +* Functions responsible for managing and accessing course categories are moved to class coursecat
 +  in lib/coursecatlib.php. The following global functions are deprecated: make_categories_list(),
 +  category_delete_move(), category_delete_full(), move_category(), course_category_hide(),
 +  course_category_show(), get_course_category(), create_course_category(), get_all_subcategories(),
 +  get_child_categories(), get_categories()
 +
++Database (DML) layer:
+ * $DB->sql_empty() is deprecated, you have to use sql parameters with empty values instead,
+   please note hardcoding of empty strings in SQL queries breaks execution in Oracle database.
  YUI changes:
  * M.util.help_icon has been deprecated. Code should be updated to use moodle-core-popuphelp
    instead. To do so, remove any existing JS calls to M.util.help_icon from your PHP and ensure