Merge branch 'wip-MDL-55127_master' of https://github.com/dg711/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 23 Aug 2016 10:12:46 +0000 (11:12 +0100)
committerDan Poltawski <dan@moodle.com>
Tue, 23 Aug 2016 10:12:46 +0000 (11:12 +0100)
14 files changed:
mod/data/classes/search/entry.php [new file with mode: 0644]
mod/data/classes/search/sortedcontentqueue.php [new file with mode: 0644]
mod/data/field/checkbox/field.class.php
mod/data/field/menu/field.class.php
mod/data/field/multimenu/field.class.php
mod/data/field/radiobutton/field.class.php
mod/data/field/text/field.class.php
mod/data/field/textarea/field.class.php
mod/data/field/url/field.class.php
mod/data/lang/en/data.php
mod/data/lib.php
mod/data/tests/generator/lib.php
mod/data/tests/generator_test.php
mod/data/tests/search_test.php

diff --git a/mod/data/classes/search/entry.php b/mod/data/classes/search/entry.php
new file mode 100644 (file)
index 0000000..0a2e8ce
--- /dev/null
@@ -0,0 +1,330 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Search area for mod_data activity entries.
+ *
+ * @package    mod_data
+ * @copyright  2016 Devang Gaur
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\search;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->dirroot . '/mod/data/lib.php');
+require_once($CFG->dirroot . '/lib/grouplib.php');
+
+/**
+ * Search area for mod_data activity entries.
+ *
+ * @package    mod_data
+ * @copyright  2016 Devang Gaur
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class entry extends \core_search\base_mod {
+
+    /**
+     * @var array Internal quick static cache.
+     */
+    protected $entriesdata = array();
+
+    /**
+     * Returns recordset containing required data for indexing database entries.
+     *
+     * @param int $modifiedfrom timestamp
+     * @return moodle_recordset
+     */
+    public function get_recordset_by_timestamp($modifiedfrom = 0) {
+        global $DB;
+
+        $sql = "SELECT dr.*, d.course
+                  FROM {data_records} dr
+                  JOIN {data} d ON d.id = dr.dataid
+                 WHERE dr.timemodified >= :timemodified";
+        return $DB->get_recordset_sql($sql, array('timemodified' => $modifiedfrom));
+    }
+
+    /**
+     * Returns the documents associated with this glossary entry id.
+     *
+     * @param stdClass $entry glossary entry.
+     * @param array    $options
+     * @return \core_search\document
+     */
+    public function get_document($entry, $options = array()) {
+        global $DB;
+
+        try {
+            $cm = $this->get_cm('data', $entry->dataid, $entry->course);
+            $context = \context_module::instance($cm->id);
+        } catch (\dml_missing_record_exception $ex) {
+            // Notify it as we run here as admin, we should see everything.
+            debugging('Error retrieving mod_data ' . $entry->id . ' document, not all required data is available: ' .
+                $ex->getMessage(), DEBUG_DEVELOPER);
+            return false;
+        } catch (\dml_exception $ex) {
+            // Notify it as we run here as admin, we should see everything.
+            debugging('Error retrieving mod_data' . $entry->id . ' document: ' . $ex->getMessage(), DEBUG_DEVELOPER);
+            return false;
+        }
+
+        // Prepare associative array with data from DB.
+        $doc = \core_search\document_factory::instance($entry->id, $this->componentname, $this->areaname);
+        $doc->set('contextid', $context->id);
+        $doc->set('courseid', $entry->course);
+        $doc->set('userid', $entry->userid);
+        $doc->set('owneruserid', \core_search\manager::NO_OWNER_ID);
+        $doc->set('modified', $entry->timemodified);
+
+        $indexfields = $this->get_fields_for_entries($entry);
+
+        if (count($indexfields) < 2) {
+            return false;
+        }
+
+        $doc->set('title', $indexfields[0]);
+        $doc->set('content', $indexfields[1]);
+
+        if (isset($indexfields[2])) {
+            $doc->set('description1', $indexfields[2]);
+        }
+
+        if (isset($indexfields[3])) {
+            $doc->set('description2', $indexfields[3]);
+        }
+
+        return $doc;
+    }
+
+    /**
+     * Whether the user can access the document or not.
+     *
+     * @throws \dml_missing_record_exception
+     * @throws \dml_exception
+     * @param int $id Glossary entry id
+     * @return bool
+     */
+    public function check_access($id) {
+        global $DB, $USER;
+
+        if (isguestuser()) {
+            return \core_search\manager::ACCESS_DENIED;
+        }
+
+        $now = time();
+
+        $sql = "SELECT dr.*, d.*
+                  FROM {data_records} dr
+                  JOIN {data} d ON d.id = dr.dataid
+                 WHERE dr.id = ?";
+
+        $entry = $DB->get_record_sql($sql, array( $id ), IGNORE_MISSING);
+
+        if (!$entry) {
+            return \core_search\manager::ACCESS_DELETED;
+        }
+
+        if (($entry->timeviewfrom && $now < $entry->timeviewfrom) || ($entry->timeviewto && $now > $entry->timeviewto)) {
+            return \core_search\manager::ACCESS_DENIED;
+        }
+
+        $cm = $this->get_cm('data', $entry->dataid, $entry->course);
+        $context = \context_module::instance($cm->id);
+
+        $canmanageentries = has_capability('mod/data:manageentries', $context);
+
+        if (!has_capability('mod/data:viewentry', $context)) {
+            return \core_search\manager::ACCESS_DENIED;
+        }
+
+        $numberofentriesindb = $DB->count_records('data_records', array('dataid' => $entry->dataid));
+        $requiredentriestoview = $entry->requiredentriestoview;
+
+        if ($requiredentriestoview && ($requiredentriestoview > $numberofentriesindb) &&
+                ($USER->id != $entry->userid) && !$canmanageentries) {
+            return \core_search\manager::ACCESS_DENIED;
+        }
+
+        if ($entry->approval && !$entry->approved && ($entry->userid != $USER->id) && !$canmanageentries) {
+            return \core_search\manager::ACCESS_DENIED;
+        }
+
+        $currentgroup = groups_get_activity_group($cm, true);
+        $groupmode = groups_get_activity_groupmode($cm);
+
+        if (($groupmode == 1) && ($entry->groupid != $currentgroup) && !$canmanageentries) {
+            return \core_search\manager::ACCESS_DENIED;
+        }
+
+        return \core_search\manager::ACCESS_GRANTED;
+    }
+
+    /**
+     * Link to database entry.
+     *
+     * @param \core_search\document $doc
+     * @return \moodle_url
+     */
+    public function get_doc_url(\core_search\document $doc) {
+        $entry = $this->get_entry($doc->get('itemid'));
+        return new \moodle_url('/mod/data/view.php', array( 'd' => $entry->dataid, 'rid' => $entry->id ));
+    }
+
+    /**
+     * Link to the database activity.
+     *
+     * @param \core_search\document $doc
+     * @return \moodle_url
+     */
+    public function get_context_url(\core_search\document $doc) {
+        $entry = $this->get_entry($doc->get('itemid'));
+        return new \moodle_url('/mod/data/view.php', array('d' => $entry->dataid));
+    }
+
+    /**
+     * Returns true if this area uses file indexing.
+     *
+     * @return bool
+     */
+    public function uses_file_indexing() {
+        return true;
+    }
+
+    /**
+     * Add the database entries attachments.
+     *
+     * @param \core_search\document $doc
+     * @return void
+     */
+    public function attach_files($doc) {
+        global $DB;
+
+        $entryid = $doc->get('itemid');
+
+        try {
+            $entry = $this->get_entry($entryid);
+        } catch (\dml_missing_record_exception $e) {
+            debugging('Could not get record to attach files to '.$doc->get('id'), DEBUG_DEVELOPER);
+            return;
+        }
+
+        $cm = $this->get_cm('data', $entry->dataid, $doc->get('courseid'));
+        $context = \context_module::instance($cm->id);
+
+        // Get the files and attach them.
+        $fs = get_file_storage();
+        $files = $fs->get_area_files($context->id, 'mod_data', 'content', $entryid, 'filename', false);
+        foreach ($files as $file) {
+            $doc->add_stored_file($file);
+        }
+    }
+
+    /**
+     * Get database entry data
+     *
+     * @throws \dml_exception
+     * @param int $entryid
+     * @return stdClass
+     */
+    protected function get_entry($entryid) {
+        global $DB;
+
+        if (empty($this->entriesdata[$entryid])) {
+            $this->entriesdata[$entryid] = $DB->get_record('data_records', array( 'id' => $entryid ), '*', MUST_EXIST);
+        }
+
+        return $this->entriesdata[$entryid];
+    }
+
+    /**
+     * get_fields_for_entries
+     *
+     * @param StdClass $entry
+     * @return array
+     */
+    protected function get_fields_for_entries($entry) {
+        global $DB;
+
+        $indexfields = array();
+        $validfieldtypes = array('text', 'textarea', 'menu', 'radiobutton', 'checkbox', 'multimenu', 'url');
+
+        $sql = "SELECT dc.id, dc.content, df.name AS fldname,
+                       df.type AS fieldtype, df.required
+                  FROM {data_content} dc, {data_fields} df
+                 WHERE dc.fieldid = df.id
+                       AND dc.recordid = :recordid";
+
+        $contents = $DB->get_records_sql($sql, array('recordid' => $entry->id));
+        $filteredcontents = array();
+
+        $template = $DB->get_record_sql('SELECT addtemplate FROM {data} WHERE id = ?', array($entry->dataid));
+        $template = $template->addtemplate;
+
+        // Filtering out the data_content records having invalid fieldtypes.
+        foreach ($contents as $content) {
+            if (in_array($content->fieldtype, $validfieldtypes)) {
+                $filteredcontents[] = $content;
+            }
+        }
+
+        foreach ($filteredcontents as $content) {
+            $classname = 'data_field_' . trim($content->fieldtype);
+            $content->priority = $classname::get_priority();
+            $content->addtemplateposition = strpos($template, '[['.$content->fldname.']]');
+        }
+
+        $orderqueue = new \SPLPriorityQueue();
+
+        // Filtering out contents which belong to fields that aren't present in the addtemplate of the database activity instance.
+        foreach ($filteredcontents as $content) {
+
+            if ($content->addtemplateposition >= 0) {
+                $orderqueue->insert($content, $content->addtemplateposition);
+            }
+        }
+
+        $filteredcontents = array();
+
+        while ($orderqueue->valid()) {
+            $filteredcontents[] = $orderqueue->extract();
+        }
+
+        // SPLPriorityQueue sorts according to descending order of the priority (here, addtemplateposition).
+        $filteredcontents = array_reverse($filteredcontents);
+
+        // Using a CUSTOM SPLPriorityQueure instance to sort out the filtered contents according to these rules :
+        // 1. Priorities in $fieldtypepriorities
+        // 2. Compulsory fieldtypes are to be given the top priority.
+        $contentqueue = new sortedcontentqueue($filteredcontents);
+
+        foreach ($filteredcontents as $key => $content) {
+            $contentqueue->insert($content, $key);
+        }
+
+        while ($contentqueue->valid()) {
+
+            $content = $contentqueue->extract();
+            $classname = 'data_field_' . trim($content->fieldtype);
+
+            $indexfields[] = $classname::get_content_value($content->content);
+        }
+
+        return $indexfields;
+    }
+
+}
\ No newline at end of file
diff --git a/mod/data/classes/search/sortedcontentqueue.php b/mod/data/classes/search/sortedcontentqueue.php
new file mode 100644 (file)
index 0000000..12a555b
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Priority Queue class to sort out db entry contents.
+ *
+ * @package    mod_data
+ * @copyright  2016 Devang Gaur
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_data\search;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Priority Queue class to sort out db entry contents.
+ *
+ * @package    mod_data
+ * @copyright  2016 Devang Gaur
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class sortedcontentqueue extends \SPLPriorityQueue {
+
+    /**
+     * @var array All contents that will be sorted.
+     */
+    private $contents;
+
+    /**
+     * contructor
+     *
+     * @param array $contents
+     * @return void
+     */
+    public function __construct($contents) {
+        $this->contents = $contents;
+    }
+
+    /**
+     * comparator function overriden for sorting the records
+     * ...as per 'required' and 'priotirity' field values
+     *
+     * @param int $key1
+     * @param int $key2
+     * @return bool
+     */
+    public function compare($key1 , $key2) {
+        $record1 = $this->contents[$key1];
+        $record2 = $this->contents[$key2];
+
+        // If a content's fieldtype is compulsory in the database than it would have priority than any other noncompulsory content.
+        if ( ($record1->required && $record2->required) || (!$record1->required && !$record2->required)) {
+            if ($record1->priority === $record2->priority) {
+                return $key1 < $key2 ? 1 : -1;
+            }
+
+            return $record1->priority < $record2->priority ? -1 : 1;
+
+        } else if ($record1->required && !$record2->required) {
+            return 1;
+        } else {
+            return -1;
+        }
+
+    }
+}
\ No newline at end of file
index c1b60a8..c8675d9 100644 (file)
 class data_field_checkbox extends data_field_base {
 
     var $type = 'checkbox';
+    /**
+     * priority for globalsearch indexing
+     *
+     * @var int
+     */
+    protected static $priority = self::LOW_PRIORITY;
 
     function display_add_field($recordid = 0, $formdata = null) {
         global $CFG, $DB, $OUTPUT;
@@ -242,4 +248,19 @@ class data_field_checkbox extends data_field_base {
         return $found;
     }
 
+    /**
+     * Returns the presentable string value for a field content.
+     * @param string $value
+     * @return string
+     */
+    public static function get_content_value($value) {
+        $arr = explode('##', $value);
+
+        $content = '';
+        foreach ($arr as $a) {
+            $content .= $a.' ';
+        }
+
+        return trim($content);
+    }
 }
index 53e2d4f..1b62356 100644 (file)
 class data_field_menu extends data_field_base {
 
     var $type = 'menu';
+    /**
+     * priority for globalsearch indexing
+     *
+     * @var int
+     */
+    protected static $priority = self::HIGH_PRIORITY;
 
     function display_add_field($recordid = 0, $formdata = null) {
         global $DB, $OUTPUT;
index 34beb47..fb7e290 100644 (file)
 class data_field_multimenu extends data_field_base {
 
     var $type = 'multimenu';
+    /**
+     * priority for globalsearch indexing
+     *
+     * @var int
+     * */
+    protected static $priority = self::LOW_PRIORITY;
 
     function display_add_field($recordid = 0, $formdata = null) {
         global $DB, $OUTPUT;
@@ -267,4 +273,21 @@ class data_field_multimenu extends data_field_base {
         unset($value['xxx']);
         return !empty($value);
     }
+
+    /**
+     * Returns the presentable string value for a field content.
+     * @param string $value
+     * @return string
+     */
+    public static function get_content_value($value) {
+        $arr = explode('##', $value);
+
+        $content = '';
+        foreach ($arr as $a) {
+            $content .= $a.' ';
+        }
+
+        return trim($content);
+    }
+
 }
index 6dd1d3e..dbc5c1e 100644 (file)
 class data_field_radiobutton extends data_field_base {
 
     var $type = 'radiobutton';
+    /**
+     * priority for globalsearch indexing
+     *
+     * @var int
+     */
+    protected static $priority = self::HIGH_PRIORITY;
 
     function display_add_field($recordid = 0, $formdata = null) {
         global $CFG, $DB, $OUTPUT;
index 9489db7..dd72649 100644 (file)
 class data_field_text extends data_field_base {
 
     var $type = 'text';
+    /**
+     * priority for globalsearch indexing
+     *
+     * @var int
+     */
+    protected static $priority = self::MAX_PRIORITY;
 
     function display_search_field($value = '') {
         return '<label class="accesshide" for="f_' . $this->field->id . '">'. $this->field->name.'</label>' . '<input type="text" size="16" id="f_'.$this->field->id.'" name="f_'.$this->field->id.'" value="'.s($value).'" />';
index 659fed6..a6d6248 100644 (file)
@@ -27,6 +27,12 @@ require_once($CFG->dirroot.'/repository/lib.php');
 class data_field_textarea extends data_field_base {
 
     var $type = 'textarea';
+    /**
+     * priority for globalsearch indexing
+     *
+     * @var int
+     */
+    protected static $priority = self::LOW_PRIORITY;
 
     /**
      * Returns options for embedded files
@@ -275,4 +281,14 @@ class data_field_textarea extends data_field_base {
         }
         return false;
     }
+
+    /**
+     * Returns the presentable string value for a field content.
+     * @param string $value
+     * @return string
+     */
+    public static function get_content_value($value) {
+        return clean_param($value, PARAM_NOTAGS);
+    }
+
 }
index 5218911..6769c81 100644 (file)
 
 class data_field_url extends data_field_base {
     var $type = 'url';
+    /**
+     * priority for globalsearch indexing
+     *
+     * @var int
+     */
+    protected static $priority = self::MIN_PRIORITY;
 
     function display_add_field($recordid = 0, $formdata = null) {
         global $CFG, $DB, $OUTPUT, $PAGE;
index a8127e0..4b0e332 100644 (file)
@@ -324,6 +324,7 @@ $string['savesuccess'] = 'Saved successfully. Your preset will now be available
 $string['savetemplate'] = 'Save template';
 $string['search'] = 'Search';
 $string['search:activity'] = 'Database - activity information';
+$string['search:entry'] = 'Database - entries';
 $string['selectedrequired'] = 'All selected required';
 $string['showall'] = 'Show all entries';
 $string['single'] = 'View single';
index 6c03edf..5accbeb 100644 (file)
@@ -64,6 +64,18 @@ class data_field_base {     // Base class for Database Field Types (see field/*/
     var $cm;
     /** @var object activity context */
     var $context;
+    /** @var priority for globalsearch indexing */
+    protected static $priority = self::NO_PRIORITY;
+    /** priority value for invalid fields regarding indexing */
+    const NO_PRIORITY = 0;
+    /** priority value for minimum priority */
+    const MIN_PRIORITY = 1;
+    /** priority value for low priority */
+    const LOW_PRIORITY = 2;
+    /** priority value for high priority */
+    const HIGH_PRIORITY = 3;
+    /** priority value for maximum priority */
+    const MAX_PRIORITY = 4;
 
     /**
      * Constructor function
@@ -527,6 +539,24 @@ class data_field_base {     // Base class for Database Field Types (see field/*/
     function file_ok($relativepath) {
         return false;
     }
+
+    /**
+     * Returns the priority for being indexed by globalsearch
+     *
+     * @return int
+     */
+    public static function get_priority() {
+        return static::$priority;
+    }
+
+    /**
+     * Returns the presentable string value for a field content.
+     * @param string $value
+     * @return string
+     */
+    public static function get_content_value($value) {
+        return trim($value);
+    }
 }
 
 
index 86480c9..e511bbb 100644 (file)
@@ -133,8 +133,10 @@ class mod_data_generator extends testing_module_generator {
         }
 
         if (!isset($record['param1'])) {
-            if (in_array($record['type'], array('checkbox', 'menu', 'multimenu', 'radiobutton'))) {
-                $record['param1'] = implode("\n", array('one', 'two', 'three', 'four'));
+            if (in_array($record['type'], array('checkbox', 'radiobutton'))) {
+                $record['param1'] = implode("\n", array('opt1', 'opt2', 'opt3', 'opt4'));
+            } else if (in_array($record['type'], array('multimenu', 'menu'))) {
+                $record['param1'] = implode("\n", array('menu1', 'menu2', 'menu3', 'menu4'));
             } else if (($record['type'] === 'text') || ($record['type'] === 'url')) {
                 $record['param1'] = 1;
             } else {
@@ -185,6 +187,8 @@ class mod_data_generator extends testing_module_generator {
 
     /**
      * Creates a field for a mod_data instance.
+     * Keep in mind the default data field params created in create_field() function!
+     * ...if you haven't provided your own custom data field parameters there.
      * Currently, the field types in the ignoredfieldtypes array aren't supported.
      * The developers using the generator must adhere to the following format :
      *
@@ -203,12 +207,12 @@ class mod_data_generator extends testing_module_generator {
      * @param array $contents
      * @return data_field_{type}
      */
-    public function create_entry($data, array $contents) {
+    public function create_entry($data, array $contents, $groupid = 0) {
         global $DB;
 
         $this->databaserecordcount++;
 
-        $recordid = data_add_record($data);
+        $recordid = data_add_record($data, $groupid);
 
         $fields = $DB->get_records('data_fields', array('dataid' => $data->id));
 
@@ -254,11 +258,11 @@ class mod_data_generator extends testing_module_generator {
 
                 $contents[$fieldid] = $values;
 
-                foreach ($values as $fieldname => $value) {
-                    if (!$field->notemptyfield($value, $fieldname)) {
-                        $fieldhascontent = false;
-                    }
+                $fieldname = 'field_' . $fieldid;
+                if (!$field->notemptyfield($values[$fieldname], $fieldname)) {
+                    $fieldhascontent = false;
                 }
+
             } else if ($field->type === 'url') {
                 $values = array();
 
@@ -271,12 +275,11 @@ class mod_data_generator extends testing_module_generator {
                 }
 
                 $contents[$fieldid] = $values;
-
-                foreach ($values as $fieldname => $value) {
-                    if (!$field->notemptyfield($value, $fieldname)) {
-                        $fieldhascontent = false;
-                    }
+                $fieldname = 'field_' . $fieldid . '_0';
+                if (!$field->notemptyfield($values[$fieldname], $fieldname)) {
+                    $fieldhascontent = false;
                 }
+
             } else {
                 if ($field->notemptyfield($contents[$fieldid], 'field_' . $fieldid . '_0')) {
                     continue;
@@ -291,7 +294,7 @@ class mod_data_generator extends testing_module_generator {
         foreach ($contents as $fieldid => $content) {
             $field = data_get_field_from_id($fieldid, $data);
 
-            if (is_array($content)) {
+            if (is_array($content) and in_array($field->type, array('date', 'textarea', 'url'))) {
 
                 foreach ($content as $fieldname => $value) {
                     $field->update_content($recordid, $value, $fieldname);
index c554423..ebcfa33 100644 (file)
@@ -136,7 +136,12 @@ class mod_data_generator_testcase extends advanced_testcase {
         $this->setAdminUser();
         $this->assertEquals(0, $DB->count_records('data'));
 
+        $user1 = $this->getDataGenerator()->create_user();
         $course = $this->getDataGenerator()->create_course();
+        $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
+
+        $groupa = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'name' => 'groupA'));
+        $this->getDataGenerator()->create_group_member(array('userid' => $user1->id, 'groupid' => $groupa->id));
 
         /** @var mod_data_generator $generator */
         $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
@@ -166,6 +171,7 @@ class mod_data_generator_testcase extends advanced_testcase {
             $record = new StdClass();
             $record->name = $fieldname;
             $record->type = $fieldtype;
+            $record->required = 1;
 
             ${$fieldname} = $this->getDataGenerator()->get_plugin_generator('mod_data')->create_field($record, $data);
             $this->assertInstanceOf('data_field_' . $fieldtype, ${$fieldname});
@@ -177,12 +183,12 @@ class mod_data_generator_testcase extends advanced_testcase {
         $fields = $DB->get_records('data_fields', array('dataid' => $data->id), 'id');
 
         $contents = array();
-        $contents[] = array('one', 'two', 'three', 'four');
+        $contents[] = array('opt1', 'opt2', 'opt3', 'opt4');
         $contents[] = '01-01-2037'; // It should be lower than 2038, to avoid failing on 32-bit windows.
-        $contents[] = 'one';
-        $contents[] = array('one', 'two', 'three', 'four');
+        $contents[] = 'menu1';
+        $contents[] = array('menu1', 'menu2', 'menu3', 'menu4');
         $contents[] = '12345';
-        $contents[] = 'one';
+        $contents[] = 'opt1';
         $contents[] = 'text for testing';
         $contents[] = '<p>text area testing<br /></p>';
         $contents[] = array('example.url', 'sampleurl');
@@ -192,9 +198,36 @@ class mod_data_generator_testcase extends advanced_testcase {
             $fieldcontents[$fieldrecord->id] = $contents[$count++];
         }
 
-        $datarecordid = $this->getDataGenerator()->get_plugin_generator('mod_data')->create_entry($data, $fieldcontents);
+        $datarecordid = $this->getDataGenerator()->get_plugin_generator('mod_data')->create_entry($data, $fieldcontents,
+                                                                                                    $groupa->id);
 
         $this->assertEquals(1, $DB->count_records('data_records', array('dataid' => $data->id)));
         $this->assertEquals(count($contents), $DB->count_records('data_content', array('recordid' => $datarecordid)));
+
+        $entry = $DB->get_record('data_records', array('id' => $datarecordid));
+        $this->assertEquals($entry->groupid, $groupa->id);
+
+        $contents = $DB->get_records('data_content', array('recordid' => $datarecordid));
+
+        $contentstartid = 0;
+        $flag = 0;
+        foreach ($contents as $key => $content) {
+            if (!$flag++) {
+                $contentstartid = $key;
+            }
+            $this->assertFalse($content->content == null);
+        }
+
+        $this->assertEquals($contents[$contentstartid]->content, 'opt1##opt2##opt3##opt4');
+        $this->assertEquals($contents[++$contentstartid]->content, '2114380800');
+        $this->assertEquals($contents[++$contentstartid]->content, 'menu1');
+        $this->assertEquals($contents[++$contentstartid]->content, 'menu1##menu2##menu3##menu4');
+        $this->assertEquals($contents[++$contentstartid]->content, '12345');
+        $this->assertEquals($contents[++$contentstartid]->content, 'opt1');
+        $this->assertEquals($contents[++$contentstartid]->content, 'text for testing');
+        $this->assertEquals($contents[++$contentstartid]->content, '<p>text area testing<br /></p>');
+        $this->assertEquals($contents[$contentstartid]->content1, '1');
+        $this->assertEquals($contents[++$contentstartid]->content, 'http://example.url');
+        $this->assertEquals($contents[$contentstartid]->content1, 'sampleurl');
     }
-}
+}
\ No newline at end of file
index 1e54d95..ee6b073 100644 (file)
@@ -28,8 +28,10 @@ defined('MOODLE_INTERNAL') || die();
 
 global $CFG;
 require_once($CFG->dirroot . '/mod/data/lib.php');
+require_once($CFG->dirroot . '/lib/datalib.php');
 require_once($CFG->dirroot . '/lib/csvlib.class.php');
-
+require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
+require_once($CFG->dirroot . '/mod/data/tests/generator/lib.php');
 
 /**
  * Unit tests for {@see data_get_all_recordids()}.
@@ -41,7 +43,7 @@ require_once($CFG->dirroot . '/lib/csvlib.class.php');
  * @copyright  2012 Adrian Greeve
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class data_advanced_search_sql_test extends advanced_testcase {
+class mod_data_search_test extends advanced_testcase {
     /**
      * @var stdObject $recorddata An object that holds information from the table data.
      */
@@ -90,6 +92,11 @@ class data_advanced_search_sql_test extends advanced_testcase {
      */
     public $approvedatarecordcount = 89;
 
+    /**
+     * @var string Area id
+     */
+    protected $databaseentryareaid = null;
+
     /**
      * Set up function. In this instance we are setting up database
      * records to be used in the unit tests.
@@ -100,6 +107,43 @@ class data_advanced_search_sql_test extends advanced_testcase {
 
         $this->resetAfterTest(true);
 
+        set_config('enableglobalsearch', true);
+
+        $this->databaseentryareaid = \core_search\manager::generate_areaid('mod_data', 'entry');
+
+        // Set \core_search::instance to the mock_search_engine as we don't require the search engine to be working to test this.
+        $search = testable_core_search::instance();
+
+    }
+
+    /**
+     * Test 1: The function data_get_all_recordids.
+     *
+     * Test 2: This tests the data_get_advance_search_ids() function. The function takes a set
+     * of all the record IDs in the database and then with the search details ($this->recordsearcharray)
+     * returns a comma seperated string of record IDs that match the search criteria.
+     *
+     * Test 3: This function tests data_get_recordids(). This is the function that is nested in the last
+     * function (see data_get_advance_search_ids). This function takes a couple of
+     * extra parameters. $alias is the field alias used in the sql query and $commaid
+     * is a comma seperated string of record IDs.
+     *
+     * Test 3.1: This tests that if no recordids are provided (In a situation where a search is done on an empty database)
+     * That an empty array is returned.
+     *
+     * Test 4: data_get_advanced_search_sql provides an array which contains an sql string to be used for displaying records
+     * to the user when they use the advanced search criteria and the parameters that go with the sql statement. This test
+     * takes that information and does a search on the database, returning a record.
+     *
+     * Test 5: Returning to data_get_all_recordids(). Here we are ensuring that the total amount of record ids is reduced to
+     * match the group conditions that are provided. There are 25 entries which relate to group 2. They are removed
+     * from the total so we should only have 75 records total.
+     *
+     * Test 6: data_get_all_recordids() again. This time we are testing approved database records. We only want to
+     * display the records that have been approved. In this record set we have 89 approved records.
+     */
+    public function test_advanced_search_sql_section() {
+        global $DB;
 
         // we already have 2 users, we need 98 more - let's ignore the fact that guest can not post anywhere
         // We reset the user sequence here to ensure we get the expected numbers.
@@ -116,9 +160,9 @@ class data_advanced_search_sql_test extends advanced_testcase {
 
         // Set up data for the test database.
         $files = array(
-            'data_fields'  => __DIR__.'/fixtures/test_data_fields.csv',
-            'data_records' => __DIR__.'/fixtures/test_data_records.csv',
-            'data_content' => __DIR__.'/fixtures/test_data_content.csv',
+                'data_fields'  => __DIR__.'/fixtures/test_data_fields.csv',
+                'data_records' => __DIR__.'/fixtures/test_data_records.csv',
+                'data_content' => __DIR__.'/fixtures/test_data_content.csv',
         );
         $this->loadDataSet($this->createCsvDataSet($files));
         // Set dataid to the correct value now the data has been inserted by csv file.
@@ -127,10 +171,10 @@ class data_advanced_search_sql_test extends advanced_testcase {
 
         // Create the search array which contains our advanced search criteria.
         $fieldinfo = array('0' => new stdClass(),
-            '1' => new stdClass(),
-            '2' => new stdClass(),
-            '3' => new stdClass(),
-            '4' => new stdClass());
+                '1' => new stdClass(),
+                '2' => new stdClass(),
+                '3' => new stdClass(),
+                '4' => new stdClass());
         $fieldinfo['0']->id = 1;
         $fieldinfo['0']->data = '3.721,46.6126';
         $fieldinfo['1']->id = 2;
@@ -175,36 +219,6 @@ class data_advanced_search_sql_test extends advanced_testcase {
         $this->finalrecord[6]->picture = $user->picture;
         $this->finalrecord[6]->imagealt = $user->imagealt;
         $this->finalrecord[6]->email = $user->email;
-    }
-
-    /**
-     * Test 1: The function data_get_all_recordids.
-     *
-     * Test 2: This tests the data_get_advance_search_ids() function. The function takes a set
-     * of all the record IDs in the database and then with the search details ($this->recordsearcharray)
-     * returns a comma seperated string of record IDs that match the search criteria.
-     *
-     * Test 3: This function tests data_get_recordids(). This is the function that is nested in the last
-     * function (@see data_get_advance_search_ids). This function takes a couple of
-     * extra parameters. $alias is the field alias used in the sql query and $commaid
-     * is a comma seperated string of record IDs.
-     *
-     * Test 3.1: This tests that if no recordids are provided (In a situation where a search is done on an empty database)
-     * That an empty array is returned.
-     *
-     * Test 4: data_get_advanced_search_sql provides an array which contains an sql string to be used for displaying records
-     * to the user when they use the advanced search criteria and the parameters that go with the sql statement. This test
-     * takes that information and does a search on the database, returning a record.
-     *
-     * Test 5: Returning to data_get_all_recordids(). Here we are ensuring that the total amount of record ids is reduced to
-     * match the group conditions that are provided. There are 25 entries which relate to group 2. They are removed
-     * from the total so we should only have 75 records total.
-     *
-     * Test 6: data_get_all_recordids() again. This time we are testing approved database records. We only want to
-     * display the records that have been approved. In this record set we have 89 approved records.
-     */
-    function test_advanced_search_sql_section() {
-        global $DB;
 
         // Test 1
         $recordids = data_get_all_recordids($this->recorddata->id);
@@ -242,4 +256,744 @@ class data_advanced_search_sql_test extends advanced_testcase {
         $recordids = data_get_all_recordids($this->recorddata->id, $approvesql, $params);
         $this->assertEquals($this->approvedatarecordcount, count($recordids));
     }
-}
+
+    /**
+     * Indexing database entries contents.
+     *
+     * @return void
+     */
+    public function test_data_entries_indexing() {
+        global $DB;
+
+        // Returns the instance as long as the area is supported.
+        $searcharea = \core_search\manager::get_search_area($this->databaseentryareaid);
+        $this->assertInstanceOf('\mod_data\search\entry', $searcharea);
+
+        $user1 = self::getDataGenerator()->create_user();
+
+        $course1 = self::getDataGenerator()->create_course();
+
+        $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
+
+        $record = new stdClass();
+        $record->course = $course1->id;
+
+        $this->setUser($user1);
+
+        // Available for both student and teacher.
+        $data1 = $this->getDataGenerator()->create_module('data', $record);
+
+        // Excluding LatLong and Picture as we aren't indexing LatLong and Picture fields any way
+        // ...and they're complex and not of any use to consider for this test.
+        // Excluding File as we are indexing files seperately and its complex to implement.
+        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
+
+        $this->create_default_data_fields($fieldtypes, $data1);
+
+        $data1record1id = $this->create_default_data_record($data1);
+        // All records.
+        $recordset = $searcharea->get_recordset_by_timestamp(0);
+
+        $this->assertTrue($recordset->valid());
+
+        $nrecords = 0;
+        foreach ($recordset as $record) {
+            $this->assertInstanceOf('stdClass', $record);
+            $doc = $searcharea->get_document($record);
+            $this->assertInstanceOf('\core_search\document', $doc);
+            $nrecords++;
+        }
+
+        // If there would be an error/failure in the foreach above the recordset would be closed on shutdown.
+        $recordset->close();
+        $this->assertEquals(1, $nrecords);
+
+        // The +2 is to prevent race conditions.
+        $recordset = $searcharea->get_recordset_by_timestamp(time() + 2);
+
+        // No new records.
+        $this->assertFalse($recordset->valid());
+        $recordset->close();
+    }
+
+    /**
+     * Document contents.
+     *
+     * @return void
+     */
+    public function test_data_entries_document() {
+        global $DB;
+
+        // Returns the instance as long as the area is supported.
+        $searcharea = \core_search\manager::get_search_area($this->databaseentryareaid);
+        $this->assertInstanceOf('\mod_data\search\entry', $searcharea);
+
+        $user1 = self::getDataGenerator()->create_user();
+
+        $course = self::getDataGenerator()->create_course();
+
+        $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
+
+        $record = new stdClass();
+        $record->course = $course->id;
+
+        $this->setAdminUser();
+
+        // First Case.
+        $data1 = $this->getDataGenerator()->create_module('data', $record);
+
+        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
+
+        $this->create_default_data_fields($fieldtypes, $data1);
+
+        $data1record1id = $this->create_default_data_record($data1);
+
+        $data1entry1 = $this->get_entry_for_id($data1record1id);
+
+        $data1doc = $searcharea->get_document($data1entry1);
+
+        $this->assertEquals($data1doc->get('courseid'), $course->id);
+        $this->assertEquals($data1doc->get('title'), 'text for testing');
+        $this->assertEquals($data1doc->get('content'), 'menu1');
+        $this->assertEquals($data1doc->get('description1'), 'opt1');
+        $this->assertEquals($data1doc->get('description2'), 'opt1 opt2 opt3 opt4');
+
+        // Second Case.
+        $data2 = $this->getDataGenerator()->create_module('data', $record);
+
+        $fieldtypes = array(
+                array('checkbox', 1),
+                array('textarea', 0),
+                array('menu', 0),
+                array('number', 1),
+                array('url', 0),
+                array('text', 0)
+        );
+
+        $this->create_default_data_fields($fieldtypes, $data2);
+
+        $data2record1id = $this->create_default_data_record($data2);
+
+        $data2entry1 = $this->get_entry_for_id($data2record1id);
+
+        $data2doc = $searcharea->get_document($data2entry1);
+
+        $this->assertEquals($data2doc->get('courseid'), $course->id);
+        $this->assertEquals($data2doc->get('title'), 'opt1 opt2 opt3 opt4');
+        $this->assertEquals($data2doc->get('content'), 'text for testing');
+        $this->assertEquals($data2doc->get('description1'), 'menu1');
+        $this->assertEquals($data2doc->get('description2'), 'text area testing');
+
+        // Third Case.
+        $data3 = $this->getDataGenerator()->create_module('data', $record);
+
+        $fieldtypes = array( 'url' );
+
+        $this->create_default_data_fields($fieldtypes, $data3);
+
+        $data3record1id = $this->create_default_data_record($data3);
+
+        $data3entry1 = $this->get_entry_for_id($data3record1id);
+
+        $this->assertFalse($searcharea->get_document($data3entry1));
+
+        // Fourth Case.
+        $data4 = $this->getDataGenerator()->create_module('data', $record);
+
+        $fieldtypes = array( array('date', 1), array('text', 1));
+
+        $this->create_default_data_fields($fieldtypes, $data4);
+
+        $data4record1id = $this->create_default_data_record($data4);
+
+        $data4entry1 = $this->get_entry_for_id($data4record1id);
+
+        $this->assertFalse($searcharea->get_document($data4entry1));
+
+        // Fifth Case.
+        $data5 = $this->getDataGenerator()->create_module('data', $record);
+
+        $fieldtypes = array(
+                array('checkbox', 0),
+                array('number', 1),
+                array('text', 0),
+                array('date', 1),
+                array('textarea', 0),
+                array('url', 1));
+
+        $this->create_default_data_fields($fieldtypes, $data5);
+
+        $data5record1id = $this->create_default_data_record($data5);
+
+        $data5entry1 = $this->get_entry_for_id($data5record1id);
+
+        $data5doc = $searcharea->get_document($data5entry1);
+
+        $this->assertEquals($data5doc->get('courseid'), $course->id);
+        $this->assertEquals($data5doc->get('title'), 'http://example.url');
+        $this->assertEquals($data5doc->get('content'), 'text for testing');
+        $this->assertEquals($data5doc->get('description1'), 'opt1 opt2 opt3 opt4');
+        $this->assertEquals($data5doc->get('description2'), 'text area testing');
+
+        // Sixth Case.
+        $data6 = $this->getDataGenerator()->create_module('data', $record);
+
+        $fieldtypes = array( array('date', 1), array('number', 1));
+
+        $this->create_default_data_fields($fieldtypes, $data6);
+
+        $data6record1id = $this->create_default_data_record($data6);
+
+        $data6entry1 = $this->get_entry_for_id($data6record1id);
+
+        $data6doc = $searcharea->get_document($data6entry1);
+
+        $this->assertFalse($data6doc);
+
+        // Seventh Case.
+        $data7 = $this->getDataGenerator()->create_module('data', $record);
+
+        $fieldtypes = array( array('date', 1), array('number', 1),
+                array('text', 0), array('textarea', 0));
+
+        $this->create_default_data_fields($fieldtypes, $data7);
+
+        $data7record1id = $this->create_default_data_record($data7);
+
+        $data7entry1 = $this->get_entry_for_id($data7record1id);
+
+        $data7doc = $searcharea->get_document($data7entry1);
+
+        $this->assertEquals($data7doc->get('courseid'), $course->id);
+        $this->assertEquals($data7doc->get('title'), 'text for testing');
+        $this->assertEquals($data7doc->get('content'), 'text area testing');
+
+        // Eight Case.
+        $data8 = $this->getDataGenerator()->create_module('data', $record);
+
+        $fieldtypes = array('url', 'url', 'url', 'text');
+
+        $this->create_default_data_fields($fieldtypes, $data8);
+
+        $data8record1id = $this->create_default_data_record($data8);
+
+        $data8entry1 = $this->get_entry_for_id($data8record1id);
+
+        $data8doc = $searcharea->get_document($data8entry1);
+
+        $this->assertEquals($data8doc->get('courseid'), $course->id);
+        $this->assertEquals($data8doc->get('title'), 'text for testing');
+        $this->assertEquals($data8doc->get('content'), 'http://example.url');
+        $this->assertEquals($data8doc->get('description1'), 'http://example.url');
+        $this->assertEquals($data8doc->get('description2'), 'http://example.url');
+
+        // Ninth Case.
+        $data9 = $this->getDataGenerator()->create_module('data', $record);
+
+        $fieldtypes = array('radiobutton', 'menu', 'multimenu');
+
+        $this->create_default_data_fields($fieldtypes, $data9);
+
+        $data9record1id = $this->create_default_data_record($data9);
+
+        $data9entry1 = $this->get_entry_for_id($data9record1id);
+
+        $data9doc = $searcharea->get_document($data9entry1);
+
+        $this->assertEquals($data9doc->get('courseid'), $course->id);
+        $this->assertEquals($data9doc->get('title'), 'opt1');
+        $this->assertEquals($data9doc->get('content'), 'menu1');
+        $this->assertEquals($data9doc->get('description1'), 'menu1 menu2 menu3 menu4');
+
+        // Tenth Case.
+        $data10 = $this->getDataGenerator()->create_module('data', $record);
+
+        $fieldtypes = array('checkbox', 'textarea', 'multimenu');
+
+        $this->create_default_data_fields($fieldtypes, $data10);
+
+        $data10record1id = $this->create_default_data_record($data10);
+
+        $data10entry1 = $this->get_entry_for_id($data10record1id);
+
+        $data10doc = $searcharea->get_document($data10entry1);
+
+        $this->assertEquals($data10doc->get('courseid'), $course->id);
+        $this->assertEquals($data10doc->get('title'), 'opt1 opt2 opt3 opt4');
+        $this->assertEquals($data10doc->get('content'), 'text area testing');
+        $this->assertEquals($data10doc->get('description1'), 'menu1 menu2 menu3 menu4');
+
+    }
+
+    /**
+     * Document accesses.
+     *
+     * @return void
+     */
+    public function test_data_entries_access() {
+        global $DB;
+
+        // Returns the instance as long as the area is supported.
+        $searcharea = \core_search\manager::get_search_area($this->databaseentryareaid);
+        $this->assertInstanceOf('\mod_data\search\entry', $searcharea);
+
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+        $user3 = self::getDataGenerator()->create_user();
+        $userteacher1 = self::getDataGenerator()->create_user();
+
+        $course1 = self::getDataGenerator()->create_course();
+        $course2 = self::getDataGenerator()->create_course();
+
+        $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
+        $this->getDataGenerator()->enrol_user($user2->id, $course1->id, 'student');
+        $this->getDataGenerator()->enrol_user($userteacher1->id, $course1->id, 'teacher');
+
+        $this->getDataGenerator()->enrol_user($user3->id, $course2->id, 'student');
+
+        $record = new stdClass();
+        $record->course = $course1->id;
+
+        $this->setUser($userteacher1);
+
+        $data1 = $this->getDataGenerator()->create_module('data', $record);
+
+        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
+
+        $this->create_default_data_fields($fieldtypes, $data1);
+
+        $this->setUser($user1);
+        $data1record1id = $this->create_default_data_record($data1);
+
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data1record1id));
+        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access(-1));
+
+        $this->setUser($user2);
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data1record1id));
+
+        $this->setUser($user3);
+        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data1record1id));
+
+        $this->setUser($userteacher1);
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data1record1id));
+
+        $this->setAdminUser();
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data1record1id));
+
+        $this->setGuestUser();
+        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data1record1id));
+
+        // Case with groups.
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+        $user3 = self::getDataGenerator()->create_user();
+        $userteacher1 = self::getDataGenerator()->create_user();
+
+        $course = self::getDataGenerator()->create_course(array('groupmode' => 1, 'groupmodeforce' => 1));
+
+        $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
+        $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
+        $this->getDataGenerator()->enrol_user($userteacher1->id, $course->id, 'teacher');
+        $this->getDataGenerator()->enrol_user($user3->id, $course->id, 'student');
+
+        $groupa = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'name' => 'groupA'));
+        $groupb = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'name' => 'groupB'));
+
+        $this->getDataGenerator()->create_group_member(array('userid' => $user1->id, 'groupid' => $groupa->id));
+        $this->getDataGenerator()->create_group_member(array('userid' => $user2->id, 'groupid' => $groupa->id));
+        $this->getDataGenerator()->create_group_member(array('userid' => $userteacher1->id, 'groupid' => $groupa->id));
+
+        $this->getDataGenerator()->create_group_member(array('userid' => $user3->id, 'groupid' => $groupb->id));
+
+        $record = new stdClass();
+        $record->course = $course->id;
+
+        $this->setUser($userteacher1);
+
+        $data2 = $this->getDataGenerator()->create_module('data', $record);
+
+        $cm = get_coursemodule_from_instance('data', $data2->id, $course->id);
+        $cm->groupmode = '1';
+        $cm->effectivegroupmode = '1';
+
+        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
+
+        $this->create_default_data_fields($fieldtypes, $data2);
+
+        $this->setUser($user1);
+
+        $data2record1id = $this->create_default_data_record($data2, $groupa->id);
+
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data2record1id));
+        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access(-1));
+
+        $this->setUser($user2);
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data2record1id));
+
+        $this->setUser($user3);
+        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data2record1id));
+
+        $this->setUser($userteacher1);
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data2record1id));
+
+        $this->setAdminUser();
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data2record1id));
+
+        $this->setGuestUser();
+        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data2record1id));
+
+        // Case with approval.
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+        $userteacher1 = self::getDataGenerator()->create_user();
+
+        $course = self::getDataGenerator()->create_course();
+
+        $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
+        $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
+        $this->getDataGenerator()->enrol_user($userteacher1->id, $course->id, 'teacher');
+
+        $record = new stdClass();
+        $record->course = $course->id;
+
+        $this->setUser($userteacher1);
+
+        $data3 = $this->getDataGenerator()->create_module('data', $record);
+
+        $DB->update_record('data', array('id' => $data3->id, 'approval' => 1));
+
+        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
+
+        $this->create_default_data_fields($fieldtypes, $data3);
+
+        $this->setUser($user1);
+
+        $data3record1id = $this->create_default_data_record($data3);
+
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
+        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access(-1));
+
+        $this->setUser($user2);
+        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data3record1id));
+
+        $this->setUser($userteacher1);
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
+
+        $this->setAdminUser();
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
+
+        $this->setGuestUser();
+        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data3record1id));
+
+        $DB->update_record('data_records', array('id' => $data3record1id, 'approved' => 1));
+
+        $this->setUser($user1);
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
+        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access(-1));
+
+        $this->setUser($user2);
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
+
+        $this->setUser($userteacher1);
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
+
+        $this->setAdminUser();
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
+
+        $this->setGuestUser();
+        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data3record1id));
+
+        // Case with requiredentriestoview.
+        $this->setAdminUser();
+
+        $record->requiredentriestoview = 2;
+
+        $data4 = $this->getDataGenerator()->create_module('data', $record);
+        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
+
+        $this->create_default_data_fields($fieldtypes, $data4);
+
+        $data4record1id = $this->create_default_data_record($data4);
+
+        $this->setUser($user1);
+        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data4record1id));
+
+        $data4record2id = $this->create_default_data_record($data4);
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data4record1id));
+        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data4record2id));
+    }
+
+    /**
+     * Test for file contents.
+     *
+     * @return void
+     */
+    public function test_attach_files() {
+        global $DB, $USER;
+
+        $fs = get_file_storage();
+
+        // Returns the instance as long as the area is supported.
+        $searcharea = \core_search\manager::get_search_area($this->databaseentryareaid);
+        $this->assertInstanceOf('\mod_data\search\entry', $searcharea);
+
+        $user1 = self::getDataGenerator()->create_user();
+
+        $course = self::getDataGenerator()->create_course();
+
+        $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
+
+        $record = new stdClass();
+        $record->course = $course->id;
+
+        $this->setAdminUser();
+
+        // Creating database activity instance.
+        $data1 = $this->getDataGenerator()->create_module('data', $record);
+
+        // Creating file field.
+        $record = new stdClass;
+        $record->type = 'file';
+        $record->dataid = $data1->id;
+        $record->required = 0;
+        $record->name = 'FileFld';
+        $record->description = 'Just another file field';
+        $record->param3 = 0;
+        $record->param1 = '';
+        $record->param2 = '';
+
+        $data1filefieldid = $DB->insert_record('data_fields', $record);
+
+        // Creating text field.
+        $record = new stdClass;
+        $record->type = 'text';
+        $record->dataid = $data1->id;
+        $record->required = 0;
+        $record->name = 'TextFld';
+        $record->description = 'Just another text field';
+        $record->param3 = 0;
+        $record->param1 = '';
+        $record->param2 = '';
+
+        $data1textfieldid = $DB->insert_record('data_fields', $record);
+
+        // Creating textarea field.
+        $record = new stdClass;
+        $record->type = 'textarea';
+        $record->dataid = $data1->id;
+        $record->required = 0;
+        $record->name = 'TextAreaFld';
+        $record->description = 'Just another textarea field';
+        $record->param1 = '';
+        $record->param2 = 60;
+        $record->param3 = 35;
+        $record->param3 = 1;
+        $record->param3 = 0;
+
+        $data1textareafieldid = $DB->insert_record('data_fields', $record);
+
+        // Creating 1st entry.
+        $record = new stdClass;
+        $record->userid = $USER->id;
+        $record->dataid = $data1->id;
+        $record->groupid = 0;
+
+        $data1record1id = $DB->insert_record('data_records', $record);
+
+        $filerecord = array(
+                'contextid' => context_module::instance($data1->cmid)->id,
+                'component' => 'mod_data',
+                'filearea'  => 'content',
+                'itemid'    => $data1record1id,
+                'filepath'  => '/',
+                'filename'  => 'myfile1.txt'
+        );
+
+        $data1record1file = $fs->create_file_from_string($filerecord, 'Some contents 1');
+
+        $record = new stdClass;
+        $record->fieldid = $data1filefieldid;
+        $record->recordid = $data1record1id;
+        $record->content = 'myfile1.txt';
+        $DB->insert_record('data_content', $record);
+
+        $record = new stdClass;
+        $record->fieldid = $data1textfieldid;
+        $record->recordid = $data1record1id;
+        $record->content = 'sample text';
+        $DB->insert_record('data_content', $record);
+
+        $record = new stdClass;
+        $record->fieldid = $data1textareafieldid;
+        $record->recordid = $data1record1id;
+        $record->content = '<br>sample text<p /><br/>';
+        $record->content1 = 1;
+        $DB->insert_record('data_content', $record);
+
+        // Creating 2nd entry.
+        $record = new stdClass;
+        $record->userid = $USER->id;
+        $record->dataid = $data1->id;
+        $record->groupid = 0;
+        $data1record2id = $DB->insert_record('data_records', $record);
+
+        $filerecord['itemid'] = $data1record2id;
+        $filerecord['filename'] = 'myfile2.txt';
+        $data1record2file = $fs->create_file_from_string($filerecord, 'Some contents 2');
+
+        $record = new stdClass;
+        $record->fieldid = $data1filefieldid;
+        $record->recordid = $data1record2id;
+        $record->content = 'myfile2.txt';
+        $DB->insert_record('data_content', $record);
+
+        $record = new stdClass;
+        $record->fieldid = $data1textfieldid;
+        $record->recordid = $data1record2id;
+        $record->content = 'sample text';
+        $DB->insert_record('data_content', $record);
+
+        $record = new stdClass;
+        $record->fieldid = $data1textareafieldid;
+        $record->recordid = $data1record2id;
+        $record->content = '<br>sample text<p /><br/>';
+        $record->content1 = 1;
+        $DB->insert_record('data_content', $record);
+
+        // Now get all the posts and see if they have the right files attached.
+        $searcharea = \core_search\manager::get_search_area($this->databaseentryareaid);
+        $recordset = $searcharea->get_recordset_by_timestamp(0);
+        $nrecords = 0;
+        foreach ($recordset as $record) {
+            $doc = $searcharea->get_document($record);
+            $searcharea->attach_files($doc);
+            $files = $doc->get_files();
+            // Now check that each doc has the right files on it.
+            switch ($doc->get('itemid')) {
+                case ($data1record1id):
+                    $this->assertCount(1, $files);
+                    $this->assertEquals($data1record1file->get_id(), $files[$data1record1file->get_id()]->get_id());
+                    break;
+                case ($data1record2id):
+                    $this->assertCount(1, $files);
+                    $this->assertEquals($data1record2file->get_id(), $files[$data1record2file->get_id()]->get_id());
+                    break;
+                default:
+                    $this->fail('Unexpected entry returned');
+                    break;
+            }
+            $nrecords++;
+        }
+        $recordset->close();
+        $this->assertEquals(2, $nrecords);
+    }
+
+    /**
+     * Creates default fields for a database instance
+     *
+     * @param array $fieldtypes
+     * @param mod_data $data
+     * @return void
+     */
+    protected function create_default_data_fields($fieldtypes = array(), $data) {
+        $count = 1;
+
+        // Creating test Fields with default parameter values.
+        foreach ($fieldtypes as $fieldtype) {
+
+            // Creating variables dynamically.
+            $fieldname = 'field-'.$count;
+            $record = new stdClass();
+            $record->name = $fieldname;
+
+            if (is_array($fieldtype)) {
+                $record->type = $fieldtype[0];
+                $record->required = $fieldtype[1];
+            } else {
+                $record->type = $fieldtype;
+                $record->required = 0;
+            }
+
+            ${$fieldname} = $this->getDataGenerator()->get_plugin_generator('mod_data')->create_field($record, $data);
+            $count++;
+        }
+    }
+
+    /**
+     * Creates default database entry content values for default field param values
+     *
+     * @param mod_data $data
+     * @param int $groupid
+     * @return int
+     */
+    protected function create_default_data_record($data, $groupid = 0) {
+        global $DB;
+
+        $fields = $DB->get_records('data_fields', array('dataid' => $data->id));
+
+        $fieldcontents = array();
+        foreach ($fields as $fieldrecord) {
+            switch ($fieldrecord->type) {
+                case 'checkbox':
+                    $fieldcontents[$fieldrecord->id] = array('opt1', 'opt2', 'opt3', 'opt4');
+                    break;
+
+                case 'multimenu':
+                    $fieldcontents[$fieldrecord->id] = array('menu1', 'menu2', 'menu3', 'menu4');
+                    break;
+
+                case 'date':
+                    $fieldcontents[$fieldrecord->id] = '27-07-2016';
+                    break;
+
+                case 'menu':
+                    $fieldcontents[$fieldrecord->id] = 'menu1';
+                    break;
+
+                case 'radiobutton':
+                    $fieldcontents[$fieldrecord->id] = 'opt1';
+                    break;
+
+                case 'number':
+                    $fieldcontents[$fieldrecord->id] = '12345';
+                    break;
+
+                case 'text':
+                    $fieldcontents[$fieldrecord->id] = 'text for testing';
+                    break;
+
+                case 'textarea':
+                    $fieldcontents[$fieldrecord->id] = '<p>text area testing<br /></p>';
+                    break;
+
+                case 'url':
+                    $fieldcontents[$fieldrecord->id] = array('example.url', 'sampleurl');
+                    break;
+
+                default:
+                    $this->fail('Unexpected field type');
+                    break;
+            }
+
+        }
+
+        return $this->getDataGenerator()->get_plugin_generator('mod_data')->create_entry($data, $fieldcontents, $groupid);
+    }
+
+    /**
+     * Creates default database entry content values for default field param values
+     *
+     * @param int $recordid
+     * @return stdClass
+     */
+    protected function get_entry_for_id($recordid ) {
+        global $DB;
+
+        $sql = "SELECT dr.*, d.course
+                  FROM {data_records} dr
+                  JOIN {data} d ON d.id = dr.dataid
+                 WHERE dr.id = :drid";
+        return $DB->get_record_sql($sql, array('drid' => $recordid));
+    }
+
+}
\ No newline at end of file