/**
  * Adds SQL to a dynamic query for when there is a question node as an ancestor of the current
  * nodes.
  *
  * @static
  * @param block_ajax_marking_query $query
  * @return mixed|void
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     // Apply WHERE clause.
     $conditions = array('table' => 'question', 'column' => 'id', 'alias' => 'questionid');
     // TODO needs applying to just the quiz one.
     $query->add_select($conditions);
 }
 /**
  * @param block_ajax_marking_query $query
  * @param int|string $userid
  */
 protected function alter_query(block_ajax_marking_query $query, $userid)
 {
     // Applies if users are not the final nodes.
     $clause = array('type' => 'AND', 'condition' => 'quiz_attempts.userid = :quizuseridfilterancestor');
     $query->add_where($clause);
     $query->add_param('quizuseridfilterancestor', $userid);
 }
 /**
  * Adds SQL to construct a set of discussion nodes.
  *
  * @param block_ajax_marking_query $query
  * @return mixed|void
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     // We join like this because we can't put extra stuff into the UNION ALL bit
     // unless all modules have it and this is unique to forums.
     $query->add_from(array('table' => 'forum_posts', 'on' => 'moduleunion.subid = post.id', 'alias' => 'post'));
     $query->add_from(array('table' => 'forum_discussions', 'on' => 'discussion.id = post.discussion', 'alias' => 'discussion'));
     $query->add_select(array('table' => 'discussion', 'column' => 'id'), true);
 }
 /**
  * Applies the filter needed for course nodes or their descendants
  *
  * @param block_ajax_marking_query $query
  * @SuppressWarnings(PHPMD.UnusedPrivateMethod) Dynamic method names don't register
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     // This is for the displayquery when we are making course nodes.
     $query->add_from(array('table' => 'course', 'alias' => 'course', 'on' => 'countwrapperquery.id = course.id'));
     $query->add_select(array('table' => 'course', 'column' => 'shortname', 'alias' => 'name'));
     $query->add_select(array('table' => 'course', 'column' => 'fullname', 'alias' => 'tooltip'));
     $query->add_orderby('course.shortname ASC');
 }
 /**
  * Applies the filter needed for course nodes or their descendants
  *
  * @param block_ajax_marking_query $query
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     // This is for the displayquery when we are making course nodes.
     $query->add_from(array('join' => 'LEFT JOIN', 'table' => 'groups', 'on' => 'countwrapperquery.id = groups.id'));
     // We may get a load of people in no group.
     $query->add_select(array('function' => 'COALESCE', 'table' => array('groups' => 'name', get_string('notingroup', 'block_ajax_marking')), 'alias' => 'name'));
     $query->add_select(array('function' => 'COALESCE', 'table' => array('groups' => 'description', get_string('notingroupdescription', 'block_ajax_marking')), 'alias' => 'tooltip'));
     $query->add_orderby("COALESCE(groups.name, '" . get_string('notingroup', 'block_ajax_marking') . "') ASC");
 }
 /**
  * This will join the cohorts tables so tht the id can be added to the query in some way.
  *
  * @todo doesn't deal with a user being in more than one cohort yet.
  * @param block_ajax_marking_query $query
  * @return void
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     // We need to join the userid to the cohort, if there is one.
     // TODO when is there not one?
     // Add join to cohort_members.
     $table = array('join' => 'INNER JOIN', 'table' => 'cohort_members', 'on' => 'cohort_members.userid = moduleunion.userid');
     $query->add_from($table);
     $table = array('join' => 'INNER JOIN', 'table' => 'cohort', 'on' => 'cohort_members.cohortid = cohort.id');
     $query->add_from($table);
 }
 /**
  * Makes SQL for the text labels for the course nodes.
  *
  * @static
  * @param block_ajax_marking_query $query
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     // Same order as the super query will need them. Prefixed so we will have it as the
     // first column for the GROUP BY.
     $query->add_from(array('join' => 'INNER JOIN', 'table' => 'course_modules', 'on' => 'course_modules.id = countwrapperquery.id'));
     $query->add_select(array('table' => 'course_modules', 'column' => 'id', 'alias' => 'coursemoduleid'));
     // The javascript needs this for styling.
     $query->add_select(array('table' => 'countwrapperquery', 'column' => 'modulename'));
     // This will add the stuff that joins to the various module tables and gets the right names.
     $moduleclasses = block_ajax_marking_get_module_classes();
     $introcoalesce = array();
     $namecoalesce = array();
     $orderbycoalesce = array();
     foreach ($moduleclasses as $moduleclass) {
         $moduletablename = $moduleclass->get_module_name();
         $query->add_from(array('join' => 'LEFT JOIN', 'table' => $moduletablename, 'on' => "(course_modules.instance = " . $moduletablename . ".id\n                                            AND course_modules.module = '" . $moduleclass->get_module_id() . "')"));
         $namecoalesce[$moduletablename] = 'name';
         $introcoalesce[$moduletablename] = 'intro';
         $orderbycoalesce[$moduletablename] = $moduletablename . '.name';
     }
     $query->add_select(array('table' => 'course_modules', 'column' => 'id', 'alias' => 'coursemoduleid'));
     $query->add_select(array('table' => $namecoalesce, 'function' => 'COALESCE', 'column' => 'name', 'alias' => 'name'));
     $query->add_select(array('table' => $introcoalesce, 'function' => 'COALESCE', 'column' => 'intro', 'alias' => 'tooltip'));
     $query->add_orderby('COALESCE(' . implode(', ', $orderbycoalesce) . ') ASC');
     // This will add the stuff that will show us the name of the actual module instance.
     // We use the same stuff for both config and marking trees, but the config tree doesn't need
     // the stuff to pull through submission counts.
     // TODO separate counts.
     // This allows us to have separate decorators, but may obfuscate what's happening a bit.
     // Code is not duplicated, though.
 }
 /**
  * This will add a groupid to each of the submissions coming out of the moduleunion. This means getting
  * all the group memberships for this course and choosing the maximum groupid. We can't count more than
  * once when students are in two groups, so we need to do it like this. It's a greatest-n-per-group
  * problem, solved with the classic left-join approach.
  *
  * @param block_ajax_marking_query $query
  * @return void
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     list($maxquery, $maxparams) = block_ajax_marking_group_max_subquery();
     list($memberquery, $memberparams) = block_ajax_marking_group_members_subquery();
     list($visibilitysubquery, $visibilityparams) = block_ajax_marking_group_visibility_subquery();
     // We need to join to groups members to see if there are any memberships at all (in which case
     // we use the highest visible id if there is one), or 0 if there are no memberships at all.
     $table = array('join' => 'LEFT JOIN', 'table' => $memberquery, 'on' => 'membergroupquery.userid = moduleunion.userid
                  AND membergroupquery.coursemoduleid = moduleunion.coursemoduleid', 'alias' => 'membergroupquery', 'subquery' => true);
     $query->add_from($table);
     $query->add_params($memberparams);
     // To make sure it's the highest visible one, we use this subquery as a greatest-n-per-group thing.
     $table = array('join' => 'LEFT JOIN', 'table' => $maxquery, 'on' => 'membergroupquery.userid = maxgroupquery.userid
                  AND membergroupquery.coursemoduleid = maxgroupquery.coursemoduleid
                  AND maxgroupquery.groupid > membergroupquery.groupid', 'alias' => 'maxgroupquery', 'subquery' => true);
     $query->add_from($table);
     $query->add_params($maxparams);
     // We join only if the group id is larger, then specify that it must be null. This means that
     // the membergroupquery group id will be the largest available.
     $query->add_where(array('type' => 'AND', 'condition' => 'maxgroupquery.groupid IS NULL'));
     // Make sure it's not hidden. We want to know if there are people with no group, compared to a group that
     // is hidden, so the aim is to get a null group id if there are no memberships by left joining, then
     // hide that null row if the settings for group id 0 say so.
     $table = array('join' => 'LEFT JOIN', 'table' => $visibilitysubquery, 'on' => '(membervisibilityquery.groupid = membergroupquery.groupid OR
                   (membervisibilityquery.groupid = 0 AND membergroupquery.groupid IS NULL))
                  AND membervisibilityquery.coursemoduleid = membergroupquery.coursemoduleid', 'alias' => 'membervisibilityquery', 'subquery' => true);
     $query->add_from($table);
     $query->add_params($visibilityparams);
     $query->add_where(array('type' => 'AND', 'condition' => 'membervisibilityquery.coursemoduleid IS NULL'));
 }
 /**
  * Applies the filter needed for course nodes or their descendants
  *
  * @param block_ajax_marking_query $query
  * @SuppressWarnings(PHPMD.UnusedPrivateMethod) Dynamic method names don't register
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     // What do we need for the nodes?
     $table = array('join' => 'INNER JOIN', 'table' => 'cohort', 'on' => 'countwrapperquery.id = cohort.id');
     $query->add_from($table);
     $conditions = array('table' => 'cohort', 'column' => 'name');
     $query->add_select($conditions);
     $conditions = array('table' => 'cohort', 'column' => 'description');
     $query->add_select($conditions);
     $query->add_orderby('cohort.name ASC');
 }
 /**
  * Makes user nodes for the assign modules by grouping them and then adding in the right
  * text to describe them.
  *
  * @static
  * @param block_ajax_marking_query $query
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     $conditions = array('table' => 'countwrapperquery', 'column' => 'timestamp', 'alias' => 'tooltip');
     $query->add_select($conditions);
     $conditions = array('table' => 'usertable', 'column' => 'firstname');
     $query->add_select($conditions);
     $conditions = array('table' => 'usertable', 'column' => 'lastname');
     $query->add_select($conditions);
     $table = array('table' => 'user', 'alias' => 'usertable', 'on' => 'usertable.id = countwrapperquery.id');
     $query->add_from($table);
 }
 /**
  * Makes a bunch of user nodes by grouping quiz submissions by the user id. The grouping is
  * automatic, but the text labels for the nodes are specified here.
  *
  * @static
  * @param block_ajax_marking_query $query
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     $query->add_select(array('table' => 'countwrapperquery', 'column' => 'timestamp', 'alias' => 'tooltip'));
     $query->add_select(array('table' => 'usertable', 'column' => 'firstname'));
     $query->add_select(array('table' => 'usertable', 'column' => 'lastname'));
     $query->add_from(array('join' => 'INNER JOIN', 'table' => 'user', 'alias' => 'usertable', 'on' => 'usertable.id = countwrapperquery.id'));
     // This is only needed to add the right callback function.
     $query->add_select(array('column' => "'quiz'", 'alias' => 'modulename'));
 }
 /**
  * Makes a set of question nodes by grouping submissions by questionid.
  *
  * @static
  * @param block_ajax_marking_query $query
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     // Outer bit to get display name.
     $query->add_from(array('join' => 'INNER JOIN', 'table' => 'question', 'on' => 'question.id = countwrapperquery.id'));
     $query->add_select(array('table' => 'question', 'column' => 'name'));
     $query->add_select(array('table' => 'question', 'column' => 'questiontext', 'alias' => 'tooltip'));
     // This is only needed to add the right callback function.
     $query->add_select(array('column' => "'quiz'", 'alias' => 'modulename'));
     $query->add_orderby("question.name ASC");
 }
 /**
  * Makes user nodes for the assignment modules by grouping them and then adding in the right
  * text to describe them.
  *
  * @static
  * @param block_ajax_marking_query $query
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     $conditions = array('table' => 'countwrapperquery', 'column' => 'timestamp', 'alias' => 'tooltip');
     $query->add_select($conditions);
     // Need this to make the popup show properly because some assignment code shows or
     // not depending on this flag to tell if it's in a pop-up e.g. the revert to draft
     // button for advanced upload.
     $conditions = array('column' => "'single'", 'alias' => 'mode');
     $query->add_select($conditions);
     $conditions = array('table' => 'usertable', 'column' => 'firstname');
     $query->add_select($conditions);
     $conditions = array('table' => 'usertable', 'column' => 'lastname');
     $query->add_select($conditions);
     $table = array('table' => 'user', 'alias' => 'usertable', 'on' => 'usertable.id = countwrapperquery.id');
     $query->add_from($table);
 }
 /**
  * Adds SQL to construct a set of discussion nodes.
  *
  * @static
  * @param block_ajax_marking_query $query
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     // This will be derived form the coursemodule id, but how to get it cleanly?
     // The query will know, but not easy to get it out. Might have been prefixed.
     // TODO pass this properly somehow.
     $coursemoduleid = required_param('coursemoduleid', PARAM_INT);
     // Normal forum needs discussion title as label, participant usernames as
     // description eachuser needs username as title and discussion subject as
     // description.
     if (block_ajax_marking_forum::forum_is_eachuser($coursemoduleid)) {
         $query->add_select(array('table' => 'firstpost', 'column' => 'subject', 'alias' => 'description'));
     } else {
         $query->add_select(array('table' => 'firstpost', 'column' => 'subject', 'alias' => 'label'));
         // TODO need a SELECT bit to get all userids of people in the discussion
         // instead.
         $query->add_select(array('table' => 'firstpost', 'column' => 'message', 'alias' => 'tooltip'));
     }
     $query->add_from(array('join' => 'INNER JOIN', 'table' => 'forum_discussions', 'alias' => 'outerdiscussions', 'on' => 'countwrapperquery.id = outerdiscussions.id'));
     $query->add_from(array('join' => 'INNER JOIN', 'table' => 'forum_posts', 'alias' => 'firstpost', 'on' => 'firstpost.id = outerdiscussions.firstpost'));
     $query->add_orderby("timestamp ASC");
 }
 /**
  * @param block_ajax_marking_query $query
  * @return void
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     // This will add the select, which will get a zero as the groupid if we don't have a group membership at all.
     $query->add_select(array('column' => block_ajax_marking_get_countwrapper_groupid_sql(), 'alias' => 'id'));
 }
 /**
  * This will change the query so that it does whatever this decorator is supposed to do.
  *
  * @param block_ajax_marking_query $query
  * @return void
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     $select = array('table' => 'moduleunion', 'column' => 'course', 'alias' => 'id');
     $query->add_select($select, true);
 }
 /**
  * Makes user nodes for the assignment modules by grouping them and then adding in the right
  * text to describe them.
  *
  * @static
  * @param block_ajax_marking_query $query
  * @return void
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     // Make the count be grouped by user id.
     $conditions = array('table' => 'moduleunion', 'column' => 'userid', 'alias' => 'id');
     $query->add_select($conditions, true);
 }
 /**
  * Adds SQL to a dynamic query for when there is a question node as an ancestor of the current
  * nodes.
  *
  * @static
  * @param block_ajax_marking_query $query
  * @param int $questionid
  */
 protected function alter_query(block_ajax_marking_query $query, $questionid)
 {
     $clause = array('type' => 'AND', 'condition' => 'moduleunion.questionid = :quizfilterquestionidancestor');
     $query->add_where($clause);
     $query->add_param('quizfilterquestionidancestor', $questionid);
 }
 /**
  * Used when there is an ancestor node representing a coursemodule.
  *
  * @static
  * @param block_ajax_marking_query $query
  * @param int|string $groupid
  * @return void
  */
 protected function alter_query(block_ajax_marking_query $query, $groupid)
 {
     $conditions = array('type' => 'AND', 'condition' => block_ajax_marking_get_countwrapper_groupid_sql() . ' = :groupid');
     $query->add_where($conditions);
     $query->add_param('groupid', $groupid);
 }
 /**
  * Applies the filter needed for course nodes or their descendants
  *
  * @param block_ajax_marking_query $query
  * @SuppressWarnings(PHPMD.UnusedPrivateMethod) Dynamic method names don't register
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     global $USER;
     // This is for the displayquery when we are making course nodes.
     $query->add_from(array('table' => 'course', 'alias' => 'course', 'on' => 'course_modules.course = course.id'));
     $query->add_select(array('table' => 'course', 'column' => 'id', 'alias' => 'courseid', 'distinct' => true));
     $query->add_select(array('table' => 'course', 'column' => 'shortname', 'alias' => 'name'));
     $query->add_select(array('table' => 'course', 'column' => 'fullname', 'alias' => 'tooltip'));
     // We need the config settings too, if there are any.
     // TODO this should be in the config filter.
     $query->add_from(array('join' => 'LEFT JOIN', 'table' => 'block_ajax_marking', 'alias' => 'settings', 'on' => "settings.instanceid = course.id\n                                 AND settings.tablename = 'course'\n                                 AND settings.userid = :settingsuserid"));
     $query->add_param('settingsuserid', $USER->id);
     $query->add_select(array('table' => 'settings', 'column' => 'display'));
     $query->add_select(array('table' => 'settings', 'column' => 'groupsdisplay'));
     $query->add_select(array('table' => 'settings', 'column' => 'id', 'alias' => 'settingsid'));
     $query->add_orderby('course.shortname ASC');
 }
 /**
  * @param block_ajax_marking_query $query
  * @return void
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     $conditions = array('table' => 'cohort', 'column' => 'id');
     $query->add_select($conditions);
 }
 /**
  * This is for when a courseid node is an ancestor of the node that has been
  * selected, so we just do a where.
  *
  * @param block_ajax_marking_query $query
  * @param int $courseid
  */
 protected function alter_query(block_ajax_marking_query $query, $courseid)
 {
     $conditions = array('type' => 'AND', 'condition' => 'moduleunion.course = :courseidancestorcourseid');
     $query->add_where($conditions);
     $query->add_param('courseidancestorcourseid', $courseid);
 }
 /**
  * Not sure we'll ever need this, but just in case...
  *
  * @static
  * @param block_ajax_marking_query $query
  * @param int $userid
  */
 public function alter_query(block_ajax_marking_query $query, $userid)
 {
     $clause = array('type' => 'AND', 'condition' => 'sub.userid = :assignmentuseridfilteruserid');
     $query->add_where($clause);
     $query->add_param('assignmentuseridfilteruserid', $userid);
 }
 /**
  * Adds SQL for when there is a discussion node as an ancestor of the current nodes.
  *
  * @static
  * @param block_ajax_marking_query $query
  * @param int $discussionid
  */
 protected function alter_query(block_ajax_marking_query $query, $discussionid)
 {
     $clause = array('type' => 'AND', 'condition' => 'discussion.id = :discussionidfilterdiscussionid');
     $query->add_where($clause);
     $query->add_param('discussionidfilterdiscussionid', $discussionid);
 }
 /**
  * This is for when a courseid node is an ancestor of the node that has been
  * selected, so we just do a where.
  *
  * @param block_ajax_marking_query $query
  * @param int|string $cohortid
  * @return void
  */
 protected function alter_query(block_ajax_marking_query $query, $cohortid)
 {
     $clause = array('type' => 'AND', 'condition' => 'cohort.id = :cohortidfiltercohortid');
     $query->add_where($clause);
     $query->add_param('cohortidfiltercohortid', $cohortid);
 }
 /**
  * Config nodes need some stuff to be returned from the config tables so we can have settings
  * adjusted based on existing values.
  *
  * @param block_ajax_marking_query $query
  * @param string $nextnodefilter
  * @return void
  */
 private static function attach_config_settings(block_ajax_marking_query $query, $nextnodefilter)
 {
     $nodesthatneedconfigsettings = array('courseid', 'coursemoduleid');
     if (!in_array($nextnodefilter, $nodesthatneedconfigsettings)) {
         return;
     }
     // The inner query joins to the config tables already for the WHERE clauses, so we
     // make use of them to get the settings for those nodes that are not filtered out.
     $countwrapper = $query->get_subquery('countwrapperquery');
     switch ($nextnodefilter) {
         // This is for the ordinary nodes. We need to work out what to request for the next node
         // so groupsdisplay has to be sent through. Also for the config context menu to work.
         // COALESCE is no good here as we need the actual settings, so we work out that stuff
         // in JavaScript.
         case 'courseid':
             $countwrapper->add_select(array('table' => 'courseconfig', 'column' => 'display'));
             $countwrapper->add_select(array('table' => 'courseconfig', 'column' => 'groupsdisplay'));
             break;
         case 'coursemoduleid':
             // The inner query joins to the config tables already for the WHERE clauses, so we
             // make use of them to get the settings for those nodes that are not filtered out.
             $countwrapper = $query->get_subquery('countwrapperquery');
             $countwrapper->add_select(array('table' => 'cmconfig', 'column' => 'display'));
             $countwrapper->add_select(array('table' => 'cmconfig', 'column' => 'groupsdisplay'));
             break;
     }
     // The outer query (we need one because we have to do a join between the numeric
     // fields that can be fed into a GROUP BY and the text fields that we display) pulls
     // through the display fields, which were sent through from the middle query using the
     // stuff above.
     $query->add_select(array('table' => 'countwrapperquery', 'column' => 'display'));
     $query->add_select(array('table' => 'countwrapperquery', 'column' => 'groupsdisplay'));
 }
 /**
  * Adds SQL to a dynamic query for when there is a question node as an ancestor of the current
  * nodes.
  *
  * @static
  * @param block_ajax_marking_query $query
  * @return mixed|void
  */
 protected function alter_query(block_ajax_marking_query $query)
 {
     $query->add_select(array('table' => 'moduleunion', 'column' => 'questionid', 'alias' => 'id'));
 }