# THIRD-PARTY MODULES Many webtrees functions are provided by “modules”. Modules allows you to add additional features to webtrees and modify existing features. ## Installing and uninstalling modules A module is a folder containing a file called `module.php`. There may be other files in the folder, such as CSS, JS, templates, languages, data, etc. To install a module, copy its folder to `modules_v4`. To uninstall it, delete its folder from `modules_v4`. Note that module names (i.e. the folder names) must not contain spaces or the characters `.`, `[` and `]`. It must also have a maximum length of 30 characters. TIP: renaming a module from `` to `` is a quick way to hide it from webtrees. This works because modules containing `.` are ignored. ## Writing modules To write a module, you need to understand the PHP programming language. The rest of this document is aimed at PHP developers. TIP: The built-in modules can be found in `app/Module/*.php`. These contain lots of useful examples that you can copy/paste. ## Creating a custom module. This is the minimum code needed to create a custom module. ```php self::DEFAULT_GENERATIONS, 'style' => self::DEFAULT_STYLE, ]; }; ``` ## Dependency Injection webtrees uses the “Dependency Injection” pattern extensively. This is a system for automatically generating objects. The advantages over using `new SomeClass()` are * Easier testing - you can pass "dummy" objects to your class. * Run-time resolution - you can request an Interface, and webtrees will find a specific instance for you. * Can swap implementations at runtime. Note that you cannot type-hint the following objects in the constructor, as they are not created until after the modules. * other modules * interfaces, such as `UserInterface` or `LocaleInterface` (the current user and language) * the current tree `Tree` or objects that depend on it (`Statistics`) as these objects are not created until after the module is created. Instead, these objects can be obtained from the request object. e.g. ```php $tree = $request->getAttribute('tree'); $user = $request->getAttribute('user'); ``` ```php timeout_service = $timeout_service; } /** * Methods that are called in response to HTTP requests use * dependency-injection. You'll almost certainly need the request * object. * * @param ServerRequestInterface $request * * @return ResponseInterface */ public function getFooBarAction(ServerRequestInterface $request): ResponseInterface { // This assumes that there is a tree parameter in the URL. $tree = $request->getAttribute('tree'); // This will be a User (or a GuestUser for visitors). $user = $request->getAttribute('user'); $html = $tree->name() . '/' . $user->realName(); return response($html); } }; ```