console-helpers /
jira-cli
| 1 | <?php |
||||
| 2 | /** |
||||
| 3 | * This file is part of the Jira-CLI library. |
||||
| 4 | * For the full copyright and license information, please view |
||||
| 5 | * the LICENSE file that was distributed with this source code. |
||||
| 6 | * |
||||
| 7 | * @copyright Alexander Obuhovich <[email protected]> |
||||
| 8 | * @link https://github.com/console-helpers/jira-cli |
||||
| 9 | */ |
||||
| 10 | |||||
| 11 | namespace ConsoleHelpers\JiraCLI\Command; |
||||
| 12 | |||||
| 13 | |||||
| 14 | use chobie\Jira\Issue; |
||||
| 15 | use ConsoleHelpers\ConsoleKit\Exception\CommandException; |
||||
| 16 | use ConsoleHelpers\JiraCLI\Issue\ChangeLogIssueCloner; |
||||
| 17 | use ConsoleHelpers\JiraCLI\JiraApi; |
||||
| 18 | use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext; |
||||
| 19 | use Symfony\Component\Console\Input\InputArgument; |
||||
| 20 | use Symfony\Component\Console\Input\InputInterface; |
||||
| 21 | use Symfony\Component\Console\Input\InputOption; |
||||
| 22 | use Symfony\Component\Console\Output\OutputInterface; |
||||
| 23 | |||||
| 24 | class ChangeLogCloneCommand extends AbstractCommand |
||||
| 25 | { |
||||
| 26 | |||||
| 27 | /** |
||||
| 28 | * Issue cloner. |
||||
| 29 | * |
||||
| 30 | * @var ChangeLogIssueCloner |
||||
| 31 | */ |
||||
| 32 | protected $issueCloner; |
||||
| 33 | |||||
| 34 | /** |
||||
| 35 | * {@inheritdoc} |
||||
| 36 | */ |
||||
| 37 | protected function configure() |
||||
| 38 | { |
||||
| 39 | $this |
||||
| 40 | ->setName('changelog-clone') |
||||
| 41 | ->setDescription('Clones issue for changelog into another project') |
||||
| 42 | ->addArgument( |
||||
| 43 | 'issue_key', |
||||
| 44 | InputArgument::REQUIRED, |
||||
| 45 | 'Issue key, e.g. <comment>JRA-1234</comment>' |
||||
| 46 | ) |
||||
| 47 | ->addArgument( |
||||
| 48 | 'project_keys', |
||||
| 49 | InputArgument::REQUIRED | InputArgument::IS_ARRAY, |
||||
| 50 | 'Project keys, e.g. <comment>PRJ</comment>' |
||||
| 51 | ) |
||||
| 52 | ->addOption( |
||||
| 53 | 'link-name', |
||||
| 54 | null, |
||||
| 55 | InputOption::VALUE_REQUIRED, |
||||
| 56 | 'Link name between issues', |
||||
| 57 | 'Blocks' |
||||
| 58 | ); |
||||
| 59 | } |
||||
| 60 | |||||
| 61 | /** |
||||
| 62 | * Prepare dependencies. |
||||
| 63 | * |
||||
| 64 | * @return void |
||||
| 65 | */ |
||||
| 66 | protected function prepareDependencies() |
||||
| 67 | { |
||||
| 68 | parent::prepareDependencies(); |
||||
| 69 | |||||
| 70 | $container = $this->getContainer(); |
||||
| 71 | |||||
| 72 | $this->issueCloner = $container['changelog_issue_cloner']; |
||||
| 73 | } |
||||
| 74 | |||||
| 75 | /** |
||||
| 76 | * Return possible values for the named option |
||||
| 77 | * |
||||
| 78 | * @param string $optionName Option name. |
||||
| 79 | * @param CompletionContext $context Completion context. |
||||
| 80 | * |
||||
| 81 | * @return array |
||||
| 82 | */ |
||||
| 83 | public function completeOptionValues($optionName, CompletionContext $context) |
||||
| 84 | { |
||||
| 85 | $ret = parent::completeOptionValues($optionName, $context); |
||||
| 86 | |||||
| 87 | if ( $optionName === 'link-name' ) { |
||||
| 88 | return $this->jiraApi->getIssueLinkTypeNames(); |
||||
| 89 | } |
||||
| 90 | |||||
| 91 | return $ret; |
||||
| 92 | } |
||||
| 93 | |||||
| 94 | /** |
||||
| 95 | * {@inheritdoc} |
||||
| 96 | * |
||||
| 97 | * @throws CommandException When no backportable issues were found. |
||||
| 98 | */ |
||||
| 99 | protected function execute(InputInterface $input, OutputInterface $output) |
||||
| 100 | { |
||||
| 101 | $issue_key = $this->io->getArgument('issue_key'); |
||||
| 102 | $link_name = $this->io->getOption('link-name'); |
||||
| 103 | |||||
| 104 | if ( !in_array($link_name, $this->jiraApi->getIssueLinkTypeNames()) ) { |
||||
| 105 | throw new CommandException('The "' . $link_name . '" link name doesn\'t exist.'); |
||||
| 106 | } |
||||
| 107 | |||||
| 108 | $project_keys = $this->expandProjectKeys($this->io->getArgument('project_keys')); |
||||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||
| 109 | $non_existing_projects = array_diff($project_keys, $this->jiraApi->getProjectKeys()); |
||||
| 110 | |||||
| 111 | if ( $non_existing_projects ) { |
||||
|
0 ignored issues
–
show
The expression
$non_existing_projects of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using Loading history...
|
|||||
| 112 | throw new CommandException( |
||||
| 113 | 'These projects doesn\'t exist: "' . implode('", "', $non_existing_projects) . '".' |
||||
| 114 | ); |
||||
| 115 | } |
||||
| 116 | |||||
| 117 | $issues = $this->issueCloner->getIssues( |
||||
| 118 | 'key = ' . $issue_key, |
||||
|
0 ignored issues
–
show
Are you sure
$issue_key of type null|string|string[] can be used in concatenation?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 119 | $link_name, |
||||
|
0 ignored issues
–
show
It seems like
$link_name can also be of type string[]; however, parameter $link_name of ConsoleHelpers\JiraCLI\I...ssueCloner::getIssues() does only seem to accept string, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 120 | ChangeLogIssueCloner::LINK_DIRECTION_OUTWARD, |
||||
| 121 | $project_keys |
||||
| 122 | ); |
||||
| 123 | $issue_count = count($issues); |
||||
| 124 | |||||
| 125 | if ( !$issue_count ) { |
||||
| 126 | throw new CommandException('The "' . $issue_key . '" issue not found.'); |
||||
| 127 | } |
||||
| 128 | |||||
| 129 | foreach ( $issues as $issue_pair ) { |
||||
| 130 | /** @var Issue $issue */ |
||||
| 131 | /** @var Issue $linked_issue */ |
||||
| 132 | list($issue, $linked_issue, $link_project_key) = $issue_pair; |
||||
| 133 | |||||
| 134 | $issue_project = $issue->get('project'); |
||||
| 135 | |||||
| 136 | if ( $issue_project['key'] === $link_project_key ) { |
||||
| 137 | throw new CommandException('Creating of linked issue in same project is not supported.'); |
||||
| 138 | } |
||||
| 139 | |||||
| 140 | if ( is_object($linked_issue) ) { |
||||
| 141 | $this->io->writeln(sprintf( |
||||
| 142 | 'The "<info>%s</info>" issue already has "<info>%s</info>" link to "<info>%s</info>" issue.', |
||||
| 143 | $issue->getKey(), |
||||
| 144 | $link_name, |
||||
|
0 ignored issues
–
show
It seems like
$link_name can also be of type string[]; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 145 | $linked_issue->getKey() |
||||
| 146 | )); |
||||
| 147 | |||||
| 148 | continue; |
||||
| 149 | } |
||||
| 150 | |||||
| 151 | $components = array(); |
||||
| 152 | $project_components = $this->jiraApi->getProjectComponentMapping( |
||||
| 153 | $link_project_key, |
||||
| 154 | JiraApi::CACHE_DURATION_ONE_MONTH |
||||
| 155 | ); |
||||
| 156 | |||||
| 157 | if ( $project_components ) { |
||||
|
0 ignored issues
–
show
The expression
$project_components of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using Loading history...
|
|||||
| 158 | $component_name = $this->io->choose( |
||||
| 159 | 'Select linked issue component in "' . $link_project_key . '" project:', |
||||
| 160 | $project_components, |
||||
| 161 | '', |
||||
| 162 | 'The component isn\'t valid' |
||||
| 163 | ); |
||||
| 164 | |||||
| 165 | $components[] = array_search($component_name, $project_components); |
||||
| 166 | } |
||||
| 167 | |||||
| 168 | $start = microtime(true); |
||||
| 169 | |||||
| 170 | $linked_issue_key = $this->issueCloner->createLinkedIssue( |
||||
| 171 | $issue, |
||||
| 172 | $link_project_key, |
||||
| 173 | $link_name, |
||||
|
0 ignored issues
–
show
It seems like
$link_name can also be of type string[]; however, parameter $link_name of ConsoleHelpers\JiraCLI\I...er::createLinkedIssue() does only seem to accept string, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 174 | ChangeLogIssueCloner::LINK_DIRECTION_OUTWARD, |
||||
| 175 | $components |
||||
| 176 | ); |
||||
| 177 | |||||
| 178 | $this->statistics[] = sprintf( |
||||
| 179 | 'Issue %s creation time: %ss', |
||||
| 180 | $linked_issue_key, |
||||
| 181 | round(microtime(true) - $start, 3) |
||||
| 182 | ); |
||||
| 183 | |||||
| 184 | $this->io->writeln(sprintf( |
||||
| 185 | 'The "<info>%s</info>" issue now has "<info>%s</info>" link to "<info>%s</info>" issue.', |
||||
| 186 | $issue->getKey(), |
||||
| 187 | $link_name, |
||||
| 188 | $linked_issue_key |
||||
| 189 | )); |
||||
| 190 | } |
||||
| 191 | |||||
| 192 | $this->showStatistics(); |
||||
| 193 | } |
||||
| 194 | |||||
| 195 | /** |
||||
| 196 | * Expands project keys. |
||||
| 197 | * |
||||
| 198 | * @param array $project_keys Project keys. |
||||
| 199 | * |
||||
| 200 | * @return array |
||||
| 201 | */ |
||||
| 202 | protected function expandProjectKeys(array $project_keys) |
||||
| 203 | { |
||||
| 204 | $ret = array(); |
||||
| 205 | |||||
| 206 | foreach ( $project_keys as $project_key ) { |
||||
| 207 | if ( strpos($project_key, ',') === false ) { |
||||
| 208 | $ret[] = $project_key; |
||||
| 209 | } |
||||
| 210 | else { |
||||
| 211 | $ret = array_merge($ret, explode(',', $project_key)); |
||||
| 212 | } |
||||
| 213 | } |
||||
| 214 | |||||
| 215 | return $ret; |
||||
| 216 | } |
||||
| 217 | |||||
| 218 | } |
||||
| 219 |