From b3cf312edcefec3fb26bad8637f3a0969504be87 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 29 Mar 2022 22:18:40 +0200 Subject: Start theming providers Signed-off-by: Joas Schilling --- lib/private/TemplateLayout.php | 11 ----------- lib/private/legacy/OC_Template.php | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index 4e633bf8b06..a379f23a1ef 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -141,17 +141,6 @@ class TemplateLayout extends \OC_Template { $this->assign('userAvatarSet', true); $this->assign('userAvatarVersion', $this->config->getUserValue(\OC_User::getUser(), 'avatar', 'version', 0)); } - - // check if app menu icons should be inverted - try { - /** @var \OCA\Theming\Util $util */ - $util = \OC::$server->query(\OCA\Theming\Util::class); - $this->assign('themingInvertMenu', $util->invertTextColor(\OC::$server->getThemingDefaults()->getColorPrimary())); - } catch (\OCP\AppFramework\QueryException $e) { - $this->assign('themingInvertMenu', false); - } catch (\OCP\AutoloadNotAllowedException $e) { - $this->assign('themingInvertMenu', false); - } } elseif ($renderAs === TemplateResponse::RENDER_AS_ERROR) { parent::__construct('core', 'layout.guest', '', false); $this->assign('bodyid', 'body-login'); diff --git a/lib/private/legacy/OC_Template.php b/lib/private/legacy/OC_Template.php index 16ad7273cd2..b7a400d3269 100644 --- a/lib/private/legacy/OC_Template.php +++ b/lib/private/legacy/OC_Template.php @@ -105,7 +105,7 @@ class OC_Template extends \OC\Template\Base { // apps that started before the template initialization can load their own scripts/styles // so to make sure this scripts/styles here are loaded first we put all core scripts first // check lib/public/Util.php - OC_Util::addStyle('css-variables', null, true); + // OC_Util::addStyle('css-variables', null, true); OC_Util::addStyle('server', null, true); // include common nextcloud webpack bundle -- cgit v1.2.3 From 69d1d1a84e5e8937046d30714f11036b680cc04a Mon Sep 17 00:00:00 2001 From: John Molakvoæ Date: Fri, 15 Apr 2022 13:54:53 +0200 Subject: Write body theme selector straight in the template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ --- apps/theming/lib/Service/JSDataService.php | 16 +++---- apps/theming/lib/Service/ThemeInjectionService.php | 1 + apps/theming/lib/Service/ThemesService.php | 55 ++++++++++++++++++++-- core/css/apps.scss | 1 + core/templates/layout.user.php | 2 +- lib/private/TemplateLayout.php | 8 ++++ 6 files changed, 71 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/apps/theming/lib/Service/JSDataService.php b/apps/theming/lib/Service/JSDataService.php index 1c4d138a764..fdc85ea445a 100644 --- a/apps/theming/lib/Service/JSDataService.php +++ b/apps/theming/lib/Service/JSDataService.php @@ -32,22 +32,21 @@ use OCA\Theming\Util; use OCP\IConfig; class JSDataService implements \JsonSerializable { - - /** @var ThemingDefaults */ - private $themingDefaults; - /** @var Util */ - private $util; - /** @var IConfig */ - private $appConfig; + private ThemingDefaults $themingDefaults; + private Util $util; + private IConfig $appConfig; + private ThemesService $themesService; public function __construct( ThemingDefaults $themingDefaults, Util $util, - IConfig $appConfig + IConfig $appConfig, + ThemesService $themesService ) { $this->themingDefaults = $themingDefaults; $this->util = $util; $this->appConfig = $appConfig; + $this->themesService = $themesService; } public function jsonSerialize(): array { @@ -60,6 +59,7 @@ class JSDataService implements \JsonSerializable { 'privacyUrl' => $this->themingDefaults->getPrivacyUrl(), 'inverted' => $this->util->invertTextColor($this->themingDefaults->getColorPrimary()), 'cacheBuster' => $this->appConfig->getAppValue(Application::APP_ID, 'cachebuster', '0'), + 'enabledThemes' => $this->themesService->getEnabledThemes(), ]; } } diff --git a/apps/theming/lib/Service/ThemeInjectionService.php b/apps/theming/lib/Service/ThemeInjectionService.php index 0b4890cd08b..e00839c21c5 100644 --- a/apps/theming/lib/Service/ThemeInjectionService.php +++ b/apps/theming/lib/Service/ThemeInjectionService.php @@ -22,6 +22,7 @@ */ namespace OCA\Theming\Service; +use OCA\Theming\AppInfo\Application; use OCA\Theming\Themes\DefaultTheme; use OCP\IURLGenerator; use OCP\Util; diff --git a/apps/theming/lib/Service/ThemesService.php b/apps/theming/lib/Service/ThemesService.php index 3092b3bcbb5..832c443a2e1 100644 --- a/apps/theming/lib/Service/ThemesService.php +++ b/apps/theming/lib/Service/ThemesService.php @@ -22,21 +22,33 @@ */ namespace OCA\Theming\Service; +use OCA\Theming\AppInfo\Application; use OCA\Theming\Themes\DefaultTheme; use OCA\Theming\Themes\DarkTheme; use OCA\Theming\Themes\DarkHighContrastTheme; use OCA\Theming\Themes\HighContrastTheme; use OCA\Theming\ITheme; +use OCP\IAppConfig; +use OCP\IConfig; +use OCP\IUser; +use OCP\IUserSession; class ThemesService { + private IUserSession $session; + private IConfig $config; /** @var ITheme[] */ private array $themesProviders; - public function __construct(DefaultTheme $defaultTheme, + public function __construct(IUserSession $userSession, + IConfig $config, + DefaultTheme $defaultTheme, DarkTheme $darkTheme, DarkHighContrastTheme $darkHighContrastTheme, HighContrastTheme $highContrastTheme) { + $this->userSession = $userSession; + $this->config = $config; + // Register themes $this->themesProviders = [ $defaultTheme->getId() => $defaultTheme, @@ -46,11 +58,48 @@ class ThemesService { ]; } - public function getThemes() { + public function getThemes(): array { return $this->themesProviders; } - public function getThemeVariables(string $id) { + public function getThemeVariables(string $id): array { return $this->themesProviders[$id]->getCSSVariables(); } + + public function enableTheme(ITheme $theme): void { + $themes = $this->getEnabledThemes(); + array_push($themes, $theme->getId()); + $this->setEnabledThemes($themes); + } + + public function disableTheme(ITheme $theme): void { + // Using keys as it's faster + $themes = $this->getEnabledThemes(); + // If enabled, removing it + if (in_array($theme->getId(), $themes)) { + $this->setEnabledThemes(array_filter($themes, function($themeId) use ($theme) { + return $themeId !== $theme->getId(); + })); + } + } + + public function isEnabled(ITheme $theme): bool { + $user = $this->userSession->getUser(); + if ($user instanceof IUser) { + // Using keys as it's faster + $themes = $this->getEnabledThemes(); + return in_array($theme->getId(), $themes); + } + } + + public function getEnabledThemes(): array { + $user = $this->userSession->getUser(); + $enabledThemes = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'enabled-themes', '[]'); + return json_decode($enabledThemes); + } + + private function setEnabledThemes(array $themes): void { + $user = $this->userSession->getUser(); + $this->config->setUserValue($user->getUID(), Application::APP_ID, 'enabled-themes', json_encode(array_unique($themes))); + } } diff --git a/core/css/apps.scss b/core/css/apps.scss index b683ffae0ef..cf061303498 100644 --- a/core/css/apps.scss +++ b/core/css/apps.scss @@ -166,6 +166,7 @@ kbd { &, > a { background-color: var(--color-primary-light); + color: var(--color-primary-text); } } diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php index f5ac783b340..00e16414535 100644 --- a/core/templates/layout.user.php +++ b/core/templates/layout.user.php @@ -40,7 +40,7 @@ $getUserAvatar = static function (int $size) use ($_): string { - + > $initialState) { ?> diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index a379f23a1ef..b49ba49ebb8 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -81,6 +81,7 @@ class TemplateLayout extends \OC_Template { /** @var IInitialStateService */ $this->initialState = \OC::$server->get(IInitialStateService::class); + // Decide which page we show if ($renderAs === TemplateResponse::RENDER_AS_USER) { /** @var INavigationManager */ @@ -99,6 +100,13 @@ class TemplateLayout extends \OC_Template { $this->initialState->provideInitialState('unified-search', 'live-search', $this->config->getAppValue('core', 'unified-search.live-search', 'yes') === 'yes'); Util::addScript('core', 'unified-search', 'core'); + // Set body data-theme + if (\OC::$server->getAppManager()->isEnabledForUser('theming') && class_exists('\OCA\Theming\Service\ThemesService')) { + /** @var \OCA\Theming\Service\ThemesService */ + $themesService = \OC::$server->get(\OCA\Theming\Service\ThemesService::class); + $this->assign('enabledThemes', $themesService->getEnabledThemes()); + } + // set logo link target $logoUrl = $this->config->getSystemValueString('logo_url', ''); $this->assign('logoUrl', $logoUrl); -- cgit v1.2.3 From 48381b8913f90989582a60d90a1dbd0ce96608ae Mon Sep 17 00:00:00 2001 From: John Molakvoæ Date: Wed, 20 Apr 2022 11:14:40 +0200 Subject: Ship mexitek/phpcolors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ --- lib/composer/autoload.php | 5 - lib/composer/composer/InstalledVersions.php | 6 +- lib/composer/composer/autoload_classmap.php | 1 + lib/composer/composer/autoload_real.php | 4 +- lib/composer/composer/autoload_static.php | 1 + lib/composer/composer/installed.json | 59 +- lib/composer/composer/installed.php | 13 +- lib/composer/composer/platform_check.php | 26 + lib/composer/mexitek/phpcolors/.editorconfig | 17 + lib/composer/mexitek/phpcolors/.gitignore | 5 + lib/composer/mexitek/phpcolors/.phpcs.xml | 10 + lib/composer/mexitek/phpcolors/.travis.yml | 11 + lib/composer/mexitek/phpcolors/LICENSE | 21 + lib/composer/mexitek/phpcolors/README.md | 173 +++++ lib/composer/mexitek/phpcolors/composer.json | 37 + lib/composer/mexitek/phpcolors/demo/demo.php | 94 +++ .../mexitek/phpcolors/demo/phpColor-demo.png | Bin 0 -> 27634 bytes .../phpcolors/src/Mexitek/PHPColors/Color.php | 801 +++++++++++++++++++++ lib/composer/mexitek/phpcolors/tests/bootstrap.php | 11 + .../mexitek/phpcolors/tests/colorAnalyze.phpt | 35 + .../mexitek/phpcolors/tests/colorChange.phpt | 28 + .../phpcolors/tests/colorComplementary.phpt | 28 + .../phpcolors/tests/colorConvertHslToHex.phpt | 72 ++ .../phpcolors/tests/colorConvertNameToHex.phpt | 170 +++++ .../phpcolors/tests/colorConvertRgbToHex.phpt | 72 ++ .../mexitek/phpcolors/tests/colorInput.phpt | 19 + lib/composer/mexitek/phpcolors/tests/colorMix.phpt | 24 + 27 files changed, 1732 insertions(+), 11 deletions(-) create mode 100644 lib/composer/composer/platform_check.php create mode 100644 lib/composer/mexitek/phpcolors/.editorconfig create mode 100644 lib/composer/mexitek/phpcolors/.gitignore create mode 100644 lib/composer/mexitek/phpcolors/.phpcs.xml create mode 100644 lib/composer/mexitek/phpcolors/.travis.yml create mode 100644 lib/composer/mexitek/phpcolors/LICENSE create mode 100644 lib/composer/mexitek/phpcolors/README.md create mode 100644 lib/composer/mexitek/phpcolors/composer.json create mode 100644 lib/composer/mexitek/phpcolors/demo/demo.php create mode 100644 lib/composer/mexitek/phpcolors/demo/phpColor-demo.png create mode 100644 lib/composer/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php create mode 100644 lib/composer/mexitek/phpcolors/tests/bootstrap.php create mode 100644 lib/composer/mexitek/phpcolors/tests/colorAnalyze.phpt create mode 100644 lib/composer/mexitek/phpcolors/tests/colorChange.phpt create mode 100644 lib/composer/mexitek/phpcolors/tests/colorComplementary.phpt create mode 100644 lib/composer/mexitek/phpcolors/tests/colorConvertHslToHex.phpt create mode 100644 lib/composer/mexitek/phpcolors/tests/colorConvertNameToHex.phpt create mode 100644 lib/composer/mexitek/phpcolors/tests/colorConvertRgbToHex.phpt create mode 100644 lib/composer/mexitek/phpcolors/tests/colorInput.phpt create mode 100644 lib/composer/mexitek/phpcolors/tests/colorMix.phpt (limited to 'lib') diff --git a/lib/composer/autoload.php b/lib/composer/autoload.php index a3d144b1777..6de0160c0b5 100644 --- a/lib/composer/autoload.php +++ b/lib/composer/autoload.php @@ -2,11 +2,6 @@ // autoload.php @generated by Composer -if (PHP_VERSION_ID < 50600) { - echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; - exit(1); -} - require_once __DIR__ . '/composer/autoload_real.php'; return ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c::getLoader(); diff --git a/lib/composer/composer/InstalledVersions.php b/lib/composer/composer/InstalledVersions.php index fc50a9f8622..41bc143c114 100644 --- a/lib/composer/composer/InstalledVersions.php +++ b/lib/composer/composer/InstalledVersions.php @@ -21,6 +21,8 @@ use Composer\Semver\VersionParser; * See also https://getcomposer.org/doc/07-runtime.md#installed-versions * * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final */ class InstalledVersions { @@ -264,7 +266,7 @@ class InstalledVersions if (null === self::$installed) { // only require the installed.php file if this file is loaded from its dumped location, // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 - if (substr(__DIR__, -8, 1) !== 'C' && is_file(__DIR__ . '/installed.php')) { + if (substr(__DIR__, -8, 1) !== 'C') { self::$installed = include __DIR__ . '/installed.php'; } else { self::$installed = array(); @@ -337,7 +339,7 @@ class InstalledVersions if (null === self::$installed) { // only require the installed.php file if this file is loaded from its dumped location, // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 - if (substr(__DIR__, -8, 1) !== 'C' && is_file(__DIR__ . '/installed.php')) { + if (substr(__DIR__, -8, 1) !== 'C') { self::$installed = require __DIR__ . '/installed.php'; } else { self::$installed = array(); diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 685fae9bef1..f2b5cf94d11 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -7,6 +7,7 @@ $baseDir = dirname(dirname($vendorDir)); return array( 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', + 'Mexitek\\PHPColors\\Color' => $vendorDir . '/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php', 'OCP\\Accounts\\IAccount' => $baseDir . '/lib/public/Accounts/IAccount.php', 'OCP\\Accounts\\IAccountManager' => $baseDir . '/lib/public/Accounts/IAccountManager.php', 'OCP\\Accounts\\IAccountProperty' => $baseDir . '/lib/public/Accounts/IAccountProperty.php', diff --git a/lib/composer/composer/autoload_real.php b/lib/composer/composer/autoload_real.php index eecff48bcf9..9399510b985 100644 --- a/lib/composer/composer/autoload_real.php +++ b/lib/composer/composer/autoload_real.php @@ -22,12 +22,14 @@ class ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c return self::$loader; } + require __DIR__ . '/platform_check.php'; + spl_autoload_register(array('ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); spl_autoload_unregister(array('ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c', 'loadClassLoader')); require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c::getInitializer($loader)); + \Composer\Autoload\ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c::getInitializer($loader)(); $loader->register(true); diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 7e778d73b83..0f3c0a175af 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -36,6 +36,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c public static $classMap = array ( 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + 'Mexitek\\PHPColors\\Color' => __DIR__ . '/..' . '/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php', 'OCP\\Accounts\\IAccount' => __DIR__ . '/../../..' . '/lib/public/Accounts/IAccount.php', 'OCP\\Accounts\\IAccountManager' => __DIR__ . '/../../..' . '/lib/public/Accounts/IAccountManager.php', 'OCP\\Accounts\\IAccountProperty' => __DIR__ . '/../../..' . '/lib/public/Accounts/IAccountProperty.php', diff --git a/lib/composer/composer/installed.json b/lib/composer/composer/installed.json index f20a6c47c6d..61ce38b2189 100644 --- a/lib/composer/composer/installed.json +++ b/lib/composer/composer/installed.json @@ -1,5 +1,62 @@ { - "packages": [], + "packages": [ + { + "name": "mexitek/phpcolors", + "version": "v1.0.4", + "version_normalized": "1.0.4.0", + "source": { + "type": "git", + "url": "https://github.com/mexitek/phpColors.git", + "reference": "4043974240ca7dc3c2bec3c158588148b605b206" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mexitek/phpColors/zipball/4043974240ca7dc3c2bec3c158588148b605b206", + "reference": "4043974240ca7dc3c2bec3c158588148b605b206", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "require-dev": { + "nette/tester": "^2.3", + "squizlabs/php_codesniffer": "^3.5" + }, + "time": "2021-11-26T13:19:08+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "src" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Arlo Carreon", + "homepage": "http://arlocarreon.com", + "role": "creator" + } + ], + "description": "A series of methods that let you manipulate colors. Just incase you ever need different shades of one color on the fly.", + "homepage": "http://mexitek.github.com/phpColors/", + "keywords": [ + "color", + "css", + "design", + "frontend", + "ui" + ], + "support": { + "issues": "https://github.com/mexitek/phpColors/issues", + "source": "https://github.com/mexitek/phpColors" + }, + "install-path": "../mexitek/phpcolors" + } + ], "dev": false, "dev-package-names": [] } diff --git a/lib/composer/composer/installed.php b/lib/composer/composer/installed.php index 67a1ddfbd8c..caaede08016 100644 --- a/lib/composer/composer/installed.php +++ b/lib/composer/composer/installed.php @@ -5,7 +5,7 @@ 'type' => 'library', 'install_path' => __DIR__ . '/../../../', 'aliases' => array(), - 'reference' => '42c7886f80c7a5e767b192d07474114dd0848b16', + 'reference' => '3e28052303a61b134b454fdc31e72d371c03b793', 'name' => '__root__', 'dev' => false, ), @@ -16,7 +16,16 @@ 'type' => 'library', 'install_path' => __DIR__ . '/../../../', 'aliases' => array(), - 'reference' => '42c7886f80c7a5e767b192d07474114dd0848b16', + 'reference' => '3e28052303a61b134b454fdc31e72d371c03b793', + 'dev_requirement' => false, + ), + 'mexitek/phpcolors' => array( + 'pretty_version' => 'v1.0.4', + 'version' => '1.0.4.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../mexitek/phpcolors', + 'aliases' => array(), + 'reference' => '4043974240ca7dc3c2bec3c158588148b605b206', 'dev_requirement' => false, ), ), diff --git a/lib/composer/composer/platform_check.php b/lib/composer/composer/platform_check.php new file mode 100644 index 00000000000..589e9e770b9 --- /dev/null +++ b/lib/composer/composer/platform_check.php @@ -0,0 +1,26 @@ += 70200)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.'; +} + +if ($issues) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); + } elseif (!headers_sent()) { + echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; + } + } + trigger_error( + 'Composer detected issues in your platform: ' . implode(' ', $issues), + E_USER_ERROR + ); +} diff --git a/lib/composer/mexitek/phpcolors/.editorconfig b/lib/composer/mexitek/phpcolors/.editorconfig new file mode 100644 index 00000000000..989704a3d66 --- /dev/null +++ b/lib/composer/mexitek/phpcolors/.editorconfig @@ -0,0 +1,17 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +# .travis.yml +[.travis.yml] +indent_size = 2 diff --git a/lib/composer/mexitek/phpcolors/.gitignore b/lib/composer/mexitek/phpcolors/.gitignore new file mode 100644 index 00000000000..e0a462444b4 --- /dev/null +++ b/lib/composer/mexitek/phpcolors/.gitignore @@ -0,0 +1,5 @@ +*.bak +*.*.bak +vendor/* +composer.lock +.idea diff --git a/lib/composer/mexitek/phpcolors/.phpcs.xml b/lib/composer/mexitek/phpcolors/.phpcs.xml new file mode 100644 index 00000000000..bba9c9f778d --- /dev/null +++ b/lib/composer/mexitek/phpcolors/.phpcs.xml @@ -0,0 +1,10 @@ + + + The coding standard for PHPColors. + + ./src + ./tests + + + diff --git a/lib/composer/mexitek/phpcolors/.travis.yml b/lib/composer/mexitek/phpcolors/.travis.yml new file mode 100644 index 00000000000..1e5be351c4c --- /dev/null +++ b/lib/composer/mexitek/phpcolors/.travis.yml @@ -0,0 +1,11 @@ +language: php +php: + - 7.2 + - 7.3 + - 7.4 + - 8.0 +before_script: + - composer install --no-interaction --dev --prefer-source +script: + - vendor/bin/phpcs --extensions=php,phpt --warning-severity=0 + - vendor/bin/tester tests -s -p php diff --git a/lib/composer/mexitek/phpcolors/LICENSE b/lib/composer/mexitek/phpcolors/LICENSE new file mode 100644 index 00000000000..f764bbc2dcf --- /dev/null +++ b/lib/composer/mexitek/phpcolors/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Arlo Carreon, http://arlocarreon.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/composer/mexitek/phpcolors/README.md b/lib/composer/mexitek/phpcolors/README.md new file mode 100644 index 00000000000..8e3420f298f --- /dev/null +++ b/lib/composer/mexitek/phpcolors/README.md @@ -0,0 +1,173 @@ +# PHPColors [![Build Status](https://travis-ci.org/mexitek/phpColors.svg?branch=master)](https://travis-ci.org/mexitek/phpColors) + +> A series of methods that let you manipulate colors. Just incase you ever need different shades of one color on the fly. + +## Requirements + +PHPColors requires PHP version 7.2.0 or greater. + +## Installation + +### Composer + +Simply add `mexitek/phpcolors` to `composer.json` using `dev-master`. + +``` +composer require mexitek/phpcolors:dev-master +``` + +## How it works +Instantiate an object of the color class with a hex color string `$foo = new Color("336699")`. That's it! Now, call the methods you need for different color variants. + +## Available Methods +- darken( [$amount] ) : Allows you to obtain a darker shade of your color. Optionally you can decide to darken using a desired percentage. +- lighten( [$amount] ) : Allows you to obtain a lighter shade of your color. Optionally you can decide to lighten using a desired percentage. +- mix($hex, [$amount] ) : Allows you to mix another color to your color. Optionally you can decide to set the percent of second color or original color amount is ranged -100...0...100. +- isLight( [$hex] ) : Determins whether your color (or the provide param) is considered a "light" color. Returns `TRUE` if color is light. +- isDark( [$hex] ) : Determins whether your color (or the provide param) is considered a "dark" color. Returns `TRUE` if color is dark. +- makeGradient( [$amount] ) : Returns an array with 2 indices `light` and `dark`, the initial color will either be selected for `light` or `dark` depending on its brightness, then the other color will be generated. The optional param allows for a static lighten or darkened amount. +- complementary() : Returns the color "opposite" or complementary to your color. +- getHex() : Returns the original hex color. +- getHsl() : Returns HSL array for your color. +- getRgb() : Returns RGB array for your color. + +> Auto lightens/darkens by 10% for sexily-subtle gradients + +```php +/** + * Using The Class + */ + +use Mexitek\PHPColors\Color; + +// Initialize my color +$myBlue = new Color("#336699"); + +echo $myBlue->darken(); +// 1a334d + +echo $myBlue->lighten(); +// 8cb3d9 + +echo $myBlue->isLight(); +// false + +echo $myBlue->isDark(); +// true + +echo $myBlue->complementary(); +// 996633 + +echo $myBlue->getHex(); +// 336699 + +print_r( $myBlue->getHsl() ); +// array( "H"=> 210, "S"=> 0.5, "L"=>0.4 ); + +print_r( $myBlue->getRgb() ); +// array( "R"=> 51, "G"=> 102, "B"=>153 ); + +print_r($myBlue->makeGradient()); +// array( "light"=>"8cb3d9" ,"dark"=>"336699" ) + +``` + + +## Static Methods +- hslToHex( $hsl ) : Convert a HSL array to a HEX string. +- hexToHsl( $hex ) : Convert a HEX string into an HSL array. +- hexToRgb( $hex ) : Convert a HEX string into an RGB array. +- rgbToHex( $rgb ) : Convert an RGB array into a HEX string. + +```php +/** + * On The Fly Custom Calculations + */ + +use Mexitek\PHPColors\Color; + + // Convert my HEX + $myBlue = Color::hexToHsl("#336699"); + + // Get crazy with the HUE + $myBlue["H"] = 295; + + // Gimme my new color!! + echo Color::hslToHex($myBlue); + // 913399 + +``` + +## CSS Helpers +- getCssGradient( [$amount] [, $vintageBrowsers] ) : Generates the CSS3 gradients for safari, chrome, opera, firefox and IE10. Optional percentage amount for lighter/darker shade. Optional boolean for older gradient CSS support. + +> Would like to add support to custom gradient stops + +```php + +use Mexitek\PHPColors\Color; + +// Initialize my color +$myBlue = new Color("#336699"); + +// Get CSS +echo $myBlue->getCssGradient(); +/* - Actual output doesn't have comments and is single line + + // fallback background + background: #336699; + + // IE Browsers + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8cb3d9', endColorstr='#336699'); + + // Safari 5.1+, Mobile Safari, Chrome 10+ + background-image: -webkit-linear-gradient(top, #8cb3d9, #336699); + + // Standards + background-image: linear-gradient(to bottom, #8cb3d9, #336699); + +*/ + +``` + +However, if you want to support the ancient browsers (which has negligible market share and almost died out), you can set the second parameter to `TRUE`. This will output: + +```php + +use Mexitek\PHPColors\Color; +$myBlue = new Color("#336699"); + +// Get CSS +echo $myBlue->getCssGradient(10, TRUE); +/* - Actual output doesn't have comments and is single line + + background: #336699; // fallback background + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8cb3d9', endColorstr='#336699'); // IE Browsers + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#8cb3d9), to(#336699)); // Safari 4+, Chrome 1-9 + background-image: -webkit-linear-gradient(top, #8cb3d9, #336699); // Safari 5.1+, Mobile Safari, Chrome 10+ + background-image: -moz-linear-gradient(top, #8cb3d9, #336699); // Firefox 3.6+ + background-image: -o-linear-gradient(top, #8cb3d9, #336699); // Opera 11.10+ + background-image: linear-gradient(to bottom, #8cb3d9, #336699); // Standards + +*/ + +``` + +## Github Contributors +- mexitek +- danielpataki +- alexmglover +- intuxicated +- pborreli +- curtisgibby +- matthewpatterson +- there4 +- alex-humphreys +- zaher +- primozcigler +- thedavidmeister +- tylercd100 +- Braunson + +# License +See LICENSE file or [arlo.mit-license.org](http://arlo.mit-license.org) diff --git a/lib/composer/mexitek/phpcolors/composer.json b/lib/composer/mexitek/phpcolors/composer.json new file mode 100644 index 00000000000..8d074f752e1 --- /dev/null +++ b/lib/composer/mexitek/phpcolors/composer.json @@ -0,0 +1,37 @@ +{ + "name": "mexitek/phpcolors", + "description": "A series of methods that let you manipulate colors. Just incase you ever need different shades of one color on the fly.", + "type": "library", + "keywords": [ + "color", + "ui", + "css", + "frontend", + "design" + ], + "homepage": "http://mexitek.github.com/phpColors/", + "license": "MIT", + "authors": [ + { + "name": "Arlo Carreon", + "homepage": "http://arlocarreon.com", + "role": "creator" + } + ], + "support": { + "issues": "https://github.com/mexitek/phpColors/issues", + "source": "https://github.com/mexitek/phpColors" + }, + "require": { + "php": "^7.2|^8.0" + }, + "require-dev": { + "nette/tester": "^2.3", + "squizlabs/php_codesniffer": "^3.5" + }, + "autoload": { + "classmap": [ + "src" + ] + } +} diff --git a/lib/composer/mexitek/phpcolors/demo/demo.php b/lib/composer/mexitek/phpcolors/demo/demo.php new file mode 100644 index 00000000000..825cf084466 --- /dev/null +++ b/lib/composer/mexitek/phpcolors/demo/demo.php @@ -0,0 +1,94 @@ + + + + phpColors Demo + + + + +
+
phpColor Gradient #getHex() ?>
+
Plain #getHex() ?>
+
+
phpColor Gradient #getHex() ?>
+
Plain #getHex() ?>
+
+
phpColor Gradient #getHex() ?>
+
Plain #getHex() ?>
+
+
+ phpColor Gradient with vintage browsers support #getHex() ?> +
+ + diff --git a/lib/composer/mexitek/phpcolors/demo/phpColor-demo.png b/lib/composer/mexitek/phpcolors/demo/phpColor-demo.png new file mode 100644 index 00000000000..b1fbdbcae97 Binary files /dev/null and b/lib/composer/mexitek/phpcolors/demo/phpColor-demo.png differ diff --git a/lib/composer/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php b/lib/composer/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php new file mode 100644 index 00000000000..282e9926b3e --- /dev/null +++ b/lib/composer/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php @@ -0,0 +1,801 @@ + + * Info: http://mexitek.github.io/phpColors/ + * License: http://arlo.mit-license.org/ + */ + +namespace Mexitek\PHPColors; + +use Exception; + +/** + * A color utility that helps manipulate HEX colors + */ +class Color +{ + /** + * @var string + */ + private $_hex; + + /** + * @var array + */ + private $_hsl; + + /** + * @var array + */ + private $_rgb; + + /** + * Auto darkens/lightens by 10% for sexily-subtle gradients. + * Set this to FALSE to adjust automatic shade to be between given color + * and black (for darken) or white (for lighten) + */ + public const DEFAULT_ADJUST = 10; + + /** + * Instantiates the class with a HEX value + * @param string $hex + * @throws Exception + */ + public function __construct(string $hex) + { + $color = self::sanitizeHex($hex); + $this->_hex = $color; + $this->_hsl = self::hexToHsl($color); + $this->_rgb = self::hexToRgb($color); + } + + /** + * Given a HEX string returns a HSL array equivalent. + * @param string $color + * @return array HSL associative array + * @throws Exception + */ + public static function hexToHsl(string $color): array + { + // Sanity check + $color = self::sanitizeHex($color); + + // Convert HEX to DEC + $R = hexdec($color[0] . $color[1]); + $G = hexdec($color[2] . $color[3]); + $B = hexdec($color[4] . $color[5]); + + $HSL = array(); + + $var_R = ($R / 255); + $var_G = ($G / 255); + $var_B = ($B / 255); + + $var_Min = min($var_R, $var_G, $var_B); + $var_Max = max($var_R, $var_G, $var_B); + $del_Max = $var_Max - $var_Min; + + $L = ($var_Max + $var_Min) / 2; + + if ($del_Max == 0) { + $H = 0; + $S = 0; + } else { + if ($L < 0.5) { + $S = $del_Max / ($var_Max + $var_Min); + } else { + $S = $del_Max / (2 - $var_Max - $var_Min); + } + + $del_R = ((($var_Max - $var_R) / 6) + ($del_Max / 2)) / $del_Max; + $del_G = ((($var_Max - $var_G) / 6) + ($del_Max / 2)) / $del_Max; + $del_B = ((($var_Max - $var_B) / 6) + ($del_Max / 2)) / $del_Max; + + if ($var_R == $var_Max) { + $H = $del_B - $del_G; + } elseif ($var_G == $var_Max) { + $H = (1 / 3) + $del_R - $del_B; + } elseif ($var_B == $var_Max) { + $H = (2 / 3) + $del_G - $del_R; + } + + if ($H < 0) { + $H++; + } + if ($H > 1) { + $H--; + } + } + + $HSL['H'] = ($H * 360); + $HSL['S'] = $S; + $HSL['L'] = $L; + + return $HSL; + } + + /** + * Given a HSL associative array returns the equivalent HEX string + * @param array $hsl + * @return string HEX string + * @throws Exception "Bad HSL Array" + */ + public static function hslToHex(array $hsl = array()): string + { + // Make sure it's HSL + if (empty($hsl) || !isset($hsl["H"], $hsl["S"], $hsl["L"])) { + throw new Exception("Param was not an HSL array"); + } + + list($H, $S, $L) = array($hsl['H'] / 360, $hsl['S'], $hsl['L']); + + if ($S == 0) { + $r = $L * 255; + $g = $L * 255; + $b = $L * 255; + } else { + if ($L < 0.5) { + $var_2 = $L * (1 + $S); + } else { + $var_2 = ($L + $S) - ($S * $L); + } + + $var_1 = 2 * $L - $var_2; + + $r = 255 * self::hueToRgb($var_1, $var_2, $H + (1 / 3)); + $g = 255 * self::hueToRgb($var_1, $var_2, $H); + $b = 255 * self::hueToRgb($var_1, $var_2, $H - (1 / 3)); + } + + // Convert to hex + $r = dechex(round($r)); + $g = dechex(round($g)); + $b = dechex(round($b)); + + // Make sure we get 2 digits for decimals + $r = (strlen("" . $r) === 1) ? "0" . $r : $r; + $g = (strlen("" . $g) === 1) ? "0" . $g : $g; + $b = (strlen("" . $b) === 1) ? "0" . $b : $b; + + return $r . $g . $b; + } + + + /** + * Given a HEX string returns a RGB array equivalent. + * @param string $color + * @return array RGB associative array + * @throws Exception + */ + public static function hexToRgb(string $color): array + { + // Sanity check + $color = self::sanitizeHex($color); + + // Convert HEX to DEC + $R = hexdec($color[0] . $color[1]); + $G = hexdec($color[2] . $color[3]); + $B = hexdec($color[4] . $color[5]); + + $RGB['R'] = $R; + $RGB['G'] = $G; + $RGB['B'] = $B; + + return $RGB; + } + + + /** + * Given an RGB associative array returns the equivalent HEX string + * @param array $rgb + * @return string Hex string + * @throws Exception "Bad RGB Array" + */ + public static function rgbToHex(array $rgb = array()): string + { + // Make sure it's RGB + if (empty($rgb) || !isset($rgb["R"], $rgb["G"], $rgb["B"])) { + throw new Exception("Param was not an RGB array"); + } + + // https://github.com/mexitek/phpColors/issues/25#issuecomment-88354815 + // Convert RGB to HEX + $hex[0] = str_pad(dechex((int)$rgb['R']), 2, '0', STR_PAD_LEFT); + $hex[1] = str_pad(dechex((int)$rgb['G']), 2, '0', STR_PAD_LEFT); + $hex[2] = str_pad(dechex((int)$rgb['B']), 2, '0', STR_PAD_LEFT); + + // Make sure that 2 digits are allocated to each color. + $hex[0] = (strlen($hex[0]) === 1) ? '0' . $hex[0] : $hex[0]; + $hex[1] = (strlen($hex[1]) === 1) ? '0' . $hex[1] : $hex[1]; + $hex[2] = (strlen($hex[2]) === 1) ? '0' . $hex[2] : $hex[2]; + + return implode('', $hex); + } + + /** + * Given an RGB associative array, returns CSS string output. + * @param array $rgb + * @return string rgb(r,g,b) string + * @throws Exception "Bad RGB Array" + */ + public static function rgbToString(array $rgb = array()): string + { + // Make sure it's RGB + if (empty($rgb) || !isset($rgb["R"], $rgb["G"], $rgb["B"])) { + throw new Exception("Param was not an RGB array"); + } + + return 'rgb(' . + $rgb['R'] . ', ' . + $rgb['G'] . ', ' . + $rgb['B'] . ')'; + } + + /** + * Given a standard color name, return hex code + * + * @param string $color_name + * @return string + */ + public static function nameToHex(string $color_name): string + { + $colors = array( + 'aliceblue' => 'F0F8FF', + 'antiquewhite' => 'FAEBD7', + 'aqua' => '00FFFF', + 'aquamarine' => '7FFFD4', + 'azure' => 'F0FFFF', + 'beige' => 'F5F5DC', + 'bisque' => 'FFE4C4', + 'black' => '000000', + 'blanchedalmond' => 'FFEBCD', + 'blue' => '0000FF', + 'blueviolet' => '8A2BE2', + 'brown' => 'A52A2A', + 'burlywood' => 'DEB887', + 'cadetblue' => '5F9EA0', + 'chartreuse' => '7FFF00', + 'chocolate' => 'D2691E', + 'coral' => 'FF7F50', + 'cornflowerblue' => '6495ED', + 'cornsilk' => 'FFF8DC', + 'crimson' => 'DC143C', + 'cyan' => '00FFFF', + 'darkblue' => '00008B', + 'darkcyan' => '008B8B', + 'darkgoldenrod' => 'B8860B', + 'darkgray' => 'A9A9A9', + 'darkgreen' => '006400', + 'darkgrey' => 'A9A9A9', + 'darkkhaki' => 'BDB76B', + 'darkmagenta' => '8B008B', + 'darkolivegreen' => '556B2F', + 'darkorange' => 'FF8C00', + 'darkorchid' => '9932CC', + 'darkred' => '8B0000', + 'darksalmon' => 'E9967A', + 'darkseagreen' => '8FBC8F', + 'darkslateblue' => '483D8B', + 'darkslategray' => '2F4F4F', + 'darkslategrey' => '2F4F4F', + 'darkturquoise' => '00CED1', + 'darkviolet' => '9400D3', + 'deeppink' => 'FF1493', + 'deepskyblue' => '00BFFF', + 'dimgray' => '696969', + 'dimgrey' => '696969', + 'dodgerblue' => '1E90FF', + 'firebrick' => 'B22222', + 'floralwhite' => 'FFFAF0', + 'forestgreen' => '228B22', + 'fuchsia' => 'FF00FF', + 'gainsboro' => 'DCDCDC', + 'ghostwhite' => 'F8F8FF', + 'gold' => 'FFD700', + 'goldenrod' => 'DAA520', + 'gray' => '808080', + 'green' => '008000', + 'greenyellow' => 'ADFF2F', + 'grey' => '808080', + 'honeydew' => 'F0FFF0', + 'hotpink' => 'FF69B4', + 'indianred' => 'CD5C5C', + 'indigo' => '4B0082', + 'ivory' => 'FFFFF0', + 'khaki' => 'F0E68C', + 'lavender' => 'E6E6FA', + 'lavenderblush' => 'FFF0F5', + 'lawngreen' => '7CFC00', + 'lemonchiffon' => 'FFFACD', + 'lightblue' => 'ADD8E6', + 'lightcoral' => 'F08080', + 'lightcyan' => 'E0FFFF', + 'lightgoldenrodyellow' => 'FAFAD2', + 'lightgray' => 'D3D3D3', + 'lightgreen' => '90EE90', + 'lightgrey' => 'D3D3D3', + 'lightpink' => 'FFB6C1', + 'lightsalmon' => 'FFA07A', + 'lightseagreen' => '20B2AA', + 'lightskyblue' => '87CEFA', + 'lightslategray' => '778899', + 'lightslategrey' => '778899', + 'lightsteelblue' => 'B0C4DE', + 'lightyellow' => 'FFFFE0', + 'lime' => '00FF00', + 'limegreen' => '32CD32', + 'linen' => 'FAF0E6', + 'magenta' => 'FF00FF', + 'maroon' => '800000', + 'mediumaquamarine' => '66CDAA', + 'mediumblue' => '0000CD', + 'mediumorchid' => 'BA55D3', + 'mediumpurple' => '9370D0', + 'mediumseagreen' => '3CB371', + 'mediumslateblue' => '7B68EE', + 'mediumspringgreen' => '00FA9A', + 'mediumturquoise' => '48D1CC', + 'mediumvioletred' => 'C71585', + 'midnightblue' => '191970', + 'mintcream' => 'F5FFFA', + 'mistyrose' => 'FFE4E1', + 'moccasin' => 'FFE4B5', + 'navajowhite' => 'FFDEAD', + 'navy' => '000080', + 'oldlace' => 'FDF5E6', + 'olive' => '808000', + 'olivedrab' => '6B8E23', + 'orange' => 'FFA500', + 'orangered' => 'FF4500', + 'orchid' => 'DA70D6', + 'palegoldenrod' => 'EEE8AA', + 'palegreen' => '98FB98', + 'paleturquoise' => 'AFEEEE', + 'palevioletred' => 'DB7093', + 'papayawhip' => 'FFEFD5', + 'peachpuff' => 'FFDAB9', + 'peru' => 'CD853F', + 'pink' => 'FFC0CB', + 'plum' => 'DDA0DD', + 'powderblue' => 'B0E0E6', + 'purple' => '800080', + 'red' => 'FF0000', + 'rosybrown' => 'BC8F8F', + 'royalblue' => '4169E1', + 'saddlebrown' => '8B4513', + 'salmon' => 'FA8072', + 'sandybrown' => 'F4A460', + 'seagreen' => '2E8B57', + 'seashell' => 'FFF5EE', + 'sienna' => 'A0522D', + 'silver' => 'C0C0C0', + 'skyblue' => '87CEEB', + 'slateblue' => '6A5ACD', + 'slategray' => '708090', + 'slategrey' => '708090', + 'snow' => 'FFFAFA', + 'springgreen' => '00FF7F', + 'steelblue' => '4682B4', + 'tan' => 'D2B48C', + 'teal' => '008080', + 'thistle' => 'D8BFD8', + 'tomato' => 'FF6347', + 'turquoise' => '40E0D0', + 'violet' => 'EE82EE', + 'wheat' => 'F5DEB3', + 'white' => 'FFFFFF', + 'whitesmoke' => 'F5F5F5', + 'yellow' => 'FFFF00', + 'yellowgreen' => '9ACD32' + ); + + $color_name = strtolower($color_name); + if (isset($colors[$color_name])) { + return '#' . $colors[$color_name]; + } + + return $color_name; + } + + /** + * Given a HEX value, returns a darker color. If no desired amount provided, then the color halfway between + * given HEX and black will be returned. + * @param int $amount + * @return string Darker HEX value + * @throws Exception + */ + public function darken(int $amount = self::DEFAULT_ADJUST): string + { + // Darken + $darkerHSL = $this->darkenHsl($this->_hsl, $amount); + // Return as HEX + return self::hslToHex($darkerHSL); + } + + /** + * Given a HEX value, returns a lighter color. If no desired amount provided, then the color halfway between + * given HEX and white will be returned. + * @param int $amount + * @return string Lighter HEX value + * @throws Exception + */ + public function lighten(int $amount = self::DEFAULT_ADJUST): string + { + // Lighten + $lighterHSL = $this->lightenHsl($this->_hsl, $amount); + // Return as HEX + return self::hslToHex($lighterHSL); + } + + /** + * Given a HEX value, returns a mixed color. If no desired amount provided, then the color mixed by this ratio + * @param string $hex2 Secondary HEX value to mix with + * @param int $amount = -100..0..+100 + * @return string mixed HEX value + * @throws Exception + */ + public function mix(string $hex2, int $amount = 0): string + { + $rgb2 = self::hexToRgb($hex2); + $mixed = $this->mixRgb($this->_rgb, $rgb2, $amount); + // Return as HEX + return self::rgbToHex($mixed); + } + + /** + * Creates an array with two shades that can be used to make a gradient + * @param int $amount Optional percentage amount you want your contrast color + * @return array An array with a 'light' and 'dark' index + * @throws Exception + */ + public function makeGradient(int $amount = self::DEFAULT_ADJUST): array + { + // Decide which color needs to be made + if ($this->isLight()) { + $lightColor = $this->_hex; + $darkColor = $this->darken($amount); + } else { + $lightColor = $this->lighten($amount); + $darkColor = $this->_hex; + } + + // Return our gradient array + return array("light" => $lightColor, "dark" => $darkColor); + } + + + /** + * Returns whether or not given color is considered "light" + * @param string|bool $color + * @param int $lighterThan + * @return boolean + */ + public function isLight($color = false, int $lighterThan = 130): bool + { + // Get our color + $color = ($color) ? $color : $this->_hex; + + // Calculate straight from rbg + $r = hexdec($color[0] . $color[1]); + $g = hexdec($color[2] . $color[3]); + $b = hexdec($color[4] . $color[5]); + + return (($r * 299 + $g * 587 + $b * 114) / 1000 > $lighterThan); + } + + /** + * Returns whether or not a given color is considered "dark" + * @param string|bool $color + * @param int $darkerThan + * @return boolean + */ + public function isDark($color = false, int $darkerThan = 130): bool + { + // Get our color + $color = ($color) ? $color : $this->_hex; + + // Calculate straight from rbg + $r = hexdec($color[0] . $color[1]); + $g = hexdec($color[2] . $color[3]); + $b = hexdec($color[4] . $color[5]); + + return (($r * 299 + $g * 587 + $b * 114) / 1000 <= $darkerThan); + } + + /** + * Returns the complimentary color + * @return string Complementary hex color + * @throws Exception + */ + public function complementary(): string + { + // Get our HSL + $hsl = $this->_hsl; + + // Adjust Hue 180 degrees + $hsl['H'] += ($hsl['H'] > 180) ? -180 : 180; + + // Return the new value in HEX + return self::hslToHex($hsl); + } + + /** + * Returns the HSL array of your color + */ + public function getHsl(): array + { + return $this->_hsl; + } + + /** + * Returns your original color + */ + public function getHex(): string + { + return $this->_hex; + } + + /** + * Returns the RGB array of your color + */ + public function getRgb(): array + { + return $this->_rgb; + } + + /** + * Returns the cross browser CSS3 gradient + * @param int $amount Optional: percentage amount to light/darken the gradient + * @param boolean $vintageBrowsers Optional: include vendor prefixes for browsers that almost died out already + * @param string $prefix Optional: prefix for every lines + * @param string $suffix Optional: suffix for every lines + * @return string CSS3 gradient for chrome, safari, firefox, opera and IE10 + * @throws Exception + * @link http://caniuse.com/css-gradients Resource for the browser support + */ + public function getCssGradient($amount = self::DEFAULT_ADJUST, $vintageBrowsers = false, $suffix = "", $prefix = ""): string + { + // Get the recommended gradient + $g = $this->makeGradient($amount); + + $css = ""; + /* fallback/image non-cover color */ + $css .= "{$prefix}background-color: #" . $this->_hex . ";{$suffix}"; + + /* IE Browsers */ + $css .= "{$prefix}filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#" . $g['light'] . "', endColorstr='#" . $g['dark'] . "');{$suffix}"; + + /* Safari 4+, Chrome 1-9 */ + if ($vintageBrowsers) { + $css .= "{$prefix}background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#" . $g['light'] . "), to(#" . $g['dark'] . "));{$suffix}"; + } + + /* Safari 5.1+, Mobile Safari, Chrome 10+ */ + $css .= "{$prefix}background-image: -webkit-linear-gradient(top, #" . $g['light'] . ", #" . $g['dark'] . ");{$suffix}"; + + if ($vintageBrowsers) { + /* Firefox 3.6+ */ + $css .= "{$prefix}background-image: -moz-linear-gradient(top, #" . $g['light'] . ", #" . $g['dark'] . ");{$suffix}"; + + /* Opera 11.10+ */ + $css .= "{$prefix}background-image: -o-linear-gradient(top, #" . $g['light'] . ", #" . $g['dark'] . ");{$suffix}"; + } + + /* Unprefixed version (standards): FF 16+, IE10+, Chrome 26+, Safari 7+, Opera 12.1+ */ + $css .= "{$prefix}background-image: linear-gradient(to bottom, #" . $g['light'] . ", #" . $g['dark'] . ");{$suffix}"; + + // Return our CSS + return $css; + } + + /** + * Darkens a given HSL array + * @param array $hsl + * @param int $amount + * @return array $hsl + */ + private function darkenHsl(array $hsl, int $amount = self::DEFAULT_ADJUST): array + { + // Check if we were provided a number + if ($amount) { + $hsl['L'] = ($hsl['L'] * 100) - $amount; + $hsl['L'] = ($hsl['L'] < 0) ? 0 : $hsl['L'] / 100; + } else { + // We need to find out how much to darken + $hsl['L'] /= 2; + } + + return $hsl; + } + + /** + * Lightens a given HSL array + * @param array $hsl + * @param int $amount + * @return array + */ + private function lightenHsl(array $hsl, int $amount = self::DEFAULT_ADJUST): array + { + // Check if we were provided a number + if ($amount) { + $hsl['L'] = ($hsl['L'] * 100) + $amount; + $hsl['L'] = ($hsl['L'] > 100) ? 1 : $hsl['L'] / 100; + } else { + // We need to find out how much to lighten + $hsl['L'] += (1 - $hsl['L']) / 2; + } + + return $hsl; + } + + /** + * Mix two RGB colors and return the resulting RGB color + * ported from http://phpxref.pagelines.com/nav.html?includes/class.colors.php.source.html + * @param array $rgb1 + * @param array $rgb2 + * @param int $amount ranged -100..0..+100 + * @return array + */ + private function mixRgb(array $rgb1, array $rgb2, int $amount = 0): array + { + $r1 = ($amount + 100) / 100; + $r2 = 2 - $r1; + + $rmix = (($rgb1['R'] * $r1) + ($rgb2['R'] * $r2)) / 2; + $gmix = (($rgb1['G'] * $r1) + ($rgb2['G'] * $r2)) / 2; + $bmix = (($rgb1['B'] * $r1) + ($rgb2['B'] * $r2)) / 2; + + return array('R' => $rmix, 'G' => $gmix, 'B' => $bmix); + } + + /** + * Given a Hue, returns corresponding RGB value + * @param float $v1 + * @param float $v2 + * @param float $vH + * @return float + */ + private static function hueToRgb(float $v1, float $v2, float $vH): float + { + if ($vH < 0) { + ++$vH; + } + + if ($vH > 1) { + --$vH; + } + + if ((6 * $vH) < 1) { + return ($v1 + ($v2 - $v1) * 6 * $vH); + } + + if ((2 * $vH) < 1) { + return $v2; + } + + if ((3 * $vH) < 2) { + return ($v1 + ($v2 - $v1) * ((2 / 3) - $vH) * 6); + } + + return $v1; + } + + /** + * Checks the HEX string for correct formatting and converts short format to long + * @param string $hex + * @return string + * @throws Exception + */ + private static function sanitizeHex(string $hex): string + { + // Strip # sign if it is present + $color = str_replace("#", "", $hex); + + // Validate hex string + if (!preg_match('/^[a-fA-F0-9]+$/', $color)) { + throw new Exception("HEX color does not match format"); + } + + // Make sure it's 6 digits + if (strlen($color) === 3) { + $color = $color[0] . $color[0] . $color[1] . $color[1] . $color[2] . $color[2]; + } elseif (strlen($color) !== 6) { + throw new Exception("HEX color needs to be 6 or 3 digits long"); + } + + return $color; + } + + /** + * Converts object into its string representation + * @return string + */ + public function __toString() + { + return "#" . $this->getHex(); + } + + /** + * @param string $name + * @return mixed|null + */ + public function __get(string $name) + { + switch (strtolower($name)) { + case 'red': + case 'r': + return $this->_rgb["R"]; + case 'green': + case 'g': + return $this->_rgb["G"]; + case 'blue': + case 'b': + return $this->_rgb["B"]; + case 'hue': + case 'h': + return $this->_hsl["H"]; + case 'saturation': + case 's': + return $this->_hsl["S"]; + case 'lightness': + case 'l': + return $this->_hsl["L"]; + } + + $trace = debug_backtrace(); + trigger_error( + 'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], + E_USER_NOTICE + ); + return null; + } + + /** + * @param string $name + * @param mixed $value + * @throws Exception + */ + public function __set(string $name, $value) + { + switch (strtolower($name)) { + case 'red': + case 'r': + $this->_rgb["R"] = $value; + $this->_hex = self::rgbToHex($this->_rgb); + $this->_hsl = self::hexToHsl($this->_hex); + break; + case 'green': + case 'g': + $this->_rgb["G"] = $value; + $this->_hex = self::rgbToHex($this->_rgb); + $this->_hsl = self::hexToHsl($this->_hex); + break; + case 'blue': + case 'b': + $this->_rgb["B"] = $value; + $this->_hex = self::rgbToHex($this->_rgb); + $this->_hsl = self::hexToHsl($this->_hex); + break; + case 'hue': + case 'h': + $this->_hsl["H"] = $value; + $this->_hex = self::hslToHex($this->_hsl); + $this->_rgb = self::hexToRgb($this->_hex); + break; + case 'saturation': + case 's': + $this->_hsl["S"] = $value; + $this->_hex = self::hslToHex($this->_hsl); + $this->_rgb = self::hexToRgb($this->_hex); + break; + case 'lightness': + case 'light': + case 'l': + $this->_hsl["L"] = $value; + $this->_hex = self::hslToHex($this->_hsl); + $this->_rgb = self::hexToRgb($this->_hex); + break; + } + } +} diff --git a/lib/composer/mexitek/phpcolors/tests/bootstrap.php b/lib/composer/mexitek/phpcolors/tests/bootstrap.php new file mode 100644 index 00000000000..846079601db --- /dev/null +++ b/lib/composer/mexitek/phpcolors/tests/bootstrap.php @@ -0,0 +1,11 @@ + true, + "336699" => true, + "913399" => true, + "E5C3E8" => false, + "D7E8DD" => false, + "218A47" => true, + "3D41CA" => true, + "E5CCDD" => false, + "FFFFFF" => false, +); + +foreach ($isDark as $colorHex => $state) { + $color = new Color($colorHex); + Assert::same($state, $color->isDark(), 'Incorrect dark color analyzed (#' . $colorHex . ').'); +} + +$isLight = array( + "FFFFFF" => true, + "A3FFE5" => true, + "000000" => false, +); + +foreach ($isLight as $colorHex => $state) { + $color = new Color($colorHex); + Assert::same($state, $color->isLight(), 'Incorrect light color analyzed (#' . $colorHex . ').'); +} diff --git a/lib/composer/mexitek/phpcolors/tests/colorChange.phpt b/lib/composer/mexitek/phpcolors/tests/colorChange.phpt new file mode 100644 index 00000000000..373f34efef0 --- /dev/null +++ b/lib/composer/mexitek/phpcolors/tests/colorChange.phpt @@ -0,0 +1,28 @@ + "264d73", + "913399" => "6d2673" +); + +foreach ($expected as $original => $darker) { + $color = new Color($original); + Assert::same($darker, $color->darken(), 'Incorrect darker color returned.'); +} + + +$expected = array( + "336699" => "4080bf", + "913399" => "b540bf" +); + +foreach ($expected as $original => $lighter) { + $color = new Color($original); + Assert::same($lighter, $color->lighten(), "Incorrect lighter color returned."); +} diff --git a/lib/composer/mexitek/phpcolors/tests/colorComplementary.phpt b/lib/composer/mexitek/phpcolors/tests/colorComplementary.phpt new file mode 100644 index 00000000000..2876b5c8b00 --- /dev/null +++ b/lib/composer/mexitek/phpcolors/tests/colorComplementary.phpt @@ -0,0 +1,28 @@ + "00ffff", + "0000ff" => "ffff00", + "00ff00" => "ff00ff", + "ffff00" => "0000ff", + "00ffff" => "ff0000", + "49cbaf" => "cb4965", + "003eb2" => "b27400", + "b27400" => "003eb2", + "ffff99" => "9999ff", + "ccff00" => "3300ff", + "3300ff" => "ccff00", + "fb4a2c" => "2cddfb", + "9cebff" => "ffb09c", +); + +foreach ($expected as $original => $complementary) { + $color = new Color($original); + Assert::same($complementary, $color->complementary(), 'Incorrect complementary color returned.'); +} diff --git a/lib/composer/mexitek/phpcolors/tests/colorConvertHslToHex.phpt b/lib/composer/mexitek/phpcolors/tests/colorConvertHslToHex.phpt new file mode 100644 index 00000000000..fd3adbd0534 --- /dev/null +++ b/lib/composer/mexitek/phpcolors/tests/colorConvertHslToHex.phpt @@ -0,0 +1,72 @@ + 194, + 'S' => 1.0, + 'L' => 0.4, +]; +$yellow = [ + 'H' => 57, + 'S' => 0.91, + 'L' => 0.51, +]; +$black = [ + 'H' => 0, + 'S' => 0.0, + 'L' => 0.0, +]; +$grey = [ + 'H' => 0, + 'S' => 0.0, + 'L' => 0.65, +]; +$white = [ + 'H' => 0, + 'S' => 0.0, + 'L' => 1.0, +]; + +// Test cases. +$colorsToConvert = array( + 'blue' => [ // hsl(194, 100%, 40%) + 'hex' => '009ccc', + 'hsl' => $blue, + ], + 'yellow' => [ // hsl(57, 91%, 51%) + 'hex' => 'f4e810', + 'hsl' => $yellow, + ], + 'black' => [ + 'hex' => '000000', + 'hsl' => $black, + ], + 'grey' => [ + 'hex' => 'a6a6a6', + 'hsl' => $grey, + ], + 'white' => [ + 'hex' => 'ffffff', + 'hsl' => $white, + ], +); + + +foreach ($colorsToConvert as $color) { + $hsl = $color['hsl']; + $hex = $color['hex']; + + $answer = Color::hslToHex($hsl); + Assert::same( + $hex, + $answer, + 'Incorrect hex result: "' . json_encode($hsl) . + '" should convert to "' . $hex . + '", but output was: "' . $answer . '".' + ); +} diff --git a/lib/composer/mexitek/phpcolors/tests/colorConvertNameToHex.phpt b/lib/composer/mexitek/phpcolors/tests/colorConvertNameToHex.phpt new file mode 100644 index 00000000000..e4f87ca740f --- /dev/null +++ b/lib/composer/mexitek/phpcolors/tests/colorConvertNameToHex.phpt @@ -0,0 +1,170 @@ + 'F0F8FF', + 'antiquewhite' => 'FAEBD7', + 'aqua' => '00FFFF', + 'aquamarine' => '7FFFD4', + 'azure' => 'F0FFFF', + 'beige' => 'F5F5DC', + 'bisque' => 'FFE4C4', + 'black' => '000000', + 'blanchedalmond' => 'FFEBCD', + 'blue' => '0000FF', + 'blueviolet' => '8A2BE2', + 'brown' => 'A52A2A', + 'burlywood' => 'DEB887', + 'cadetblue' => '5F9EA0', + 'chartreuse' => '7FFF00', + 'chocolate' => 'D2691E', + 'coral' => 'FF7F50', + 'cornflowerblue' => '6495ED', + 'cornsilk' => 'FFF8DC', + 'crimson' => 'DC143C', + 'cyan' => '00FFFF', + 'darkblue' => '00008B', + 'darkcyan' => '008B8B', + 'darkgoldenrod' => 'B8860B', + 'darkgray' => 'A9A9A9', + 'darkgreen' => '006400', + 'darkgrey' => 'A9A9A9', + 'darkkhaki' => 'BDB76B', + 'darkmagenta' => '8B008B', + 'darkolivegreen' => '556B2F', + 'darkorange' => 'FF8C00', + 'darkorchid' => '9932CC', + 'darkred' => '8B0000', + 'darksalmon' => 'E9967A', + 'darkseagreen' => '8FBC8F', + 'darkslateblue' => '483D8B', + 'darkslategray' => '2F4F4F', + 'darkslategrey' => '2F4F4F', + 'darkturquoise' => '00CED1', + 'darkviolet' => '9400D3', + 'deeppink' => 'FF1493', + 'deepskyblue' => '00BFFF', + 'dimgray' => '696969', + 'dimgrey' => '696969', + 'dodgerblue' => '1E90FF', + 'firebrick' => 'B22222', + 'floralwhite' => 'FFFAF0', + 'forestgreen' => '228B22', + 'fuchsia' => 'FF00FF', + 'gainsboro' => 'DCDCDC', + 'ghostwhite' => 'F8F8FF', + 'gold' => 'FFD700', + 'goldenrod' => 'DAA520', + 'gray' => '808080', + 'green' => '008000', + 'greenyellow' => 'ADFF2F', + 'grey' => '808080', + 'honeydew' => 'F0FFF0', + 'hotpink' => 'FF69B4', + 'indianred' => 'CD5C5C', + 'indigo' => '4B0082', + 'ivory' => 'FFFFF0', + 'khaki' => 'F0E68C', + 'lavender' => 'E6E6FA', + 'lavenderblush' => 'FFF0F5', + 'lawngreen' => '7CFC00', + 'lemonchiffon' => 'FFFACD', + 'lightblue' => 'ADD8E6', + 'lightcoral' => 'F08080', + 'lightcyan' => 'E0FFFF', + 'lightgoldenrodyellow' => 'FAFAD2', + 'lightgray' => 'D3D3D3', + 'lightgreen' => '90EE90', + 'lightgrey' => 'D3D3D3', + 'lightpink' => 'FFB6C1', + 'lightsalmon' => 'FFA07A', + 'lightseagreen' => '20B2AA', + 'lightskyblue' => '87CEFA', + 'lightslategray' => '778899', + 'lightslategrey' => '778899', + 'lightsteelblue' => 'B0C4DE', + 'lightyellow' => 'FFFFE0', + 'lime' => '00FF00', + 'limegreen' => '32CD32', + 'linen' => 'FAF0E6', + 'magenta' => 'FF00FF', + 'maroon' => '800000', + 'mediumaquamarine' => '66CDAA', + 'mediumblue' => '0000CD', + 'mediumorchid' => 'BA55D3', + 'mediumpurple' => '9370D0', + 'mediumseagreen' => '3CB371', + 'mediumslateblue' => '7B68EE', + 'mediumspringgreen' => '00FA9A', + 'mediumturquoise' => '48D1CC', + 'mediumvioletred' => 'C71585', + 'midnightblue' => '191970', + 'mintcream' => 'F5FFFA', + 'mistyrose' => 'FFE4E1', + 'moccasin' => 'FFE4B5', + 'navajowhite' => 'FFDEAD', + 'navy' => '000080', + 'oldlace' => 'FDF5E6', + 'olive' => '808000', + 'olivedrab' => '6B8E23', + 'orange' => 'FFA500', + 'orangered' => 'FF4500', + 'orchid' => 'DA70D6', + 'palegoldenrod' => 'EEE8AA', + 'palegreen' => '98FB98', + 'paleturquoise' => 'AFEEEE', + 'palevioletred' => 'DB7093', + 'papayawhip' => 'FFEFD5', + 'peachpuff' => 'FFDAB9', + 'peru' => 'CD853F', + 'pink' => 'FFC0CB', + 'plum' => 'DDA0DD', + 'powderblue' => 'B0E0E6', + 'purple' => '800080', + 'red' => 'FF0000', + 'rosybrown' => 'BC8F8F', + 'royalblue' => '4169E1', + 'saddlebrown' => '8B4513', + 'salmon' => 'FA8072', + 'sandybrown' => 'F4A460', + 'seagreen' => '2E8B57', + 'seashell' => 'FFF5EE', + 'sienna' => 'A0522D', + 'silver' => 'C0C0C0', + 'skyblue' => '87CEEB', + 'slateblue' => '6A5ACD', + 'slategray' => '708090', + 'slategrey' => '708090', + 'snow' => 'FFFAFA', + 'springgreen' => '00FF7F', + 'steelblue' => '4682B4', + 'tan' => 'D2B48C', + 'teal' => '008080', + 'thistle' => 'D8BFD8', + 'tomato' => 'FF6347', + 'turquoise' => '40E0D0', + 'violet' => 'EE82EE', + 'wheat' => 'F5DEB3', + 'white' => 'FFFFFF', + 'whitesmoke' => 'F5F5F5', + 'yellow' => 'FFFF00', + 'yellowgreen' => '9ACD32' +); + +foreach ($colorsToConvert as $name => $hex) { + $hex = '#' . $hex; + + $answer = Color::nameToHex($name); + Assert::same( + $hex, + $answer, + 'Incorrect hex result: "' . Color::nameToHex($name) . + '" should convert to "' . $hex . + '", but output was: "' . $answer . '".' + ); +} diff --git a/lib/composer/mexitek/phpcolors/tests/colorConvertRgbToHex.phpt b/lib/composer/mexitek/phpcolors/tests/colorConvertRgbToHex.phpt new file mode 100644 index 00000000000..a65f1a7e874 --- /dev/null +++ b/lib/composer/mexitek/phpcolors/tests/colorConvertRgbToHex.phpt @@ -0,0 +1,72 @@ + 0, + 'G' => 158, + 'B' => 204, +]; +$yellow = [ + 'R' => 244, + 'G' => 231, + 'B' => 15, +]; +$black = [ + 'R' => 0, + 'G' => 0, + 'B' => 0, +]; +$white = [ + 'R' => 255, + 'G' => 255, + 'B' => 255, +]; + +// Test cases. +$colorsToConvert = array( + 'blue' => [ // rgb(0, 158, 204) + 'hex' => '009ecc', + 'rgb' => $blue, + ], + 'yellow' => [ // rgb(244, 231, 15) + 'hex' => 'f4e70f', + 'rgb' => $yellow, + ], + 'black' => [ + 'hex' => '000000', + 'rgb' => $black, + ], + 'white' => [ + 'hex' => 'ffffff', + 'rgb' => $white, + ], +); + + +foreach ($colorsToConvert as $color) { + $rgb = $color['rgb']; + $hex = $color['hex']; + + $answer = Color::rgbToHex($rgb); + Assert::same( + $hex, + $answer, + 'Incorrect hex result: "' . Color::rgbToString($rgb) . + '" should convert to "' . $hex . + '", but output was: "' . $answer . '".' + ); + + $revertAnswer = Color::hexToRgb($hex); + Assert::same( + $rgb, + $revertAnswer, + 'Incorrect rgb result: "' . $hex . + '" should convert to "' . Color::rgbToString($rgb) . + '", but output was: "' . Color::rgbToString($revertAnswer) . '".' + ); +} diff --git a/lib/composer/mexitek/phpcolors/tests/colorInput.phpt b/lib/composer/mexitek/phpcolors/tests/colorInput.phpt new file mode 100644 index 00000000000..8ace3057821 --- /dev/null +++ b/lib/composer/mexitek/phpcolors/tests/colorInput.phpt @@ -0,0 +1,19 @@ + array("ff0000", "ff7f7f"), // ffffff + ff0000 = ff7f7f + "00ff00" => array("ff0000", "7f7f00"), + "000000" => array("ff0000", "7f0000"), + "002fff" => array("000000", "00177f"), + "00ffed" => array("000000", "007f76"), + "ff9a00" => array("000000", "7f4d00"), + "ff9a00" => array("ffffff", "ffcc7f"), + "00ff2d" => array("ffffff", "7fff96"), + "8D43B4" => array("35CF64", "61898c"), +); + +foreach ($expected as $original => $complementary) { + $color = new Color($original); + Assert::same($complementary[1], $color->mix($complementary[0]), 'Incorrect mix color returned.'); +} -- cgit v1.2.3 From 850d8ac1cd9e5b28e37668469237d8daa5c5d51d Mon Sep 17 00:00:00 2001 From: John Molakvoæ Date: Fri, 22 Apr 2022 09:56:12 +0200 Subject: Add default theming disabled fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ --- apps/theming/css/default.css | 57 ++++++++ apps/theming/lib/Service/ThemeInjectionService.php | 1 - apps/theming/lib/Service/ThemesService.php | 2 +- apps/theming/tests/Service/ThemesServiceTest.php | 2 +- apps/theming/tests/Themes/DefaultThemeTest.php | 146 +++++++++++++++++++++ lib/private/TemplateLayout.php | 5 + 6 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 apps/theming/css/default.css create mode 100644 apps/theming/tests/Themes/DefaultThemeTest.php (limited to 'lib') diff --git a/apps/theming/css/default.css b/apps/theming/css/default.css new file mode 100644 index 00000000000..f7bf3a20d09 --- /dev/null +++ b/apps/theming/css/default.css @@ -0,0 +1,57 @@ +:root { + --color-main-background: #ffffff; + --color-main-background-rgb: 255,255,255; + --color-main-background-translucent: rgba(var(--color-main-background-rgb), .97); + --gradient-main-background: var(--color-main-background) 0%, var(--color-main-background-translucent) 85%, transparent 100%; + --color-background-hover: #f5f5f5; + --color-background-dark: #ededed; + --color-background-darker: #dbdbdb; + --color-placeholder-light: #e6e6e6; + --color-placeholder-dark: #cccccc; + --color-primary: #0082c9; + --color-primary-text: #ffffff; + --color-primary-hover: #198ece; + --color-primary-light: #72bae1; + --color-primary-light-text: #0082c9; + --color-primary-light-hover: #0f567d; + --color-primary-text-dark: #ededed; + --color-primary-element: #0082c9; + --color-primary-element-hover: #198ece; + --color-primary-element-light: #17adff; + --color-primary-element-lighter: #6cb7df; + --color-main-text: #222222; + --color-text-maxcontrast: #767676; + --color-text-light: #222222; + --color-text-lighter: #767676; + --color-error: #e9322d; + --color-error-hover: #eb4642; + --color-warning: #eca700; + --color-warning-hover: #edaf19; + --color-success: #46ba61; + --color-success-hover: #58c070; + --color-loading-light: #cccccc; + --color-loading-dark: #444444; + --color-box-shadow-rgb: 77,77,77; + --color-box-shadow: rgba(var(--color-box-shadow-rgb), 0.5); + --color-border: #ededed; + --color-border-dark: #dbdbdb; + --font-face: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Cantarell, Ubuntu, 'Helvetica Neue', Arial, sans-serif, 'Noto Color Emoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; + --default-font-size: 15px; + --animation-quick: 100ms; + --animation-slow: 300ms; + --border-radius: 3px; + --border-radius-large: 10px; + --border-radius-pill: 100px; + --default-line-height: 24px; + --header-height: 50px; + --navigation-width: 300px; + --sidebar-min-width: 300px; + --sidebar-max-width: 500px; + --list-min-width: 200px; + --list-max-width: 300px; + --header-menu-item-height: 44px; + --header-menu-profile-item-height: 66px; + --breakpoint-mobile: 1024px; + --primary-invert-if-bright: unset; + --background-invert-if-dark: unset; +} diff --git a/apps/theming/lib/Service/ThemeInjectionService.php b/apps/theming/lib/Service/ThemeInjectionService.php index 81edc19bc4b..fec14de96cf 100644 --- a/apps/theming/lib/Service/ThemeInjectionService.php +++ b/apps/theming/lib/Service/ThemeInjectionService.php @@ -22,7 +22,6 @@ */ namespace OCA\Theming\Service; -use OCA\Theming\AppInfo\Application; use OCA\Theming\Themes\DefaultTheme; use OCP\IURLGenerator; use OCP\Util; diff --git a/apps/theming/lib/Service/ThemesService.php b/apps/theming/lib/Service/ThemesService.php index c2e9e2b24bf..01ebc3fb504 100644 --- a/apps/theming/lib/Service/ThemesService.php +++ b/apps/theming/lib/Service/ThemesService.php @@ -99,7 +99,7 @@ class ThemesService { return $t->getId(); }, array_values($filteredThemes)); - $enabledThemes = [...array_diff($themesIds, $filteredThemesIds), $theme->getId()]; + $enabledThemes = array_merge(array_diff($themesIds, $filteredThemesIds), [$theme->getId()]); $this->setEnabledThemes($enabledThemes); return $enabledThemes; diff --git a/apps/theming/tests/Service/ThemesServiceTest.php b/apps/theming/tests/Service/ThemesServiceTest.php index 64f461c88a7..2d0d313f9e4 100644 --- a/apps/theming/tests/Service/ThemesServiceTest.php +++ b/apps/theming/tests/Service/ThemesServiceTest.php @@ -55,7 +55,7 @@ use OCP\IUserSession; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; -class UserThemeControllerTest extends TestCase { +class ThemesServiceTest extends TestCase { /** @var ThemesService */ private $themesService; diff --git a/apps/theming/tests/Themes/DefaultThemeTest.php b/apps/theming/tests/Themes/DefaultThemeTest.php new file mode 100644 index 00000000000..d3494b1c304 --- /dev/null +++ b/apps/theming/tests/Themes/DefaultThemeTest.php @@ -0,0 +1,146 @@ + + * + * @author Bjoern Schiessle + * @author Christoph Wurst + * @author Daniel Calviño Sánchez + * @author Joas Schilling + * @author John Molakvoæ + * @author Julius Haertl + * @author Julius Härtl + * @author Kyle Fazzari + * @author Lukas Reschke + * @author Michael Weimann + * @author rakekniven + * @author Roeland Jago Douma + * + * @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 . + * + */ +namespace OCA\Theming\Tests\Service; + +use OC\App\AppManager; +use OCA\Theming\ImageManager; +use OCA\Theming\ITheme; +use OCA\Theming\Themes\DefaultTheme; +use OCA\Theming\ThemingDefaults; +use OCA\Theming\Util; +use OCP\Files\IAppData; +use OCP\IConfig; +use OCP\IL10N; +use OCP\IURLGenerator; +use PHPUnit\Framework\MockObject\MockObject; +use Test\TestCase; + + +class DefaultThemeTest extends TestCase { + /** @var ThemingDefaults|MockObject */ + private $themingDefaults; + /** @var IURLGenerator|MockObject */ + private $urlGenerator; + /** @var ImageManager|MockObject */ + private $imageManager; + /** @var IConfig|MockObject */ + private $config; + /** @var IL10N|MockObject */ + private $l10n; + + private DefaultTheme $defaultTheme; + + protected function setUp(): void { + $this->themingDefaults = $this->createMock(ThemingDefaults::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->imageManager = $this->createMock(ImageManager::class); + $this->config = $this->createMock(IConfig::class); + $this->l10n = $this->createMock(IL10N::class); + + $util = new Util( + $this->config, + $this->createMock(AppManager::class), + $this->createMock(IAppData::class) + ); + + $this->themingDefaults + ->expects($this->any()) + ->method('getColorPrimary') + ->willReturn('#0082c9'); + + $this->l10n + ->expects($this->any()) + ->method('t') + ->willReturnCallback(function ($text, $parameters = []) { + return vsprintf($text, $parameters); + }); + + $this->defaultTheme = new DefaultTheme( + $util, + $this->themingDefaults, + $this->urlGenerator, + $this->imageManager, + $this->config, + $this->l10n, + ); + + parent::setUp(); + } + + + public function testGetId() { + $this->assertEquals('default', $this->defaultTheme->getId()); + } + + public function testGetType() { + $this->assertEquals(ITheme::TYPE_THEME, $this->defaultTheme->getType()); + } + + public function testGetTitle() { + $this->assertEquals('Light theme', $this->defaultTheme->getTitle()); + } + + public function testGetEnableLabel() { + $this->assertEquals('Enable the default light theme', $this->defaultTheme->getEnableLabel()); + } + + public function testGetDescription() { + $this->assertEquals('The default light appearance.', $this->defaultTheme->getDescription()); + } + + public function testGetMediaQuery() { + $this->assertEquals('', $this->defaultTheme->getMediaQuery()); + } + + public function testGetCustomCss() { + $this->assertEquals('', $this->defaultTheme->getCustomCss()); + } + + /** + * Ensure parity between the default theme and the static generated file + * @see ThemingController.php:313 + */ + public function testThemindDisabledFallbackCss() { + // Generate variables + $variables = ''; + foreach ($this->defaultTheme->getCSSVariables() as $variable => $value) { + $variables .= " $variable: $value;" . PHP_EOL; + }; + + $css = ":root { " . PHP_EOL . "$variables}" . PHP_EOL; + $fallbackCss = file_get_contents(__DIR__ . '/../../css/default.css'); + + $this->assertEquals($css, $fallbackCss); + } +} diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index b49ba49ebb8..4b53af37679 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -81,6 +81,11 @@ class TemplateLayout extends \OC_Template { /** @var IInitialStateService */ $this->initialState = \OC::$server->get(IInitialStateService::class); + // Add fallback theming variables if theming is disabled + if (!\OC::$server->getAppManager()->isEnabledForUser('theming')) { + // TODO cache generated default theme if enabled for fallback if server is erroring ? + Util::addStyle('theming', 'default'); + } // Decide which page we show if ($renderAs === TemplateResponse::RENDER_AS_USER) { -- cgit v1.2.3