|
| 1 | +<?php namespace WP_CLI\Maintenance; |
| 2 | + |
| 3 | +use WP_CLI; |
| 4 | +use WP_CLI\Utils; |
| 5 | + |
| 6 | +final class Contrib_List_Command { |
| 7 | + |
| 8 | + /** |
| 9 | + * Lists all contributors to this release. |
| 10 | + * |
| 11 | + * Run within the main WP-CLI project repository. |
| 12 | + * |
| 13 | + * ## OPTIONS |
| 14 | + * |
| 15 | + * [--format=<format>] |
| 16 | + * : Render output in a specific format. |
| 17 | + * --- |
| 18 | + * default: markdown |
| 19 | + * options: |
| 20 | + * - markdown |
| 21 | + * - html |
| 22 | + * --- |
| 23 | + * |
| 24 | + * @when before_wp_load |
| 25 | + */ |
| 26 | + public function __invoke( $_, $assoc_args ) { |
| 27 | + |
| 28 | + $contributors = array(); |
| 29 | + $pull_request_count = 0; |
| 30 | + |
| 31 | + // Get the contributors to the current open large project milestones |
| 32 | + foreach( array( 'wp-cli/wp-cli-bundle', 'wp-cli/wp-cli', 'wp-cli/handbook', 'wp-cli/wp-cli.github.com' ) as $repo ) { |
| 33 | + $milestones = GitHub::get_project_milestones( $repo ); |
| 34 | + // Cheap way to get the latest milestone |
| 35 | + $milestone = array_shift( $milestones ); |
| 36 | + if ( ! $milestone ) { |
| 37 | + continue; |
| 38 | + } |
| 39 | + WP_CLI::log( 'Current open ' . $repo . ' milestone: ' . $milestone->title ); |
| 40 | + $pull_requests = GitHub::get_project_milestone_pull_requests( $repo, $milestone->number ); |
| 41 | + $repo_contributors = GitHub::parse_contributors_from_pull_requests( $pull_requests ); |
| 42 | + WP_CLI::log( ' - Contributors: ' . count( $repo_contributors ) ); |
| 43 | + WP_CLI::log( ' - Pull requests: ' . count( $pull_requests ) ); |
| 44 | + $pull_request_count += count( $pull_requests ); |
| 45 | + $contributors = array_merge( $contributors, $repo_contributors ); |
| 46 | + } |
| 47 | + |
| 48 | + // Identify all command dependencies and their contributors |
| 49 | + |
| 50 | + // TODO: Bundle repo needs to be switched to `wp-cli/wp-cli-bundle` for next release. |
| 51 | + $bundle = 'wp-cli/wp-cli'; |
| 52 | + |
| 53 | + $milestones = GitHub::get_project_milestones( 'wp-cli/wp-cli', array( 'state' => 'closed' ) ); |
| 54 | + // Cheap way to get the latest closed milestone |
| 55 | + $milestone = array_shift( $milestones ); |
| 56 | + $tag = is_object( $milestone ) ? "v{$milestone->title}" : 'master'; |
| 57 | + |
| 58 | + // TODO: Only needed for switch from v1 to v2. |
| 59 | + if ( 'wp-cli/wp-cli' === $bundle ) { |
| 60 | + $tag = 'v1.5.1'; |
| 61 | + } |
| 62 | + |
| 63 | + $composer_lock_url = sprintf( 'https://raw.githubusercontent.com/%s/%s/composer.lock', $bundle, $tag ); |
| 64 | + WP_CLI::log( 'Fetching ' . $composer_lock_url ); |
| 65 | + $response = Utils\http_request( 'GET', $composer_lock_url ); |
| 66 | + if ( 200 !== $response->status_code ) { |
| 67 | + WP_CLI::error( sprintf( 'Could not fetch composer.json (HTTP code %d)', $response->status_code ) ); |
| 68 | + } |
| 69 | + $composer_json = json_decode( $response->body, true ); |
| 70 | + |
| 71 | + // TODO: Only need for initial v2. |
| 72 | + $composer_json['packages'][] = array( 'name' => 'wp-cli/i18n-command', 'version' => 'v2' ); |
| 73 | + usort( $composer_json['packages'], function ( $a, $b ) { |
| 74 | + return $a['name'] < $b['name'] ? -1 : 1; |
| 75 | + } ); |
| 76 | + |
| 77 | + foreach( $composer_json['packages'] as $package ) { |
| 78 | + $package_name = $package['name']; |
| 79 | + $version_constraint = str_replace( 'v', '', $package['version'] ); |
| 80 | + if ( ! preg_match( '#^wp-cli/.+-command$#', $package_name ) |
| 81 | + && ! in_array( $package_name, array( |
| 82 | + 'wp-cli/wp-cli-tests', |
| 83 | + 'wp-cli/regenerate-readme', |
| 84 | + 'wp-cli/autoload-splitter', |
| 85 | + 'wp-cli/wp-config-transformer', |
| 86 | + 'wp-cli/php-cli-tools', |
| 87 | + 'wp-cli/spyc', |
| 88 | + ), true ) ) { |
| 89 | + continue; |
| 90 | + } |
| 91 | + // Closed milestones denote a tagged release |
| 92 | + $milestones = GitHub::get_project_milestones( $package_name, array( 'state' => 'closed' ) ); |
| 93 | + $milestone_ids = array(); |
| 94 | + $milestone_titles = array(); |
| 95 | + foreach( $milestones as $milestone ) { |
| 96 | + if ( ! version_compare( $milestone->title, $version_constraint, '>' ) ) { |
| 97 | + continue; |
| 98 | + } |
| 99 | + $milestone_ids[] = $milestone->number; |
| 100 | + $milestone_titles[] = $milestone->title; |
| 101 | + } |
| 102 | + // No shipped releases for this milestone. |
| 103 | + if ( empty( $milestone_ids ) ) { |
| 104 | + continue; |
| 105 | + } |
| 106 | + WP_CLI::log( 'Closed ' . $package_name . ' milestone(s): ' . implode( ', ', $milestone_titles ) ); |
| 107 | + foreach( $milestone_ids as $milestone_id ) { |
| 108 | + $pull_requests = GitHub::get_project_milestone_pull_requests( $package_name, $milestone_id ); |
| 109 | + $repo_contributors = GitHub::parse_contributors_from_pull_requests( $pull_requests ); |
| 110 | + WP_CLI::log( ' - Contributors: ' . count( $repo_contributors ) ); |
| 111 | + WP_CLI::log( ' - Pull requests: ' . count( $pull_requests ) ); |
| 112 | + $pull_request_count += count( $pull_requests ); |
| 113 | + $contributors = array_merge( $contributors, $repo_contributors ); |
| 114 | + } |
| 115 | + } |
| 116 | + |
| 117 | + WP_CLI::log( 'Total contributors: ' . count( $contributors ) ); |
| 118 | + WP_CLI::log( 'Total pull requests: ' . $pull_request_count ); |
| 119 | + |
| 120 | + // Sort and render the contributor list |
| 121 | + asort( $contributors, SORT_NATURAL | SORT_FLAG_CASE ); |
| 122 | + if ( in_array( $assoc_args['format'], array( 'markdown', 'html' ) ) ) { |
| 123 | + $contrib_list = ''; |
| 124 | + foreach( $contributors as $url => $login ) { |
| 125 | + if ( 'markdown' === $assoc_args['format'] ) { |
| 126 | + $contrib_list .= '[@' . $login . '](' . $url . '), '; |
| 127 | + } elseif ( 'html' === $assoc_args['format'] ) { |
| 128 | + $contrib_list .= '<a href="' . $url . '">@' . $login . '</a>, '; |
| 129 | + } |
| 130 | + } |
| 131 | + $contrib_list = rtrim( $contrib_list, ', ' ); |
| 132 | + WP_CLI::log( $contrib_list ); |
| 133 | + } |
| 134 | + } |
| 135 | +} |
0 commit comments