git subrepo commit (merge) mailcow/src/mailcow-dockerized

subrepo: subdir:   "mailcow/src/mailcow-dockerized"
  merged:   "02ae5285"
upstream: origin:   "https://github.com/mailcow/mailcow-dockerized.git"
  branch:   "master"
  commit:   "649a5c01"
git-subrepo: version:  "0.4.3"
  origin:   "???"
  commit:   "???"
Change-Id: I870ad468fba026cc5abf3c5699ed1e12ff28b32b
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Mixin.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Mixin.php
new file mode 100644
index 0000000..b9c868d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Mixin.php
@@ -0,0 +1,190 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Closure;
+use Generator;
+use ReflectionClass;
+use ReflectionException;
+use ReflectionMethod;
+use Throwable;
+
+/**
+ * Trait Mixin.
+ *
+ * Allows mixing in entire classes with multiple macros.
+ */
+trait Mixin
+{
+    /**
+     * Stack of macro instance contexts.
+     *
+     * @var array
+     */
+    protected static $macroContextStack = [];
+
+    /**
+     * Mix another object into the class.
+     *
+     * @example
+     * ```
+     * Carbon::mixin(new class {
+     *   public function addMoon() {
+     *     return function () {
+     *       return $this->addDays(30);
+     *     };
+     *   }
+     *   public function subMoon() {
+     *     return function () {
+     *       return $this->subDays(30);
+     *     };
+     *   }
+     * });
+     * $fullMoon = Carbon::create('2018-12-22');
+     * $nextFullMoon = $fullMoon->addMoon();
+     * $blackMoon = Carbon::create('2019-01-06');
+     * $previousBlackMoon = $blackMoon->subMoon();
+     * echo "$nextFullMoon\n";
+     * echo "$previousBlackMoon\n";
+     * ```
+     *
+     * @param object|string $mixin
+     *
+     * @throws ReflectionException
+     *
+     * @return void
+     */
+    public static function mixin($mixin)
+    {
+        \is_string($mixin) && trait_exists($mixin)
+            ? static::loadMixinTrait($mixin)
+            : static::loadMixinClass($mixin);
+    }
+
+    /**
+     * @param object|string $mixin
+     *
+     * @throws ReflectionException
+     */
+    private static function loadMixinClass($mixin)
+    {
+        $methods = (new ReflectionClass($mixin))->getMethods(
+            ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
+        );
+
+        foreach ($methods as $method) {
+            if ($method->isConstructor() || $method->isDestructor()) {
+                continue;
+            }
+
+            $method->setAccessible(true);
+
+            static::macro($method->name, $method->invoke($mixin));
+        }
+    }
+
+    /**
+     * @param string $trait
+     */
+    private static function loadMixinTrait($trait)
+    {
+        $context = eval(self::getAnonymousClassCodeForTrait($trait));
+        $className = \get_class($context);
+
+        foreach (self::getMixableMethods($context) as $name) {
+            $closureBase = Closure::fromCallable([$context, $name]);
+
+            static::macro($name, function () use ($closureBase, $className) {
+                /** @phpstan-ignore-next-line */
+                $context = isset($this) ? $this->cast($className) : new $className();
+
+                try {
+                    // @ is required to handle error if not converted into exceptions
+                    $closure = @$closureBase->bindTo($context);
+                } catch (Throwable $throwable) { // @codeCoverageIgnore
+                    $closure = $closureBase; // @codeCoverageIgnore
+                }
+
+                // in case of errors not converted into exceptions
+                $closure = $closure ?? $closureBase;
+
+                return $closure(...\func_get_args());
+            });
+        }
+    }
+
+    private static function getAnonymousClassCodeForTrait(string $trait)
+    {
+        return 'return new class() extends '.static::class.' {use '.$trait.';};';
+    }
+
+    private static function getMixableMethods(self $context): Generator
+    {
+        foreach (get_class_methods($context) as $name) {
+            if (method_exists(static::class, $name)) {
+                continue;
+            }
+
+            yield $name;
+        }
+    }
+
+    /**
+     * Stack a Carbon context from inside calls of self::this() and execute a given action.
+     *
+     * @param static|null $context
+     * @param callable    $callable
+     *
+     * @throws Throwable
+     *
+     * @return mixed
+     */
+    protected static function bindMacroContext($context, callable $callable)
+    {
+        static::$macroContextStack[] = $context;
+        $exception = null;
+        $result = null;
+
+        try {
+            $result = $callable();
+        } catch (Throwable $throwable) {
+            $exception = $throwable;
+        }
+
+        array_pop(static::$macroContextStack);
+
+        if ($exception) {
+            throw $exception;
+        }
+
+        return $result;
+    }
+
+    /**
+     * Return the current context from inside a macro callee or a null if static.
+     *
+     * @return static|null
+     */
+    protected static function context()
+    {
+        return end(static::$macroContextStack) ?: null;
+    }
+
+    /**
+     * Return the current context from inside a macro callee or a new one if static.
+     *
+     * @return static
+     */
+    protected static function this()
+    {
+        return end(static::$macroContextStack) ?: new static();
+    }
+}