diff --git a/administrator/components/com_patchtester/PatchTester/Controller/DisplayController.php b/administrator/components/com_patchtester/PatchTester/Controller/DisplayController.php index 086557e..fdd86a1 100644 --- a/administrator/components/com_patchtester/PatchTester/Controller/DisplayController.php +++ b/administrator/components/com_patchtester/PatchTester/Controller/DisplayController.php @@ -107,6 +107,7 @@ class DisplayController extends AbstractController $state->set('filter.applied', $app->getUserStateFromRequest($this->context . '.filter.applied', 'filter_applied', '')); $state->set('filter.branch', $app->getUserStateFromRequest($this->context . '.filter.branch', 'filter_branch', '')); $state->set('filter.rtc', $app->getUserStateFromRequest($this->context . '.filter.rtc', 'filter_rtc', '')); + $state->set('filter.npm', $app->getUserStateFromRequest($this->context . '.filter.npm', 'filter_npm', '')); // Pre-fill the limits. $limit = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->get('list_limit', 20), 'uint'); @@ -128,7 +129,7 @@ class DisplayController extends AbstractController // The 2nd part will be considered the direction $direction = $orderingParts[array_key_last($orderingParts)]; - if (in_array(strtoupper($direction), array('ASC', 'DESC', ''))) + if (in_array(strtoupper($direction), ['ASC', 'DESC', ''])) { $state->set('list.direction', $direction); } diff --git a/administrator/components/com_patchtester/PatchTester/Model/PullsModel.php b/administrator/components/com_patchtester/PatchTester/Model/PullsModel.php index 0f18e6f..ea5be1e 100644 --- a/administrator/components/com_patchtester/PatchTester/Model/PullsModel.php +++ b/administrator/components/com_patchtester/PatchTester/Model/PullsModel.php @@ -63,7 +63,6 @@ class PullsModel extends AbstractModel */ public function getBranches() { - // Create a new query object. $db = $this->getDb(); $query = $db->getQuery(true); @@ -85,17 +84,32 @@ class PullsModel extends AbstractModel */ public function getItems() { - // Get a storage key. $store = $this->getStoreId(); - // Try to load the data from internal storage. if (isset($this->cache[$store])) { return $this->cache[$store]; } - // Load the list items and add the items to the internal cache. - $this->cache[$store] = $this->getList($this->getListQueryCache(), $this->getStart(), $this->getState()->get('list.limit')); + $items = $this->getList($this->getListQueryCache(), $this->getStart(), $this->getState()->get('list.limit')); + + $db = $this->getDb(); + $query = $db->getQuery(true) + ->select($db->quoteName(['name', 'color'])) + ->from($db->quoteName('#__patchtester_pulls_labels')); + + array_walk( + $items, + static function ($item) use ($db, $query) { + $query->clear('where'); + $query->where($db->quoteName('pull_id') . ' = ' . $item->pull_id); + $db->setQuery($query); + + $item->labels = $db->loadObjectList(); + } + ); + + $this->cache[$store] = $items; return $this->cache[$store]; } @@ -146,7 +160,7 @@ class PullsModel extends AbstractModel if (!empty($applied)) { // Not applied patches have a NULL value, so build our value part of the query based on this - $value = $applied == 'no' ? ' IS NULL' : ' = 1'; + $value = $applied === 'no' ? ' IS NULL' : ' = 1'; $query->where($db->quoteName('applied') . $value); } @@ -165,11 +179,22 @@ class PullsModel extends AbstractModel if (!empty($applied)) { // Not applied patches have a NULL value, so build our value part of the query based on this - $value = $applied == 'no' ? '0' : '1'; + $value = $applied === 'no' ? '0' : '1'; $query->where($db->quoteName('is_rtc') . ' = ' . $value); } + // Filter for NPM patches + $npm = $this->getState()->get('filter.npm'); + + if (!empty($npm)) + { + // Not applied patches have a NULL value, so build our value part of the query based on this + $value = $npm === 'no' ? '0' : '1'; + + $query->where($db->quoteName('is_npm') . ' = ' . $value); + } + // Handle the list ordering. $ordering = $this->getState()->get('list.ordering', 'a.pull_id'); $direction = $this->getState()->get('list.direction', 'DESC'); @@ -314,6 +339,7 @@ class PullsModel extends AbstractModel if ($page === 1) { $this->getDb()->truncateTable('#__patchtester_pulls'); + $this->getDb()->truncateTable('#__patchtester_pulls_labels'); } try @@ -327,9 +353,9 @@ class PullsModel extends AbstractModel $pulls = json_decode($pullsResponse->body); } - catch (UnexpectedResponse $e) + catch (UnexpectedResponse $exception) { - throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_ERROR_GITHUB_FETCH', $e->getMessage()), $e->getCode(), $e); + throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_ERROR_GITHUB_FETCH', $exception->getMessage()), $exception->getCode(), $exception); } // If this is page 1, let's check to see if we need to paginate @@ -363,10 +389,11 @@ class PullsModel extends AbstractModel // If there are no pulls to insert then bail, assume we're finished if (count($pulls) === 0) { - return array('complete' => true); + return ['complete' => true]; } - $data = array(); + $data = []; + $labels = []; foreach ($pulls as $pull) { @@ -374,29 +401,44 @@ class PullsModel extends AbstractModel { // Check if this PR is RTC and has a `PR-` branch label $isRTC = false; + $isNPM = false; $branch = ''; foreach ($pull->labels as $label) { - if ($label->name === 'RTC') + if (strtolower($label->name) === 'rtc') { $isRTC = true; } - elseif (substr($label->name, 0, 3) === 'PR-') + elseif (strpos($label->name, 'PR-') === 0) { $branch = substr($label->name, 3); } + elseif (strtolower($label->name) === 'npm resource changed') + { + $isNPM = true; + } + + $labels[] = implode( + ',', + [ + (int) $pull->number, + $this->getDb()->quote($label->name), + $this->getDb()->quote($label->color) + ] + ); } // Build the data object to store in the database - $pullData = array( + $pullData = [ (int) $pull->number, $this->getDb()->quote(HTMLHelper::_('string.truncate', $pull->title, 150)), $this->getDb()->quote(HTMLHelper::_('string.truncate', $pull->body, 100)), $this->getDb()->quote($pull->pull_request->html_url), (int) $isRTC, + (int) $isNPM, $this->getDb()->quote($branch), - ); + ]; $data[] = implode(',', $pullData); } @@ -411,7 +453,7 @@ class PullsModel extends AbstractModel $this->getDb()->setQuery( $this->getDb()->getQuery(true) ->insert('#__patchtester_pulls') - ->columns(array('pull_id', 'title', 'description', 'pull_url', 'is_rtc', 'branch')) + ->columns(['pull_id', 'title', 'description', 'pull_url', 'is_rtc', 'is_npm', 'branch']) ->values($data) ); @@ -419,13 +461,47 @@ class PullsModel extends AbstractModel { $this->getDb()->execute(); } - catch (\RuntimeException $e) + catch (\RuntimeException $exception) { - throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_ERROR_INSERT_DATABASE', $e->getMessage()), $e->getCode(), $e); + throw new \RuntimeException( + Text::sprintf( + 'COM_PATCHTESTER_ERROR_INSERT_DATABASE', + $exception->getMessage() + ), + $exception->getCode(), + $exception + ); + } + + $this->getDb()->setQuery( + $this->getDb()->getQuery(true) + ->insert('#__patchtester_pulls_labels') + ->columns(['pull_id', 'name', 'color']) + ->values($labels) + ); + + try + { + $this->getDb()->execute(); + } + catch (\RuntimeException $exception) + { + throw new \RuntimeException( + Text::sprintf( + 'COM_PATCHTESTER_ERROR_INSERT_DATABASE', + $exception->getMessage() + ), + $exception->getCode(), + $exception + ); } // Need to make another request - return array('complete' => false, 'page' => ($page + 1), 'lastPage' => isset($lastPage) ? $lastPage : false); + return [ + 'complete' => false, + 'page' => ($page + 1), + 'lastPage' => $lastPage ?? false + ]; } /** diff --git a/administrator/components/com_patchtester/PatchTester/View/Pulls/tmpl/default.php b/administrator/components/com_patchtester/PatchTester/View/Pulls/tmpl/default.php index 739237b..9407897 100644 --- a/administrator/components/com_patchtester/PatchTester/View/Pulls/tmpl/default.php +++ b/administrator/components/com_patchtester/PatchTester/View/Pulls/tmpl/default.php @@ -36,6 +36,7 @@ $listLimit = (int) ($this->state->get('list.limit')); $filterApplied = $this->escape($this->state->get('filter.applied')); $filterBranch = $this->escape($this->state->get('filter.branch')); $filterRtc = $this->escape($this->state->get('filter.rtc')); +$filterNpm = $this->escape($this->state->get('filter.npm')); $visible = ''; if ($filterApplied || $filterBranch || $filterRtc) @@ -109,6 +110,13 @@ if ($filterApplied || $filterBranch || $filterRtc) +
GitHub will discontinue the use of username and password on of November 13, 2020 at 4:00 PM UTC. It is highly recommended to use the Token Authentication Method
" -COM_PATCHTESTER_FIELD_GH_TOKEN_DESC="Use this field to input a GitHub API Token in place of your username and password. Note that this is required if your account has Two Factor Authentication enabled.To setup an access token, follow these steps.You can always revoke access by deleting the Personal access token from the Personal access tokens on Github.
" -COM_PATCHTESTER_FIELD_GH_TOKEN_LABEL="GitHub Token" -COM_PATCHTESTER_FIELD_GH_USER_LABEL="GitHub Account Username" -COM_PATCHTESTER_FIELD_GH_USER_DESC="Name of account on GitHub to use to authenticate to the API." -COM_PATCHTESTER_FIELD_ORG_LABEL="Custom Project Owner" -COM_PATCHTESTER_FIELD_ORG_DESC="A username or organisation on GitHub to monitor pull requests for." -COM_PATCHTESTER_FIELD_REPO_LABEL="Custom Project Repository" -COM_PATCHTESTER_FIELD_REPO_DESC="Name of a repository on GitHub to monitor pull requests for." -COM_PATCHTESTER_FIELD_REPOSITORY_DESC="Available Joomla! repositories. Select to autopopulate the organisation and repository fields values." -COM_PATCHTESTER_FIELD_REPOSITORY_LABEL="GitHub Repository" -COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_JOOMLA_CMS="Joomla! CMS" -COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_PATCHTESTER="Joomla! Patch Tester Component" -COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_INSTALL_FROM_WEB="Joomla! Install From Web Plugin" -COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_WEBLINKS="Joomla! Weblinks Package" -COM_PATCHTESTER_FIELD_REPOSITORY_CUSTOM="Custom" COM_PATCHTESTER_FIELD_CI_SERVER_NAME="CI Server Address" COM_PATCHTESTER_FIELD_CI_SERVER_NAME_DESC="Server address for obtaining compiled patches." COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH="Switch CI Integration" COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH_DESC="Turn CI integration on or off." -COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH_OPTION_ON="On" COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH_OPTION_OFF="Off" -COM_PATCHTESTER_FIELDSET_REPOSITORIES_DESC="Configuration Values for GitHub Repository" -COM_PATCHTESTER_FIELDSET_REPOSITORIES_LABEL="GitHub Repository" +COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH_OPTION_ON="On" +COM_PATCHTESTER_FIELD_GH_AUTH_DESC="Select 'Credentials' to use authentication through your GitHub Username and Password, or 'Token' for a GitHub API Token" +COM_PATCHTESTER_FIELD_GH_AUTH_LABEL="GitHub Authentication Method" +COM_PATCHTESTER_FIELD_GH_AUTH_OPTION_CREDENTIALS="Credentials" +COM_PATCHTESTER_FIELD_GH_AUTH_OPTION_TOKEN="Token" +COM_PATCHTESTER_FIELD_GH_PASSWORD_DESC="Password for the account entered in the 'GitHub Account Username' field. Note that accounts using Two Factor Authentication will not work with username and password authentication.GitHub will discontinue the use of username and password on of November 13, 2020 at 4:00 PM UTC. It is highly recommended to use the Token Authentication Method
" +COM_PATCHTESTER_FIELD_GH_PASSWORD_LABEL="GitHub Account Password" +COM_PATCHTESTER_FIELD_GH_TOKEN_DESC="Use this field to input a GitHub API Token in place of your username and password. Note that this is required if your account has Two Factor Authentication enabled.To setup an access token, follow these steps.You can always revoke access by deleting the Personal access token from the Personal access tokens on Github.
" +COM_PATCHTESTER_FIELD_GH_TOKEN_LABEL="GitHub Token" +COM_PATCHTESTER_FIELD_GH_USER_DESC="Name of account on GitHub to use to authenticate to the API." +COM_PATCHTESTER_FIELD_GH_USER_LABEL="GitHub Account Username" +COM_PATCHTESTER_FIELD_ORG_DESC="A username or organisation on GitHub to monitor pull requests for." +COM_PATCHTESTER_FIELD_ORG_LABEL="Custom Project Owner" +COM_PATCHTESTER_FIELD_REPO_DESC="Name of a repository on GitHub to monitor pull requests for." +COM_PATCHTESTER_FIELD_REPO_LABEL="Custom Project Repository" +COM_PATCHTESTER_FIELD_REPOSITORY_CUSTOM="Custom" +COM_PATCHTESTER_FIELD_REPOSITORY_DESC="Available Joomla! repositories. Select to autopopulate the organisation and repository fields values." +COM_PATCHTESTER_FIELD_REPOSITORY_LABEL="GitHub Repository" +COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_INSTALL_FROM_WEB="Joomla! Install From Web Plugin" +COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_JOOMLA_CMS="Joomla! CMS" +COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_PATCHTESTER="Joomla! Patch Tester Component" +COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_WEBLINKS="Joomla! Weblinks Package" COM_PATCHTESTER_FIELDSET_AUTHENTICATION_DESC="Configuration Values for GitHub Authentication" COM_PATCHTESTER_FIELDSET_AUTHENTICATION_LABEL="GitHub Authentication" COM_PATCHTESTER_FIELDSET_CI_SETTINGS="CI Server Settings" COM_PATCHTESTER_FIELDSET_CI_SETTINGS_DESC="Configuration Values for CI Server Patching" +COM_PATCHTESTER_FIELDSET_REPOSITORIES_DESC="Configuration Values for GitHub Repository" +COM_PATCHTESTER_FIELDSET_REPOSITORIES_LABEL="GitHub Repository" COM_PATCHTESTER_FILE_DELETED_DOES_NOT_EXIST_S="The file marked for deletion does not exist: %s" COM_PATCHTESTER_FILE_MODIFIED_DOES_NOT_EXIST_S="The file marked for modification does not exist: %s" COM_PATCHTESTER_FILTER_APPLIED_PATCHES="Filter Applied Patches" COM_PATCHTESTER_FILTER_BRANCH="Filter Target Branch" +COM_PATCHTESTER_FILTER_NPM_PATCHES="Filter NPM Patches" COM_PATCHTESTER_FILTER_RTC_PATCHES="Filter RTC Patches" COM_PATCHTESTER_FILTER_SEARCH_DESCRIPTION="Search the list by title or prefix with 'id:' to search by Pull ID." COM_PATCHTESTER_GITHUB="GitHub" @@ -85,7 +86,9 @@ COM_PATCHTESTER_NO_CREDENTIALS="You have not entered your user credentials in th COM_PATCHTESTER_NO_FILES_TO_PATCH="There are no files to patch from this pull request. This may mean that the files in the pull request are not present in your installation." COM_PATCHTESTER_NO_ITEMS="No data has been retrieved from GitHub, please click the 'Fetch Data' button in the toolbar to retrieve the open pull requests." COM_PATCHTESTER_NOT_APPLIED="Not Applied" +COM_PATCHTESTER_NOT_NPM="Not NPM" COM_PATCHTESTER_NOT_RTC="Not RTC" +COM_PATCHTESTER_NPM="NPM" COM_PATCHTESTER_PATCH_BREAKS_SITE="The patch could not be applied because it would break the site. Check the pull request to see if it is up-to-date." COM_PATCHTESTER_PULL_ID="Pull ID" COM_PATCHTESTER_PULL_ID_ASC="Pull ID ascending"