/** * This is a hacky way how to populate a forum at lang.moodle.org with commits into the core * * @param mlang_stage $stage * @param string $commitmsg * @param string $committer * @param string $committeremail * @param string $commithash * @param string $fullcommitmsg * @return void */ function amos_core_commit_notify(mlang_stage $stage, $commitmsg, $committer, $committeremail, $commithash, $fullcommitmsg) { global $CFG; $DB; require_once $CFG->dirroot . '/mod/forum/lib.php'; if ($CFG->wwwroot !== 'http://lang.moodle.org') { // this is intended for lang.moodle.org portal only return; } if (!$stage->has_component()) { // nothing to commit return; } // these are hard-coded values of a forum to inject commit messages into $courseid = 2; // course 'Translating Moodle' $cmid = 7; // forum 'Notification of string changes' $userid = 2; // user 'AMOS bot' $cm = get_coursemodule_from_id('forum', $cmid); $discussion = new stdclass(); $discussion->course = $courseid; $discussion->forum = $cm->instance; $discussion->name = substr(s('[AMOS commit] ' . $commitmsg), 0, 255); $discussion->message = 'Author: ' . $committer . "\n"; $discussion->message .= $fullcommitmsg . "\n\n"; $discussion->message .= 'http://git.moodle.org/gw?p=moodle.git;a=commit;h=' . $commithash . "\n"; $discussion->message .= 'http://github.com/moodle/moodle/commit/' . $commithash . "\n\n"; $standardplugins = local_amos_standard_plugins(); foreach ($stage->get_iterator() as $component) { foreach ($component->get_iterator() as $string) { if ($string->deleted) { $sign = '- '; } else { $sign = '+ '; } if (isset($standardplugins[$component->version->dir][$component->name])) { $name = $standardplugins[$component->version->dir][$component->name]; } else { $name = $component->name; } $discussion->message .= $sign . $component->version->dir . ' en [' . $string->id . ',' . $name . "]\n"; } } $discussion->message = s($discussion->message); $discussion->messageformat = FORMAT_MOODLE; $discussion->messagetrust = 0; $discussion->attachments = null; $discussion->mailnow = 1; $message = null; forum_add_discussion($discussion, null, $message, $userid); }
$startat = trim(file_get_contents($startatlock)); if (!empty($startat) and $startat != $rootcommit) { $startat = '^' . $startat . '^'; } } $gitout = array(); $gitstatus = 0; $gitcmd = AMOS_PATH_GIT . " whatchanged --topo-order --reverse --format=format:COMMIT:%H origin/cvshead {$startat} " . AMOS_REPO_LANGS; fputs(STDOUT, "RUN {$gitcmd}\n"); exec($gitcmd, $gitout, $gitstatus); if ($gitstatus != 0) { // error occured fputs(STDERR, "RUN ERROR {$gitstatus}\n"); exit(1); } $stage = new mlang_stage(); $commithash = ''; foreach ($gitout as $line) { $line = trim($line); if (empty($line)) { continue; } if (substr($line, 0, 7) == 'COMMIT:') { // remember the processed commithash if (!empty($commithash)) { // new commit is here - if we have something to push into AMOS repository, do it now amos_parse_lang_commit(); } $commithash = substr($line, 7); continue; }
/** * AMOS upgrade scripts * * @package local_amos * @copyright 2010 David Mudrak <*****@*****.**> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ function xmldb_local_amos_upgrade($oldversion) { global $CFG, $DB, $OUTPUT; $dbman = $DB->get_manager(); $result = true; if ($oldversion < 2010090103) { $dbman->install_one_table_from_xmldb_file($CFG->dirroot . '/local/amos/db/install.xml', 'amos_stashes'); upgrade_plugin_savepoint(true, 2010090103, 'local', 'amos'); } if ($oldversion < 2010090107) { $dbman->install_one_table_from_xmldb_file($CFG->dirroot . '/local/amos/db/install.xml', 'amos_hidden_requests'); upgrade_plugin_savepoint(true, 2010090107, 'local', 'amos'); } if ($oldversion < 2010110400) { $dbman->install_one_table_from_xmldb_file($CFG->dirroot . '/local/amos/db/install.xml', 'amos_greylist'); upgrade_plugin_savepoint(true, 2010110400, 'local', 'amos'); } if ($oldversion < 2011010600) { $dbman->install_one_table_from_xmldb_file($CFG->dirroot . '/local/amos/db/install.xml', 'amos_contributions'); upgrade_plugin_savepoint(true, 2011010600, 'local', 'amos'); } if ($oldversion < 2011011000) { require_once dirname(dirname(__FILE__)) . '/mlanglib.php'; // convert legacy stashes that were pull-requested $stashids = $DB->get_records('amos_stashes', array('pullrequest' => 1), 'timemodified ASC', 'id'); foreach ($stashids as $stashrecord) { $stash = mlang_stash::instance_from_id($stashrecord->id); // split the stashed components into separate packages by their language $stage = new mlang_stage(); $langstages = array(); // (string)langcode => (mlang_stage) $stash->apply($stage); foreach ($stage->get_iterator() as $component) { $lang = $component->lang; if (!isset($langstages[$lang])) { $langstages[$lang] = new mlang_stage(); } $langstages[$lang]->add($component); } $stage->clear(); unset($stage); // create new contribution record for every language and attach a new stash to it foreach ($langstages as $lang => $stage) { if (!$stage->has_component()) { // this should not happen, but... continue; } $copy = new mlang_stage(); foreach ($stage->get_iterator() as $component) { $copy->add($component); } $copy->rebase(); if ($copy->has_component()) { $tostatus = 0; // new } else { $tostatus = 30; // nothing left after rebase - consider it accepted } $langstash = mlang_stash::instance_from_stage($stage, 0, $stash->name); $langstash->message = $stash->message; $langstash->push(); $contribution = new stdClass(); $contribution->authorid = $stash->ownerid; $contribution->lang = $lang; $contribution->assignee = null; $contribution->subject = $stash->name; $contribution->message = $stash->message; $contribution->stashid = $langstash->id; $contribution->status = $tostatus; $contribution->timecreated = $stash->timemodified; $contribution->timemodified = null; $contribution->id = $DB->insert_record('amos_contributions', $contribution); // add a comment there $comment = new stdClass(); $comment->contextid = SITEID; $comment->commentarea = 'amos_contribution'; $comment->itemid = $contribution->id; $comment->content = 'This contribution was automatically created during the conversion of legacy pull-requested stashes.'; $comment->format = 0; $comment->userid = 2; $comment->timecreated = time(); $DB->insert_record('comments', $comment); } $stash->drop(); } upgrade_plugin_savepoint(true, 2011011000, 'local', 'amos'); } if ($oldversion < 2011011001) { $table = new xmldb_table('amos_stashes'); $field = new xmldb_field('shared'); if ($dbman->field_exists($table, $field)) { $dbman->drop_field($table, $field); } $field = new xmldb_field('pullrequest'); if ($dbman->field_exists($table, $field)) { $dbman->drop_field($table, $field); } $table = new xmldb_table('amos_hidden_requests'); if ($dbman->table_exists($table)) { $dbman->drop_table($table); } upgrade_plugin_savepoint(true, 2011011001, 'local', 'amos'); } return $result; }
foreach ($languages['en'] as $componentname => $unused) { if ($componentname == 'langconfig') { continue; } $memprev = $mem; $mem = memory_get_usage(); $memdiff = $memprev < $mem ? '+' : '-'; $memdiff = $memdiff . abs($mem - $memprev); $english = mlang_component::from_snapshot($componentname, 'en', $version, null, true, true); foreach ($english->get_iterator() as $string) { if (empty($options['full']) and $string->timemodified < time() - DAYSECS) { continue; } if ($string->deleted) { // propagate removal of this string to all other languages where it is present $stage = new mlang_stage(); foreach (array_keys($tree[$vercode]) as $otherlang) { if ($otherlang == 'en') { continue; } $other = mlang_component::from_snapshot($componentname, $otherlang, $version, null, true, false, array($string->id)); if ($other->has_string($string->id)) { $current = $other->get_string($string->id); if (!$current->deleted) { $current->deleted = true; $current->timemodified = time(); $stage->add($other); } } $other->clear(); unset($other);
* --execute - execute required steps to make AMOS and Git repo synced * * @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
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) { if ($string->deleted) { $sign = '-'; } else { $sign = '+'; } echo $sign . ' ' . $string->id . PHP_EOL; }
/** * Factory method using an instance if {@link mlang_stash} as a data source * * @param mlang_stash $stash * @param stdClass $owner owner user data * @return local_amos_stash new instance */ public static function instance_from_mlang_stash(mlang_stash $stash, stdClass $owner) { if ($stash->ownerid != $owner->id) { throw new coding_exception('Stash owner mismatch'); } $new = new local_amos_stash(); $new->id = $stash->id; $new->name = $stash->name; $new->timecreated = $stash->timecreated; $stage = new mlang_stage(); $stash->apply($stage); list($new->strings, $new->languages, $new->components) = mlang_stage::analyze($stage); $stage->clear(); unset($stage); $new->components = explode('/', trim($new->components, '/')); $new->languages = explode('/', trim($new->languages, '/')); $new->owner = $owner; if ($stash->hash === 'xxxxautosaveuser' . $new->owner->id) { $new->isautosave = true; } else { $new->isautosave = false; } return $new; }
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(); }
/** * Migrate help file into a help string if such one does not exist yet * * This is a temporary method and will be dropped once we have all English helps migrated. It does not do anything * yet. It is intended to be run once upon a checkout of 1.9 language files prepared just for this purpose. * * @param mixed $helpfile * @param mixed $tostring * @param mixed $tocomponent * @param mixed $timestamp * @return mlang_stage */ protected static function migrate_helpfile($version, $helpfile, $tostring, $tocomponent, $timestamp = null) { global $CFG; require_once $CFG->dirroot . '/local/amos/cli/config.php'; $stage = new mlang_stage(); foreach (array_keys(self::list_languages(false)) as $lang) { $fullpath = AMOS_REPO_LANGS . '/' . $lang . '_utf8/help/' . $helpfile; if (!is_readable($fullpath)) { continue; } $helpstring = file_get_contents($fullpath); $helpstring = preg_replace('|<h1>.*</h1>|i', '', $helpstring); $helpstring = iconv('UTF-8', 'UTF-8//IGNORE', $helpstring); $helpstring = trim($helpstring); if (empty($helpstring)) { continue; } $to = mlang_component::from_snapshot($tocomponent, $lang, $version, $timestamp, false, false, array($tostring)); if (!$to->has_string($tostring)) { $to->add_string(new mlang_string($tostring, $helpstring, $timestamp)); $stage->add($to); } $to->clear(); } return $stage; }
if ($maintainerof !== 'all') { if (!in_array($contribution->lang, $maintainerof)) { print_error('contributionaccessdenied', 'local_amos'); } } $author = $DB->get_record('user', array('id' => $contribution->authorid)); } else { $author = $USER; } // get the contributed components and rebase them to see what would happen $stash = mlang_stash::instance_from_id($contribution->stashid); $stage = new mlang_stage(); $stash->apply($stage); list($origstrings, $origlanguages, $origcomponents) = mlang_stage::analyze($stage); $stage->rebase(); list($rebasedstrings, $rebasedlanguages, $rebasedcomponents) = mlang_stage::analyze($stage); if ($stage->has_component()) { } else { // nothing left after rebase } $contribinfo = new local_amos_contribution($contribution, $author); $contribinfo->language = implode(', ', array_filter(array_map('trim', explode('/', $origlanguages)))); $contribinfo->components = implode(', ', array_filter(array_map('trim', explode('/', $origcomponents)))); $contribinfo->strings = $origstrings; $contribinfo->stringsreb = $rebasedstrings; echo $output->render($contribinfo); echo html_writer::start_tag('div', array('class' => 'contribactions')); if ($maintainerof) { if ($contribution->status == local_amos_contribution::STATE_NEW) { echo $output->single_button(new moodle_url($PAGE->url, array('review' => $id)), get_string('contribstartreview', 'local_amos'), 'post', array('class' => 'singlebutton review')); }