/** * Checks the decsep and thousandssep config strings are set correctly * * @link http://tracker.moodle.org/browse/MDL-31332 * @return bool check success flag */ protected function check_decsep_thousandssep() { $details = array(); $langnames = array(); $tree = mlang_tools::components_tree(array('component' => 'langconfig')); foreach ($tree as $branch => $languages) { $version = mlang_version::by_code($branch); foreach (array_keys($languages) as $language) { $langconfig = mlang_component::from_snapshot('langconfig', $language, $version); if ($langname = $langconfig->get_string('thislanguageint')) { $langnames[$language] = $langname->text; } else { $langnames[$language] = $language; } if ($decsep = $langconfig->get_string('decsep')) { $decsep = $decsep->text; } if ($thousandssep = $langconfig->get_string('thousandssep')) { $thousandssep = $thousandssep->text; } if (empty($decsep) and empty($thousandssep)) { $details[$language][$version->label] = 1; } else { if (empty($decsep) or empty($thousandssep)) { $details[$language][$version->label] = 2; } else { if ($decsep === $thousandssep) { $details[$language][$version->label] = 3; } } } } } ksort($details); foreach ($details as $language => $branches) { $msg = sprintf('Invalid decsep and/or thousandssep in %s {%s} at', $langnames[$language], $language); foreach ($branches as $branch => $severity) { $msg .= ' ' . $branch . str_repeat('!', $severity); } $this->output($msg, true); } if (empty($details)) { return 0; } return 1; }
function definition() { global $USER; $mform = $this->_form; // Commits filter $mform->addElement('header', 'logfiltercommits', get_string('logfiltercommits', 'local_amos')); // Committed after $mform->addElement('date_time_selector', 'committedafter', get_string('logfiltercommittedafter', 'local_amos'), array('optional' => true, 'timezone' => 'UTC', 'applydst' => false)); $mform->setDefault('committedafter', $USER->lastlogin); // Committed before $mform->addElement('date_time_selector', 'committedbefore', get_string('logfiltercommittedbefore', 'local_amos'), array('optional' => true, 'timezone' => 'UTC', 'applydst' => false)); $mform->setAdvanced('committedbefore'); // Committer $committers = get_users_by_capability(get_system_context(), 'local/amos:commit', user_picture::fields('u'), 'lastname, firstname'); $users = array('' => ''); foreach ($committers as $committer) { $users[$committer->id] = s(fullname($committer) . ' <' . $committer->email . '>'); } $usergrp[] = $mform->createElement('select', 'userid', '', $users); $usergrp[] = $mform->createElement('text', 'userinfo', ''); $mform->setType('userinfo', PARAM_NOTAGS); $mform->addGroup($usergrp, 'usergrp', get_string('logfilterusergrp', 'local_amos'), get_string('logfilterusergrpor', 'local_amos'), false); $mform->setAdvanced('usergrp'); // Source $sources = array('' => '', 'git' => get_string('logfiltersourcegit', 'local_amos'), 'amos' => get_string('logfiltersourceamos', 'local_amos'), 'revclean' => get_string('logfiltersourcerevclean', 'local_amos'), 'commitscript' => get_string('logfiltersourcecommitscript', 'local_amos'), 'fixdrift' => get_string('logfiltersourcefixdrift', 'local_amos'), 'bot' => get_string('logfiltersourcebot', 'local_amos')); $mform->addElement('select', 'source', get_string('logfiltersource', 'local_amos'), $sources); $mform->setAdvanced('source'); // Commit message $mform->addElement('text', 'commitmsg', get_string('logfiltercommitmsg', 'local_amos')); $mform->setAdvanced('commitmsg'); // Commit hash $mform->addElement('text', 'commithash', get_string('logfiltercommithash', 'local_amos')); $mform->setAdvanced('commithash'); // Strings filter $mform->addElement('header', 'logfilterstrings', get_string('logfilterstrings', 'local_amos')); // Branch $branchgrp = array(); foreach (mlang_version::list_all() as $version) { $branchgrp[] = $mform->createElement('checkbox', $version->code, '', $version->label); } $mform->addGroup($branchgrp, 'branch', get_string('logfilterbranch', 'local_amos'), ' '); foreach (mlang_version::list_all() as $version) { if ($version->current) { $mform->setDefault('branch[' . $version->code . ']', 1); } } // Lang $langgrp = array(); $langgrp[] = $mform->createElement('checkbox', 'langenabled', '', get_string('enable')); $langgrp[] = $mform->createElement('select', 'lang', '', mlang_tools::list_languages(), array('multiple' => 'multiple', 'size' => 5)); $mform->addGroup($langgrp, 'langgrp', get_string('logfilterlang', 'local_amos'), '<br />', false); $mform->setDefault('lang', array('en', current_language())); $mform->disabledIf('lang', 'langenabled'); // does not seem to work for multiple selects :-/ $mform->setAdvanced('langgrp'); // Components $optionscore = array(); $optionsstandard = array(); $optionscontrib = array(); $standard = array(); foreach (local_amos_standard_plugins() as $plugins) { $standard = array_merge($standard, $plugins); } foreach (mlang_tools::list_components() as $componentname => $undefined) { if (isset($standard[$componentname])) { if ($standard[$componentname] === 'core' or substr($standard[$componentname], 0, 5) === 'core_') { $optionscore[$componentname] = $standard[$componentname]; } else { $optionsstandard[$componentname] = $standard[$componentname]; } } else { $optionscontrib[$componentname] = $componentname; } } asort($optionscore); asort($optionsstandard); asort($optionscontrib); $options = array(get_string('pluginclasscore', 'local_amos') => $optionscore, get_string('pluginclassstandard', 'local_amos') => $optionsstandard, get_string('pluginclassnonstandard', 'local_amos') => $optionscontrib); $componentgrp = array(); $componentgrp[] = $mform->createElement('checkbox', 'componentenabled', '', get_string('enable')); $componentgrp[] = $mform->createElement('selectgroups', 'component', '', $options, array('multiple' => 'multiple', 'size' => 5)); $mform->addGroup($componentgrp, 'componentgrp', get_string('logfiltercomponent', 'local_amos'), '<br />', false); $mform->disabledIf('component', 'componentenabled'); // does not seem to work for multiple selects :-/ $mform->setAdvanced('componentgrp'); // Stringid $mform->addElement('text', 'stringid', get_string('logfilterstringid', 'local_amos')); $mform->setType('stringid', PARAM_STRINGID); $mform->setAdvanced('stringid'); // Submit $mform->addElement('submit', 'submit', get_string('logfiltershow', 'local_amos')); $mform->closeHeaderBefore('submit'); }
*/ require_once dirname(dirname(dirname(__FILE__))) . '/config.php'; require_once dirname(__FILE__) . '/locallib.php'; require_once dirname(__FILE__) . '/mlanglib.php'; require_once dirname(__FILE__) . '/execute_form.php'; require_login(SITEID, false); require_capability('local/amos:execute', get_system_context()); require_capability('local/amos:stage', get_system_context()); $PAGE->set_pagelayout('standard'); $PAGE->set_url('/local/amos/execute.php'); navigation_node::override_active_url(new moodle_url('/local/amos/stage.php')); $PAGE->set_title('AMOS ' . get_string('scriptexecute', 'local_amos')); $PAGE->set_heading('AMOS ' . get_string('scriptexecute', 'local_amos')); $executeform = new local_amos_execute_form(null, local_amos_execute_options()); if ($data = $executeform->get_data()) { $version = mlang_version::by_code($data->version); $stage = mlang_persistent_stage::instance_for_user($USER->id, sesskey()); $instructions = mlang_tools::extract_script_from_text($data->script); if (!empty($instructions)) { foreach ($instructions as $instruction) { $changes = mlang_tools::execute($instruction, $version); if ($changes instanceof mlang_stage) { foreach ($changes->get_iterator() as $component) { $stage->add($component, true); } $changes->clear(); } elseif ($changes < 0) { throw new moodle_exception('error_during_amoscript_execution', 'local_amos', '', null, $changes); } unset($changes); }
require_once dirname(__FILE__) . '/locallib.php'; require_once dirname(__FILE__) . '/mlanglib.php'; require_once dirname(__FILE__) . '/merge_form.php'; require_login(SITEID, false); require_capability('local/amos:commit', get_system_context()); // for langpack maintainers only $PAGE->set_pagelayout('standard'); $PAGE->set_url('/local/amos/merge.php'); navigation_node::override_active_url(new moodle_url('/local/amos/stage.php')); $PAGE->set_title('AMOS ' . get_string('merge', 'local_amos')); $PAGE->set_heading('AMOS ' . get_string('merge', 'local_amos')); $mergeform = new local_amos_merge_form(null, local_amos_merge_options()); if ($data = $mergeform->get_data()) { $stage = mlang_persistent_stage::instance_for_user($USER->id, sesskey()); $sourceversion = mlang_version::by_code($data->sourceversion); $targetversion = mlang_version::by_code($data->targetversion); if (is_null($sourceversion) or is_null($targetversion)) { notice('Invalid version selected', new moodle_url('/local/amos/stage.php')); } $tree = mlang_tools::components_tree(array('branch' => $sourceversion->code, 'lang' => $data->language)); $sourcecomponentnames = array_keys(reset(reset($tree))); unset($tree); foreach ($sourcecomponentnames as $sourcecomponentname) { // get a snapshot of both components and merge source into target $sourcecomponent = mlang_component::from_snapshot($sourcecomponentname, $data->language, $sourceversion); $targetcomponent = mlang_component::from_snapshot($sourcecomponent->name, $sourcecomponent->lang, $targetversion); mlang_tools::merge($sourcecomponent, $targetcomponent); $sourcecomponent->clear(); // keep just strings that are defined in english $englishcomponent = mlang_component::from_snapshot($sourcecomponent->name, 'en', $targetversion); $targetcomponent->intersect($englishcomponent);
public function test_php_parser_security_variable_expansion() { // security issues $parser = mlang_parser_factory::get_parser('php'); $data = '<?php $string[\'dbpass\'] = $CFG->dbpass;'; // this would give the user sensitive data about AMOS portal $component = new mlang_component('test', 'xx', mlang_version::by_branch('MOODLE_20_STABLE')); $this->expectException('mlang_parser_exception'); $parser->parse($data, $component); }
require_once dirname(__FILE__) . '/diff_form.php'; require_login(SITEID, false); require_capability('local/amos:stage', get_system_context()); $PAGE->set_pagelayout('standard'); $PAGE->set_url('/local/amos/diff.php'); navigation_node::override_active_url(new moodle_url('/local/amos/stage.php')); $PAGE->set_title('AMOS ' . get_string('diff', 'local_amos')); $PAGE->set_heading('AMOS ' . get_string('diff', 'local_amos')); $diffform = new local_amos_diff_form(null, local_amos_diff_options()); if ($data = $diffform->get_data()) { if ($data->versiona == $data->versionb) { notice(get_string('nodiffs', 'local_amos'), new moodle_url('/local/amos/stage.php')); } $stage = mlang_persistent_stage::instance_for_user($USER->id, sesskey()); $versiona = mlang_version::by_code($data->versiona); $versionb = mlang_version::by_code($data->versionb); $tree = mlang_tools::components_tree(array('branch' => $versiona->code, 'lang' => 'en')); $componentnames = array_keys($tree[$versiona->code]['en']); $total = count($componentnames); unset($tree); echo $OUTPUT->header(); $progressbar = new progress_bar(); $progressbar->create(); // prints the HTML code of the progress bar // we may need a bit of extra execution time and memory here @set_time_limit(HOURSECS); raise_memory_limit(MEMORY_EXTRA); // number of differences $num = 0; foreach ($componentnames as $i => $componentname) { $progressbar->update($i, $total, get_string('diffprogress', 'local_amos'));
* @subpackage amos * @copyright 2011 David Mudrak <*****@*****.**> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ define('CLI_SCRIPT', true); require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php'; require_once $CFG->dirroot . '/local/amos/cli/config.php'; require_once $CFG->dirroot . '/local/amos/mlanglib.php'; require_once $CFG->libdir . '/clilib.php'; list($options, $unrecognized) = cli_get_params(array('from' => false, 'to' => false, 'help' => false), array('h' => 'help')); if ($options['help'] or !$options['from'] or !$options['to']) { echo 'Usage: ' . basename(__FILE__) . ' --from=MOODLE_XX_STABLE --to=MOODLE_YY_STABLE' . PHP_EOL; exit(1); } $fromversion = mlang_version::by_branch($options['from']); $toversion = mlang_version::by_branch($options['to']); if (is_null($fromversion) or is_null($toversion)) { echo 'Unknown branch' . PHP_EOL; exit(2); } // Make sure that this is not executed by mistake if ($DB->record_exists('amos_repository', array('branch' => $toversion->code))) { echo 'The target branch already exists' . PHP_EOL; exit(3); } // Let us get the list of commits that change strings on the given branch $sql = "SELECT DISTINCT commitid\n FROM {amos_repository}\n WHERE branch = ?\n ORDER BY commitid"; $rs = $DB->get_recordset_sql($sql, array($fromversion->code)); foreach ($rs as $record) { $commitid = $record->commitid; echo 'cloning changes introduced by commit ' . $commitid . ' ... ';
header('HTTP/1.1 403 Forbidden'); die; } if (!confirm_sesskey()) { header('HTTP/1.1 403 Forbidden'); die; } $stringid = optional_param('stringid', null, PARAM_ALPHANUMEXT); $text = optional_param('text', null, PARAM_RAW); if (is_null($stringid) or is_null($text)) { header('HTTP/1.1 400 Bad Request'); die; } list($lang, $originalid, $translationid) = local_amos_translator::decode_identifier($stringid); $record = $DB->get_record('amos_repository', array('id' => $originalid), 'id,stringid,component,branch', MUST_EXIST); $version = mlang_version::by_code($record->branch); $component = new mlang_component($record->component, $lang, $version); if ($version->code < mlang_version::MOODLE_20) { header('HTTP/1.1 400 Bad Request'); die; } $string = new mlang_string($record->stringid, $text); $string->clean_text(); $component->add_string($string); $stage = mlang_persistent_stage::instance_for_user($USER->id, sesskey()); $stage->add($component, true); $stage->store(); mlang_stash::autosave($stage); header('Content-Type: application/json; charset: utf-8'); $response = new stdclass(); $response->text = local_amos_renderer::add_breaks(s($string->text));
The file is directly included into the PHP processor. Make sure to review the file for a malicious contents before you import it via this script. EOF; if ($options['help'] or empty($options['message']) or empty($unrecognized)) { echo $usage . PHP_EOL; exit(1); } $filepath = $unrecognized[0]; if (!is_readable($filepath)) { echo 'File not readable' . PHP_EOL; echo $usage . PHP_EOL; exit(2); } $version = mlang_version::by_branch($options['version']); if (is_null($version)) { echo 'Invalid version' . PHP_EOL; exit(3); } $component = mlang_component::from_phpfile($filepath, $options['lang'], $version, $options['timemodified'], $options['name'], (int) $options['format']); fputs(STDOUT, "{$component->name} {$component->version->label} {$component->lang}" . PHP_EOL); $stage = new mlang_stage(); $stage->add($component); $stage->rebase(null, true, $options['timemodified']); if (!$stage->has_component()) { echo 'No strings found (after rebase)' . PHP_EOL; exit(4); } foreach ($stage->get_iterator() as $component) { foreach ($component->get_iterator() as $string) {
/** * Fetches the required commits from the repository * * @param array $filter allows to filter commits */ public function __construct(array $filter = array()) { global $DB; // we can not use limits inside subquery so firstly let us get commits we are interested in $params = array(); $where = array(); $getsql = "SELECT id"; $countsql = "SELECT COUNT(*)"; $sql = " FROM {amos_commits}"; if (!empty($filter['userid'])) { $where['userid'] = "userid = ?"; $params[] = $filter['userid']; } if (!empty($filter['userinfo'])) { $where['userinfo'] = $DB->sql_like('userinfo', '?', false, false); $params[] = '%' . $filter['userinfo'] . '%'; } if (!empty($where['userinfo']) and !empty($where['userid'])) { $where['user'] = '******' . $where['userid'] . ') OR (' . $where['userinfo'] . ')'; unset($where['userinfo']); unset($where['userid']); } if (!empty($filter['committedafter'])) { $where['committedafter'] = 'timecommitted >= ?'; $params[] = $filter['committedafter']; } if (!empty($filter['committedbefore'])) { $where['committedbefore'] = 'timecommitted < ?'; $params[] = $filter['committedbefore']; } if (!empty($filter['source'])) { $where['source'] = 'source = ?'; $params[] = $filter['source']; } if (!empty($filter['commitmsg'])) { $where['commitmsg'] = $DB->sql_like('commitmsg', '?', false, false); $params[] = '%' . $filter['commitmsg'] . '%'; } if (!empty($filter['commithash'])) { $where['commithash'] = $DB->sql_like('commithash', '?', false, false); $params[] = $filter['commithash'] . '%'; } if ($where) { $where = '(' . implode(') AND (', $where) . ')'; $sql .= " WHERE {$where}"; } $ordersql = " ORDER BY timecommitted DESC, id DESC"; $this->numofcommits = $DB->count_records_sql($countsql . $sql, $params); $commitids = $DB->get_records_sql($getsql . $sql . $ordersql, $params, 0, self::LIMITCOMMITS); if (empty($commitids)) { // nothing to load return; } // now get all repository records modified by these commits // and optionally filter them if requested $params = array(); list($csql, $params) = $DB->get_in_or_equal(array_keys($commitids)); if (!empty($filter['branch'])) { list($branchsql, $branchparams) = $DB->get_in_or_equal(array_keys($filter['branch'])); } else { $branchsql = ''; } if (!empty($filter['lang'])) { list($langsql, $langparams) = $DB->get_in_or_equal($filter['lang']); } else { $langsql = ''; } if (!empty($filter['component'])) { list($componentsql, $componentparams) = $DB->get_in_or_equal($filter['component']); } else { $componentsql = ''; } $countsql = "SELECT COUNT(r.id)"; $getsql = "SELECT r.id, c.source, c.timecommitted, c.commitmsg, c.commithash, c.userid, c.userinfo,\n r.commitid, r.branch, r.lang, r.component, r.stringid, r.text, r.timemodified, r.deleted"; $sql = " FROM {amos_commits} c\n JOIN {amos_repository} r ON (c.id = r.commitid)\n WHERE c.id {$csql}"; if ($branchsql) { $sql .= " AND r.branch {$branchsql}"; $params = array_merge($params, $branchparams); } if ($langsql) { $sql .= " AND r.lang {$langsql}"; $params = array_merge($params, $langparams); } if ($componentsql) { $sql .= " AND r.component {$componentsql}"; $params = array_merge($params, $componentparams); } if (!empty($filter['stringid'])) { $sql .= " AND r.stringid = ?"; $params[] = $filter['stringid']; } $ordersql = " ORDER BY c.timecommitted DESC, c.id DESC, r.branch DESC, r.lang, r.component, r.stringid"; $this->numofstrings = $DB->count_records_sql($countsql . $sql, $params); $rs = $DB->get_recordset_sql($getsql . $sql . $ordersql, $params); $numofcommits = 0; foreach ($rs as $r) { if (!isset($this->commits[$r->commitid])) { if ($numofcommits == self::LIMITCOMMITS) { // we already have enough break; } $commit = new stdclass(); $commit->id = $r->commitid; $commit->source = $r->source; $commit->timecommitted = $r->timecommitted; $commit->commitmsg = $r->commitmsg; $commit->commithash = $r->commithash; $commit->userid = $r->userid; $commit->userinfo = $r->userinfo; $commit->strings = array(); $this->commits[$r->commitid] = $commit; $numofcommits++; } $string = new stdclass(); $string->branch = mlang_version::by_code($r->branch)->label; $string->component = $r->component; $string->lang = $r->lang; $string->stringid = $r->stringid; $string->deleted = $r->deleted; $this->commits[$r->commitid]->strings[] = $string; } $rs->close(); }
define('AJAX_SCRIPT', true); require_once dirname(dirname(dirname(__FILE__))) . '/config.php'; //require_once(dirname(__FILE__).'/locallib.php'); require_once dirname(__FILE__) . '/mlanglib.php'; require_login(SITEID, false); if (!has_capability('local/amos:stage', get_system_context())) { header('HTTP/1.1 403 Forbidden'); die; } if (!confirm_sesskey()) { header('HTTP/1.1 403 Forbidden'); die; } $name = required_param('component', PARAM_ALPHANUMEXT); $branch = required_param('branch', PARAM_INT); $lang = required_param('lang', PARAM_ALPHANUMEXT); $unstage = required_param('unstage', PARAM_STRINGID); $response = new stdClass(); $response->success = true; $response->error = ''; $stage = mlang_persistent_stage::instance_for_user($USER->id, sesskey()); $component = $stage->get_component($name, $lang, mlang_version::by_code($branch)); if ($component) { $component->unlink_string($unstage); $stage->store(); } else { $response->success = false; $response->error = 'Unable to get load component'; } header('Content-Type: application/json; charset: utf-8'); echo json_encode($response);
public function test_stage_propagate() { $version20 = mlang_version::by_branch('MOODLE_20_STABLE'); $version21 = mlang_version::by_branch('MOODLE_21_STABLE'); $version22 = mlang_version::by_branch('MOODLE_22_STABLE'); $component20en = new mlang_component('admin', 'en', $version20); $component20en->add_string(new mlang_string('foo1', 'Bar1')); $component20en->add_string(new mlang_string('foo2', 'Bar2')); $component20cs = new mlang_component('admin', 'cs', $version20); $component20cs->add_string(new mlang_string('foo1', 'TranslatedOldBar1')); $component21en = new mlang_component('admin', 'en', $version21); $component21en->add_string(new mlang_string('foo1', 'Bar1')); $component21en->add_string(new mlang_string('foo2', 'Bar2')); $component21en->add_string(new mlang_string('foo3', 'Bar3')); $component22en = new mlang_component('admin', 'en', $version22); $component22en->add_string(new mlang_string('foo1', 'Bar1')); $component22en->add_string(new mlang_string('foo2', 'Bar2')); $component22en->add_string(new mlang_string('foo3', 'NewBar3')); $stage = new mlang_stage(); $stage->add($component20en); $stage->add($component20cs); $stage->add($component21en); $stage->add($component22en); $stage->commit('Initial strings', array('source' => 'unittest'), true); $component20en->clear(); $component21en->clear(); $component22en->clear(); unset($stage); // simple usage - the user translated a string on 2.1 and want it being applied to 2.2, too $stage = new mlang_stage(); $component21cs = new mlang_component('admin', 'cs', $version21); $component21cs->add_string(new mlang_string('foo1', 'TranslatedBar1')); $stage->add($component21cs); $component21cs->clear(); $this->assertEqual($stage->propagate(array($version22)), 1); $propagatedcomponent = $stage->get_component('admin', 'cs', $version22); $this->assertNotNull($propagatedcomponent, 'The component "admin" must exist on ' . $version22->label); $this->assertTrue($propagatedcomponent->has_string('foo1')); $propagatedstring = $propagatedcomponent->get_string('foo1'); $this->assertTrue($propagatedstring->text, 'TranslatedBar1'); $stage->clear(); // the change is not propagated if the changed string is staged several times and the values // are different $stage = new mlang_stage(); $component20cs = new mlang_component('admin', 'cs', $version20); $component20cs->add_string(new mlang_string('foo2', 'TranslatedOldBar2')); $component21cs = new mlang_component('admin', 'cs', $version21); $component21cs->add_string(new mlang_string('foo2', 'TranslatedBar2')); $stage->add($component20cs); $stage->add($component21cs); $component20cs->clear(); $component21cs->clear(); $this->assertEqual($stage->propagate(array($version20, $version21, $version22)), 0); $this->assertEqual($stage->get_component('admin', 'cs', $version20)->get_string('foo2')->text, 'TranslatedOldBar2'); $this->assertEqual($stage->get_component('admin', 'cs', $version21)->get_string('foo2')->text, 'TranslatedBar2'); $this->assertNull($stage->get_component('admin', 'cs', $version22)); $stage->clear(); // but the change is propagated if the changed string is staged several times and the values // are the same $stage = new mlang_stage(); $component20cs = new mlang_component('admin', 'cs', $version20); $component20cs->add_string(new mlang_string('foo2', 'TranslatedBar2')); $component21cs = new mlang_component('admin', 'cs', $version21); $component21cs->add_string(new mlang_string('foo2', 'TranslatedBar2')); $stage->add($component20cs); $stage->add($component21cs); $component20cs->clear(); $component21cs->clear(); $this->assertEqual($stage->propagate(array($version20, $version21, $version22)), 1); $this->assertEqual($stage->get_component('admin', 'cs', $version22)->get_string('foo2')->text, 'TranslatedBar2'); $this->assertEqual($stage->get_component('admin', 'cs', $version21)->get_string('foo2')->text, 'TranslatedBar2'); $this->assertEqual($stage->get_component('admin', 'cs', $version20)->get_string('foo2')->text, 'TranslatedBar2'); $stage->clear(); // the staged string is propagated to another branch only if the English originals match // in the following test, the 2.1 translation of foo3 should not propagate to neither 2.0 // (because the string does not exist there) not 2.2 (because the English originals differ) $stage = new mlang_stage(); $component21cs = new mlang_component('admin', 'cs', $version21); $component21cs->add_string(new mlang_string('foo3', 'TranslatedBar3')); $stage->add($component21cs); $component21cs->clear(); $this->assertEqual($stage->propagate(array($version20, $version21, $version22)), 0); $this->assertNull($stage->get_component('admin', 'cs', $version20)); $this->assertNull($stage->get_component('admin', 'cs', $version22)); $stage->clear(); }
* Register new language * * @package local-amos * @copyright 2010 David Mudrak <*****@*****.**> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php'; require_once dirname(dirname(__FILE__)) . '/mlanglib.php'; require_once dirname(__FILE__) . '/newlanguage_form.php'; require_login(SITEID, false); require_capability('local/amos:manage', get_system_context()); $PAGE->set_pagelayout('standard'); $PAGE->set_url('/local/amos/admin/newlanguage.php'); $PAGE->set_title('AMOS ' . get_string('newlanguage', 'local_amos')); $PAGE->set_heading('AMOS ' . get_string('newlanguage', 'local_amos')); $form = new local_amos_newlanguage_form(); if ($data = $form->get_data()) { $component = new mlang_component('langconfig', $data->langcode, mlang_version::by_code(mlang_version::MOODLE_22)); $data->langname = mlang_string::fix_syntax($data->langname); $data->langnameint = mlang_string::fix_syntax($data->langnameint); $component->add_string(new mlang_string('thislanguage', $data->langname)); $component->add_string(new mlang_string('thislanguageint', $data->langnameint)); $stage = mlang_persistent_stage::instance_for_user($USER->id, sesskey()); $stage->add($component); $stage->store(); redirect(new moodle_url('/local/amos/stage.php')); } /// Output starts here echo $OUTPUT->header(); $form->display(); echo $OUTPUT->footer();
if (!empty($submit)) { require_sesskey(); $stage = mlang_persistent_stage::instance_for_user($USER->id, sesskey()); $stash = mlang_stash::instance_from_stage($stage, $stage->userid); $stash->push(); redirect(new moodle_url('/local/amos/stash.php', array('sesskey' => sesskey(), 'submit' => $stash->id))); } if (!empty($propagate)) { require_sesskey(); $stage = mlang_persistent_stage::instance_for_user($USER->id, sesskey()); $ver = optional_param('ver', array(), PARAM_INT); $num = null; if (!empty($ver) and is_array($ver)) { $versions = array(); foreach ($ver as $versioncode) { $versions[] = mlang_version::by_code($versioncode); } if ($versions) { $num = $stage->propagate($versions); $stage->store(); } } if (is_null($num)) { redirect($PAGE->url); } else { redirect(new moodle_url($PAGE->url, array('justpropagated' => $num))); } } $output = $PAGE->get_renderer('local_amos'); // make sure that USER contains sesskey property $sesskey = sesskey();
define('CLI_SCRIPT', true); require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php'; require_once $CFG->dirroot . '/local/amos/cli/config.php'; require_once $CFG->dirroot . '/local/amos/mlanglib.php'; // Let us get an information about existing components $sql = "SELECT branch,lang,component,COUNT(stringid) AS numofstrings\n FROM {amos_repository}\n WHERE deleted=0\n GROUP BY branch,lang,component\n ORDER BY branch,lang,component"; $rs = $DB->get_recordset_sql($sql); $tree = array(); // [branch][language][component] => numofstrings foreach ($rs as $record) { $tree[$record->branch][$record->lang][$record->component] = $record->numofstrings; } $rs->close(); remove_dir(AMOS_EXPORT_DIR, true); foreach ($tree as $vercode => $languages) { $version = mlang_version::by_code($vercode); foreach ($languages as $langcode => $components) { if ($langcode == 'en') { continue; } foreach ($components as $componentname => $unused) { $component = mlang_component::from_snapshot($componentname, $langcode, $version); if ($component->has_string()) { $file = AMOS_EXPORT_DIR . '/' . $version->dir . '/' . $langcode . '/' . $component->get_phpfile_location(false); if (!file_exists(dirname($file))) { mkdir(dirname($file), 0755, true); } echo "{$file}\n"; $component->export_phpfile($file); } $component->clear();
* @package local * @subpackage amos * @copyright 2011 David Mudrak <*****@*****.**> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ define('CLI_SCRIPT', true); require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php'; require_once $CFG->dirroot . '/local/amos/cli/config.php'; require_once $CFG->dirroot . '/local/amos/mlanglib.php'; require_once $CFG->dirroot . '/local/amos/locallib.php'; require_once $CFG->libdir . '/clilib.php'; list($options, $unrecognized) = cli_get_params(array('execute' => false)); $plugins = local_amos_standard_plugins(); $stage = new mlang_stage(); foreach ($plugins as $versionnumber => $plugintypes) { $version = mlang_version::by_dir($versionnumber); if ($version->branch == 'MOODLE_23_STABLE') { $gitbranch = 'origin/master'; } else { $gitbranch = 'origin/' . $version->branch; } foreach ($plugintypes as $legacyname => $frankenstylename) { // moodle.org was replaced with a local plugin and strings were dropped from 2.0 and 2.1 if ($legacyname == 'moodle.org') { continue; } // prepare an empty component containing the fixes $fixcomponent = new mlang_component($legacyname, 'en', $version); // get the most recent snapshot from the AMOS repository $amoscomponent = mlang_component::from_snapshot($legacyname, 'en', $version); // get the location of the plugin
// whole file removal - xxx what can be done? :-/ continue; } // dump the given revision of the file to a temporary area $checkout = $commithash . '_' . str_replace('/', '_', $file); if (in_array($checkout, $MLANG_BROKEN_CHECKOUTS)) { fputs(STDERR, "BROKEN {$checkout}\n"); continue; } $checkout = $tmp . '/' . $checkout; exec(AMOS_PATH_GIT . " show {$commithash}:{$file} > {$checkout}"); // push the string on all branches where the English original is currently (or has ever been) defined // note that all English strings history must already be registered in AMOS repository // pushing into Moodle 1.x branches only to prevent conflicts with translations done via web foreach (array('MOODLE_19_STABLE') as $branch) { $version = mlang_version::by_branch($branch); // get the translated strings from PHP file - the lang repository in in 1.x format $component = mlang_component::from_phpfile($checkout, $langcode, $version, $timemodified, mlang_component::name_from_filename($file), 1); $encomponent = mlang_component::from_snapshot($component->name, 'en', $version, $timemodified); // keep just those defined in English on that branch - this is where we are reconstruct branching of lang packs. // langconfig.php is not compared with English because it may contain extra string like parentlanguage. if ($component->name !== 'langconfig') { $component->intersect($encomponent); } elseif ($version->code >= mlang_version::MOODLE_20) { if ($parentlanguage = $component->get_string('parentlanguage')) { if (substr($parentlanguage->text, -5) == '_utf8') { $parentlanguage->text = substr($parentlanguage->text, 0, -5); } } } $stage->add($component);
/** * Renders the stage * * @param local_amos_stage $stage * @return string */ protected function render_local_amos_stage(local_amos_stage $stage) { global $CFG; $table = new html_table(); $table->id = 'amosstage'; $table->head = array(get_string('stagestring', 'local_amos'), get_string('stageoriginal', 'local_amos'), get_string('stagelang', 'local_amos'), get_string('stagetranslation', 'local_amos') . $this->help_icon('stagetranslation', 'local_amos')); $table->colclasses = array('stringinfo', 'original', 'lang', 'translation'); $standard = array(); foreach (local_amos_standard_plugins() as $plugins) { $standard = array_merge($standard, $plugins); } $committable = 0; foreach ($stage->strings as $string) { $cells = array(); // string identification if (isset($standard[$string->component])) { $componentname = $standard[$string->component]; } else { $componentname = $string->component; } $stringinfo = html_writer::tag('span', $string->version, array('class' => 'version')); $stringinfo .= ' [' . html_writer::tag('span', $string->stringid, array('class' => 'stringid')) . ',' . html_writer::tag('span', $componentname, array('class' => 'component')) . ']'; $cells[0] = new html_table_cell($stringinfo); // original of the string $cells[1] = new html_table_cell(html_writer::tag('div', self::add_breaks(s($string->original)), array('class' => 'preformatted'))); // the language in which the original is displayed $cells[2] = new html_table_cell($string->language); // the current and the new translation $unstageurl = new moodle_url('/local/amos/stage.php', array('unstage' => $string->stringid, 'component' => $string->component, 'branch' => $string->branch, 'lang' => $string->language)); $unstagebutton = $this->single_button($unstageurl, get_string('unstage', 'local_amos'), 'post', array('class' => 'singlebutton protected unstagebutton')); if ($string->deleted) { // removal of the string $t = self::add_breaks(s($string->current)); $t = html_writer::tag('div', $t, array('class' => 'preformatted')); $cells[3] = new html_table_cell($t . $unstagebutton); if ($string->committable) { $committable++; $cells[3]->attributes['class'] .= 'committable removal'; } else { $cells[3]->attributes['class'] .= 'uncommittable removal'; } } else { if (trim($string->current) === trim($string->new)) { // no difference $t = self::add_breaks(s($string->current)); $t = html_writer::tag('div', $t, array('class' => 'preformatted')); $cells[3] = new html_table_cell($t . $unstagebutton); $cells[3]->attributes['class'] .= ' uncommittable nodiff'; } else { if (is_null($string->current)) { // new translation $t = $t = self::add_breaks(s($string->new)); $t = html_writer::tag('div', $t, array('class' => 'preformatted')); $cells[3] = new html_table_cell($t . $unstagebutton); if ($string->committable) { $cells[3]->attributes['class'] .= ' committable new'; $committable++; } if (!$string->committable) { $cells[3]->attributes['class'] .= ' uncommittable new'; } } else { // there is a difference $c = s($string->current); $n = s($string->new); $x1 = explode(' ', $c); $x2 = explode(' ', $n); $t = ''; $diff = local_amos_simplediff($x1, $x2); $numd = 0; $numi = 0; foreach ($diff as $k) { // $diff is a sequence of chunks (words) $k if (is_array($k)) { if (!empty($k['d'])) { $kd = implode(' ', $k['d']); if (!empty($kd)) { $t .= '<del>' . $kd . '</del> '; $numd += count($k['d']); } } if (!empty($k['i'])) { $ki = implode(' ', $k['i']); if (!empty($ki)) { $t .= '<ins>' . $ki . '</ins> '; $numi += count($k['i']); } } } else { $t .= $k . ' '; } } if ($numi == 0 or $numd == 0 or $numd == 1 and $numi == 1) { $cstyle = 'display:none;'; $nstyle = 'display:none;'; $tstyle = 'display:block;'; } else { $cstyle = 'display:block;'; $nstyle = 'display:block;'; $tstyle = 'display:none;'; } $n = html_writer::tag('ins', $n); $n = html_writer::tag('div', self::add_breaks($n), array('class' => 'preformatted stringtext new', 'style' => $nstyle)); $c = html_writer::tag('del', $c); $c = html_writer::tag('div', self::add_breaks($c), array('class' => 'preformatted stringtext current', 'style' => $cstyle)); $t = html_writer::tag('div', self::add_breaks($t), array('class' => 'preformatted stringtext diff', 'style' => $tstyle)); $difflink = html_writer::tag('div', '', array('class' => 'diffmode')); $cells[3] = new html_table_cell($difflink . $n . $c . $t . $unstagebutton); if ($string->committable) { $cells[3]->attributes['class'] .= ' committable diff'; $committable++; } if (!$string->committable) { $cells[3]->attributes['class'] .= ' uncommittable diff'; } } } } $row = new html_table_row($cells); $table->data[] = $row; } $table = html_writer::table($table); $propagateform = ''; $propagateform .= html_writer::empty_tag('input', array('name' => 'sesskey', 'value' => sesskey(), 'type' => 'hidden')); $propagateform .= html_writer::empty_tag('input', array('name' => 'propagate', 'value' => 1, 'type' => 'hidden')); foreach (mlang_version::list_all() as $version) { if ($version->code < 2000) { continue; } $checkbox = html_writer::checkbox('ver[]', $version->code, true, $version->label); $propagateform .= html_writer::tag('div', $checkbox, array('class' => 'labelled_checkbox')); } $propagateform .= html_writer::empty_tag('input', array('value' => get_string('propagaterun', 'local_amos'), 'type' => 'submit')); $propagateform = html_writer::tag('div', $propagateform); $propagateform = html_writer::tag('form', $propagateform, array('method' => 'post', 'action' => $CFG->wwwroot . '/local/amos/stage.php')); $propagateform .= html_writer::tag('legend', get_string('propagate', 'local_amos') . $this->help_icon('propagate', 'local_amos')); $propagateform = html_writer::tag('fieldset', $propagateform, array('class' => 'propagateformwrapper protected')); $commitform = html_writer::label(get_string('commitmessage', 'local_amos'), 'commitmessage', false); $commitform .= html_writer::empty_tag('img', array('src' => $this->pix_url('req'), 'title' => 'Required', 'alt' => 'Required', 'class' => 'req')); $commitform .= html_writer::empty_tag('br'); $commitform .= html_writer::tag('textarea', s($stage->presetmessage), array('id' => 'commitmessage', 'name' => 'message')); $commitform .= html_writer::empty_tag('input', array('name' => 'sesskey', 'value' => sesskey(), 'type' => 'hidden')); $button = html_writer::empty_tag('input', array('value' => get_string('commitbutton', 'local_amos'), 'type' => 'submit')); $button = html_writer::tag('div', $button); $commitform = html_writer::tag('div', $commitform . $button); $commitform = html_writer::tag('form', $commitform, array('method' => 'post', 'action' => $CFG->wwwroot . '/local/amos/stage.php')); $commitform .= html_writer::tag('legend', get_string('commitstage', 'local_amos') . $this->help_icon('commitstage', 'local_amos')); $commitform = html_writer::tag('fieldset', $commitform, array('class' => 'commitformwrapper protected')); $a = new stdClass(); $a->time = userdate(time(), get_string('strftimedaydatetime', 'langconfig')); $stashtitle = get_string('stashtitledefault', 'local_amos', $a); $stashform = html_writer::label(get_string('stashtitle', 'local_amos'), 'stashtitle', true); $stashform .= html_writer::empty_tag('input', array('name' => 'sesskey', 'value' => sesskey(), 'type' => 'hidden')); $stashform .= html_writer::empty_tag('input', array('name' => 'new', 'value' => 1, 'type' => 'hidden')); $stashform .= html_writer::empty_tag('input', array('name' => 'name', 'value' => $stashtitle, 'type' => 'text', 'size' => 50, 'id' => 'stashtitle', 'maxlength' => 255)); $stashform .= html_writer::empty_tag('input', array('value' => get_string('stashpush', 'local_amos'), 'type' => 'submit')); $stashform = html_writer::tag('div', $stashform); $stashform = html_writer::tag('form', $stashform, array('method' => 'post', 'action' => $CFG->wwwroot . '/local/amos/stash.php')); $stashform = html_writer::tag('div', $stashform, array('class' => 'stashformwrapper')); $submiturl = new moodle_url('/local/amos/stage.php', array('submit' => 1)); $submitbutton = $this->single_button($submiturl, get_string('stagesubmit', 'local_amos'), 'post', array('class' => 'singlebutton submit')); $pruneurl = new moodle_url('/local/amos/stage.php', array('prune' => 1)); $prunebutton = $this->single_button($pruneurl, get_string('stageprune', 'local_amos'), 'post', array('class' => 'singlebutton protected prune')); $rebaseurl = new moodle_url('/local/amos/stage.php', array('rebase' => 1)); $rebasebutton = $this->single_button($rebaseurl, get_string('stagerebase', 'local_amos'), 'post', array('class' => 'singlebutton protected rebase')); $unstageallurl = new moodle_url('/local/amos/stage.php', array('unstageall' => 1)); $unstageallbutton = $this->single_button($unstageallurl, get_string('stageunstageall', 'local_amos'), 'post', array('class' => 'singlebutton protected unstageall')); $i = 0; foreach ($stage->filterfields->fver as $fver) { $params['fver[' . $i . ']'] = $fver; $i++; } $i = 0; foreach ($stage->filterfields->flng as $flng) { $params['flng[' . $i . ']'] = $flng; $i++; } $i = 0; foreach ($stage->filterfields->fcmp as $fcmp) { $params['fcmp[' . $i . ']'] = $fcmp; $i++; } $params['fstg'] = 1; $params['__lazyform_amosfilter'] = 1; $editurl = new moodle_url('/local/amos/view.php', $params); $editbutton = $this->single_button($editurl, get_string('stageedit', 'local_amos'), 'post', array('class' => 'singlebutton edit')); if (empty($stage->strings)) { $output = $this->heading(get_string('stagestringsnone', 'local_amos'), 2, 'main', 'numberofstagedstrings'); if ($stage->importform) { $legend = html_writer::tag('legend', get_string('importfile', 'local_amos') . $this->help_icon('importfile', 'local_amos')); ob_start(); $stage->importform->display(); $importform = ob_get_contents(); ob_end_clean(); $output .= html_writer::tag('fieldset', $legend . $importform, array('class' => 'wrappedmform importform')); } if ($stage->mergeform) { $legend = html_writer::tag('legend', get_string('mergestrings', 'local_amos') . $this->help_icon('mergestrings', 'local_amos')); ob_start(); $stage->mergeform->display(); $mergeform = ob_get_contents(); ob_end_clean(); $output .= html_writer::tag('fieldset', $legend . $mergeform, array('class' => 'wrappedmform mergeform')); } if ($stage->diffform) { $legend = html_writer::tag('legend', get_string('diffstrings', 'local_amos') . $this->help_icon('diffstrings', 'local_amos')); ob_start(); $stage->diffform->display(); $diffform = ob_get_contents(); ob_end_clean(); $output .= html_writer::tag('fieldset', $legend . $diffform, array('class' => 'wrappedmform diffform')); } if ($stage->executeform) { $legend = html_writer::tag('legend', get_string('script', 'local_amos') . $this->help_icon('script', 'local_amos')); ob_start(); $stage->executeform->display(); $executeform = ob_get_contents(); ob_end_clean(); $output .= html_writer::tag('fieldset', $legend . $executeform, array('class' => 'wrappedmform executeform')); } } else { $output = ''; if (!empty($stage->stagedcontribution)) { $output .= $this->heading_with_help(get_string('contribstaged', 'local_amos', $stage->stagedcontribution), 'contribstagedinfo', 'local_amos'); } $a = (object) array('staged' => count($stage->strings), 'committable' => $committable); if ($committable) { $output .= $this->heading(get_string('stagestringssome', 'local_amos', $a), 2, 'main', 'numberofstagedstrings'); } else { $output .= $this->heading(get_string('stagestringsnocommit', 'local_amos', $a), 2, 'main', 'numberofstagedstrings'); } unset($a); $justpropagated = optional_param('justpropagated', null, PARAM_INT); // usability hack to hide the propagator just after it was used if (is_null($justpropagated)) { $output .= $propagateform; } else { if ($justpropagated == 0) { $output .= $this->heading(get_string('propagatednone', 'local_amos')); } else { $output .= $this->heading(get_string('propagatedsome', 'local_amos', $justpropagated)); } } if ($committable) { $output .= $commitform; } $legend = html_writer::tag('legend', get_string('stageactions', 'local_amos') . $this->help_icon('stageactions', 'local_amos')); $actionbuttons = $legend . $submitbutton . $editbutton; if ($committable) { $actionbuttons .= $prunebutton . $rebasebutton; } $actionbuttons .= $unstageallbutton; $output .= html_writer::tag('fieldset', $actionbuttons, array('class' => 'actionbuttons')); $legend = html_writer::tag('legend', get_string('stashactions', 'local_amos') . $this->help_icon('stashactions', 'local_amos')); $output .= html_writer::tag('fieldset', $legend . $stashform, array('class' => 'actionbuttons')); $output .= $table; } $output = html_writer::tag('div', $output, array('class' => 'stagewrapper')); return $output; }