| Code Coverage
| Classes and Traits | Functions and Methods | Lines
Total |  | 0.00% | 0 / 1 |  | 66.67% | 4 / 6 | CRAP |  | 97.44% | 76 / 78
LoggerConfigurationAdapterINI |  | 0.00% | 0 / 1 |  | 66.67% | 4 / 6 | 26 |  | 97.44% | 76 / 78
load($url) |  | 100.00% | 1 / 1 | 3 |  | 100.00% | 7 / 7
convert($path) |  | 100.00% | 1 / 1 | 8 |  | 100.00% | 25 / 25
parseLogger($value, $name) |  | 0.00% | 0 / 1 | 6.01 |  | 94.44% | 17 / 18
parseAppender($key, $value) |  | 0.00% | 0 / 1 | 7 |  | 95.65% | 22 / 23
parseRenderer($key, $value) |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 4 / 4
beginsWith($str, $sub) |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1

1 | <?php
2 | /**
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | *
18 | * @package log4php
19 | */
20 |
21 | /**
22 | * Converts ini configuration files to a PHP array.
23 | *
24 | * These used to be called "properties" files (inherited from log4j), and that
25 | * file extension is still supported.
26 | *
27 | * @package log4php
28 | * @subpackage configurators
29 | * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
30 | * @version $Revision: 1343601 $
31 | * @since 2.2
32 | */
33 | class LoggerConfigurationAdapterINI implements LoggerConfigurationAdapter {
34 |
35 | /** Name to assign to the root logger. */
36 | const ROOT_LOGGER_NAME = "root";
37 |
38 | /** Prefix used for defining logger additivity. */
39 | const ADDITIVITY_PREFIX = "log4php.additivity.";
40 |
41 | /** Prefix used for defining logger threshold. */
42 | const THRESHOLD_PREFIX = "log4php.threshold";
43 |
44 | /** Prefix used for defining the root logger. */
45 | const ROOT_LOGGER_PREFIX = "log4php.rootLogger";
46 |
47 | /** Prefix used for defining a logger. */
48 | const LOGGER_PREFIX = "log4php.logger.";
49 |
50 | /** Prefix used for defining an appender. */
51 | const APPENDER_PREFIX = "log4php.appender.";
52 |
53 | /** Prefix used for defining a renderer. */
54 | const RENDERER_PREFIX = "log4php.renderer.";
55 |
56 | /** Holds the configuration. */
57 | private $config = array();
58 |
59 | /**
60 | * Loads and parses the INI configuration file.
61 | *
62 | * @param string $url Path to the config file.
63 | * @throws LoggerException
64 | */
65 | private function load($url) {
66 | if (!file_exists($url)) {
67 | throw new LoggerException("File [$url] does not exist.");
68 | }
69 |
70 | $properties = @parse_ini_file($url, true);
71 | if ($properties === false) {
72 | $error = error_get_last();
73 | throw new LoggerException("Error parsing configuration file: {$error['message']}");
74 | }
75 |
76 | return $properties;
77 | }
78 |
79 | /**
80 | * Converts the provided INI configuration file to a PHP array config.
81 | *
82 | * @param string $path Path to the config file.
83 | * @throws LoggerException If the file cannot be loaded or parsed.
84 | */
85 | public function convert($path) {
86 | // Load the configuration
87 | $properties = $this->load($path);
88 |
89 | // Parse threshold
90 | if (isset($properties[self::THRESHOLD_PREFIX])) {
91 | $this->config['threshold'] = $properties[self::THRESHOLD_PREFIX];
92 | }
93 |
94 | // Parse root logger
95 | if (isset($properties[self::ROOT_LOGGER_PREFIX])) {
96 | $this->parseLogger($properties[self::ROOT_LOGGER_PREFIX], self::ROOT_LOGGER_NAME);
97 | }
98 |
99 | $appenders = array();
100 |
101 | foreach($properties as $key => $value) {
102 | // Parse loggers
103 | if ($this->beginsWith($key, self::LOGGER_PREFIX)) {
104 | $name = substr($key, strlen(self::LOGGER_PREFIX));
105 | $this->parseLogger($value, $name);
106 | }
107 |
108 | // Parse additivity
109 | if ($this->beginsWith($key, self::ADDITIVITY_PREFIX)) {
110 | $name = substr($key, strlen(self::ADDITIVITY_PREFIX));
111 | $this->config['loggers'][$name]['additivity'] = $value;
112 | }
113 |
114 | // Parse appenders
115 | else if ($this->beginsWith($key, self::APPENDER_PREFIX)) {
116 | $this->parseAppender($key, $value);
117 | }
118 |
119 | // Parse renderers
120 | else if ($this->beginsWith($key, self::RENDERER_PREFIX)) {
121 | $this->parseRenderer($key, $value);
122 | }
123 | }
124 |
125 | return $this->config;
126 | }
127 |
128 |
129 | /**
130 | * Parses a logger definition.
131 | *
132 | * Loggers are defined in the following manner:
133 | * <pre>
134 | * log4php.logger.<name> = [<level>], [<appender-ref>, <appender-ref>, ...]
135 | * </pre>
136 | *
137 | * @param string $value The configuration value (level and appender-refs).
138 | * @param string $name Logger name.
139 | */
140 | private function parseLogger($value, $name) {
141 | // Value is divided by commas
142 | $parts = explode(',', $value);
143 | if (empty($value) || empty($parts)) {
144 | return;
145 | }
146 |
147 | // The first value is the logger level
148 | $level = array_shift($parts);
149 |
150 | // The remaining values are appender references
151 | $appenders = array();
152 | while($appender = array_shift($parts)) {
153 | $appender = trim($appender);
154 | if (!empty($appender)) {
155 | $appenders[] = trim($appender);
156 | }
157 | }
158 |
159 | // Find the target configuration
160 | if ($name == self::ROOT_LOGGER_NAME) {
161 | $this->config['rootLogger']['level'] = trim($level);
162 | $this->config['rootLogger']['appenders'] = $appenders;
163 | } else {
164 | $this->config['loggers'][$name]['level'] = trim($level);
165 | $this->config['loggers'][$name]['appenders'] = $appenders;
166 | }
167 | }
168 |
169 | /**
170 | * Parses an configuration line pertaining to an appender.
171 | *
172 | * Parses the following patterns:
173 | *
174 | * Appender class:
175 | * <pre>
176 | * log4php.appender.<name> = <class>
177 | * </pre>
178 | *
179 | * Appender parameter:
180 | * <pre>
181 | * log4php.appender.<name>.<param> = <value>
182 | * </pre>
183 | *
184 | * Appender threshold:
185 | * <pre>
186 | * log4php.appender.<name>.threshold = <level>
187 | * </pre>
188 | *
189 | * Appender layout:
190 | * <pre>
191 | * log4php.appender.<name>.layout = <layoutClass>
192 | * </pre>
193 | *
194 | * Layout parameter:
195 | * <pre>
196 | * log4php.appender.<name>.layout.<param> = <value>
197 | * </pre>
198 | *
199 | * For example, a full appender config might look like:
200 | * <pre>
201 | * log4php.appender.myAppender = LoggerAppenderConsole
202 | * log4php.appender.myAppender.threshold = info
203 | * log4php.appender.myAppender.target = stdout
204 | * log4php.appender.myAppender.layout = LoggerLayoutPattern
205 | * log4php.appender.myAppender.layout.conversionPattern = "%d %c: %m%n"
206 | * </pre>
207 | *
208 | * After parsing all these options, the following configuration can be
209 | * found under $this->config['appenders']['myAppender']:
210 | * <pre>
211 | * array(
212 | * 'class' => LoggerAppenderConsole,
213 | * 'threshold' => info,
214 | * 'params' => array(
215 | * 'target' => 'stdout'
216 | * ),
217 | * 'layout' => array(
218 | * 'class' => 'LoggerAppenderConsole',
219 | * 'params' => array(
220 | * 'conversionPattern' => '%d %c: %m%n'
221 | * )
222 | * )
223 | * )
224 | * </pre>
225 | *
226 | * @param string $key
227 | * @param string $value
228 | */
229 | private function parseAppender($key, $value) {
230 |
231 | // Remove the appender prefix from key
232 | $subKey = substr($key, strlen(self::APPENDER_PREFIX));
233 |
234 | // Divide the string by dots
235 | $parts = explode('.', $subKey);
236 | $count = count($parts);
237 |
238 | // The first part is always the appender name
239 | $name = trim($parts[0]);
240 |
241 | // Only one part - this line defines the appender class
242 | if ($count == 1) {
243 | $this->config['appenders'][$name]['class'] = $value;
244 | return;
245 | }
246 |
247 | // Two parts - either a parameter, a threshold or layout class
248 | else if ($count == 2) {
249 |
250 | if ($parts[1] == 'layout') {
251 | $this->config['appenders'][$name]['layout']['class'] = $value;
252 | return;
253 | } else if ($parts[1] == 'threshold') {
254 | $this->config['appenders'][$name]['threshold'] = $value;
255 | return;
256 | } else {
257 | $this->config['appenders'][$name]['params'][$parts[1]] = $value;
258 | return;
259 | }
260 | }
261 |
262 | // Three parts - this can only be a layout parameter
263 | else if ($count == 3) {
264 | if ($parts[1] == 'layout') {
265 | $this->config['appenders'][$name]['layout']['params'][$parts[2]] = $value;
266 | return;
267 | }
268 | }
269 |
270 | trigger_error("log4php: Don't know how to parse the following line: \"$key = $value\". Skipping.");
271 | }
272 |
273 | /**
274 | * Parses a renderer definition.
275 | *
276 | * Renderers are defined as:
277 | * <pre>
278 | * log4php.renderer.<renderedClass> = <renderingClass>
279 | * </pre>
280 | *
281 | * @param string $key log4php.renderer.<renderedClass>
282 | * @param string $value <renderingClass>
283 | */
284 | private function parseRenderer($key, $value) {
285 | // Remove the appender prefix from key
286 | $renderedClass = substr($key, strlen(self::APPENDER_PREFIX));
287 | $renderingClass = $value;
288 |
289 | $this->config['renderers'][] = compact('renderedClass', 'renderingClass');
290 | }
291 |
292 | /** Helper method. Returns true if $str begins with $sub. */
293 | private function beginsWith($str, $sub) {
294 | return (strncmp($str, $sub, strlen($sub)) == 0);
295 | }
296 |
297 |
298 | }
299 |