@@ -52,6 +52,13 @@ class IssueCloner
5252 */
5353 protected $ queryFields = array ('summary ' , 'issuelinks ' );
5454
55+ /**
56+ * Project of an issue.
57+ *
58+ * @var array
59+ */
60+ private $ _issueProjects = array ();
61+
5562 /**
5663 * IssueCloner constructor.
5764 *
@@ -81,23 +88,101 @@ public function getIssues($jql, $link_name, $link_direction, array $link_project
8188 $ walker = new Walker ($ this ->jiraApi );
8289 $ walker ->push ($ jql , implode (', ' , $ this ->_getQueryFields ()));
8390
84- $ ret = array ();
91+ $ cache = array ();
8592
8693 foreach ( $ walker as $ issue ) {
8794 foreach ( $ link_project_keys as $ link_project_key ) {
88- $ linked_issue = $ this ->_getLinkedIssue ($ issue , $ link_name , $ link_direction, $ link_project_key );
95+ $ linked_issue = $ this ->_getLinkedIssue ($ issue , $ link_name , $ link_direction );
8996
90- if ( is_object ( $ linked_issue) && $ this -> isAlreadyProcessed ( $ issue , $ linked_issue ) ) {
91- continue ;
97+ if ( $ linked_issue !== null ) {
98+ $ this -> _addToProjectDetectionQueue ( $ linked_issue ) ;
9299 }
93100
94- $ ret [] = array ($ issue , $ linked_issue , $ link_project_key );
101+ $ cache [] = array ($ issue , $ linked_issue , $ link_project_key );
102+ }
103+ }
104+
105+ $ this ->_processProjectDetectionQueue ();
106+
107+ $ ret = array ();
108+
109+ foreach ( $ cache as $ cached_data ) {
110+ list ($ issue , $ linked_issue , $ link_project_key ) = $ cached_data ;
111+
112+ if ( $ linked_issue === null ) {
113+ $ ret [] = $ cached_data ;
114+ continue ;
115+ }
116+
117+ if ( $ this ->isLinkAccepted ($ issue , $ linked_issue )
118+ && $ this ->_getIssueProject ($ linked_issue ) === $ link_project_key
119+ && !$ this ->isAlreadyProcessed ($ issue , $ linked_issue )
120+ ) {
121+ $ ret [] = $ cached_data ;
95122 }
96123 }
97124
98125 return $ ret ;
99126 }
100127
128+ /**
129+ * Adds an issue to the project detection queue.
130+ *
131+ * @param Issue $issue Issue.
132+ *
133+ * @return void
134+ */
135+ private function _addToProjectDetectionQueue (Issue $ issue )
136+ {
137+ $ this ->_issueProjects [$ issue ->getKey ()] = null ;
138+ }
139+
140+ /**
141+ * Detects projects for queued issues.
142+ *
143+ * @return void
144+ */
145+ private function _processProjectDetectionQueue ()
146+ {
147+ $ issues_without_projects = array_keys (array_filter ($ this ->_issueProjects , function ($ project_key ) {
148+ return $ project_key === null ;
149+ }));
150+
151+ if ( !$ issues_without_projects ) {
152+ return ;
153+ }
154+
155+ $ walker = new Walker ($ this ->jiraApi );
156+ $ walker ->push (
157+ 'key IN ( ' . implode (', ' , $ issues_without_projects ) . ') ' ,
158+ 'project '
159+ );
160+
161+ foreach ( $ walker as $ linked_issue ) {
162+ $ linked_issue_project_data = $ linked_issue ->get ('project ' );
163+ $ this ->_issueProjects [$ linked_issue ->getKey ()] = $ linked_issue_project_data ['key ' ];
164+ }
165+ }
166+
167+ /**
168+ * Returns an issue project.
169+ *
170+ * @param Issue $issue Issue.
171+ *
172+ * @return string
173+ * @throws \RuntimeException When issue's project isn't available.
174+ */
175+ private function _getIssueProject (Issue $ issue )
176+ {
177+ $ issue_key = $ issue ->getKey ();
178+
179+ if ( array_key_exists ($ issue_key , $ this ->_issueProjects ) ) {
180+ return $ this ->_issueProjects [$ issue_key ];
181+ }
182+
183+ throw new \RuntimeException ('The issue " ' . $ issue_key . '" project wasn \'t queried. ' );
184+ }
185+
101186 /**
102187 * Builds custom field map.
103188 *
@@ -131,17 +216,16 @@ private function _getQueryFields()
131216 }
132217
133218 /**
134- * Returns issue, which backports given issue.
219+ * Returns issue, which backports given issue (project not matched yet) .
135220 *
136- * @param Issue $issue Issue.
137- * @param string $link_name Link name.
138- * @param integer $link_direction Link direction.
139- * @param string $link_project_key Link project key.
221+ * @param Issue $issue Issue.
222+ * @param string $link_name Link name.
223+ * @param integer $link_direction Link direction.
140224 *
141225 * @return Issue|null
142226 * @throws \InvalidArgumentException When link direction isn't valid.
143227 */
144- private function _getLinkedIssue (Issue $ issue , $ link_name , $ link_direction, $ link_project_key )
228+ private function _getLinkedIssue (Issue $ issue , $ link_name , $ link_direction )
145229 {
146230 foreach ( $ issue ->get ('issuelinks ' ) as $ issue_link ) {
147231 if ( $ issue_link ['type ' ]['name ' ] !== $ link_name ) {
@@ -159,14 +243,7 @@ private function _getLinkedIssue(Issue $issue, $link_name, $link_direction, $lin
159243 }
160244
161245 if ( array_key_exists ($ check_key , $ issue_link ) ) {
162- $ linked_issue = new Issue ($ issue_link [$ check_key ]);
163- $ linked_issue_data = $ this ->jiraApi ->getIssue ($ linked_issue ->getKey (), 'project ' )->getResult ();
164-
165- if ( $ this ->isLinkAccepted ($ issue , $ linked_issue )
166- && $ linked_issue_data ['fields ' ]['project ' ]['key ' ] === $ link_project_key
167- ) {
168- return $ linked_issue ;
169- }
246+ return new Issue ($ issue_link [$ check_key ]);
170247 }
171248 }
172249
0 commit comments