diff options
20 files changed, 639 insertions, 28 deletions
diff --git a/plugins/Feedback/Controller.php b/plugins/Feedback/Controller.php index 73fa5e346a..5fa8a94023 100644 --- a/plugins/Feedback/Controller.php +++ b/plugins/Feedback/Controller.php @@ -8,17 +8,16 @@ */ namespace Piwik\Plugins\Feedback; -use Piwik\Common; -use Piwik\Container\StaticContainer; use Piwik\Date; -use Piwik\Option; +use Piwik\View; use Piwik\Piwik; +use Piwik\Common; use Piwik\Version; -use Piwik\View; +use Piwik\Container\StaticContainer; +use Piwik\Plugins\Feedback\ReferReminder; +use Piwik\Plugins\Feedback\FeedbackReminder; +use Piwik\DataTable\Renderer\Json; -/** - * - */ class Controller extends \Piwik\Plugin\Controller { function index() @@ -37,12 +36,34 @@ class Controller extends \Piwik\Plugin\Controller public function updateFeedbackReminderDate() { Piwik::checkUserIsNotAnonymous(); + $nextReminder = Common::getRequestVar('nextReminder'); + if ($nextReminder !== Feedback::NEVER_REMIND_ME_AGAIN) { $nextReminder = Date::now()->getStartOfDay()->addDay($nextReminder)->toString('Y-m-d'); } - $optionKey = 'Feedback.nextFeedbackReminder.' . Piwik::getCurrentUserLogin(); - Option::set($optionKey, $nextReminder); + $feedbackReminder = new FeedbackReminder(); + $feedbackReminder->setUserOption($nextReminder); + + Json::sendHeaderJSON(); + return json_encode(['Next reminder date: ' . $nextReminder]); + } + + public function updateReferReminderDate() + { + Piwik::checkUserIsNotAnonymous(); + + $nextReminder = Common::getRequestVar('nextReminder'); + + if ($nextReminder !== Feedback::NEVER_REMIND_ME_AGAIN) { + $nextReminder = Date::now()->getStartOfDay()->addDay($nextReminder)->toString('Y-m-d'); + } + + $referReminder = new ReferReminder(); + $referReminder->setUserOption($nextReminder); + + Json::sendHeaderJSON(); + return json_encode(['Next reminder date: ' . $nextReminder]); } } diff --git a/plugins/Feedback/Feedback.php b/plugins/Feedback/Feedback.php index 2cad4d77de..dbbd2dd7ad 100644 --- a/plugins/Feedback/Feedback.php +++ b/plugins/Feedback/Feedback.php @@ -8,12 +8,12 @@ */ namespace Piwik\Plugins\Feedback; -use Piwik\Common; use Piwik\Date; -use Piwik\Option; +use Piwik\View; use Piwik\Piwik; +use Piwik\Common; use Piwik\Plugins\UsersManager\Model; -use Piwik\View; +use Piwik\Plugins\Feedback\FeedbackReminder; /** * @@ -31,7 +31,7 @@ class Feedback extends \Piwik\Plugin 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', 'AssetManager.getJavaScriptFiles' => 'getJsFiles', 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', - 'Controller.CoreHome.index.end' => 'renderFeedbackPopup' + 'Controller.CoreHome.index.end' => 'renderViewsAndAddToPage' ); } @@ -40,6 +40,7 @@ class Feedback extends \Piwik\Plugin $stylesheets[] = "plugins/Feedback/stylesheets/feedback.less"; $stylesheets[] = "plugins/Feedback/angularjs/ratefeature/ratefeature.directive.less"; $stylesheets[] = "plugins/Feedback/angularjs/feedback-popup/feedback-popup.directive.less"; + $stylesheets[] = "plugins/Feedback/angularjs/refer-banner/refer-banner.directive.less"; } public function getJsFiles(&$jsFiles) @@ -49,11 +50,14 @@ class Feedback extends \Piwik\Plugin $jsFiles[] = "plugins/Feedback/angularjs/ratefeature/ratefeature.directive.js"; $jsFiles[] = "plugins/Feedback/angularjs/feedback-popup/feedback-popup.controller.js"; $jsFiles[] = "plugins/Feedback/angularjs/feedback-popup/feedback-popup.directive.js"; + $jsFiles[] = "plugins/Feedback/angularjs/refer-banner/refer-banner.directive.js"; + $jsFiles[] = "plugins/Feedback/angularjs/refer-banner/refer-banner.controller.js"; } public function getClientSideTranslationKeys(&$translationKeys) { $translationKeys[] = 'Feedback_ThankYou'; + $translationKeys[] = 'Feedback_ThankYouForSpreading'; $translationKeys[] = 'Feedback_RateFeatureTitle'; $translationKeys[] = 'Feedback_RateFeatureThankYouTitle'; $translationKeys[] = 'Feedback_RateFeatureLeaveMessageLike'; @@ -64,17 +68,84 @@ class Feedback extends \Piwik\Plugin $translationKeys[] = 'Feedback_PleaseLeaveExternalReviewForMatomo'; $translationKeys[] = 'Feedback_RemindMeLater'; $translationKeys[] = 'Feedback_NeverAskMeAgain'; + $translationKeys[] = 'Feedback_ReferMatomo'; + $translationKeys[] = 'Feedback_ReferBannerTitle'; + $translationKeys[] = 'Feedback_ReferBannerLonger'; + $translationKeys[] = 'Feedback_ReferBannerSocialShareText'; + $translationKeys[] = 'Feedback_ReferBannerEmailShareSubject'; + $translationKeys[] = 'Feedback_ReferBannerEmailShareBody'; $translationKeys[] = 'General_Ok'; $translationKeys[] = 'General_Cancel'; } - public function renderFeedbackPopup(&$pageHtml) + public function renderViewsAndAddToPage(&$pageHtml) + { + $feedbackPopopView = $this->renderFeedbackPopup(); + $referBannerView = $this->renderReferBanner(); + + $views = [$feedbackPopopView, $referBannerView]; + $implodedViews = implode('', $views); + + $endOfBody = strpos($pageHtml, '</body>'); + $pageHtml = substr_replace($pageHtml, $implodedViews, $endOfBody, 0); + } + + public function renderFeedbackPopup() { $popupView = new View('@Feedback/feedbackPopup'); $popupView->promptForFeedback = (int)$this->getShouldPromptForFeedback(); - $popupHtml = $popupView->render(); - $endOfBody = strpos($pageHtml, "</body>"); - $pageHtml = substr_replace($pageHtml, $popupHtml, $endOfBody, 0); + + return $popupView->render(); + } + + public function renderReferBanner() + { + $referBannerView = new View('@Feedback/referBanner'); + $referBannerView->showReferBanner = (int) $this->showReferBanner(); + + return $referBannerView->render(); + } + + public function showReferBanner() + { + if (Piwik::isUserIsAnonymous()) { + return false; + } + + if (!Piwik::hasUserSuperUserAccess()) { + return false; + } + + if ($this->isDisabledInTestMode()) { + return false; + } + + $shouldShowReferBanner = true; + + /** + * @internal + */ + Piwik::postEvent('Feedback.showReferBanner', [&$shouldShowReferBanner]); + + if (!$shouldShowReferBanner) { + return false; + } + + $referReminder = new ReferReminder(); + $nextReminderDate = $referReminder->getUserOption(); + + if ($nextReminderDate === false) { + return true; + } + + if ($nextReminderDate === self::NEVER_REMIND_ME_AGAIN) { + return false; + } + + $now = Date::now()->getTimestamp(); + $nextReminderDate = Date::factory($nextReminderDate); + + return $nextReminderDate->getTimestamp() <= $now; } public function getShouldPromptForFeedback() @@ -88,9 +159,8 @@ class Feedback extends \Piwik\Plugin return false; } - $login = Piwik::getCurrentUserLogin(); - $feedbackReminderKey = 'Feedback.nextFeedbackReminder.' . Piwik::getCurrentUserLogin(); - $nextReminderDate = Option::get($feedbackReminderKey); + $feedbackReminder = new FeedbackReminder(); + $nextReminderDate = $feedbackReminder->getUserOption(); if ($nextReminderDate === self::NEVER_REMIND_ME_AGAIN) { return false; @@ -98,7 +168,7 @@ class Feedback extends \Piwik\Plugin if ($nextReminderDate === false) { $model = new Model(); - $user = $model->getUser($login); + $user = $model->getUser(Piwik::getCurrentUserLogin()); if (empty($user['date_registered'])) { return false; } diff --git a/plugins/Feedback/FeedbackReminder.php b/plugins/Feedback/FeedbackReminder.php new file mode 100644 index 0000000000..64b8827496 --- /dev/null +++ b/plugins/Feedback/FeedbackReminder.php @@ -0,0 +1,34 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Feedback; + +use Piwik\Piwik; +use Piwik\Option; + +class FeedbackReminder +{ + public $userLogin; + public $option; + + public function __construct() + { + $this->userLogin = Piwik::getCurrentUserLogin(); + $this->option = 'Feedback.nextFeedbackReminder'; + } + + public function getUserOption() + { + return Option::get("{$this->option}.{$this->userLogin}"); + } + + public function setUserOption($value) + { + Option::set("{$this->option}.{$this->userLogin}", $value); + } +} diff --git a/plugins/Feedback/ReferReminder.php b/plugins/Feedback/ReferReminder.php new file mode 100644 index 0000000000..b6cfa46c3b --- /dev/null +++ b/plugins/Feedback/ReferReminder.php @@ -0,0 +1,34 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Feedback; + +use Piwik\Piwik; +use Piwik\Option; + +class ReferReminder +{ + public $userLogin; + public $option; + + public function __construct() + { + $this->userLogin = Piwik::getCurrentUserLogin(); + $this->option = 'Feedback.nextReferReminder'; + } + + public function getUserOption() + { + return Option::get("{$this->option}.{$this->userLogin}"); + } + + public function setUserOption($value) + { + Option::set("{$this->option}.{$this->userLogin}", $value); + } +} diff --git a/plugins/Feedback/angularjs/feedback-popup/feedback-popup.directive.html b/plugins/Feedback/angularjs/feedback-popup/feedback-popup.directive.html index 28be4b3f3b..ef48a83efe 100644 --- a/plugins/Feedback/angularjs/feedback-popup/feedback-popup.directive.html +++ b/plugins/Feedback/angularjs/feedback-popup/feedback-popup.directive.html @@ -1,9 +1,9 @@ <div ng-controller="FeedbackPopupController"> - <div class="feedbackPopup ui-confirm" - piwik-dialog="feedbackPopup.dialog.show" - yes="feedbackPopup.remindMeLater()" + <div class="feedbackPopup ui-confirm" + piwik-dialog="feedbackPopup.dialog.show" + yes="feedbackPopup.remindMeLater()" no="feedbackPopup.dontShowAgain()" - close="feedbackPopup.remindMeLater()" + close="" > <div class="intro"> diff --git a/plugins/Feedback/angularjs/refer-banner/refer-banner.controller.js b/plugins/Feedback/angularjs/refer-banner/refer-banner.controller.js new file mode 100644 index 0000000000..fb18a6b7ff --- /dev/null +++ b/plugins/Feedback/angularjs/refer-banner/refer-banner.controller.js @@ -0,0 +1,99 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link http://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +(function () { + angular.module('piwikApp').controller('ReferBannerController', ReferBannerController); + + ReferBannerController.$inject = ['$scope']; + + function ReferBannerController($scope) { + var setNextReminder = function(nextReminder) { + var ajaxHandler = new ajaxHelper(); + ajaxHandler.addParams({'module': 'Feedback', 'action': 'updateReferReminderDate'}, 'GET'); + ajaxHandler.addParams({'nextReminder': nextReminder}, 'POST'); + ajaxHandler.send(); + }; + + var closeBanner = function() { + $scope.referBanner.show = false; + + if ($scope.referBanner.shared === false) { + setNextReminder(6 * 30); + } + }; + + var share = function() { + $scope.referBanner.showThanks = true; + $scope.referBanner.shared = true; + + setNextReminder(-1); + } + + $scope.socialUrl = function (type) { + var text = _pk_translate('Feedback_ReferBannerSocialShareText'); + var url = 'https://matomo.org/google-owns-your-data/?pk_campaign=share&pk_kwd=onpremise'; + + if (type === 'twitter') { + var base = 'https://twitter.com/intent/tweet?'; + + var params = { 'text': text, 'url': url}; + var paramString = ''; + for (const param in params) { + paramString += param + '=' + encodeURIComponent(params[param]) + '&'; + } + + return base + paramString.slice(0, -1); + } + + if (type === 'facebook') { + var base = 'https://www.facebook.com/sharer.php?'; + + var params = { 't': text, 'u': url}; + var paramString = ''; + for (const param in params) { + paramString += param + '=' + encodeURIComponent(params[param]) + '&'; + } + + return base + paramString.slice(0, -1); + } + + if (type === 'linkedin') { + var base = 'https://www.linkedin.com/sharing/share-offsite/?'; + + var params = { 'url': url }; + var paramString = ''; + for (const param in params) { + paramString += param + '=' + encodeURIComponent(params[param]) + '&'; + } + + return base + paramString.slice(0, -1); + } + + return '#'; + }; + + $scope.referEmail = function () { + var subject = _pk_translate('Feedback_ReferBannerEmailShareSubject'); + var body = _pk_translate('Feedback_ReferBannerEmailShareBody'); + + return encodeURI('mailto:YOUR_FRIEND@EMAIL.ADDRESS?subject=' + subject + '&body=' + body); + } + + var init = function() { + $scope.referBanner.show = false; + $scope.referBanner.showThanks = false; + $scope.referBanner.closeBanner = closeBanner; + $scope.referBanner.share = share; + $scope.referBanner.shared = false; + + if ($scope.showReferBanner === 1) { + $scope.referBanner.show = true; + }; + }; + + init(); + } +})(); diff --git a/plugins/Feedback/angularjs/refer-banner/refer-banner.directive.html b/plugins/Feedback/angularjs/refer-banner/refer-banner.directive.html new file mode 100644 index 0000000000..d3ce1e862a --- /dev/null +++ b/plugins/Feedback/angularjs/refer-banner/refer-banner.directive.html @@ -0,0 +1,45 @@ +<div ng-controller="ReferBannerController"> + <div class="refer-banner" ng-show="referBanner.show"> + <div class="flex items-center justify-center h-full" id="default-text"> + <div class="flex-none"></div> + <div class="flex items-center justify-center flex-grow"> + <div> + {{ 'Feedback_ReferBannerTitle'|translate }} + <span class="hide-on-med-and-down">{{ 'Feedback_ReferBannerLonger'|translate }}</span> + </div> + + <div> + <a ng-href="{{ referEmail() }}" ng-click="referBanner.share()" target="_blank" class="btn premiumDownloadPiwik" rel="noreferrer noopener" id="send-email" style="width: max-content;"> + {{ 'Feedback_ReferMatomo'|translate }} + </a> + </div> + + <div class="hide-on-med-and-down flex items-center"> + <div>or share us on</div> + <div class="flex items-center"> + <a ng-href="{{ socialUrl('twitter') }}" ng-click="referBanner.share()" class="share-button" target="_blank" rel="noreferrer noopener"> + <ng-include src="'plugins/Feedback/images/twitter_logo.svg'" /> + </a> + <a ng-href="{{ socialUrl('facebook') }}" ng-click="referBanner.share()" class="share-button" target="_blank" rel="noreferrer noopener"> + <ng-include src="'plugins/Feedback/images/facebook_logo.svg'" /> + </a> + <a ng-href="{{ socialUrl('linkedin') }}" ng-click="referBanner.share()" class="share-button" target="_blank" rel="noreferrer noopener"> + <ng-include src="'plugins/Feedback/images/linkedin_logo.svg'" /> + </a> + <a ng-show="{{ false }}" href="{{ socialUrl('mastodon') }}" ng-click="referBanner.share()" class="share-button" target="_blank" rel="noreferrer noopener"> + <ng-include src="'plugins/Feedback/images/mastodon_logo.svg'" /> + </a> + </div> + </div> + </div> + + <div title="Close" class="icon-close flex-none" ng-click="referBanner.closeBanner()"></div> + </div> + </div> + + <div class="ui-confirm ratefeatureDialog" piwik-dialog="referBanner.showThanks" yes=""> + <h2>{{ 'Feedback_ThankYouForSpreading'|translate }}</h2> + + <input type="button" value="{{ 'General_Ok'|translate }}" role="yes"/> + </div> +</div> diff --git a/plugins/Feedback/angularjs/refer-banner/refer-banner.directive.js b/plugins/Feedback/angularjs/refer-banner/refer-banner.directive.js new file mode 100644 index 0000000000..4c14a49e3f --- /dev/null +++ b/plugins/Feedback/angularjs/refer-banner/refer-banner.directive.js @@ -0,0 +1,28 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link http://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +/** + * Usage: + * <div piwik-refer-banner> + */ +(function () { + angular.module('piwikApp').directive('piwikReferBanner', piwikReferBanner); + + piwikReferBanner.$inject = ['piwik']; + + function piwikReferBanner(piwik){ + return { + restrict: 'A', + scope: { + showReferBanner: '<' + }, + templateUrl: 'plugins/Feedback/angularjs/refer-banner/refer-banner.directive.html?cb=' + piwik.cacheBuster, + controller: 'ReferBannerController', + controllerAs: 'referBanner', + }; + } +})();
\ No newline at end of file diff --git a/plugins/Feedback/angularjs/refer-banner/refer-banner.directive.less b/plugins/Feedback/angularjs/refer-banner/refer-banner.directive.less new file mode 100644 index 0000000000..829348231d --- /dev/null +++ b/plugins/Feedback/angularjs/refer-banner/refer-banner.directive.less @@ -0,0 +1,69 @@ +@media only screen and (max-width: 600px) { + .refer-banner { + min-height: 48px; + height: auto !important; + font-size: 13px; + } +} + +.flex { + display: flex; +} + +.flex-grow { + flex-grow: 1; +} + +.flex-none { + flex: none; +} + +.items-center { + align-items: center; +} + +.justify-center { + justify-content: center; +} + +.h-full { + height: 100%; +} + +.refer-banner { + height: 48px; + position: fixed; + width: 100%; + text-align: center; + color: #fff; + bottom: 0; + background: #263238; + clear: both; + z-index: 9999; +} + +.refer-banner .icon-close { + background: #263238; + font-size: 12px; + color: #fff; + cursor: pointer; + width: 18px; + margin-right: 4px; +} + +.refer-banner .piwikOrgLink { + color: #fff; + text-decoration: underline; +} + +.refer-banner .share-button { + color:#fff; + display:inline-block; + width:20px; + margin-left: 4px; +} + +.refer-banner .signUpPiwik, +.refer-banner .premiumDownloadPiwik { + margin: 5px; +} diff --git a/plugins/Feedback/images/facebook_logo.svg b/plugins/Feedback/images/facebook_logo.svg new file mode 100644 index 0000000000..54a49626e0 --- /dev/null +++ b/plugins/Feedback/images/facebook_logo.svg @@ -0,0 +1 @@ +<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>
\ No newline at end of file diff --git a/plugins/Feedback/images/linkedin_logo.svg b/plugins/Feedback/images/linkedin_logo.svg new file mode 100644 index 0000000000..6a5826451d --- /dev/null +++ b/plugins/Feedback/images/linkedin_logo.svg @@ -0,0 +1 @@ +<svg fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>
\ No newline at end of file diff --git a/plugins/Feedback/images/mastodon_logo.svg b/plugins/Feedback/images/mastodon_logo.svg new file mode 100644 index 0000000000..e19e492758 --- /dev/null +++ b/plugins/Feedback/images/mastodon_logo.svg @@ -0,0 +1 @@ +<svg fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M23.193 7.88c0-5.207-3.411-6.733-3.411-6.733C18.062.357 15.108.025 12.041 0h-.076c-3.069.025-6.02.357-7.74 1.147 0 0-3.412 1.526-3.412 6.732 0 1.193-.023 2.619.015 4.13.124 5.092.934 10.11 5.641 11.355 2.17.574 4.034.695 5.536.612 2.722-.15 4.25-.972 4.25-.972l-.09-1.975s-1.945.613-4.13.54c-2.165-.075-4.449-.234-4.799-2.892a5.5 5.5 0 0 1-.048-.745s2.125.52 4.818.643c1.646.075 3.19-.097 4.758-.283 3.007-.359 5.625-2.212 5.954-3.905.517-2.665.475-6.508.475-6.508zm-4.024 6.709h-2.497v-6.12c0-1.29-.543-1.944-1.628-1.944-1.2 0-1.802.776-1.802 2.313v3.349h-2.484v-3.35c0-1.537-.602-2.313-1.802-2.313-1.085 0-1.628.655-1.628 1.945v6.119H4.831V8.285c0-1.29.328-2.314.987-3.07.68-.759 1.57-1.147 2.674-1.147 1.278 0 2.246.491 2.886 1.474L12 6.585l.622-1.043c.64-.983 1.608-1.474 2.886-1.474 1.104 0 1.994.388 2.674 1.146.658.757.986 1.781.986 3.07v6.305z"/></svg>
\ No newline at end of file diff --git a/plugins/Feedback/images/twitter_logo.svg b/plugins/Feedback/images/twitter_logo.svg new file mode 100644 index 0000000000..49a98867fa --- /dev/null +++ b/plugins/Feedback/images/twitter_logo.svg @@ -0,0 +1 @@ +<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/></svg>
\ No newline at end of file diff --git a/plugins/Feedback/lang/en.json b/plugins/Feedback/lang/en.json index 9c7182a8c4..de60599b62 100644 --- a/plugins/Feedback/lang/en.json +++ b/plugins/Feedback/lang/en.json @@ -14,6 +14,7 @@ "RateFeatureTitle": "Do you like the '%s' feature? Please rate and leave a comment", "SendFeedback": "Send Feedback", "ThankYou": "Thank you for helping us to make Matomo better!", + "ThankYouForSpreading": "Thank you for spreading the word and creating a safer web", "TopLinkTooltip": "Tell us what you think, or request Professional Support.", "ViewAnswersToFAQ": "View answers to %1$sFrequently Asked Questions%2$s", "FAQs": "FAQs", @@ -41,6 +42,12 @@ "RemoveOtherLabel": "I want to see my 'Others' data", "PurgeOldData": "I want to remove some old data", "SearchHelpResources": "Search matomo.org help resources", - "PopularHelpTopics": "Popular help topics" + "PopularHelpTopics": "Popular help topics", + "ReferMatomo": "Refer Matomo", + "ReferBannerTitle": "Don't let your friend's data end up in the wrong hands!", + "ReferBannerLonger": "Refer them to Matomo Analytics now to take back control!", + "ReferBannerEmailShareSubject": "Refer them to Matomo Analytics now to take back control!", + "ReferBannerEmailShareBody": "I choose Matomo, an ethical alternative to Google Analytics that gives me 100% data ownership and protects the data of my website visitors.\r\nI’m sharing this message in the hope that you too will take back the power from Google and get complete ownership of your own data.\r\n\r\nCheck out Matomo at https://matomo.org", + "ReferBannerSocialShareText": "If you’re using Google Analytics, stay in control by switching to an ethical alternative like Matomo now!" } } diff --git a/plugins/Feedback/templates/referBanner.twig b/plugins/Feedback/templates/referBanner.twig new file mode 100644 index 0000000000..628d56c45c --- /dev/null +++ b/plugins/Feedback/templates/referBanner.twig @@ -0,0 +1 @@ +<div piwik-refer-banner show-refer-banner="{{ showReferBanner }}"></div> diff --git a/plugins/Feedback/tests/Fixtures/ReferBannerFixture.php b/plugins/Feedback/tests/Fixtures/ReferBannerFixture.php new file mode 100644 index 0000000000..7e461bdb48 --- /dev/null +++ b/plugins/Feedback/tests/Fixtures/ReferBannerFixture.php @@ -0,0 +1,25 @@ +<?php + + +namespace Piwik\Plugins\Feedback\tests\Fixtures; + +use Piwik\Date; +use Piwik\Option; +use Piwik\Tests\Fixtures\UITestFixture; + +class ReferBannerFixture extends UITestFixture +{ + public function setUp(): void + { + parent::setUp(); + $yesterday = Date::yesterday(); + Option::set('Feedback.nextReferReminder.superUserLogin', $yesterday->toString('Y-m-d')); + } + + public function tearDown(): void + { + parent::tearDown(); + Option::delete('Feedback.nextReferReminder.superUserLogin'); + } + +}
\ No newline at end of file diff --git a/plugins/Feedback/tests/Integration/ControllerTest.php b/plugins/Feedback/tests/Integration/ControllerTest.php index 533dc533f5..a1699cf2bd 100644 --- a/plugins/Feedback/tests/Integration/ControllerTest.php +++ b/plugins/Feedback/tests/Integration/ControllerTest.php @@ -62,7 +62,6 @@ class ControllerTest extends IntegrationTestCase ); } - public function test_updateFeedbackReminder_addNinetyDays() { $_POST['nextReminder'] = '90'; @@ -88,4 +87,30 @@ class ControllerTest extends IntegrationTestCase FakeAccess::$superUser = false; $this->controller->updateFeedbackReminderDate(); } -}
\ No newline at end of file + + public function test_updateReferReminder_add180Days() + { + $_POST['nextReminder'] = '180'; + $this->controller->updateReferReminderDate(); + + $option = Option::get('Feedback.nextReferReminder.user1'); + $this->assertEquals($option, '2019-11-27'); + } + + public function test_updateReferReminder_neverAgain() + { + $_POST['nextReminder'] = '-1'; + $this->controller->updateReferReminderDate(); + + $option = Option::get('Feedback.nextReferReminder.user1'); + $this->assertEquals($option, '-1'); + } + + public function test_updateReferReminder_notLoggedIn() + { + $this->expectException(NoAccessException::class); + FakeAccess::$identity = null; + FakeAccess::$superUser = false; + $this->controller->updateReferReminderDate(); + } +} diff --git a/plugins/Feedback/tests/Integration/ReferBannerTest.php b/plugins/Feedback/tests/Integration/ReferBannerTest.php new file mode 100644 index 0000000000..b7b86aeae3 --- /dev/null +++ b/plugins/Feedback/tests/Integration/ReferBannerTest.php @@ -0,0 +1,116 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link http://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +namespace Piwik\Plugins\Feedback\tests\Unit; + + +use Piwik\Date; +use Piwik\Option; +use Piwik\Plugins\Feedback\Feedback; +use Piwik\Plugins\UsersManager\Model; +use Piwik\Tests\Framework\Mock\FakeAccess; +use Piwik\Tests\Framework\TestCase\IntegrationTestCase; + +class ReferBannerTest extends IntegrationTestCase +{ + /** @var Feedback */ + private $feedback; + + /** @var Model */ + private $userModel; + + public function setUp(): void + { + parent::setUp(); + + $this->feedback = $this->createPartialMock(Feedback::class, ['isDisabledInTestMode']); + $this->feedback->method('isDisabledInTestMode')->willReturn(false); + + $this->userModel = new Model(); + $this->userModel->addUser( + 'user1', + 'a98732d98732', + 'user1@example.com', + '2019-03-03', + 'super' + ); + FakeAccess::$identity = 'user1'; + FakeAccess::$superUser = false; + } + + public function tearDown(): void + { + Option::deleteLike('Feedback.nextReferReminder.%'); + $this->userModel->deleteUserOnly('user1'); + + parent::tearDown(); + } + + public function provideContainerConfig() + { + return array( + 'Piwik\Access' => new FakeAccess() + ); + } + + + public function test_shouldNotShowReferBannerTo_AnonymousUser() + { + FakeAccess::$identity = ''; + + $this->assertFalse($this->feedback->showReferBanner()); + } + + public function test_shouldNotShowReferBannerTo_NotSuperUser() + { + FakeAccess::$identity = 'user1'; + + $this->assertFalse($this->feedback->showReferBanner()); + } + + public function test_shouldShowReferBannerTo_SuperUser() + { + FakeAccess::$identity = 'super'; + FakeAccess::$superUser = true; + + $this->assertTrue($this->feedback->showReferBanner()); + } + + public function test_shouldNotShowReferBanner_ifNeverRemindOn() + { + FakeAccess::$identity = 'super'; + FakeAccess::$superUser = true; + Option::set('Feedback.nextReferReminder.super', '-1'); + + $this->assertFalse($this->feedback->showReferBanner()); + } + + public function test_shouldNotShowReferBanner_ifNextReminderDateInTheFuture() + { + FakeAccess::$identity = 'super'; + FakeAccess::$superUser = true; + + Date::$now = strtotime('2021-01-01'); + $futureDate = Date::factory('2021-02-01')->toString('Y-m-d'); + Option::set('Feedback.nextReferReminder.super', $futureDate); + + $this->assertFalse($this->feedback->showReferBanner()); + } + + public function test_shouldShowReferBanner_ifNextReminderDateInThePast() + { + FakeAccess::$identity = 'super'; + FakeAccess::$superUser = true; + + Date::$now = strtotime('2021-01-01'); + $pastDate = Date::factory('2020-01-01')->toString('Y-m-d'); + Option::set('Feedback.nextReferReminder.super', $pastDate); + + $this->assertTrue($this->feedback->showReferBanner()); + } +} diff --git a/plugins/Feedback/tests/UI/ReferBanner_spec.js b/plugins/Feedback/tests/UI/ReferBanner_spec.js new file mode 100644 index 0000000000..7b0364f111 --- /dev/null +++ b/plugins/Feedback/tests/UI/ReferBanner_spec.js @@ -0,0 +1,30 @@ +/*! + * Matomo - free/libre analytics platform + * + * UsersManager screenshot tests. + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +describe("ReferBannerTest", function () { + this.timeout(0); + this.fixture = "Piwik\\Plugins\\Feedback\\tests\\Fixtures\\ReferBannerFixture"; + + var url = "?module=CoreHome&action=index&idSite=1&period=day&date=2019-07-11&forceFeedbackTest=1"; + + before(async function() { + await page.webpage.setViewport({ + width: 1250, + height: 768 + }); + }); + + it('should display popup when next reminder date is in past', async function () { + await page.goto(url); + await page.waitForNetworkIdle(); + + var banner = await page.waitFor('.refer-banner', { visible: true }); + expect(await banner.screenshot()).to.matchImage('feedback_popup'); + }); +}); diff --git a/plugins/Feedback/tests/UI/expected-screenshots/ReferBannerTest_feedback_popup.png b/plugins/Feedback/tests/UI/expected-screenshots/ReferBannerTest_feedback_popup.png new file mode 100644 index 0000000000..b33ed5d4c8 --- /dev/null +++ b/plugins/Feedback/tests/UI/expected-screenshots/ReferBannerTest_feedback_popup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de4ce7f20f82c2c70a2ff0587ec3e14f5d93869e12f9cd4a6ac057d9747c0bc2 +size 14151 |