]> source.dussan.org Git - nextcloud-server.git/commitdiff
Add occ command to set theming values
authorJulius Härtl <jus@bitgrid.net>
Wed, 23 Sep 2020 15:48:48 +0000 (17:48 +0200)
committerbackportbot[bot] <backportbot[bot]@users.noreply.github.com>
Thu, 24 Sep 2020 12:38:53 +0000 (12:38 +0000)
Signed-off-by: Julius Härtl <jus@bitgrid.net>
apps/theming/appinfo/info.xml
apps/theming/lib/Command/UpdateConfig.php [new file with mode: 0644]
apps/theming/lib/Controller/ThemingController.php
apps/theming/lib/ImageManager.php
apps/theming/lib/ThemingDefaults.php
lib/private/Server.php

index c2017c461e503de72461f0ac645792237bee0ac5..00f9f27fc84e7334e17e6855d71707210290db64 100644 (file)
@@ -25,4 +25,7 @@
                <admin>OCA\Theming\Settings\Admin</admin>
                <admin-section>OCA\Theming\Settings\Section</admin-section>
        </settings>
+       <commands>
+               <command>OCA\Theming\Command\UpdateConfig</command>
+       </commands>
 </info>
diff --git a/apps/theming/lib/Command/UpdateConfig.php b/apps/theming/lib/Command/UpdateConfig.php
new file mode 100644 (file)
index 0000000..7d61687
--- /dev/null
@@ -0,0 +1,135 @@
+<?php
+/**
+ * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Theming\Command;
+
+use OCA\Theming\ImageManager;
+use OCA\Theming\ThemingDefaults;
+use OCP\IConfig;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class UpdateConfig extends Command {
+       public const SUPPORTED_KEYS = [
+               'name', 'url', 'imprintUrl', 'privacyUrl', 'slogan', 'color'
+       ];
+
+       public const SUPPORTED_IMAGE_KEYS = [
+               'background', 'logo', 'favicon', 'logoheader'
+       ];
+
+       private $themingDefaults;
+       private $imageManager;
+       private $config;
+
+       public function __construct(ThemingDefaults $themingDefaults, ImageManager $imageManager, IConfig $config) {
+               parent::__construct();
+
+               $this->themingDefaults = $themingDefaults;
+               $this->imageManager = $imageManager;
+               $this->config = $config;
+       }
+
+       protected function configure() {
+               $this
+                       ->setName('theming:config')
+                       ->setDescription('Set theming app config values')
+                       ->addArgument(
+                               'key',
+                               InputArgument::OPTIONAL,
+                               'Key to update the theming app configuration (leave empty to get a list of all configured values)' . PHP_EOL .
+                               'One of: ' . implode(', ', self::SUPPORTED_KEYS)
+                       )
+                       ->addArgument(
+                               'value',
+                               InputArgument::OPTIONAL,
+                               'Value to set (leave empty to obtain the current value)'
+                       )
+                       ->addOption(
+                               'reset',
+                               'r',
+                               InputOption::VALUE_NONE,
+                               'Reset the given config key to default'
+                       );
+       }
+
+
+       protected function execute(InputInterface $input, OutputInterface $output): int {
+               $key = $input->getArgument('key');
+               $value = $input->getArgument('value');
+
+               if ($key === null) {
+                       $output->writeln('Current theming config:');
+                       foreach (self::SUPPORTED_KEYS as $key) {
+                               $value = $this->config->getAppValue('theming', $key, '');
+                               $output->writeln('- ' . $key . ': ' . $value . '');
+                       }
+                       foreach (self::SUPPORTED_IMAGE_KEYS as $key) {
+                               $value = $this->config->getAppValue('theming', $key . 'Mime', '');
+                               $output->writeln('- ' . $key . ': ' . $value . '');
+                       }
+                       return 0;
+               }
+
+               if (!in_array($key, self::SUPPORTED_KEYS, true)) {
+                       $output->writeln('<error>Invalid config key provided</error>');
+                       return 1;
+               }
+
+               if ($input->getOption('reset')) {
+                       $defaultValue = $this->themingDefaults->undo($key);
+                       $output->writeln('<info>Reset ' . $key . ' to ' . $defaultValue . '</info>');
+                       return 0;
+               }
+
+               if ($value === null) {
+                       $value = $this->config->getAppValue('theming', $key, '');
+                       if ($value !== '') {
+                               $output->writeln('<info>' . $key . ' is currently set to ' . $value . '</info>');
+                       } else {
+                               $output->writeln('<info>' . $key . ' is currently not set</info>');
+                       }
+                       return 0;
+               }
+
+               if (in_array($key, self::SUPPORTED_IMAGE_KEYS, true)) {
+                       if (file_exists(__DIR__ . $value)) {
+                               $value = __DIR__ . $value;
+                       }
+                       if (!file_exists($value)) {
+                               $output->writeln('<error>File could not be found: ' . $value . '</error>');
+                               return 1;
+                       }
+                       $value = $this->imageManager->updateImage($key, $value);
+                       $key = $key . 'Mime';
+               }
+
+               $this->themingDefaults->set($key, $value);
+               $output->writeln('<info>Updated ' . $key . ' to ' . $value . '</info>');
+
+               return 0;
+       }
+}
index 3ef5f0de506b53f98f72b39ab58ed7ab8005ebfd..56570794247c42f02977d20b2f578e415ff867da 100644 (file)
@@ -214,9 +214,6 @@ class ThemingController extends Controller {
         * @throws NotPermittedException
         */
        public function uploadImage(): DataResponse {
-               // logo / background
-               // new: favicon logo-header
-               //
                $key = $this->request->getParam('key');
                $image = $this->request->getUploadedFile('image');
                $error = null;
@@ -249,23 +246,14 @@ class ThemingController extends Controller {
                        );
                }
 
-               $name = '';
                try {
-                       $folder = $this->appData->getFolder('images');
-               } catch (NotFoundException $e) {
-                       $folder = $this->appData->newFolder('images');
-               }
-
-               $this->imageManager->delete($key);
-
-               $target = $folder->newFile($key);
-               $supportedFormats = $this->getSupportedUploadImageFormats($key);
-               $detectedMimeType = mime_content_type($image['tmp_name']);
-               if (!in_array($image['type'], $supportedFormats) || !in_array($detectedMimeType, $supportedFormats)) {
+                       $mime = $this->imageManager->updateImage($key, $image['tmp_name']);
+                       $this->themingDefaults->set($key . 'Mime', $mime);
+               } catch (\Exception $e) {
                        return new DataResponse(
                                [
                                        'data' => [
-                                               'message' => $this->l10n->t('Unsupported image type'),
+                                               'message' => $e->getMessage()
                                        ],
                                        'status' => 'failure',
                                ],
@@ -273,28 +261,7 @@ class ThemingController extends Controller {
                        );
                }
 
-               if ($key === 'background' && strpos($detectedMimeType, 'image/svg') === false) {
-                       // Optimize the image since some people may upload images that will be
-                       // either to big or are not progressive rendering.
-                       $newImage = @imagecreatefromstring(file_get_contents($image['tmp_name'], 'r'));
-
-                       $tmpFile = $this->tempManager->getTemporaryFile();
-                       $newWidth = imagesx($newImage) < 4096 ? imagesx($newImage) : 4096;
-                       $newHeight = imagesy($newImage) / (imagesx($newImage) / $newWidth);
-                       $outputImage = imagescale($newImage, $newWidth, $newHeight);
-
-                       imageinterlace($outputImage, 1);
-                       imagejpeg($outputImage, $tmpFile, 75);
-                       imagedestroy($outputImage);
-
-                       $target->putContent(file_get_contents($tmpFile, 'r'));
-               } else {
-                       $target->putContent(file_get_contents($image['tmp_name'], 'r'));
-               }
                $name = $image['name'];
-
-               $this->themingDefaults->set($key.'Mime', $image['type']);
-
                $cssCached = $this->scssCacher->process(\OC::$SERVERROOT, 'core/css/css-variables.scss', 'core');
 
                return new DataResponse(
@@ -311,24 +278,6 @@ class ThemingController extends Controller {
                );
        }
 
-       /**
-        * Returns a list of supported mime types for image uploads.
-        * "favicon" images are only allowed to be SVG when imagemagick with SVG support is available.
-        *
-        * @param string $key The image key, e.g. "favicon"
-        * @return array
-        */
-       private function getSupportedUploadImageFormats(string $key): array {
-               $supportedFormats = ['image/jpeg', 'image/png', 'image/gif',];
-
-               if ($key !== 'favicon' || $this->imageManager->shouldReplaceIcons() === true) {
-                       $supportedFormats[] = 'image/svg+xml';
-                       $supportedFormats[] = 'image/svg';
-               }
-
-               return $supportedFormats;
-       }
-
        /**
         * Revert setting to default value
         *
@@ -341,11 +290,6 @@ class ThemingController extends Controller {
                // reprocess server scss for preview
                $cssCached = $this->scssCacher->process(\OC::$SERVERROOT, 'core/css/css-variables.scss', 'core');
 
-               if (strpos($setting, 'Mime') !== -1) {
-                       $imageKey = str_replace('Mime', '', $setting);
-                       $this->imageManager->delete($imageKey);
-               }
-
                return new DataResponse(
                        [
                                'data' =>
index bf52fd8176229de5e12e2ae800534feeba7ec775..3fe76899dcdcbada245bb69d704c9950a971d1b7 100644 (file)
@@ -36,6 +36,7 @@ use OCP\Files\SimpleFS\ISimpleFolder;
 use OCP\ICacheFactory;
 use OCP\IConfig;
 use OCP\ILogger;
+use OCP\ITempManager;
 use OCP\IURLGenerator;
 
 class ImageManager {
@@ -52,27 +53,22 @@ class ImageManager {
        private $cacheFactory;
        /** @var ILogger */
        private $logger;
+       /** @var ITempManager */
+       private $tempManager;
 
-       /**
-        * ImageManager constructor.
-        *
-        * @param IConfig $config
-        * @param IAppData $appData
-        * @param IURLGenerator $urlGenerator
-        * @param ICacheFactory $cacheFactory
-        * @param ILogger $logger
-        */
        public function __construct(IConfig $config,
                                                                IAppData $appData,
                                                                IURLGenerator $urlGenerator,
                                                                ICacheFactory $cacheFactory,
-                                                               ILogger $logger
+                                                               ILogger $logger,
+                                                               ITempManager $tempManager
        ) {
                $this->config = $config;
                $this->appData = $appData;
                $this->urlGenerator = $urlGenerator;
                $this->cacheFactory = $cacheFactory;
                $this->logger = $logger;
+               $this->tempManager = $tempManager;
        }
 
        public function getImageUrl(string $key, bool $useSvg = true): string {
@@ -211,6 +207,62 @@ class ImageManager {
                }
        }
 
+       public function updateImage(string $key, string $tmpFile) {
+               $this->delete($key);
+
+               try {
+                       $folder = $this->appData->getFolder('images');
+               } catch (NotFoundException $e) {
+                       $folder = $this->appData->newFolder('images');
+               }
+
+               $target = $folder->newFile($key);
+               $supportedFormats = $this->getSupportedUploadImageFormats($key);
+               $detectedMimeType = mime_content_type($tmpFile);
+               if (!in_array($detectedMimeType, $supportedFormats, true)) {
+                       throw new \Exception('Unsupported image type');
+               }
+
+               if ($key === 'background' && strpos($detectedMimeType, 'image/svg') === false) {
+                       // Optimize the image since some people may upload images that will be
+                       // either to big or are not progressive rendering.
+                       $newImage = @imagecreatefromstring(file_get_contents($tmpFile));
+
+                       $tmpFile = $this->tempManager->getTemporaryFile();
+                       $newWidth = (int)(imagesx($newImage) < 4096 ? imagesx($newImage) : 4096);
+                       $newHeight = (int)(imagesy($newImage) / (imagesx($newImage) / $newWidth));
+                       $outputImage = imagescale($newImage, $newWidth, $newHeight);
+
+                       imageinterlace($outputImage, 1);
+                       imagejpeg($outputImage, $tmpFile, 75);
+                       imagedestroy($outputImage);
+
+                       $target->putContent(file_get_contents($tmpFile));
+               } else {
+                       $target->putContent(file_get_contents($tmpFile));
+               }
+
+               return $detectedMimeType;
+       }
+
+       /**
+        * Returns a list of supported mime types for image uploads.
+        * "favicon" images are only allowed to be SVG when imagemagick with SVG support is available.
+        *
+        * @param string $key The image key, e.g. "favicon"
+        * @return array
+        */
+       private function getSupportedUploadImageFormats(string $key): array {
+               $supportedFormats = ['image/jpeg', 'image/png', 'image/gif'];
+
+               if ($key !== 'favicon' || $this->shouldReplaceIcons() === true) {
+                       $supportedFormats[] = 'image/svg+xml';
+                       $supportedFormats[] = 'image/svg';
+               }
+
+               return $supportedFormats;
+       }
+
        /**
         * remove cached files that are not required any longer
         *
index e5680846627bfe69eddf603c4d9f81a44500e36b..3fdbc1a61ae2fde8b0b2152d34073460fb9e069a 100644 (file)
@@ -398,6 +398,7 @@ class ThemingDefaults extends \OC_Defaults {
                $this->config->deleteAppValue('theming', $setting);
                $this->increaseCacheBuster();
 
+               $returnValue = '';
                switch ($setting) {
                        case 'name':
                                $returnValue = $this->getEntity();
@@ -411,8 +412,11 @@ class ThemingDefaults extends \OC_Defaults {
                        case 'color':
                                $returnValue = $this->getColorPrimary();
                                break;
-                       default:
-                               $returnValue = '';
+                       case 'logo':
+                       case 'logoheader':
+                       case 'background':
+                       case 'favicon':
+                               $this->imageManager->delete($setting);
                                break;
                }
 
index 884e1eab3c69f3c56326c729f1f66c1a42ab2824..ffe91e93f880ce313abae1dcf472a1477ba0ce7f 100644 (file)
@@ -1121,7 +1121,7 @@ class Server extends ServerContainer implements IServerContainer {
                                        $c->getURLGenerator(),
                                        $c->getMemCacheFactory(),
                                        new Util($c->getConfig(), $this->getAppManager(), $c->getAppDataDir('theming')),
-                                       new ImageManager($c->getConfig(), $c->getAppDataDir('theming'), $c->getURLGenerator(), $this->getMemCacheFactory(), $this->getLogger()),
+                                       new ImageManager($c->getConfig(), $c->getAppDataDir('theming'), $c->getURLGenerator(), $this->getMemCacheFactory(), $this->getLogger(), $this->getTempManager()),
                                        $c->getAppManager(),
                                        $c->getNavigationManager()
                                );