Merge branch 'MDL-42951-master' of git://github.com/FMCorz/moodle
authorSam Hemelryk <sam@moodle.com>
Sun, 1 Dec 2013 21:52:11 +0000 (10:52 +1300)
committerSam Hemelryk <sam@moodle.com>
Sun, 1 Dec 2013 21:52:11 +0000 (10:52 +1300)
19 files changed:
admin/tool/behat/version.php
composer.json
install/lang/lt_uni/admin.php
install/lang/pt_br/admin.php
install/lang/tr/install.php
lang/en/message.php
lib/behat/classes/behat_config_manager.php
lib/messagelib.php
lib/phpunit/classes/util.php
lib/testing/classes/util.php
lib/tests/messagelib_test.php
message/defaultoutputs.php
message/module.js
message/renderer.php
mod/quiz/report/statistics/report.php
mod/quiz/report/statistics/tests/stats_from_steps_walkthrough_test.php
question/classes/statistics/questions/calculator.php
question/classes/statistics/responses/analyser.php
version.php

index b750aa7..12b96cd 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2013110500;
+$plugin->version   = 2013110501;
 $plugin->requires  = 2013110500; // Requires Moodle 2.5.
 $plugin->component = 'tool_behat';
index 0699884..a0d5ea3 100644 (file)
@@ -8,6 +8,6 @@
     "require-dev": {
         "phpunit/phpunit": "3.7.*",
         "phpunit/dbUnit": "1.2.*",
-        "moodlehq/behat-extension": "1.26.2"
+        "moodlehq/behat-extension": "1.26.3"
     }
 }
index 4b8efef..8326f42 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
+$string['clianswerno'] = 'n';
+$string['cliansweryes'] = 't';
+$string['cliincorrectvalueerror'] = 'Klaida, klaidinga "{$a->option}" reikšmė "{$a->value}"';
+$string['cliincorrectvalueretry'] = 'Klaidinga reikšmė, bandykite dar kartą';
 $string['clitypevalue'] = 'tipo reikšmė';
 $string['clitypevaluedefault'] = 'tipo reikšmė, paspauskite „Enter“, jei norite naudoti numatytąją reikšmę ({$a})';
 $string['cliunknowoption'] = 'Neatpažintos parinktys: {$a} naudokite --žinyno parinktį.';
+$string['cliyesnoprompt'] = 'įveskite t (taip) arba n (ne)';
 $string['environmentrequireinstall'] = 'turi būti įdiegta ir įjungta';
 $string['environmentrequireversion'] = 'būtina naudoti versiją {$a->needed}, o jūs naudojate {$a->current}';
index 81d6d56..950fd59 100644 (file)
@@ -39,6 +39,6 @@ $string['clitypevaluedefault'] = 'digite o valor, pressione Enter para utilizar
 $string['cliunknowoption'] = 'Opções não reconhecidas:
   {$a}
 Por favor use a opção --help.';
-$string['cliyesnoprompt'] = 'digite y (sim) ou n (não)';
+$string['cliyesnoprompt'] = 'digite s (sim) ou n (não)';
 $string['environmentrequireinstall'] = 'deve ser instalado e habilitado';
 $string['environmentrequireversion'] = 'a versão {$a->needed} é necessária e você está usando a versão {$a->current}';
index b884f4b..c77770f 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 $string['admindirname'] = 'Yönetici Dizini';
-$string['availablelangs'] = 'Kullanılabilir diller';
+$string['availablelangs'] = 'Kullanılabilir dil paketleri';
 $string['chooselanguagehead'] = 'Bir dil seçin';
 $string['chooselanguagesub'] = 'Lütfen, SADECE kurulum için bir dil seçin. Site ve kullanıcı dillerini sonraki ekranda seçebilirsiniz.';
 $string['clialreadyconfigured'] = 'config.php halihazırda mevcut, lütfen eğer bu siteyi yüklemek istiyorsanız şu dizini kullanın: admin/cli/install_database.php';
 $string['clialreadyinstalled'] = 'Config.php zaten var. Sitenizi güncellemek istiyorsanız bu adresi kullanın: admin/cli/upgrade.php';
 $string['cliinstallheader'] = 'Moodle {$a} komut satırı kurulum programı';
-$string['databasehost'] = 'Veritabanı sunucusu:';
-$string['databasename'] = 'Veritabanı adı:';
+$string['databasehost'] = 'Veritabanı sunucusu';
+$string['databasename'] = 'Veritabanı adı';
 $string['databasetypehead'] = 'Veritabanı sürücünü seçin';
 $string['dataroot'] = 'Veri Dizini';
 $string['datarootpermission'] = 'Veri dizinleri izni';
@@ -46,7 +46,7 @@ $string['dbprefix'] = 'Tablo öneki';
 $string['dirroot'] = 'Moodle Dizini';
 $string['environmenthead'] = 'Ortam kontrol ediliyor...';
 $string['environmentsub2'] = 'Her Moodle dağıtımı, bazı PHP versiyon gereksinimi ve bir takım PHP uzantılarının yüklü olmalı zorunluluğuna sahiptir. Tüm ortam denetimi her yükleme ve güncellemeden önce yapılmalıdır. Eğer PHP \'nin yeni versiyonunu veya PHP uzantılarını nasıl yükleyeceğinizi bilmiyorsanız lütfen sunucu yöneticiniz ile iletişime geçiniz.';
-$string['errorsinenvironment'] = 'Ortamda hatalar var!';
+$string['errorsinenvironment'] = 'Ortam kontrolu başarısız oldu!';
 $string['installation'] = 'Kurulum';
 $string['langdownloaderror'] = 'Maalesef "{$a}" dil paketi kurulamadı. Kuruluma İngilizce olarak devam edilecek.';
 $string['memorylimithelp'] = '<p>Sunucunuz için PHP bellek limiti şu anda {$a} olarak ayarlanmış durumda.</p>
@@ -77,7 +77,13 @@ $string['pathserrcreatedataroot'] = 'Veri Klasörü ({$a->dataroot}) kurulum tar
 $string['pathshead'] = 'Yolları doğrulayın';
 $string['pathsrodataroot'] = 'Veri yolu yazılabilir değil.';
 $string['pathsroparentdataroot'] = 'Ana klasör ({$a->parent}) yazılabilir değil. Veri Klasörü ({$a->dataroot}) kurulum tarafından oluşturulamıyor.';
+$string['pathssubadmindir'] = 'Pek az web sunucusu /admin adresini kontrol paneline yada benzeri birşeye erişmek için kullanır. Ne yazık ki bu Moodle admin sayfalarının standart konumuyla bir karışıklık yaratır. Bu durumu düzeltmek için kurulumunuzdaki admin dizinini yeniden isimlendirip buraya yeni ismi yazınız. Örneğin: <em>moodleadmin</em>. Bu Moodle\'daki admin bağlantısını düzeltecektir.';
+$string['pathssubdataroot'] = 'Moodle\'ın yüklenen dosyaları kayıt etmesi için bir yere ihtiyacınız var. Bu dizin/klasör web sunucusunun kullanıcı hesabı tarafından okunabilir ve yazılabilir olmalıdır. Bu okuma, yazma izinlerini klasöre vermelisiniz. Fakat bu klasör aynı zamanda web üzerinden direk erişilebilir olmamalıdır. Yükleyici eğer klasör yok ise oluşturmayı deneyecektir.';
 $string['pathssubdirroot'] = 'Moodle kurulumu için tam klasör yolu. Sadece sembolik linkleri kullanmaya gereksinim duyuyorsanız değiştirin.';
+$string['pathssubwwwroot'] = 'Moodle\'a erişlecek tam web adresi. Moodle\'ın birden çok adres kullanması mümkün değildir.
+Eğer siteniz birden fazla adrese sahip ise bu adres harici diğerlerinin yönlendirme ayarlarını yapılandırın.
+Eğer siteniz Intranet ve İnternet üzerinden erişilebilirse burada genel bir adres kullanın ve DNS\'iniz ayarlayın. Bu şekilde Intranet kullanıcları da genel adresi kullanabilirler.
+Eğer adres doğru değilse lütfen kurulumu tekrar başlatmak için tarayıcınızdaki URL\'i değiştirin.';
 $string['pathsunsecuredataroot'] = 'Veri yolu güvenli değil';
 $string['pathswrongadmindir'] = 'Yönetici klasörü yok';
 $string['phpextension'] = '{$a} PHP eklentisi';
index a816753..3689531 100644 (file)
@@ -51,6 +51,7 @@ $string['discussion'] = 'Discussion';
 $string['emailmessages'] = 'Email messages when I am offline';
 $string['emailtagline'] = 'This is a copy of a message sent to you at "{$a->sitename}". Go to {$a->url} to reply.';
 $string['emptysearchstring'] = 'You must search for something';
+$string['enabled'] = 'Enabled';
 $string['errorcallingprocessor'] = 'Error calling defined output';
 $string['errortranslatingdefault'] = 'Error translating default setting provided by plugin, using system defaults instead.';
 $string['forced'] = 'Forced';
index c277e13..11fbf4d 100644 (file)
@@ -190,12 +190,15 @@ class behat_config_manager {
                         'selenium2' => null
                     ),
                     'Moodle\BehatExtension\Extension' => array(
+                        'formatters' => array(
+                            'moodle_progress' => 'Moodle\BehatExtension\Formatter\MoodleProgressFormatter'
+                        ),
                         'features' => $features,
                         'steps_definitions' => $stepsdefinitions
                     )
                 ),
                 'formatter' => array(
-                    'name' => 'progress'
+                    'name' => 'moodle_progress'
                 )
             )
         );
index 426c593..51c71c4 100644 (file)
@@ -57,6 +57,14 @@ function message_send($eventdata) {
     //new message ID to return
     $messageid = false;
 
+    // Fetch default (site) preferences
+    $defaultpreferences = get_message_output_default_preferences();
+    $preferencebase = $eventdata->component.'_'.$eventdata->name;
+    // If message provider is disabled then don't do any processing.
+    if (!empty($defaultpreferences->{$preferencebase.'_disable'})) {
+        return $messageid;
+    }
+
     //TODO: we need to solve problems with database transactions here somehow, for now we just prevent transactions - sorry
     $DB->transactions_forbidden();
 
@@ -150,12 +158,9 @@ function message_send($eventdata) {
 
     // Fetch enabled processors
     $processors = get_message_processors(true);
-    // Fetch default (site) preferences
-    $defaultpreferences = get_message_output_default_preferences();
 
     // Preset variables
     $processorlist = array();
-    $preferencebase = $eventdata->component.'_'.$eventdata->name;
     // Fill in the array of processors to be used based on default and user preferences
     foreach ($processors as $processor) {
         // Skip adding processors for internal user, if processor doesn't support sending message to internal user.
index 91efe88..28d7ea5 100644 (file)
@@ -272,63 +272,7 @@ class phpunit_util extends testing_util {
      * @return void
      */
     public static function bootstrap_moodle_info() {
-        global $CFG;
-
-        // All developers have to understand English, do not localise!
-
-        $release = null;
-        require("$CFG->dirroot/version.php");
-
-        echo "Moodle $release, $CFG->dbtype";
-        if ($hash = self::get_git_hash()) {
-            echo ", $hash";
-        }
-        echo "\n";
-    }
-
-    /**
-     * Try to get current git hash of the Moodle in $CFG->dirroot.
-     * @return string null if unknown, sha1 hash if known
-     */
-    public static function get_git_hash() {
-        global $CFG;
-
-        // This is a bit naive, but it should mostly work for all platforms.
-
-        if (!file_exists("$CFG->dirroot/.git/HEAD")) {
-            return null;
-        }
-
-        $ref = file_get_contents("$CFG->dirroot/.git/HEAD");
-        if ($ref === false) {
-            return null;
-        }
-
-        $ref = trim($ref);
-
-        if (strpos($ref, 'ref: ') !== 0) {
-            return null;
-        }
-
-        $ref = substr($ref, 5);
-
-        if (!file_exists("$CFG->dirroot/.git/$ref")) {
-            return null;
-        }
-
-        $hash = file_get_contents("$CFG->dirroot/.git/$ref");
-
-        if ($hash === false) {
-            return null;
-        }
-
-        $hash = trim($hash);
-
-        if (strlen($hash) != 40) {
-            return null;
-        }
-
-        return $hash;
+        echo self::get_site_info();
     }
 
     /**
index fe30ecd..41a4243 100644 (file)
@@ -607,6 +607,75 @@ abstract class testing_util {
         cache_helper::purge_all();
     }
 
+    /**
+     * Gets a text-based site version description.
+     *
+     * @return string The site info
+     */
+    public static function get_site_info() {
+        global $CFG;
+
+        $output = '';
+
+        // All developers have to understand English, do not localise!
+
+        $release = null;
+        require("$CFG->dirroot/version.php");
+
+        $output .= "Moodle $release, $CFG->dbtype";
+        if ($hash = self::get_git_hash()) {
+            $output .= ", $hash";
+        }
+        $output .= "\n";
+
+        return $output;
+    }
+
+    /**
+     * Try to get current git hash of the Moodle in $CFG->dirroot.
+     * @return string null if unknown, sha1 hash if known
+     */
+    public static function get_git_hash() {
+        global $CFG;
+
+        // This is a bit naive, but it should mostly work for all platforms.
+
+        if (!file_exists("$CFG->dirroot/.git/HEAD")) {
+            return null;
+        }
+
+        $ref = file_get_contents("$CFG->dirroot/.git/HEAD");
+        if ($ref === false) {
+            return null;
+        }
+
+        $ref = trim($ref);
+
+        if (strpos($ref, 'ref: ') !== 0) {
+            return null;
+        }
+
+        $ref = substr($ref, 5);
+
+        if (!file_exists("$CFG->dirroot/.git/$ref")) {
+            return null;
+        }
+
+        $hash = file_get_contents("$CFG->dirroot/.git/$ref");
+
+        if ($hash === false) {
+            return null;
+        }
+
+        $hash = trim($hash);
+
+        if (strlen($hash) != 40) {
+            return null;
+        }
+
+        return $hash;
+    }
+
     /**
      * Drop the whole test database
      * @static
index 4f95515..46c710b 100644 (file)
@@ -27,6 +27,47 @@ defined('MOODLE_INTERNAL') || die();
 
 class core_messagelib_testcase extends advanced_testcase {
 
+    public function test_message_provider_disabled() {
+        $this->resetAfterTest();
+        $this->preventResetByRollback();
+        unset_config('noemailever');
+
+        // Disable instantmessage provider.
+        $disableprovidersetting = 'moodle_instantmessage_disable';
+        set_config($disableprovidersetting, 1, 'message');
+        $preferences = get_message_output_default_preferences();
+        $this->assertTrue($preferences->$disableprovidersetting == 1);
+
+        $message = new stdClass();
+        $message->component         = 'moodle';
+        $message->name              = 'instantmessage';
+        $message->userfrom          = get_admin();
+        $message->userto            = $this->getDataGenerator()->create_user();;
+        $message->subject           = 'message subject 1';
+        $message->fullmessage       = 'message body';
+        $message->fullmessageformat = FORMAT_MARKDOWN;
+        $message->fullmessagehtml   = '<p>message body</p>';
+        $message->smallmessage      = 'small message';
+
+        // Check message is not sent.
+        $sink = $this->redirectEmails();
+        $this->assertTrue(phpunit_util::is_redirecting_phpmailer());
+        message_send($message);
+        $emails = $sink->get_messages();
+        $this->assertEmpty($emails);
+
+        // Check message is sent.
+        set_config($disableprovidersetting, 0, 'message');
+        $preferences = get_message_output_default_preferences();
+        $this->assertTrue($preferences->$disableprovidersetting == 0);
+
+        $sink = $this->redirectEmails();
+        $this->assertTrue(phpunit_util::is_redirecting_phpmailer());
+        message_send($message);
+        $emails = $sink->get_messages();
+        $email = reset($emails);
+        $this->assertEquals($email->subject, 'message subject 1');
+    }
     public function test_message_get_providers_for_user() {
         global $CFG, $DB;
 
index 58513ea..3e95a30 100644 (file)
@@ -41,6 +41,15 @@ if (($form = data_submitted()) && confirm_sesskey()) {
     // Prepare default message outputs settings
     foreach ( $providers as $provider) {
         $componentproviderbase = $provider->component.'_'.$provider->name;
+        $disableprovidersetting = $componentproviderbase.'_disable';
+        $providerdisabled = false;
+        if (!isset($form->$disableprovidersetting)) {
+            $providerdisabled = true;
+            $preferences[$disableprovidersetting] = 1;
+        } else {
+            $preferences[$disableprovidersetting] = 0;
+        }
+
         foreach (array('permitted', 'loggedin', 'loggedoff') as $setting){
             $value = null;
             $componentprovidersetting = $componentproviderbase.'_'.$setting;
@@ -56,13 +65,13 @@ if (($form = data_submitted()) && confirm_sesskey()) {
                     }
                     // Ensure that loggedin loggedoff options are set correctly
                     // for this permission
-                    if ($value == 'forced') {
-                        $form->{$componentproviderbase.'_loggedin'}[$processor->name] = 1;
-                        $form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 1;
-                    } else if ($value == 'disallowed') {
+                    if (($value == 'disallowed') || $providerdisabled) {
                         // It might be better to unset them, but I can't figure out why that cause error
                         $form->{$componentproviderbase.'_loggedin'}[$processor->name] = 0;
                         $form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 0;
+                    } else if ($value == 'forced') {
+                        $form->{$componentproviderbase.'_loggedin'}[$processor->name] = 1;
+                        $form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 1;
                     }
                     // record the site preference
                     $preferences[$processor->name.'_provider_'.$componentprovidersetting] = $value;
index dc4ee7a..6fd3bf4 100644 (file)
@@ -54,6 +54,12 @@ M.core_message.init_defaultoutputs = function(Y) {
                 // set initial layout
                 node.simulate("change");
             }, this);
+
+            Y.all('#defaultmessageoutputs input.messagedisable').each(function(node) {
+                // Attach event listener
+                node.on('change', defaultoutputs.changeProviderState);
+                node.simulate("change");
+            }, this);
         },
 
         changeState : function(e) {
@@ -83,6 +89,26 @@ M.core_message.init_defaultoutputs = function(Y) {
                     node.setAttribute('checked', 1)
                 }
             }, this);
+        },
+
+        changeProviderState : function(e) {
+            var isenabled = e.target.get('checked') || undefined;
+            var parentnode = e.target.ancestor('tr');
+            if (!isenabled) {
+                parentnode.all('select').each(function(node) {
+                    node.set('value', 'disallowed');
+                    node.setAttribute('disabled', 1);
+                    defaultoutputs.updateCheckboxes(node.ancestor('td'), 1, 0);
+                }, this);
+                parentnode.addClass('dimmed_text');
+            } else {
+                parentnode.all('select').each(function(node) {
+                    node.removeAttribute('disabled');
+                    node.set('value', 'permitted');
+                    defaultoutputs.updateCheckboxes(node.ancestor('td'), 0, 0);
+                }, this);
+                parentnode.removeClass('dimmed_text');
+            }
         }
     }
 
index 82e8e68..846a795 100644 (file)
@@ -134,6 +134,9 @@ class core_message_renderer extends plugin_renderer_base {
         foreach ($processors as $processor) {
             $table->head[]  = get_string('pluginname', 'message_'.$processor->name);
         }
+        // Add enable/disable to head
+        $table->head[] = get_string('enabled', 'core_message');
+
         // Generate the matrix of settings for each provider and processor
         foreach ($providers as $provider) {
             $row = new html_table_row();
@@ -143,14 +146,16 @@ class core_message_renderer extends plugin_renderer_base {
             // Provider Name
             $providername = get_string('messageprovider:'.$provider->name, $provider->component);
             $row->cells[] = new html_table_cell($providername);
-
+            $providersettingprefix = $provider->component.'_'.$provider->name.'_';
+            $disableprovidersetting = $providersettingprefix.'disable';
+            $providerdisabled = !empty($preferences->$disableprovidersetting);
             // Settings for each processor
             foreach ($processors as $processor) {
                 $cellcontent = '';
                 foreach (array('permitted', 'loggedin', 'loggedoff') as $setting) {
                     // pepare element and preference names
-                    $elementname = $provider->component.'_'.$provider->name.'_'.$setting.'['.$processor->name.']';
-                    $preferencebase = $provider->component.'_'.$provider->name.'_'.$setting;
+                    $elementname = $providersettingprefix.$setting.'['.$processor->name.']';
+                    $preferencebase = $providersettingprefix.$setting;
                     // prepare language bits
                     $processorname = get_string('pluginname', 'message_'.$processor->name);
                     $statename = get_string($setting, 'message');
@@ -164,7 +169,9 @@ class core_message_renderer extends plugin_renderer_base {
                         // determine the current setting or use default
                         $select = MESSAGE_DEFAULT_PERMITTED;
                         $preference = $processor->name.'_provider_'.$preferencebase;
-                        if (array_key_exists($preference, $preferences)) {
+                        if ($providerdisabled) {
+                            $select = MESSAGE_DISALLOWED;
+                        } else if (array_key_exists($preference, $preferences)) {
                             $select = $preferences->{$preference};
                         }
                         // dropdown menu
@@ -193,6 +200,10 @@ class core_message_renderer extends plugin_renderer_base {
                 }
                 $row->cells[] = new html_table_cell($cellcontent);
             }
+            $disableprovider = html_writer::checkbox($disableprovidersetting, 1, !$providerdisabled, '',
+                    array('id' => $disableprovidersetting, 'class' => 'messagedisable'));
+            $disableprovider = html_writer::tag('div', $disableprovider);
+            $row->cells[] = new html_table_cell($disableprovider);
             $table->data[] = $row;
         }
 
@@ -240,6 +251,7 @@ class core_message_renderer extends plugin_renderer_base {
         $numprocs = count($processors);
         // Display the messaging options table(s)
         foreach ($components as $component) {
+            $provideradded = false;
             $table = new html_table();
             $table->attributes['class'] = 'generaltable';
             $table->data = array();
@@ -249,18 +261,18 @@ class core_message_renderer extends plugin_renderer_base {
                 $componentname = get_string('coresystem');
             }
             $table->head = array($componentname);
-
             foreach ($readyprocessors as $processor) {
                 $table->head[]  = get_string('pluginname', 'message_'.$processor->name);
             }
-
             // Populate the table with rows
-            foreach ( $providers as $provider) {
-                if( $provider->component != $component) {
+            foreach ($providers as $provider) {
+                $preferencebase = $provider->component.'_'.$provider->name;
+                // If provider component is not same or provider disabled then don't show.
+                if (($provider->component != $component) ||
+                        (!empty($defaultpreferences->{$preferencebase.'_disable'}))) {
                     continue;
                 }
-                $preferencebase = $provider->component.'_'.$provider->name;
-
+                $provideradded = true;
                 $headerrow = new html_table_row();
                 $providername = get_string('messageprovider:'.$provider->name, $provider->component);
                 $providercell = new html_table_cell($providername);
@@ -331,9 +343,12 @@ class core_message_renderer extends plugin_renderer_base {
                     $table->data[] = $optionrow;
                 }
             }
-            $output .= html_writer::start_tag('div', array('class' => 'messagesettingcomponent'));
-            $output .= html_writer::table($table);
-            $output .= html_writer::end_tag('div');
+            // Add settings only if provider added for component.
+            if ($provideradded) {
+                $output .= html_writer::start_tag('div', array('class' => 'messagesettingcomponent'));
+                $output .= html_writer::table($table);
+                $output .= html_writer::end_tag('div');
+            }
         }
 
         $output .= html_writer::end_tag('fieldset');
index 4945b2d..8609335 100644 (file)
@@ -500,7 +500,7 @@ class quiz_statistics_report extends quiz_default_report {
      *     - $questionstats array of \core_question\statistics\questions\calculated objects keyed by slot.
      *     - $subquestionstats array of \core_question\statistics\questions\calculated_for_subquestion objects keyed by question id.
      */
-    protected function get_quiz_and_questions_stats($quiz, $whichattempts, $groupstudents, $questions) {
+    public function get_quiz_and_questions_stats($quiz, $whichattempts, $groupstudents, $questions) {
 
         $qubaids = quiz_statistics_qubaids_condition($quiz->id, $groupstudents, $whichattempts);
 
index c9aae05..26b9a82 100644 (file)
@@ -31,22 +31,7 @@ require_once($CFG->dirroot . '/mod/quiz/tests/attempt_walkthrough_from_csv_test.
 require_once($CFG->dirroot . '/mod/quiz/report/default.php');
 require_once($CFG->dirroot . '/mod/quiz/report/statistics/report.php');
 require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
-/**
- * Test helper subclass of quiz_statistics_report
- *
- * @copyright  2013 The Open University
- * @author     Jamie Pratt <me@jamiep.org>
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class testable_quiz_statistics_report extends quiz_statistics_report {
 
-    public function get_stats($quiz, $whichattempts = QUIZ_GRADEAVERAGE, $groupstudents = array()) {
-        $qubaids = quiz_statistics_qubaids_condition($quiz->id, $groupstudents, $whichattempts);
-        $this->clear_cached_data($qubaids);
-        $questions = $this->load_and_initialise_questions_for_calculations($quiz);
-        return $this->get_quiz_and_questions_stats($quiz, $whichattempts, $groupstudents, $questions);
-    }
-}
 
 /**
  * Quiz attempt walk through using data from csv file.
@@ -92,8 +77,31 @@ class quiz_report_statistics_from_steps extends mod_quiz_attempt_walkthrough_fro
 
         $this->check_attempts_results($csvdata['results'], $attemptids);
 
-        $this->report = new testable_quiz_statistics_report();
-        list($quizstats, $questionstats, $subquestionstats) = $this->report->get_stats($this->quiz);
+        $this->report = new quiz_statistics_report();
+        $whichattempts = QUIZ_GRADEAVERAGE;
+        $groupstudents = array();
+        $questions = $this->report->load_and_initialise_questions_for_calculations($this->quiz);
+        list($quizstats, $questionstats, $subquestionstats) =
+                        $this->report->get_quiz_and_questions_stats($this->quiz, $whichattempts, $groupstudents, $questions);
+
+        $qubaids = quiz_statistics_qubaids_condition($this->quiz->id, $groupstudents, $whichattempts);
+
+        // We will create some quiz and question stat calculator instances and some response analyser instances, just in order
+        // to check the time of the
+        $quizcalc = new quiz_statistics_calculator();
+        // Should not be a delay of more than one second between the calculation of stats above and here.
+        $this->assertTimeCurrent($quizcalc->get_last_calculated_time($qubaids));
+
+        $qcalc = new \core_question\statistics\questions\calculator($questions);
+        $this->assertTimeCurrent($qcalc->get_last_calculated_time($qubaids));
+
+        foreach ($questions as $question) {
+            if (!question_bank::get_qtype($question->qtype, false)->can_analyse_responses()) {
+                continue;
+            }
+            $responesstats = new \core_question\statistics\responses\analyser($question);
+            $this->assertTimeCurrent($responesstats->get_last_analysed_time($qubaids));
+        }
 
         // These quiz stats and the question stats found in qstats00.csv were calculated independently in spreadsheet which is
         // available in open document or excel format here :
index 78ab82e..e1919e9 100644 (file)
@@ -251,7 +251,7 @@ class calculator {
 
         $timemodified = time() - self::TIME_TO_CACHE;
         return $DB->get_field_select('question_statistics', 'timemodified', 'hashcode = ? AND timemodified > ?',
-                                     array($qubaids->get_hash_code(), $timemodified));
+                                     array($qubaids->get_hash_code(), $timemodified), IGNORE_MULTIPLE);
     }
 
     /** @var integer Time after which statistics are automatically recomputed. */
index a42d2f0..bfaa26f 100644 (file)
@@ -161,7 +161,8 @@ class analyser {
         global $DB;
 
         $timemodified = time() - self::TIME_TO_CACHE;
-        return $DB->get_field_select('question_response_analysis', 'hashcode = ? AND questionid = ? AND timemodified > ?',
+        return $DB->get_field_select('question_response_analysis', 'timemodified',
+                                     'hashcode = ? AND questionid = ? AND timemodified > ?',
                                      array($qubaids->get_hash_code(), $this->questiondata->id, $timemodified), IGNORE_MULTIPLE);
     }
 }
index 4944b6c..f9c195d 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2013111800.02;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2013112900.00;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.
 
-$release  = '2.7dev (Build: 20131122)'; // Human-friendly version name
+$release  = '2.7dev (Build: 20131129)'; // Human-friendly version name
 
 $branch   = '27';                       // This version's branch.
 $maturity = MATURITY_ALPHA;             // This version's maturity level.