Commit 34a8e67b authored by Thomas Löffler's avatar Thomas Löffler

Merge branch 'develop' into 'master'

Release 29-05-19

See merge request !423
parents 8e10f216 ff4fb8d8
Pipeline #7112 passed with stages
in 4 minutes and 14 seconds
......@@ -58,7 +58,7 @@ class UpdateCurrentVersionListTask extends \TYPO3\CMS\Extbase\Scheduler\Task
{
$result = false;
$targetFile = PATH_site . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . 'currentdocumentationdata.json';
$sourceData = GeneralUtility::getUrl('https://docs.typo3.org/typo3cms/extensions/manuals.json');
$sourceData = GeneralUtility::getUrl('https://intercept.typo3.com/assets/docs/manuals.json');
if (json_decode($sourceData, true) !== null) {
$result = GeneralUtility::writeFile($targetFile, $sourceData);
}
......
......@@ -210,6 +210,7 @@ class ExtensionController extends \T3o\TerFe2\Controller\AbstractController
$currentUser = $this->ownerRepository->findByUid((int)$GLOBALS['TSFE']->fe_user->user['uid']);
if ($currentUser instanceof \T3o\TerFe2\Domain\Model\FrontendUser) {
$this->view->assign('hasLiked', $currentUser->getLikedExtensions()->contains($extension));
$this->view->assign('notification', $currentUser->getNotifiedExtensions()->contains($extension));
}
}
}
......@@ -522,14 +523,12 @@ class ExtensionController extends \T3o\TerFe2\Controller\AbstractController
public function likeAction(\T3o\TerFe2\Domain\Model\Extension $extension)
{
$liked = false;
if ($GLOBALS['TSFE'] && $GLOBALS['TSFE']->loginUser) {
$currentUser = $this->ownerRepository->findByUid((int)$GLOBALS['TSFE']->fe_user->user['uid']);
if ($currentUser instanceof \T3o\TerFe2\Domain\Model\FrontendUser) {
$currentUser->addLikedExtension($extension);
$this->ownerRepository->update($currentUser);
$this->extensionRepository->update($extension);
$liked = true;
}
$currentUser = $this->getLoggedInUser();
if ($currentUser instanceof \T3o\TerFe2\Domain\Model\FrontendUser) {
$currentUser->addLikedExtension($extension);
$this->ownerRepository->update($currentUser);
$this->extensionRepository->update($extension);
$liked = true;
}
return json_encode($liked);
......@@ -538,19 +537,45 @@ class ExtensionController extends \T3o\TerFe2\Controller\AbstractController
public function disLikeAction(\T3o\TerFe2\Domain\Model\Extension $extension)
{
$disliked = false;
if ($GLOBALS['TSFE'] && $GLOBALS['TSFE']->loginUser) {
$currentUser = $this->ownerRepository->findByUid((int)$GLOBALS['TSFE']->fe_user->user['uid']);
if ($currentUser instanceof \T3o\TerFe2\Domain\Model\FrontendUser) {
$currentUser->removeLikedExtension($extension);
$this->ownerRepository->update($currentUser);
$this->extensionRepository->update($extension);
$disliked = true;
}
$currentUser = $this->getLoggedInUser();
if ($currentUser instanceof \T3o\TerFe2\Domain\Model\FrontendUser) {
$currentUser->removeLikedExtension($extension);
$this->ownerRepository->update($currentUser);
$this->extensionRepository->update($extension);
$disliked = true;
}
return json_encode($disliked);
}
public function activateNotificationAction(\T3o\TerFe2\Domain\Model\Extension $extension): string
{
$notified = false;
$currentUser = $this->getLoggedInUser();
if ($currentUser instanceof \T3o\TerFe2\Domain\Model\FrontendUser) {
$currentUser->addNotifiedExtension($extension);
$this->ownerRepository->update($currentUser);
$this->extensionRepository->update($extension);
$notified = true;
}
return json_encode($notified);
}
public function deactivateNotificationAction(\T3o\TerFe2\Domain\Model\Extension $extension): string
{
$unnotified = false;
$currentUser = $this->getLoggedInUser();
if ($currentUser instanceof \T3o\TerFe2\Domain\Model\FrontendUser) {
$currentUser->removeNotifiedExtension($extension);
$this->ownerRepository->update($currentUser);
$this->extensionRepository->update($extension);
$unnotified = true;
}
return json_encode($unnotified);
}
/**
* Check if current frontend user can upload given extension
*
......@@ -574,6 +599,18 @@ class ExtensionController extends \T3o\TerFe2\Controller\AbstractController
return !empty($isAllowedToUploadKey);
}
/**
* @return \T3o\TerFe2\Domain\Model\FrontendUser|null
*/
protected function getLoggedInUser(): ?\T3o\TerFe2\Domain\Model\FrontendUser
{
if ($GLOBALS['TSFE'] && $GLOBALS['TSFE']->fe_user && $GLOBALS['TSFE']->fe_user->user) {
return $this->ownerRepository->findByUid((int)$GLOBALS['TSFE']->fe_user->user['uid']);
}
return null;
}
/**
* Check if an version does not exist for extension
*
......
......@@ -121,6 +121,11 @@ class Extension extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
*/
protected $likes = 0;
/**
* @var int
*/
protected $notifications = 0;
/**
* Initialize all ObjectStorage instances.
*/
......@@ -600,4 +605,14 @@ class Extension extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
$this->likes--;
}
}
public function getNotifications(): int
{
return $this->notifications;
}
public function setNotifications(int $notifications): void
{
$this->notifications = $notifications;
}
}
......@@ -21,10 +21,16 @@ class FrontendUser extends \TYPO3\CMS\Extbase\Domain\Model\FrontendUser
*/
protected $likedExtensions;
/**
* @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\T3o\TerFe2\Domain\Model\Extension>
*/
protected $notifiedExtensions;
public function __construct()
{
parent::__construct();
$this->likedExtensions = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
$this->notifiedExtensions = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
/**
......@@ -61,4 +67,34 @@ class FrontendUser extends \TYPO3\CMS\Extbase\Domain\Model\FrontendUser
$this->likedExtensions->detach($extension);
}
}
public function getNotifiedExtensions(): \TYPO3\CMS\Extbase\Persistence\ObjectStorage
{
if ($this->notifiedExtensions === null) {
$this->notifiedExtensions = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
return $this->notifiedExtensions;
}
public function setNotifiedExtensions(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $notifiedExtensions): void
{
$this->notifiedExtensions = $notifiedExtensions;
}
public function addNotifiedExtension(Extension $extension): void
{
if ($this->notifiedExtensions === null) {
$this->notifiedExtensions = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
$this->notifiedExtensions->attach($extension);
}
public function removeNotifiedExtension(Extension $extension): void
{
if ($this->notifiedExtensions === null) {
$this->notifiedExtensions = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
$this->notifiedExtensions->detach($extension);
}
}
......@@ -21,12 +21,6 @@ namespace T3o\TerFe2\Service;
*/
class DocumentationService implements \TYPO3\CMS\Core\SingletonInterface
{
/**
* @var string
*/
protected $baseUrl = '';
/**
* @var array
*/
......@@ -42,7 +36,6 @@ class DocumentationService implements \TYPO3\CMS\Core\SingletonInterface
*/
public function __construct()
{
$this->baseUrl = 'https://docs.typo3.org/typo3cms/extensions/';
$this->availableFormats = [
'sxw',
'html',
......@@ -68,13 +61,13 @@ class DocumentationService implements \TYPO3\CMS\Core\SingletonInterface
throw new \Exception('Extension key and version string are required to build a documentation url');
}
$manualExists = isset($this->docsInformation->$extensionKey);
$manualExists = isset($this->docsInformation->{$extensionKey}['docs'][$versionString]);
$documentationLink = null;
$url = null;
if ($manualExists) {
// link to extension to get the latest manual
$url = $this->baseUrl . $extensionKey . '/';
$url = $this->docsInformation->{$extensionKey}['docs'][$versionString]['url'];
// check if link is not broken
// need to remove the 200 response check due to change in header for docs.typo3.org
$documentationLink = '<a href="' . $url . '">Extension Manual</a>';
......
......@@ -79,6 +79,7 @@ class ImportExtensionsFromQueueTask extends Task
$indexQueue = GeneralUtility::makeInstance(Queue::class);
$indexQueue->updateItem('tx_terfe2_domain_model_extension', $extUid);
}
$this->sendNotifications($extUid, $extensionData);
}
$this->logger->info(sprintf(
'Extension "%s" still exists in ter_fe2 with version %s',
......@@ -470,6 +471,52 @@ class ImportExtensionsFromQueueTask extends Task
->execute();
}
protected function sendNotifications(int $extensionUid, array $extensionData)
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('fe_users');
$notifications = $queryBuilder
->select(...['u.email', 'u.name', 'e.ext_key', 'e.composer_name'])
->from('tx_terfe2_extension_feuser_notification_mm', 'notify')
->join(
'notify',
'fe_users',
'u',
'u.uid = notify.uid_foreign'
)
->join(
'notify',
'tx_terfe2_domain_model_extension',
'e',
'e.uid = notify.uid_local'
)
->where(
$queryBuilder->expr()->eq('notify.uid_local', (int)$extensionUid)
)
->execute()
->fetchAll();
if (!empty($notifications)) {
foreach ($notifications as $notification) {
$mail = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Mail\MailMessage::class);
$mail->setTo($notification['email'], $notification['name']);
$mail->setSubject('Release of extension "' . $notification['ext_key'] . '", version ' . $extensionData['version']);
$standalone = GeneralUtility::makeInstance(\TYPO3\CMS\Fluid\View\StandaloneView::class);
$standalone->setTemplatePathAndFilename('EXT:ter_fe2/Resources/Private/Templates/Mail/NewVersionNotify.html');
$standalone->assignMultiple(
[
'notify' => $notification,
'extData' => $extensionData
]
);
$mail->setBody($standalone->render());
$mail->send();
}
}
}
/**
* @param string $extKey
*
......
......@@ -11,6 +11,17 @@ $columns = [
'MM' => 'tx_terfe2_extension_feuser_mm',
'MM_opposite_field' => 'likes'
]
],
'notified_extensions' => [
'exclude' => 1,
'label' => 'Liked extensions',
'config' => [
'type' => 'select',
'renderType' => 'selectMultipleSideBySide',
'foreign_table' => 'tx_terfe2_domain_model_extension',
'MM' => 'tx_terfe2_extension_feuser_notification_mm',
'MM_opposite_field' => 'notifications'
]
]
];
......
......@@ -234,6 +234,16 @@ return [
'foreign_table' => 'fe_users',
'MM' => 'tx_terfe2_extension_feuser_mm'
]
],
'notifications' => [
'exclude' => 1,
'label' => 'Notifications for users',
'config' => [
'type' => 'select',
'renderType' => 'selectMultipleSideBySide',
'foreign_table' => 'fe_users',
'MM' => 'tx_terfe2_extension_feuser_notification_mm'
]
]
],
];
......@@ -151,6 +151,8 @@ plugin.tx_terfe2 {
like.typeNum = 4500
dislike.typeNum = 4501
activateNotification.typeNum = 4502
deactivateNotification.typeNum = 4503
}
const.page.ter_fe = 1
......@@ -160,6 +160,14 @@ dislike < like
dislike.typeNum = {$plugin.tx_terfe2.dislike.typeNum}
dislike.10.switchableControllerActions.Extension.1 = disLike
activateNotification < like
activateNotification.typeNum = {$plugin.tx_terfe2.activateNotification.typeNum}
activateNotification.10.switchableControllerActions.Extension.1 = activateNotification
deactivateNotification < like
deactivateNotification.typeNum = {$plugin.tx_terfe2.deactivateNotification.typeNum}
deactivateNotification.10.switchableControllerActions.Extension.1 = deactivateNotification
plugin.tx_terfe2_rating {
features.requireCHashArgumentForActionArguments = 0
}
......
......@@ -155,6 +155,20 @@
</f:if>
</f:else>
</f:if>
<f:security.ifAuthenticated>
<f:if condition="{notification}">
<f:then>
<button class="btn btn-success btn-block" data-rating-type="deactivateNotification" data-rating-extension="{extension.uid}" title="Do not notify me anymore of new extension releases">
<strong><i class="fa fa-bell"></i> Notify me via email on new releases</strong>
</button>
</f:then>
<f:else>
<button class="btn btn-danger btn-block" data-rating-type="activateNotification" data-rating-extension="{extension.uid}" title="Notify me on new extension releases">
<strong><i class="fa fa-bell-slash"></i> Notify me via email on new releases</strong>
</button>
</f:else>
</f:if>
</f:security.ifAuthenticated>
<f:if condition="{extension.forgeLink}">
<f:link.external class="btn btn-secondary btn-block" rel="nofollow" uri="{extension.forgeLink}" target="_blank">
<i class="fa fa-hand-o-right"></i> Found an Issue?
......
Dear {notify.name},
there was just a new release of the extension "{notify.ext_key}" with version {extData.version}.
Upload comment:
{extData.uploadcomment -> f:format.nl2br()}
URL: https://extensions.typo3.org/extension/{notify.ext_key}
Download as ZIP: https://extensions.typo3.org/extension/download/{notify.ext_key}/{extData.version}/
<f:if condition="{notify.composer_name}">Composer command: composer update {notify.composer_name} --with-all-dependencies</f:if>
If you don't want to get notified anymore, go to https://extensions.typo3.org/extension/{notify.ext_key}, login and deactivate the notifications for this extension.
Best regards,
Your typo3.org maintenance team
--
This is an automatic message from the typo3.org system
Contact us: https://typo3.org/teams-committees/typo3org/ or just reply to this email
......@@ -78,6 +78,22 @@ jQuery(document).ready(function ($) {
likes--;
newRatingType = 'like';
}
if (ratingType === 'activateNotification') {
pageType = 4502;
removeClass = 'btn-danger';
addClass = 'btn-success';
subRemoveClass = 'fa-bell-slash';
subAddClass = 'fa-bell';
newRatingType = 'deactivateNotification';
}
if (ratingType === 'deactivateNotification') {
pageType = 4503;
removeClass = 'btn-success';
addClass = 'btn-danger';
subRemoveClass = 'fa-bell';
subAddClass = 'fa-bell-slash';
newRatingType = 'activateNotification';
}
$.ajax({
url: '/index.php?type=' + pageType,
data: {
......@@ -87,7 +103,11 @@ jQuery(document).ready(function ($) {
success: function (returnData) {
$(item).removeClass(removeClass).addClass(addClass);
$(item).data('rating-type', newRatingType);
item.lastChild.nodeValue = " " + likes.toLocaleString('en');
if (subRemoveClass && subAddClass) {
$(item).find('i').removeClass(subRemoveClass).addClass(subAddClass);
} else {
item.lastChild.nodeValue = " " + likes.toLocaleString('en');
}
}
});
})
......
......@@ -27,10 +27,10 @@ if (!defined('TYPO3_MODE')) {
'T3o.ter_fe2',
'Rating',
[
'Extension' => 'like,disLike'
'Extension' => 'like,disLike,activateNotification,deactivateNotification'
],
[
'Extension' => 'like,disLike'
'Extension' => 'like,disLike,activateNotification,deactivateNotification'
]
);
......
......@@ -20,6 +20,7 @@ CREATE TABLE tx_terfe2_domain_model_extension (
paypal_url varchar(255) DEFAULT '' NOT NULL,
expire int(11) unsigned default '0' NOT NULL,
likes int(11) unsigned default '0' NOT NULL,
notifications int(11) unsigned default '0' NOT NULL,
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
crdate int(11) unsigned DEFAULT '0' NOT NULL,
......@@ -222,7 +223,8 @@ CREATE TABLE tx_terfe2_domain_model_author (
);
CREATE TABLE fe_users (
liked_extensions int(11) unsigned DEFAULT '0' NOT NULL
liked_extensions int(11) unsigned DEFAULT '0' NOT NULL,
notified_extensions int(11) unsigned DEFAULT '0' NOT NULL
);
# ======================================================================
......@@ -238,6 +240,7 @@ CREATE TABLE tx_terfe2_extension_tag_mm (
KEY uid_foreign (uid_foreign)
);
# MM table for likes
CREATE TABLE `tx_terfe2_extension_feuser_mm` (
`uid_local` int(10) unsigned DEFAULT '0' NOT NULL,
`uid_foreign` int(10) unsigned DEFAULT '0' NOT NULL,
......@@ -247,3 +250,14 @@ CREATE TABLE `tx_terfe2_extension_feuser_mm` (
KEY `uid_local` (`uid_local`),
KEY `uid_foreign` (`uid_foreign`)
);
# MM table for notifications
CREATE TABLE `tx_terfe2_extension_feuser_notification_mm` (
`uid_local` int(10) unsigned DEFAULT '0' NOT NULL,
`uid_foreign` int(10) unsigned DEFAULT '0' NOT NULL,
`sorting` int(10) unsigned DEFAULT '0' NOT NULL,
`sorting_foreign` int(10) unsigned DEFAULT '0' NOT NULL,
KEY `uid_local` (`uid_local`),
KEY `uid_foreign` (`uid_foreign`)
);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment