MappingTrait   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 192
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 192
c 0
b 0
f 0
wmc 17
lcom 1
cbo 1
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A setMappings() 0 20 2
A hasMappings() 0 4 1
A getMappings() 0 10 2
A resetMappings() 0 4 1
A messageDefined() 0 4 1
A getMessage() 0 8 2
A getTemplateByCode() 0 21 3
A loadMappings() 0 18 3
A checkStatus() 0 7 2
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Shared
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Shared\Message\Mapping;
16
17
use Phossa2\Shared\Message\Loader\LoaderAwareTrait;
18
19
/**
20
 * MappingTrait
21
 *
22
 * One implementation of `MappingInterface`
23
 *
24
 * @package Phossa2\Shared
25
 * @author  Hong Zhang <[email protected]>
26
 * @see     MappingInterface
27
 * @version 2.0.0
28
 * @since   2.0.0 added
29
 */
30
trait MappingTrait
31
{
32
    use LoaderAwareTrait;
33
34
    /**
35
     * Ddefault messages for current message class
36
     *
37
     * This property HAS TO BE redefined for each descendant message class !
38
     *
39
     * @var    string[]
40
     * @access protected
41
     */
42
    protected static $messages = [];
43
44
    /**
45
     * Message mapping cache
46
     *
47
     * @var    array
48
     * @access private
49
     */
50
    private static $mappings = [];
51
52
    /**
53
     * Reset current message class' code to message mappings cache
54
     *
55
     * ```php
56
     *     MyMessage::setMappings([
57
     *         MyMessage::MSG_HELLO => 'Hello %s'
58
     *     ]);
59
     * ```
60
     *
61
     * @param  array $messages messages mapping array
62
     * @param  bool $manual manually, not auto load from $loader
63
     * @access public
64
     * @api
65
     */
66
    public static function setMappings(
67
        array $messages,
68
        /*# bool */ $manual = true
69
    ) {
70
        $class = get_called_class();
71
72
        if ($manual) {
73
            // set default
74
            static::$messages = $messages;
75
76
            // status changed
77
            self::setStatus();
78
        } else {
79
            // set cache
80
            self::$mappings[$class] = array_replace(
81
                $class::getMappings(),
82
                $messages
83
            );
84
        }
85
    }
86
87
    /**
88
     * Check current class' message mapping cache
89
     *
90
     * @return bool
91
     * @access protected
92
     */
93
    protected static function hasMappings()/*# : bool */
94
    {
95
        return isset(self::$mappings[get_called_class()]);
96
    }
97
98
    /**
99
     * Get current class' message mapping, default or cached
100
     *
101
     * @return array
102
     * @access protected
103
     */
104
    protected static function getMappings()/*# : array */
105
    {
106
        // use cached first if any
107
        if (static::hasMappings()) {
108
            return self::$mappings[get_called_class()];
109
        }
110
111
        // return the default
112
        return static::$messages;
113
    }
114
115
    /**
116
     * Clear the mapping cache
117
     *
118
     * @access protected
119
     */
120
    protected static function resetMappings()
121
    {
122
        self::$mappings = [];
123
    }
124
125
    /**
126
     * Check message template in default mapping
127
     *
128
     * @param  int $code the message code
129
     * @return bool
130
     * @access protected
131
     */
132
    protected static function messageDefined(/*# int */ $code)/*# : bool */
133
    {
134
        return isset(static::$messages[$code]);
135
    }
136
137
    /**
138
     * Resolving code for current message class, from cache or default
139
     *
140
     * If nothing found, return the code anyway
141
     *
142
     * @param  int $code the message code
143
     * @return string
144
     * @access protected
145
     */
146
    protected static function getMessage(/*# int */ $code)/*# : string */
147
    {
148
        $mapping = static::getMappings();
149
        if (isset($mapping[$code])) {
150
            return $mapping[$code];
151
        }
152
        return (string) $code;
153
    }
154
155
    /**
156
     * Resolving $code to message template, start from $class
157
     *
158
     * @param  int $code message code
159
     * @param  string $class class name
160
     * @return string
161
     * @access protected
162
     */
163
    protected static function getTemplateByCode(
164
        /*# int */ $code,
165
        /*# string */ $class
166
    )/*# : string */ {
167
        // default template, last resort
168
        if (__CLASS__ === $class) {
169
            return "unknown message code: $code, %s";
170
        }
171
172
        // check $class
173
        if ($class::messageDefined($code)) {
174
            // load message mapping for $class
175
            $class::loadMappings();
176
177
            // get the message template
178
            return $class::getMessage($code);
179
        }
180
181
        // search upwards
182
        return self::getTemplateByCode($code, get_parent_class($class));
183
    }
184
185
    /**
186
     * Load message mappings into cache for $class
187
     *
188
     * @access protected
189
     */
190
    protected static function loadMappings()
191
    {
192
        // check status
193
        self::checkStatus();
194
195
        // mapping cache loaded already for $class
196
        if (static::hasMappings()) {
197
            return;
198
        }
199
200
        // load $class mapping
201
        $loadedClass = static::hasLoader(true);
202
        static::setMappings(
203
            $loadedClass ?
204
                $loadedClass::getLoader()->loadMessages(get_called_class()) : [],
205
            false
206
        );
207
    }
208
209
    /**
210
     * Update mapping cache if status changed
211
     *
212
     * @access protected
213
     */
214
    protected static function checkStatus()
215
    {
216
        if (self::isStatusUpdated()) {
217
            self::resetMappings();
218
            self::setStatus(false);
219
        }
220
    }
221
}
222