33
0
mirror of https://github.com/joomla-extensions/patchtester.git synced 2025-01-11 01:32:05 +00:00

Merge branch '4.0-dev'

This commit is contained in:
Roland Dalmulder 2020-03-21 09:51:05 +01:00
commit fac5d93bb0
No known key found for this signature in database
GPG Key ID: FD49814C56AE3AF9
35 changed files with 1214 additions and 869 deletions

37
.drone.yml Normal file
View File

@ -0,0 +1,37 @@
---
kind: pipeline
name: default
clone:
depth: 42
steps:
- name: composer
image: joomlaprojects/docker-tools:develop
commands:
- composer validate --no-check-all --strict
- composer install --no-progress --no-suggest
- name: phpcs
image: joomlaprojects/docker-images:php7.2
commands:
- echo $(date)
- ./administrator/components/com_patchtester/vendor/bin/phpcs --extensions=php -p --ignore=administrator/components/com_patchtester/vendor --standard=administrator/components/com_patchtester/vendor/joomla/cms-coding-standards/lib/Joomla-CMS administrator
- echo $(date)
- name: crowdin
image: joomlaprojects/docker-images:php7.2
environment:
CROWDIN_API_KEY:
from_secret: CROWDIN_API_KEY
commands:
- echo $(date)
- ./administrator/components/com_patchtester/vendor/bin/crowdin --upload
- echo $(date)
when:
event: push
---
kind: signature
hmac: db121d6418e6f0702b311cce34d0a0dd12a4b88814138a4d1d02c1e6189e9d43
...

View File

@ -1,25 +0,0 @@
# Forces new Travis-CI Infrastructure
sudo: false
language: php
env:
global:
- secure: DW+TBREK61G9CahBZ+3FoMD8GvsGyZHPNW0lTR0gpKmGvmjkJXWxgiB2ZlnBMIPTq3CTbV0vZa/XNHELlhjHLMUCz1aQJ+07JnNt+nVvhmpUgS1C2Nci8jpYP6hjDadOU+D4b90YclrrQDcYbeCHuoLW2kiqiuB+DXyoCWEJXls=
- RUN_PHPCS="no"
- UPDATE_CROWDIN="no"
matrix:
include:
- php: 5.6
env: RUN_PHPCS="yes"
- php: 7.0
env: UPDATE_CROWDIN="yes"
before_script:
# Make sure all dev dependencies are installed
- composer install
script:
- if [[ $RUN_PHPCS == "yes" ]]; then administrator/components/com_patchtester/vendor/bin/phpcs --report=full --extensions=php -p --standard=build/phpcs/Joomla --ignore=./*tmpl/*,administrator/components/com_patchtester/vendor/* administrator/components/com_patchtester; fi
- if [[ $UPDATE_CROWDIN == "yes" && $TRAVIS_PULL_REQUEST == "false" && $TRAVIS_BRANCH == "master" ]]; then administrator/components/com_patchtester/vendor/bin/crowdin --upload; fi

View File

@ -100,18 +100,19 @@ class DisplayController extends AbstractController
protected function initializeState(AbstractModel $model) protected function initializeState(AbstractModel $model)
{ {
$state = parent::initializeState($model); $state = parent::initializeState($model);
$app = $this->getApplication();
// Load the filter state. // Load the filter state.
$state->set('filter.search', $this->getApplication()->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '')); $state->set('filter.search', $app->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', ''));
$state->set('filter.applied', $this->getApplication()->getUserStateFromRequest($this->context . '.filter.applied', 'filter_applied', '')); $state->set('filter.applied', $app->getUserStateFromRequest($this->context . '.filter.applied', 'filter_applied', ''));
$state->set('filter.branch', $this->getApplication()->getUserStateFromRequest($this->context . '.filter.branch', 'filter_branch', '')); $state->set('filter.branch', $app->getUserStateFromRequest($this->context . '.filter.branch', 'filter_branch', ''));
$state->set('filter.rtc', $this->getApplication()->getUserStateFromRequest($this->context . '.filter.rtc', 'filter_rtc', '')); $state->set('filter.rtc', $app->getUserStateFromRequest($this->context . '.filter.rtc', 'filter_rtc', ''));
// Pre-fill the limits. // Pre-fill the limits.
$limit = $this->getApplication()->getUserStateFromRequest('global.list.limit', 'limit', $this->getApplication()->get('list_limit', 20), 'uint'); $limit = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->get('list_limit', 20), 'uint');
$state->set('list.limit', $limit); $state->set('list.limit', $limit);
$fullOrdering = $this->getApplication()->getUserStateFromRequest($this->context . '.fullorder', 'list_fullordering', $this->defaultFullOrdering); $fullOrdering = $app->getUserStateFromRequest($this->context . '.fullorder', 'list_fullordering', $this->defaultFullOrdering);
$orderingParts = explode(' ', $fullOrdering); $orderingParts = explode(' ', $fullOrdering);
@ -140,7 +141,7 @@ class DisplayController extends AbstractController
$state->set('list.ordering', $ordering); $state->set('list.ordering', $ordering);
} }
$value = $this->getApplication()->getUserStateFromRequest($this->context . '.limitstart', 'limitstart', 0); $value = $app->getUserStateFromRequest($this->context . '.limitstart', 'limitstart', 0);
$limitstart = ($limit != 0 ? (floor($value / $limit) * $limit) : 0); $limitstart = ($limit != 0 ? (floor($value / $limit) * $limit) : 0);
$state->set('list.start', $limitstart); $state->set('list.start', $limitstart);

View File

@ -36,30 +36,46 @@ class ResetController extends AbstractController
try try
{ {
$hasErrors = false; $hasErrors = false;
$revertErrored = false;
$pullModel = new PullModel(null, Factory::getDbo()); $pullModel = new PullModel(null, Factory::getDbo());
$pullsModel = new PullsModel($this->context, null, Factory::getDbo()); $pullsModel = new PullsModel($this->context, null, Factory::getDbo());
$testsModel = new TestsModel(null, Factory::getDbo()); $testsModel = new TestsModel(null, Factory::getDbo());
// Check the applied patches in the database first // Check the applied patches in the database first
$appliedPatches = $testsModel->getAppliedPatches(); $appliedPatches = $pullModel->getPatchesDividedInProcs();
if (count($appliedPatches)) if (count($appliedPatches['git']))
{ {
$revertErrored = false;
// Let's try to cleanly revert all applied patches // Let's try to cleanly revert all applied patches
foreach ($appliedPatches as $patch) foreach ($appliedPatches['git'] as $patch)
{ {
try try
{ {
$pullModel->revert($patch->id); $pullModel->revertWithGitHub($patch->id);
} }
catch (\RuntimeException $e) catch (\RuntimeException $e)
{ {
$revertErrored = true; $revertErrored = true;
} }
} }
}
if (count($appliedPatches['ci']))
{
// Let's try to cleanly revert all applied patches with ci
foreach ($appliedPatches['ci'] as $patch)
{
try
{
$pullModel->revertWithCIServer($patch->insert_id);
}
catch (\RuntimeException $e)
{
$revertErrored = true;
}
}
}
// If we errored out reverting patches, we'll need to truncate the table // If we errored out reverting patches, we'll need to truncate the table
if ($revertErrored) if ($revertErrored)
@ -77,7 +93,6 @@ class ResetController extends AbstractController
); );
} }
} }
}
// Now truncate the pulls table // Now truncate the pulls table
try try

View File

@ -62,4 +62,34 @@ abstract class Helper
return new GitHub($options); return new GitHub($options);
} }
/**
* Initializes the CI Settings
*
* @return Registry
*
* @since 3.0
*/
public static function initializeCISettings()
{
$params = ComponentHelper::getParams('com_patchtester');
$options = new Registry;
// Set CI server address for the request
$options->set('server.url', $params->get('ci_server', 'https://ci.joomla.org:444'));
// Set name of the zip archive
$options->set('zip.name', 'build.zip');
$options->set('zip.log.name', 'deleted_files.log');
// Set temp archive for extracting and downloading files
$options->set('folder.temp', Factory::getConfig()->get('tmp_path'));
$options->set('folder.backups', JPATH_COMPONENT . '/backups');
// Set full url for addressing the file
$options->set('zip.url', $options->get('server.url') . '/artifacts/joomla/joomla-cms/4.0-dev/%s/patchtester/' . $options->get('zip.name'));
return $options;
}
} }

View File

@ -8,12 +8,17 @@
namespace PatchTester\Model; namespace PatchTester\Model;
use Joomla\Archive\Zip;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory; use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\Path; use Joomla\CMS\Filesystem\Path;
use Joomla\CMS\Http\Response;
use Joomla\CMS\Language\Text; use Joomla\CMS\Language\Text;
use Joomla\CMS\Version; use Joomla\CMS\Version;
use Joomla\Filesystem\File; use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
use PatchTester\GitHub\Exception\UnexpectedResponse; use PatchTester\GitHub\Exception\UnexpectedResponse;
use PatchTester\GitHub\GitHub;
use PatchTester\Helper; use PatchTester\Helper;
/** /**
@ -134,6 +139,193 @@ class PullModel extends AbstractModel
return $parsedFiles; return $parsedFiles;
} }
/**
* Patches the code with the supplied pull request
* However uses different methods for different repositories.
*
* @param integer $id ID of the pull request to apply
*
* @return boolean
*
* @since 3.0
*
* @throws \RuntimeException
*/
public function apply($id)
{
$params = ComponentHelper::getParams('com_patchtester');
// Decide based on repository settings whether patch will be applied through Github or CIServer
if (version_compare(JVERSION, "4", "ge") && (bool) $params->get('ci_switch', 1))
{
return $this->applyWithCIServer($id);
}
else
{
return $this->applyWithGitHub($id);
}
}
/**
* Patches the code with the supplied pull request
*
* @param integer $id ID of the pull request to apply
*
* @return boolean
*
* @since 3.0
*
* @throws \RuntimeException
*/
private function applyWithCIServer($id)
{
// Get the CIServer Registry
$ciSettings = Helper::initializeCISettings();
// Get the Github object
$github = Helper::initializeGithub();
// Retrieve pullData for sha later on.
try
{
$pull = $this->retrieveGitHubData($github, $id);
$sha = $pull->head->sha;
}
catch (\RuntimeException $e)
{
// Catch the Exception and continue, because the hash is not that
// necessary for applying patches
$sha = "Error:429";
}
// Create tmp folder if it does not exist
if (!file_exists($ciSettings->get('folder.temp')))
{
Folder::create($ciSettings->get('folder.temp'));
}
$tempPath = $ciSettings->get('folder.temp') . "/$id";
$backupsPath = $ciSettings->get('folder.backups') . "/$id";
$delLogPath = $tempPath . '/' . $ciSettings->get('zip.log.name');
$zipPath = $tempPath . '/' . $ciSettings->get('zip.name');
$serverZipPath = sprintf($ciSettings->get('zip.url'), $id);
// Patch has already been applied
if (file_exists($backupsPath))
{
return false;
}
// Check if zip folder exists on server
$serverHeaders = @get_headers($serverZipPath);
if (!$serverHeaders || $serverHeaders[0] != 'HTTP/1.1 200 OK')
{
throw new \RuntimeException(Text::_('COM_PATCHTESTER_SERVER_RESPONDED_NOT_200'));
}
Folder::create($tempPath);
file_put_contents($zipPath, fopen($serverZipPath, "r"));
// Check if zip folder could have been downloaded
if (!file_exists($zipPath))
{
Folder::delete($tempPath);
throw new \RuntimeException(Text::_('COM_PATCHTESTER_ZIP_DOES_NOT_EXIST'));
}
$zip = new Zip;
if (!$zip->extract($zipPath, $tempPath))
{
Folder::delete($tempPath);
throw new \RuntimeException(Text::_('COM_PATCHTESTER_ZIP_EXTRACT_FAILED'));
}
// Remove zip to avoid get listing afterwards
File::delete($zipPath);
// Get files from deleted_logs
$deletedFiles = (file_exists($delLogPath) ? file($delLogPath) : array());
$deletedFiles = array_map('trim', $deletedFiles);
if (file_exists($delLogPath))
{
// Remove deleted_logs to avoid get listing afterwards
File::delete($delLogPath);
}
// Retrieve all files and merge them into one array
$files = Folder::files($tempPath, null, true, true);
$files = str_replace(Path::clean("$tempPath\\"), '', $files);
$files = array_merge($files, $deletedFiles);
Folder::create($backupsPath);
// Moves existent files to backup and replace them or creates new one if they don't exist
foreach ($files as $key => $file)
{
try
{
$filePath = explode(DIRECTORY_SEPARATOR, Path::clean($file));
array_pop($filePath);
$filePath = implode(DIRECTORY_SEPARATOR, $filePath);
// Deleted_logs returns files as well as folder, if value is folder, unset and skip
if (is_dir(JPATH_ROOT . "/$file"))
{
unset($files[$key]);
continue;
}
if (file_exists(JPATH_ROOT . "/$file"))
{
// Create directories if they don't exist until file
if (!file_exists("$backupsPath/$filePath"))
{
Folder::create("$backupsPath/$filePath");
}
File::move(JPATH_ROOT . "/$file", "$backupsPath/$file");
}
if (file_exists("$tempPath/$file"))
{
// Create directories if they don't exist until file
if (!file_exists(JPATH_ROOT . "/$filePath") || !is_dir(JPATH_ROOT . "/$filePath"))
{
Folder::create(JPATH_ROOT . "/$filePath");
}
File::copy("$tempPath/$file", JPATH_ROOT . "/$file");
}
}
catch (\RuntimeException $e)
{
Folder::delete($tempPath);
Folder::move($backupsPath, $backupsPath . "_failed");
throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_FAILED_APPLYING_PATCH', $file, $e->getMessage()));
}
}
// Clear temp folder and store applied patch in database
Folder::delete($tempPath);
$lastInserted = $this->saveAppliedPatch($id, $files, $sha);
// Write or create patch chain for correct order of patching
$this->appendPatchChain($lastInserted, $id);
// Change the media version
$version = new Version;
$version->refreshMediaVersion();
return true;
}
/** /**
* Patches the code with the supplied pull request * Patches the code with the supplied pull request
* *
@ -142,40 +334,15 @@ class PullModel extends AbstractModel
* @return boolean * @return boolean
* *
* @since 2.0 * @since 2.0
*
* @throws \RuntimeException * @throws \RuntimeException
*/ */
public function apply($id) private function applyWithGitHub($id)
{ {
// Get the Github object // Get the Github object
$github = Helper::initializeGithub(); $github = Helper::initializeGithub();
try $pull = $this->retrieveGitHubData($github, $id);
{
$rateResponse = $github->getRateLimit();
$rate = json_decode($rateResponse->body);
}
catch (UnexpectedResponse $e)
{
throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_COULD_NOT_CONNECT_TO_GITHUB', $e->getMessage()), $e->getCode(), $e);
}
// If over the API limit, we can't build this list
if ($rate->resources->core->remaining == 0)
{
throw new \RuntimeException(
Text::sprintf('COM_PATCHTESTER_API_LIMIT_LIST', Factory::getDate($rate->resources->core->reset))
);
}
try
{
$pullResponse = $github->getPullRequest($this->getState()->get('github_user'), $this->getState()->get('github_repo'), $id);
$pull = json_decode($pullResponse->body);
}
catch (UnexpectedResponse $e)
{
throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_COULD_NOT_CONNECT_TO_GITHUB', $e->getMessage()), $e->getCode(), $e);
}
if (is_null($pull->head->repo)) if (is_null($pull->head->repo))
{ {
@ -199,6 +366,11 @@ class PullModel extends AbstractModel
$parsedFiles = $this->parseFileList($files); $parsedFiles = $this->parseFileList($files);
if (!count($parsedFiles))
{
return false;
}
foreach ($parsedFiles as $file) foreach ($parsedFiles as $file)
{ {
switch ($file->action) switch ($file->action)
@ -247,7 +419,11 @@ class PullModel extends AbstractModel
} }
catch (UnexpectedResponse $e) catch (UnexpectedResponse $e)
{ {
throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_COULD_NOT_CONNECT_TO_GITHUB', $e->getMessage()), $e->getCode(), $e); throw new \RuntimeException(
Text::sprintf('COM_PATCHTESTER_COULD_NOT_CONNECT_TO_GITHUB', $e->getMessage()),
$e->getCode(),
$e
);
} }
break; break;
@ -293,7 +469,9 @@ class PullModel extends AbstractModel
case 'renamed': case 'renamed':
if (!File::delete(Path::clean(JPATH_ROOT . '/' . $file->originalFile))) if (!File::delete(Path::clean(JPATH_ROOT . '/' . $file->originalFile)))
{ {
throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_ERROR_CANNOT_DELETE_FILE', JPATH_ROOT . '/' . $file->originalFile)); throw new \RuntimeException(
Text::sprintf('COM_PATCHTESTER_ERROR_CANNOT_DELETE_FILE', JPATH_ROOT . '/' . $file->originalFile)
);
} }
if (!File::write(Path::clean(JPATH_ROOT . '/' . $file->filename), $file->body)) if (!File::write(Path::clean(JPATH_ROOT . '/' . $file->filename), $file->body))
@ -308,25 +486,7 @@ class PullModel extends AbstractModel
unset($file->body); unset($file->body);
} }
$record = (object) array( $this->saveAppliedPatch($pull->number, $parsedFiles, $pull->head->sha);
'pull_id' => $pull->number,
'data' => json_encode($parsedFiles),
'patched_by' => Factory::getUser()->id,
'applied' => 1,
'applied_version' => JVERSION,
);
$db = $this->getDb();
$db->insertObject('#__patchtester_tests', $record);
// Insert the retrieved commit SHA into the pulls table for this item
$db->setQuery(
$db->getQuery(true)
->update('#__patchtester_pulls')
->set('sha = ' . $db->quote($pull->head->sha))
->where($db->quoteName('pull_id') . ' = ' . (int) $id)
)->execute();
// Change the media version // Change the media version
$version = new Version; $version = new Version;
@ -335,8 +495,215 @@ class PullModel extends AbstractModel
return true; return true;
} }
/**
* Patches the code with the supplied pull request
*
* @param GitHub $github github object
* @param integer $id Id of the pull request
*
* @return Response
*
* @since 2.0
*
* @throws \RuntimeException
*/
private function retrieveGitHubData($github, $id)
{
try
{
$rateResponse = $github->getRateLimit();
$rate = json_decode($rateResponse->body);
}
catch (UnexpectedResponse $e)
{
throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_COULD_NOT_CONNECT_TO_GITHUB', $e->getMessage()), $e->getCode(), $e);
}
// If over the API limit, we can't build this list
if ($rate->resources->core->remaining == 0)
{
throw new \RuntimeException(
Text::sprintf('COM_PATCHTESTER_API_LIMIT_LIST', Factory::getDate($rate->resources->core->reset))
);
}
try
{
$pullResponse = $github->getPullRequest($this->getState()->get('github_user'), $this->getState()->get('github_repo'), $id);
$pull = json_decode($pullResponse->body);
}
catch (UnexpectedResponse $e)
{
throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_COULD_NOT_CONNECT_TO_GITHUB', $e->getMessage()), $e->getCode(), $e);
}
return $pull;
}
/**
* Saves the applied patch into database
*
* @param integer $id ID of the applied pull request
* @param array $fileList List of files
* @param string $sha sha-key from pull request
*
* @return integer $id last inserted id
*
* @since 3.0
*/
private function saveAppliedPatch($id, $fileList, $sha = null)
{
$record = (object) array(
'pull_id' => $id,
'data' => json_encode($fileList),
'patched_by' => Factory::getUser()->id,
'applied' => 1,
'applied_version' => JVERSION,
);
$db = $this->getDb();
$db->insertObject('#__patchtester_tests', $record);
$insertId = $db->insertid();
if (!is_null($sha))
{
// Insert the retrieved commit SHA into the pulls table for this item
$db->setQuery(
$db->getQuery(true)
->update('#__patchtester_pulls')
->set('sha = ' . $db->quote($sha))
->where($db->quoteName('pull_id') . ' = ' . (int) $id)
)->execute();
}
return $insertId;
}
/** /**
* Reverts the specified pull request * Reverts the specified pull request
* However uses different methods for different repositories.
*
* @param integer $id ID of the pull request to revert
*
* @return boolean
*
* @since 3.0
* @throws \RuntimeException
*/
public function revert($id)
{
$params = ComponentHelper::getParams('com_patchtester');
// Decide based on repository settings whether patch will be applied through Github or CIServer
if (version_compare(JVERSION, "4", "ge") && ((bool) $params->get('ci_switch', 1) || $id === $this->getPatchChain($id)->insert_id))
{
return $this->revertWithCIServer($id);
}
else
{
return $this->revertWithGitHub($id);
}
}
/**
* Reverts the specified pull request with CIServer options
*
* @param integer $id ID of the pull request to revert
*
* @return boolean
*
* @since 3.0
* @throws \RuntimeException
*/
public function revertWithCIServer($id)
{
// Get the CIServer Registry
$ciSettings = Helper::initializeCISettings();
$testRecord = $this->getTestRecord($id);
// Get PatchChain as array, remove any EOL set by php
$patchChain = $this->getPatchChain(-1);
// Allow only reverts in order of the patch chain
if ($patchChain->insert_id != $id)
{
throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_NOT_IN_ORDER_OF_PATCHCHAIN', $patchChain->pull_id));
}
else
{
$this->removeLastChain($patchChain->insert_id);
}
// We don't want to restore files from an older version
if ($testRecord->applied_version != JVERSION)
{
return $this->removeTest($testRecord);
}
$files = json_decode($testRecord->data);
if (!$files)
{
throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_ERROR_READING_DATABASE_TABLE', __METHOD__, htmlentities($testRecord->data)));
}
$backupsPath = $ciSettings->get('folder.backups') . "/$testRecord->pull_id";
foreach ($files as $file)
{
try
{
$filePath = explode("\\", $file);
array_pop($filePath);
$filePath = implode("\\", $filePath);
// Delete file from root of it exists
if (file_Exists(JPATH_ROOT . "/$file"))
{
File::delete(JPATH_ROOT . "/$file");
// Move from backup, if it exists there
if (file_exists("$backupsPath/$file"))
{
File::move("$backupsPath/$file", JPATH_ROOT . "/$file");
}
// If folder is empty, remove it as well
if (count(glob(JPATH_ROOT . "/$filePath/*")) === 0)
{
Folder::delete(JPATH_ROOT . "/$filePath");
}
}
// Move from backup, if file exists there - got deleted by patch
elseif (file_exists("$backupsPath/$file"))
{
if (!file_exists(JPATH_ROOT . "/$filePath"))
{
Folder::create(JPATH_ROOT . "/$filePath");
}
File::move("$backupsPath/$file", JPATH_ROOT . "/$file");
}
}
catch (\RuntimeException $e)
{
throw new \RuntimeException(Text::sprintf('COM_PATCHTESTER_FAILED_REVERT_PATCH', $file, $e->getMessage()));
}
}
Folder::delete($backupsPath);
// Change the media version
$version = new Version;
$version->refreshMediaVersion();
return $this->removeTest($testRecord);
}
/**
* Reverts the specified pull request with Github Requests
* *
* @param integer $id ID of the pull request to revert * @param integer $id ID of the pull request to revert
* *
@ -345,16 +712,9 @@ class PullModel extends AbstractModel
* @since 2.0 * @since 2.0
* @throws \RuntimeException * @throws \RuntimeException
*/ */
public function revert($id) public function revertWithGitHub($id)
{ {
$db = $this->getDb(); $testRecord = $this->getTestRecord($id);
$testRecord = $db->setQuery(
$db->getQuery(true)
->select('*')
->from('#__patchtester_tests')
->where('id = ' . (int) $id)
)->loadObject();
// We don't want to restore files from an older version // We don't want to restore files from an older version
if ($testRecord->applied_version != JVERSION) if ($testRecord->applied_version != JVERSION)
@ -469,7 +829,7 @@ class PullModel extends AbstractModel
$db->getQuery(true) $db->getQuery(true)
->update('#__patchtester_pulls') ->update('#__patchtester_pulls')
->set('sha = ' . $db->quote('')) ->set('sha = ' . $db->quote(''))
->where($db->quoteName('pull_id') . ' = ' . (int) $testRecord->pull_id) ->where($db->quoteName('id') . ' = ' . (int) $testRecord->id)
)->execute(); )->execute();
// And delete the record from the tests table // And delete the record from the tests table
@ -481,4 +841,152 @@ class PullModel extends AbstractModel
return true; return true;
} }
/**
* Retrieves test data from database by specific id
*
* @param integer $id ID of the record
*
* @return stdClass $testRecord The record looking for
*
* @since 3.0.0
*/
private function getTestRecord($id)
{
$db = $this->getDb();
return $db->setQuery(
$db->getQuery(true)
->select('*')
->from('#__patchtester_tests')
->where('id = ' . (int) $id)
)->loadObject();
}
/**
* Retrieves a list of patches in chain
*
* @return mixed
*
* @since 3.0
*/
private function getPatchChains()
{
$db = $this->getDb();
$db->setQuery(
$db->getQuery(true)
->select('*')
->from($db->quoteName('#__patchtester_chain'))
->order('id DESC')
);
return $db->loadObjectList('pull_id');
}
/**
* Returns a chain by specific value, returns the last
* element on $id = -1 and the first on $id = null
*
* @param integer $id specific id of a pull
*
* @return stdClass $chain last chain of the table
*
* @since 3.0.0
*/
private function getPatchChain($id = null)
{
$db = $this->getDb();
$query = $db->getQuery(true)
->select('*')
->from('#__patchtester_chain');
if (!is_null($id) && $id !== -1)
{
$query = $query->where('insert_id =' . (int) $id);
}
if ($id === -1)
{
$query = $query->order('id DESC');
}
if (is_null($id))
{
$query = $query->order('id ASC');
}
return $db->setQuery($query, 0, 1)->loadObject();
}
/**
* Returns a two dimensional array with applied patches
* by the github or ci procedure
*
* @return array two-dimensional array with github patches
* and ci patches
*
* @since 3.0.0
*/
public function getPatchesDividedInProcs()
{
$db = $this->getDb();
$appliedByGit = $db->setQuery(
$db->getQuery(true)
->select('tests.id, tests.pull_id')
->from('#__patchtester_tests tests')
->leftJoin('#__patchtester_chain chain', 'tests.id = chain.insert_id')
->where('chain.insert_id IS NULL')
)->loadObjectList('pull_id');
$appliedByCI = $this->getPatchChains();
return array('git' => $appliedByGit, 'ci' => $appliedByCI);
}
/**
* Adds a value to the patch chain in the database
*
* @param integer $insertId ID of the patch in the database
* @param integer $pullId ID of the pull request
*
* @return integer $insertId last inserted element
*
* @since 3.0.0
*/
private function appendPatchChain($insertId, $pullId)
{
$record = (object) array(
'insert_id' => $insertId,
'pull_id' => $pullId,
);
$db = $this->getDb();
$db->insertObject('#__patchtester_chain', $record);
return $db->insertid();
}
/**
* Removes the last value of the chain
*
* @param integer $insertId ID of the patch in the database
*
* @return void
*
* @since 3.0.0
*/
private function removeLastChain($insertId)
{
$db = $this->getDb();
$db->setQuery(
$db->getQuery(true)
->delete('#__patchtester_chain')
->where('insert_id = ' . (int) $insertId)
)->execute();
}
} }

View File

@ -95,7 +95,7 @@ class PullsModel extends AbstractModel
} }
// Load the list items and add the items to the internal cache. // Load the list items and add the items to the internal cache.
$this->cache[$store] = $this->_getList($this->_getListQuery(), $this->getStart(), $this->getState()->get('list.limit')); $this->cache[$store] = $this->getList($this->getListQueryCache(), $this->getStart(), $this->getState()->get('list.limit'));
return $this->cache[$store]; return $this->cache[$store];
} }
@ -293,7 +293,7 @@ class PullsModel extends AbstractModel
} }
// Load the total and add the total to the internal cache. // Load the total and add the total to the internal cache.
$this->cache[$store] = (int) $this->_getListCount($this->_getListQuery()); $this->cache[$store] = (int) $this->getListCount($this->getListQueryCache());
return $this->cache[$store]; return $this->cache[$store];
} }
@ -452,7 +452,7 @@ class PullsModel extends AbstractModel
* @since 2.0 * @since 2.0
* @throws RuntimeException * @throws RuntimeException
*/ */
protected function _getList($query, $limitstart = 0, $limit = 0) protected function getList($query, $limitstart = 0, $limit = 0)
{ {
return $this->getDb()->setQuery($query, $limitstart, $limit)->loadObjectList(); return $this->getDb()->setQuery($query, $limitstart, $limit)->loadObjectList();
} }
@ -466,7 +466,7 @@ class PullsModel extends AbstractModel
* *
* @since 2.0 * @since 2.0
*/ */
protected function _getListCount($query) protected function getListCount($query)
{ {
// Use fast COUNT(*) on JDatabaseQuery objects if there no GROUP BY or HAVING clause: // Use fast COUNT(*) on JDatabaseQuery objects if there no GROUP BY or HAVING clause:
if ($query instanceof \JDatabaseQuery && $query->type == 'select' && $query->group === null && $query->having === null) if ($query instanceof \JDatabaseQuery && $query->type == 'select' && $query->group === null && $query->having === null)
@ -494,7 +494,7 @@ class PullsModel extends AbstractModel
* *
* @since 2.0 * @since 2.0
*/ */
protected function _getListQuery() protected function getListQueryCache()
{ {
// Capture the last store id used. // Capture the last store id used.
static $lastStoreId; static $lastStoreId;

View File

@ -21,8 +21,8 @@ HTMLHelper::_('script', 'com_patchtester/fetcher.js', array('version' => 'auto',
<div id="patchtester-container"> <div id="patchtester-container">
<h1 id="patchtester-progress-header"><?php echo Text::_('COM_PATCHTESTER_FETCH_INITIALIZING'); ?></h1> <h1 id="patchtester-progress-header"><?php echo Text::_('COM_PATCHTESTER_FETCH_INITIALIZING'); ?></h1>
<p id="patchtester-progress-message"><?php echo Text::_('COM_PATCHTESTER_FETCH_INITIALIZING_DESCRIPTION'); ?></p> <p id="patchtester-progress-message"><?php echo Text::_('COM_PATCHTESTER_FETCH_INITIALIZING_DESCRIPTION'); ?></p>
<div id="progress" class="progress progress-striped active"> <div id="progress" class="progress">
<div id="progress-bar" class="bar bar-success" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div> <div id="progress-bar" class="progress-bar progress-bar-striped progress-bar-animated bg-success" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" role="progressbar"></div>
</div> </div>
<input id="patchtester-token" type="hidden" name="<?php echo Factory::getSession()->getFormToken(); ?>" value="1" /> <input id="patchtester-token" type="hidden" name="<?php echo Factory::getSession()->getFormToken(); ?>" value="1" />
</div> </div>

View File

@ -8,7 +8,6 @@
namespace PatchTester\View\Pulls; namespace PatchTester\View\Pulls;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text; use Joomla\CMS\Language\Text;
use Joomla\CMS\Pagination\Pagination; use Joomla\CMS\Pagination\Pagination;
use Joomla\CMS\Toolbar\Toolbar; use Joomla\CMS\Toolbar\Toolbar;
@ -114,12 +113,6 @@ class PullsHtmlView extends DefaultHtmlView
// Make text strings available in the JavaScript API // Make text strings available in the JavaScript API
Text::script('COM_PATCHTESTER_CONFIRM_RESET'); Text::script('COM_PATCHTESTER_CONFIRM_RESET');
// Set a warning on 4.0 branch
if (version_compare(JVERSION, '4.0', 'ge'))
{
Factory::getApplication()->enqueueMessage(Text::_('COM_PATCHTESTER_40_WARNING'), 'warning');
}
return parent::render(); return parent::render();
} }
@ -148,7 +141,7 @@ class PullsHtmlView extends DefaultHtmlView
0, 0,
0, 0,
'window.parent.location.reload()', 'window.parent.location.reload()',
'COM_PATCHTESTER_HEADING_FETCH_DATA' Text::_('COM_PATCHTESTER_HEADING_FETCH_DATA')
); );
// Add a reset button. // Add a reset button.

View File

@ -6,102 +6,140 @@
* @license GNU General Public License version 2 or later * @license GNU General Public License version 2 or later
*/ */
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text; use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route; use Joomla\CMS\Router\Route;
/** @var \PatchTester\View\Pulls\PullsHtmlView $this */ /** @var \PatchTester\View\Pulls\PullsHtmlView $this */
$searchToolsOptions = array(
'filtersHidden' => true,
'filterButton' => true,
'defaultLimit' => Factory::getApplication()->get('list_limit', 20),
'searchFieldSelector' => '#filter_search',
'selectorFieldName' => 'client_id',
'showSelector' => false,
'orderFieldSelector' => '#list_fullordering',
'showNoResults' => false,
'noResultsText' => '',
'formSelector' => '#adminForm',
);
HTMLHelper::_('behavior.core'); HTMLHelper::_('behavior.core');
HTMLHelper::_('bootstrap.tooltip'); HTMLHelper::_('searchtools.form', '#adminForm', $searchToolsOptions);
HTMLHelper::_('formbehavior.chosen', 'select');
HTMLHelper::_('stylesheet', 'com_patchtester/octicons.css', array('version' => '3.5.0', 'relative' => true)); HTMLHelper::_('stylesheet', 'com_patchtester/octicons.css', array('version' => '3.5.0', 'relative' => true));
HTMLHelper::_('script', 'com_patchtester/patchtester.js', array('version' => 'auto', 'relative' => true)); HTMLHelper::_('script', 'com_patchtester/patchtester.js', array('version' => 'auto', 'relative' => true));
$listOrder = $this->escape($this->state->get('list.fullordering', 'a.pull_id DESC')); $listOrder = $this->escape($this->state->get('list.fullordering', 'a.pull_id DESC'));
$listLimit = (int) ($this->state->get('list.limit'));
$filterApplied = $this->escape($this->state->get('filter.applied')); $filterApplied = $this->escape($this->state->get('filter.applied'));
$filterBranch = $this->escape($this->state->get('filter.branch')); $filterBranch = $this->escape($this->state->get('filter.branch'));
$filterRtc = $this->escape($this->state->get('filter.rtc')); $filterRtc = $this->escape($this->state->get('filter.rtc'));
?> ?>
<form action="<?php echo Route::_('index.php?option=com_patchtester&view=pulls'); ?>" method="post" name="adminForm" id="adminForm" data-order="<?php echo $listOrder; ?>"> <form action="<?php echo Route::_('index.php?option=com_patchtester&view=pulls'); ?>" method="post" name="adminForm" id="adminForm">
<div id="j-main-container"> <div class="row">
<div id="filter-bar" class="btn-toolbar"> <div class="col-md-12">
<div class="filter-search btn-group pull-left"> <div id="j-main-container" class="j-main-container">
<label for="filter_search" class="element-invisible"><?php echo Text::_('COM_PATCHTESTER_FILTER_SEARCH_DESCRIPTION'); ?></label> <div class="js-stools" role="search">
<input type="text" name="filter_search" placeholder="<?php echo Text::_('COM_PATCHTESTER_FILTER_SEARCH_DESCRIPTION'); ?>" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo Text::_('COM_PATCHTESTER_FILTER_SEARCH_DESCRIPTION'); ?>" /> <div class="js-stools-container-bar">
<div class="btn-toolbar">
<div class="btn-group mr-2">
<div class="input-group">
<label for="filter_search" class="sr-only">
<?php echo Text::_('COM_PATCHTESTER_FILTER_SEARCH_DESCRIPTION'); ?>
</label>
<input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" class="form-control" placeholder="<?php echo Text::_('JSEARCH_FILTER'); ?>">
<div role="tooltip" id="filter[search]-desc">
<?php echo $this->escape(Text::_('COM_PATCHTESTER_FILTER_SEARCH_DESCRIPTION')); ?>
</div> </div>
<div class="btn-group pull-left hidden-phone"> <span class="input-group-append">
<button class="btn tip hasTooltip" type="submit" title="<?php echo Text::_('JSEARCH_FILTER_SUBMIT'); ?>"><i class="icon-search"></i></button> <button type="submit" class="btn btn-primary" aria-label="<?php echo Text::_('JSEARCH_FILTER_SUBMIT'); ?>">
<button class="btn tip hasTooltip" type="button" onclick="document.getElementById('filter_search').value='';this.form.submit();" title="<?php echo Text::_('JSEARCH_FILTER_CLEAR'); ?>"><i class="icon-remove"></i></button> <span class="fa fa-search" aria-hidden="true"></span>
</button>
</span>
</div> </div>
<div class="btn-group pull-right hidden-phone">
<label for="limit" class="element-invisible"><?php echo Text::_('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC'); ?></label>
<?php echo $this->pagination->getLimitBox(); ?>
</div> </div>
<div class="btn-group pull-right"> <div class="btn-group">
<label for="list_fullordering" class="element-invisible"><?php echo Text::_('JGLOBAL_SORT_BY'); ?></label> <button type="button" class="btn btn-primary hasTooltip js-stools-btn-filter">
<select name="list_fullordering" id="list_fullordering" class="input-medium" onchange="this.form.submit();"> <?php echo Text::_('JFILTER_OPTIONS'); ?>
<span class="fa fa-angle-down" aria-hidden="true"></span>
</button>
<button type="button" class="btn btn-primary js-stools-btn-clear mr-2">
<?php echo Text::_('JSEARCH_FILTER_CLEAR'); ?>
</button>
</div>
<div class="ordering-select">
<div class="js-stools-field-list">
<select name="list_fullordering" id="list_fullordering" class="custom-select" onchange="this.form.submit()">
<option value=""><?php echo Text::_('JGLOBAL_SORT_BY'); ?></option> <option value=""><?php echo Text::_('JGLOBAL_SORT_BY'); ?></option>
<?php echo HTMLHelper::_('select.options', $this->getSortFields(), 'value', 'text', $listOrder); ?> <?php echo HTMLHelper::_('select.options', $this->getSortFields(), 'value', 'text', $listOrder); ?>
</select> </select>
</div> </div>
<div class="btn-group pull-right"> <div class="js-stools-field-list">
<label for="filter_applied" class="element-invisible"><?php echo Text::_('JSEARCH_TOOLS_DESC'); ?></label> <span class="sr-only">
<select name="filter_applied" class="input-medium" onchange="this.form.submit();"> <label id="list_limit-lbl" for="list_limit">Select number of items per page.</label>
</span>
<select name="list_limit" id="list_limit" class="custom-select" onchange="this.form.submit()">
<?php echo HTMLHelper::_('select.options', $this->getLimitOptions(), 'value', 'text', $listLimit); ?>
</select>
</div>
</div>
</div>
</div>
<!-- Filters div -->
<div class="js-stools-container-filters clearfix">
<div class="js-stools-field-filter">
<select name="filter_applied" class="custom-select" onchange="this.form.submit();">
<option value=""><?php echo Text::_('COM_PATCHTESTER_FILTER_APPLIED_PATCHES'); ?></option> <option value=""><?php echo Text::_('COM_PATCHTESTER_FILTER_APPLIED_PATCHES'); ?></option>
<option value="yes"<?php if ($filterApplied == 'yes') echo ' selected="selected"'; ?>><?php echo Text::_('COM_PATCHTESTER_APPLIED'); ?></option> <option value="yes"<?php echo $filterApplied == 'yes' ? ' selected="selected"' : ''; ?>><?php echo Text::_('COM_PATCHTESTER_APPLIED'); ?></option>
<option value="no"<?php if ($filterApplied == 'no') echo ' selected="selected"'; ?>><?php echo Text::_('COM_PATCHTESTER_NOT_APPLIED'); ?></option> <option value="no"<?php echo $filterApplied == 'no' ? ' selected="selected"' : ''; ?>><?php echo Text::_('COM_PATCHTESTER_NOT_APPLIED'); ?></option>
</select> </select>
</div> </div>
<div class="btn-group pull-right"> <div class="js-stools-field-filter">
<label for="filter_rtc" class="element-invisible"><?php echo Text::_('JSEARCH_TOOLS_DESC'); ?></label> <select name="filter_rtc" class="custom-select" onchange="this.form.submit();">
<select name="filter_rtc" class="input-medium" onchange="this.form.submit();">
<option value=""><?php echo Text::_('COM_PATCHTESTER_FILTER_RTC_PATCHES'); ?></option> <option value=""><?php echo Text::_('COM_PATCHTESTER_FILTER_RTC_PATCHES'); ?></option>
<option value="yes"<?php if ($filterRtc == 'yes') echo ' selected="selected"'; ?>><?php echo Text::_('COM_PATCHTESTER_RTC'); ?></option> <option value="yes"<?php echo $filterRtc == 'yes' ? ' selected="selected"' : ''; ?>><?php echo Text::_('COM_PATCHTESTER_RTC'); ?></option>
<option value="no"<?php if ($filterRtc == 'no') echo ' selected="selected"'; ?>><?php echo Text::_('COM_PATCHTESTER_NOT_RTC'); ?></option> <option value="no"<?php echo $filterRtc == 'no' ? ' selected="selected"' : ''; ?>><?php echo Text::_('COM_PATCHTESTER_NOT_RTC'); ?></option>
</select> </select>
</div> </div>
<div class="btn-group pull-right"> <div class="js-stools-field-filter">
<label for="filter_branch" class="element-invisible"><?php echo Text::_('JSEARCH_TOOLS_DESC'); ?></label> <select name="filter_branch" class="custom-select" onchange="this.form.submit();">
<select name="filter_branch" class="input-medium" onchange="this.form.submit();">
<option value=""><?php echo Text::_('COM_PATCHTESTER_FILTER_BRANCH'); ?></option> <option value=""><?php echo Text::_('COM_PATCHTESTER_FILTER_BRANCH'); ?></option>
<?php echo HTMLHelper::_('select.options', $this->branches, 'text', 'text', $filterBranch, false); ?> <?php echo HTMLHelper::_('select.options', $this->branches, 'text', 'text', $filterBranch, false); ?>
</select> </select>
</div> </div>
</div> </div>
</div>
<div id="j-main-container" class="j-main-container">
<?php if (empty($this->items)) : ?> <?php if (empty($this->items)) : ?>
<div class="alert alert-no-items"> <div class="alert alert-info">
<span class="fa fa-info-circle" aria-hidden="true"></span><span class="sr-only"><?php echo Text::_('INFO'); ?></span>
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?> <?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
</div> </div>
<?php else : ?> <?php else : ?>
<table class="table table-striped"> <table class="table">
<caption id="captionTable" class="sr-only">
<?php echo Text::_('COM_PATCHTESTER_PULLS_TABLE_CAPTION'); ?>, <?php echo Text::_('JGLOBAL_SORTED_BY'); ?>
</caption>
<thead> <thead>
<tr> <tr>
<th width="5%" class="nowrap center"> <th scope="col" style="width:5%" class="text-center">
<?php echo Text::_('COM_PATCHTESTER_PULL_ID'); ?> <?php echo Text::_('COM_PATCHTESTER_PULL_ID'); ?>
</th> </th>
<th class="nowrap"> <th scope="col" style="min-width:100px">
<?php echo Text::_('JGLOBAL_TITLE'); ?> <?php echo Text::_('JGLOBAL_TITLE'); ?>
</th> </th>
<th width="8%" class="nowrap center hidden-phone"> <th scope="col" style="width:8%" class="d-none d-md-table-cell text-center">
<?php echo Text::_('COM_PATCHTESTER_BRANCH'); ?> <?php echo Text::_('COM_PATCHTESTER_BRANCH'); ?>
</th> </th>
<th width="8%" class="nowrap center hidden-phone"> <th scope="col" style="width:8%" class="d-none d-md-table-cell text-center">
<?php echo Text::_('COM_PATCHTESTER_READY_TO_COMMIT'); ?> <?php echo Text::_('COM_PATCHTESTER_READY_TO_COMMIT'); ?>
</th> </th>
<th width="8%" class="nowrap center"> <th scope="col" style="width:10%" class="text-center">
<?php echo Text::_('COM_PATCHTESTER_GITHUB'); ?>
</th>
<?php if ($this->trackerAlias !== false) : ?>
<th width="8%" class="nowrap center">
<?php echo Text::_('COM_PATCHTESTER_JISSUES'); ?>
</th>
<?php endif; ?>
<th width="10%" class="nowrap center">
<?php echo Text::_('JSTATUS'); ?> <?php echo Text::_('JSTATUS'); ?>
</th> </th>
<th width="15%" class="nowrap center"> <th scope="col" style="width:15%" class="text-center">
<?php echo Text::_('COM_PATCHTESTER_TEST_THIS_PATCH'); ?> <?php echo Text::_('COM_PATCHTESTER_TEST_THIS_PATCH'); ?>
</th> </th>
</tr> </tr>
@ -119,4 +157,7 @@ $filterRtc = $this->escape($this->state->get('filter.rtc'));
<input type="hidden" name="pull_id" id="pull_id" value="" /> <input type="hidden" name="pull_id" id="pull_id" value="" />
<?php echo HTMLHelper::_('form.token'); ?> <?php echo HTMLHelper::_('form.token'); ?>
</div> </div>
</div>
</div>
</div>
</form> </form>

View File

@ -14,59 +14,62 @@ foreach ($this->items as $i => $item) :
$status = ''; $status = '';
if ($item->applied) : if ($item->applied) :
$status = ' class="success"'; $status = ' class="table-active"';
endif; endif;
?> ?>
<tr<?php echo $status; ?>> <tr<?php echo $status; ?>>
<td class="center"> <th scope="row" class="text-center">
<?php echo $item->pull_id; ?> <?php echo $item->pull_id; ?>
</td> </th>
<td> <td>
<span class="hasTooltip" title="<strong>Info</strong><br/><?php echo $this->escape($item->description); ?>"><?php echo $this->escape($item->title); ?></span> <span><?php echo $this->escape($item->title); ?></span>
<div role="tooltip" id="tip<?php echo $i; ?>">
<?php echo $this->escape($item->description); ?>
</div>
<div class="row">
<div class="col-md-auto">
<a class="badge badge-info" href="<?php echo $item->pull_url; ?>" target="_blank">
<?php echo Text::_('COM_PATCHTESTER_VIEW_ON_GITHUB'); ?>
</a>
</div>
<div class="col-md-auto">
<a class="badge badge-info"
href="https://issues.joomla.org/tracker/<?php echo $this->trackerAlias; ?>/<?php echo $item->pull_id; ?>"
target="_blank">
<?php echo Text::_('COM_PATCHTESTER_VIEW_ON_JOOMLA_ISSUE_TRACKER'); ?>
</a>
</div>
<?php if ($item->applied) : ?> <?php if ($item->applied) : ?>
<div class="small"> <div class="col-md-auto">
<span class="label label-info"><?php echo Text::sprintf('COM_PATCHTESTER_APPLIED_COMMIT_SHA', substr($item->sha, 0, 10)); ?></span> <span class="badge badge-info"><?php echo Text::sprintf('COM_PATCHTESTER_APPLIED_COMMIT_SHA', substr($item->sha, 0, 10)); ?></span>
</div> </div>
<?php endif; ?> <?php endif; ?>
</div>
</td> </td>
<td class="center hidden-phone"> <td class="d-none d-md-table-cell text-center">
<?php echo $this->escape($item->branch); ?> <?php echo $this->escape($item->branch); ?>
</td> </td>
<td class="center hidden-phone"> <td class="d-none d-md-table-cell text-center">
<?php if ($item->is_rtc) : ?> <?php if ($item->is_rtc) : ?>
<span class="label label-success"><?php echo Text::_('JYES'); ?></span> <span class="badge badge-success"><?php echo Text::_('JYES'); ?></span>
<?php else : ?> <?php else : ?>
<span class="label label-primary"><?php echo Text::_('JNO'); ?></span> <span class="badge badge-secondary"><?php echo Text::_('JNO'); ?></span>
<?php endif; ?> <?php endif; ?>
</td> </td>
<td class="center"> <td class="text-center">
<a class="btn btn-small btn-info" href="<?php echo $item->pull_url; ?>" target="_blank">
<span class="octicon octicon-mark-github"></span> <?php echo Text::_('COM_PATCHTESTER_GITHUB'); ?>
</a>
</td>
<?php if ($this->trackerAlias !== false) : ?>
<td class="center">
<a class="btn btn-small btn-warning" href="https://issues.joomla.org/tracker/<?php echo $this->trackerAlias; ?>/<?php echo $item->pull_id; ?>" target="_blank">
<i class="icon-joomla"></i> <?php echo Text::_('COM_PATCHTESTER_JISSUE'); ?>
</a>
</td>
<?php endif; ?>
<td class="center">
<?php if ($item->applied) : ?> <?php if ($item->applied) : ?>
<div> <span class="badge badge-success"><?php echo Text::_('COM_PATCHTESTER_APPLIED'); ?></span>
<span class="label label-success"><?php echo Text::_('COM_PATCHTESTER_APPLIED'); ?></span>
</div>
<?php else : ?> <?php else : ?>
<span class="label"> <span class="badge badge-secondary"><?php echo Text::_('COM_PATCHTESTER_NOT_APPLIED'); ?></span>
<?php echo Text::_('COM_PATCHTESTER_NOT_APPLIED'); ?>
</span>
<?php endif; ?> <?php endif; ?>
</td> </td>
<td class="center"> <td class="text-center">
<?php if ($item->applied) : ?> <?php if ($item->applied) : ?>
<a class="btn btn-small btn-success" href="javascript:PatchTester.submitpatch('revert', '<?php echo (int) $item->applied; ?>');"><?php echo Text::_('COM_PATCHTESTER_REVERT_PATCH'); ?></a><br /> <button type="button" class="btn btn-sm btn-success submitPatch"
data-task="revert-<?php echo (int) $item->applied; ?>"><?php echo Text::_('COM_PATCHTESTER_REVERT_PATCH'); ?></button>
<?php else : ?> <?php else : ?>
<a class="btn btn-small btn-primary" href="javascript:PatchTester.submitpatch('apply', '<?php echo (int) $item->pull_id; ?>');"><?php echo Text::_('COM_PATCHTESTER_APPLY_PATCH'); ?></a> <button type="button" class="btn btn-sm btn-primary submitPatch"
data-task="apply-<?php echo (int) $item->pull_id; ?>"><?php echo Text::_('COM_PATCHTESTER_APPLY_PATCH'); ?></button>
<?php endif; ?> <?php endif; ?>
</td> </td>
</tr> </tr>

View File

@ -57,7 +57,6 @@
description="COM_PATCHTESTER_FIELD_GH_AUTH_DESC" description="COM_PATCHTESTER_FIELD_GH_AUTH_DESC"
default="" default=""
onchange="jQuery('#jform_gh_user, #jform_gh_password, #jform_gh_token').val('');" onchange="jQuery('#jform_gh_user, #jform_gh_password, #jform_gh_token').val('');"
> >
<option value="">JNONE</option> <option value="">JNONE</option>
<option value="credentials">COM_PATCHTESTER_FIELD_GH_AUTH_OPTION_CREDENTIALS</option> <option value="credentials">COM_PATCHTESTER_FIELD_GH_AUTH_OPTION_CREDENTIALS</option>
@ -95,6 +94,34 @@
</fieldset> </fieldset>
<fieldset
name="ci_settings"
label="COM_PATCHTESTER_FIELDSET_CI_SETTINGS"
description="COM_PATCHTESTER_FIELDSET_CI_SETTINGS_DESC"
>
<field
name="ci_server"
type="text"
label="COM_PATCHTESTER_FIELD_CI_SERVER_NAME"
description="COM_PATCHTESTER_FIELD_CI_SERVER_NAME_DESC"
autocomplete="off"
default="https://ci.joomla.org:444"
/>
<field
name="ci_switch"
type="list"
label="COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH"
description="COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH_DESC"
default="1"
>
<option value="1">COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH_OPTION_ON</option>
<option value="0">COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH_OPTION_OFF</option>
</field>
</fieldset>
<fieldset <fieldset
name="permissions" name="permissions"
label="JCONFIG_PERMISSIONS_LABEL" label="JCONFIG_PERMISSIONS_LABEL"

View File

@ -19,3 +19,10 @@ CREATE TABLE IF NOT EXISTS `#__patchtester_tests` (
`applied_version` varchar(25) NOT NULL, `applied_version` varchar(25) NOT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `#__patchtester_chain` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`insert_id` int(11) NOT NULL,
`pull_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

View File

@ -1,2 +1,3 @@
DROP TABLE IF EXISTS `#__patchtester_pulls`; DROP TABLE IF EXISTS `#__patchtester_pulls`;
DROP TABLE IF EXISTS `#__patchtester_tests`; DROP TABLE IF EXISTS `#__patchtester_tests`;
DROP TABLE IF EXISTS `#__patchtester_chain`;

View File

@ -19,3 +19,10 @@ CREATE TABLE IF NOT EXISTS "#__patchtester_tests" (
"applied_version" character varying(25) NOT NULL, "applied_version" character varying(25) NOT NULL,
PRIMARY KEY ("id") PRIMARY KEY ("id")
); );
CREATE TABLE IF NOT EXISTS "#__patchtester_chain" (
"id" serial NOT NULL,
"insert_id" bigint NOT NULL,
"pull_id" bigint NOT NULL,
PRIMARY KEY ("id")
);

View File

@ -1,2 +1,3 @@
DROP TABLE IF EXISTS "#__patchtester_pulls"; DROP TABLE IF EXISTS "#__patchtester_pulls";
DROP TABLE IF EXISTS "#__patchtester_tests"; DROP TABLE IF EXISTS "#__patchtester_tests";
DROP TABLE IF EXISTS "#__patchtester_chain";

View File

@ -25,3 +25,13 @@ CREATE TABLE [#__patchtester_tests](
[id] ASC [id] ASC
) WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ) WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF)
); );
CREATE TABLE [#__patchtester_chain] (
[id] [bigint] IDENTITY(1,1) NOT NULL,
[insert_id] [bigint] NOT NULL,
[pull_id] [bigint] NOT NULL,
CONSTRAINT [PK_#__patchtester_chain] PRIMARY KEY CLUSTERED
(
[id] ASC
) WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF)
);

View File

@ -1,2 +1,3 @@
DROP TABLE [#__patchtester_pulls]; DROP TABLE [#__patchtester_pulls];
DROP TABLE [#__patchtester_tests]; DROP TABLE [#__patchtester_tests];
DROP TABLE [#__patchtester_chain];

View File

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS `#__patchtester_chain` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`insert_id` int(11) NOT NULL,
`pull_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

View File

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS "#__patchtester_chain" (
"id" serial NOT NULL,
"insert_id" bigint NOT NULL,
"pull_id" bigint NOT NULL,
PRIMARY KEY ("id")
);

View File

@ -0,0 +1,9 @@
CREATE TABLE [#__patchtester_chain] (
[id] [bigint] IDENTITY(1,1) NOT NULL,
[insert_id] [bigint] NOT NULL,
[pull_id] [bigint] NOT NULL,
CONSTRAINT [PK_#__patchtester_chain] PRIMARY KEY CLUSTERED
(
[id] ASC
) WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF)
);

View File

@ -28,6 +28,8 @@ COM_PATCHTESTER_ERROR_TRUNCATING_PULLS_TABLE="Fehler beim Leeren der Pulls-Tabel
COM_PATCHTESTER_ERROR_TRUNCATING_TESTS_TABLE="Fehler beim Leeren der Tests-Tabelle %s" COM_PATCHTESTER_ERROR_TRUNCATING_TESTS_TABLE="Fehler beim Leeren der Tests-Tabelle %s"
COM_PATCHTESTER_ERROR_UNSUPPORTED_ENCODING="Die Patch-Dateien sind in mit einem nicht unterstützten Format codiert." COM_PATCHTESTER_ERROR_UNSUPPORTED_ENCODING="Die Patch-Dateien sind in mit einem nicht unterstützten Format codiert."
COM_PATCHTESTER_ERROR_VIEW_NOT_FOUND="Ansicht nicht gefunden [Name, Format]: %1$s, %2$s" COM_PATCHTESTER_ERROR_VIEW_NOT_FOUND="Ansicht nicht gefunden [Name, Format]: %1$s, %2$s"
COM_PATCHTESTER_FAILED_APPLYING_PATCH="Der Patch konnte nicht angewendet werden aufgrund eines Problems mit %1$s. %2$s"
COM_PATCHTESTER_FAILED_REVERT_PATCH="Der Patch konnte nicht zurückgesetzt werden aufgrund eines Problems mit %1$s. %2$s"
COM_PATCHTESTER_FETCH_AN_ERROR_HAS_OCCURRED="Fehler beim Abrufen der Daten von GitHub." COM_PATCHTESTER_FETCH_AN_ERROR_HAS_OCCURRED="Fehler beim Abrufen der Daten von GitHub."
COM_PATCHTESTER_FETCH_COMPLETE_CLOSE_WINDOW="Alle Daten wurden abgerufen. Schließen Sie bitte dieses Popup um die Seite neu zu laden." COM_PATCHTESTER_FETCH_COMPLETE_CLOSE_WINDOW="Alle Daten wurden abgerufen. Schließen Sie bitte dieses Popup um die Seite neu zu laden."
COM_PATCHTESTER_FETCH_INITIALIZING="Vorbereitungen für das Abrufen der Daten von GitHub" COM_PATCHTESTER_FETCH_INITIALIZING="Vorbereitungen für das Abrufen der Daten von GitHub"
@ -57,10 +59,18 @@ COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_PATCHTESTER="Joomla! Patch-Tester Kompon
COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_INSTALL_FROM_WEB="Joomla! Webkataloginstallations-Plugin" COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_INSTALL_FROM_WEB="Joomla! Webkataloginstallations-Plugin"
COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_WEBLINKS="Joomla! Weblinks-Paket" COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_WEBLINKS="Joomla! Weblinks-Paket"
COM_PATCHTESTER_FIELD_REPOSITORY_CUSTOM="Benutzerdefiniert" COM_PATCHTESTER_FIELD_REPOSITORY_CUSTOM="Benutzerdefiniert"
COM_PATCHTESTER_FIELD_CI_SERVER_NAME="CI Server Adresse"
COM_PATCHTESTER_FIELD_CI_SERVER_NAME_DESC="Server Adresse für das Herunterladen kompilierter Patches."
COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH="Switch CI Integration"
COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH_DESC="Schaltet die CI Integration an oder aus."
COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH_OPTION_ON="An"
COM_PATCHTESTER_FIELD_CI_SERVER_SWITCH_OPTION_OFF="Aus"
COM_PATCHTESTER_FIELDSET_REPOSITORIES_DESC="Konfigurationswerte für GitHub Repository" COM_PATCHTESTER_FIELDSET_REPOSITORIES_DESC="Konfigurationswerte für GitHub Repository"
COM_PATCHTESTER_FIELDSET_REPOSITORIES_LABEL="GitHub Repository" COM_PATCHTESTER_FIELDSET_REPOSITORIES_LABEL="GitHub Repository"
COM_PATCHTESTER_FIELDSET_AUTHENTICATION_DESC="Konfigurationswerte für GitHub Authentifizierung" COM_PATCHTESTER_FIELDSET_AUTHENTICATION_DESC="Konfigurationswerte für GitHub Authentifizierung"
COM_PATCHTESTER_FIELDSET_AUTHENTICATION_LABEL="GitHub Authentifizierung" COM_PATCHTESTER_FIELDSET_AUTHENTICATION_LABEL="GitHub Authentifizierung"
COM_PATCHTESTER_FIELDSET_CI_SETTINGS="CI Server Einstellungen"
COM_PATCHTESTER_FIELDSET_CI_SETTINGS_DESC="Konfigurationswerte für CI Server Patching"
COM_PATCHTESTER_FILE_DELETED_DOES_NOT_EXIST_S="Die zu löschende Datei existiert nicht: %s" COM_PATCHTESTER_FILE_DELETED_DOES_NOT_EXIST_S="Die zu löschende Datei existiert nicht: %s"
COM_PATCHTESTER_FILE_MODIFIED_DOES_NOT_EXIST_S="Die zu ändernde Datei existiert nicht: %s" COM_PATCHTESTER_FILE_MODIFIED_DOES_NOT_EXIST_S="Die zu ändernde Datei existiert nicht: %s"
COM_PATCHTESTER_FILTER_APPLIED_PATCHES="Angewendete Patches filtern" COM_PATCHTESTER_FILTER_APPLIED_PATCHES="Angewendete Patches filtern"
@ -75,6 +85,7 @@ COM_PATCHTESTER_NO_CREDENTIALS="In den Optionen wurden noch keine Benutzerdaten
COM_PATCHTESTER_NO_FILES_TO_PATCH="Es sind keine Dateien aus diesem Pull Request zu patchen. Dies kann bedeuten, dass die Dateien des Pull Requests in Ihrer Installation nicht vorhanden sind." COM_PATCHTESTER_NO_FILES_TO_PATCH="Es sind keine Dateien aus diesem Pull Request zu patchen. Dies kann bedeuten, dass die Dateien des Pull Requests in Ihrer Installation nicht vorhanden sind."
COM_PATCHTESTER_NO_ITEMS="Es wurden noch keine Daten von Github abgerufen. Klicken Sie auf 'Daten abrufen' um die aktuellen Daten von Github zu holen." COM_PATCHTESTER_NO_ITEMS="Es wurden noch keine Daten von Github abgerufen. Klicken Sie auf 'Daten abrufen' um die aktuellen Daten von Github zu holen."
COM_PATCHTESTER_NOT_APPLIED="Nicht angewendet" COM_PATCHTESTER_NOT_APPLIED="Nicht angewendet"
COM_PATCHTESTER_NOT_IN_ORDER_OF_PATCHCHAIN="Der Patch kann nicht zurückgesetzt werden, es muss zunächst erstmal der Patch mit der Pull ID %s zurückgesetzt werden."
COM_PATCHTESTER_NOT_RTC="Nicht RTC" COM_PATCHTESTER_NOT_RTC="Nicht RTC"
COM_PATCHTESTER_PULL_ID="Pull-ID" COM_PATCHTESTER_PULL_ID="Pull-ID"
COM_PATCHTESTER_PULL_ID_ASC="Pull-ID aufsteigend" COM_PATCHTESTER_PULL_ID_ASC="Pull-ID aufsteigend"
@ -91,9 +102,11 @@ COM_PATCHTESTER_RESET_OK="Die Daten wurden erfolgreich zurück gesetzt."
COM_PATCHTESTER_REVERT_OK="Der Patch wurde erfolgreich entfernt" COM_PATCHTESTER_REVERT_OK="Der Patch wurde erfolgreich entfernt"
COM_PATCHTESTER_REVERT_PATCH="Patch entfernen" COM_PATCHTESTER_REVERT_PATCH="Patch entfernen"
COM_PATCHTESTER_RTC="RTC" COM_PATCHTESTER_RTC="RTC"
COM_PATCHTESTER_SERVER_RESPONDED_NOT_200="Es konnte entweder keine Verbindung zum Server aufgebaut werden oder der angegebene Pull Request existiert nicht auf dem Server."
COM_PATCHTESTER_TEST_THIS_PATCH="Diesen Patch testen" COM_PATCHTESTER_TEST_THIS_PATCH="Diesen Patch testen"
COM_PATCHTESTER_TOOLBAR_FETCH_DATA="Daten abrufen" COM_PATCHTESTER_TOOLBAR_FETCH_DATA="Daten abrufen"
COM_PATCHTESTER_TOOLBAR_RESET="Zurücksetzen" COM_PATCHTESTER_TOOLBAR_RESET="Zurücksetzen"
COM_PATCHTESTER_VIEW_ON_GITHUB="Auf GitHub ansehen" COM_PATCHTESTER_VIEW_ON_GITHUB="Auf GitHub ansehen"
COM_PATCHTESTER_VIEW_ON_JOOMLA_ISSUE_TRACKER="Im Joomla! Issue Tracker ansehen" COM_PATCHTESTER_VIEW_ON_JOOMLA_ISSUE_TRACKER="Im Joomla! Issue Tracker ansehen"
COM_PATCHTESTER_ZIP_DOES_NOT_EXIST="Der Patch konnte nicht angewendet werden, weil er nicht vom Server heruntergeladen werden konnte."
COM_PATCHTESTER_ZIP_EXTRACT_FAILED="Der Patch konnte nicht angewendet werden, weil nicht entpackt werden konnte."

View File

@ -4,7 +4,6 @@
; Note : All ini files need to be saved as UTF-8 ; Note : All ini files need to be saved as UTF-8
COM_PATCHTESTER="Joomla! Patch Tester" COM_PATCHTESTER="Joomla! Patch Tester"
COM_PATCHTESTER_40_WARNING="While Joomla! 4.0 is in development, using the patch tester is considered experimental since breaking changes may be merged into Joomla, including the code contained in a patch."
COM_PATCHTESTER_API_LIMIT_ACTION="The GitHub API rate limit has been reached for this resource, could not connect to GitHub to perform the requested action. The rate limit will reset at %s" COM_PATCHTESTER_API_LIMIT_ACTION="The GitHub API rate limit has been reached for this resource, could not connect to GitHub to perform the requested action. The rate limit will reset at %s"
COM_PATCHTESTER_API_LIMIT_LIST="The GitHub API rate limit has been reached for this resource, could not connect to GitHub for updated data. The rate limit will reset at %s" COM_PATCHTESTER_API_LIMIT_LIST="The GitHub API rate limit has been reached for this resource, could not connect to GitHub for updated data. The rate limit will reset at %s"
COM_PATCHTESTER_APPLIED="Applied" COM_PATCHTESTER_APPLIED="Applied"
@ -28,6 +27,8 @@ COM_PATCHTESTER_ERROR_TRUNCATING_PULLS_TABLE="Error truncating the pulls table:
COM_PATCHTESTER_ERROR_TRUNCATING_TESTS_TABLE="Error truncating the tests table: %s" COM_PATCHTESTER_ERROR_TRUNCATING_TESTS_TABLE="Error truncating the tests table: %s"
COM_PATCHTESTER_ERROR_UNSUPPORTED_ENCODING="The patch's files are encoded in an unsupported format." COM_PATCHTESTER_ERROR_UNSUPPORTED_ENCODING="The patch's files are encoded in an unsupported format."
COM_PATCHTESTER_ERROR_VIEW_NOT_FOUND="View not found [name, format]: %1$s, %2$s" COM_PATCHTESTER_ERROR_VIEW_NOT_FOUND="View not found [name, format]: %1$s, %2$s"
COM_PATCHTESTER_FAILED_APPLYING_PATCH="Patch could not be applied due to exception with %1$s. %2$s"
COM_PATCHTESTER_FAILED_REVERT_PATCH="Patch could not be reverted due to exception with %1$s. %2$s"
COM_PATCHTESTER_FETCH_AN_ERROR_HAS_OCCURRED="An error has occurred while fetching the data from GitHub." COM_PATCHTESTER_FETCH_AN_ERROR_HAS_OCCURRED="An error has occurred while fetching the data from GitHub."
COM_PATCHTESTER_FETCH_COMPLETE_CLOSE_WINDOW="All data has been retrieved. Please close this modal window to refresh the page." COM_PATCHTESTER_FETCH_COMPLETE_CLOSE_WINDOW="All data has been retrieved. Please close this modal window to refresh the page."
COM_PATCHTESTER_FETCH_INITIALIZING="Preparing to fetch GitHub data" COM_PATCHTESTER_FETCH_INITIALIZING="Preparing to fetch GitHub data"
@ -57,10 +58,18 @@ COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_PATCHTESTER="Joomla! Patch Tester Compon
COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_INSTALL_FROM_WEB="Joomla! Install From Web Plugin" 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_OPTION_WEBLINKS="Joomla! Weblinks Package"
COM_PATCHTESTER_FIELD_REPOSITORY_CUSTOM="Custom" 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_DESC="Configuration Values for GitHub Repository"
COM_PATCHTESTER_FIELDSET_REPOSITORIES_LABEL="GitHub Repository" COM_PATCHTESTER_FIELDSET_REPOSITORIES_LABEL="GitHub Repository"
COM_PATCHTESTER_FIELDSET_AUTHENTICATION_DESC="Configuration Values for GitHub Authentication" COM_PATCHTESTER_FIELDSET_AUTHENTICATION_DESC="Configuration Values for GitHub Authentication"
COM_PATCHTESTER_FIELDSET_AUTHENTICATION_LABEL="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_FILE_DELETED_DOES_NOT_EXIST_S="The file marked for deletion does not exist: %s" 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_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_APPLIED_PATCHES="Filter Applied Patches"
@ -75,6 +84,7 @@ 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_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_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_APPLIED="Not Applied"
COM_PATCHTESTER_NOT_IN_ORDER_OF_PATCHCHAIN="You can't revert this patch, you need to revert the patch with the pull id %s first."
COM_PATCHTESTER_NOT_RTC="Not RTC" COM_PATCHTESTER_NOT_RTC="Not RTC"
COM_PATCHTESTER_PULL_ID="Pull ID" COM_PATCHTESTER_PULL_ID="Pull ID"
COM_PATCHTESTER_PULL_ID_ASC="Pull ID ascending" COM_PATCHTESTER_PULL_ID_ASC="Pull ID ascending"
@ -91,8 +101,11 @@ COM_PATCHTESTER_RESET_OK="The reset process has completed successfully."
COM_PATCHTESTER_REVERT_OK="Patch successfully reverted" COM_PATCHTESTER_REVERT_OK="Patch successfully reverted"
COM_PATCHTESTER_REVERT_PATCH="Revert Patch" COM_PATCHTESTER_REVERT_PATCH="Revert Patch"
COM_PATCHTESTER_RTC="RTC" COM_PATCHTESTER_RTC="RTC"
COM_PATCHTESTER_SERVER_RESPONDED_NOT_200="The patch could not be applied either due to missing connection to the server or missing patch on the server."
COM_PATCHTESTER_TEST_THIS_PATCH="Test This Patch" COM_PATCHTESTER_TEST_THIS_PATCH="Test This Patch"
COM_PATCHTESTER_TOOLBAR_FETCH_DATA="Fetch Data" COM_PATCHTESTER_TOOLBAR_FETCH_DATA="Fetch Data"
COM_PATCHTESTER_TOOLBAR_RESET="Reset" COM_PATCHTESTER_TOOLBAR_RESET="Reset"
COM_PATCHTESTER_VIEW_ON_GITHUB="View on GitHub" COM_PATCHTESTER_VIEW_ON_GITHUB="View on GitHub"
COM_PATCHTESTER_VIEW_ON_JOOMLA_ISSUE_TRACKER="View on Joomla! Issue Tracker" COM_PATCHTESTER_VIEW_ON_JOOMLA_ISSUE_TRACKER="View on Joomla! Issue Tracker"
COM_PATCHTESTER_ZIP_DOES_NOT_EXIST="The patch could not be applied, because it couldn't be retrieved from server."
COM_PATCHTESTER_ZIP_EXTRACT_FAILED="The patch could not be applied, because it couldn't be extracted."

View File

@ -28,6 +28,8 @@ COM_PATCHTESTER_ERROR_TRUNCATING_PULLS_TABLE="Error truncating the pulls table:
COM_PATCHTESTER_ERROR_TRUNCATING_TESTS_TABLE="Error truncating the tests table: %s" COM_PATCHTESTER_ERROR_TRUNCATING_TESTS_TABLE="Error truncating the tests table: %s"
COM_PATCHTESTER_ERROR_UNSUPPORTED_ENCODING="The patch's files are encoded in an unsupported format." COM_PATCHTESTER_ERROR_UNSUPPORTED_ENCODING="The patch's files are encoded in an unsupported format."
COM_PATCHTESTER_ERROR_VIEW_NOT_FOUND="View not found [name, format]: %1$s, %2$s" COM_PATCHTESTER_ERROR_VIEW_NOT_FOUND="View not found [name, format]: %1$s, %2$s"
COM_PATCHTESTER_FAILED_APPLYING_PATCH="Patch could not be applied due to exception with %1$s. %2$s"
COM_PATCHTESTER_FAILED_REVERT_PATCH="Patch could not be reverted due to exception with %1$s. %2$s"
COM_PATCHTESTER_FETCH_AN_ERROR_HAS_OCCURRED="An error has occurred while fetching the data from GitHub." COM_PATCHTESTER_FETCH_AN_ERROR_HAS_OCCURRED="An error has occurred while fetching the data from GitHub."
COM_PATCHTESTER_FETCH_COMPLETE_CLOSE_WINDOW="All data has been retrieved. Please close this modal window to refresh the page." COM_PATCHTESTER_FETCH_COMPLETE_CLOSE_WINDOW="All data has been retrieved. Please close this modal window to refresh the page."
COM_PATCHTESTER_FETCH_INITIALIZING="Preparing to fetch GitHub data" COM_PATCHTESTER_FETCH_INITIALIZING="Preparing to fetch GitHub data"
@ -57,10 +59,18 @@ COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_PATCHTESTER="Joomla! Patch Tester Compon
COM_PATCHTESTER_FIELD_REPOSITORY_OPTION_INSTALL_FROM_WEB="Joomla! Install From Web Plugin" 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_OPTION_WEBLINKS="Joomla! Weblinks Package"
COM_PATCHTESTER_FIELD_REPOSITORY_CUSTOM="Custom" 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_DESC="Configuration Values for GitHub Repository"
COM_PATCHTESTER_FIELDSET_REPOSITORIES_LABEL="GitHub Repository" COM_PATCHTESTER_FIELDSET_REPOSITORIES_LABEL="GitHub Repository"
COM_PATCHTESTER_FIELDSET_AUTHENTICATION_DESC="Configuration Values for GitHub Authentication" COM_PATCHTESTER_FIELDSET_AUTHENTICATION_DESC="Configuration Values for GitHub Authentication"
COM_PATCHTESTER_FIELDSET_AUTHENTICATION_LABEL="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_FILE_DELETED_DOES_NOT_EXIST_S="The file marked for deletion does not exist: %s" 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_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_APPLIED_PATCHES="Filter Applied Patches"
@ -75,6 +85,7 @@ 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_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_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_APPLIED="Not Applied"
COM_PATCHTESTER_NOT_IN_ORDER_OF_PATCHCHAIN="You can't revert this patch, you need to revert the patch with the pull id %s first."
COM_PATCHTESTER_NOT_RTC="Not RTC" COM_PATCHTESTER_NOT_RTC="Not RTC"
COM_PATCHTESTER_PULL_ID="Pull ID" COM_PATCHTESTER_PULL_ID="Pull ID"
COM_PATCHTESTER_PULL_ID_ASC="Pull ID ascending" COM_PATCHTESTER_PULL_ID_ASC="Pull ID ascending"
@ -91,9 +102,11 @@ COM_PATCHTESTER_RESET_OK="The reset process has completed successfully."
COM_PATCHTESTER_REVERT_OK="Patch successfully reverted" COM_PATCHTESTER_REVERT_OK="Patch successfully reverted"
COM_PATCHTESTER_REVERT_PATCH="Revert Patch" COM_PATCHTESTER_REVERT_PATCH="Revert Patch"
COM_PATCHTESTER_RTC="RTC" COM_PATCHTESTER_RTC="RTC"
COM_PATCHTESTER_SERVER_RESPONDED_NOT_200="The patch could not be applied either due to missing connection to the server or missing patch on the server."
COM_PATCHTESTER_TEST_THIS_PATCH="Test This Patch" COM_PATCHTESTER_TEST_THIS_PATCH="Test This Patch"
COM_PATCHTESTER_TOOLBAR_FETCH_DATA="Fetch Data" COM_PATCHTESTER_TOOLBAR_FETCH_DATA="Fetch Data"
COM_PATCHTESTER_TOOLBAR_RESET="Reset" COM_PATCHTESTER_TOOLBAR_RESET="Reset"
COM_PATCHTESTER_VIEW_ON_GITHUB="View on GitHub" COM_PATCHTESTER_VIEW_ON_GITHUB="View on GitHub"
COM_PATCHTESTER_VIEW_ON_JOOMLA_ISSUE_TRACKER="View on Joomla! Issue Tracker" COM_PATCHTESTER_VIEW_ON_JOOMLA_ISSUE_TRACKER="View on Joomla! Issue Tracker"
COM_PATCHTESTER_ZIP_DOES_NOT_EXIST="The patch could not be applied, because it couldn't be retrieved from server."
COM_PATCHTESTER_ZIP_EXTRACT_FAILED="The patch could not be applied, because it couldn't be extracted."

View File

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<extension type="component" version="3.6" method="upgrade"> <extension type="component" version="4.0" method="upgrade">
<name>com_patchtester</name> <name>com_patchtester</name>
<author>Joomla! Project</author> <author>Joomla! Project</author>
<creationDate>01-September-2018</creationDate> <creationDate>17-October-2019</creationDate>
<copyright>(C) 2011 - 2012 Ian MacLennan, (C) 2013 - 2018 Open Source Matters, Inc. All rights reserved.</copyright> <copyright>(C) 2011 - 2012 Ian MacLennan, (C) 2013 - 2018 Open Source Matters, Inc. All rights reserved.</copyright>
<license>GNU General Public License version 2 or later</license> <license>GNU General Public License version 2 or later</license>
<authorEmail>admin@joomla.org</authorEmail> <authorEmail>admin@joomla.org</authorEmail>
<authorUrl>https://www.joomla.org</authorUrl> <authorUrl>https://www.joomla.org</authorUrl>
<version>3.0.0-beta5-dev</version> <version>4.0.0-beta2</version>
<description>COM_PATCHTESTER_XML_DESCRIPTION</description> <description>COM_PATCHTESTER_XML_DESCRIPTION</description>
<scriptfile>script.php</scriptfile> <scriptfile>script.php</scriptfile>
<install> <install>
@ -15,7 +15,6 @@
<file driver="mysql" charset="utf8">install/sql/mysql/install.sql</file> <file driver="mysql" charset="utf8">install/sql/mysql/install.sql</file>
<file driver="postgresql" charset="utf8">install/sql/postgresql/install.sql</file> <file driver="postgresql" charset="utf8">install/sql/postgresql/install.sql</file>
<file driver="pgsql" charset="utf8">install/sql/postgresql/install.sql</file> <file driver="pgsql" charset="utf8">install/sql/postgresql/install.sql</file>
<file driver="sqlsrv" charset="utf8">install/sql/sqlsrv/install.sql</file>
</sql> </sql>
</install> </install>
<uninstall> <uninstall>
@ -23,7 +22,6 @@
<file driver="mysql" charset="utf8">install/sql/mysql/uninstall.sql</file> <file driver="mysql" charset="utf8">install/sql/mysql/uninstall.sql</file>
<file driver="postgresql" charset="utf8">install/sql/postgresql/uninstall.sql</file> <file driver="postgresql" charset="utf8">install/sql/postgresql/uninstall.sql</file>
<file driver="pgsql" charset="utf8">install/sql/postgresql/uninstall.sql</file> <file driver="pgsql" charset="utf8">install/sql/postgresql/uninstall.sql</file>
<file driver="sqlsrv" charset="utf8">install/sql/sqlsrv/uninstall.sql</file>
</sql> </sql>
</uninstall> </uninstall>
<update> <update>
@ -31,7 +29,6 @@
<schemapath type="mysql">install/sql/updates/mysql</schemapath> <schemapath type="mysql">install/sql/updates/mysql</schemapath>
<schemapath type="postgresql">install/sql/updates/postgresql</schemapath> <schemapath type="postgresql">install/sql/updates/postgresql</schemapath>
<schemapath type="pgsql">install/sql/updates/postgresql</schemapath> <schemapath type="pgsql">install/sql/updates/postgresql</schemapath>
<schemapath type="sqlsrv">install/sql/updates/sqlsrv</schemapath>
</schemas> </schemas>
</update> </update>
<media destination="com_patchtester" folder="media"> <media destination="com_patchtester" folder="media">

View File

@ -1,180 +0,0 @@
<?php
/**
* Patch testing component for the Joomla! CMS
*
* @copyright Copyright (C) 2011 - 2012 Ian MacLennan, Copyright (C) 2013 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later
*/
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Installer\Adapter\ComponentAdapter;
use Joomla\CMS\Installer\InstallerScript;
use Joomla\CMS\Language\Text;
/**
* Installation class to perform additional changes during install/uninstall/update
*
* @since 2.0
*/
class Com_PatchtesterInstallerScript extends InstallerScript
{
/**
* Array of templates with supported overrides
*
* @var array
* @since 2.0
*/
protected $templateOverrides = array('atum');
/**
* Extension script constructor.
*
* @since 3.0.0
*/
public function __construct()
{
$this->minimumJoomla = '3.9';
$this->minimumPhp = JOOMLA_MINIMUM_PHP;
$this->deleteFiles = array(
'/administrator/components/com_patchtester/PatchTester/View/Pulls/tmpl/default_errors.php',
'/administrator/templates/hathor/html/com_patchtester/pulls/default.php',
'/administrator/templates/hathor/html/com_patchtester/pulls/default_items.php',
);
$this->deleteFolders = array(
'/administrator/components/com_patchtester/PatchTester/Table',
'/administrator/templates/hathor/html/com_patchtester/pulls',
'/administrator/templates/hathor/html/com_patchtester',
'/components/com_patchtester',
);
}
/**
* Function to perform changes during install
*
* @param ComponentAdapter $parent The class calling this method
*
* @return void
*
* @since 2.0
*/
public function install($parent)
{
$this->copyLayouts();
}
/**
* Function to perform changes during update
*
* @param ComponentAdapter $parent The class calling this method
*
* @return void
*
* @since 2.0
*/
public function update($parent)
{
$this->copyLayouts();
}
/**
* Function to perform changes during uninstall
*
* @param ComponentAdapter $parent The class calling this method
*
* @return void
*
* @since 2.0
*/
public function uninstall($parent)
{
// Initialize the error array
$errorTemplates = array();
// Loop the supported templates
foreach ($this->templateOverrides as $template)
{
// Set the file paths
$tmplRoot = JPATH_ADMINISTRATOR . '/templates/' . $template;
$overrideFolder = JPATH_ADMINISTRATOR . '/templates/' . $template . '/html/com_patchtester';
// Make sure the template is actually installed
if (is_dir($tmplRoot))
{
// If there's a failure in copying the overrides, log it to the error array
if (Folder::delete($overrideFolder))
{
$errorTemplates[] = ucfirst($template);
}
}
}
// If we couldn't remove any overrides, notify the user
if (count($errorTemplates) > 0)
{
Factory::getApplication()->enqueueMessage(Text::sprintf('COM_PATCHTESTER_COULD_NOT_REMOVE_OVERRIDES', implode(', ', $errorTemplates)));
}
}
/**
* Function to perform changes during postflight
*
* @param string $type The action being performed
* @param ComponentAdapter $parent The class calling this method
*
* @return void
*
* @since 3.0.0
*/
public function postflight($type, $parent)
{
$this->removeFiles();
}
/**
* Function to copy layout overrides for core templates at install or update
*
* @return void
*
* @since 2.0
*/
private function copyLayouts()
{
// Initialize the error array
$errorTemplates = array();
// Loop the supported templates
foreach ($this->templateOverrides as $template)
{
// Set the file paths
$source = __DIR__ . '/' . $template;
$tmplRoot = JPATH_ADMINISTRATOR . '/templates/' . $template;
$destination = JPATH_ADMINISTRATOR . '/templates/' . $template . '/html/com_patchtester';
// Make sure the template is actually installed
if (is_dir($tmplRoot))
{
// If there's a failure in copying the overrides, log it to the error array
try
{
if (Folder::copy($source, $destination, '', true))
{
$errorTemplates[] = ucfirst($template);
}
}
catch (RuntimeException $exception)
{
$errorTemplates[] = ucfirst($template);
}
}
}
// If we couldn't remove any overrides, notify the user
if (count($errorTemplates) > 0)
{
Factory::getApplication()->enqueueMessage(Text::sprintf('COM_PATCHTESTER_COULD_NOT_INSTALL_OVERRIDES', implode(', ', $errorTemplates)));
}
}
}

View File

@ -1,28 +0,0 @@
<?php
/**
* Patch testing component for the Joomla! CMS
*
* @copyright Copyright (C) 2011 - 2012 Ian MacLennan, Copyright (C) 2013 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later
*/
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
/** @var \PatchTester\View\DefaultHtmlView $this */
HTMLHelper::_('jquery.framework');
HTMLHelper::_('behavior.core');
HTMLHelper::_('script', 'com_patchtester/fetcher.js', array('version' => 'auto', 'relative' => true));
?>
<div id="patchtester-container">
<h1 id="patchtester-progress-header"><?php echo Text::_('COM_PATCHTESTER_FETCH_INITIALIZING'); ?></h1>
<p id="patchtester-progress-message"><?php echo Text::_('COM_PATCHTESTER_FETCH_INITIALIZING_DESCRIPTION'); ?></p>
<div id="progress" class="progress">
<div id="progress-bar" class="progress-bar progress-bar-striped progress-bar-animated bg-success" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" role="progressbar"></div>
</div>
<input id="patchtester-token" type="hidden" name="<?php echo Factory::getSession()->getFormToken(); ?>" value="1" />
</div>

View File

@ -1,163 +0,0 @@
<?php
/**
* Patch testing component for the Joomla! CMS
*
* @copyright Copyright (C) 2011 - 2012 Ian MacLennan, Copyright (C) 2013 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later
*/
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
/** @var \PatchTester\View\Pulls\PullsHtmlView $this */
$searchToolsOptions = array(
'filtersHidden' => true,
'filterButton' => true,
'defaultLimit' => Factory::getApplication()->get('list_limit', 20),
'searchFieldSelector' => '#filter_search',
'selectorFieldName' => 'client_id',
'showSelector' => false,
'orderFieldSelector' => '#list_fullordering',
'showNoResults' => false,
'noResultsText' => '',
'formSelector' => '#adminForm',
);
HTMLHelper::_('behavior.core');
HTMLHelper::_('searchtools.form', '#adminForm', $searchToolsOptions);
HTMLHelper::_('stylesheet', 'com_patchtester/octicons.css', array('version' => '3.5.0', 'relative' => true));
HTMLHelper::_('script', 'com_patchtester/patchtester.js', array('version' => 'auto', 'relative' => true));
$listOrder = $this->escape($this->state->get('list.fullordering', 'a.pull_id DESC'));
$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'));
?>
<form action="<?php echo Route::_('index.php?option=com_patchtester&view=pulls'); ?>" method="post" name="adminForm" id="adminForm">
<div class="row">
<div class="col-md-12">
<div id="j-main-container" class="j-main-container">
<div class="js-stools" role="search">
<div class="js-stools-container-bar">
<div class="btn-toolbar">
<div class="btn-group mr-2">
<div class="input-group">
<label for="filter_search" class="sr-only">
<?php echo Text::_('COM_PATCHTESTER_FILTER_SEARCH_DESCRIPTION'); ?>
</label>
<input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" class="form-control" placeholder="<?php echo Text::_('JSEARCH_FILTER'); ?>">
<div role="tooltip" id="filter_search-desc">
<?php echo $this->escape(Text::_('COM_PATCHTESTER_FILTER_SEARCH_DESCRIPTION')); ?>
</div>
<span class="input-group-append">
<button type="submit" class="btn btn-primary" aria-label="<?php echo Text::_('JSEARCH_FILTER_SUBMIT'); ?>">
<span class="fa fa-search" aria-hidden="true"></span>
</button>
</span>
</div>
</div>
<div class="btn-group">
<button type="button" class="btn btn-primary hasTooltip js-stools-btn-filter">
<?php echo Text::_('JFILTER_OPTIONS'); ?>
<span class="fa fa-angle-down" aria-hidden="true"></span>
</button>
<button type="button" class="btn btn-primary js-stools-btn-clear mr-2">
<?php echo Text::_('JSEARCH_FILTER_CLEAR'); ?>
</button>
</div>
<div class="ordering-select">
<div class="js-stools-field-list">
<select name="list_fullordering" id="list_fullordering" class="custom-select" onchange="this.form.submit()">
<option value=""><?php echo Text::_('JGLOBAL_SORT_BY'); ?></option>
<?php echo HTMLHelper::_('select.options', $this->getSortFields(), 'value', 'text', $listOrder); ?>
</select>
</div>
<div class="js-stools-field-list">
<span class="sr-only">
<label id="list_limit-lbl" for="list_limit">Select number of items per page.</label>
</span>
<select name="list_limit" id="list_limit" class="custom-select" onchange="this.form.submit()">
<?php echo HTMLHelper::_('select.options', $this->getLimitOptions(), 'value', 'text', $listLimit); ?>
</select>
</div>
</div>
</div>
</div>
<!-- Filters div -->
<div class="js-stools-container-filters clearfix">
<div class="js-stools-field-filter">
<select name="filter_applied" class="custom-select" onchange="this.form.submit();">
<option value=""><?php echo Text::_('COM_PATCHTESTER_FILTER_APPLIED_PATCHES'); ?></option>
<option value="yes"<?php if ($filterApplied == 'yes') echo ' selected="selected"'; ?>><?php echo Text::_('COM_PATCHTESTER_APPLIED'); ?></option>
<option value="no"<?php if ($filterApplied == 'no') echo ' selected="selected"'; ?>><?php echo Text::_('COM_PATCHTESTER_NOT_APPLIED'); ?></option>
</select>
</div>
<div class="js-stools-field-filter">
<select name="filter_rtc" class="custom-select" onchange="this.form.submit();">
<option value=""><?php echo Text::_('COM_PATCHTESTER_FILTER_RTC_PATCHES'); ?></option>
<option value="yes"<?php if ($filterRtc == 'yes') echo ' selected="selected"'; ?>><?php echo Text::_('COM_PATCHTESTER_RTC'); ?></option>
<option value="no"<?php if ($filterRtc == 'no') echo ' selected="selected"'; ?>><?php echo Text::_('COM_PATCHTESTER_NOT_RTC'); ?></option>
</select>
</div>
<div class="js-stools-field-filter">
<select name="filter_branch" class="custom-select" onchange="this.form.submit();">
<option value=""><?php echo Text::_('COM_PATCHTESTER_FILTER_BRANCH'); ?></option>
<?php echo HTMLHelper::_('select.options', $this->branches, 'text', 'text', $filterBranch, false); ?>
</select>
</div>
</div>
</div>
<div id="j-main-container" class="j-main-container">
<?php if (empty($this->items)) : ?>
<div class="alert alert-info">
<span class="fa fa-info-circle" aria-hidden="true"></span><span class="sr-only"><?php echo Text::_('INFO'); ?></span>
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
</div>
<?php else : ?>
<table class="table">
<caption id="captionTable" class="sr-only">
<?php echo Text::_('COM_PATCHTESTER_PULLS_TABLE_CAPTION'); ?>, <?php echo Text::_('JGLOBAL_SORTED_BY'); ?>
</caption>
<thead>
<tr>
<th scope="col" style="width:5%" class="text-center">
<?php echo Text::_('COM_PATCHTESTER_PULL_ID'); ?>
</th>
<th scope="col" style="min-width:100px">
<?php echo Text::_('JGLOBAL_TITLE'); ?>
</th>
<th scope="col" style="width:8%" class="d-none d-md-table-cell text-center">
<?php echo Text::_('COM_PATCHTESTER_BRANCH'); ?>
</th>
<th scope="col" style="width:8%" class="d-none d-md-table-cell text-center">
<?php echo Text::_('COM_PATCHTESTER_READY_TO_COMMIT'); ?>
</th>
<th scope="col" style="width:10%" class="text-center">
<?php echo Text::_('JSTATUS'); ?>
</th>
<th scope="col" style="width:15%" class="text-center">
<?php echo Text::_('COM_PATCHTESTER_TEST_THIS_PATCH'); ?>
</th>
</tr>
</thead>
<tbody>
<?php echo $this->loadTemplate('items'); ?>
</tbody>
</table>
<?php endif; ?>
<?php echo $this->pagination->getListFooter(); ?>
<input type="hidden" name="task" value="" />
<input type="hidden" name="boxchecked" value="0" />
<input type="hidden" name="pull_id" id="pull_id" value="" />
<?php echo HTMLHelper::_('form.token'); ?>
</div>
</div>
</div>
</div>
</form>

View File

@ -1,72 +0,0 @@
<?php
/**
* Patch testing component for the Joomla! CMS
*
* @copyright Copyright (C) 2011 - 2012 Ian MacLennan, Copyright (C) 2013 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later
*/
use Joomla\CMS\Language\Text;
/** @var \PatchTester\View\DefaultHtmlView $this */
foreach ($this->items as $i => $item) :
$status = '';
if ($item->applied) :
$status = ' class="table-active"';
endif;
?>
<tr<?php echo $status; ?>>
<th scope="row" class="text-center">
<?php echo $item->pull_id; ?>
</th>
<td>
<span><?php echo $this->escape($item->title); ?></span>
<div role="tooltip" id="tip<?php echo $i; ?>">
<?php echo $this->escape($item->description); ?>
</div>
<div class="row">
<div class="col-md-auto">
<a class="badge badge-info" href="<?php echo $item->pull_url; ?>" target="_blank">
<?php echo Text::_('COM_PATCHTESTER_VIEW_ON_GITHUB'); ?>
</a>
</div>
<div class="col-md-auto">
<a class="badge badge-info" href="https://issues.joomla.org/tracker/<?php echo $this->trackerAlias; ?>/<?php echo $item->pull_id; ?>" target="_blank">
<?php echo Text::_('COM_PATCHTESTER_VIEW_ON_JOOMLA_ISSUE_TRACKER'); ?>
</a>
</div>
<?php if ($item->applied) : ?>
<div class="col-md-auto">
<span class="badge badge-info"><?php echo Text::sprintf('COM_PATCHTESTER_APPLIED_COMMIT_SHA', substr($item->sha, 0, 10)); ?></span>
</div>
<?php endif; ?>
</div>
</td>
<td class="d-none d-md-table-cell text-center">
<?php echo $this->escape($item->branch); ?>
</td>
<td class="d-none d-md-table-cell text-center">
<?php if ($item->is_rtc) : ?>
<span class="badge badge-success"><?php echo Text::_('JYES'); ?></span>
<?php else : ?>
<span class="badge badge-secondary"><?php echo Text::_('JNO'); ?></span>
<?php endif; ?>
</td>
<td class="text-center">
<?php if ($item->applied) : ?>
<span class="badge badge-success"><?php echo Text::_('COM_PATCHTESTER_APPLIED'); ?></span>
<?php else : ?>
<span class="badge badge-secondary"><?php echo Text::_('COM_PATCHTESTER_NOT_APPLIED'); ?></span>
<?php endif; ?>
</td>
<td class="text-center">
<?php if ($item->applied) : ?>
<button class="btn btn-sm btn-success" onclick="PatchTester.submitpatch('revert', '<?php echo (int) $item->applied; ?>');"><?php echo Text::_('COM_PATCHTESTER_REVERT_PATCH'); ?></button>
<?php else : ?>
<button class="btn btn-sm btn-primary" onclick="PatchTester.submitpatch('apply', '<?php echo (int) $item->pull_id; ?>');"><?php echo Text::_('COM_PATCHTESTER_APPLY_PATCH'); ?></button>
<?php endif; ?>
</td>
</tr>
<?php endforeach;

View File

@ -5,11 +5,9 @@ rm -rf build/packages && mkdir build/packages
composer install --no-dev -o composer install --no-dev -o
cp -r administrator/components/com_patchtester build/packaging/admin cp -r administrator/components/com_patchtester build/packaging/admin
cp -r administrator/templates/atum/html/com_patchtester build/packaging/atum cp -r administrator/templates/atum/html/com_patchtester build/packaging/atum
cp -r administrator/templates/hathor/html/com_patchtester build/packaging/hathor
cp -r media/com_patchtester build/packaging/media cp -r media/com_patchtester build/packaging/media
rm -rf build/packaging/admin/backups/*.txt rm -rf build/packaging/admin/backups/*.txt
mv build/packaging/admin/patchtester.xml build/packaging/patchtester.xml mv build/packaging/admin/patchtester.xml build/packaging/patchtester.xml
mv build/packaging/admin/script.php build/packaging/script.php
cd build/packaging cd build/packaging
tar jcf ../packages/com_patchtester.tar.bz2 . tar jcf ../packages/com_patchtester.tar.bz2 .
tar zcf ../packages/com_patchtester.tar.gz . tar zcf ../packages/com_patchtester.tar.gz .

@ -1 +0,0 @@
Subproject commit 92233693cc8cf9634e00b8bc13b56c787d5f0871

View File

@ -9,12 +9,13 @@
"vendor-dir": "administrator/components/com_patchtester/vendor" "vendor-dir": "administrator/components/com_patchtester/vendor"
}, },
"require": { "require": {
"php": "^5.3.10|^7.0" "php": "^7.2"
}, },
"require-dev": { "require-dev": {
"php": "^5.6|^7.0",
"joomla/crowdin-sync": "dev-master", "joomla/crowdin-sync": "dev-master",
"squizlabs/php_codesniffer": "~1.5" "joomla/cms-coding-standards": "~2.0.0-alpha2@dev",
"joomla/coding-standards": "~3.0@dev",
"squizlabs/php_codesniffer": "~3.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

188
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "35e372f08cd218b7040fd37d8e7dcaeb", "content-hash": "ea3333f86c6c0231db3f7c0611ade016",
"packages": [], "packages": [],
"packages-dev": [ "packages-dev": [
{ {
@ -332,6 +332,108 @@
], ],
"time": "2019-03-28T14:55:36+00:00" "time": "2019-03-28T14:55:36+00:00"
}, },
{
"name": "joomla/cms-coding-standards",
"version": "2.0.0-alpha2",
"source": {
"type": "git",
"url": "https://github.com/joomla/cms-coding-standards.git",
"reference": "25abae52f9167fa47ce57331bbece8079ad27ab3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/joomla/cms-coding-standards/zipball/25abae52f9167fa47ce57331bbece8079ad27ab3",
"reference": "25abae52f9167fa47ce57331bbece8079ad27ab3",
"shasum": ""
},
"require": {
"joomla/coding-standards": "~2.0 || ~3.0",
"php": ">=5.3.10"
},
"require-dev": {
"phpunit/phpunit": "^4.8.7"
},
"suggest": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.3 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically."
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Joomla-CMS\\Sniffs\\": "lib/Joomla-CMS/Sniffs"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0-or-later"
],
"authors": [
{
"name": "Joomla Coding Standards Contributors",
"homepage": "https://github.com/joomla/cms-coding-standards/graphs/contributors"
}
],
"description": "Extended Joomla Coding Standards for the Joomla CMS application",
"homepage": "https://github.com/joomla/cms-coding-standards",
"keywords": [
"coding standards",
"joomla",
"php codesniffer",
"phpcs"
],
"time": "2019-07-13T18:56:54+00:00"
},
{
"name": "joomla/coding-standards",
"version": "dev-3.x-dev",
"source": {
"type": "git",
"url": "https://github.com/joomla/coding-standards.git",
"reference": "fc041ba4352689d0834fc3f6bce14edc6e40aebe"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/joomla/coding-standards/zipball/fc041ba4352689d0834fc3f6bce14edc6e40aebe",
"reference": "fc041ba4352689d0834fc3f6bce14edc6e40aebe",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"squizlabs/php_codesniffer": "^3.4"
},
"require-dev": {
"phpunit/phpunit": "^4.8.7"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-3.x-dev": "3.0-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0-or-later"
],
"authors": [
{
"name": "Joomla Coding Standards Contributors",
"homepage": "https://github.com/joomla/coding-standards/graphs/contributors"
}
],
"description": "Joomla Coding Standards",
"homepage": "https://github.com/joomla/coding-standards",
"keywords": [
"coding standards",
"joomla",
"php codesniffer",
"phpcs"
],
"time": "2019-07-12T10:04:53+00:00"
},
{ {
"name": "joomla/compat", "name": "joomla/compat",
"version": "1.2.0", "version": "1.2.0",
@ -375,12 +477,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/joomla-projects/crowdin-sync.git", "url": "https://github.com/joomla-projects/crowdin-sync.git",
"reference": "8a61f12161b30ff4aa0402ad0dccd599b38714af" "reference": "c1db9d2186a273b66297f4fbf239bbc06b70a9fb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/joomla-projects/crowdin-sync/zipball/8a61f12161b30ff4aa0402ad0dccd599b38714af", "url": "https://api.github.com/repos/joomla-projects/crowdin-sync/zipball/c1db9d2186a273b66297f4fbf239bbc06b70a9fb",
"reference": "8a61f12161b30ff4aa0402ad0dccd599b38714af", "reference": "c1db9d2186a273b66297f4fbf239bbc06b70a9fb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -401,7 +503,7 @@
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"GPL-2.0+" "GPL-2.0-or-later"
], ],
"description": "CLI application to synchronize a project with Crowdin", "description": "CLI application to synchronize a project with Crowdin",
"homepage": "https://github.com/joomla-projects/crowdin-sync", "homepage": "https://github.com/joomla-projects/crowdin-sync",
@ -409,7 +511,7 @@
"crowdin", "crowdin",
"joomla" "joomla"
], ],
"time": "2019-03-29T12:07:12+00:00" "time": "2019-09-10T14:24:41+00:00"
}, },
{ {
"name": "joomla/filter", "name": "joomla/filter",
@ -812,61 +914,37 @@
}, },
{ {
"name": "squizlabs/php_codesniffer", "name": "squizlabs/php_codesniffer",
"version": "1.5.6", "version": "3.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5" "reference": "0afebf16a2e7f1e434920fa976253576151effe9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6f3e42d311b882b25b4d409d23a289f4d3b803d5", "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/0afebf16a2e7f1e434920fa976253576151effe9",
"reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5", "reference": "0afebf16a2e7f1e434920fa976253576151effe9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-simplexml": "*",
"ext-tokenizer": "*", "ext-tokenizer": "*",
"php": ">=5.1.2" "ext-xmlwriter": "*",
"php": ">=5.4.0"
}, },
"suggest": { "require-dev": {
"phpunit/php-timer": "dev-master" "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
}, },
"bin": [ "bin": [
"scripts/phpcs" "bin/phpcs",
"bin/phpcbf"
], ],
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-phpcs-fixer": "2.0.x-dev" "dev-master": "3.x-dev"
} }
}, },
"autoload": {
"classmap": [
"CodeSniffer.php",
"CodeSniffer/CLI.php",
"CodeSniffer/Exception.php",
"CodeSniffer/File.php",
"CodeSniffer/Report.php",
"CodeSniffer/Reporting.php",
"CodeSniffer/Sniff.php",
"CodeSniffer/Tokens.php",
"CodeSniffer/Reports/",
"CodeSniffer/CommentParser/",
"CodeSniffer/Tokenizers/",
"CodeSniffer/DocGenerators/",
"CodeSniffer/Standards/AbstractPatternSniff.php",
"CodeSniffer/Standards/AbstractScopeSniff.php",
"CodeSniffer/Standards/AbstractVariableSniff.php",
"CodeSniffer/Standards/IncorrectPatternException.php",
"CodeSniffer/Standards/Generic/Sniffs/",
"CodeSniffer/Standards/MySource/Sniffs/",
"CodeSniffer/Standards/PEAR/Sniffs/",
"CodeSniffer/Standards/PSR1/Sniffs/",
"CodeSniffer/Standards/PSR2/Sniffs/",
"CodeSniffer/Standards/Squiz/Sniffs/",
"CodeSniffer/Standards/Zend/Sniffs/"
]
},
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"BSD-3-Clause" "BSD-3-Clause"
@ -877,13 +955,13 @@
"role": "lead" "role": "lead"
} }
], ],
"description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "http://www.squizlabs.com/php-codesniffer", "homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [ "keywords": [
"phpcs", "phpcs",
"standards" "standards"
], ],
"time": "2014-12-04T22:32:15+00:00" "time": "2019-09-26T23:12:26+00:00"
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
@ -1001,16 +1079,16 @@
}, },
{ {
"name": "symfony/yaml", "name": "symfony/yaml",
"version": "v3.4.31", "version": "v3.4.32",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/yaml.git", "url": "https://github.com/symfony/yaml.git",
"reference": "3dc414b7db30695bae671a1d86013d03f4ae9834" "reference": "768f817446da74a776a31eea335540f9dcb53942"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/3dc414b7db30695bae671a1d86013d03f4ae9834", "url": "https://api.github.com/repos/symfony/yaml/zipball/768f817446da74a776a31eea335540f9dcb53942",
"reference": "3dc414b7db30695bae671a1d86013d03f4ae9834", "reference": "768f817446da74a776a31eea335540f9dcb53942",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1056,20 +1134,20 @@
], ],
"description": "Symfony Yaml Component", "description": "Symfony Yaml Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2019-08-20T13:31:17+00:00" "time": "2019-09-10T10:38:46+00:00"
} }
], ],
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": { "stability-flags": {
"joomla/crowdin-sync": 20 "joomla/crowdin-sync": 20,
"joomla/cms-coding-standards": 20,
"joomla/coding-standards": 20
}, },
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": "^5.3.10|^7.0" "php": "^7.2"
}, },
"platform-dev": { "platform-dev": []
"php": "^5.6|^7.0"
}
} }

View File

@ -112,7 +112,7 @@ if (typeof Joomla === 'undefined') {
jQuery('#progress').remove(); jQuery('#progress').remove();
} }
}); });
} };
initialize(); initialize();
}; };

View File

@ -9,27 +9,25 @@ if (typeof Joomla === 'undefined') {
throw new Error('PatchTester JavaScript requires the Joomla core JavaScript API') throw new Error('PatchTester JavaScript requires the Joomla core JavaScript API')
} }
!function (Joomla, window, document) { document.addEventListener("DOMContentLoaded", function (event) {
'use strict';
var submitPatch = document.querySelectorAll(".submitPatch");
var pullIdForm = document.querySelector("#pull_id");
window.PatchTester = {
/** /**
* Process the patch action * EventListener which listens on submitPatch Button,
* checks if it is an apply or revert method and
* processes the patch action
* *
* @param {String} task The task to perform * @param {Event} event
* @param {Number} id The item ID
*/ */
submitpatch: function (task, id) { submitPatch.forEach(function (element) {
var idField = document.getElementById('pull_id'); element.addEventListener("click", function (event) {
idField.value = id; var currentTarget = event.currentTarget;
var data = currentTarget.dataset.task.split("-");
Joomla.submitform(task); pullIdForm.value = data[1];
} Joomla.submitform(data[0]);
}; });
});
Joomla.submitbutton = function (task) { });
if (task != 'reset' || confirm(Joomla.JText._('COM_PATCHTESTER_CONFIRM_RESET', 'Resetting will attempt to revert all applied patches and removes all backed up files. This may result in a corrupted environment. Are you sure you want to continue?'))) {
Joomla.submitform(task);
}
};
}(Joomla, window, document);