31
0
mirror of https://github.com/joomla-extensions/patchtester.git synced 2024-05-29 03:50:46 +00:00

Start refactoring to store the pull requests in the database

This commit is contained in:
Michael Babker 2014-05-01 09:35:26 -05:00
parent 435f8d1430
commit 57852d602d
10 changed files with 225 additions and 283 deletions

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<config>
<fieldset name="component" label="COM_PATCHTESTER_COMPONENT_LABEL" description="COM_PATCHTESTER_COMPONENT_DESC">
<field name="org" type="text" default="joomla"
description="COM_PATCHTESTER_FIELD_ORG_DESC"
label="COM_PATCHTESTER_FIELD_ORG_LABEL"
@ -21,22 +20,9 @@
description="COM_PATCHTESTER_FIELD_GH_PASSWORD_DESC"
label="COM_PATCHTESTER_FIELD_GH_PASSWORD_LABEL"
/>
<field name="cache" type="radio" class="btn-group" default="1"
description="COM_PATCHTESTER_FIELD_CACHE_DESC"
label="COM_PATCHTESTER_FIELD_CACHE_LABEL" >
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field name="cache_lifetime" type="text" default="60"
description="COM_PATCHTESTER_FIELD_CACHE_LIFETIME_DESC"
label="COM_PATCHTESTER_FIELD_CACHE_LIFETIME_LABEL"
/>
</fieldset>
<fieldset name="permissions" description="JCONFIG_PERMISSIONS_DESC" label="JCONFIG_PERMISSIONS_LABEL">
<field name="rules" type="rules"
component="com_patchtester"
filter="rules"

View File

@ -23,57 +23,4 @@ class PatchTesterController extends JControllerLegacy
* @since 1.0
*/
protected $default_view = 'pulls';
/**
* Method to purge the cache
*
* @return void
*
* @since 2.0
*/
public function purge()
{
// Check for request forgeries
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');
$failures = 0;
$successes = 0;
$cacheFiles = JFolder::files(JPATH_CACHE);
foreach ($cacheFiles as $file)
{
if (strpos($file, 'patchtester-page-') === 0)
{
if (!JFile::delete(JPATH_CACHE . '/' . $file))
{
$failures++;
}
else
{
$successes++;
}
}
}
if ($failures > 0)
{
JFactory::getApplication()->enqueueMessage(JText::plural('COM_PATCHTESTER_PURGE_FAIL', $failures), 'error');
}
if ($successes > 0)
{
JFactory::getApplication()->enqueueMessage(JText::plural('COM_PATCHTESTER_PURGE_SUCCESS', $successes), 'message');
}
if ($failures == 0 && $successes == 0)
{
JFactory::getApplication()->enqueueMessage(JText::_('COM_PATCHTESTER_PURGE_NA'), 'message');
}
$this->setRedirect('index.php?option=com_patchtester&view=pulls');
}
}

View File

@ -0,0 +1,43 @@
<?php
/**
* @package PatchTester
*
* @copyright Copyright (C) 2011 - 2012 Ian MacLennan, Copyright (C) 2013 - 2014 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later
*/
defined('_JEXEC') or die;
/**
* Pulls controller class
*
* @package PatchTester
* @since 2.0
*/
class PatchtesterControllerPull extends JControllerLegacy
{
/**
* Fetch pull request data from GitHub
*
* @return void
*
* @since 2.0
*/
public function fetch()
{
try
{
$this->getModel('pulls')->requestFromGithub();
$msg = JText::_('COM_PATCHTESTER_FETCH_SUCCESSFUL');
$type = 'message';
}
catch (Exception $e)
{
$msg = $e->getMessage();
$type = 'error';
}
$this->setRedirect(JRoute::_('index.php?option=com_patchtester&view=pulls', false), $msg, $type);
}
}

View File

@ -1,3 +1,13 @@
CREATE TABLE IF NOT EXISTS `#__patchtester_pulls` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pull_id` int(11) NOT NULL,
`title` varchar(100) NOT NULL,
`description` varchar(5000) NOT NULL DEFAULT '',
`pull_url` varchar(255) NOT NULL,
`joomlacode_id` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `#__patchtester_tests` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pull_id` int(11) NOT NULL,

View File

@ -13,10 +13,8 @@ COM_PATCHTESTER_COMPONENT_DESC="Joomla! Patch Tester Configuration Values"
COM_PATCHTESTER_COMPONENT_LABEL="Joomla! Patch Tester"
COM_PATCHTESTER_CONFIGURATION="Joomla! Patch Tester Settings"
COM_PATCHTESTER_CONFLICT_S="The patch could not be applied because it conflicts with a previously applied patch: %s"
COM_PATCHTESTER_FIELD_CACHE_DESC="Enabling caching will save the GitHub data locally for the specified time"
COM_PATCHTESTER_FIELD_CACHE_LABEL="Enable Caching"
COM_PATCHTESTER_FIELD_CACHE_LIFETIME_DESC="The amount of time (in minutes) before the cache is reset"
COM_PATCHTESTER_FIELD_CACHE_LIFETIME_LABEL="Cache Lifetime"
COM_PATCHTESTER_ERROR_INSERT_DATABASE="Error inserting pull request data into the database: %s"
COM_PATCHTESTER_FETCH_SUCCESSFUL="Successfully retrieved pull requests."
COM_PATCHTESTER_FIELD_GH_PASSWORD_LABEL="GitHub Account Password"
COM_PATCHTESTER_FIELD_GH_PASSWORD_DESC="Password for the account entered in the "_QQ_"GitHub Account"_QQ_" field. Note that accounts using Two Factor Authentication will not work with this component."
COM_PATCHTESTER_FIELD_GH_USER_LABEL="GitHub Account"
@ -27,18 +25,14 @@ COM_PATCHTESTER_FIELD_REPO_LABEL="GitHub Repository"
COM_PATCHTESTER_FIELD_REPO_DESC="Name of repository on GitHub of which to monitor pull requests"
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_SEARCH_DESCRIPTION="Filter the list by title or ID."
COM_PATCHTESTER_JOOMLACODE_ISSUE="Joomlacode Issue"
COM_PATCHTESTER_PULL_ID="Pull ID"
COM_PATCHTESTER_NO_CREDENTIALS="No user credentials are saved, this will allow only 60 requests to the GitHub API per hour. Saving user credentials will allow 5,000 requests per hour."
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_OPEN_IN_GITHUB="Open in GitHub"
COM_PATCHTESTER_OPEN_IN_JOOMLACODE="Open in JoomlaCode"
COM_PATCHTESTER_PURGE_CACHE="Purge Cache"
COM_PATCHTESTER_PURGE_FAIL="Purge operation not completed successfully, %s files not removed."
COM_PATCHTESTER_PURGE_FAIL_1="Purge operation not completed successfully, %s file not removed."
COM_PATCHTESTER_PURGE_NA="No cache files to remove."
COM_PATCHTESTER_PURGE_SUCCESS="Purge operation completed successfully, %s files removed."
COM_PATCHTESTER_PURGE_SUCCESS_1="Purge operation completed successfully, %s file removed."
COM_PATCHTESTER_REPO_IS_GONE="The patch could not be applied because the repository is missing"
COM_PATCHTESTER_REQUIREMENT_HTTPS="HTTPS wrappers must be enabled"
COM_PATCHTESTER_REQUIREMENT_OPENSSL="The OpenSSL extension must be installed and enabled in your php.ini"
@ -46,6 +40,5 @@ COM_PATCHTESTER_REQUIREMENTS_HEADING="Requirements Not Met"
COM_PATCHTESTER_REQUIREMENTS_NOT_MET="Your system does not meet the requirements to run the Patch Tester extension:"
COM_PATCHTESTER_REVERT_OK="Patch successfully reverted"
COM_PATCHTESTER_REVERT_PATCH="Revert Patch"
COM_PATCHTESTER_SEARCH_IN_PULL_ID="Pull ID"
COM_PATCHTESTER_SEARCH_IN_TITLE="Pull title"
COM_PATCHTESTER_TEST_THIS_PATCH="Test This Patch"
COM_PATCHTESTER_TOOLBAR_FETCH_DATA="Fetch Data"

View File

@ -37,7 +37,7 @@ class PatchtesterModelPulls extends JModelList
*
* @param array $config An optional associative array of configuration settings.
*
* @see JController
* @see JControllerLegacy
* @since 1.0
*/
public function __construct($config = array())
@ -45,7 +45,7 @@ class PatchtesterModelPulls extends JModelList
if (empty($config['filter_fields']))
{
$config['filter_fields'] = array(
'id', 'title', 'updated_at', 'user', 'applied'
'id', 'title', 'applied'
);
}
@ -72,12 +72,6 @@ class PatchtesterModelPulls extends JModelList
// Store the rate data for reuse during this request cycle
$this->rate = $this->github->authorization->getRateLimit()->rate;
// Check the API rate limit, display a message if over
if ($this->rate->remaining == 0)
{
JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_PATCHTESTER_API_LIMIT_LIST', JFactory::getDate($this->rate->reset)), 'notice');
}
}
/**
@ -97,9 +91,6 @@ class PatchtesterModelPulls extends JModelList
$search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '');
$this->setState('filter.search', $search);
$searchId = $this->getUserStateFromRequest($this->context . '.filter.searchid', 'filter_searchid', '');
$this->setState('filter.searchid', $searchId);
// Load the parameters.
$params = JComponentHelper::getParams('com_patchtester');
@ -108,10 +99,7 @@ class PatchtesterModelPulls extends JModelList
$this->setState('github_repo', $params->get('repo', 'joomla-cms'));
// List state information.
parent::populateState('number', 'desc');
// GitHub's default list limit is 30
$this->setState('list.limit', 30);
parent::populateState('a.pull_id', 'desc');
}
/**
@ -123,13 +111,14 @@ class PatchtesterModelPulls extends JModelList
*/
public function getAppliedPatches()
{
$db = $this->getDbo();
$query = $db->getQuery(true)
->select('*')
->from('#__patchtester_tests')
->where('applied = 1');
$db = $this->getDbo();
$db->setQuery($query);
$db->setQuery(
$db->getQuery(true)
->select('*')
->from($db->quoteName('#__patchtester_tests'))
->where($db->quoteName('applied') . ' = 1')
);
try
{
@ -146,111 +135,83 @@ class PatchtesterModelPulls extends JModelList
}
/**
* Method to get an array of data items.
* Method to get a JDatabaseQuery object for retrieving the data set from a database.
*
* @return mixed An array of data items on success, false on failure.
* @return JDatabaseQuery A JDatabaseQuery object to retrieve the data set.
*
* @since 1.0
* @since 2.0
*/
public function getItems()
protected function getListQuery()
{
if ($this->getState('github_user') == '' || $this->getState('github_repo') == '')
// Create a new query object.
$db = $this->getDbo();
$query = $db->getQuery(true);
// Select the required fields from the table.
$query->select($this->getState('list.select', 'a.*'));
$query->from($db->quoteName('#__patchtester_pulls', 'a'));
// Filter by search
$search = $this->getState('filter.search');
if (!empty($search))
{
return array();
}
$this->ordering = $this->getState('list.ordering', 'title');
$this->orderDir = $this->getState('list.direction', 'asc');
try
{
$cacheFile = JPATH_CACHE . '/patchtester-page-' . $this->getPagination()->pagesCurrent . '.json';
$params = $this->getState('params');
$searchId = $this->getState('filter.searchid');
$searchWord = $this->getState('filter.search');
// Check if caching is enabled or that we aren't filtering
if ($params->get('cache', 1) == 1 && $searchId != '' && $searchWord != '')
if (stripos($search, 'id:') === 0)
{
// Fetch cache time from component parameters and convert to seconds
$cacheTime = $params->get('cache_lifetime', 60);
$cacheTime = $cacheTime * 60;
// Cache files expired?
if (!file_exists($cacheFile) || (time() - @filemtime($cacheFile) > $cacheTime))
{
// Do a request to the GitHub API for new data
$pulls = $this->requestFromGithub();
}
else
{
// Render from the cached data
$pulls = json_decode(file_get_contents($cacheFile));
}
$query->where($db->quoteName('a.pull_id') . ' = ' . (int) substr($search, 3));
}
else
{
// No caching, request from GitHub
$pulls = $this->requestFromGithub();
$search = $db->quote('%' . $db->escape($search, true) . '%');
$query->where('(' . $db->quoteName('a.title') . ' LIKE ' . $search . ')');
}
return $pulls;
}
catch (Exception $e)
// Handle the list ordering.
$ordering = $this->getState('list.ordering');
$direction = $this->getState('list.direction');
if (!empty($ordering))
{
JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');
return array();
$query->order($db->escape($ordering) . ' ' . $db->escape($direction));
}
return $query;
}
/**
* Method to request new data from GitHub
*
* @return array Pull request data
* @return void
*
* @since 2.0
* @throws RuntimeException
*/
protected function requestFromGithub()
public function requestFromGithub()
{
// If over the API limit, we can't build this list
if ($this->rate->remaining > 0)
{
$page = $this->getPagination()->pagesCurrent;
$search = $this->getState('filter.search');
$searchId = $this->getState('filter.searchid');
// Check if we're searching for a single PR
if ($searchId != '' && $search == '')
{
$pulls = array();
$pulls[0] = $this->github->pulls->get($this->getState('github_user'), $this->getState('github_repo'), $searchId);
}
else
{
$pulls = $this->github->pulls->getList($this->getState('github_user'), $this->getState('github_repo'), 'open', $page);
$pulls = $this->mergeAppliedData($pulls);
usort($pulls, array($this, 'sortItems'));
}
$db = $this->getDbo();
$pulls = $this->github->pulls->getList($this->getState('github_user'), $this->getState('github_repo'), 'open');
foreach ($pulls as $i => &$pull)
{
if ($search && false === strpos($pull->title, $search))
{
unset($pulls[$i]);
continue;
}
// Build the data object to store in the database
$data = new stdClass;
$data->pull_id = $pull->number;
$data->title = $pull->title;
$data->description = $pull->body;
$data->pull_url = $pull->html_url;
// Try to find a Joomlacode issue number
$pulls[$i]->joomlacode_issue = 0;
$matches = array();
preg_match('#\[\#([0-9]+)\]#', $pull->title, $matches);
if (isset($matches[1]))
{
$pulls[$i]->joomlacode_issue = (int) $matches[1];
$data->joomlacode_id = (int) $matches[1];
}
else
{
@ -262,101 +223,24 @@ class PatchtesterModelPulls extends JModelList
if (isset($matches[1]))
{
$pulls[$i]->joomlacode_issue = (int) $matches[1];
$data->joomlacode_id = (int) $matches[1];
}
}
}
}
// If caching is enabled, save the request data
$params = $this->getState('params');
if ($params->get('cache', 1) == 1 && $searchId != '' && $search != '')
{
$data = json_encode($pulls);
file_put_contents(JPATH_CACHE . '/patchtester-page-' . $this->getPagination()->pagesCurrent . '.json', $data);
try
{
$db->insertObject('#__patchtester_pulls', $data, 'id');
}
catch (RuntimeException $e)
{
throw new RuntimeException(JText::sprintf('COM_PATCHTESTER_ERROR_INSERT_DATABASE', $e->getMessage()));
}
}
}
else
{
$pulls = array();
throw new RuntimeException(JText::sprintf('COM_PATCHTESTER_API_LIMIT_LIST', JFactory::getDate($this->rate->reset)));
}
return $pulls;
}
/**
* Method to sort the items array
*
* @param object $a First sort object
* @param object $b Second sort object
*
* @return mixed
*
* @since 1.0
*/
public function sortItems($a, $b)
{
switch ($this->ordering)
{
case 'title' :
return ($this->orderDir == 'asc') ? strcasecmp($a->title, $b->title) : strcasecmp($b->title, $a->title);
case 'applied' :
return ($this->orderDir == 'asc') ? $b->applied > $a->applied : $b->applied < $a->applied;
case 'number' :
default :
return ($this->orderDir == 'asc') ? $b->number < $a->number : $b->number > $a->number;
}
}
/**
* Method to get the total number of items for the data set.
*
* @return integer The total number of items available in the data set.
*
* @since 2.0
*/
public function getTotal()
{
if ($this->rate->remaining > 0)
{
return $this->github->repositories->get('joomla', 'joomla-cms')->open_issues_count;
}
else
{
return 0;
}
}
/**
* Flags pull requests as having been applied in the current environment
*
* @param array $pulls Array of pull data
*
* @return array
*
* @since 2.0
*/
protected function mergeAppliedData($pulls)
{
// Fetch the applied patches
$appliedData = $this->getAppliedPatches();
// Loop through the pulls and add an applied flag
foreach ($pulls as $pull)
{
if (array_key_exists($pull->number, $appliedData))
{
$pull->applied = 1;
}
else
{
$pull->applied = 0;
}
}
return $pulls;
}
}

View File

@ -0,0 +1,30 @@
<?php
/**
* @package PatchTester
*
* @copyright Copyright (C) 2011 - 2012 Ian MacLennan, Copyright (C) 2013 - 2014 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later
*/
defined('_JEXEC') or die;
/**
* Pulls Table class
*
* @package PatchTester
* @since 1.0
*/
class PatchtesterTablePulls extends JTable
{
/**
* Constructor
*
* @param JDatabaseDriver &$db JDatabaseDriver object.
*
* @since 1.0
*/
public function __construct(&$db)
{
parent::__construct('#__patchtester_pulls', 'id', $db);
}
}

View File

@ -13,8 +13,9 @@ defined('_JEXEC') or die;
JHtml::_('behavior.tooltip');
JHtml::_('behavior.modal');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn = $this->escape($this->state->get('list.direction'));
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn = $this->escape($this->state->get('list.direction'));
$sortFields = $this->getSortFields();
if (count($this->envErrors)) :
$this->loadTemplate('errors');
@ -25,21 +26,53 @@ else :
document.id('pull_id').set('value', id);
return Joomla.submitbutton(task);
}
Joomla.orderTable = function() {
table = document.getElementById('sortTable');
direction = document.getElementById('directionTable');
order = table.options[table.selectedIndex].value;
if (order != '<?php echo $listOrder; ?>') {
dirn = 'asc';
} else {
dirn = direction.options[direction.selectedIndex].value;
}
Joomla.tableOrdering(order, dirn, '');
}
</script>
<form action="<?php echo JRoute::_('index.php?option=com_patchtester&view=pulls'); ?>" method="post" name="adminForm" id="adminForm">
<div id="filter-bar" class="btn-toolbar">
<div class="btn-group pull-right">
<label for="sortTable" class="element-invisible"><?php echo JText::_('JGLOBAL_SORT_BY'); ?></label>
<select name="sortTable" id="sortTable" class="input-medium" onchange="Joomla.orderTable()">
<option value=""><?php echo JText::_('JGLOBAL_SORT_BY'); ?></option>
<?php echo JHtml::_('select.options', $sortFields, 'value', 'text', $listOrder);?>
</select>
</div>
</div>
<div id="j-main-container">
<div id="filter-bar" class="btn-toolbar">
<div class="filter-search btn-group pull-left">
<label for="filter_search" class="element-invisible"><?php echo JText::_('COM_PATCHTESTER_FILTER_SEARCH_DESCRIPTION'); ?></label>
<input type="text" name="filter_search" placeholder="<?php echo JText::_('COM_PATCHTESTER_FILTER_SEARCH_DESCRIPTION'); ?>" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('COM_PATCHTESTER_FILTER_SEARCH_DESCRIPTION'); ?>" />
</div>
<div class="btn-group pull-left hidden-phone">
<button type="submit" class="btn"><?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?></button>
<button type="button" class="btn" onclick="document.id('filter_search').value='';document.id('filter_searchid').value='';this.form.submit();">
<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>
</button>
<button class="btn tip hasTooltip" type="submit" title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>"><i class="icon-search"></i></button>
<button class="btn tip hasTooltip" type="button" onclick="document.id('filter_search').value='';this.form.submit();" title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>"><i class="icon-remove"></i></button>
</div>
<div class="btn-group pull-right hidden-phone">
<label for="limit" class="element-invisible"><?php echo JText::_('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC'); ?></label>
<?php echo $this->pagination->getLimitBox(); ?>
</div>
<div class="btn-group pull-right hidden-phone">
<label for="directionTable" class="element-invisible"><?php echo JText::_('JFIELD_ORDERING_DESC'); ?></label>
<select name="directionTable" id="directionTable" class="input-medium" onchange="Joomla.orderTable()">
<option value=""><?php echo JText::_('JFIELD_ORDERING_DESC');?></option>
<option value="asc" <?php if ($listDirn == 'asc') echo 'selected="selected"'; ?>><?php echo JText::_('JGLOBAL_ORDER_ASCENDING'); ?></option>
<option value="desc" <?php if ($listDirn == 'desc') echo 'selected="selected"'; ?>><?php echo JText::_('JGLOBAL_ORDER_DESCENDING'); ?></option>
</select>
</div>
</div>
<div class="clearfix"> </div>
@ -47,21 +80,17 @@ else :
<thead>
<tr>
<th width="5%" class="nowrap center">
<?php echo JHtml::_('grid.sort', 'COM_PATCHTESTER_PULL_ID', 'number', $listDirn, $listOrder); ?>
<br />
<input type="text" name="filter_searchid" id="filter_searchid" class="span10" value="<?php echo $this->escape($this->state->get('filter.searchid')); ?>" />
<?php echo JText::_('COM_PATCHTESTER_PULL_ID'); ?>
</th>
<th class="nowrap center">
<?php echo JHtml::_('grid.sort', 'JGLOBAL_TITLE', 'title', $listDirn, $listOrder); ?>
<br />
<input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" />
<?php echo JText::_('JGLOBAL_TITLE'); ?>
</th>
<th class="nowrap center">I</th>
<th class="nowrap center">
<?php echo JText::_('COM_PATCHTESTER_JOOMLACODE_ISSUE'); ?>
</th>
<th width="20%" class="nowrap center">
<?php echo JHtml::_('grid.sort', 'JSTATUS', 'applied', $listDirn, $listOrder); ?>
<?php echo JText::_('JSTATUS'); ?>
</th>
<th width="20%" class="nowrap center">
<?php echo JText::_('COM_PATCHTESTER_TEST_THIS_PATCH'); ?>
@ -75,7 +104,11 @@ else :
</tr>
</tfoot>
<tbody>
<?php echo $this->loadTemplate('items'); ?>
<?php if (count($this->items)) :
echo $this->loadTemplate('items');
else :
echo JText::_('COM_PATCHTESTER_NO_ITEMS');
endif; ?>
</tbody>
</table>
<?php echo $this->pagination->getListFooter(); ?>

View File

@ -13,8 +13,8 @@ defined('_JEXEC') or die;
foreach ($this->items as $i => $item) :
$status = '';
if (isset($this->patches[$item->number])) :
$patch = $this->patches[$item->number];
if (isset($this->patches[$item->pull_id])) :
$patch = $this->patches[$item->pull_id];
$status = ($patch->applied) ? 'success' : '';
else :
$patch = false;
@ -22,31 +22,31 @@ foreach ($this->items as $i => $item) :
?>
<tr class="<?php echo $status ?>">
<td class="center">
<?php echo $item->number; ?>
<?php echo $item->pull_id; ?>
</td>
<td>
<a class="icon icon16-github hasTip" title="<?php echo JText::_('COM_PATCHTESTER_OPEN_IN_GITHUB'); ?>" href="<?php echo $item->html_url; ?>" target="_blank">
<a class="icon icon16-github hasTip" title="<?php echo JText::_('COM_PATCHTESTER_OPEN_IN_GITHUB'); ?>" href="<?php echo $item->pull_url; ?>" target="_blank">
<?php echo $item->title; ?>
</a>
</td>
<td>
<?php if ($item->body) :
echo JHtml::_('tooltip', htmlspecialchars($item->body), 'Info');
<?php if ($item->description) :
echo JHtml::_('tooltip', htmlspecialchars($item->description), 'Info');
else :
echo '&nbsp;';
endif;
?>
</td>
<td>
<?php if ($item->joomlacode_issue) :
<?php if ($item->joomlacode_id) :
$title = ' title="Open link::' . JText::_('COM_PATCHTESTER_OPEN_IN_JOOMLACODE') . '"';
if (is_int($item->joomlacode_issue)) :
if (is_int($item->joomlacode_id)) :
echo '<a href="http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=';
echo $item->joomlacode_issue . '"' . $title . ' class="modal hasTip" rel="{handler: \'iframe\', size: {x: 900, y: 500}}">';
echo '[#' . $item->joomlacode_issue . ']</a>';
echo $item->joomlacode_id . '"' . $title . ' class="modal hasTip" rel="{handler: \'iframe\', size: {x: 900, y: 500}}">';
echo '[#' . $item->joomlacode_id . ']</a>';
else :
echo '<a href="' . $item->joomlacode_issue . '"' . $title;
echo '<a href="' . $item->joomlacode_id . '"' . $title;
echo ' class="modal hasTip" rel="{handler: \'iframe\', size: {x: 900, y: 500}}">';
echo '[#joomlacode]</a>';
endif;
@ -67,7 +67,7 @@ foreach ($this->items as $i => $item) :
<?php if ($patch && $patch->applied) :
echo '<a class="btn btn-small btn-success" href="javascript:submitpatch(\'pull.revert\', ' . (int) $patch->id . ');">' . JText::_('COM_PATCHTESTER_REVERT_PATCH') . '</a>';
else :
echo '<a class="btn btn-small btn-primary" href="javascript:submitpatch(\'pull.apply\', ' . (int) $item->number . ');">' . JText::_('COM_PATCHTESTER_APPLY_PATCH') . '</a>';
echo '<a class="btn btn-small btn-primary" href="javascript:submitpatch(\'pull.apply\', ' . (int) $item->pull_id . ');">' . JText::_('COM_PATCHTESTER_APPLY_PATCH') . '</a>';
endif; ?>
</td>
</tr>

View File

@ -114,7 +114,7 @@ class PatchtesterViewPulls extends JViewLegacy
if (!count($this->envErrors))
{
JToolbarHelper::custom('purge', 'delete.png', 'delete_f2.png', 'COM_PATCHTESTER_PURGE_CACHE', false);
JToolbarHelper::custom('pulls.fetch', 'delete.png', 'delete_f2.png', 'COM_PATCHTESTER_TOOLBAR_FETCH_DATA', false);
}
JToolBarHelper::preferences('com_patchtester');
@ -123,4 +123,20 @@ class PatchtesterViewPulls extends JViewLegacy
'.icon-48-patchtester {background-image: url(components/com_patchtester/assets/images/icon-48-patchtester.png);}'
);
}
/**
* Returns an array of fields the table can be sorted by
*
* @return array Array containing the field name to sort by as the key and display text as value
*
* @since 2.0
*/
protected function getSortFields()
{
return array(
'a.title' => JText::_('JGLOBAL_TITLE'),
'a.pull_id' => JText::_('COM_PATCHTESTER_PULL_ID'),
'applied' => JText::_('JSTATUS')
);
}
}