/** * Get an item. * * @param integer $identifier The item identifier. * * @return IssuesTable * * @since 1.0 * @throws \RuntimeException */ public function getItem($identifier) { if (!$identifier) { throw new \RuntimeException('No id given'); } $item = $this->db->setQuery($this->db->getQuery(true)->select('i.*')->from($this->db->quoteName('#__issues', 'i'))->where($this->db->quoteName('i.project_id') . ' = ' . (int) $this->getProject()->project_id)->where($this->db->quoteName('i.issue_number') . ' = ' . (int) $identifier)->select($this->db->quoteName('s.status', 'status_title'))->select($this->db->quoteName('s.closed', 'closed'))->leftJoin($this->db->quoteName('#__status', 's') . ' ON ' . $this->db->quoteName('i.status') . ' = ' . $this->db->quoteName('s.id'))->select('a1.title AS rel_title, a1.status AS rel_status')->join('LEFT', '#__issues AS a1 ON i.rel_number = a1.issue_number AND a1.project_id = ' . (int) $this->getProject()->project_id)->select('s1.closed AS rel_closed')->join('LEFT', '#__status AS s1 ON a1.status = s1.id')->select('t.name AS rel_name')->join('LEFT', '#__issues_relations_types AS t ON i.rel_type = t.id')->select('m.title AS milestone_title')->join('LEFT', '#__tracker_milestones AS m ON m.milestone_id = i.milestone_id')->select('u.id AS user_id')->leftJoin('#__users AS u ON i.opened_by = u.username'))->loadObject(); if (!$item) { throw new \RuntimeException('Invalid Issue', 1); } // Fetch activities $table = new ActivitiesTable($this->db); $query = $this->db->getQuery(true); $query->select('a.*'); $query->from($this->db->quoteName($table->getTableName(), 'a')); $query->where($this->db->quoteName('a.project_id') . ' = ' . (int) $this->getProject()->project_id); $query->where($this->db->quoteName('a.issue_number') . ' = ' . (int) $item->issue_number); $query->order($this->db->quoteName('a.created_date')); $activityData = $this->db->setQuery($query)->loadObjectList(); $commits = json_decode($item->commits) ?: []; $activities = []; // Store the last commit to fetch the test results later $lastCommit = end($commits); foreach ($activityData as $i => $activity) { foreach ($commits as $i1 => $commit) { $d1 = new \DateTime($commit->committer_date); $d2 = new \DateTime($activity->created_date, new \DateTimeZone('UTC')); if ($d1 < $d2) { $m = explode("\n", $commit->message); $a = new \stdClass(); $a->event = 'commit'; $a->user = $commit->author_name; $a->text = $m[0]; $a->created_date = $commit->committer_date; $a->activities_id = $commit->sha; $activities[] = $a; unset($commits[$i1]); } } $activities[] = $activity; } $item->activities = $activities; // Fetch foreign relations $item->relations_f = $this->db->setQuery($this->db->getQuery(true)->from($this->db->quoteName('#__issues', 'a'))->join('LEFT', '#__issues_relations_types AS t ON a.rel_type = t.id')->join('LEFT', '#__status AS s ON a.status = s.id')->select('a.issue_number, a.title, a.rel_type')->select('t.name AS rel_name')->select('s.status AS status_title, s.closed AS closed')->where($this->db->quoteName('a.rel_number') . '=' . (int) $item->issue_number)->order(array('a.issue_number', 'a.rel_type')))->loadObjectList(); // Group relations by type if ($item->relations_f) { $arr = array(); foreach ($item->relations_f as $relation) { if (false == isset($arr[$relation->rel_name])) { $arr[$relation->rel_name] = array(); } $arr[$relation->rel_name][] = $relation; } $item->relations_f = $arr; } // Fetch the voting data $query->clear()->select('COUNT(id) AS votes, SUM(experienced) AS experienced, SUM(score) AS score')->from($this->db->quoteName('#__issues_voting'))->where($this->db->quoteName('issue_number') . ' = ' . (int) $item->id); $voteData = $this->db->setQuery($query)->loadObject(); $item->votes = $voteData->votes; $item->experienced = $voteData->experienced; $item->score = $voteData->score; // Set the score if we have votes if ($item->votes > 0) { $item->importanceScore = $item->score / $item->votes; } else { $item->importanceScore = 0; } // Decode the merge status $item->gh_merge_status = json_decode($item->gh_merge_status); // Fetch test data if ($lastCommit) { $item->testsSuccess = $this->db->setQuery($query->clear()->select('username')->from($this->db->quoteName('#__issues_tests'))->where($this->db->quoteName('item_id') . ' = ' . (int) $item->id)->where($this->db->quoteName('result') . ' = 1')->where($this->db->quoteName('sha') . ' = ' . $this->db->quote($lastCommit->sha)))->loadColumn(); sort($item->testsSuccess); $item->testsFailure = $this->db->setQuery($query->clear()->select('username')->from($this->db->quoteName('#__issues_tests'))->where($this->db->quoteName('item_id') . ' = ' . (int) $item->id)->where($this->db->quoteName('result') . ' = 2')->where($this->db->quoteName('sha') . ' = ' . $this->db->quote($lastCommit->sha)))->loadColumn(); sort($item->testsFailure); } // Fetch category $item->categories = $this->db->setQuery($query->clear()->select('a.title, a.id, a.color, a.alias')->from($this->db->quoteName('#__issues_categories', 'a'))->innerJoin($this->db->quoteName('#__issue_category_map', 'b') . ' ON b.category_id = a.id')->where('b.issue_id =' . (int) $item->id))->loadObjectList(); return $item; }
/** * Method to process the list of issues and inject into the database as needed * * @return $this * * @since 1.0 */ protected function processData() { if (!$this->items) { $this->logOut(g11n3t('Everything is up to date.')); return $this; } /* @type \Joomla\Database\DatabaseDriver $db */ $db = $this->getContainer()->get('db'); // Initialize our query object $query = $db->getQuery(true); $this->out(sprintf(g11n4t('Processing comments for one modified issue...', 'Processing comments for %d modified issues...', count($this->items)), count($this->items))); $adds = 0; $updates = 0; $count = 1; // Initialize our ActivitiesTable instance to insert the new record $table = new ActivitiesTable($db); // Comments ids for computing the difference $commentsIds = array(); // Comments ids to delete $toDelete = array(); // Start processing the comments now foreach ($this->items as $issueNumber => $comments) { if (!count($comments)) { $this->out()->out(sprintf(g11n3t('No comments for issue # %d'), $issueNumber)); } else { $this->out()->out(sprintf(g11n4t('Processing one comment for issue # %2$d (%3$d/%4$d)', 'Processing %1$d comments for issue # %2$d (%3$d/%4$d)', count($comments)), count($comments), $issueNumber, $count, count($this->items))); $progressBar = $this->getProgressBar(count($comments)); $this->usePBar ? $this->out() : null; foreach ($comments as $i => $comment) { // Store the comment id for computing the difference $commentsIds[] = $comment->id; $check = $db->setQuery($query->clear()->select($table->getKeyName())->select($db->quoteName('updated_date'))->from($db->quoteName($table->getTableName()))->where($db->quoteName('gh_comment_id') . ' = ' . (int) $comment->id)->where($db->quoteName('project_id') . ' = ' . (int) $this->project->project_id))->loadObject(); if ($check) { if (!$this->force) { // If we have something already, check if it needs an update... $d1 = new Date($check->updated_date); $d2 = new Date($comment->updated_at); if ($d1 == $d2) { // No update required $this->usePBar ? $progressBar->update($i + 1) : $this->out('-', false); continue; } } $table->load($check->{$table->getKeyName()}); $this->usePBar ? null : $this->out($this->force ? 'F ' : '~ ', false); } else { // New item $table->reset(); $table->{$table->getKeyName()} = null; $this->usePBar ? null : $this->out('+', false); } $table->gh_comment_id = $comment->id; $table->issue_number = (int) $issueNumber; $table->project_id = $this->project->project_id; $table->user = $comment->user->login; $table->event = 'comment'; $table->text_raw = $comment->body; $table->text = $this->github->markdown->render($comment->body, 'gfm', $this->project->gh_user . '/' . $this->project->gh_project); $this->checkGitHubRateLimit($this->github->markdown->getRateLimitRemaining()); $table->created_date = (new Date($comment->created_at))->format('Y-m-d H:i:s'); $table->updated_date = (new Date($comment->updated_at))->format('Y-m-d H:i:s'); $table->store(); if ($check) { ++$updates; } else { ++$adds; } $this->usePBar ? $progressBar->update($i + 1) : null; } ++$count; } // Compute the difference between GitHub comments and issue comments $issueComments = $this->getIssueCommentsIds($issueNumber); $commentsToDelete = array_diff($issueComments, $commentsIds); $toDelete = array_merge($toDelete, $commentsToDelete); } // Delete comments which does not exist on GitHub if (!empty($toDelete)) { $this->deleteIssuesComments($toDelete); } $this->out()->outOK()->logOut(sprintf(g11n3t('%1$d added, %2$d updated, %3$d deleted.'), $adds, $updates, count($toDelete))); return $this; }