Skip to content
Extraits de code Groupes Projets
CreatePull.php 8,29 ko
Newer Older
  • Learn to ignore specific revisions
  •  * 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('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;
            }
    
    
    Matthieu Aubry's avatar
    Matthieu Aubry a validé
            $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('
    
    Matthieu Aubry's avatar
    Matthieu Aubry a validé
                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('
    
    Matthieu Aubry's avatar
    Matthieu Aubry a validé
                    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');
            }
    
    
    Matthieu Aubry's avatar
    Matthieu Aubry a validé
            // switch to branch and update it to latest $GIT_BASE_BRANCH
    
                git checkout -f translationupdates > /dev/null 2>&1
    
    Matthieu Aubry's avatar
    Matthieu Aubry a validé
                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'),
                '--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.");
    
    Matthieu Aubry's avatar
    Matthieu Aubry a validé
                shell_exec('git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1');
    
            API::unsetInstance(); // reset languagemanager api (to force refresh of data)
    
    
    sgiehl's avatar
    sgiehl a validé
            $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();
    
    sgiehl's avatar
    sgiehl a validé
            $lineChangesCount = count($lineChanges[0]);
            for ($i = 0; $i < $lineChangesCount; $i++) {
    
    sgiehl's avatar
    sgiehl a validé
                @$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);
    
    sgiehl's avatar
    sgiehl a validé
    
            $messages = array();
    
            $languageCodesTouched = array();
    
    sgiehl's avatar
    sgiehl a validé
            if (!empty($addedFiles[1])) {
    
                foreach ($addedFiles[1] as $addedFile) {
    
    sgiehl's avatar
    sgiehl a validé
                    $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) {
    
                    $languageInfo = $this->getLanguageInfoByIsoCode($modifiedFile);
    
    sgiehl's avatar
    sgiehl a validé
                    $messages[$modifiedFile] = sprintf('- Updated %s (%s changes / %s translated)\n', $languageInfo['english_name'], $linesSumByLang[$modifiedFile], $languageInfo['percentage_complete']);
    
                $languageCodesTouched = array_merge($languageCodesTouched, $modifiedFiles[1]);
    
    sgiehl's avatar
    sgiehl a validé
            $message = implode('', $messages);
    
            $message .= '\n\nHelp us translate Piwik in your language!\nSignup at https://www.transifex.com/piwik/piwik/\nIf you have any questions, get in touch with us at translations@piwik.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}"');
    
    Matthieu Aubry's avatar
    Matthieu Aubry a validé
            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) {
    
    
    Panayiotis Lipiridis's avatar
    Panayiotis Lipiridis a validé
                $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.' \
    
    Matthieu Aubry's avatar
    Matthieu Aubry a validé
                     --data "{\"title\":\"[automatic translation update] '.$title.'\",\"body\":\"'.$message.'\",\"head\":\"translationupdates\",\"base\":\"' . self::GIT_BASE_BRANCH . '\"}" \
    
                     -H "Accept: application/json" \
                     https://api.github.com/repos/piwik/piwik/pulls');
    
                switch ($returnCode) {
                    case 401:
                        $output->writeln("Pull request failed. Bad credentials... Please try again");
                        continue;
    
                    case 422:
                        $output->writeln("Pull request failed. Unprocessable Entity. Maybe a pull request was already created before.");
    
    sgiehl's avatar
    sgiehl a validé
                        return;
    
    
                    case 201:
                    case 200:
                        $output->writeln("Pull request successfully created.");
    
    sgiehl's avatar
    sgiehl a validé
                        return;
    
    
                    default:
                        $output->writeln("Pull request failed... Please try again");
                }
            }
        }