[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/phpunit/classes/ -> util.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Utility class.
  19   *
  20   * @package    core
  21   * @category   phpunit
  22   * @copyright  2012 Petr Skoda {@link http://skodak.org}
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  require_once (__DIR__.'/../../testing/classes/util.php');
  27  
  28  /**
  29   * Collection of utility methods.
  30   *
  31   * @package    core
  32   * @category   phpunit
  33   * @copyright  2012 Petr Skoda {@link http://skodak.org}
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class phpunit_util extends testing_util {
  37      /**
  38       * @var int last value of db writes counter, used for db resetting
  39       */
  40      public static $lastdbwrites = null;
  41  
  42      /** @var array An array of original globals, restored after each test */
  43      protected static $globals = array();
  44  
  45      /** @var array list of debugging messages triggered during the last test execution */
  46      protected static $debuggings = array();
  47  
  48      /** @var phpunit_message_sink alternative target for moodle messaging */
  49      protected static $messagesink = null;
  50  
  51      /** @var phpunit_phpmailer_sink alternative target for phpmailer messaging */
  52      protected static $phpmailersink = null;
  53  
  54      /** @var phpunit_message_sink alternative target for moodle messaging */
  55      protected static $eventsink = null;
  56  
  57      /**
  58       * @var array Files to skip when resetting dataroot folder
  59       */
  60      protected static $datarootskiponreset = array('.', '..', 'phpunittestdir.txt', 'phpunit', '.htaccess');
  61  
  62      /**
  63       * @var array Files to skip when dropping dataroot folder
  64       */
  65      protected static $datarootskipondrop = array('.', '..', 'lock', 'webrunner.xml');
  66  
  67      /**
  68       * Load global $CFG;
  69       * @internal
  70       * @static
  71       * @return void
  72       */
  73      public static function initialise_cfg() {
  74          global $DB;
  75          $dbhash = false;
  76          try {
  77              $dbhash = $DB->get_field('config', 'value', array('name'=>'phpunittest'));
  78          } catch (Exception $e) {
  79              // not installed yet
  80              initialise_cfg();
  81              return;
  82          }
  83          if ($dbhash !== core_component::get_all_versions_hash()) {
  84              // do not set CFG - the only way forward is to drop and reinstall
  85              return;
  86          }
  87          // standard CFG init
  88          initialise_cfg();
  89      }
  90  
  91      /**
  92       * Reset contents of all database tables to initial values, reset caches, etc.
  93       *
  94       * Note: this is relatively slow (cca 2 seconds for pg and 7 for mysql) - please use with care!
  95       *
  96       * @static
  97       * @param bool $detectchanges
  98       *      true  - changes in global state and database are reported as errors
  99       *      false - no errors reported
 100       *      null  - only critical problems are reported as errors
 101       * @return void
 102       */
 103      public static function reset_all_data($detectchanges = false) {
 104          global $DB, $CFG, $USER, $SITE, $COURSE, $PAGE, $OUTPUT, $SESSION, $FULLME;
 105  
 106          // Stop any message redirection.
 107          self::stop_message_redirection();
 108  
 109          // Stop any message redirection.
 110          self::stop_event_redirection();
 111  
 112          // Start a new email redirection.
 113          // This will clear any existing phpmailer redirection.
 114          // We redirect all phpmailer output to this message sink which is
 115          // called instead of phpmailer actually sending the message.
 116          self::start_phpmailer_redirection();
 117  
 118          // We used to call gc_collect_cycles here to ensure desctructors were called between tests.
 119          // This accounted for 25% of the total time running phpunit - so we removed it.
 120  
 121          // Show any unhandled debugging messages, the runbare() could already reset it.
 122          self::display_debugging_messages();
 123          self::reset_debugging();
 124  
 125          // reset global $DB in case somebody mocked it
 126          $DB = self::get_global_backup('DB');
 127  
 128          if ($DB->is_transaction_started()) {
 129              // we can not reset inside transaction
 130              $DB->force_transaction_rollback();
 131          }
 132  
 133          $resetdb = self::reset_database();
 134          $localename = self::get_locale_name();
 135          $warnings = array();
 136  
 137          if ($detectchanges === true) {
 138              if ($resetdb) {
 139                  $warnings[] = 'Warning: unexpected database modification, resetting DB state';
 140              }
 141  
 142              $oldcfg = self::get_global_backup('CFG');
 143              $oldsite = self::get_global_backup('SITE');
 144              foreach($CFG as $k=>$v) {
 145                  if (!property_exists($oldcfg, $k)) {
 146                      $warnings[] = 'Warning: unexpected new $CFG->'.$k.' value';
 147                  } else if ($oldcfg->$k !== $CFG->$k) {
 148                      $warnings[] = 'Warning: unexpected change of $CFG->'.$k.' value';
 149                  }
 150                  unset($oldcfg->$k);
 151  
 152              }
 153              if ($oldcfg) {
 154                  foreach($oldcfg as $k=>$v) {
 155                      $warnings[] = 'Warning: unexpected removal of $CFG->'.$k;
 156                  }
 157              }
 158  
 159              if ($USER->id != 0) {
 160                  $warnings[] = 'Warning: unexpected change of $USER';
 161              }
 162  
 163              if ($COURSE->id != $oldsite->id) {
 164                  $warnings[] = 'Warning: unexpected change of $COURSE';
 165              }
 166  
 167              if ($FULLME !== self::get_global_backup('FULLME')) {
 168                  $warnings[] = 'Warning: unexpected change of $FULLME';
 169              }
 170  
 171              if (setlocale(LC_TIME, 0) !== $localename) {
 172                  $warnings[] = 'Warning: unexpected change of locale';
 173              }
 174          }
 175  
 176          if (ini_get('max_execution_time') != 0) {
 177              // This is special warning for all resets because we do not want any
 178              // libraries to mess with timeouts unintentionally.
 179              // Our PHPUnit integration is not supposed to change it either.
 180  
 181              if ($detectchanges !== false) {
 182                  $warnings[] = 'Warning: max_execution_time was changed to '.ini_get('max_execution_time');
 183              }
 184              set_time_limit(0);
 185          }
 186  
 187          // restore original globals
 188          $_SERVER = self::get_global_backup('_SERVER');
 189          $CFG = self::get_global_backup('CFG');
 190          $SITE = self::get_global_backup('SITE');
 191          $FULLME = self::get_global_backup('FULLME');
 192          $_GET = array();
 193          $_POST = array();
 194          $_FILES = array();
 195          $_REQUEST = array();
 196          $COURSE = $SITE;
 197  
 198          // reinitialise following globals
 199          $OUTPUT = new bootstrap_renderer();
 200          $PAGE = new moodle_page();
 201          $FULLME = null;
 202          $ME = null;
 203          $SCRIPT = null;
 204  
 205          // Empty sessison and set fresh new not-logged-in user.
 206          \core\session\manager::init_empty_session();
 207  
 208          // reset all static caches
 209          \core\event\manager::phpunit_reset();
 210          accesslib_clear_all_caches(true);
 211          get_string_manager()->reset_caches(true);
 212          reset_text_filters_cache(true);
 213          events_get_handlers('reset');
 214          core_text::reset_caches();
 215          get_message_processors(false, true, true);
 216          filter_manager::reset_caches();
 217          core_filetypes::reset_caches();
 218          \core_search\manager::clear_static();
 219          core_user::reset_caches();
 220  
 221          // Reset static unit test options.
 222          if (class_exists('\availability_date\condition', false)) {
 223              \availability_date\condition::set_current_time_for_test(0);
 224          }
 225  
 226          // Reset internal users.
 227          core_user::reset_internal_users();
 228  
 229          //TODO MDL-25290: add more resets here and probably refactor them to new core function
 230  
 231          // Reset course and module caches.
 232          if (class_exists('format_base')) {
 233              // If file containing class is not loaded, there is no cache there anyway.
 234              format_base::reset_course_cache(0);
 235          }
 236          get_fast_modinfo(0, 0, true);
 237  
 238          // Reset other singletons.
 239          if (class_exists('core_plugin_manager')) {
 240              core_plugin_manager::reset_caches(true);
 241          }
 242          if (class_exists('\core\update\checker')) {
 243              \core\update\checker::reset_caches(true);
 244          }
 245  
 246          // Clear static cache within restore.
 247          if (class_exists('restore_section_structure_step')) {
 248              restore_section_structure_step::reset_caches();
 249          }
 250  
 251          // purge dataroot directory
 252          self::reset_dataroot();
 253  
 254          // restore original config once more in case resetting of caches changed CFG
 255          $CFG = self::get_global_backup('CFG');
 256  
 257          // inform data generator
 258          self::get_data_generator()->reset();
 259  
 260          // fix PHP settings
 261          error_reporting($CFG->debug);
 262  
 263          // Reset the date/time class.
 264          core_date::phpunit_reset();
 265  
 266          // Make sure the time locale is consistent - that is Australian English.
 267          setlocale(LC_TIME, $localename);
 268  
 269          // verify db writes just in case something goes wrong in reset
 270          if (self::$lastdbwrites != $DB->perf_get_writes()) {
 271              error_log('Unexpected DB writes in phpunit_util::reset_all_data()');
 272              self::$lastdbwrites = $DB->perf_get_writes();
 273          }
 274  
 275          if ($warnings) {
 276              $warnings = implode("\n", $warnings);
 277              trigger_error($warnings, E_USER_WARNING);
 278          }
 279      }
 280  
 281      /**
 282       * Reset all database tables to default values.
 283       * @static
 284       * @return bool true if reset done, false if skipped
 285       */
 286      public static function reset_database() {
 287          global $DB;
 288  
 289          if (!is_null(self::$lastdbwrites) and self::$lastdbwrites == $DB->perf_get_writes()) {
 290              return false;
 291          }
 292  
 293          if (!parent::reset_database()) {
 294              return false;
 295          }
 296  
 297          self::$lastdbwrites = $DB->perf_get_writes();
 298  
 299          return true;
 300      }
 301  
 302      /**
 303       * Called during bootstrap only!
 304       * @internal
 305       * @static
 306       * @return void
 307       */
 308      public static function bootstrap_init() {
 309          global $CFG, $SITE, $DB, $FULLME;
 310  
 311          // backup the globals
 312          self::$globals['_SERVER'] = $_SERVER;
 313          self::$globals['CFG'] = clone($CFG);
 314          self::$globals['SITE'] = clone($SITE);
 315          self::$globals['DB'] = $DB;
 316          self::$globals['FULLME'] = $FULLME;
 317  
 318          // refresh data in all tables, clear caches, etc.
 319          self::reset_all_data();
 320      }
 321  
 322      /**
 323       * Print some Moodle related info to console.
 324       * @internal
 325       * @static
 326       * @return void
 327       */
 328      public static function bootstrap_moodle_info() {
 329          echo self::get_site_info();
 330      }
 331  
 332      /**
 333       * Returns original state of global variable.
 334       * @static
 335       * @param string $name
 336       * @return mixed
 337       */
 338      public static function get_global_backup($name) {
 339          if ($name === 'DB') {
 340              // no cloning of database object,
 341              // we just need the original reference, not original state
 342              return self::$globals['DB'];
 343          }
 344          if (isset(self::$globals[$name])) {
 345              if (is_object(self::$globals[$name])) {
 346                  $return = clone(self::$globals[$name]);
 347                  return $return;
 348              } else {
 349                  return self::$globals[$name];
 350              }
 351          }
 352          return null;
 353      }
 354  
 355      /**
 356       * Is this site initialised to run unit tests?
 357       *
 358       * @static
 359       * @return int array errorcode=>message, 0 means ok
 360       */
 361      public static function testing_ready_problem() {
 362          global $DB;
 363  
 364          $localename = self::get_locale_name();
 365          if (setlocale(LC_TIME, $localename) === false) {
 366              return array(PHPUNIT_EXITCODE_CONFIGERROR, "Required locale '$localename' is not installed.");
 367          }
 368  
 369          if (!self::is_test_site()) {
 370              // dataroot was verified in bootstrap, so it must be DB
 371              return array(PHPUNIT_EXITCODE_CONFIGERROR, 'Can not use database for testing, try different prefix');
 372          }
 373  
 374          $tables = $DB->get_tables(false);
 375          if (empty($tables)) {
 376              return array(PHPUNIT_EXITCODE_INSTALL, '');
 377          }
 378  
 379          if (!self::is_test_data_updated()) {
 380              return array(PHPUNIT_EXITCODE_REINSTALL, '');
 381          }
 382  
 383          return array(0, '');
 384      }
 385  
 386      /**
 387       * Drop all test site data.
 388       *
 389       * Note: To be used from CLI scripts only.
 390       *
 391       * @static
 392       * @param bool $displayprogress if true, this method will echo progress information.
 393       * @return void may terminate execution with exit code
 394       */
 395      public static function drop_site($displayprogress = false) {
 396          global $DB, $CFG;
 397  
 398          if (!self::is_test_site()) {
 399              phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGERROR, 'Can not drop non-test site!!');
 400          }
 401  
 402          // Purge dataroot
 403          if ($displayprogress) {
 404              echo "Purging dataroot:\n";
 405          }
 406  
 407          self::reset_dataroot();
 408          testing_initdataroot($CFG->dataroot, 'phpunit');
 409          self::drop_dataroot();
 410  
 411          // drop all tables
 412          self::drop_database($displayprogress);
 413      }
 414  
 415      /**
 416       * Perform a fresh test site installation
 417       *
 418       * Note: To be used from CLI scripts only.
 419       *
 420       * @static
 421       * @return void may terminate execution with exit code
 422       */
 423      public static function install_site() {
 424          global $DB, $CFG;
 425  
 426          if (!self::is_test_site()) {
 427              phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGERROR, 'Can not install on non-test site!!');
 428          }
 429  
 430          if ($DB->get_tables()) {
 431              list($errorcode, $message) = self::testing_ready_problem();
 432              if ($errorcode) {
 433                  phpunit_bootstrap_error(PHPUNIT_EXITCODE_REINSTALL, 'Database tables already present, Moodle PHPUnit test environment can not be initialised');
 434              } else {
 435                  phpunit_bootstrap_error(0, 'Moodle PHPUnit test environment is already initialised');
 436              }
 437          }
 438  
 439          $options = array();
 440          $options['adminpass'] = 'admin';
 441          $options['shortname'] = 'phpunit';
 442          $options['fullname'] = 'PHPUnit test site';
 443  
 444          install_cli_database($options, false);
 445  
 446          // Set the admin email address.
 447          $DB->set_field('user', 'email', 'admin@example.com', array('username' => 'admin'));
 448  
 449          // Disable all logging for performance and sanity reasons.
 450          set_config('enabled_stores', '', 'tool_log');
 451  
 452          // We need to keep the installed dataroot filedir files.
 453          // So each time we reset the dataroot before running a test, the default files are still installed.
 454          self::save_original_data_files();
 455  
 456          // Store version hash in the database and in a file.
 457          self::store_versions_hash();
 458  
 459          // Store database data and structure.
 460          self::store_database_state();
 461      }
 462  
 463      /**
 464       * Builds dirroot/phpunit.xml and dataroot/phpunit/webrunner.xml files using defaults from /phpunit.xml.dist
 465       * @static
 466       * @return bool true means main config file created, false means only dataroot file created
 467       */
 468      public static function build_config_file() {
 469          global $CFG;
 470  
 471          $template = '
 472          <testsuite name="@component@_testsuite">
 473              <directory suffix="_test.php">@dir@</directory>
 474          </testsuite>';
 475          $data = file_get_contents("$CFG->dirroot/phpunit.xml.dist");
 476  
 477          $suites = '';
 478  
 479          $plugintypes = core_component::get_plugin_types();
 480          ksort($plugintypes);
 481          foreach ($plugintypes as $type=>$unused) {
 482              $plugs = core_component::get_plugin_list($type);
 483              ksort($plugs);
 484              foreach ($plugs as $plug=>$fullplug) {
 485                  if (!file_exists("$fullplug/tests/")) {
 486                      continue;
 487                  }
 488                  $dir = substr($fullplug, strlen($CFG->dirroot)+1);
 489                  $dir .= '/tests';
 490                  $component = $type.'_'.$plug;
 491  
 492                  $suite = str_replace('@component@', $component, $template);
 493                  $suite = str_replace('@dir@', $dir, $suite);
 494  
 495                  $suites .= $suite;
 496              }
 497          }
 498          // Start a sequence between 100000 and 199000 to ensure each call to init produces
 499          // different ids in the database.  This reduces the risk that hard coded values will
 500          // end up being placed in phpunit or behat test code.
 501          $sequencestart = 100000 + mt_rand(0, 99) * 1000;
 502  
 503          $data = preg_replace('|<!--@plugin_suites_start@-->.*<!--@plugin_suites_end@-->|s', $suites, $data, 1);
 504          $data = str_replace(
 505              '<const name="PHPUNIT_SEQUENCE_START" value=""/>',
 506              '<const name="PHPUNIT_SEQUENCE_START" value="' . $sequencestart . '"/>',
 507              $data);
 508  
 509          $result = false;
 510          if (is_writable($CFG->dirroot)) {
 511              if ($result = file_put_contents("$CFG->dirroot/phpunit.xml", $data)) {
 512                  testing_fix_file_permissions("$CFG->dirroot/phpunit.xml");
 513              }
 514          }
 515  
 516          // relink - it seems that xml:base does not work in phpunit xml files, remove this nasty hack if you find a way to set xml base for relative refs
 517          $data = str_replace('lib/phpunit/', $CFG->dirroot.DIRECTORY_SEPARATOR.'lib'.DIRECTORY_SEPARATOR.'phpunit'.DIRECTORY_SEPARATOR, $data);
 518          $data = preg_replace('|<directory suffix="_test.php">([^<]+)</directory>|',
 519              '<directory suffix="_test.php">'.$CFG->dirroot.(DIRECTORY_SEPARATOR === '\\' ? '\\\\' : DIRECTORY_SEPARATOR).'$1</directory>',
 520              $data);
 521          file_put_contents("$CFG->dataroot/phpunit/webrunner.xml", $data);
 522          testing_fix_file_permissions("$CFG->dataroot/phpunit/webrunner.xml");
 523  
 524          return (bool)$result;
 525      }
 526  
 527      /**
 528       * Builds phpunit.xml files for all components using defaults from /phpunit.xml.dist
 529       *
 530       * @static
 531       * @return void, stops if can not write files
 532       */
 533      public static function build_component_config_files() {
 534          global $CFG;
 535  
 536          $template = '
 537          <testsuites>
 538              <testsuite name="@component@_testsuite">
 539                  <directory suffix="_test.php">.</directory>
 540              </testsuite>
 541          </testsuites>';
 542  
 543          // Start a sequence between 100000 and 199000 to ensure each call to init produces
 544          // different ids in the database.  This reduces the risk that hard coded values will
 545          // end up being placed in phpunit or behat test code.
 546          $sequencestart = 100000 + mt_rand(0, 99) * 1000;
 547  
 548          // Use the upstream file as source for the distributed configurations
 549          $ftemplate = file_get_contents("$CFG->dirroot/phpunit.xml.dist");
 550          $ftemplate = preg_replace('|<!--All core suites.*</testsuites>|s', '<!--@component_suite@-->', $ftemplate);
 551  
 552          // Gets all the components with tests
 553          $components = tests_finder::get_components_with_tests('phpunit');
 554  
 555          // Create the corresponding phpunit.xml file for each component
 556          foreach ($components as $cname => $cpath) {
 557              // Calculate the component suite
 558              $ctemplate = $template;
 559              $ctemplate = str_replace('@component@', $cname, $ctemplate);
 560  
 561              // Apply it to the file template
 562              $fcontents = str_replace('<!--@component_suite@-->', $ctemplate, $ftemplate);
 563              $fcontents = str_replace(
 564                  '<const name="PHPUNIT_SEQUENCE_START" value=""/>',
 565                  '<const name="PHPUNIT_SEQUENCE_START" value="' . $sequencestart . '"/>',
 566                  $fcontents);
 567  
 568              // fix link to schema
 569              $level = substr_count(str_replace('\\', '/', $cpath), '/') - substr_count(str_replace('\\', '/', $CFG->dirroot), '/');
 570              $fcontents = str_replace('lib/phpunit/', str_repeat('../', $level).'lib/phpunit/', $fcontents);
 571  
 572              // Write the file
 573              $result = false;
 574              if (is_writable($cpath)) {
 575                  if ($result = (bool)file_put_contents("$cpath/phpunit.xml", $fcontents)) {
 576                      testing_fix_file_permissions("$cpath/phpunit.xml");
 577                  }
 578              }
 579              // Problems writing file, throw error
 580              if (!$result) {
 581                  phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGWARNING, "Can not create $cpath/phpunit.xml configuration file, verify dir permissions");
 582              }
 583          }
 584      }
 585  
 586      /**
 587       * To be called from debugging() only.
 588       * @param string $message
 589       * @param int $level
 590       * @param string $from
 591       */
 592      public static function debugging_triggered($message, $level, $from) {
 593          // Store only if debugging triggered from actual test,
 594          // we need normal debugging outside of tests to find problems in our phpunit integration.
 595          $backtrace = debug_backtrace();
 596  
 597          foreach ($backtrace as $bt) {
 598              $intest = false;
 599              if (isset($bt['object']) and is_object($bt['object'])) {
 600                  if ($bt['object'] instanceof PHPUnit_Framework_TestCase) {
 601                      if (strpos($bt['function'], 'test') === 0) {
 602                          $intest = true;
 603                          break;
 604                      }
 605                  }
 606              }
 607          }
 608          if (!$intest) {
 609              return false;
 610          }
 611  
 612          $debug = new stdClass();
 613          $debug->message = $message;
 614          $debug->level   = $level;
 615          $debug->from    = $from;
 616  
 617          self::$debuggings[] = $debug;
 618  
 619          return true;
 620      }
 621  
 622      /**
 623       * Resets the list of debugging messages.
 624       */
 625      public static function reset_debugging() {
 626          self::$debuggings = array();
 627          set_debugging(DEBUG_DEVELOPER);
 628      }
 629  
 630      /**
 631       * Returns all debugging messages triggered during test.
 632       * @return array with instances having message, level and stacktrace property.
 633       */
 634      public static function get_debugging_messages() {
 635          return self::$debuggings;
 636      }
 637  
 638      /**
 639       * Prints out any debug messages accumulated during test execution.
 640       * @return bool false if no debug messages, true if debug triggered
 641       */
 642      public static function display_debugging_messages() {
 643          if (empty(self::$debuggings)) {
 644              return false;
 645          }
 646          foreach(self::$debuggings as $debug) {
 647              echo 'Debugging: ' . $debug->message . "\n" . trim($debug->from) . "\n";
 648          }
 649  
 650          return true;
 651      }
 652  
 653      /**
 654       * Start message redirection.
 655       *
 656       * Note: Do not call directly from tests,
 657       *       use $sink = $this->redirectMessages() instead.
 658       *
 659       * @return phpunit_message_sink
 660       */
 661      public static function start_message_redirection() {
 662          if (self::$messagesink) {
 663              self::stop_message_redirection();
 664          }
 665          self::$messagesink = new phpunit_message_sink();
 666          return self::$messagesink;
 667      }
 668  
 669      /**
 670       * End message redirection.
 671       *
 672       * Note: Do not call directly from tests,
 673       *       use $sink->close() instead.
 674       */
 675      public static function stop_message_redirection() {
 676          self::$messagesink = null;
 677      }
 678  
 679      /**
 680       * Are messages redirected to some sink?
 681       *
 682       * Note: to be called from messagelib.php only!
 683       *
 684       * @return bool
 685       */
 686      public static function is_redirecting_messages() {
 687          return !empty(self::$messagesink);
 688      }
 689  
 690      /**
 691       * To be called from messagelib.php only!
 692       *
 693       * @param stdClass $message record from message_read table
 694       * @return bool true means send message, false means message "sent" to sink.
 695       */
 696      public static function message_sent($message) {
 697          if (self::$messagesink) {
 698              self::$messagesink->add_message($message);
 699          }
 700      }
 701  
 702      /**
 703       * Start phpmailer redirection.
 704       *
 705       * Note: Do not call directly from tests,
 706       *       use $sink = $this->redirectEmails() instead.
 707       *
 708       * @return phpunit_phpmailer_sink
 709       */
 710      public static function start_phpmailer_redirection() {
 711          if (self::$phpmailersink) {
 712              // If an existing mailer sink is active, just clear it.
 713              self::$phpmailersink->clear();
 714          } else {
 715              self::$phpmailersink = new phpunit_phpmailer_sink();
 716          }
 717          return self::$phpmailersink;
 718      }
 719  
 720      /**
 721       * End phpmailer redirection.
 722       *
 723       * Note: Do not call directly from tests,
 724       *       use $sink->close() instead.
 725       */
 726      public static function stop_phpmailer_redirection() {
 727          self::$phpmailersink = null;
 728      }
 729  
 730      /**
 731       * Are messages for phpmailer redirected to some sink?
 732       *
 733       * Note: to be called from moodle_phpmailer.php only!
 734       *
 735       * @return bool
 736       */
 737      public static function is_redirecting_phpmailer() {
 738          return !empty(self::$phpmailersink);
 739      }
 740  
 741      /**
 742       * To be called from messagelib.php only!
 743       *
 744       * @param stdClass $message record from message_read table
 745       * @return bool true means send message, false means message "sent" to sink.
 746       */
 747      public static function phpmailer_sent($message) {
 748          if (self::$phpmailersink) {
 749              self::$phpmailersink->add_message($message);
 750          }
 751      }
 752  
 753      /**
 754       * Start event redirection.
 755       *
 756       * @private
 757       * Note: Do not call directly from tests,
 758       *       use $sink = $this->redirectEvents() instead.
 759       *
 760       * @return phpunit_event_sink
 761       */
 762      public static function start_event_redirection() {
 763          if (self::$eventsink) {
 764              self::stop_event_redirection();
 765          }
 766          self::$eventsink = new phpunit_event_sink();
 767          return self::$eventsink;
 768      }
 769  
 770      /**
 771       * End event redirection.
 772       *
 773       * @private
 774       * Note: Do not call directly from tests,
 775       *       use $sink->close() instead.
 776       */
 777      public static function stop_event_redirection() {
 778          self::$eventsink = null;
 779      }
 780  
 781      /**
 782       * Are events redirected to some sink?
 783       *
 784       * Note: to be called from \core\event\base only!
 785       *
 786       * @private
 787       * @return bool
 788       */
 789      public static function is_redirecting_events() {
 790          return !empty(self::$eventsink);
 791      }
 792  
 793      /**
 794       * To be called from \core\event\base only!
 795       *
 796       * @private
 797       * @param \core\event\base $event record from event_read table
 798       * @return bool true means send event, false means event "sent" to sink.
 799       */
 800      public static function event_triggered(\core\event\base $event) {
 801          if (self::$eventsink) {
 802              self::$eventsink->add_event($event);
 803          }
 804      }
 805  
 806      /**
 807       * Gets the name of the locale for testing environment (Australian English)
 808       * depending on platform environment.
 809       *
 810       * @return string the locale name.
 811       */
 812      protected static function get_locale_name() {
 813          global $CFG;
 814          if ($CFG->ostype === 'WINDOWS') {
 815              return 'English_Australia.1252';
 816          } else {
 817              return 'en_AU.UTF-8';
 818          }
 819      }
 820  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1