diff --git a/.gitignore b/.gitignore index 96e5e4c52a3..3b5e5a59abd 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ misc/*.dat misc/user/logo-header.png misc/user/logo.png misc/user/logo.svg +misc/user/favicon.png php_errors.log piwik-min.js plugins/*.zip @@ -53,4 +54,4 @@ tests/PHPUnit/proxy/libs tests/PHPUnit/proxy/piwik.js tests/PHPUnit/proxy/plugins tests/PHPUnit/proxy/tests -config/*.config.ini.php \ No newline at end of file +config/*.config.ini.php diff --git a/core/Plugin/Controller.php b/core/Plugin/Controller.php index 3e6d4a8e119..af58f852ba1 100644 --- a/core/Plugin/Controller.php +++ b/core/Plugin/Controller.php @@ -606,6 +606,7 @@ protected function setBasicVariablesView($view) $customLogo = new CustomLogo(); $view->isCustomLogo = $customLogo->isEnabled(); + $view->customFavicon = $customLogo->getPathUserFavicon(); $view->logoHeader = \Piwik\Plugins\API\API::getInstance()->getHeaderLogoUrl(); $view->logoLarge = \Piwik\Plugins\API\API::getInstance()->getLogoUrl(); diff --git a/lang/en.json b/lang/en.json index 37df529d9b3..e47c3bf41d3 100644 --- a/lang/en.json +++ b/lang/en.json @@ -142,6 +142,7 @@ "LatestStableRelease": "The latest stable release", "LogoNotWriteableInstruction": "To use your custom logo instead of the default Piwik logo, give write permission to this directory: %1$s Piwik needs write access for your logos stored in the files %2$s.", "LogoUpload": "Select a Logo to upload", + "FaviconUpload": "Select a Favicon to upload", "LogoUploadHelp": "Please upload a file in %s formats with a minimum height of %s pixels.", "MenuDiagnostic": "Diagnostic", "MenuGeneralSettings": "General settings", diff --git a/plugins/CoreAdminHome/Controller.php b/plugins/CoreAdminHome/Controller.php index d59557e1b83..41fb7aab2d4 100644 --- a/plugins/CoreAdminHome/Controller.php +++ b/plugins/CoreAdminHome/Controller.php @@ -55,6 +55,7 @@ public function generalSettings() $view->branding = array('use_custom_logo' => $logo->isEnabled()); $view->logosWriteable = $logo->isCustomLogoWritable(); $view->pathUserLogo = CustomLogo::getPathUserLogo(); + $view->pathUserFavicon = CustomLogo::getPathUserFavicon(); $view->pathUserLogoSmall = CustomLogo::getPathUserLogoSmall(); $view->pathUserLogoSVG = CustomLogo::getPathUserSvgLogo(); $view->pathUserLogoDirectory = realpath(dirname($view->pathUserLogo) . '/'); @@ -260,9 +261,10 @@ public function uploadCustomLogo() Piwik::checkUserHasSuperUserAccess(); $logo = new CustomLogo(); - $success = $logo->copyUploadedLogoToFilesystem(); + $successLogo = $logo->copyUploadedLogoToFilesystem(); + $successFavicon = $logo->copyUploadedFaviconToFilesystem(); - if($success) { + if($successLogo || $successFavicon) { return '1'; } return '0'; diff --git a/plugins/CoreAdminHome/CustomLogo.php b/plugins/CoreAdminHome/CustomLogo.php index ca845fe4fbe..f4c95c49b3c 100644 --- a/plugins/CoreAdminHome/CustomLogo.php +++ b/plugins/CoreAdminHome/CustomLogo.php @@ -17,6 +17,7 @@ class CustomLogo { const LOGO_HEIGHT = 300; const LOGO_SMALL_HEIGHT = 100; + const FAVICON_HEIGHT = 32; public function getLogoUrl($pathOnly = false) { @@ -129,6 +130,11 @@ public static function getPathUserLogo() return self::rewritePath('misc/user/logo.png'); } + public static function getPathUserFavicon() + { + return self::rewritePath('misc/user/favicon.png'); + } + public static function getPathUserSvgLogo() { return self::rewritePath('misc/user/logo.svg'); @@ -146,20 +152,36 @@ protected static function rewritePath($path) public function copyUploadedLogoToFilesystem() { + $uploadFieldName = 'customLogo'; + + $success = $this->uploadImage($uploadFieldName, self::LOGO_SMALL_HEIGHT, $this->getPathUserLogoSmall()); + $success = $success && $this->uploadImage($uploadFieldName, self::LOGO_HEIGHT, $this->getPathUserLogo()); + + return $success; + } + + public function copyUploadedFaviconToFilesystem() + { + $uploadFieldName = 'customFavicon'; + + return $this->uploadImage($uploadFieldName, self::FAVICON_HEIGHT, $this->getPathUserFavicon()); + } - if (empty($_FILES['customLogo']) - || !empty($_FILES['customLogo']['error']) + private function uploadImage($uploadFieldName, $targetHeight, $userPath) + { + if (empty($_FILES[$uploadFieldName]) + || !empty($_FILES[$uploadFieldName]['error']) ) { return false; } - $file = $_FILES['customLogo']['tmp_name']; + $file = $_FILES[$uploadFieldName]['tmp_name']; if (!file_exists($file)) { return false; } list($width, $height) = getimagesize($file); - switch ($_FILES['customLogo']['type']) { + switch ($_FILES[$uploadFieldName]['type']) { case 'image/jpeg': $image = imagecreatefromjpeg($file); break; @@ -173,30 +195,21 @@ public function copyUploadedLogoToFilesystem() return false; } - $widthExpected = round($width * self::LOGO_HEIGHT / $height); - $smallWidthExpected = round($width * self::LOGO_SMALL_HEIGHT / $height); + $smallWidthExpected = round($width * $targetHeight / $height); - $logo = imagecreatetruecolor($widthExpected, self::LOGO_HEIGHT); - $logoSmall = imagecreatetruecolor($smallWidthExpected, self::LOGO_SMALL_HEIGHT); + $logoSmall = imagecreatetruecolor($smallWidthExpected, $targetHeight); // Handle transparency - $background = imagecolorallocate($logo, 0, 0, 0); $backgroundSmall = imagecolorallocate($logoSmall, 0, 0, 0); - imagecolortransparent($logo, $background); imagecolortransparent($logoSmall, $backgroundSmall); - if ($_FILES['customLogo']['type'] == 'image/png') { - imagealphablending($logo, false); + if ($_FILES[$uploadFieldName]['type'] == 'image/png') { imagealphablending($logoSmall, false); - imagesavealpha($logo, true); imagesavealpha($logoSmall, true); } - imagecopyresized($logo, $image, 0, 0, 0, 0, $widthExpected, self::LOGO_HEIGHT, $width, $height); - imagecopyresized($logoSmall, $image, 0, 0, 0, 0, $smallWidthExpected, self::LOGO_SMALL_HEIGHT, $width, $height); - - imagepng($logo, PIWIK_DOCUMENT_ROOT . '/' . $this->getPathUserLogo(), 3); - imagepng($logoSmall, PIWIK_DOCUMENT_ROOT . '/' . $this->getPathUserLogoSmall(), 3); + imagecopyresized($logoSmall, $image, 0, 0, 0, 0, $smallWidthExpected, $targetHeight, $width, $height); + imagepng($logoSmall, PIWIK_DOCUMENT_ROOT . '/' . $userPath, 3); return true; } diff --git a/plugins/CoreAdminHome/javascripts/generalSettings.js b/plugins/CoreAdminHome/javascripts/generalSettings.js index 30483202f4e..867cdc60d06 100644 --- a/plugins/CoreAdminHome/javascripts/generalSettings.js +++ b/plugins/CoreAdminHome/javascripts/generalSettings.js @@ -55,10 +55,14 @@ function isCustomLogoEnabled() { } function refreshCustomLogo() { - var imageDiv = $("#currentLogo"); - if (imageDiv && imageDiv.attr("src")) { - var logoUrl = imageDiv.attr("src").split("?")[0]; - imageDiv.attr("src", logoUrl + "?" + (new Date()).getTime()); + var selectors = ['#currentLogo', '#currentFavicon']; + var index; + for (index = 0; index < selectors.length; index++) { + var imageDiv = $(selectors[index]); + if (imageDiv && imageDiv.attr("src")) { + var logoUrl = imageDiv.attr("src").split("?")[0]; + imageDiv.attr("src", logoUrl + "?" + (new Date()).getTime()); + } } } @@ -122,7 +126,10 @@ $(document).ready(function () { submittingForm.attr("target", frameName); }); - $('#customLogo').change(function () {$("#logoUploadForm").submit()}); + $('#customLogo,#customFavicon').change(function () { + $("#logoUploadForm").submit(); + $(this).val(''); + }); // trusted hosts event handling var trustedHostSettings = $('#trustedHostSettings'); diff --git a/plugins/CoreAdminHome/templates/generalSettings.twig b/plugins/CoreAdminHome/templates/generalSettings.twig index bed62b3ac7d..78b2f87f7a7 100644 --- a/plugins/CoreAdminHome/templates/generalSettings.twig +++ b/plugins/CoreAdminHome/templates/generalSettings.twig @@ -235,18 +235,31 @@