22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | /**
26 | * Populates the contribution front page block contents.
27 | *
28 | * @return string
29 | */
30 | function local_amos_frontpage_contribution_stats() {
31 | global $CFG, $DB;
32 |
33 | $total = (int)$DB->get_field_sql("
34 | SELECT SUM(strings)
35 | FROM {amos_contributions} c
36 | JOIN mdl_amos_stashes s ON c.stashid = s.id
37 | WHERE c.status = 30");
38 |
39 | $namefields = get_all_user_name_fields(true, "u");
40 | $recent = $DB->get_records_sql("
41 | SELECT c.authorid AS id, $namefields, MAX(c.timecreated) AS mostrecent
42 | FROM {amos_contributions} c
43 | JOIN {user} u ON u.id = c.authorid
44 | GROUP BY c.authorid, $namefields
45 | ORDER BY mostrecent DESC", null, 0, 4);
46 |
47 | $links = array();
48 | foreach ($recent as $contributor) {
49 | $links[] = ''.s(fullname($contributor)).'';
50 | }
51 |
52 | $last = array_pop($links);
53 |
54 | $links = implode(', ', $links) . ' and ' . $last;
55 |
56 | return '' . get_string('contributestats', 'local_amos', array('count' => $total)) . '
57 |
60 | ' . get_string('contributethanks', 'local_amos', array('listcontributors' => $links)) . '
';
61 | }
62 |
63 | ?>
64 |
65 |
92 |
--------------------------------------------------------------------------------
/cli/intersect.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * Removes translation of strings that are not present in the English pack
20 | *
21 | * In other words, it calls mlang_component::intersect() against the English
22 | * original for all components in the repository.
23 | *
24 | * Usage:
25 | *
26 | * php intersect.php (for dry-run)
27 | * php intersect.php --execute (to actually commit the removal)
28 | *
29 | * @package local_amos
30 | * @copyright 2012 David Mudrak
31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32 | */
33 |
34 | define('CLI_SCRIPT', true);
35 |
36 | require_once(dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php');
37 | require_once($CFG->dirroot . '/local/amos/cli/config.php');
38 | require_once($CFG->dirroot . '/local/amos/mlanglib.php');
39 | require_once($CFG->dirroot . '/local/amos/renderer.php');
40 | require_once($CFG->libdir.'/clilib.php');
41 |
42 | list($options, $unrecognized) = cli_get_params(array('execute' => false));
43 |
44 | fputs(STDOUT, "*****************************************\n");
45 | fputs(STDOUT, date('Y-m-d H:i', time()));
46 | fputs(STDOUT, " INTERSECT JOB STARTED\n");
47 |
48 | $cliresult = 0;
49 |
50 | $tree = mlang_tools::components_tree();
51 | foreach ($tree as $vercode => $languages) {
52 | if ($vercode < mlang_version::MOODLE_20) {
53 | continue;
54 | }
55 | $version = mlang_version::by_code($vercode);
56 | foreach ($languages['en'] as $componentname => $unused) {
57 | $english = mlang_component::from_snapshot($componentname, 'en', $version);
58 | foreach (array_keys($tree[$vercode]) as $otherlang) {
59 | if ($otherlang == 'en') {
60 | continue;
61 | }
62 | $stage = new mlang_stage();
63 | $other = mlang_component::from_snapshot($componentname, $otherlang, $version);
64 | $removed = $other->intersect($english);
65 | if ($removed) {
66 | $stage->add($other);
67 | }
68 | $other->clear();
69 | unset($other);
70 |
71 | $stage->rebase(null, true);
72 |
73 | if ($options['execute']) {
74 | $action = 'removing';
75 | } else {
76 | $action = 'would remove';
77 | }
78 |
79 | foreach ($stage->get_iterator() as $xcomp) {
80 | foreach ($xcomp->get_iterator() as $xstr) {
81 | fputs(STDERR, $action.' '.$xstr->id.' from '.$componentname.' '.$otherlang.' '.$version->label.PHP_EOL);
82 | if (!$options['execute']) {
83 | $cliresult = 1;
84 | }
85 | }
86 | }
87 |
88 | if ($options['execute']) {
89 | $msg = 'Reverse clean-up of strings that do not exist in the English pack';
90 | $stage->commit($msg, array('source' => 'bot', 'userinfo' => 'AMOS-bot '), true);
91 | } else {
92 | $stage->clear();
93 | }
94 | }
95 | $english->clear();
96 | }
97 | }
98 |
99 | fputs(STDOUT, date('Y-m-d H:i', time()));
100 | fputs(STDOUT, " INTERSECT CLEANUP JOB DONE\n");
101 |
102 | exit($cliresult);
103 |
--------------------------------------------------------------------------------
/cli/compare-packs.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * @package local_amos
20 | * @subpackage cli
21 | * @copyright 2013 David Mudrak
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | $usage = "
26 | Use this script to compare the contents of two unzipped language packs
27 |
28 | $ php compare-packs.php --version=2.6 --master=/tmp/en --slave=/tmp/fr
29 | ";
30 |
31 | define('CLI_SCRIPT', 1);
32 |
33 | require(__DIR__.'/../../../config.php');
34 | require_once($CFG->libdir.'/pluginlib.php');
35 | require_once($CFG->libdir.'/clilib.php');
36 | require_once($CFG->dirroot.'/local/amos/mlanglib.php');
37 | require_once($CFG->dirroot.'/local/amos/locallib.php');
38 |
39 | list($options, $unrecognized) = cli_get_params(array('version' => '', 'master' => '', 'slave' => ''));
40 |
41 | $version = $options['version'];
42 | $master = $options['master'];
43 | $slave = $options['slave'];
44 |
45 | if (empty($version) or empty($master) or empty($slave)) {
46 | cli_error($usage);
47 | }
48 |
49 | $standard = local_amos_standard_plugins();
50 |
51 | if (!isset($standard[$version])) {
52 | cli_error($version.' not a known version');
53 | }
54 |
55 | if (!is_dir($master)) {
56 | cli_error($master.' is not a directory');
57 | }
58 |
59 | if (!is_dir($slave)) {
60 | cli_error($slave.' is not a directory');
61 | }
62 |
63 | $mpack = array();
64 | $spack = array();
65 |
66 | foreach (new DirectoryIterator($master) as $file) {
67 | if ($file->isDot() or $file->isDir()) {
68 | continue;
69 | }
70 | if (substr($file->getFilename(), -4) !== '.php') {
71 | fputs(STDERR, 'Unexpected file '.$file->getPathname());
72 | exit(1);
73 | }
74 | $component = mlang_component::name_from_filename($file->getFilename());
75 | $string = array();
76 | require($file->getPathname());
77 | $mpack[$component] = array_flip(array_keys($string));
78 | unset($string);
79 | }
80 |
81 | foreach (new DirectoryIterator($slave) as $file) {
82 | if ($file->isDot() or $file->isDir()) {
83 | continue;
84 | }
85 | if (substr($file->getFilename(), -4) !== '.php') {
86 | fputs(STDERR, 'Unexpected file '.$file->getPathname());
87 | exit(1);
88 | }
89 | $component = mlang_component::name_from_filename($file->getFilename());
90 | $string = array();
91 | require($file->getPathname());
92 | $spack[$component] = array_flip(array_keys($string));
93 | unset($string);
94 | }
95 |
96 | // Report all slave strings not present in the master pack.
97 | foreach ($spack as $component => $strings) {
98 | foreach (array_keys($strings) as $string) {
99 | if (!isset($mpack[$component][$string])) {
100 | fputs(STDERR, '['.$component.','.$string.'] defined in the slave only'.PHP_EOL);
101 | }
102 | }
103 | }
104 |
105 | // Report all missing slave strings if the master pack is a standard one.
106 | foreach ($mpack as $component => $strings) {
107 | if (!isset($standard[$version][$component])) {
108 | continue;
109 | }
110 | foreach (array_keys($strings) as $string) {
111 | if (substr($string, -5) === '_link') {
112 | continue;
113 | }
114 | if (!isset($spack[$component][$string])) {
115 | fputs(STDERR, '['.$component.','.$string.'] defined in the master only'.PHP_EOL);
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/classes/external/plugin_translation_stats.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Provides the {@link \local_amos\external\plugin_translation_stats} trait.
19 | *
20 | * @package local_amos
21 | * @category external
22 | * @copyright 2019 David Mudrak
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | namespace local_amos\external;
27 |
28 | defined('MOODLE_INTERNAL') || die();
29 |
30 | /**
31 | * Trait implementing the plugin_translation_stats external function.
32 | */
33 | trait plugin_translation_stats {
34 |
35 | /**
36 | * Describes parameters of the {@link plugin_translation_stats()} method
37 | */
38 | public static function plugin_translation_stats_parameters() {
39 | return new \external_function_parameters([
40 | 'component' => new \external_value(PARAM_COMPONENT, 'Name of the component to obtain stats for'),
41 | ]);
42 | }
43 |
44 | /**
45 | * Returns stats about the given plugin / component translations.
46 | *
47 | * @param string $component
48 | * @return stdClass
49 | */
50 | public static function plugin_translation_stats($component) {
51 |
52 | // Validate parameters.
53 | $params = self::validate_parameters(self::plugin_translation_stats_parameters(), ['component' => $component]);
54 | $component = $params['component'];
55 |
56 | // Validate the context.
57 | $context = \context_system::instance();
58 | self::validate_context($context);
59 |
60 | $statsman = new \local_amos_stats_manager();
61 |
62 | $data = $statsman->get_component_stats($component);
63 |
64 | if ($data === false) {
65 | throw new \invalid_parameter_exception('Stats requested for an unknown component.');
66 | }
67 |
68 | return $data;
69 | }
70 |
71 | /**
72 | * Describes the return value of the {@link plugin_translation_stats()} method.
73 | *
74 | * @return external_description
75 | */
76 | public static function plugin_translation_stats_returns() {
77 | return new \external_single_structure([
78 | 'lastmodified' => new \external_value(PARAM_INT, 'Timestamp of when the data was last modified'),
79 | 'langnames' => new \external_multiple_structure(
80 | new \external_single_structure([
81 | 'lang' => new \external_value(PARAM_SAFEDIR, 'Language code'),
82 | 'name' => new \external_value(PARAM_TEXT, 'International name of the language followed by its code')
83 | ])
84 | ),
85 | 'branches' => new \external_multiple_structure(
86 | new \external_single_structure([
87 | 'branch' => new \external_value(PARAM_FILE, 'Moodle branch (eg. 3.6)'),
88 | 'languages' => new \external_multiple_structure(
89 | new \external_single_structure([
90 | 'lang' => new \external_value(PARAM_SAFEDIR, 'Language code'),
91 | 'numofstrings' => new \external_value(PARAM_INT, 'Number of strings in the language pack'),
92 | 'ratio' => new \external_value(PARAM_INT, 'Completeness of the translation'),
93 | ])
94 | ),
95 | ])
96 | )
97 | ]);
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/tests/fixtures/parserdata002.txt:
--------------------------------------------------------------------------------
1 |
2 | diff --git a/lang/en/admin.php b/lang/en/admin.php
3 | index 7c67ea9..6271297 100644
4 | --- a/lang/en/admin.php
5 | +++ b/lang/en/admin.php
6 | @@ -183,7 +183,7 @@ $string['configdefaultallowedmodules'] = 'For the courses which fall into the ab
7 | $string['configdefaulthomepage'] = 'This determines the home page for logged in users';
8 | $string['configdefaultrequestcategory'] = 'Courses requested by users will be automatically placed in this category.';
9 | $string['configdefaultrequestedcategory'] = 'Default category to put courses that were requested into, if they\'re approved.';
10 | -$string['configdefaultuserroleid'] = 'All logged in users will be given the capabilities of the role you specify here, at the site level, in ADDITION to any other roles they may have been given. The default is the Authenticated user role (or Guest role in older versions). Note that this will not conflict with other roles they have, it just ensures that all users have capabilities that are not assignable at the course level (eg post blog entries, manage own calendar, etc).';
11 | +$string['configdefaultuserroleid'] = 'All logged in users will be given the capabilities of the role you specify here, at the site level, in ADDITION to any other roles they may have been given. The default is the Authenticated user role. Note that this will not conflict with other roles they have unless you prohibit capabilities, it just ensures that all users have capabilities that are not assignable at the course level (eg post blog entries, manage own calendar, etc).';
12 | $string['configdeleteincompleteusers'] = 'After this period, old not fully setup accounts are deleted.';
13 | $string['configdeleteunconfirmed'] = 'If you are using email authentication,
14 |
15 | this is the period within which a response will be accepted from users. After this period, old unconfirmed accounts are deleted.';
16 | $string['configdenyemailaddresses'] = 'To deny email addresses from particular domains list them here in the same way. All other domains will be accepted. To deny subdomains add the domain with a preceding \'.\'. eg hotmail.com yahoo.co.uk .live.com';
17 | @@ -276,7 +276,6 @@ $string['configmypagelocked'] = 'This setting prevents the default page from bei
18 | $string['confignavcourselimit'] = 'Limits the number of courses shown to the user when they are either not logged in or are not enrolled in any courses.';
19 | $string['confignavshowallcourses'] = 'Setting this ensures that all courses on the site are shown in the navigation at all times.';
20 | $string['confignavshowcategories'] = 'Show course categories in the navigation bar and navigation blocks. This does not occur with courses the user is currently enrolled in, they will still be listed under mycourses without categories.';
21 | -$string['confignodefaultuserrolelists'] = 'This setting prevents all users from being returned from the database from deprecated calls of get_course_user, etc., for the site course if the default role provides that access. Check this, if you suffer a performance hit.';
22 | $string['confignoreplyaddress'] = 'Emails are sometimes sent out on behalf of a user (eg forum posts). The email address you specify here will be used as the "From" address in those cases when the recipients should not be able to reply directly to the user (eg when a user chooses to keep their address private).';
23 | $string['confignotifyloginfailures'] = 'If login failures have been recorded, email notifications can be sent out. Who should see these notifications?';
24 | $string['confignotifyloginthreshold'] = 'If notifications about failed logins are active, how many failed login attempts by one user or one IP address is it worth notifying about?';
25 | @@ -747,7 +746,6 @@ $string['navshowcategories'] = 'Show course categories';
26 | $string['neverdeleteruns'] = 'Never delete runs';
27 | $string['nobookmarksforuser'] = 'You do not have any bookmarks.';
28 | $string['nodatabase'] = 'No database';
29 | -$string['nodefaultuserrolelists'] = 'Don\'t return all default role users';
30 | $string['nochanges'] = 'No changes';
31 | +$string['nolangupdateneeded'] = 'All your language packs are up to date, no update is needed';
32 | $string['nomissingstrings'] = 'No missing strings';
33 | +$string['mod/something:really_nasty-like0098187.this'] ='Valid';
34 |
--------------------------------------------------------------------------------
/merge.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * Merge all missing strings from branch to another and stage them
20 | *
21 | * @package local
22 | * @subpackage amos
23 | * @copyright 2010 David Mudrak
24 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 | */
26 |
27 | require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
28 | require_once(dirname(__FILE__).'/locallib.php');
29 | require_once(dirname(__FILE__).'/mlanglib.php');
30 | require_once(dirname(__FILE__).'/merge_form.php');
31 |
32 | require_login(SITEID, false);
33 | require_capability('local/amos:commit', context_system::instance()); // for langpack maintainers only
34 |
35 | $PAGE->set_pagelayout('standard');
36 | $PAGE->set_url('/local/amos/merge.php');
37 | navigation_node::override_active_url(new moodle_url('/local/amos/stage.php'));
38 | $PAGE->set_title('AMOS ' . get_string('merge', 'local_amos'));
39 | $PAGE->set_heading('AMOS ' . get_string('merge', 'local_amos'));
40 |
41 | $mergeform = new local_amos_merge_form(null, local_amos_merge_options());
42 |
43 | if ($data = $mergeform->get_data()) {
44 | $stage = mlang_persistent_stage::instance_for_user($USER->id, sesskey());
45 |
46 | $sourceversion = mlang_version::by_code($data->sourceversion);
47 | $targetversion = mlang_version::by_code($data->targetversion);
48 | if (is_null($sourceversion) or is_null($targetversion)) {
49 | notice('Invalid version selected', new moodle_url('/local/amos/stage.php'));
50 | }
51 |
52 | $tree = mlang_tools::components_tree(array('branch' => $sourceversion->code, 'lang' => $data->language));
53 | $tree = reset($tree);
54 | $sourcecomponentnames = array_keys(reset($tree));
55 | unset($tree);
56 |
57 | foreach ($sourcecomponentnames as $sourcecomponentname) {
58 | // get a snapshot of both components and merge source into target
59 | $sourcecomponent = mlang_component::from_snapshot($sourcecomponentname, $data->language, $sourceversion);
60 | $targetcomponent = mlang_component::from_snapshot($sourcecomponent->name, $sourcecomponent->lang, $targetversion);
61 | mlang_tools::merge($sourcecomponent, $targetcomponent);
62 | $sourcecomponent->clear();
63 | // keep just strings that are defined in english
64 | $englishcomponent = mlang_component::from_snapshot($sourcecomponent->name, 'en', $targetversion);
65 | $targetcomponent->intersect($englishcomponent);
66 | $englishcomponent->clear();
67 | // stage the target
68 | $stage->add($targetcomponent);
69 | $targetcomponent->clear();
70 | }
71 |
72 | // prune the stage so that only committable strings are staged
73 | $allowed = mlang_tools::list_allowed_languages($USER->id);
74 | $stage->prune($allowed);
75 | // keep just really modified (that is new in this case) strings
76 | $stage->rebase();
77 | // and store the persistant stage
78 | $stage->store();
79 |
80 | // if no new strings are merged, inform the user
81 | if (!$stage->has_component()) {
82 | notice(get_string('nothingtomerge', 'local_amos'), new moodle_url('/local/amos/stage.php'));
83 | }
84 |
85 | if (!isset($SESSION->local_amos)) {
86 | $SESSION->local_amos = new stdClass();
87 | }
88 | $a = new stdClass();
89 | $a->source = $sourceversion->label;
90 | $a->target = $targetversion->label;
91 | $SESSION->local_amos->presetcommitmessage = get_string('presetcommitmessage2', 'local_amos', $a);
92 | }
93 |
94 | redirect(new moodle_url('/local/amos/stage.php'));
95 |
--------------------------------------------------------------------------------
/timeline.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * Displays a timeline history of a given string
20 | *
21 | * @package local
22 | * @subpackage amos
23 | * @copyright 2010 David Mudrak
24 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 | */
26 |
27 | require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
28 | //require_once($CFG->dirroot . '/local/amos/locallib.php');
29 | require_once($CFG->dirroot . '/local/amos/mlanglib.php');
30 | require_once($CFG->dirroot . '/local/amos/renderer.php');
31 |
32 | require_login(SITEID, false);
33 | require_capability('local/amos:stage', context_system::instance());
34 |
35 | $component = required_param('component', PARAM_ALPHANUMEXT);
36 | $language = required_param('language', PARAM_ALPHANUMEXT);
37 | $branch = required_param('branch', PARAM_INT);
38 | $stringid = required_param('stringid', PARAM_STRINGID);
39 | $ajax = optional_param('ajax', 0, PARAM_BOOL);
40 |
41 | $PAGE->set_url('/local/amos/timeline.ajax.php');
42 | $PAGE->set_pagelayout('popup');
43 | $PAGE->set_context(context_system::instance());
44 |
45 | if ($ajax) {
46 | @header('Content-Type: text/plain; charset=utf-8');
47 | } else {
48 | echo $OUTPUT->header();
49 | }
50 |
51 | $sql = "SELECT s.id, s.lang, t.text, s.timemodified, s.deleted,
52 | c.userinfo, c.commitmsg, c.commithash
53 | FROM {amos_repository} s
54 | JOIN {amos_texts} t ON t.id = s.textid
55 | JOIN {amos_commits} c ON c.id = s.commitid
56 | WHERE branch = ? AND (lang = 'en' OR lang = ?) AND component = ? AND stringid = ?
57 | ORDER BY s.timemodified DESC, s.id DESC";
58 |
59 | $params = array($branch, $language, $component, $stringid);
60 |
61 | $results = $DB->get_records_sql($sql, $params);
62 |
63 | if (!$results) {
64 | print_error('invalidtimelineparams', 'local_amos');
65 | }
66 |
67 | $table = new html_table();
68 | $table->attributes['class'] = 'timelinetable';
69 |
70 | foreach ($results as $result) {
71 |
72 | $encell = new html_table_cell();
73 | $langcell = new html_table_cell();
74 | if ($result->lang == 'en') {
75 | $cell = $encell;
76 | $none = $langcell;
77 | } else {
78 | $cell = $langcell;
79 | $none = $encell;
80 | }
81 |
82 | $date = html_writer::tag('div', local_amos_renderer::commit_datetime($result->timemodified), array('class' => 'timemodified'));
83 | $userinfo = html_writer::tag('span', s($result->userinfo), array('class' => 'userinfo'));
84 | $commitmsg = html_writer::tag('span', s($result->commitmsg), array('class' => 'commitmsg'));
85 | if ($result->deleted) {
86 | $text = html_writer::tag('del', s($result->text));
87 | } else {
88 | $text = s($result->text);
89 | }
90 | $text = local_amos_renderer::add_breaks($text);
91 | if ($result->commithash) {
92 | if ($result->lang == 'en') {
93 | $url = 'https://github.com/moodle/moodle/commit/'.$result->commithash;
94 | } else {
95 | $url = 'https://github.com/mudrd8mz/moodle-lang/commit/'.$result->commithash;
96 | }
97 | $hashlink = html_writer::link($url, $result->commithash);
98 | $commithash = html_writer::tag('div', $hashlink, array('class' => 'commithash'));
99 | } else {
100 | $commithash = '';
101 | }
102 | $text = html_writer::tag('div', $text, array('class' => 'text preformatted'));
103 |
104 | $cell->text = $date . html_writer::tag('div', $userinfo . ' ' . $commitmsg . $commithash, array('class' => 'usermessage')) . $text;
105 | $none->text = ' ';
106 |
107 | $row = new html_table_row(array($encell, $langcell));
108 | $table->data[] = $row;
109 | }
110 |
111 | echo html_writer::table($table);
112 |
113 | if (!$ajax) {
114 | echo $OUTPUT->footer();
115 | }
116 |
--------------------------------------------------------------------------------
/tests/git_test.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Provides {@link local_amos_git_testcase} class.
19 | *
20 | * @package local_amos
21 | * @category test
22 | * @copyright 2019 David Mudrák
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | defined('MOODLE_INTERNAL') || die();
27 |
28 | global $CFG;
29 |
30 | /**
31 | * Test the implementation of {@link \local_amos\local\git} class.
32 | *
33 | * @copyright 2019 David Mudrák
34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 | */
36 | class local_amos_git_testcase extends basic_testcase {
37 |
38 | /**
39 | * Test {@link \local_amos\local\git::exec()}.
40 | */
41 | public function test_exec() {
42 |
43 | $repo = make_request_directory();
44 | $git = new \local_amos\local\git($repo);
45 |
46 | $out = $git->exec('init');
47 | $this->assertEquals('Initialized empty Git repository in '.$repo.'/.git/', $out[0]);
48 |
49 | file_put_contents($repo.'/README.txt', 'Hello world');
50 | $git->exec('add README.txt');
51 | $git->exec('commit -m "Adding a first file"');
52 |
53 | $out = $git->exec('log -n 1 --oneline');
54 | $this->assertTrue(strpos($out[0], 'Adding a first file') > 0);
55 |
56 | $this->expectException(Exception::class);
57 | $git->exec('add FOO.exe 2>/dev/null');
58 | }
59 |
60 | /**
61 | * Test {@link \local_amos\local\git::is_success()}.
62 | */
63 | public function test_is_success() {
64 |
65 | $repo = make_request_directory();
66 | $git = new \local_amos\local\git($repo);
67 |
68 | $git->exec('init');
69 | file_put_contents($repo.'/index.php', '');
70 | $git->exec('add .');
71 | $git->exec('commit -m "Initial commit"');
72 | $git->exec('checkout -b slave 2>/dev/null');
73 |
74 | $this->assertTrue($git->is_success('show-ref --verify --quiet refs/heads/master'));
75 | $this->assertTrue($git->is_success('show-ref --verify --quiet refs/heads/slave'));
76 | $this->assertFalse($git->is_success('show-ref --verify --quiet refs/heads/justice_exists'));
77 | }
78 |
79 | /**
80 | * Test {@link \local_amos\local\git::list_local_branches()}.
81 | */
82 | public function test_list_local_branches() {
83 |
84 | $repo = make_request_directory();
85 | $git = new \local_amos\local\git($repo);
86 |
87 | $git->exec('init');
88 | $this->assertSame([], $git->list_local_branches());
89 |
90 | file_put_contents($repo.'/index.php', '');
91 | $git->exec('add .');
92 | $git->exec('commit -m "Initial commit"');
93 | $this->assertEquals(['master'], $git->list_local_branches());
94 |
95 | $git->exec('checkout -b slave 2>/dev/null');
96 | $this->assertEquals(2, count($git->list_local_branches()));
97 | $this->assertContains('master', $git->list_local_branches());
98 | $this->assertContains('slave', $git->list_local_branches());
99 | }
100 |
101 | /**
102 | * Test {@link \local_amos\local\git::has_local_branch()}.
103 | */
104 | public function test_has_local_branch() {
105 |
106 | $repo = make_request_directory();
107 | $git = new \local_amos\local\git($repo);
108 |
109 | $git->exec('init');
110 | file_put_contents($repo.'/index.php', '');
111 | $git->exec('add .');
112 | $git->exec('commit -m "Initial commit"');
113 | $git->exec('checkout -b slave 2>/dev/null');
114 |
115 | $this->assertTrue($git->has_local_branch('master'));
116 | $this->assertTrue($git->has_local_branch('slave'));
117 | $this->assertFalse($git->has_local_branch('justice_exists'));
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/cli/enfix-merge.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * @package local_amos
20 | * @subpackage enfix
21 | * @copyright 2013 David Mudrak
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | $help =
26 | "Merges en_fix strings into the Git working directory.
27 |
28 | Options:
29 |
30 | --symlinksdir Full path to the directory with symbolic links generated
31 | by the enfix-makesymlinks.sh script
32 | --enfixdir Full path to the directory containing en_fix string files
33 | generated by enfix-export.php script
34 | --help, -h Print out this help
35 |
36 | Example:
37 | \$ php enfix-merge.php --symlinksdir=/home/mudrd8mz/public_html/moodle25/amos --enfixdir=/home/mudrd8mz/moodledata/moodle24amos/amos/export-enfix/2.5
38 | ";
39 |
40 | define('CLI_SCRIPT', true);
41 |
42 | require_once(dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php');
43 | require_once($CFG->dirroot . '/local/amos/cli/config.php');
44 | require_once($CFG->dirroot . '/local/amos/mlanglib.php');
45 | require_once($CFG->dirroot . '/local/amos/cli/utilslib.php');
46 |
47 | list($options, $unrecognized) = cli_get_params(
48 | array(
49 | 'symlinksdir' => '',
50 | 'enfixdir' => '',
51 | 'help' => false),
52 | array('h' => 'help'));
53 |
54 |
55 | if ($options['help'] or empty($options['symlinksdir']) or empty($options['enfixdir'])) {
56 | cli_error($help, 2);
57 | }
58 |
59 | // Make sure that all target files exist, are symlinks and are writable.
60 |
61 | foreach (new DirectoryIterator($options['enfixdir']) as $enfixfileinfo) {
62 | if ($enfixfileinfo->isDot()) {
63 | continue;
64 | }
65 | $filename = $enfixfileinfo->getFilename();
66 |
67 | if (!is_link($options['symlinksdir'].'/'.$filename)) {
68 | cli_error('File not symlink: '.$options['symlinksdir'].'/'.$filename);
69 | }
70 |
71 | if (!is_writable($options['symlinksdir'].'/'.$filename)) {
72 | cli_error('File not writable: '.$options['symlinksdir'].'/'.$filename);
73 | }
74 | }
75 |
76 | // Let's rock!
77 |
78 | $logger = new amos_cli_logger();
79 | $helper = new amos_merge_string_files($logger);
80 | $total = 0;
81 |
82 | foreach (new DirectoryIterator($options['enfixdir']) as $enfixfileinfo) {
83 | if ($enfixfileinfo->isDot()) {
84 | continue;
85 | }
86 | $filename = $enfixfileinfo->getFilename();
87 |
88 | $logger->log('enfix-merge', 'Processing file '.$filename.' ...');
89 |
90 | if ($filename === 'langconfig.php') {
91 | $logger->log('enfix-merge', 'Skipping file '.$filename, amos_cli_logger::LEVEL_DEBUG);
92 | continue;
93 | }
94 |
95 | $filecontents = file_get_contents($options['symlinksdir'].'/'.$filename);
96 |
97 | $fromstrings = $helper->load_strings_from_file($options['symlinksdir'].'/'.$filename);
98 | $logger->log('enfix-merge', count($fromstrings).' string(s) found in '.$options['symlinksdir'].'/'.$filename, amos_cli_logger::LEVEL_DEBUG);
99 |
100 | $tostrings = $helper->load_strings_from_file($options['enfixdir'].'/'.$filename);
101 | $logger->log('enfix-merge', count($tostrings).' string(s) found in '.$options['enfixdir'].'/'.$filename, amos_cli_logger::LEVEL_DEBUG);
102 |
103 | $changes = $helper->replace_strings_in_file($filecontents, $fromstrings, $tostrings);
104 |
105 | if ($changes) {
106 | $total += $changes;
107 | file_put_contents($options['symlinksdir'].'/'.$filename, $filecontents);
108 | $logger->log('enfix-merge', $changes.' string(s) fixed in '.$filename);
109 | } else if ($changes === 0) {
110 | $logger->log('enfix-merge', 'No changes in '.$filename);
111 | } else {
112 | $logger->log('enfix-merge', 'Error while processing file '.$filename, amos_cli_logger::LEVEL_ERROR);
113 | }
114 | }
115 |
116 | $logger->log('enfix-merge', 'Finished! Total of '.$total.' string(s) merged.');
117 |
--------------------------------------------------------------------------------
/cli/import-strings.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * Imports English strings for a given component from PHP file
20 | *
21 | * This is used typically for contributed plugins.
22 | *
23 | * @package local
24 | * @subpackage amos
25 | * @copyright 2011 David Mudrak
26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 | */
28 |
29 | define('CLI_SCRIPT', true);
30 |
31 | require_once(dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php');
32 | require_once($CFG->dirroot . '/local/amos/cli/config.php');
33 | require_once($CFG->dirroot . '/local/amos/mlanglib.php');
34 | require_once($CFG->libdir.'/clilib.php');
35 |
36 | list($options, $unrecognized) = cli_get_params(array(
37 | 'lang' => 'en',
38 | 'version' => 'MOODLE_21_STABLE',
39 | 'timemodified' => null,
40 | 'name' => null,
41 | 'format' => 2,
42 | 'message' => '',
43 | 'userinfo' => 'David Mudrak ',
44 | 'commithash' => null,
45 | 'yes' => false,
46 | 'help' => false
47 |
48 | ), array('h' => 'help'));
49 |
50 | $usage = <<'
64 | --commithash Allows to specify the git commit hash
65 | --yes It won't ask to continue
66 | --help Show this usage
67 |
68 | The file is directly included into the PHP processor. Make sure to review the file
69 | for a malicious contents before you import it via this script.
70 |
71 | EOF;
72 |
73 | if ($options['help'] or empty($options['message']) or empty($unrecognized)) {
74 | echo $usage . PHP_EOL;
75 | exit(1);
76 | }
77 |
78 | $filepath = $unrecognized[0];
79 | if (!is_readable($filepath)) {
80 | echo 'File "'.$filepath.'" not readable' . PHP_EOL;
81 | echo $usage . PHP_EOL;
82 | exit(2);
83 | }
84 |
85 | $version = mlang_version::by_branch($options['version']);
86 | if (is_null($version)) {
87 | echo 'Invalid version' . PHP_EOL;
88 | exit(3);
89 | }
90 |
91 | $component = mlang_component::from_phpfile($filepath, $options['lang'], $version,
92 | $options['timemodified'], $options['name'], (int)$options['format']);
93 |
94 | fputs(STDOUT, "{$component->name} {$component->version->label} {$component->lang}" . PHP_EOL);
95 |
96 | $stage = new mlang_stage();
97 | $stage->add($component);
98 | $stage->rebase(null, true, $options['timemodified']);
99 |
100 | if (!$stage->has_component()) {
101 | echo 'No strings found (after rebase)' . PHP_EOL;
102 | exit(4);
103 | }
104 |
105 | foreach ($stage->get_iterator() as $component) {
106 | foreach ($component->get_iterator() as $string) {
107 | if ($string->deleted) {
108 | $sign = '-';
109 | } else {
110 | $sign = '+';
111 | }
112 | echo $sign . ' ' . $string->id . PHP_EOL;
113 | }
114 | }
115 |
116 | echo PHP_EOL;
117 | if (!$options['yes']) {
118 | $continue = cli_input('Continue? [y/n]', 'n', array('y', 'n'));
119 | if ($continue !== 'y') {
120 | echo 'Import aborted' . PHP_EOL;
121 | exit(5);
122 | }
123 | }
124 |
125 | $meta = array('source' => 'import', 'userinfo' => $options['userinfo']);
126 | if ($options['commithash']) {
127 | $meta['commithash'] = $commithash;
128 | }
129 |
130 | $stage->commit($options['message'], $meta, true);
131 |
--------------------------------------------------------------------------------
/cli/enfix-cleanup.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * Deletes all en_fix strings that are merged into the en pack.
20 | *
21 | * @package local_amos
22 | * @copyright 2013 David Mudrak
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | define('CLI_SCRIPT', true);
27 |
28 | require(dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php');
29 | require_once($CFG->libdir . '/clilib.php');
30 | require_once($CFG->dirroot . '/local/amos/cli/config.php');
31 | require_once($CFG->dirroot . '/local/amos/mlanglib.php');
32 |
33 | list($options, $unrecognized) = cli_get_params(array('execute' => false, 'aggresive' => false));
34 |
35 | fputs(STDOUT, "*****************************************\n");
36 | fputs(STDOUT, date('Y-m-d H:i', time()));
37 | fputs(STDOUT, " ENFIX CLEANUP JOB STARTED\n");
38 |
39 | // Get an information about existing strings in the en_fix
40 | $sql = "SELECT branch,lang,component,COUNT(stringid) AS numofstrings
41 | FROM {amos_repository}
42 | WHERE deleted=0
43 | AND lang='en_fix'
44 | GROUP BY branch,lang,component
45 | ORDER BY branch,lang,component";
46 | $rs = $DB->get_recordset_sql($sql);
47 | $tree = array(); // [branch][language][component] => numofstrings
48 | foreach ($rs as $record) {
49 | $tree[$record->branch][$record->lang][$record->component] = $record->numofstrings;
50 | }
51 | $rs->close();
52 |
53 | $stage = new mlang_stage();
54 |
55 | foreach ($tree as $vercode => $languages) {
56 | $version = mlang_version::by_code($vercode);
57 | foreach ($languages as $langcode => $components) {
58 | if ($langcode !== 'en_fix') {
59 | throw new coding_exception('Unexpected language');
60 | }
61 | foreach ($components as $componentname => $unused) {
62 | $en = mlang_component::from_snapshot($componentname, 'en', $version);
63 | $enfix = mlang_component::from_snapshot($componentname, $langcode, $version);
64 | $enfix->intersect($en);
65 | $removed = $enfix->complement($en);
66 |
67 | if ($options['aggresive']) {
68 | foreach ($enfix->get_iterator() as $enfixstring) {
69 | $enstring = $en->get_string($enfixstring->id);
70 | if ($enstring === null) {
71 | fputs(STDERR, 'orphaned string '.$enfixstring->id.' in '.$componentname.' '.$version->label.PHP_EOL);
72 | continue;
73 | }
74 | if ($enstring->timemodified > $enfixstring->timemodified) {
75 | fputs(STDERR, 'string '.$enfixstring->id.' outdated in '.$componentname.' '.$version->label.PHP_EOL);
76 | $enfix->unlink_string($enfixstring->id);
77 | $removed++;
78 | }
79 | }
80 | }
81 |
82 | if ($removed) {
83 |
84 | if ($options['execute']) {
85 | $action = 'removing';
86 | } else {
87 | $action = 'would remove';
88 | }
89 |
90 | fputs(STDERR, $action.' '.$removed.' string(s) from '.$componentname.' '.$version->label.PHP_EOL);
91 |
92 | if ($options['execute']) {
93 | $stage->add($enfix);
94 | $stage->rebase(null, true);
95 | $msg = 'Clean-up strings that were merged into the English pack';
96 | $stage->commit($msg, array('source' => 'bot', 'userinfo' => 'AMOS-bot '), true);
97 | } else {
98 | $stage->clear();
99 | }
100 | } else {
101 | fputs(STDERR, 'nothing to do in '.$componentname.' '.$version->label.PHP_EOL);
102 | }
103 | $en->clear();
104 | $enfix->clear();
105 | }
106 | }
107 | }
108 |
109 | fputs(STDOUT, date('Y-m-d H:i', time()));
110 | fputs(STDOUT, " ENFIX CLEANUP JOB DONE\n");
111 |
--------------------------------------------------------------------------------
/translate.ajax.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * @package local_amos
20 | * @copyright 2012 David Mudrak
21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22 | */
23 |
24 | define('AJAX_SCRIPT', true);
25 |
26 | require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
27 | require_once($CFG->libdir.'/filelib.php');
28 |
29 | require_login(SITEID, false);
30 |
31 | if (!has_capability('local/amos:usegoogle', context_system::instance())) {
32 | error_log('AMOS No capability to fetching Google translation');
33 | header('HTTP/1.1 403 Forbidden');
34 | die();
35 | }
36 |
37 | if (!confirm_sesskey(optional_param('sesskey', -1, PARAM_RAW))) {
38 | error_log('AMOS Invalid sesskey');
39 | header('HTTP/1.1 403 Forbidden');
40 | die();
41 | }
42 |
43 | $enid = optional_param('enid', null, PARAM_INT);
44 | $lang = optional_param('lng', null, PARAM_SAFEDIR);
45 | if (is_null($enid) or empty($lang)) {
46 | error_log('AMOS Invalid parameters provided');
47 | header('HTTP/1.1 400 Bad Request');
48 | die();
49 | }
50 |
51 | if (empty($CFG->amosgoogleapi)) {
52 | header('HTTP/1.1 500 Internal Server Error - Google API key not defined');
53 | die();
54 | }
55 |
56 | try {
57 | $string = $DB->get_record_sql("SELECT t.text AS text
58 | FROM {amos_repository} r
59 | JOIN {amos_texts} t ON t.id = r.textid
60 | WHERE r.id = :enid AND r.lang = :lang AND r.deleted = 0",
61 | array('enid' => $enid, 'lang' => 'en'), MUST_EXIST);
62 |
63 | } catch (Exception $e) {
64 | error_log('AMOS Unable to find the string to translate');
65 | header('HTTP/1.1 400 Bad Request');
66 | die();
67 | }
68 |
69 | add_to_log(SITEID, 'amos', 'usegoogle', '', $enid, 0, $USER->id);
70 |
71 | $entext = str_replace('{$a}', 'PLACEHOLDERA__', $string->text);
72 | $entext = preg_replace('/\{\$a->(.+?)\}/', 'PLACEHOLDER__$1__', $entext);
73 |
74 | // map Moodle language codes to Google language codes
75 | switch ($lang) {
76 | case 'zh_cn':
77 | $lang = 'zh-CN';
78 | break;
79 | case 'zh_tw':
80 | $lang = 'zh-TW';
81 | break;
82 | case 'pt_br':
83 | $lang = 'pt';
84 | break;
85 | case 'he':
86 | $lang = 'iw';
87 | break;
88 | }
89 |
90 | $curl = new curl(array('cache' => false, 'proxy' => true));
91 | $params = array(
92 | 'key' => $CFG->amosgoogleapi,
93 | 'format' => 'html',
94 | 'prettyprint' => 'false',
95 | 'source' => 'en',
96 | 'target' => $lang,
97 | 'userIp' => getremoteaddr(),
98 | 'q' => $entext,
99 | );
100 |
101 | $response = $curl->get('https://www.googleapis.com/language/translate/v2', $params);
102 | $curlinfo = $curl->get_info();
103 |
104 | $translation = null;
105 |
106 | if (empty($curlinfo)) {
107 | error_log('AMOS Unable to fetch Google translation - empty cURL info');
108 |
109 | } else if ($curlinfo['http_code'] != 200) {
110 | error_log('AMOS Fetching Google translation - got HTTP response '.$curlinfo['http_code']);
111 |
112 | } else if ($response) {
113 | $response = json_decode($response);
114 | if (!empty($response->data->translations) and is_array($response->data->translations)) {
115 | $first = reset($response->data->translations);
116 | if (isset($first->translatedText)) {
117 | $translation = s($first->translatedText);
118 | }
119 | }
120 | }
121 |
122 | if (is_null($translation)) {
123 | $response = array(
124 | 'error' => array(
125 | 'message' => 'Unable to translate this at the moment'
126 | )
127 | );
128 |
129 | } else {
130 | $translation = preg_replace('/PLACEHOLDER__(.+?)__/', '{$a->$1}', $translation);
131 | $translation = str_replace('PLACEHOLDERA__', '{$a}', $translation);
132 |
133 | $response = array(
134 | 'data' => array(
135 | 'translation' => $translation,
136 | )
137 | );
138 | }
139 |
140 | header('Content-Type: application/json; charset: utf-8');
141 | echo json_encode($response);
142 |
--------------------------------------------------------------------------------
/cli/export-installer.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * Exports the strings needed by the installer
20 | *
21 | * Moodle core contains a subset of strings needed for the start of the installation.
22 | * The list of required strings is maintained in install/stringnames.txt. This
23 | * script parses that file and exports the translations into a configured destination.
24 | *
25 | * @package local_amos
26 | * @copyright 2010 David Mudrak
27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28 | */
29 |
30 | define('CLI_SCRIPT', true);
31 |
32 | require_once(dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php');
33 | require_once($CFG->dirroot . '/local/amos/cli/config.php');
34 | require_once($CFG->dirroot . '/local/amos/mlanglib.php');
35 |
36 | // list of branches to process
37 | $branches = array(
38 | 'MOODLE_35_STABLE',
39 | 'MOODLE_36_STABLE',
40 | 'MOODLE_37_STABLE',
41 | 'MOODLE_38_STABLE',
42 | );
43 |
44 | fputs(STDOUT, "*****************************************\n");
45 | fputs(STDOUT, date('Y-m-d H:i', time()));
46 | fputs(STDOUT, " EXPORT INSTALLER JOB STARTED\n");
47 |
48 | remove_dir(AMOS_EXPORT_INSTALLER_DIR, true);
49 |
50 | foreach ($branches as $branch) {
51 | fputs(STDOUT, "BRANCH {$branch}\n");
52 | if ($branch == 'MOODLE_38_STABLE') {
53 | $gitbranch = 'origin/master';
54 | } else {
55 | $gitbranch = 'origin/' . $branch;
56 | }
57 | $version = mlang_version::by_branch($branch);
58 |
59 | // read the contents of stringnames.txt at the given branch
60 | chdir(AMOS_REPO_MOODLE);
61 | $gitout = array();
62 | $gitstatus = 0;
63 | $gitcmd = AMOS_PATH_GIT . " show {$gitbranch}:install/stringnames.txt";
64 | exec($gitcmd, $gitout, $gitstatus);
65 |
66 | if ($gitstatus <> 0) {
67 | fputs(STDERR, "ERROR EXECUTING {$gitcmd}\n");
68 | exit($gitstatus);
69 | }
70 |
71 | $list = array(); // [component][stringid] => true
72 | foreach ($gitout as $string) {
73 | list($stringid, $component) = array_map('trim', explode(',', $string));
74 | $list[$component][$stringid] = true;
75 | }
76 | unset($gitout);
77 |
78 | $tree = mlang_tools::components_tree(array('branch' => $version->code));
79 | $langs = array_keys($tree[$version->code]);
80 | unset($tree);
81 |
82 | $phpdoc = << $stringids) {
102 | foreach ($langs as $lang) {
103 | if ($lang === 'en_fix') {
104 | continue;
105 | }
106 | $component = mlang_component::from_snapshot($componentname, $lang, $version, null, false, false, array_keys($stringids));
107 | if ($component->has_string()) {
108 | $file = AMOS_EXPORT_INSTALLER_DIR . '/' . $version->dir . '/install/lang/' . $lang . '/' . $component->name . '.php';
109 | if (!file_exists(dirname($file))) {
110 | mkdir(dirname($file), 0755, true);
111 | }
112 | $component->export_phpfile($file, $phpdoc);
113 | }
114 | if ($lang == 'en') {
115 | // check that all string were exported
116 | foreach (array_keys($stringids) as $stringid) {
117 | if (!$component->has_string($stringid)) {
118 | fputs(STDERR, "ERROR Unknown $stringid,$componentname\n");
119 | $status = 1;
120 | }
121 | }
122 | }
123 | $component->clear();
124 | }
125 | }
126 | }
127 |
128 | fputs(STDOUT, date('Y-m-d H:i', time()));
129 | fputs(STDOUT, " EXPORT INSTALLER JOB DONE\n");
130 |
131 | exit($status);
132 |
--------------------------------------------------------------------------------
/cli/rev-clean.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * Propagates deletions of English strings into the other lang packs
20 | *
21 | * The procedure is known as reverse cleanup. This script takes the most recent
22 | * snapshot of every component in the English lang pack. If a string removal is
23 | * part of the snapshot, the script propagates such removal into all other
24 | * languages. If the string is already removed in the other language, the
25 | * removing commit is not recorded.
26 | *
27 | * By default, the script checks just for the recent deletions, not older
28 | * than one day. During the initial import and once per day, for example,
29 | * run it with --full argument to re-check all the history, so that commits
30 | * dated into past are propadagated as well (full check takes ~30 mins).
31 | *
32 | * @package local_amos
33 | * @copyright 2010 David Mudrak
34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 | */
36 |
37 | define('CLI_SCRIPT', true);
38 |
39 | require_once(dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php');
40 | require_once($CFG->dirroot . '/local/amos/cli/config.php');
41 | require_once($CFG->dirroot . '/local/amos/mlanglib.php');
42 | require_once($CFG->dirroot . '/local/amos/renderer.php');
43 | require_once($CFG->libdir.'/clilib.php');
44 |
45 | list($options, $unrecognized) = cli_get_params(array('full'=>false), array('f'=>'full'));
46 |
47 | fputs(STDOUT, "*****************************************\n");
48 | fputs(STDOUT, date('Y-m-d H:i', time()));
49 | fputs(STDOUT, " REVERSE CLEANUP JOB STARTED\n");
50 |
51 | $mem = memory_get_usage();
52 | $tree = mlang_tools::components_tree();
53 | foreach ($tree as $vercode => $languages) {
54 | $version = mlang_version::by_code($vercode);
55 | foreach ($languages['en'] as $componentname => $unused) {
56 | if ($componentname == 'langconfig') {
57 | continue;
58 | }
59 | $memprev = $mem;
60 | $mem = memory_get_usage();
61 | $memdiff = $memprev < $mem ? '+' : '-';
62 | $memdiff = $memdiff . abs($mem - $memprev);
63 | $english = mlang_component::from_snapshot($componentname, 'en', $version, null, true, true);
64 | foreach ($english->get_iterator() as $string) {
65 | if (empty($options['full']) and $string->timemodified < time() - DAYSECS) {
66 | continue;
67 | }
68 | if ($string->deleted) {
69 | // propagate removal of this string to all other languages where it is present
70 | $stage = new mlang_stage();
71 | foreach (array_keys($tree[$vercode]) as $otherlang) {
72 | if ($otherlang == 'en') {
73 | continue;
74 | }
75 | $other = mlang_component::from_snapshot($componentname, $otherlang, $version, null, true, false, array($string->id));
76 | if ($other->has_string($string->id)) {
77 | $current = $other->get_string($string->id);
78 | if (!$current->deleted) {
79 | $current->deleted = true;
80 | $current->timemodified = time();
81 | $stage->add($other);
82 | }
83 | }
84 | $other->clear();
85 | unset($other);
86 | }
87 | $stage->rebase();
88 | if ($stage->has_component()) {
89 | $string->timemodified = local_amos_renderer::commit_datetime($string->timemodified);
90 | $msg = <<id}' was removed from the English language pack by
94 | {$string->extra->userinfo} at {$string->timemodified}. Their commit message was:
95 | {$string->extra->commitmsg}
96 | {$string->extra->commithash}
97 | EOF;
98 | fputs(STDOUT, "COMMIT removal of '{$string->id}' from '{$english->name}'\n");
99 | $stage->commit($msg, array('source' => 'revclean', 'userinfo' => 'AMOS-bot '), true);
100 | }
101 | $stage->clear();
102 | unset($stage);
103 | }
104 | }
105 | }
106 | }
107 |
108 | fputs(STDOUT, date('Y-m-d H:i', time()));
109 | fputs(STDOUT, " REVERSE CLEANUP JOB DONE\n");
110 |
--------------------------------------------------------------------------------
/credits.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * Displays maintainers and contributors per language
20 | *
21 | * @package local_amos
22 | * @copyright 2013 David Mudrak
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | require_once(__DIR__.'/../../config.php');
27 | require_once($CFG->dirroot.'/local/amos/locallib.php');
28 | require_once($CFG->dirroot.'/local/amos/mlanglib.php');
29 | require_once($CFG->dirroot.'/local/amos/renderer.php');
30 |
31 | $editmode = optional_param('editmode', false, PARAM_BOOL);
32 | $canedit = has_capability('local/amos:manage', context_system::instance());
33 |
34 | if (!$canedit) {
35 | $editmode = false;
36 | } else if (!$editmode) {
37 | $editmode = null;
38 | } else {
39 | $editmode = true;
40 | }
41 |
42 | $PAGE->set_context(context_system::instance());
43 | $PAGE->set_pagelayout('standard');
44 | $PAGE->set_url('/local/amos/credits.php');
45 | $PAGE->set_title(get_string('creditstitleshort', 'local_amos'));
46 | $PAGE->set_heading(get_string('creditstitleshort', 'local_amos'));
47 |
48 | if ($canedit and $editmode) {
49 | $PAGE->set_button($OUTPUT->single_button(new moodle_url($PAGE->url, array('editmode' => 0)), get_string('turneditingoff'), 'get'));
50 | $PAGE->set_url(new moodle_url($PAGE->url, array('editmode' => 1)));
51 | } else if ($canedit and !$editmode) {
52 | $PAGE->set_button($OUTPUT->single_button(new moodle_url($PAGE->url, array('editmode' => 1)), get_string('turneditingon'), 'get'));
53 | }
54 |
55 | $languages = mlang_tools::list_languages(false, true, false);
56 |
57 | // Get the list of known languages.
58 |
59 | foreach ($languages as $langcode => $langname) {
60 | $list[$langcode] = (object)array('langname' => $langname, 'maintainers' => array(), 'contributors' => array());
61 | }
62 |
63 | // Get the list of maintainers, explicitly assigned contributors and
64 | // other contributors based on submitted contributions.
65 |
66 | $userfields = user_picture::fields('u');
67 | list($sortsql, $sortparams) = users_order_by_sql();
68 |
69 | $sql = "SELECT t.lang AS amoslang, t.status AS contribstatus, 1 AS iseditable, {$userfields}
70 | FROM {amos_translators} t
71 | JOIN {user} u ON t.userid = u.id
72 | WHERE t.lang <> 'X' AND t.lang <> 'en'
73 |
74 | UNION
75 |
76 | SELECT c.lang AS amoslang, ".AMOS_USER_CONTRIBUTOR." AS contribstatus, 0 AS iseditable, {$userfields}
77 | FROM {amos_contributions} c
78 | JOIN {user} u ON c.authorid = u.id
79 | WHERE c.status = :status
80 | GROUP BY c.lang, {$userfields}
81 | HAVING COUNT(*) >= 3
82 |
83 | ORDER BY amoslang, contribstatus, {$sortsql}, iseditable";
84 |
85 | $rs = $DB->get_recordset_sql($sql, array_merge($sortparams,
86 | array('status' => local_amos_contribution::STATE_ACCEPTED)));
87 |
88 | // Track credits with unexpected data.
89 | $issues = array();
90 |
91 | foreach ($rs as $user) {
92 |
93 | $lang = $user->amoslang;
94 | if (empty($lang)) {
95 | $issues[] = (object)array(
96 | 'problem' => 'Empty contribution language',
97 | 'record' => $user,
98 | );
99 | continue;
100 | }
101 | unset($user->amoslang);
102 |
103 | $status = $user->contribstatus;
104 | unset($user->contribstatus);
105 |
106 | if (empty($list[$lang])) {
107 | $issues[] = (object)array(
108 | 'problem' => 'Unknown language',
109 | 'record' => $user,
110 | );
111 | continue;
112 | }
113 |
114 | if ($status == AMOS_USER_MAINTAINER) {
115 | if (!isset($list[$lang]->maintainers[$user->id])) {
116 | $list[$lang]->maintainers[$user->id] = $user;
117 | }
118 |
119 | } else if ($status == AMOS_USER_CONTRIBUTOR) {
120 | if (!isset($list[$lang]->maintainers[$user->id]) and !isset($list[$lang]->contributors[$user->id])) {
121 | $list[$lang]->contributors[$user->id] = $user;
122 | }
123 |
124 | } else {
125 | $issues[] = (object)array(
126 | 'problem' => 'Unknown credit status',
127 | 'record' => $user,
128 | );
129 | continue;
130 | }
131 | }
132 |
133 | $rs->close();
134 |
135 | // Output starts here
136 | echo $OUTPUT->header();
137 |
138 | $output = $PAGE->get_renderer('local_amos');
139 | echo $output->page_credits($list, current_language(), $editmode);
140 |
141 | if (!empty($issues) and has_capability('local/amos:manage', $PAGE->context)) {
142 | echo $output->page_credits_issues($issues);
143 | }
144 |
145 | echo $OUTPUT->footer();
146 |
--------------------------------------------------------------------------------
/importfile.php:
--------------------------------------------------------------------------------
1 | .
17 |
18 | /**
19 | * Import strings from uploaded file and stage them
20 | *
21 | * @package local
22 | * @subpackage amos
23 | * @copyright 2010 David Mudrak
24 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 | */
26 |
27 | require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
28 | require_once(dirname(__FILE__).'/locallib.php');
29 | require_once(dirname(__FILE__).'/mlanglib.php');
30 | require_once(dirname(__FILE__).'/mlangparser.php');
31 | require_once(dirname(__FILE__).'/importfile_form.php');
32 |
33 | require_login(SITEID, false);
34 | require_capability('local/amos:importfile', context_system::instance());
35 |
36 | $PAGE->set_pagelayout('standard');
37 | $PAGE->set_url('/local/amos/importfile.php');
38 | navigation_node::override_active_url(new moodle_url('/local/amos/stage.php'));
39 | $PAGE->set_title('AMOS ' . get_string('importfile', 'local_amos'));
40 | $PAGE->set_heading('AMOS ' . get_string('importfile', 'local_amos'));
41 |
42 | $importform = new local_amos_importfile_form(null, local_amos_importfile_options());
43 |
44 | if (($data = $importform->get_data()) and has_capability('local/amos:stage', context_system::instance())) {
45 | $tmpdir = $CFG->dataroot . '/amos/temp/import-uploads/' . $USER->id;
46 | check_dir_exists($tmpdir);
47 | $filenameorig = basename($importform->get_new_filename('importfile'));
48 | $filename = $filenameorig . '-' . md5(time() . '-' . $USER->id . '-'. random_string(20));
49 | $pathname = $tmpdir . '/' . $filename;
50 |
51 | if ($importform->save_file('importfile', $pathname)) {
52 |
53 | // Prepare the list of files to import.
54 | $stringfiles = array();
55 |
56 | if (strtolower(substr($filenameorig, -4)) === '.zip') {
57 | $tmpzipdir = $pathname . '-content';
58 | check_dir_exists($tmpzipdir);
59 | $fp = get_file_packer('application/zip');
60 | $zipcontents = $fp->extract_to_pathname($pathname, $tmpzipdir);
61 | if (!$zipcontents) {
62 | notice(get_string('novalidzip', 'local_amos'), new moodle_url('/local/amos/stage.php'));
63 | @remove_dir($tmpzipdir);
64 | } else {
65 | foreach ($zipcontents as $zipfilename => $zipfilestatus) {
66 | // We want PHP files in the root of the ZIP only.
67 | if ($zipfilestatus === true and basename($zipfilename) === $zipfilename and strtolower(substr($zipfilename, -4)) === '.php') {
68 | $stringfiles[$zipfilename] = $tmpzipdir . '/' . $zipfilename;
69 | }
70 | }
71 | }
72 |
73 | } else if (strtolower(substr($filenameorig, -4)) === '.php') {
74 | $stringfiles = array($filenameorig => $pathname);
75 | }
76 |
77 | if (empty($stringfiles)) {
78 | notice(get_string('nostringtoimport', 'local_amos'), new moodle_url('/local/amos/stage.php'));
79 |
80 | } else {
81 | $stage = mlang_persistent_stage::instance_for_user($USER->id, sesskey());
82 | $version = mlang_version::by_code($data->version);
83 | $parser = mlang_parser_factory::get_parser('php');
84 |
85 | foreach ($stringfiles as $filenameorig => $pathname) {
86 | $name = mlang_component::name_from_filename($filenameorig);
87 | $component = new mlang_component($name, $data->language, $version);
88 |
89 | try {
90 | $parser->parse(file_get_contents($pathname), $component);
91 |
92 | } catch (mlang_parser_exception $e) {
93 | notice($e->getMessage(), new moodle_url('/local/amos/stage.php'));
94 | }
95 |
96 | $encomponent = mlang_component::from_snapshot($component->name, 'en', $version);
97 | $component->intersect($encomponent);
98 |
99 | if ($component->has_string()) {
100 | $stage->add($component, true);
101 | $component->clear();
102 | $stage->store();
103 | }
104 | }
105 | mlang_stash::autosave($stage);
106 | }
107 |
108 | if (!empty($tmpzipdir)) {
109 | @remove_dir($tmpzipdir);
110 | }
111 |
112 | } else {
113 | notice(get_string('nofiletoimport', 'local_amos'), new moodle_url('/local/amos/stage.php'));
114 | }
115 | }
116 |
117 | if (!isset($stage) or !$stage->has_component()) {
118 | notice(get_string('nostringtoimport', 'local_amos'), new moodle_url('/local/amos/stage.php'));
119 | }
120 |
121 | redirect(new moodle_url('/local/amos/stage.php'));
122 |
--------------------------------------------------------------------------------