234 lines
8.7 KiB
PHP
234 lines
8.7 KiB
PHP
<?php
|
|
/**
|
|
* Piwik - free/libre analytics platform
|
|
*
|
|
* @link http://piwik.org
|
|
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
|
*
|
|
*/
|
|
|
|
namespace Piwik\Plugins\LanguagesManager\Commands;
|
|
|
|
use Piwik\Plugins\LanguagesManager\API;
|
|
use Symfony\Component\Console\Input\ArrayInput;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
|
|
/**
|
|
*/
|
|
class CreatePull extends TranslationBase
|
|
{
|
|
const GIT_BASE_BRANCH = '3.x-dev';
|
|
|
|
protected function configure()
|
|
{
|
|
$this->setName('translations:createpull')
|
|
->setDescription('Updates translation files')
|
|
->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'Transifex username')
|
|
->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'Transifex password')
|
|
->addOption('slug', 's', InputOption::VALUE_OPTIONAL, 'Transifex project slug')
|
|
->addOption('plugin', 'P', InputOption::VALUE_OPTIONAL, 'optional name of plugin to update translations for');
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output)
|
|
{
|
|
$changes = shell_exec('git status --porcelain -uno');
|
|
|
|
if (!empty($changes)) {
|
|
|
|
$output->writeln("You have uncommited changes. Creating pull request is only available with a clean working directory");
|
|
return;
|
|
}
|
|
|
|
$unpushedCommits = shell_exec('git log origin/' . self::GIT_BASE_BRANCH . '..HEAD');
|
|
|
|
if (!empty($unpushedCommits)) {
|
|
|
|
$output->writeln("You have unpushed commits. Creating pull request is only available with a clean working directory");
|
|
return;
|
|
}
|
|
|
|
chdir(PIWIK_DOCUMENT_ROOT);
|
|
|
|
shell_exec('
|
|
git checkout -f ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
|
|
git pull > /dev/null 2>&1
|
|
git submodule init > /dev/null 2>&1
|
|
git submodule update > /dev/null 2>&1
|
|
');
|
|
|
|
$plugin = $input->getOption('plugin');
|
|
if (!empty($plugin)) {
|
|
|
|
chdir(PIWIK_DOCUMENT_ROOT.DIRECTORY_SEPARATOR.'plugins'.DIRECTORY_SEPARATOR.$plugin);
|
|
shell_exec('
|
|
git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
|
|
git pull > /dev/null 2>&1
|
|
');
|
|
}
|
|
|
|
// check if branch exists localy and track it if not
|
|
$branch = shell_exec('git branch | grep translationupdates');
|
|
|
|
if (empty($branch)) {
|
|
|
|
shell_exec('git checkout -b translationupdates origin/translationupdates');
|
|
}
|
|
|
|
// switch to branch and update it to latest $GIT_BASE_BRANCH
|
|
shell_exec('
|
|
git checkout -f translationupdates > /dev/null 2>&1
|
|
git reset --hard origin/' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
|
|
git push origin translationupdates > /dev/null 2>&1
|
|
');
|
|
|
|
// update translation files
|
|
$command = $this->getApplication()->find('translations:update');
|
|
$arguments = array(
|
|
'command' => 'translations:update',
|
|
'--username' => $input->getOption('username'),
|
|
'--password' => $input->getOption('password'),
|
|
'--slug' => $input->getOption('slug'),
|
|
'--plugin' => $plugin
|
|
);
|
|
$inputObject = new ArrayInput($arguments);
|
|
$inputObject->setInteractive($input->isInteractive());
|
|
$command->run($inputObject, $output);
|
|
|
|
shell_exec('git add lang/. > /dev/null 2>&1');
|
|
|
|
if (empty($plugin)) {
|
|
foreach (Update::getPluginsInCore() as $pluginName) {
|
|
shell_exec(sprintf('git add plugins/%s/lang/. > /dev/null 2>&1', $pluginName));
|
|
}
|
|
}
|
|
|
|
$changes = shell_exec('git status --porcelain -uno');
|
|
|
|
if (empty($changes)) {
|
|
|
|
$output->writeln("Nothing changed. Everything is already up to date.");
|
|
shell_exec('git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1');
|
|
return;
|
|
}
|
|
|
|
API::unsetInstance(); // reset languagemanager api (to force refresh of data)
|
|
|
|
$stats = shell_exec('git diff --numstat HEAD');
|
|
|
|
preg_match_all('/([0-9]+)\t([0-9]+)\t[a-zA-Z\/]*lang\/([a-z]{2,3}(?:-[a-z]{2,3})?)\.json/', $stats, $lineChanges);
|
|
|
|
$addedLinesSum = 0;
|
|
if (!empty($lineChanges[1])) {
|
|
$addedLinesSum = array_sum($lineChanges[1]);
|
|
}
|
|
|
|
$linesSumByLang = array();
|
|
$lineChangesCount = count($lineChanges[0]);
|
|
for ($i = 0; $i < $lineChangesCount; $i++) {
|
|
@$linesSumByLang[$lineChanges[3][$i]] += $lineChanges[1][$i];
|
|
}
|
|
|
|
preg_match_all('/M [a-zA-Z\/]*lang\/([a-z]{2,3}(?:-[a-z]{2,3})?)\.json/', $changes, $modifiedFiles);
|
|
preg_match_all('/A [a-zA-Z\/]*lang\/([a-z]{2,3}(?:-[a-z]{2,3})?)\.json/', $changes, $addedFiles);
|
|
|
|
$messages = array();
|
|
|
|
$languageCodesTouched = array();
|
|
if (!empty($addedFiles[1])) {
|
|
foreach ($addedFiles[1] as $addedFile) {
|
|
$languageInfo = $this->getLanguageInfoByIsoCode($addedFile);
|
|
$messages[$addedFile] = sprintf('- Added %s (%s changes / %s translated)\n', $languageInfo['english_name'], $linesSumByLang[$addedFile], $languageInfo['percentage_complete']);
|
|
}
|
|
$languageCodesTouched = array_merge($languageCodesTouched, $addedFiles[1]);
|
|
}
|
|
|
|
if (!empty($modifiedFiles[1])) {
|
|
foreach ($modifiedFiles[1] as $modifiedFile) {
|
|
if ($linesSumByLang[$modifiedFile]) {
|
|
$languageInfo = $this->getLanguageInfoByIsoCode($modifiedFile);
|
|
$messages[$modifiedFile] = sprintf(
|
|
'- Updated %s (%s changes / %s translated)\n',
|
|
$languageInfo['english_name'],
|
|
$linesSumByLang[$modifiedFile],
|
|
$languageInfo['percentage_complete']
|
|
);
|
|
$languageCodesTouched[] = $modifiedFile;
|
|
}
|
|
}
|
|
$languageCodesTouched = array_unique($languageCodesTouched);
|
|
}
|
|
|
|
$message = implode('', $messages);
|
|
|
|
$message .= '\n\nHelp us translate Matomo in your language!\nSignup at https://www.transifex.com/matomo/matomo/\nIf you have any questions, get in touch with us at translations@matomo.org';
|
|
|
|
$languageCodesTouched = array_unique($languageCodesTouched, SORT_REGULAR);
|
|
|
|
$title = sprintf(
|
|
'Updated %s strings in %u languages (%s)',
|
|
$addedLinesSum,
|
|
count($languageCodesTouched),
|
|
implode(', ', $languageCodesTouched)
|
|
);
|
|
|
|
shell_exec('git commit -m "language update ${pluginName}"');
|
|
shell_exec('git push');
|
|
shell_exec('git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1');
|
|
|
|
$this->createPullRequest($output, $title, $message);
|
|
}
|
|
|
|
private function getLanguageInfoByIsoCode($isoCode)
|
|
{
|
|
$languages = API::getInstance()->getAvailableLanguagesInfo();
|
|
foreach ($languages as $languageInfo) {
|
|
if ($languageInfo['code'] == $isoCode) {
|
|
return $languageInfo;
|
|
}
|
|
}
|
|
return array();
|
|
}
|
|
|
|
private function createPullRequest(OutputInterface $output, $title, $message)
|
|
{
|
|
$dialog = $this->getHelperSet()->get('dialog');
|
|
|
|
while (true) {
|
|
|
|
$username = $dialog->ask($output, 'Please provide your GitHub username (to create a pull request using GitHub API): ');
|
|
|
|
$returnCode = shell_exec('curl \
|
|
-X POST \
|
|
-k \
|
|
--silent \
|
|
--write-out %{http_code} \
|
|
--stderr /dev/null \
|
|
-o /dev/null \
|
|
-u '.$username.' \
|
|
--data "{\"title\":\"[automatic translation update] '.$title.'\",\"body\":\"'.$message.'\",\"head\":\"translationupdates\",\"base\":\"' . self::GIT_BASE_BRANCH . '\"}" \
|
|
-H "Accept: application/json" \
|
|
https://api.github.com/repos/matomo-org/matomo/pulls');
|
|
|
|
switch ($returnCode) {
|
|
case 401:
|
|
$output->writeln("Pull request failed. Bad credentials... Please try again");
|
|
continue 2;
|
|
|
|
case 422:
|
|
$output->writeln("Pull request failed. Unprocessable Entity. Maybe a pull request was already created before.");
|
|
return;
|
|
|
|
case 201:
|
|
case 200:
|
|
$output->writeln("Pull request successfully created.");
|
|
return;
|
|
|
|
default:
|
|
$output->writeln("Pull request failed... Please try again");
|
|
}
|
|
}
|
|
}
|
|
}
|