From f527349d279f50984312dd6458ff5651061c45e9 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 30 Dec 2021 17:02:24 -0700 Subject: [PATCH 1/4] Updated library and added name_to_hex filter/function - Fixes #4 --- CHANGELOG.md | 7 + README.md | 17 +- classes/Color.php | 589 +------------------------- color-tools.php | 10 + composer.json | 5 +- composer.lock | 69 ++- vendor/composer/ClassLoader.php | 157 ++++++- vendor/composer/InstalledVersions.php | 350 +++++++++++++++ vendor/composer/autoload_classmap.php | 2 + vendor/composer/autoload_real.php | 6 +- vendor/composer/autoload_static.php | 2 + vendor/composer/installed.json | 64 ++- vendor/composer/installed.php | 34 ++ vendor/composer/platform_check.php | 26 ++ 14 files changed, 726 insertions(+), 612 deletions(-) create mode 100644 vendor/composer/InstalledVersions.php create mode 100644 vendor/composer/installed.php create mode 100644 vendor/composer/platform_check.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 457e4a8..f1128e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# v1.1.0 +## mm/dd/2021 + +1. [](#new) + * Updated to `dev-master` of `Mexitek/PHPColors` to get latest functionality + * Added `name_to_hex` Twig function and filter [#4](https://github.com/trilbymedia/grav-plugin-color-tools/issues/4) + # v1.0.2 ## 12/23/2021 diff --git a/README.md b/README.md index 32c92e7..ff65a17 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,12 @@ The **Color Tools** Plugin is an extension for [Grav CMS](http://github.com/getg * `lighten()` * `makeGradient()` * `mix()` +* `nameToHex()` * `rgbToHex()` * `rgbToString()` +More information can be found on the GitHub site for the library: https://github.com/mexitek/phpColors + ## Installation Installing the Color Tools plugin can be done in one of three ways: The GPM (Grav Package Manager) installation method lets you quickly install the plugin with a simple terminal command, the manual method lets you do so via a zip file, and the admin method lets you do so via the Admin Plugin. @@ -60,6 +63,18 @@ A `color()` function is also available: {{ orange_color.darken(20) }} ``` +To use the `name_to_hex` function or twig: + +```twig +{{ name_to_hex('chartreuse') }} + +or + +{{ 'lavender'|name_to_hex }} +``` + +Full list of color names: https://github.com/mexitek/phpColors/blob/master/src/Mexitek/PHPColors/Color.php#L241 + ## PHP Usage To use this class in PHP is also quite simple, an example that mimic above can be seen below: @@ -76,4 +91,4 @@ $button_css_class = $button_color->isLight() ? 'text-dark' : 'text-light'; ## Credits -The PHP class used was originally developed by Arlo Carreon , then modified by Trilby Media. +The PHP class used was originally developed by Arlo Carreon in [mexitek/phpColors](https://github.com/mexitek/phpColors), then modified by Trilby Media. diff --git a/classes/Color.php b/classes/Color.php index 6e91ece..4ac83ee 100644 --- a/classes/Color.php +++ b/classes/Color.php @@ -2,598 +2,17 @@ /** * Author: Arlo Carreon - * Modified: Andy Miller + * Grav integration: Andy Miller * Info: http://mexitek.github.io/phpColors/ * License: http://arlo.mit-license.org/ */ namespace Grav\Plugin\ColorTools; -use \Exception; - /** * A color utility that helps manipulate HEX colors */ -class Color { - - private $_hex; - private $_hsl; - 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) - */ - const DEFAULT_ADJUST = 10; - - /** - * Instantiates the class with a HEX value - * @param string $hex - * @throws Exception "Bad color format" - */ - function __construct( $hex ) { - // Strip # sign is present - $color = str_replace("#", "", $hex); - - // Make sure it's 6 digits - if( strlen($color) === 3 ) { - $color = $color[0].$color[0].$color[1].$color[1].$color[2].$color[2]; - } else if( strlen($color) != 6 ) { - throw new Exception("HEX color needs to be 6 or 3 digits long"); - } - - $this->_hsl = self::hexToHsl( $color ); - $this->_hex = $color; - $this->_rgb = self::hexToRgb( $color ); - } - - // ==================== - // = Public Interface = - // ==================== - - /** - * Given a HEX string returns a HSL array equivalent. - * @param string $color - * @return array HSL associative array - */ - public static function hexToHsl( $color ){ - - // Sanity check - $color = self::_checkHex($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; - else if ($var_G == $var_Max) $H = ( 1 / 3 ) + $del_R - $del_B; - else if ($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( $hsl = array() ){ - // Make sure it's HSL - if(empty($hsl) || !isset($hsl["H"]) || !isset($hsl["S"]) || !isset($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 = round(255 * self::_huetorgb( $var_1, $var_2, $H + (1/3) )); - $g = round(255 * self::_huetorgb( $var_1, $var_2, $H )); - $b = round(255 * self::_huetorgb( $var_1, $var_2, $H - (1/3) )); - - } - - // Convert to hex - $r = dechex($r); - $g = dechex($g); - $b = dechex($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 - */ - public static function hexToRgb( $color ){ - - // Sanity check - $color = self::_checkHex($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( $rgb = array() ){ - // Make sure it's RGB - if(empty($rgb) || !isset($rgb["R"]) || !isset($rgb["G"]) || !isset($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($rgb['R']), 2, '0', STR_PAD_LEFT); - $hex[1] = str_pad(dechex($rgb['G']), 2, '0', STR_PAD_LEFT); - $hex[2] = str_pad(dechex($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( $rgb = array() ){ - // Make sure it's RGB - if(empty($rgb) || !isset($rgb["R"]) || !isset($rgb["G"]) || !isset($rgb["B"]) ) { - throw new Exception("Param was not an RGB array"); - } - - return 'rgb('. - $rgb['R'] . ', ' . - $rgb['G'] . ', ' . - $rgb['B'] . ')'; - } - - - - /** - * 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 - */ - public function darken( $amount = self::DEFAULT_ADJUST ){ - // Darken - $darkerHSL = $this->_darken($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 - */ - public function lighten( $amount = self::DEFAULT_ADJUST ){ - // Lighten - $lighterHSL = $this->_lighten($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 - */ - public function mix($hex2, $amount = 0){ - $rgb2 = self::hexToRgb($hex2); - $mixed = $this->_mix($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 - */ - public function makeGradient( $amount = self::DEFAULT_ADJUST ) { - // 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|Boolean $color - * @param int $lighterThan - * @return boolean - */ - public function isLight( $color = FALSE, $lighterThan = 130 ){ - // Get our 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|Boolean $color - * @param int $darkerThan - * @return boolean - */ - public function isDark( $color = FALSE, $darkerThan = 130 ){ - // 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 - * - */ - public function complementary() { - // 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 your color's HSL array - */ - public function getHsl() { - return $this->_hsl; - } - /** - * Returns your original color - */ - public function getHex() { - return $this->_hex; - } - /** - * Returns your color's RGB array - */ - public function getRgb() { - 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 - * @link http://caniuse.com/css-gradients Resource for the browser support - * @return string CSS3 gradient for chrome, safari, firefox, opera and IE10 - */ - public function getCssGradient( $amount = self::DEFAULT_ADJUST, $vintageBrowsers = FALSE, $suffix = "" , $prefix = "" ) { - - // 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}"; - - /* Firefox 3.6+ */ - if ( $vintageBrowsers ) { - $css .= "{$prefix}background-image: -moz-linear-gradient(top, #".$g['light'].", #".$g['dark'].");{$suffix}"; - } - - /* Opera 11.10+ */ - if ( $vintageBrowsers ) { - $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; - } - - // =========================== - // = Private Functions Below = - // =========================== - - - /** - * Darkens a given HSL array - * @param array $hsl - * @param int $amount - * @return array $hsl - */ - private function _darken( $hsl, $amount = self::DEFAULT_ADJUST){ - // 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'] = $hsl['L']/2 ; - } - - return $hsl; - } - - /** - * Lightens a given HSL array - * @param array $hsl - * @param int $amount - * @return array $hsl - */ - private function _lighten( $hsl, $amount = self::DEFAULT_ADJUST){ - // 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 2 rgb colors and return an rgb color - * @param array $rgb1 - * @param array $rgb2 - * @param int $amount ranged -100..0..+100 - * @return array $rgb - * - * ported from http://phpxref.pagelines.com/nav.html?includes/class.colors.php.source.html - */ - private function _mix($rgb1, $rgb2, $amount = 0) { - - $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 int $v1 - * @param int $v2 - * @param int $vH - * @return int - */ - private static function _huetorgb( $v1,$v2,$vH ) { - if( $vH < 0 ) { - $vH += 1; - } - - if( $vH > 1 ) { - $vH -= 1; - } - - 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; - - } - - /** - * You need to check if you were given a good hex string - * @param string $hex - * @return string Color - * @throws Exception "Bad color format" - */ - private static function _checkHex( $hex ) { - // Strip # sign is present - $color = str_replace("#", "", $hex); - - if (preg_match('/^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/', $hex)) { - if( strlen($color) === 3 ) { - $color = $color[0] . $color[0] . $color[1] . $color[1] . $color[2] . $color[2]; - } - } else { - throw new Exception("HEX color needs to be 6 or 3 digits long"); - } - - return $color; - } - - /** - * Converts object into its string representation - * @return string Color - */ - public function __toString() { - return "#".$this->getHex(); - } - - public function __get($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"]; - } - } - - public function __set($name, $value) - { - switch (strtolower($name)) - { - case 'red': - case 'r': - $this->_rgb["R"] = $value; - $this->_hex = $this->rgbToHex($this->_rgb); - $this->_hsl = $this->hexToHsl($this->_hex); - break; - case 'green': - case 'g': - $this->_rgb["G"] = $value; - $this->_hex = $this->rgbToHex($this->_rgb); - $this->_hsl = $this->hexToHsl($this->_hex); - break; - case 'blue': - case 'b': - $this->_rgb["B"] = $value; - $this->_hex = $this->rgbToHex($this->_rgb); - $this->_hsl = $this->hexToHsl($this->_hex); - break; - case 'hue': - case 'h': - $this->_hsl["H"] = $value; - $this->_hex = $this->hslToHex($this->_hsl); - $this->_rgb = $this->hexToRgb($this->_hex); - break; - case 'saturation': - case 's': - $this->_hsl["S"] = $value; - $this->_hex = $this->hslToHex($this->_hsl); - $this->_rgb = $this->hexToRgb($this->_hex); - break; - case 'lightness': - case 'light': - case 'l': - $this->_hsl["L"] = $value; - $this->_hex = $this->hslToHex($this->_hsl); - $this->_rgb = $this->hexToRgb($this->_hex); - break; - } - } +class Color extends \Mexitek\PHPColors\Color +{ + // Allow for custom methods as needed } -?> \ No newline at end of file diff --git a/color-tools.php b/color-tools.php index 4e516f2..589a44f 100644 --- a/color-tools.php +++ b/color-tools.php @@ -70,6 +70,16 @@ public function onTwigInitialized() return new Color($hex); }) ); + $this->grav['twig']->twig()->addFunction( + new \Twig\TwigFunction('name_to_hex', function ($name) { + return Color::nameToHex($name); + }) + ); + $this->grav['twig']->twig()->addFilter( + new \Twig\TwigFilter('name_to_hex', function ($name) { + return Color::nameToHex($name); + }) + ); } } diff --git a/composer.json b/composer.json index a4e4ade..3d60953 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ } ], "require": { - "php": ">=7.1.3" + "php": ">=7.3.6", + "mexitek/phpcolors": "dev-master" }, "autoload": { "psr-4": { @@ -23,7 +24,7 @@ }, "config": { "platform": { - "php": "7.1.3" + "php": "7.3.6" } } } diff --git a/composer.lock b/composer.lock index 05f38be..51911aa 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,77 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "94cd801a0ddd9af23bec6d752535dfe3", - "packages": [], + "content-hash": "3bd2defe9e51fc5d6b2b146fe29bfa52", + "packages": [ + { + "name": "mexitek/phpcolors", + "version": "dev-master", + "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" + }, + "default-branch": true, + "type": "library", + "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" + }, + "time": "2021-11-26T13:19:08+00:00" + } + ], "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "mexitek/phpcolors": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.1.3" + "php": ">=7.3.6" }, "platform-dev": [], "platform-overrides": { - "php": "7.1.3" + "php": "7.3.6" }, - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.1.0" } diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index fce8549..0cd6055 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -37,57 +37,130 @@ * * @author Fabien Potencier * @author Jordi Boggiano - * @see http://www.php-fig.org/psr/psr-0/ - * @see http://www.php-fig.org/psr/psr-4/ + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ */ class ClassLoader { + /** @var ?string */ + private $vendorDir; + // PSR-4 + /** + * @var array[] + * @psalm-var array> + */ private $prefixLengthsPsr4 = array(); + /** + * @var array[] + * @psalm-var array> + */ private $prefixDirsPsr4 = array(); + /** + * @var array[] + * @psalm-var array + */ private $fallbackDirsPsr4 = array(); // PSR-0 + /** + * @var array[] + * @psalm-var array> + */ private $prefixesPsr0 = array(); + /** + * @var array[] + * @psalm-var array + */ private $fallbackDirsPsr0 = array(); + /** @var bool */ private $useIncludePath = false; + + /** + * @var string[] + * @psalm-var array + */ private $classMap = array(); + + /** @var bool */ private $classMapAuthoritative = false; + + /** + * @var bool[] + * @psalm-var array + */ private $missingClasses = array(); + + /** @var ?string */ private $apcuPrefix; + /** + * @var self[] + */ + private static $registeredLoaders = array(); + + /** + * @param ?string $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + } + + /** + * @return string[] + */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', $this->prefixesPsr0); + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); } return array(); } + /** + * @return array[] + * @psalm-return array> + */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } + /** + * @return array[] + * @psalm-return array + */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } + /** + * @return array[] + * @psalm-return array + */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } + /** + * @return string[] Array of classname => path + * @psalm-var array + */ public function getClassMap() { return $this->classMap; } /** - * @param array $classMap Class to filename map + * @param string[] $classMap Class to filename map + * @psalm-param array $classMap + * + * @return void */ public function addClassMap(array $classMap) { @@ -102,9 +175,11 @@ public function addClassMap(array $classMap) * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void */ public function add($prefix, $paths, $prepend = false) { @@ -147,11 +222,13 @@ public function add($prefix, $paths, $prepend = false) * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException + * + * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { @@ -195,8 +272,10 @@ public function addPsr4($prefix, $paths, $prepend = false) * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 base directories + * + * @return void */ public function set($prefix, $paths) { @@ -211,10 +290,12 @@ public function set($prefix, $paths) * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException + * + * @return void */ public function setPsr4($prefix, $paths) { @@ -234,6 +315,8 @@ public function setPsr4($prefix, $paths) * Turns on searching the include path for class files. * * @param bool $useIncludePath + * + * @return void */ public function setUseIncludePath($useIncludePath) { @@ -256,6 +339,8 @@ public function getUseIncludePath() * that have not been registered with the class map. * * @param bool $classMapAuthoritative + * + * @return void */ public function setClassMapAuthoritative($classMapAuthoritative) { @@ -276,6 +361,8 @@ public function isClassMapAuthoritative() * APCu prefix to use to cache found/not-found classes, if the extension is enabled. * * @param string|null $apcuPrefix + * + * @return void */ public function setApcuPrefix($apcuPrefix) { @@ -296,25 +383,44 @@ public function getApcuPrefix() * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } } /** * Unregisters this instance as an autoloader. + * + * @return void */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } } /** * Loads the given class or interface. * * @param string $class The name of the class - * @return bool|null True if loaded, null otherwise + * @return true|null True if loaded, null otherwise */ public function loadClass($class) { @@ -323,6 +429,8 @@ public function loadClass($class) return true; } + + return null; } /** @@ -367,6 +475,21 @@ public function findFile($class) return $file; } + /** + * Returns the currently registered loaders indexed by their corresponding vendor directories. + * + * @return self[] + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ private function findFileWithExtension($class, $ext) { // PSR-4 lookup @@ -438,6 +561,10 @@ private function findFileWithExtension($class, $ext) * Scope isolated include. * * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + * @private */ function includeFile($file) { diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php new file mode 100644 index 0000000..d50e0c9 --- /dev/null +++ b/vendor/composer/InstalledVersions.php @@ -0,0 +1,350 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints($constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + 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') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + 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') { + self::$installed = require __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + $installed[] = self::$installed; + + return $installed; + } +} diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 7bc6835..4890421 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -6,5 +6,7 @@ $baseDir = dirname($vendorDir); return array( + 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'Grav\\Plugin\\ColorToolsPlugin' => $baseDir . '/color-tools.php', + 'Mexitek\\PHPColors\\Color' => $vendorDir . '/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php', ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 20d91f9..97616c5 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -22,13 +22,15 @@ public static function getLoader() return self::$loader; } + require __DIR__ . '/platform_check.php'; + spl_autoload_register(array('ComposerAutoloaderInitc86e4df7714fddc74885de4c86d6c390', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); spl_autoload_unregister(array('ComposerAutoloaderInitc86e4df7714fddc74885de4c86d6c390', 'loadClassLoader')); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { - require_once __DIR__ . '/autoload_static.php'; + require __DIR__ . '/autoload_static.php'; call_user_func(\Composer\Autoload\ComposerStaticInitc86e4df7714fddc74885de4c86d6c390::getInitializer($loader)); } else { diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 949ddfc..deed25a 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -21,7 +21,9 @@ class ComposerStaticInitc86e4df7714fddc74885de4c86d6c390 ); public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'Grav\\Plugin\\ColorToolsPlugin' => __DIR__ . '/../..' . '/color-tools.php', + 'Mexitek\\PHPColors\\Color' => __DIR__ . '/..' . '/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index fe51488..6d51f6f 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1 +1,63 @@ -[] +{ + "packages": [ + { + "name": "mexitek/phpcolors", + "version": "dev-master", + "version_normalized": "dev-master", + "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", + "default-branch": true, + "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": true, + "dev-package-names": [] +} diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php new file mode 100644 index 0000000..5d178ca --- /dev/null +++ b/vendor/composer/installed.php @@ -0,0 +1,34 @@ + array( + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'type' => 'grav-plugin', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => '6e6feb52a5293618f56865e3fc1ee4f3ad91036d', + 'name' => 'trilbymedia/color-tools', + 'dev' => true, + ), + 'versions' => array( + 'mexitek/phpcolors' => array( + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'type' => 'library', + 'install_path' => __DIR__ . '/../mexitek/phpcolors', + 'aliases' => array( + 0 => '9999999-dev', + ), + 'reference' => '4043974240ca7dc3c2bec3c158588148b605b206', + 'dev_requirement' => false, + ), + 'trilbymedia/color-tools' => array( + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'type' => 'grav-plugin', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => '6e6feb52a5293618f56865e3fc1ee4f3ad91036d', + 'dev_requirement' => false, + ), + ), +); diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php new file mode 100644 index 0000000..0109125 --- /dev/null +++ b/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 70306)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.6". 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 + ); +} From b38471a08ca633e9f13a9a5b0c5a4dd58cead7f7 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Mon, 3 Jan 2022 09:07:31 -0700 Subject: [PATCH 2/4] remove temporarily --- vendor/autoload.php | 7 - vendor/composer/ClassLoader.php | 572 ------------------------ vendor/composer/InstalledVersions.php | 350 --------------- vendor/composer/LICENSE | 21 - vendor/composer/autoload_classmap.php | 12 - vendor/composer/autoload_namespaces.php | 9 - vendor/composer/autoload_psr4.php | 10 - vendor/composer/autoload_real.php | 57 --- vendor/composer/autoload_static.php | 38 -- vendor/composer/installed.json | 63 --- vendor/composer/installed.php | 34 -- vendor/composer/platform_check.php | 26 -- vendor/mexitek/phpcolors | 1 - 13 files changed, 1200 deletions(-) delete mode 100644 vendor/autoload.php delete mode 100644 vendor/composer/ClassLoader.php delete mode 100644 vendor/composer/InstalledVersions.php delete mode 100644 vendor/composer/LICENSE delete mode 100644 vendor/composer/autoload_classmap.php delete mode 100644 vendor/composer/autoload_namespaces.php delete mode 100644 vendor/composer/autoload_psr4.php delete mode 100644 vendor/composer/autoload_real.php delete mode 100644 vendor/composer/autoload_static.php delete mode 100644 vendor/composer/installed.json delete mode 100644 vendor/composer/installed.php delete mode 100644 vendor/composer/platform_check.php delete mode 160000 vendor/mexitek/phpcolors diff --git a/vendor/autoload.php b/vendor/autoload.php deleted file mode 100644 index b647c2e..0000000 --- a/vendor/autoload.php +++ /dev/null @@ -1,7 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Autoload; - -/** - * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. - * - * $loader = new \Composer\Autoload\ClassLoader(); - * - * // register classes with namespaces - * $loader->add('Symfony\Component', __DIR__.'/component'); - * $loader->add('Symfony', __DIR__.'/framework'); - * - * // activate the autoloader - * $loader->register(); - * - * // to enable searching the include path (eg. for PEAR packages) - * $loader->setUseIncludePath(true); - * - * In this example, if you try to use a class in the Symfony\Component - * namespace or one of its children (Symfony\Component\Console for instance), - * the autoloader will first look for the class under the component/ - * directory, and it will then fallback to the framework/ directory if not - * found before giving up. - * - * This class is loosely based on the Symfony UniversalClassLoader. - * - * @author Fabien Potencier - * @author Jordi Boggiano - * @see https://www.php-fig.org/psr/psr-0/ - * @see https://www.php-fig.org/psr/psr-4/ - */ -class ClassLoader -{ - /** @var ?string */ - private $vendorDir; - - // PSR-4 - /** - * @var array[] - * @psalm-var array> - */ - private $prefixLengthsPsr4 = array(); - /** - * @var array[] - * @psalm-var array> - */ - private $prefixDirsPsr4 = array(); - /** - * @var array[] - * @psalm-var array - */ - private $fallbackDirsPsr4 = array(); - - // PSR-0 - /** - * @var array[] - * @psalm-var array> - */ - private $prefixesPsr0 = array(); - /** - * @var array[] - * @psalm-var array - */ - private $fallbackDirsPsr0 = array(); - - /** @var bool */ - private $useIncludePath = false; - - /** - * @var string[] - * @psalm-var array - */ - private $classMap = array(); - - /** @var bool */ - private $classMapAuthoritative = false; - - /** - * @var bool[] - * @psalm-var array - */ - private $missingClasses = array(); - - /** @var ?string */ - private $apcuPrefix; - - /** - * @var self[] - */ - private static $registeredLoaders = array(); - - /** - * @param ?string $vendorDir - */ - public function __construct($vendorDir = null) - { - $this->vendorDir = $vendorDir; - } - - /** - * @return string[] - */ - public function getPrefixes() - { - if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); - } - - return array(); - } - - /** - * @return array[] - * @psalm-return array> - */ - public function getPrefixesPsr4() - { - return $this->prefixDirsPsr4; - } - - /** - * @return array[] - * @psalm-return array - */ - public function getFallbackDirs() - { - return $this->fallbackDirsPsr0; - } - - /** - * @return array[] - * @psalm-return array - */ - public function getFallbackDirsPsr4() - { - return $this->fallbackDirsPsr4; - } - - /** - * @return string[] Array of classname => path - * @psalm-var array - */ - public function getClassMap() - { - return $this->classMap; - } - - /** - * @param string[] $classMap Class to filename map - * @psalm-param array $classMap - * - * @return void - */ - public function addClassMap(array $classMap) - { - if ($this->classMap) { - $this->classMap = array_merge($this->classMap, $classMap); - } else { - $this->classMap = $classMap; - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, either - * appending or prepending to the ones previously set for this prefix. - * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories - * - * @return void - */ - public function add($prefix, $paths, $prepend = false) - { - if (!$prefix) { - if ($prepend) { - $this->fallbackDirsPsr0 = array_merge( - (array) $paths, - $this->fallbackDirsPsr0 - ); - } else { - $this->fallbackDirsPsr0 = array_merge( - $this->fallbackDirsPsr0, - (array) $paths - ); - } - - return; - } - - $first = $prefix[0]; - if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; - - return; - } - if ($prepend) { - $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, - $this->prefixesPsr0[$first][$prefix] - ); - } else { - $this->prefixesPsr0[$first][$prefix] = array_merge( - $this->prefixesPsr0[$first][$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, either - * appending or prepending to the ones previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories - * - * @throws \InvalidArgumentException - * - * @return void - */ - public function addPsr4($prefix, $paths, $prepend = false) - { - if (!$prefix) { - // Register directories for the root namespace. - if ($prepend) { - $this->fallbackDirsPsr4 = array_merge( - (array) $paths, - $this->fallbackDirsPsr4 - ); - } else { - $this->fallbackDirsPsr4 = array_merge( - $this->fallbackDirsPsr4, - (array) $paths - ); - } - } elseif (!isset($this->prefixDirsPsr4[$prefix])) { - // Register directories for a new namespace. - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } elseif ($prepend) { - // Prepend directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, - $this->prefixDirsPsr4[$prefix] - ); - } else { - // Append directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - $this->prefixDirsPsr4[$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, - * replacing any others previously set for this prefix. - * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 base directories - * - * @return void - */ - public function set($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr0 = (array) $paths; - } else { - $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, - * replacing any others previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories - * - * @throws \InvalidArgumentException - * - * @return void - */ - public function setPsr4($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr4 = (array) $paths; - } else { - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } - } - - /** - * Turns on searching the include path for class files. - * - * @param bool $useIncludePath - * - * @return void - */ - public function setUseIncludePath($useIncludePath) - { - $this->useIncludePath = $useIncludePath; - } - - /** - * Can be used to check if the autoloader uses the include path to check - * for classes. - * - * @return bool - */ - public function getUseIncludePath() - { - return $this->useIncludePath; - } - - /** - * Turns off searching the prefix and fallback directories for classes - * that have not been registered with the class map. - * - * @param bool $classMapAuthoritative - * - * @return void - */ - public function setClassMapAuthoritative($classMapAuthoritative) - { - $this->classMapAuthoritative = $classMapAuthoritative; - } - - /** - * Should class lookup fail if not found in the current class map? - * - * @return bool - */ - public function isClassMapAuthoritative() - { - return $this->classMapAuthoritative; - } - - /** - * APCu prefix to use to cache found/not-found classes, if the extension is enabled. - * - * @param string|null $apcuPrefix - * - * @return void - */ - public function setApcuPrefix($apcuPrefix) - { - $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; - } - - /** - * The APCu prefix in use, or null if APCu caching is not enabled. - * - * @return string|null - */ - public function getApcuPrefix() - { - return $this->apcuPrefix; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - * - * @return void - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - - if (null === $this->vendorDir) { - return; - } - - if ($prepend) { - self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; - } else { - unset(self::$registeredLoaders[$this->vendorDir]); - self::$registeredLoaders[$this->vendorDir] = $this; - } - } - - /** - * Unregisters this instance as an autoloader. - * - * @return void - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - - if (null !== $this->vendorDir) { - unset(self::$registeredLoaders[$this->vendorDir]); - } - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * @return true|null True if loaded, null otherwise - */ - public function loadClass($class) - { - if ($file = $this->findFile($class)) { - includeFile($file); - - return true; - } - - return null; - } - - /** - * Finds the path to the file where the class is defined. - * - * @param string $class The name of the class - * - * @return string|false The path if found, false otherwise - */ - public function findFile($class) - { - // class map lookup - if (isset($this->classMap[$class])) { - return $this->classMap[$class]; - } - if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { - return false; - } - if (null !== $this->apcuPrefix) { - $file = apcu_fetch($this->apcuPrefix.$class, $hit); - if ($hit) { - return $file; - } - } - - $file = $this->findFileWithExtension($class, '.php'); - - // Search for Hack files if we are running on HHVM - if (false === $file && defined('HHVM_VERSION')) { - $file = $this->findFileWithExtension($class, '.hh'); - } - - if (null !== $this->apcuPrefix) { - apcu_add($this->apcuPrefix.$class, $file); - } - - if (false === $file) { - // Remember that this class does not exist. - $this->missingClasses[$class] = true; - } - - return $file; - } - - /** - * Returns the currently registered loaders indexed by their corresponding vendor directories. - * - * @return self[] - */ - public static function getRegisteredLoaders() - { - return self::$registeredLoaders; - } - - /** - * @param string $class - * @param string $ext - * @return string|false - */ - private function findFileWithExtension($class, $ext) - { - // PSR-4 lookup - $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; - - $first = $class[0]; - if (isset($this->prefixLengthsPsr4[$first])) { - $subPath = $class; - while (false !== $lastPos = strrpos($subPath, '\\')) { - $subPath = substr($subPath, 0, $lastPos); - $search = $subPath . '\\'; - if (isset($this->prefixDirsPsr4[$search])) { - $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); - foreach ($this->prefixDirsPsr4[$search] as $dir) { - if (file_exists($file = $dir . $pathEnd)) { - return $file; - } - } - } - } - } - - // PSR-4 fallback dirs - foreach ($this->fallbackDirsPsr4 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { - return $file; - } - } - - // PSR-0 lookup - if (false !== $pos = strrpos($class, '\\')) { - // namespaced class name - $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) - . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); - } else { - // PEAR-like class name - $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; - } - - if (isset($this->prefixesPsr0[$first])) { - foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { - if (0 === strpos($class, $prefix)) { - foreach ($dirs as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - } - } - } - - // PSR-0 fallback dirs - foreach ($this->fallbackDirsPsr0 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - - // PSR-0 include paths. - if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { - return $file; - } - - return false; - } -} - -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - * - * @param string $file - * @return void - * @private - */ -function includeFile($file) -{ - include $file; -} diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php deleted file mode 100644 index d50e0c9..0000000 --- a/vendor/composer/InstalledVersions.php +++ /dev/null @@ -1,350 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer; - -use Composer\Autoload\ClassLoader; -use Composer\Semver\VersionParser; - -/** - * This class is copied in every Composer installed project and available to all - * - * See also https://getcomposer.org/doc/07-runtime.md#installed-versions - * - * To require its presence, you can require `composer-runtime-api ^2.0` - */ -class InstalledVersions -{ - /** - * @var mixed[]|null - * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null - */ - private static $installed; - - /** - * @var bool|null - */ - private static $canGetVendors; - - /** - * @var array[] - * @psalm-var array}> - */ - private static $installedByVendor = array(); - - /** - * Returns a list of all package names which are present, either by being installed, replaced or provided - * - * @return string[] - * @psalm-return list - */ - public static function getInstalledPackages() - { - $packages = array(); - foreach (self::getInstalled() as $installed) { - $packages[] = array_keys($installed['versions']); - } - - if (1 === \count($packages)) { - return $packages[0]; - } - - return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); - } - - /** - * Returns a list of all package names with a specific type e.g. 'library' - * - * @param string $type - * @return string[] - * @psalm-return list - */ - public static function getInstalledPackagesByType($type) - { - $packagesByType = array(); - - foreach (self::getInstalled() as $installed) { - foreach ($installed['versions'] as $name => $package) { - if (isset($package['type']) && $package['type'] === $type) { - $packagesByType[] = $name; - } - } - } - - return $packagesByType; - } - - /** - * Checks whether the given package is installed - * - * This also returns true if the package name is provided or replaced by another package - * - * @param string $packageName - * @param bool $includeDevRequirements - * @return bool - */ - public static function isInstalled($packageName, $includeDevRequirements = true) - { - foreach (self::getInstalled() as $installed) { - if (isset($installed['versions'][$packageName])) { - return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); - } - } - - return false; - } - - /** - * Checks whether the given package satisfies a version constraint - * - * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: - * - * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') - * - * @param VersionParser $parser Install composer/semver to have access to this class and functionality - * @param string $packageName - * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package - * @return bool - */ - public static function satisfies(VersionParser $parser, $packageName, $constraint) - { - $constraint = $parser->parseConstraints($constraint); - $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); - - return $provided->matches($constraint); - } - - /** - * Returns a version constraint representing all the range(s) which are installed for a given package - * - * It is easier to use this via isInstalled() with the $constraint argument if you need to check - * whether a given version of a package is installed, and not just whether it exists - * - * @param string $packageName - * @return string Version constraint usable with composer/semver - */ - public static function getVersionRanges($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - $ranges = array(); - if (isset($installed['versions'][$packageName]['pretty_version'])) { - $ranges[] = $installed['versions'][$packageName]['pretty_version']; - } - if (array_key_exists('aliases', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); - } - if (array_key_exists('replaced', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); - } - if (array_key_exists('provided', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); - } - - return implode(' || ', $ranges); - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present - */ - public static function getVersion($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['version'])) { - return null; - } - - return $installed['versions'][$packageName]['version']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present - */ - public static function getPrettyVersion($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['pretty_version'])) { - return null; - } - - return $installed['versions'][$packageName]['pretty_version']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference - */ - public static function getReference($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['reference'])) { - return null; - } - - return $installed['versions'][$packageName]['reference']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. - */ - public static function getInstallPath($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @return array - * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} - */ - public static function getRootPackage() - { - $installed = self::getInstalled(); - - return $installed[0]['root']; - } - - /** - * Returns the raw installed.php data for custom implementations - * - * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. - * @return array[] - * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} - */ - public static function getRawData() - { - @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); - - 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') { - self::$installed = include __DIR__ . '/installed.php'; - } else { - self::$installed = array(); - } - } - - return self::$installed; - } - - /** - * Returns the raw data of all installed.php which are currently loaded for custom implementations - * - * @return array[] - * @psalm-return list}> - */ - public static function getAllRawData() - { - return self::getInstalled(); - } - - /** - * Lets you reload the static array from another file - * - * This is only useful for complex integrations in which a project needs to use - * this class but then also needs to execute another project's autoloader in process, - * and wants to ensure both projects have access to their version of installed.php. - * - * A typical case would be PHPUnit, where it would need to make sure it reads all - * the data it needs from this class, then call reload() with - * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure - * the project in which it runs can then also use this class safely, without - * interference between PHPUnit's dependencies and the project's dependencies. - * - * @param array[] $data A vendor/composer/installed.php data set - * @return void - * - * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data - */ - public static function reload($data) - { - self::$installed = $data; - self::$installedByVendor = array(); - } - - /** - * @return array[] - * @psalm-return list}> - */ - private static function getInstalled() - { - if (null === self::$canGetVendors) { - self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); - } - - $installed = array(); - - if (self::$canGetVendors) { - foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { - if (isset(self::$installedByVendor[$vendorDir])) { - $installed[] = self::$installedByVendor[$vendorDir]; - } elseif (is_file($vendorDir.'/composer/installed.php')) { - $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; - if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { - self::$installed = $installed[count($installed) - 1]; - } - } - } - } - - 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') { - self::$installed = require __DIR__ . '/installed.php'; - } else { - self::$installed = array(); - } - } - $installed[] = self::$installed; - - return $installed; - } -} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE deleted file mode 100644 index f27399a..0000000 --- a/vendor/composer/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - -Copyright (c) Nils Adermann, Jordi Boggiano - -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/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php deleted file mode 100644 index 4890421..0000000 --- a/vendor/composer/autoload_classmap.php +++ /dev/null @@ -1,12 +0,0 @@ - $vendorDir . '/composer/InstalledVersions.php', - 'Grav\\Plugin\\ColorToolsPlugin' => $baseDir . '/color-tools.php', - 'Mexitek\\PHPColors\\Color' => $vendorDir . '/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php', -); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php deleted file mode 100644 index b7fc012..0000000 --- a/vendor/composer/autoload_namespaces.php +++ /dev/null @@ -1,9 +0,0 @@ - array($baseDir . '/classes'), -); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php deleted file mode 100644 index 97616c5..0000000 --- a/vendor/composer/autoload_real.php +++ /dev/null @@ -1,57 +0,0 @@ -= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require __DIR__ . '/autoload_static.php'; - - call_user_func(\Composer\Autoload\ComposerStaticInitc86e4df7714fddc74885de4c86d6c390::getInitializer($loader)); - } else { - $map = require __DIR__ . '/autoload_namespaces.php'; - foreach ($map as $namespace => $path) { - $loader->set($namespace, $path); - } - - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } - - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - } - - $loader->register(true); - - return $loader; - } -} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php deleted file mode 100644 index deed25a..0000000 --- a/vendor/composer/autoload_static.php +++ /dev/null @@ -1,38 +0,0 @@ - - array ( - 'Grav\\Plugin\\ColorTools\\' => 23, - ), - ); - - public static $prefixDirsPsr4 = array ( - 'Grav\\Plugin\\ColorTools\\' => - array ( - 0 => __DIR__ . '/../..' . '/classes', - ), - ); - - public static $classMap = array ( - 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', - 'Grav\\Plugin\\ColorToolsPlugin' => __DIR__ . '/../..' . '/color-tools.php', - 'Mexitek\\PHPColors\\Color' => __DIR__ . '/..' . '/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php', - ); - - public static function getInitializer(ClassLoader $loader) - { - return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInitc86e4df7714fddc74885de4c86d6c390::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInitc86e4df7714fddc74885de4c86d6c390::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInitc86e4df7714fddc74885de4c86d6c390::$classMap; - - }, null, ClassLoader::class); - } -} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json deleted file mode 100644 index 6d51f6f..0000000 --- a/vendor/composer/installed.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "packages": [ - { - "name": "mexitek/phpcolors", - "version": "dev-master", - "version_normalized": "dev-master", - "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", - "default-branch": true, - "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": true, - "dev-package-names": [] -} diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php deleted file mode 100644 index 5d178ca..0000000 --- a/vendor/composer/installed.php +++ /dev/null @@ -1,34 +0,0 @@ - array( - 'pretty_version' => 'dev-develop', - 'version' => 'dev-develop', - 'type' => 'grav-plugin', - 'install_path' => __DIR__ . '/../../', - 'aliases' => array(), - 'reference' => '6e6feb52a5293618f56865e3fc1ee4f3ad91036d', - 'name' => 'trilbymedia/color-tools', - 'dev' => true, - ), - 'versions' => array( - 'mexitek/phpcolors' => array( - 'pretty_version' => 'dev-master', - 'version' => 'dev-master', - 'type' => 'library', - 'install_path' => __DIR__ . '/../mexitek/phpcolors', - 'aliases' => array( - 0 => '9999999-dev', - ), - 'reference' => '4043974240ca7dc3c2bec3c158588148b605b206', - 'dev_requirement' => false, - ), - 'trilbymedia/color-tools' => array( - 'pretty_version' => 'dev-develop', - 'version' => 'dev-develop', - 'type' => 'grav-plugin', - 'install_path' => __DIR__ . '/../../', - 'aliases' => array(), - 'reference' => '6e6feb52a5293618f56865e3fc1ee4f3ad91036d', - 'dev_requirement' => false, - ), - ), -); diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php deleted file mode 100644 index 0109125..0000000 --- a/vendor/composer/platform_check.php +++ /dev/null @@ -1,26 +0,0 @@ -= 70306)) { - $issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.6". 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/vendor/mexitek/phpcolors b/vendor/mexitek/phpcolors deleted file mode 160000 index 9d7cf28..0000000 --- a/vendor/mexitek/phpcolors +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9d7cf28aab475a26b9f5be4f9dc4106736956678 From 24a690790731f8d7b583debafee0e570d0e5b036 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Mon, 3 Jan 2022 09:07:51 -0700 Subject: [PATCH 3/4] put back --- vendor/autoload.php | 7 + vendor/composer/ClassLoader.php | 572 +++++++++++++ vendor/composer/InstalledVersions.php | 350 ++++++++ vendor/composer/LICENSE | 21 + vendor/composer/autoload_classmap.php | 12 + vendor/composer/autoload_namespaces.php | 9 + vendor/composer/autoload_psr4.php | 10 + vendor/composer/autoload_real.php | 57 ++ vendor/composer/autoload_static.php | 38 + vendor/composer/installed.json | 63 ++ vendor/composer/installed.php | 34 + vendor/composer/platform_check.php | 26 + vendor/mexitek/phpcolors/.editorconfig | 17 + vendor/mexitek/phpcolors/.gitignore | 5 + vendor/mexitek/phpcolors/.phpcs.xml | 10 + vendor/mexitek/phpcolors/.travis.yml | 11 + vendor/mexitek/phpcolors/LICENSE | 21 + vendor/mexitek/phpcolors/README.md | 173 ++++ vendor/mexitek/phpcolors/composer.json | 37 + vendor/mexitek/phpcolors/demo/demo.php | 94 ++ .../mexitek/phpcolors/demo/phpColor-demo.png | Bin 0 -> 27634 bytes .../phpcolors/src/Mexitek/PHPColors/Color.php | 801 ++++++++++++++++++ vendor/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 ++ .../tests/colorConvertNameToHex.phpt | 170 ++++ .../phpcolors/tests/colorConvertRgbToHex.phpt | 72 ++ .../mexitek/phpcolors/tests/colorInput.phpt | 19 + vendor/mexitek/phpcolors/tests/colorMix.phpt | 24 + 31 files changed, 2827 insertions(+) create mode 100644 vendor/autoload.php create mode 100644 vendor/composer/ClassLoader.php create mode 100644 vendor/composer/InstalledVersions.php create mode 100644 vendor/composer/LICENSE create mode 100644 vendor/composer/autoload_classmap.php create mode 100644 vendor/composer/autoload_namespaces.php create mode 100644 vendor/composer/autoload_psr4.php create mode 100644 vendor/composer/autoload_real.php create mode 100644 vendor/composer/autoload_static.php create mode 100644 vendor/composer/installed.json create mode 100644 vendor/composer/installed.php create mode 100644 vendor/composer/platform_check.php create mode 100644 vendor/mexitek/phpcolors/.editorconfig create mode 100644 vendor/mexitek/phpcolors/.gitignore create mode 100644 vendor/mexitek/phpcolors/.phpcs.xml create mode 100644 vendor/mexitek/phpcolors/.travis.yml create mode 100644 vendor/mexitek/phpcolors/LICENSE create mode 100644 vendor/mexitek/phpcolors/README.md create mode 100644 vendor/mexitek/phpcolors/composer.json create mode 100644 vendor/mexitek/phpcolors/demo/demo.php create mode 100644 vendor/mexitek/phpcolors/demo/phpColor-demo.png create mode 100644 vendor/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php create mode 100644 vendor/mexitek/phpcolors/tests/bootstrap.php create mode 100644 vendor/mexitek/phpcolors/tests/colorAnalyze.phpt create mode 100644 vendor/mexitek/phpcolors/tests/colorChange.phpt create mode 100644 vendor/mexitek/phpcolors/tests/colorComplementary.phpt create mode 100644 vendor/mexitek/phpcolors/tests/colorConvertHslToHex.phpt create mode 100644 vendor/mexitek/phpcolors/tests/colorConvertNameToHex.phpt create mode 100644 vendor/mexitek/phpcolors/tests/colorConvertRgbToHex.phpt create mode 100644 vendor/mexitek/phpcolors/tests/colorInput.phpt create mode 100644 vendor/mexitek/phpcolors/tests/colorMix.phpt diff --git a/vendor/autoload.php b/vendor/autoload.php new file mode 100644 index 0000000..8f1193b --- /dev/null +++ b/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + /** @var ?string */ + private $vendorDir; + + // PSR-4 + /** + * @var array[] + * @psalm-var array> + */ + private $prefixLengthsPsr4 = array(); + /** + * @var array[] + * @psalm-var array> + */ + private $prefixDirsPsr4 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr4 = array(); + + // PSR-0 + /** + * @var array[] + * @psalm-var array> + */ + private $prefixesPsr0 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr0 = array(); + + /** @var bool */ + private $useIncludePath = false; + + /** + * @var string[] + * @psalm-var array + */ + private $classMap = array(); + + /** @var bool */ + private $classMapAuthoritative = false; + + /** + * @var bool[] + * @psalm-var array + */ + private $missingClasses = array(); + + /** @var ?string */ + private $apcuPrefix; + + /** + * @var self[] + */ + private static $registeredLoaders = array(); + + /** + * @param ?string $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + } + + /** + * @return string[] + */ + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); + } + + return array(); + } + + /** + * @return array[] + * @psalm-return array> + */ + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + /** + * @return string[] Array of classname => path + * @psalm-var array + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param string[] $classMap Class to filename map + * @psalm-param array $classMap + * + * @return void + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 base directories + * + * @return void + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + * + * @return void + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + * + * @return void + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + * + * @return void + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } + } + + /** + * Unregisters this instance as an autoloader. + * + * @return void + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return true|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + + return null; + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + /** + * Returns the currently registered loaders indexed by their corresponding vendor directories. + * + * @return self[] + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + * @private + */ +function includeFile($file) +{ + include $file; +} diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php new file mode 100644 index 0000000..d50e0c9 --- /dev/null +++ b/vendor/composer/InstalledVersions.php @@ -0,0 +1,350 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints($constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + 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') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + 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') { + self::$installed = require __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + $installed[] = self::$installed; + + return $installed; + } +} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +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/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..4890421 --- /dev/null +++ b/vendor/composer/autoload_classmap.php @@ -0,0 +1,12 @@ + $vendorDir . '/composer/InstalledVersions.php', + 'Grav\\Plugin\\ColorToolsPlugin' => $baseDir . '/color-tools.php', + 'Mexitek\\PHPColors\\Color' => $vendorDir . '/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php', +); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..b7fc012 --- /dev/null +++ b/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + array($baseDir . '/classes'), +); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php new file mode 100644 index 0000000..851d070 --- /dev/null +++ b/vendor/composer/autoload_real.php @@ -0,0 +1,57 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInit8d24c6cfdbbca0c2bd80548a1eefba75::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + return $loader; + } +} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php new file mode 100644 index 0000000..d0d7f79 --- /dev/null +++ b/vendor/composer/autoload_static.php @@ -0,0 +1,38 @@ + + array ( + 'Grav\\Plugin\\ColorTools\\' => 23, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Grav\\Plugin\\ColorTools\\' => + array ( + 0 => __DIR__ . '/../..' . '/classes', + ), + ); + + public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + 'Grav\\Plugin\\ColorToolsPlugin' => __DIR__ . '/../..' . '/color-tools.php', + 'Mexitek\\PHPColors\\Color' => __DIR__ . '/..' . '/mexitek/phpcolors/src/Mexitek/PHPColors/Color.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit8d24c6cfdbbca0c2bd80548a1eefba75::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit8d24c6cfdbbca0c2bd80548a1eefba75::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInit8d24c6cfdbbca0c2bd80548a1eefba75::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json new file mode 100644 index 0000000..6d51f6f --- /dev/null +++ b/vendor/composer/installed.json @@ -0,0 +1,63 @@ +{ + "packages": [ + { + "name": "mexitek/phpcolors", + "version": "dev-master", + "version_normalized": "dev-master", + "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", + "default-branch": true, + "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": true, + "dev-package-names": [] +} diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php new file mode 100644 index 0000000..a656c6f --- /dev/null +++ b/vendor/composer/installed.php @@ -0,0 +1,34 @@ + array( + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'type' => 'grav-plugin', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => 'b38471a08ca633e9f13a9a5b0c5a4dd58cead7f7', + 'name' => 'trilbymedia/color-tools', + 'dev' => true, + ), + 'versions' => array( + 'mexitek/phpcolors' => array( + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'type' => 'library', + 'install_path' => __DIR__ . '/../mexitek/phpcolors', + 'aliases' => array( + 0 => '9999999-dev', + ), + 'reference' => '4043974240ca7dc3c2bec3c158588148b605b206', + 'dev_requirement' => false, + ), + 'trilbymedia/color-tools' => array( + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'type' => 'grav-plugin', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => 'b38471a08ca633e9f13a9a5b0c5a4dd58cead7f7', + 'dev_requirement' => false, + ), + ), +); diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php new file mode 100644 index 0000000..0109125 --- /dev/null +++ b/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 70306)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.6". 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/vendor/mexitek/phpcolors/.editorconfig b/vendor/mexitek/phpcolors/.editorconfig new file mode 100644 index 0000000..989704a --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/.gitignore b/vendor/mexitek/phpcolors/.gitignore new file mode 100644 index 0000000..e0a4624 --- /dev/null +++ b/vendor/mexitek/phpcolors/.gitignore @@ -0,0 +1,5 @@ +*.bak +*.*.bak +vendor/* +composer.lock +.idea diff --git a/vendor/mexitek/phpcolors/.phpcs.xml b/vendor/mexitek/phpcolors/.phpcs.xml new file mode 100644 index 0000000..bba9c9f --- /dev/null +++ b/vendor/mexitek/phpcolors/.phpcs.xml @@ -0,0 +1,10 @@ + + + The coding standard for PHPColors. + + ./src + ./tests + + + diff --git a/vendor/mexitek/phpcolors/.travis.yml b/vendor/mexitek/phpcolors/.travis.yml new file mode 100644 index 0000000..1e5be35 --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/LICENSE b/vendor/mexitek/phpcolors/LICENSE new file mode 100644 index 0000000..f764bbc --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/README.md b/vendor/mexitek/phpcolors/README.md new file mode 100644 index 0000000..8e3420f --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/composer.json b/vendor/mexitek/phpcolors/composer.json new file mode 100644 index 0000000..8d074f7 --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/demo/demo.php b/vendor/mexitek/phpcolors/demo/demo.php new file mode 100644 index 0000000..825cf08 --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/demo/phpColor-demo.png b/vendor/mexitek/phpcolors/demo/phpColor-demo.png new file mode 100644 index 0000000000000000000000000000000000000000..b1fbdbcae97fab971dec24b8a045277a80542203 GIT binary patch literal 27634 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 + * 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/vendor/mexitek/phpcolors/tests/bootstrap.php b/vendor/mexitek/phpcolors/tests/bootstrap.php new file mode 100644 index 0000000..8460796 --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/tests/colorChange.phpt b/vendor/mexitek/phpcolors/tests/colorChange.phpt new file mode 100644 index 0000000..373f34e --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/tests/colorComplementary.phpt b/vendor/mexitek/phpcolors/tests/colorComplementary.phpt new file mode 100644 index 0000000..2876b5c --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/tests/colorConvertHslToHex.phpt b/vendor/mexitek/phpcolors/tests/colorConvertHslToHex.phpt new file mode 100644 index 0000000..fd3adbd --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/tests/colorConvertNameToHex.phpt b/vendor/mexitek/phpcolors/tests/colorConvertNameToHex.phpt new file mode 100644 index 0000000..e4f87ca --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/tests/colorConvertRgbToHex.phpt b/vendor/mexitek/phpcolors/tests/colorConvertRgbToHex.phpt new file mode 100644 index 0000000..a65f1a7 --- /dev/null +++ b/vendor/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/vendor/mexitek/phpcolors/tests/colorInput.phpt b/vendor/mexitek/phpcolors/tests/colorInput.phpt new file mode 100644 index 0000000..8ace305 --- /dev/null +++ b/vendor/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.'); +} From ae5a70a18091a450fbbc449a8c1efb9427e933e8 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Mon, 3 Jan 2022 10:02:16 -0700 Subject: [PATCH 4/4] prepare for release --- CHANGELOG.md | 2 +- blueprints.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1128e2..84df6ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # v1.1.0 -## mm/dd/2021 +## 01/03/2022 1. [](#new) * Updated to `dev-master` of `Mexitek/PHPColors` to get latest functionality diff --git a/blueprints.yaml b/blueprints.yaml index 0735bb8..54090ec 100644 --- a/blueprints.yaml +++ b/blueprints.yaml @@ -1,7 +1,7 @@ name: Color Tools slug: color-tools type: plugin -version: 1.0.2 +version: 1.1.0 description: Color Tools for PHP and Twig icon: paint-brush author: