Making WordPress.org

Ticket #1089: 1089.3.diff

File 1089.3.diff, 30.3 KB (added by akirk, 9 years ago)
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/cli/grant-bulk-permissions.php

     
     1<?php
     2/**
     3 * This script enables granting and removing of rights for bulk import and bulk export
     4 */
     5require_once dirname( dirname( dirname( __DIR__ ) ) ) . '/gp-load.php';
     6
     7class Grant_Bulk_Permissions extends GP_CLI {
     8        var $short_options = 'u:p:g:r:';
     9
     10        var $usage = "-u <username> -p <project-path> ( -g <grant-permission>] | [-r <revoke-permission> )
     11
     12Supported permissions are:
     13 - bulk-import
     14 - bulk-export
     15";
     16
     17        function run() {
     18                if ( ! isset( $this->options['u'] )
     19                        || ( ! isset( $this->options['g'] ) && ! isset( $this->options['r'] ) )
     20                ) {
     21                        $this->usage();
     22                }
     23                $user = GP::$user->get( $this->options['u'] );
     24                if ( !$user || !$user->id ) $this->error( __('User not found!') );
     25
     26                $project = GP::$project->by_path( $this->options['p'] );
     27                if ( !$project ) $this->error( __('Project not found!') );
     28
     29                $grants = gp_array_get( $this->options, 'g' );
     30                if ( $grants ) {
     31                        if ( !is_array( $grants ) ) {
     32                                $grants = array( $grants );
     33                        }
     34
     35                        foreach ( $grants as $permission_name ) {
     36                                if ( ! in_array( $permission_name, array( 'bulk-import', 'bulk-export') ) ) {
     37                                        echo "Invalid permission: $permission_name\n";
     38                                        continue;
     39                                }
     40                                $permission = GP::$permission->find_one( $this->get_permission_array( $user, $project, $permission_name ) );
     41                                if ( ! $permission ) {
     42                                        GP::$permission->create( $this->get_permission_array( $user, $project, $permission_name ) );
     43                                        echo "Permission $permission_name granted to user ", $user->user_login, " for project ", $project->slug, ".\n";
     44                                } else {
     45                                        echo "User ", $user->user_login, " already has the permission $permission_name for project ", $project->slug, ".\n";
     46                                }
     47                        }
     48                }
     49
     50                $revokes = gp_array_get( $this->options, 'r' );
     51                if ( $revokes ) {
     52                        if ( !is_array( $revokes ) ) {
     53                                $revokes = array( $revokes );
     54                        }
     55
     56                        foreach ( $revokes as $permission_name ) {
     57                                if ( ! in_array( $permission_name, array( 'bulk-import', 'bulk-export') ) ) {
     58                                        echo "Invalid permission: $permission_name\n";
     59                                        continue;
     60                                }
     61                                $permission = GP::$permission->find_one( $this->get_permission_array( $user, $project, $permission_name ) );
     62                                if ( $permission ) {
     63                                        $permission->delete();
     64                                        echo "Permission $permission_name revoked from user ", $user->user_login, " for project ", $project->slug, ".\n";
     65                                } else {
     66                                        echo "User ", $user->user_login, " did not have the permission $permission_name for project ", $project->slug, ".\n";
     67                                }
     68                        }
     69                }
     70        }
     71
     72        private function get_permission_array( GP_User $user, GP_Project $project, $permission_name ) {
     73                return array( 'user_id' => $user->id, 'object_type' => 'project', 'object_id' => $project->id, 'action' => $permission_name );
     74        }
     75}
     76
     77$grant_bulk_permissions = new Grant_Bulk_Permissions;
     78$grant_bulk_permissions->run();
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/gp-import-export.php

     
     1<?php
     2
     3/* GP_Import_Export
     4 * This plugin adds "Bulk Import" and "Bulk Export" project actions
     5 *  - Import a zip archive with multiple PO files to different sets
     6 *  - Export a zip archive of translations based on filters.
     7 */
     8
     9require_once( dirname(__FILE__) .'/includes/router.php' );
     10
     11class GP_Import_Export extends GP_Plugin {
     12
     13        public $id = 'importer';
     14
     15        public function __construct() {
     16                parent::__construct();
     17                $this->add_routes();
     18                $this->add_filter( 'gp_project_actions', array( 'args' => 2 ) );
     19        }
     20
     21        function add_routes() {
     22                $path = '(.+?)';
     23
     24                GP::$router->add( "/importer/$path", array( 'GP_Route_Import_Export', 'importer_get' ), 'get' );
     25                GP::$router->add( "/importer/$path", array( 'GP_Route_Import_Export', 'importer_post' ), 'post' );
     26
     27                GP::$router->add( "/exporter/$path/-do", array( 'GP_Route_Import_Export', 'exporter_do_get' ), 'get' );
     28                GP::$router->add( "/exporter/$path", array( 'GP_Route_Import_Export', 'exporter_get' ), 'get' );
     29        }
     30
     31        function gp_project_actions( $actions, $project ) {
     32
     33                if ( GP::$user->current()->can( 'bulk-import', 'project', $project->id ) ) {
     34                        $actions[] = gp_link_get( gp_url( '/importer/' . $project->path ), __( 'Bulk Import' ) );
     35                }
     36
     37                if ( GP::$user->current()->can( 'bulk-export', 'project', $project->id ) ) {
     38                        $actions[] = gp_link_get( gp_url( '/exporter/' . $project->path ), __( 'Bulk Export' ) );
     39                }
     40
     41                return $actions;
     42        }
     43
     44        public static function rrmdir( $dir ) {
     45                if ( trim( str_replace( array( '/', '.' ), '', $dir) ) == '' ) {
     46                        // prevent empty argument, thus deleting more than wanted
     47                        return false;
     48                }
     49
     50                foreach ( glob( str_replace( '*', '', $dir ) . '/{,.}*', GLOB_BRACE ) as $file ) { // Also look for hidden files
     51
     52                        if (  $file == $dir . '/.' || $file == $dir . '/..' ) { // but ignore dot directories
     53                                continue;
     54                        }
     55
     56                        if ( is_dir( $file ) ) {
     57                                self::rrmdir( $file );
     58                        } else {
     59                                unlink( $file );
     60                        }
     61                }
     62
     63                rmdir( $dir );
     64        }
     65}
     66
     67GP::$plugins->import_export = new GP_Import_Export;
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/includes/router.php

     
     1<?php
     2
     3class GP_Route_Import_export extends GP_Route_Main {
     4
     5        function __construct() {
     6                $this->template_path = dirname( dirname( __FILE__ ) ) . '/templates/';
     7        }
     8
     9        function exporter_get( $project_path ) {
     10                $project = GP::$project->by_path( $project_path );
     11
     12                if ( ! $project ) {
     13                        $this->die_with_404();
     14                }
     15
     16                $can_write = $this->can( 'bulk-export', 'project', $project->id );
     17
     18                if ( isset( GP::$plugins->views ) ) {
     19                        GP::$plugins->views->set_project_id( $project->id );
     20                        if ( $views = GP::$plugins->views->views ) {
     21                                $views_for_select = array( '' => __( '&mdash; Select &mdash;' ) );
     22                                foreach ( $views as $id => $view ) {
     23                                        $views_for_select[ $id ] = $view->name;
     24                                }
     25                                unset( $views );
     26                        }
     27                }
     28
     29
     30                $translation_sets = GP::$translation_set->by_project_id( $project->id );
     31
     32                $values = array_map( function( $set ) { return $set->id; }, $translation_sets );
     33                $labels = array_map( function( $set ) { return $set->name_with_locale(); }, $translation_sets );
     34                $sets_for_select = apply_filters( 'exporter_translations_sets_for_select', array_combine( $values, $labels ), $project->id );
     35                $sets_for_select =  array( '' => __('&mdash; All &mdash;') ) +  $sets_for_select;
     36
     37                $this->tmpl( 'exporter', get_defined_vars() );
     38        }
     39
     40        function exporter_do_get( $project_path ) {
     41                @ini_set( 'memory_limit', '256M' );
     42
     43                $project = GP::$project->by_path( $project_path );
     44
     45                if ( ! $project ) {
     46                        $this->die_with_404();
     47                }
     48
     49                $format = gp_array_get( GP::$formats, gp_get( 'format', 'po' ), null );
     50
     51                if ( ! $format ) {
     52                        $this->die_with_404();
     53                }
     54
     55
     56                if ( isset( GP::$plugins->views ) ) {
     57                        GP::$plugins->views->set_project_id( $project->id );
     58                        $current_view = GP::$plugins->views->current_view;
     59                }
     60
     61                $project_for_slug = isset( $current_view ) ? $project_path . '/' . $current_view : $project_path;
     62                $filters = gp_get('filters');
     63                if ( isset( $filters['status'] ) && $filters['status'] != 'current_or_waiting_or_fuzzy_or_untranslated' ) {
     64                        $project_for_slug .= '/' . $filters['status'];
     65                }
     66                $slug = str_replace( '/', '-', $project_for_slug ) . '-' . date( 'Y-d-m-Hi' );
     67
     68                $working_path = '/tmp/' . $slug ;
     69
     70                // Make sure we have a fresh working directory.
     71                if ( file_exists( $working_path ) ) {
     72                        GP_Import_Export::rrmdir( $working_path );
     73                }
     74
     75                mkdir( $working_path );
     76
     77                $translations_sets = apply_filters( 'exporter_translations_sets_for_processing', gp_get( 'translation_sets' ), $project->id );
     78                if ( ! array_filter( $translations_sets ) || in_array( '0', $translations_sets ) ){
     79                        $_translation_sets = GP::$translation_set->by_project_id( $project->id );
     80                        $translations_sets = array_map( function( $set ) { return $set->id; }, $_translation_sets );
     81                };
     82
     83                $export_created = false;
     84                $empty = 0;
     85                foreach ( $translations_sets as $set_id ) {
     86                        $translation_set = GP::$translation_set->get( $set_id );
     87                        if ( ! $translation_set ) {
     88                                $this->errors[] = 'Translation set not found'; //TODO: do something with this
     89                                continue;
     90                        }
     91                        $locale = GP_Locales::by_slug( $translation_set->locale );
     92                        $filename = $working_path . '/' . sprintf(  '%s-%s.' . $format->extension, str_replace( '/', '-', $project_for_slug ), $locale->slug );
     93                        $entries = GP::$translation->for_export( $project, $translation_set, gp_get( 'filters' ) );
     94                        if ( empty( $entries ) ) {
     95                                $empty++;
     96                                continue;
     97                        }
     98                        file_put_contents(  $filename, $format->print_exported_file( $project, $locale, $translation_set, $entries ) );
     99                        $export_created = true;
     100                }
     101
     102                if ( ! $export_created ) {
     103                        if ( count( $translations_sets ) == count( $empty ) ) {
     104                                $this->notices[] = 'No matches for your selection';
     105                                $this->redirect();
     106                        } else {
     107                                $this->die_with_error( 'Error creating export files' );
     108                        }
     109                }
     110
     111                $tempdir = sys_get_temp_dir();
     112                $archive_file =  $tempdir . '/' . $slug . '.zip';
     113
     114                $zip = new ZipArchiveExtended;
     115                if ( $zip->open( $archive_file, ZipArchiveExtended::CREATE | ZipArchiveExtended::OVERWRITE ) ) {
     116                        $zip->addDir( $slug, $tempdir );
     117                        $zip->close();
     118                }
     119
     120                $this->headers_for_download( $archive_file );
     121                readfile( $archive_file );
     122
     123                GP_Import_Export::rrmdir( $working_path );
     124                unlink( $archive_file );
     125        }
     126
     127        function importer_get( $project_path ) {
     128                $project = GP::$project->by_path( $project_path );
     129
     130                if ( ! $project ) {
     131                        $this->die_with_404();
     132                }
     133
     134                if ( $this->cannot_and_redirect( 'bulk-import', 'project', $project->id ) ) {
     135                        return;
     136                }
     137
     138                $this->tmpl( 'importer', get_defined_vars() );
     139        }
     140
     141        function importer_post( $project_path ) {
     142                $project = GP::$project->by_path( $project_path );
     143
     144                if ( ! $project ) {
     145                        $this->die_with_404();
     146                }
     147
     148                if ( $this->cannot_and_redirect( 'bulk-import', 'project', $project->id ) ) {
     149                        return;
     150                }
     151
     152                $step = gp_post( 'importer-step', '1' );
     153
     154                // process the archive file upon each step because it is uploaded on every step because of the server-farm infrastructure
     155                $pofiles = $this->process_archive_file( $project );
     156
     157                switch( $step ) {
     158                        case 1:
     159                        default:
     160                                $this->show_selections( $project, $pofiles );
     161                                break;
     162                        case 2:
     163                                $this->confirm_selections( $project, $pofiles );
     164                                break;
     165                        case 3:
     166                                $this->process_imports( $project, $pofiles );
     167                                break;
     168                }
     169
     170        }
     171
     172        /**
     173         * extract the uploaded ZIP file
     174         * @param  object $project the project derived from the URL
     175         * @return array           the filenames of the extracted .po files
     176         */
     177        function process_archive_file( $project ) {
     178
     179                if ( ! is_uploaded_file( $_FILES['import-file']['tmp_name'] ) ) {
     180                        $this->redirect_with_error( __( 'Error uploading the file.' ) );
     181                        return;
     182                } else {
     183                        if ( ! gp_endswith( $_FILES['import-file']['name'], '.zip' ) || ! in_array( $_FILES['import-file']['type'], array( 'application/octet-stream', 'application/zip' ) ) ) {
     184                                $upload_error = true;
     185                                $this->redirect_with_error( __( 'Please upload a zip file.' ) );
     186                        }
     187                }
     188
     189                $filename = preg_replace("([^\w\s\d\-_~,;:\[\]\(\].]|[\.]{2,})", '',  $_FILES['import-file']['name'] );
     190                $slug = preg_replace( '/\.zip$/', '', $filename );
     191
     192                $working_directory = '/bulk-importer-' . $slug;
     193                $this->working_path = sys_get_temp_dir() . $working_directory;
     194
     195                // Make sure we have a fresh working directory.
     196                if ( file_exists( $this->working_path ) ) {
     197                        GP_Import_Export::rrmdir( $this->working_path );
     198                }
     199
     200                mkdir( $this->working_path );
     201
     202                $zip = new ZipArchiveExtended;
     203                if ( $zip->open( $_FILES['import-file']['tmp_name'] ) ) {
     204                        $zip->extractToFlatten( $this->working_path );
     205                        $zip->close();
     206                }
     207
     208                $pofiles = glob( $this->working_path . '/*.po' );
     209                if ( empty( $pofiles ) ) {
     210                        GP_Import_Export::rrmdir( $this->working_path );
     211                        $this->redirect_with_error( __( 'No PO files found in zip archive' ) );
     212                }
     213
     214                return $pofiles;
     215        }
     216
     217        /**
     218         * Step 1: extract the uploaded ZIP file
     219         * @param  object $project the project derived from the URL
     220         * @param  array $pofiles the filenames of the extracted .po files
     221         */
     222        function show_selections( $project, $pofiles ) {
     223                $sets = GP::$translation_set->by_project_id( $project->id );
     224                $sets_for_select = array_combine(
     225                        array_map( function( $s ){ return $s->id; }, $sets ),
     226                        array_map( function( $s ){ return $s->locale . ' - ' . $s->name; }, $sets )
     227                );
     228
     229                $sets_for_select = array( '0' => __('&mdash; Translation Set &mdash;' ) ) + $sets_for_select;
     230                unset( $sets );
     231
     232                $this->tmpl( 'importer-files', get_defined_vars() );
     233        }
     234
     235
     236        /**
     237         * Step 2: Confirm the locale mappings by the user and select
     238         * @param  object $project the project derived from the URL
     239         * @param  array $pofiles the filenames of the extracted .po files
     240         */
     241        function confirm_selections( $project, $pofiles ) {
     242
     243                $to_import = array();
     244                foreach( $pofiles as $po_file ) {
     245                        $target_set = gp_post( basename( $po_file, '.po') );
     246                        if ( $target_set  ) {
     247
     248                                $translation_set = GP::$translation_set->get( $target_set );
     249
     250                                if ( ! $translation_set ) {
     251                                        $this->errors[] = sprintf( __( 'Couldn&#8217;t find translation set id %d!' ), $target_set );
     252                                }
     253
     254                                $to_import[ basename( $po_file ) ] = array( 'id' => $translation_set->id, 'name' => $translation_set->name_with_locale() );
     255                        }
     256                }
     257
     258                if ( empty( $to_import ) ) {
     259                        $this->redirect_with_error( __( 'Please select a matching translation set for each PO file.' ) );
     260                }
     261
     262                $this->tmpl( 'importer-confirmation', get_defined_vars() );
     263        }
     264
     265        /**
     266         * Step 3: Do the import
     267         * @param  object $project the project derived from the URL
     268         * @param  array $pofiles the filenames of the extracted .po files
     269         */
     270
     271        function process_imports( $project, $pofiles ) {
     272
     273                if ( 'no' == gp_post( 'overwrite', 'yes' ) ) {
     274                        add_filter( 'translation_set_import_over_existing', '__return_false' );
     275                }
     276
     277                if ( 'waiting' == gp_post( 'status', 'current' ) ) {
     278                        add_filter( 'translation_set_import_status', function( $status ) {
     279                                return 'waiting';
     280                        });
     281                }
     282
     283                $last = end( $pofiles ); $processed = false;
     284                foreach( $pofiles as $po_file ) {
     285                        $target_set = gp_post( basename( $po_file, '.po') );
     286                        if ( $target_set  ) {
     287                                $processed = $po_file;
     288                                $id = basename( $po_file, '.po' );
     289
     290                                $translation_set = GP::$translation_set->get( $target_set );
     291
     292                                if ( ! $translation_set ) {
     293                                        $status = sprintf( __( 'Couldn&#8217;t find translation set id %d!' ), $target_set );
     294                                        break;
     295                                }
     296
     297                                $format = gp_array_get( GP::$formats, 'po', null );
     298                                $translations = $format->read_translations_from_file( $po_file, $project );
     299                                if ( ! $translations ) {
     300                                        $status = sprintf( __( 'Couldn&#8217;t load translations from file %s!' ), basename( $po_file ) );
     301                                        break;
     302                                }
     303                                $translations_added = $translation_set->import( $translations );
     304                                $status = sprintf( __( '%s translations were added from %s' ), $translations_added, basename( $po_file ) );
     305                        }
     306                }
     307
     308                // cleanup
     309                if ( $this->working_path && $processed === $last ) {
     310                        GP_Import_Export::rrmdir( $this->working_path );
     311                }
     312
     313                $this->tmpl( 'importer-report-status', get_defined_vars() );
     314        }
     315
     316
     317        function headers_for_download( $filename ) {
     318                $this->header( 'Pragma: public' );
     319                $this->header( 'Expires: 0' );
     320                $this->header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
     321                $this->header( 'Cache-Control: public' );
     322                $this->header( 'Content-Description: File Transfer' );
     323                $this->header( 'Content-type: application/octet-stream' );
     324                $this->header( 'Content-Disposition: attachment; filename="' . basename( $filename ) . '"' );
     325                $this->header( 'Content-Transfer-Encoding: binary' );
     326                $this->header( 'Content-Length: ' . filesize( $filename ) );
     327        }
     328
     329}
     330
     331if ( class_exists( 'ZipArchive' ) ) {
     332        class ZipArchiveExtended extends ZipArchive {
     333
     334                public function addDir( $path, $basedir ) {
     335                        $cwd = getcwd();
     336                        chdir( $basedir );
     337
     338                        $this->addEmptyDir( $path );
     339                        $nodes = glob( $path . '/*' );
     340                        foreach ( $nodes as $node ) {
     341                                if ( is_dir( $node ) ) {
     342                                        $this->addDir( $node );
     343                                } else if ( is_file( $node ) )  {
     344                                        $this->addFile( $node );
     345                                }
     346                        }
     347
     348                        chdir( $cwd );
     349                        return true;
     350                }
     351
     352                public function extractToFlatten( $path ) {
     353                        for ( $i = 0; $i < $this->numFiles; $i++ ) {
     354
     355                                $entry = $this->getNameIndex( $i );
     356                                if ( substr( $entry, -1 ) == '/' ) continue; // skip directories to flatten the file structure
     357
     358                                $fp = $this->getStream( $entry );
     359                                if ( $fp ) {
     360                                        $ofp = fopen( $path . '/' . basename( $entry ), 'w' );
     361                                        while ( ! feof( $fp ) ) {
     362                                                fwrite( $ofp, fread( $fp, 8192 ) );
     363                                        }
     364
     365                                        fclose( $fp );
     366                                        fclose( $ofp );
     367                                }
     368                        }
     369
     370                        return $path;
     371                }
     372        }
     373} else {
     374        class ZipArchiveExtended {
     375                const CREATE = 0;
     376                const OVERWRITE = 0;
     377
     378                private $archive_file;
     379                public function open( $archive_file, $flags = false ) {
     380                        $this->archive_file = $archive_file;
     381                        return true;
     382                }
     383
     384                public function addDir( $path, $basedir ) {
     385                        $cwd = getcwd();
     386                        chdir( $basedir );
     387
     388                        $zip_command = 'zip -r ' . escapeshellarg( $this->archive_file ) . ' ' . escapeshellarg( $path );
     389                        $zip_output = array();
     390                        $zip_status = null;
     391
     392                        exec( $zip_command, $zip_output, $zip_status );
     393
     394                        if ( 0 !== $zip_status ) {
     395                                return false;
     396                        }
     397
     398                        return true;
     399                }
     400
     401                public function extractToFlatten( $path ) {
     402                        system( 'unzip -j -qq ' . $this->archive_file . ' *.po -d ' . escapeshellarg( $path ) );
     403                        return $path;
     404                }
     405
     406                public function close() {
     407                }
     408
     409        }
     410}
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/templates/exporter.php

     
     1<?php
     2gp_title( sprintf( __('Bulk Export Translations &lt; %s &lt; GlotPress'), esc_html( $project->name ) ) );
     3gp_breadcrumb( array(
     4        gp_project_links_from_root( $project ),
     5        __('Bulk Export')
     6) );
     7
     8gp_tmpl_header();
     9?>
     10        <h2><?php _e('Bulk Export Translations'); ?></h2>
     11        <form id="export-filters" class="export-filters" action="<?php echo esc_url( gp_url_current() ); ?>/-do" method="get" accept-charset="utf-8">
     12                <dl>
     13                        <dt><label>Translation Sets</label></dt>
     14                        <dd>
     15                                <?php echo gp_select( 'translation_sets[]', $sets_for_select, null, array( 'multiple' => 'multiple', 'size' => '12', 'style' =>'height:auto;' ) ); ?>
     16                        </dd>
     17                        <dt><label><?php _e( 'Translations status:' ); ?></label></dt>
     18                        <dd>
     19                                <?php
     20                                echo gp_radio_buttons( 'filters[status]',
     21                                        array(
     22                                                'current_or_waiting_or_fuzzy_or_untranslated' => __('Current/waiting/fuzzy + untranslated (All)'),
     23                                                'current' => __('Current only'),
     24                                                'old' => __('Approved, but obsoleted by another string'),
     25                                                'waiting' => __('Waiting approval'),
     26                                                'fuzzy' => __('Fuzzy'),
     27                                                'rejected' => __('Rejected'),
     28                                                'untranslated' => __('Without current translation'),
     29                                                'either' => __('Any'),
     30                                        ), 'current_or_waiting_or_fuzzy_or_untranslated' );
     31                                ?>
     32                        </dd>
     33
     34                        <dt><label><?php _e('Originals priority:'); ?></label></dt>
     35                        <dd>
     36                                <?php
     37                                $valid_priorities = GP::$original->get_static( 'priorities' );
     38                                krsort( $valid_priorities);
     39                                if ( ! isset( $can_write) || ! $can_write ) {
     40                                        //Non admins can't see hidden strings
     41                                        unset( $valid_priorities['-2'] );
     42                                }
     43                                foreach ( $valid_priorities as $priority => $label ):
     44                                        ?>
     45                                        <input checked="checked" type="checkbox" name="filters[priority][]" value="<?php echo esc_attr( $priority );?>" id="priority[<?php echo esc_attr( $label );?>]"><label for='priority[<?php echo esc_attr( $label );?>]'><?php echo esc_html( $label );?></label><br />
     46                                <?php endforeach; ?>
     47                        </dd>
     48                        <?php if( isset( $views_for_select ) ): ?>
     49                        <dt><?php _e( 'Predefined View' ); ?></dt>
     50                        <dd>
     51                                <?php echo gp_select('filters[view]', $views_for_select, null ); ?>
     52                        </dd>
     53                        <?php endif; ?>
     54                        <dt><label><?php _e( 'Format:' ); ?></label></dt>
     55                        <dd>
     56                                <?php
     57                                $format_options = array();
     58                                foreach ( GP::$formats as $slug => $format ) {
     59                                        $format_options[$slug] = $format->name;
     60                                }
     61                                echo gp_select( 'export-format', $format_options, 'po' );
     62                                ?>
     63                        </dd>
     64                </dl>
     65                <p><input type="submit" value="<?php echo esc_attr( __( 'Export' ) ); ?>" name="export" /></p>
     66        </form>
     67
     68<?php gp_tmpl_footer();
     69 No newline at end of file
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/templates/importer-confirmation.php

     
     1<?php
     2gp_title( sprintf( __('Bulk Import Translations &lt; %s &lt; GlotPress'), esc_html( $project->name ) ) );
     3gp_breadcrumb( array(
     4        gp_project_links_from_root( $project ),
     5        __('Bulk Import')
     6) );
     7gp_tmpl_header();
     8?>
     9
     10        <h2><?php _e('Bulk Import Translations'); ?></h2>
     11        <form action="" method="post" enctype="multipart/form-data" id="step3">
     12        <input type="hidden" name="importer-step" value="3">
     13                <dl>
     14                        <dt><?php _e( 'Select Sets' ); ?></dt>
     15                        <dd>
     16                        <?php foreach ( $to_import as $po => $destination ) : ?>
     17                                <p>
     18                                        <?php echo basename( $po ); ?> &rarr; <?php echo $destination['name']; ?>
     19                                        <input type="hidden" name="<?php echo esc_attr( basename( $po, '.po' ) ) ; ?>" value="<?php echo absint( $destination['id'] );?>" class="po-mapping" title="<?php echo basename( $po ); ?> &rarr; <?php echo $destination['name']; ?>" />
     20                                </p>
     21                        <?php endforeach; ?>
     22                        </dd>
     23                        <dt><?php _e( 'Overwrite Translations' ); ?></dt>
     24                        <dd>
     25                                <?php echo gp_radio_buttons( 'overwrite', array(
     26                                        'yes' => 'Overwrite existing translations',
     27                                        'no' => 'Only import new translations',
     28                                ), 'yes' ); ?>
     29                        </dd>
     30                        <dt><?php _e( 'Translation Status' ); ?></dt>
     31                        <dd>
     32                                <?php echo gp_radio_buttons( 'status', array(
     33                                        'current' => 'Current',
     34                                        'waiting' => 'Waiting',
     35                                ), 'current' ); ?>
     36                        </dd>
     37                        <dt><input type="submit" value="<?php echo esc_attr( __( 'Import' ) ); ?>"></dt>
     38                </dl>
     39        </form>
     40
     41        <script type="text/javascript">
     42                parent.document.getElementById('step2').style.display = 'none';
     43                parent.document.getElementById('step3').innerHTML = document.getElementById('step3').innerHTML;
     44        </script>
     45
     46
     47<?php gp_tmpl_footer();
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/templates/importer-files.php

     
     1<?php
     2gp_title( sprintf( __('Bulk Import Translations &lt; %s &lt; GlotPress'), esc_html( $project->name ) ) );
     3gp_breadcrumb( array(
     4        gp_project_links_from_root( $project ),
     5        __('Bulk Import')
     6) );
     7gp_tmpl_header();
     8
     9function get_key_to_be_selected( $name_and_id, $options ) {
     10        $selected_locale = '';
     11
     12        foreach( $options as $value => $label ) {
     13                $locale = substr( $label, 0, strpos( $label, ' - ' ) );
     14
     15                // we don't stop after the first match but continue the search because of cases like:
     16                // pt-br: br == Breton, but we want Brasilian Portuguese
     17                // zh vs. zh-cn vs zh-tw
     18                // In general: Take the longest possible match
     19
     20                if ( strlen( $locale ) > strlen( $selected_locale ) ) {
     21                        if ( preg_match( "#\b$locale\b#", $name_and_id ) ) {
     22                                $selected_key = $value;
     23                                $selected_locale = $locale;
     24                        }
     25                }
     26        }
     27        return $selected_key;
     28}
     29
     30?>
     31
     32        <h2><?php _e('Bulk Import Translations'); ?></h2>
     33        <form action="" method="post" enctype="multipart/form-data" id="step2">
     34                <input type="hidden" name="importer-step" value="2">
     35                <dl>
     36                        <dt><?php _e( 'Select Sets' ); ?></dt>
     37                        <dd>
     38                        <?php foreach ( $pofiles as $po ) : ?>
     39                        <?php $po_name = basename( $po, '.po' ); ?>
     40                                <p>
     41                                        <label for="<?php echo $po_name; ?>"><?php echo basename( $po ) ?> &rarr;</label>
     42                                        <?php echo gp_select( $po_name, $sets_for_select, get_key_to_be_selected( $po_name, $sets_for_select ) ); ?>
     43                                </p>
     44                        <?php endforeach; ?>
     45                        </dd>
     46                        <dt><input type="submit" value="<?php echo esc_attr( __('Review') ); ?>"></dt>
     47                </dl>
     48        </form>
     49
     50        <script type="text/javascript">
     51                parent.document.getElementById('step1').style.display = 'none';
     52                parent.document.getElementById('step2').innerHTML = document.getElementById('step2').innerHTML;
     53        </script>
     54
     55<?php gp_tmpl_footer();
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/templates/importer-report-status.php

     
     1<script type="text/javascript">
     2        parent.document.getElementById('<?php echo $id; ?>-status').innerHTML = '<?php echo $status; ?>';
     3        parent.document.getElementById('<?php echo $id; ?>').className = 'done';
     4        if ( typeof parent.importNext === 'function' ) {
     5                parent.importNext();
     6        } else {
     7                alert( 'error importing the next file' );
     8        }
     9</script>
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/templates/importer.php

     
     1<?php
     2gp_title( sprintf( __('Bulk Import Translations &lt; %s &lt; GlotPress'), esc_html( $project->name ) ) );
     3gp_breadcrumb( array(
     4        gp_project_links_from_root( $project ),
     5        __('Bulk Import')
     6) );
     7gp_tmpl_header();
     8?>
     9
     10        <h2><?php _e('Bulk Import Translations'); ?></h2>
     11        <form action="" method="post" enctype="multipart/form-data" id="step1form">
     12                <div id="inner-error" class="error" style="display: none"></div>
     13                <input type="hidden" name="importer-step" value="1">
     14                <dl id="step1">
     15                        <dt><label for="import-file"><?php _e( 'Import File:' ); ?></label></dt>
     16                        <dd><input type="file" name="import-file" id="import-file" /></dd>
     17                        <dt><input type="submit" value="<?php echo esc_attr( __( 'Import' ) ); ?>"></dt>
     18                </dl>
     19                <dl id="step2">
     20                </dl>
     21                <dl id="step3">
     22                </dl>
     23                <dl id="step4">
     24                </dl>
     25        </form>
     26
     27        <div id="tempframe-holder" style="display: none"></div>
     28
     29        <script type="text/javascript">
     30        var updateErrorsInterval, mappings;
     31        jQuery( function() {
     32                jQuery( '#tempframe-holder' ).html( '<iframe name="tempframe"></iframe>' );
     33                jQuery( '#step1form' ).attr( 'target', 'tempframe' ).on( 'submit', function() {
     34                        if ( jQuery('input[name=importer-step]').last().val() != 3 ) {
     35                                return true;
     36                        }
     37                        jQuery( '#step1form' ).off( 'submit' );
     38                        jQuery( '#step3' ).hide();
     39                        mappings = jQuery( 'input.po-mapping' );
     40                        var el, name, entry, step4 = jQuery( '#step4' );
     41                        for ( var i = 0; i < mappings.length; i++ ) {
     42                                el = mappings.eq( i );
     43                                name = el.attr( 'name' );
     44                                entry = jQuery( '<div><span class="title"></span> <span class="status">');
     45                                entry.find( 'div' ).attr( 'id', name );
     46                                entry.find( 'span.title' ).text( el.attr( 'title' ) );
     47                                entry.find( 'span.status' ).attr( 'id', name + '-status' ).text( 'waiting...' );
     48                                step4.append( entry );
     49
     50                                el.prop( 'disabled', true);
     51                                jQuery( 'select[name=' + name + ']' ).prop( 'disabled', true);
     52                        }
     53                        importNext();
     54                });
     55                updateErrorsInterval = setInterval( updateErrors, 1000 );
     56        }) ;
     57        function importNext() {
     58                var el, name, done = true;
     59                for ( var i = 0; i < mappings.length; i++ ) {
     60                        el = mappings.eq( i );
     61                        name = el.attr( 'name' );
     62                        if ( jQuery( '#' + name ).hasClass( 'done' ) ) {
     63                                continue;
     64                        }
     65                        done = false;
     66                        mappings.prop( 'disabled', true );
     67                        el.prop( 'disabled', false);
     68                        jQuery( '#step1form' ).submit();
     69                        break;
     70                }
     71                if ( done ) {
     72                        jQuery( '#step4' ).prepend('<div><strong>Done!');
     73                }
     74        }
     75        function updateErrors() {
     76                if ( typeof window.tempframe === 'undefined' || typeof window.tempframe.jQuery === 'undefined' ) {
     77                        return false;
     78                }
     79                var error = window.tempframe.jQuery('.error');
     80                if ( error.length > 0 ) {
     81                        jQuery('#inner-error').html( error.html() ).show();
     82                        jQuery('html, body').animate({
     83                            scrollTop: jQuery("#inner-error").offset().top
     84                        }, 200);
     85                } else {
     86                        jQuery('#inner-error').hide();
     87                }
     88        }
     89        </script>
     90
     91<?php gp_tmpl_footer();
  • translate.wordpress.org/includes/gp-plugins/wporg-rosetta-roles/wporg-rosetta-roles.php

     
    4343         * @return bool True if user has permissions, false if not.
    4444         */
    4545        public function pre_can_user( $verdict, $args ) {
     46                if ( in_array( $args['action'], array( 'bulk-import', 'bulk-export' ) ) ) {
     47                        // these permissions are checked by GlotPress, independently of the user's status within Rosetta
     48                        return;
     49                }
     50
    4651                if ( ! class_exists( 'BP_Roles' ) ) {
    4752                        require_once( BACKPRESS_PATH . 'class.bp-roles.php' );
    4853                }