configuration.doxy
1 /*!
2 \page configuration Configuration
3 <div class="has-toc"></div>
4 
5 # Configuration # {#conf_main}
6 
7 Application configuration is handled by implementations of
8 \link wcmf::lib::config::Configuration `Configuration`\endlink. To use the configuration
9 throughout the application, an instance of the appropriate implementation is
10 passed to \link wcmf::lib::core::ObjectFactory `ObjectFactory`\endlink.
11 
12 The following code demonstrates how to set up and use the
13 \link wcmf::lib::config::impl::InifileConfiguration `InifileConfiguration`\endlink
14 configuration in code:
15 
16 <div class="php">
17 ```
18 $configPath = WCMF_BASE.'app/config/';
19 
20 // setup configuration
21 $configuration = new InifileConfiguration($configPath);
22 $configuration->addConfiguration('config.ini');
23 
24 // register with object factory
25 ObjectFactory::registerInstance('configuration', $configuration);
26 
27 // get a configuration value
28 $configuration = ObjectFactory::getInstance('configuration');
29 $tz = $configuration->getValue('timezone', 'application');
30 ```
31 </div>
32 
33 ## Configuration Format ## {#conf_format}
34 
35 Currently wCMF provides an implementation for using the
36 [INI file](http://en.wikipedia.org/wiki/INI_file) format.
37 \link wcmf::lib::config::impl::InifileConfiguration `InifileConfiguration`\endlink
38 handles ini files that consist of __key-value pairs__ that are grouped in __sections__:
39 
40 <div class="ini">
41 ```
42 [SectionA]
43 key1 = value1
44 key2 = value2
45 
46 [SectionB]
47 key3 = value3
48 ```
49 </div>
50 
51 @note Configuration section and key names are treated case-insensitive.
52 
53 Additionally it defines __array values__ (enclosed in curly braces) and __inclusion__
54 of additional files. Included files are defined in the `include` key of the `Config`
55 section. If a configuration section with the same name exists in both files, the
56 values are merged, whereby values in the current file override values from included files.
57 This behavior is comparable to the concept of inheritance and can be disabled by
58 adding the `__inherit` configuration key to the section and setting it to _false_.
59 
60 The following example shows how to include an array of additional configuration
61 files to separate concerns:
62 
63 <div class="ini">
64 ```
65 [Config]
66 include = {server.ini, persistence.ini, presentation.ini, security.ini}
67 ```
68 </div>
69 
70 Configuration sections from following files override identically named sections
71 from preceding files.
72 
73 @note While path values in the configuration are normally resolved relative to the
74 value of the `WCMF_BASE` constant, the included files are expected to be located
75 in the directory that is passed to the constructor of
76 \link wcmf::lib::config::impl::InifileConfiguration `InifileConfiguration`\endlink.
77 
78 The possibility to include configuration files into others is useful, if you want
79 to __separate varying parts__ from static ones to simplify the deployment process.
80 In the \ref app "default application" for example all server specific configuration
81 (e.g. database connection) are separated into a file called _server.ini_.
82 
83 ## Dependency injection ## {#conf_di}
84 
85 wCMF supports [Dependency injection](http://en.wikipedia.org/wiki/Dependency_injection)
86 through \link wcmf::lib::core::Factory `ObjectFactory`\endlink and it's
87 \link wcmf::lib::core::impl::DefaultFactory `DefaultFactory`\endlink implementation.
88 This class implements _constructor_ and _setter injection_, which means that dependencies
89 are either set through the _constructor_ or a _setter method_ of the client class
90 or a _public member variable_.
91 
92 Assembly details for client instances are defined in the application configuration
93 in special sections containing a `__class` key. The value of the key denotes the
94 class to be used to create the client instance. All other keys are tried to be
95 mapped to constructor parameters or setters/members of that class. Complex
96 dependencies of an instance are set by using the `$` notation, which refers
97 to another configuration section. If a section does not contain a `__class` key
98 it is instantiated as an associative array.
99 
100 @note Instance names are treated case-insensitive.
101 
102 The following example demonstrates the pattern by means of the
103 \link wcmf::lib::persistence::PersistenceFacade `PersistenceFacade`\endlink instance:
104 
105 <div class="ini">
106 ```
107 [PersistenceFacade]
108 __class = wcmf\lib\persistence\impl\DefaultPersistenceFacade
109 mappers = $typeMapping
110 logStrategy = $auditingLogStragegy
111 
112 [AuditingLogStragegy]
113 __class = wcmf\lib\persistence\output\impl\AuditingOutputStrategy
114 
115 [TypeMapping]
116 app.src.model.wcmf.DBSequence = $app_src_model_wcmf_DBSequenceRDBMapper
117 app.src.model.wcmf.Lock = $app_src_model_wcmf_LockRDBMapper
118 
119 [app_src_model_wcmf_DBSequenceRDBMapper]
120 __class = app\src\model\wcmf\DBSequenceRDBMapper
121 connectionParams = $database
122 
123 [app_src_model_wcmf_LockRDBMapper]
124 __class = app\src\model\wcmf\LockRDBMapper
125 connectionParams = $database
126 
127 [Database]
128 dbType = sqlite
129 dbHostName = 127.0.0.1
130 dbName = app/test-db.sq3
131 dbUserName =
132 dbPassword =
133 dbCharSet = utf8
134 
135 [EventManager]
136 __class = wcmf\lib\core\impl\DefaultEventManager
137 ```
138 </div>
139 
140 The first section defines that the instance named _PersistenceFacade_ is an object of
141 the class \link wcmf::lib::persistence::impl::DefaultPersistenceFacade `DefaultPersistenceFacade`\endlink.
142 
143 So let's have a look at the relevant code in
144 \link wcmf::lib::persistence::impl::DefaultPersistenceFacade `DefaultPersistenceFacade`\endlink:
145 
146 <div class="php">
147 ```
148 class DefaultPersistenceFacade implements PersistenceFacade {
149 
150  public function __construct(EventManager $eventManager,
151  OutputStrategy $logStrategy) {
152  ...
153  }
154 
155  public function setMappers($mappers) {
156  ...
157  }
158 }
159 ```
160 </div>
161 
162 When requested the first time, the _PersistenceFacade_ instance is created in
163 the following steps:
164 
165 1. _Constructor parameters_:
166  - <em>$eventManager</em> is not explicitly defined in the instance configuration,
167  so the factory looks it up in the configuration. Since there is a `EventManager`
168  section, it uses it to create an instance of
169  \link wcmf::lib::core::impl::DefaultEventManager `DefaultEventManager`\endlink
170  and injects it into the constructor. If there would be no section with
171  this name, the factory would use the _type hint_ and search for a class
172  called `EventManager`.
173  - <em>$logStrategy</em> is explicitly defined as an instance of
174  \link wcmf::lib::persistence::output::impl::AuditingOutputStrategy `AuditingOutputStrategy`\endlink.
175  This is an example of a complex dependency that is defined in another
176  configuration section.
177 2. _Setter injection of the remaining parameters_:
178  - The _mappers_ configuration parameter is not used in the constructor.
179  The factory searches for a _setter method_ (_setMappers_) or a public member
180  variable (<em>$mappers</em>). Since the class defines a setter method, it is used
181  to inject the dependency. The `TypeMapping` section does not contain a
182  `__class` key, which means that the _mappers_ property will be an associative
183  array. In this example it maps class names (e.g. _app.src.model.wcmf.DBSequence_)
184  to mapper instances (e.g. `DBSequenceRDBMapper`). Further sections show that
185  the _connectionParams_ property of the `DBSequenceRDBMapper` instance is set
186  to an associative array describing the database connection (section `Database`).
187 
188 The \link wcmf::lib::persistence::PersistenceFacade `PersistenceFacade`\endlink
189 instance can be retrieved by using the following code:
190 
191 <div class="php">
192 ```
193 $persistenceFacade = ObjectFactory::getInstance('persistenceFacade');
194 ```
195 </div>
196 
197 @note An exception is thrown if a constructor parameter can't be resolved. That means if a
198 constructor parameter is supposed to be optional, a default value must be provided.
199 
200 ### Shared and Non-Shared instances ### {#conf_shareddi}
201 
202 By default all instances created by \link wcmf::lib::core::ObjectFactory `ObjectFactory`\endlink
203 are _shared_ instances, which means, that they will be created on the first call
204 and only returned by succeeding calls. If you want to create a _non-shared_ instance,
205 you must use the `__shared` key in the configuration and set it to _false_.
206 
207 The following example shows the configuration of a non-shared
208 \link wcmf::lib::presentation::view::View `View`\endlink instance:
209 
210 <div class="ini">
211 ```
212 [View]
213 __class = wcmf\lib\presentation\view\impl\SmartyView
214 __shared = false
215 compileCheck = true
216 caching = false
217 cacheLifetime = 3600
218 cacheDir = app/cache/smarty/
219 ```
220 </div>
221 
222 ### Aliases ### {#conf_aliasdi}
223 
224 The same instance can be referenced using different names (_aliases_). To define
225 an alias, the `__ref` key is used. Aliases help avoiding duplicate configuration
226 sections.
227 
228 The following example shows the configuration of different caches, that actually
229 use the same configuration.
230 
231 <div class="ini">
232 ```
233 [Cache]
234 __class = wcmf\lib\io\impl\FileCache
235 cacheDir = app/cache/
236 
237 [SQLCache]
238 __ref = $cache
239 
240 [ActionKeyCache]
241 __ref = $cache
242 ```
243 </div>
244 
245 ### Circular dependencies ### {#conf_circulardi}
246 
247 Since \link wcmf::lib::core::impl::DefaultFactory `DefaultFactory`\endlink tries
248 to resolve all dependencies when constructing an instance, it might happen that
249 a dependency depends on the instance being currently constructed. This is called
250 a _circular dependency_ and would cause infinite recursion. To solve this problem
251 the dependency in question _must not_ be injected in the constructor, but in a
252 setter method or member variable. This allows the factory to construct the initial
253 instance first without requiring the child dependency. It is then available
254 when constructing the child dependency.
255 
256 ## Configuration for individual users ## {#conf_peruser}
257 
258 wCMF's user base class \link wcmf::lib::security::principal::impl::AbstractUser `AbstractUser`\endlink
259 has a persistent property `config` which is used to set an individual configuration
260 for a user. This will be loaded after the standard configuration and extends its settings.
261 If two keys have the same name the one from the user configuration overwrites the standard one.
262 Using the `RoleConfig` configuration section, you can easily assign configuration files
263 to groups:
264 
265 <div class="ini">
266 ```
267 [RoleConfig]
268 administrators = admin.ini
269 ```
270 </div>
271 
272 If a user is added to a listed role, the given configuration file will be automatically
273 assigned to it, if no individual configuration is set yet.
274 
275 ## Default application configuration ## {#conf_default_app}
276 
277 The \ref app "default application" uses some special configuration sections:
278 
279 <div class="ini">
280 ```
281 [Application]
282 title = WCMF TEST MODEL
283 color = #428BCA
284 rootTypes = {Author, Book, Publisher}
285 timezone = Europe/Berlin
286 listeners = {Search, EventListener}
287 
288 [Media]
289 uploadDir = app/public/media/
290 ```
291 </div>
292 
293 - `Application`
294  - `title` Application title
295  - `color` Color to be used in the header of the login screen
296  - `rootTypes` List of entity types to create tabs for
297  - `timezone` Application timezone
298  - `listeners` List of listeners to install (see \ref pres_listeners)
299 
300 - `Media`
301  - `uploadDir` Directory, to which media files should be uploaded
302 
303 ## PHP configuration ## {#conf_php}
304 
305 PHP configuration values can be set in the `PhpConfig` section. The `ini_set`
306 function will be called for each key value pair when initializing the
307 \link wcmf::lib::presentation::Application `Application`\endlink instance.
308 
309 ## Logging configuration ## {#conf_logging}
310 
311 Since logging is potentially required right from application startup, it is
312 usually the first service to set up - even before setting up the application
313 configuration. This implies that logging should not depend on other services,
314 especially not on the application configuration.
315 
316 wCMF provides integrations for [log4php](http://logging.apache.org/log4php/)
317 and [Monolog](https://github.com/Seldaek/monolog) through implementations
318 of the \link wcmf::lib::core::Logger `Logger`\endlink interface. The concrete
319 classes are configured using a configuration file, that is passed to the constructor.
320 An instance of the concrete class is then passed to the
321 \link wcmf::lib::core::LogManager::configure `LogManager::configure`\endlink
322 method.
323 
324 ### Monolog ### {#conf_monolog}
325 
326 To use the _log4php_ library, instantiate
327 \link wcmf::lib::core::impl::MonologFileLogger `MonologFileLogger`\endlink in the
328 following way:
329 
330 <div class="php">
331 ```
332 $logger = new MonologFileLogger('main', WCMF_BASE.'app/config/log.ini');
333 LogManager::configure($logger);
334 ```
335 </div>
336 
337 \link wcmf::lib::core::impl::MonologFileLogger `MonologFileLogger`\endlink is
338 a simple wrapper class that allows logging to files or streams. The configuration is defined
339 in the [INI file](http://en.wikipedia.org/wiki/INI_file) format using the following
340 sections and keys:
341 
342 - `Root` section defines properties valid for all loggers unless otherwise stated
343  - `level` The default log level
344  - `target` The logging target. This could be either a
345  - _directory_ (e.g. _app/log/_) for daily rotating log files or a
346  - _stream_ (e.g. _php://output_) for logging to a stream
347 - `Logger` section defines log levels for individual loggers
348  - _logger name_ (e.g. <em>wcmf\\lib\\presentation\\Application</em>) is used as
349  key and the log level (e.g. `DEBUG`) as value
350 
351 Since in wCMF each class uses it's own logger named after the class name, setting
352 up the log level for individual classes is straightforward.
353 
354 The following configuration sets the default log level to `ERROR` and the
355 log level for the
356 \link wcmf::lib::presentation::Controller `Controller`\endlink class to `DEBUG`:
357 
358 <div class="ini">
359 ```
360 [Root]
361 level = ERROR
362 target = app/log/
363 
364 [Logger]
365 wcmf\lib\presentation\Controller = DEBUG
366 ```
367 </div>
368 
369 ### log4php ### {#conf_log4php}
370 
371 To use the _log4php_ library, instantiate
372 \link wcmf::lib::core::impl::Log4phpLogger `Log4phpLogger`\endlink in the following
373 way:
374 
375 <div class="php">
376 ```
377 $logger = new Log4phpLogger('main', WCMF_BASE.'app/config/log4php.php');
378 LogManager::configure($logger);
379 ```
380 </div>
381 
382 The configuration file _log4php.php_ uses log4php's
383 [PHP configuration format](https://logging.apache.org/log4php/docs/configuration.html#PHP).
384 
385 The following configuration sets the default log level to `ERROR` and the
386 log level for the
387 \link wcmf::lib::presentation::Controller `Controller`\endlink class to `DEBUG`:
388 
389 <div class="php">
390 ```
391 return [
392  'rootLogger' => [
393  'level' => 'ERROR',
394  'appenders' => ['dailyFile', 'echo'],
395  ],
396 
397  'loggers' => [
398  'wcmf.lib.presentation.Controller' => ['level' => 'DEBUG', 'appenders' => ['dailyFile']],
399  ],
400 
401  ...
402 ];
403 ```
404 </div>
405 */