1<?php
2
3/**
4 * This file is part of the Carbon package.
5 *
6 * (c) Brian Nesbitt <brian@nesbot.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11namespace Carbon\Traits;
12
13/**
14 * Trait Macros.
15 *
16 * Allows users to register macros within the Carbon class.
17 */
18trait Macro
19{
20    use Mixin;
21
22    /**
23     * The registered macros.
24     *
25     * @var array
26     */
27    protected static $globalMacros = [];
28
29    /**
30     * The registered generic macros.
31     *
32     * @var array
33     */
34    protected static $globalGenericMacros = [];
35
36    /**
37     * Register a custom macro.
38     *
39     * @example
40     * ```
41     * $userSettings = [
42     *   'locale' => 'pt',
43     *   'timezone' => 'America/Sao_Paulo',
44     * ];
45     * Carbon::macro('userFormat', function () use ($userSettings) {
46     *   return $this->copy()->locale($userSettings['locale'])->tz($userSettings['timezone'])->calendar();
47     * });
48     * echo Carbon::yesterday()->hours(11)->userFormat();
49     * ```
50     *
51     * @param string          $name
52     * @param object|callable $macro
53     *
54     * @return void
55     */
56    public static function macro($name, $macro)
57    {
58        static::$globalMacros[$name] = $macro;
59    }
60
61    /**
62     * Remove all macros and generic macros.
63     */
64    public static function resetMacros()
65    {
66        static::$globalMacros = [];
67        static::$globalGenericMacros = [];
68    }
69
70    /**
71     * Register a custom macro.
72     *
73     * @param object|callable $macro
74     * @param int             $priority marco with higher priority is tried first
75     *
76     * @return void
77     */
78    public static function genericMacro($macro, $priority = 0)
79    {
80        if (!isset(static::$globalGenericMacros[$priority])) {
81            static::$globalGenericMacros[$priority] = [];
82            krsort(static::$globalGenericMacros, SORT_NUMERIC);
83        }
84
85        static::$globalGenericMacros[$priority][] = $macro;
86    }
87
88    /**
89     * Checks if macro is registered globally.
90     *
91     * @param string $name
92     *
93     * @return bool
94     */
95    public static function hasMacro($name)
96    {
97        return isset(static::$globalMacros[$name]);
98    }
99
100    /**
101     * Get the raw callable macro registered globally for a given name.
102     *
103     * @param string $name
104     *
105     * @return callable|null
106     */
107    public static function getMacro($name)
108    {
109        return static::$globalMacros[$name] ?? null;
110    }
111
112    /**
113     * Checks if macro is registered globally or locally.
114     *
115     * @param string $name
116     *
117     * @return bool
118     */
119    public function hasLocalMacro($name)
120    {
121        return ($this->localMacros && isset($this->localMacros[$name])) || static::hasMacro($name);
122    }
123
124    /**
125     * Get the raw callable macro registered globally or locally for a given name.
126     *
127     * @param string $name
128     *
129     * @return callable|null
130     */
131    public function getLocalMacro($name)
132    {
133        return ($this->localMacros ?? [])[$name] ?? static::getMacro($name);
134    }
135}
136