[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/admin/tool/customlang/ -> locallib.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   * Definition of classes used by language customization admin tool
  19   *
  20   * @package    tool
  21   * @subpackage customlang
  22   * @copyright  2010 David Mudrak <david@moodle.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  /**
  29   * Provides various utilities to be used by the plugin
  30   *
  31   * All the public methods here are static ones, this class can not be instantiated
  32   */
  33  class tool_customlang_utils {
  34  
  35      /**
  36       * Rough number of strings that are being processed during a full checkout.
  37       * This is used to estimate the progress of the checkout.
  38       */
  39      const ROUGH_NUMBER_OF_STRINGS = 16500;
  40  
  41      /** @var array cache of {@link self::list_components()} results */
  42      protected static $components = null;
  43  
  44      /**
  45       * This class can not be instantiated
  46       */
  47      private function __construct() {
  48      }
  49  
  50      /**
  51       * Returns a list of all components installed on the server
  52       *
  53       * @return array (string)legacyname => (string)frankenstylename
  54       */
  55      public static function list_components() {
  56  
  57          $list['moodle'] = 'core';
  58  
  59          $coresubsystems = core_component::get_core_subsystems();
  60          ksort($coresubsystems); // should be but just in case
  61          foreach ($coresubsystems as $name => $location) {
  62              $list[$name] = 'core_'.$name;
  63          }
  64  
  65          $plugintypes = core_component::get_plugin_types();
  66          foreach ($plugintypes as $type => $location) {
  67              $pluginlist = core_component::get_plugin_list($type);
  68              foreach ($pluginlist as $name => $ununsed) {
  69                  if ($type == 'mod') {
  70                      // Plugin names are now automatically validated.
  71                      $list[$name] = $type.'_'.$name;
  72                  } else {
  73                      $list[$type.'_'.$name] = $type.'_'.$name;
  74                  }
  75              }
  76          }
  77  
  78          return $list;
  79      }
  80  
  81      /**
  82       * Updates the translator database with the strings from files
  83       *
  84       * This should be executed each time before going to the translation page
  85       *
  86       * @param string $lang language code to checkout
  87       * @param progress_bar $progressbar optionally, the given progress bar can be updated
  88       */
  89      public static function checkout($lang, progress_bar $progressbar = null) {
  90          global $DB;
  91  
  92          // make sure that all components are registered
  93          $current = $DB->get_records('tool_customlang_components', null, 'name', 'name,version,id');
  94          foreach (self::list_components() as $component) {
  95              if (empty($current[$component])) {
  96                  $record = new stdclass();
  97                  $record->name = $component;
  98                  if (!$version = get_component_version($component)) {
  99                      $record->version = null;
 100                  } else {
 101                      $record->version = $version;
 102                  }
 103                  $DB->insert_record('tool_customlang_components', $record);
 104              } elseif ($version = get_component_version($component)) {
 105                  if (is_null($current[$component]->version) or ($version > $current[$component]->version)) {
 106                      $DB->set_field('tool_customlang_components', 'version', $version, array('id' => $current[$component]->id));
 107                  }
 108              }
 109          }
 110          unset($current);
 111  
 112          // initialize the progress counter - stores the number of processed strings
 113          $done = 0;
 114          $strinprogress = get_string('checkoutinprogress', 'tool_customlang');
 115  
 116          // reload components and fetch their strings
 117          $stringman  = get_string_manager();
 118          $components = $DB->get_records('tool_customlang_components');
 119          foreach ($components as $component) {
 120              $sql = "SELECT stringid, id, lang, componentid, original, master, local, timemodified, timecustomized, outdated, modified
 121                        FROM {tool_customlang} s
 122                       WHERE lang = ? AND componentid = ?
 123                    ORDER BY stringid";
 124              $current = $DB->get_records_sql($sql, array($lang, $component->id));
 125              $english = $stringman->load_component_strings($component->name, 'en', true, true);
 126              if ($lang == 'en') {
 127                  $master =& $english;
 128              } else {
 129                  $master = $stringman->load_component_strings($component->name, $lang, true, true);
 130              }
 131              $local = $stringman->load_component_strings($component->name, $lang, true, false);
 132  
 133              foreach ($english as $stringid => $stringoriginal) {
 134                  $stringmaster = isset($master[$stringid]) ? $master[$stringid] : null;
 135                  $stringlocal = isset($local[$stringid]) ? $local[$stringid] : null;
 136                  $now = time();
 137  
 138                  if (!is_null($progressbar)) {
 139                      $done++;
 140                      $donepercent = floor(min($done, self::ROUGH_NUMBER_OF_STRINGS) / self::ROUGH_NUMBER_OF_STRINGS * 100);
 141                      $progressbar->update_full($donepercent, $strinprogress);
 142                  }
 143  
 144                  if (isset($current[$stringid])) {
 145                      $needsupdate     = false;
 146                      $currentoriginal = $current[$stringid]->original;
 147                      $currentmaster   = $current[$stringid]->master;
 148                      $currentlocal    = $current[$stringid]->local;
 149  
 150                      if ($currentoriginal !== $stringoriginal or $currentmaster !== $stringmaster) {
 151                          $needsupdate = true;
 152                          $current[$stringid]->original       = $stringoriginal;
 153                          $current[$stringid]->master         = $stringmaster;
 154                          $current[$stringid]->timemodified   = $now;
 155                          $current[$stringid]->outdated       = 1;
 156                      }
 157  
 158                      if ($stringmaster !== $stringlocal) {
 159                          $needsupdate = true;
 160                          $current[$stringid]->local          = $stringlocal;
 161                          $current[$stringid]->timecustomized = $now;
 162                      }
 163  
 164                      if ($needsupdate) {
 165                          $DB->update_record('tool_customlang', $current[$stringid]);
 166                          continue;
 167                      }
 168  
 169                  } else {
 170                      $record                 = new stdclass();
 171                      $record->lang           = $lang;
 172                      $record->componentid    = $component->id;
 173                      $record->stringid       = $stringid;
 174                      $record->original       = $stringoriginal;
 175                      $record->master         = $stringmaster;
 176                      $record->timemodified   = $now;
 177                      $record->outdated       = 0;
 178                      if ($stringmaster !== $stringlocal) {
 179                          $record->local          = $stringlocal;
 180                          $record->timecustomized = $now;
 181                      } else {
 182                          $record->local          = null;
 183                          $record->timecustomized = null;
 184                      }
 185  
 186                      $DB->insert_record('tool_customlang', $record);
 187                  }
 188              }
 189          }
 190  
 191          if (!is_null($progressbar)) {
 192              $progressbar->update_full(100, get_string('checkoutdone', 'tool_customlang'));
 193          }
 194      }
 195  
 196      /**
 197       * Exports the translator database into disk files
 198       *
 199       * @param mixed $lang language code
 200       */
 201      public static function checkin($lang) {
 202          global $DB, $USER, $CFG;
 203          require_once($CFG->libdir.'/filelib.php');
 204  
 205          if ($lang !== clean_param($lang, PARAM_LANG)) {
 206              return false;
 207          }
 208  
 209          // get all customized strings from updated components
 210          $sql = "SELECT s.*, c.name AS component
 211                    FROM {tool_customlang} s
 212                    JOIN {tool_customlang_components} c ON s.componentid = c.id
 213                   WHERE s.lang = ?
 214                         AND (s.local IS NOT NULL OR s.modified = 1)
 215                ORDER BY componentid, stringid";
 216          $strings = $DB->get_records_sql($sql, array($lang));
 217  
 218          $files = array();
 219          foreach ($strings as $string) {
 220              if (!is_null($string->local)) {
 221                  $files[$string->component][$string->stringid] = $string->local;
 222              }
 223          }
 224  
 225          fulldelete(self::get_localpack_location($lang));
 226          foreach ($files as $component => $strings) {
 227              self::dump_strings($lang, $component, $strings);
 228          }
 229  
 230          $DB->set_field_select('tool_customlang', 'modified', 0, 'lang = ?', array($lang));
 231          $sm = get_string_manager();
 232          $sm->reset_caches();
 233      }
 234  
 235      /**
 236       * Returns full path to the directory where local packs are dumped into
 237       *
 238       * @param string $lang language code
 239       * @return string full path
 240       */
 241      protected static function get_localpack_location($lang) {
 242          global $CFG;
 243  
 244          return $CFG->langlocalroot.'/'.$lang.'_local';
 245      }
 246  
 247      /**
 248       * Writes strings into a local language pack file
 249       *
 250       * @param string $component the name of the component
 251       * @param array $strings
 252       */
 253      protected static function dump_strings($lang, $component, $strings) {
 254          global $CFG;
 255  
 256          if ($lang !== clean_param($lang, PARAM_LANG)) {
 257              debugging('Unable to dump local strings for non-installed language pack .'.s($lang));
 258              return false;
 259          }
 260          if ($component !== clean_param($component, PARAM_COMPONENT)) {
 261              throw new coding_exception('Incorrect component name');
 262          }
 263          if (!$filename = self::get_component_filename($component)) {
 264              debugging('Unable to find the filename for the component '.s($component));
 265              return false;
 266          }
 267          if ($filename !== clean_param($filename, PARAM_FILE)) {
 268              throw new coding_exception('Incorrect file name '.s($filename));
 269          }
 270          list($package, $subpackage) = core_component::normalize_component($component);
 271          $packageinfo = " * @package    $package";
 272          if (!is_null($subpackage)) {
 273              $packageinfo .= "\n * @subpackage $subpackage";
 274          }
 275          $filepath = self::get_localpack_location($lang);
 276          $filepath = $filepath.'/'.$filename;
 277          if (!is_dir(dirname($filepath))) {
 278              check_dir_exists(dirname($filepath));
 279          }
 280  
 281          if (!$f = fopen($filepath, 'w')) {
 282              debugging('Unable to write '.s($filepath));
 283              return false;
 284          }
 285          fwrite($f, <<<EOF
 286  <?php
 287  
 288  // This file is part of Moodle - http://moodle.org/
 289  //
 290  // Moodle is free software: you can redistribute it and/or modify
 291  // it under the terms of the GNU General Public License as published by
 292  // the Free Software Foundation, either version 3 of the License, or
 293  // (at your option) any later version.
 294  //
 295  // Moodle is distributed in the hope that it will be useful,
 296  // but WITHOUT ANY WARRANTY; without even the implied warranty of
 297  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 298  // GNU General Public License for more details.
 299  //
 300  // You should have received a copy of the GNU General Public License
 301  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 302  
 303  /**
 304   * Local language pack from $CFG->wwwroot
 305   *
 306  $packageinfo
 307   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 308   */
 309  
 310  defined('MOODLE_INTERNAL') || die();
 311  
 312  
 313  EOF
 314          );
 315  
 316          foreach ($strings as $stringid => $text) {
 317              if ($stringid !== clean_param($stringid, PARAM_STRINGID)) {
 318                  debugging('Invalid string identifier '.s($stringid));
 319                  continue;
 320              }
 321              fwrite($f, '$string[\'' . $stringid . '\'] = ');
 322              fwrite($f, var_export($text, true));
 323              fwrite($f, ";\n");
 324          }
 325          fclose($f);
 326          @chmod($filepath, $CFG->filepermissions);
 327      }
 328  
 329      /**
 330       * Returns the name of the file where the component's local strings should be exported into
 331       *
 332       * @param string $component normalized name of the component, eg 'core' or 'mod_workshop'
 333       * @return string|boolean filename eg 'moodle.php' or 'workshop.php', false if not found
 334       */
 335      protected static function get_component_filename($component) {
 336          if (is_null(self::$components)) {
 337              self::$components = self::list_components();
 338          }
 339          $return = false;
 340          foreach (self::$components as $legacy => $normalized) {
 341              if ($component === $normalized) {
 342                  $return = $legacy.'.php';
 343                  break;
 344              }
 345          }
 346          return $return;
 347      }
 348  
 349      /**
 350       * Returns the number of modified strings checked out in the translator
 351       *
 352       * @param string $lang language code
 353       * @return int
 354       */
 355      public static function get_count_of_modified($lang) {
 356          global $DB;
 357  
 358          return $DB->count_records('tool_customlang', array('lang'=>$lang, 'modified'=>1));
 359      }
 360  
 361      /**
 362       * Saves filter data into a persistant storage such as user session
 363       *
 364       * @see self::load_filter()
 365       * @param stdclass $data filter values
 366       * @param stdclass $persistant storage object
 367       */
 368      public static function save_filter(stdclass $data, stdclass $persistant) {
 369          if (!isset($persistant->tool_customlang_filter)) {
 370              $persistant->tool_customlang_filter = array();
 371          }
 372          foreach ($data as $key => $value) {
 373              if ($key !== 'submit') {
 374                  $persistant->tool_customlang_filter[$key] = serialize($value);
 375              }
 376          }
 377      }
 378  
 379      /**
 380       * Loads the previously saved filter settings from a persistent storage
 381       *
 382       * @see self::save_filter()
 383       * @param stdclass $persistant storage object
 384       * @return stdclass filter data
 385       */
 386      public static function load_filter(stdclass $persistant) {
 387          $data = new stdclass();
 388          if (isset($persistant->tool_customlang_filter)) {
 389              foreach ($persistant->tool_customlang_filter as $key => $value) {
 390                  $data->{$key} = unserialize($value);
 391              }
 392          }
 393          return $data;
 394      }
 395  }
 396  
 397  /**
 398   * Represents the action menu of the tool
 399   */
 400  class tool_customlang_menu implements renderable {
 401  
 402      /** @var menu items */
 403      protected $items = array();
 404  
 405      public function __construct(array $items = array()) {
 406          global $CFG;
 407  
 408          foreach ($items as $itemkey => $item) {
 409              $this->add_item($itemkey, $item['title'], $item['url'], empty($item['method']) ? 'post' : $item['method']);
 410          }
 411      }
 412  
 413      /**
 414       * Returns the menu items
 415       *
 416       * @return array (string)key => (object)[->(string)title ->(moodle_url)url ->(string)method]
 417       */
 418      public function get_items() {
 419          return $this->items;
 420      }
 421  
 422      /**
 423       * Adds item into the menu
 424       *
 425       * @param string $key item identifier
 426       * @param string $title localized action title
 427       * @param moodle_url $url action handler
 428       * @param string $method form method
 429       */
 430      public function add_item($key, $title, moodle_url $url, $method) {
 431          if (isset($this->items[$key])) {
 432              throw new coding_exception('Menu item already exists');
 433          }
 434          if (empty($title) or empty($key)) {
 435              throw new coding_exception('Empty title or item key not allowed');
 436          }
 437          $item = new stdclass();
 438          $item->title = $title;
 439          $item->url = $url;
 440          $item->method = $method;
 441          $this->items[$key] = $item;
 442      }
 443  }
 444  
 445  /**
 446   * Represents the translation tool
 447   */
 448  class tool_customlang_translator implements renderable {
 449  
 450      /** @const int number of rows per page */
 451      const PERPAGE = 100;
 452  
 453      /** @var int total number of the rows int the table */
 454      public $numofrows = 0;
 455  
 456      /** @var moodle_url */
 457      public $handler;
 458  
 459      /** @var string language code */
 460      public $lang;
 461  
 462      /** @var int page to display, starting with page 0 */
 463      public $currentpage = 0;
 464  
 465      /** @var array of stdclass strings to display */
 466      public $strings = array();
 467  
 468      /** @var stdclass */
 469      protected $filter;
 470  
 471      public function __construct(moodle_url $handler, $lang, $filter, $currentpage = 0) {
 472          global $DB;
 473  
 474          $this->handler      = $handler;
 475          $this->lang         = $lang;
 476          $this->filter       = $filter;
 477          $this->currentpage  = $currentpage;
 478  
 479          if (empty($filter) or empty($filter->component)) {
 480              // nothing to do
 481              $this->currentpage = 1;
 482              return;
 483          }
 484  
 485          list($insql, $inparams) = $DB->get_in_or_equal($filter->component, SQL_PARAMS_NAMED);
 486  
 487          $csql = "SELECT COUNT(*)";
 488          $fsql = "SELECT s.*, c.name AS component";
 489          $sql  = "  FROM {tool_customlang_components} c
 490                     JOIN {tool_customlang} s ON s.componentid = c.id
 491                    WHERE s.lang = :lang
 492                          AND c.name $insql";
 493  
 494          $params = array_merge(array('lang' => $lang), $inparams);
 495  
 496          if (!empty($filter->customized)) {
 497              $sql .= "   AND s.local IS NOT NULL";
 498          }
 499  
 500          if (!empty($filter->modified)) {
 501              $sql .= "   AND s.modified = 1";
 502          }
 503  
 504          if (!empty($filter->stringid)) {
 505              $sql .= "   AND s.stringid = :stringid";
 506              $params['stringid'] = $filter->stringid;
 507          }
 508  
 509          if (!empty($filter->substring)) {
 510              $sql .= "   AND (".$DB->sql_like('s.original', ':substringoriginal', false)." OR
 511                               ".$DB->sql_like('s.master', ':substringmaster', false)." OR
 512                               ".$DB->sql_like('s.local', ':substringlocal', false).")";
 513              $params['substringoriginal'] = '%'.$filter->substring.'%';
 514              $params['substringmaster']   = '%'.$filter->substring.'%';
 515              $params['substringlocal']    = '%'.$filter->substring.'%';
 516          }
 517  
 518          if (!empty($filter->helps)) {
 519              $sql .= "   AND ".$DB->sql_like('s.stringid', ':help', false); //ILIKE
 520              $params['help'] = '%\_help';
 521          } else {
 522              $sql .= "   AND ".$DB->sql_like('s.stringid', ':link', false, true, true); //NOT ILIKE
 523              $params['link'] = '%\_link';
 524          }
 525  
 526          $osql = " ORDER BY c.name, s.stringid";
 527  
 528          $this->numofrows = $DB->count_records_sql($csql.$sql, $params);
 529          $this->strings = $DB->get_records_sql($fsql.$sql.$osql, $params, ($this->currentpage) * self::PERPAGE, self::PERPAGE);
 530      }
 531  }


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