xref: /webtrees/app/Module/ModuleCustomTrait.php (revision 9ef73392e918bb739aaf4bae10ef7ee867ad703d)
149a243cbSGreg Roach<?php
249a243cbSGreg Roach/**
349a243cbSGreg Roach * webtrees: online genealogy
449a243cbSGreg Roach * Copyright (C) 2019 webtrees development team
549a243cbSGreg Roach * This program is free software: you can redistribute it and/or modify
649a243cbSGreg Roach * it under the terms of the GNU General Public License as published by
749a243cbSGreg Roach * the Free Software Foundation, either version 3 of the License, or
849a243cbSGreg Roach * (at your option) any later version.
949a243cbSGreg Roach * This program is distributed in the hope that it will be useful,
1049a243cbSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
1149a243cbSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1249a243cbSGreg Roach * GNU General Public License for more details.
1349a243cbSGreg Roach * You should have received a copy of the GNU General Public License
1449a243cbSGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
1549a243cbSGreg Roach */
1649a243cbSGreg Roachdeclare(strict_types=1);
1749a243cbSGreg Roach
1849a243cbSGreg Roachnamespace Fisharebest\Webtrees\Module;
1949a243cbSGreg Roach
20*9ef73392SGreg Roachuse Fisharebest\Webtrees\Carbon;
21*9ef73392SGreg Roachuse Illuminate\Support\Str;
22*9ef73392SGreg Roachuse Symfony\Component\HttpFoundation\Request;
23*9ef73392SGreg Roachuse Symfony\Component\HttpFoundation\Response;
24*9ef73392SGreg Roachuse Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
25*9ef73392SGreg Roachuse Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
26*9ef73392SGreg Roach
2749a243cbSGreg Roach/**
2849a243cbSGreg Roach * Trait ModuleCustomTrait - default implementation of ModuleCustomInterface
2949a243cbSGreg Roach */
3049a243cbSGreg Roachtrait ModuleCustomTrait
3149a243cbSGreg Roach{
3249a243cbSGreg Roach    /**
3349a243cbSGreg Roach     * The person or organisation who created this module.
3449a243cbSGreg Roach     *
3549a243cbSGreg Roach     * @return string
3649a243cbSGreg Roach     */
37cbf4b7faSGreg Roach    public function customModuleAuthorName(): string
38cbf4b7faSGreg Roach    {
39304fefbeSGreg Roach        return '';
4049a243cbSGreg Roach    }
4149a243cbSGreg Roach
4249a243cbSGreg Roach    /**
4349a243cbSGreg Roach     * The version of this module.
4449a243cbSGreg Roach     *
45304fefbeSGreg Roach     * @return string  e.g. '1.2.3'
4649a243cbSGreg Roach     */
47cbf4b7faSGreg Roach    public function customModuleVersion(): string
48cbf4b7faSGreg Roach    {
49304fefbeSGreg Roach        return '';
5049a243cbSGreg Roach    }
5149a243cbSGreg Roach
5249a243cbSGreg Roach    /**
5349a243cbSGreg Roach     * A URL that will provide the latest version of this module.
5449a243cbSGreg Roach     *
5549a243cbSGreg Roach     * @return string
5649a243cbSGreg Roach     */
57cbf4b7faSGreg Roach    public function customModuleLatestVersionUrl(): string
58cbf4b7faSGreg Roach    {
59304fefbeSGreg Roach        return '';
6049a243cbSGreg Roach    }
6149a243cbSGreg Roach
6249a243cbSGreg Roach    /**
6349a243cbSGreg Roach     * Where to get support for this module.  Perhaps a github respository?
6449a243cbSGreg Roach     *
6549a243cbSGreg Roach     * @return string
6649a243cbSGreg Roach     */
67cbf4b7faSGreg Roach    public function customModuleSupportUrl(): string
68cbf4b7faSGreg Roach    {
69304fefbeSGreg Roach        return '';
7049a243cbSGreg Roach    }
71d37db671SGreg Roach
72d37db671SGreg Roach    /**
73d37db671SGreg Roach     * Additional/updated translations.
74d37db671SGreg Roach     *
75d37db671SGreg Roach     * @param string $language
76d37db671SGreg Roach     *
77d37db671SGreg Roach     * @return string[]
78d37db671SGreg Roach     */
79d37db671SGreg Roach    public function customTranslations(string $language): array
80d37db671SGreg Roach    {
81d37db671SGreg Roach        return [];
82d37db671SGreg Roach    }
83*9ef73392SGreg Roach
84*9ef73392SGreg Roach
85*9ef73392SGreg Roach    /**
86*9ef73392SGreg Roach     * Where does this module store its resources
87*9ef73392SGreg Roach     *
88*9ef73392SGreg Roach     * @return string
89*9ef73392SGreg Roach     */
90*9ef73392SGreg Roach    public function resourceFolder(): string
91*9ef73392SGreg Roach    {
92*9ef73392SGreg Roach        return WT_ROOT . 'resources/';
93*9ef73392SGreg Roach    }
94*9ef73392SGreg Roach
95*9ef73392SGreg Roach    /**
96*9ef73392SGreg Roach     * Create a URL for an asset.
97*9ef73392SGreg Roach     *
98*9ef73392SGreg Roach     * @param string $asset e.g. "css/theme.css" or "img/banner.png"
99*9ef73392SGreg Roach     *
100*9ef73392SGreg Roach     * @return string
101*9ef73392SGreg Roach     */
102*9ef73392SGreg Roach    public function assetUrl(string $asset): string
103*9ef73392SGreg Roach    {
104*9ef73392SGreg Roach        $file = $this->resourceFolder() . $asset;
105*9ef73392SGreg Roach
106*9ef73392SGreg Roach        // Add the file's modification time to the URL, so we can set long expiry cache headers.
107*9ef73392SGreg Roach        $hash = filemtime($file);
108*9ef73392SGreg Roach
109*9ef73392SGreg Roach        return route('module', [
110*9ef73392SGreg Roach            'module' => $this->name(),
111*9ef73392SGreg Roach            'action' => 'asset',
112*9ef73392SGreg Roach            'asset'  => $asset,
113*9ef73392SGreg Roach            'hash'   => $hash,
114*9ef73392SGreg Roach        ]);
115*9ef73392SGreg Roach    }
116*9ef73392SGreg Roach
117*9ef73392SGreg Roach    /**
118*9ef73392SGreg Roach     * Serve a CSS/JS file.
119*9ef73392SGreg Roach     *
120*9ef73392SGreg Roach     * @param Request $request
121*9ef73392SGreg Roach     *
122*9ef73392SGreg Roach     * @return Response
123*9ef73392SGreg Roach     */
124*9ef73392SGreg Roach    public function getAssetAction(Request $request): Response
125*9ef73392SGreg Roach    {
126*9ef73392SGreg Roach        // The file being requested.  e.g. "css/theme.css"
127*9ef73392SGreg Roach        $asset = $request->get('asset');
128*9ef73392SGreg Roach
129*9ef73392SGreg Roach        // Do not allow requests that try to access parent folders.
130*9ef73392SGreg Roach        if (Str::contains($asset, '..')) {
131*9ef73392SGreg Roach            throw new AccessDeniedHttpException($asset);
132*9ef73392SGreg Roach        }
133*9ef73392SGreg Roach
134*9ef73392SGreg Roach        // Find the file for this asset.
135*9ef73392SGreg Roach        // Note that we could also generate CSS files using views/templates.
136*9ef73392SGreg Roach        // e.g. $file = view(....
137*9ef73392SGreg Roach        $file = $this->resourceFolder() . $asset;
138*9ef73392SGreg Roach
139*9ef73392SGreg Roach        if (!file_exists($file)) {
140*9ef73392SGreg Roach            throw new NotFoundHttpException($file);
141*9ef73392SGreg Roach        }
142*9ef73392SGreg Roach
143*9ef73392SGreg Roach        $content     = file_get_contents($file);
144*9ef73392SGreg Roach        $expiry_date = Carbon::now()->addYears(10);
145*9ef73392SGreg Roach
146*9ef73392SGreg Roach        $extension = pathinfo($asset, PATHINFO_EXTENSION);
147*9ef73392SGreg Roach
148*9ef73392SGreg Roach        $mime_types = [
149*9ef73392SGreg Roach            'css'  => 'text/css',
150*9ef73392SGreg Roach            'gif'  => 'image/gif',
151*9ef73392SGreg Roach            'js'   => 'application/javascript',
152*9ef73392SGreg Roach            'jpg'  => 'image/jpg',
153*9ef73392SGreg Roach            'jpeg' => 'image/jpg',
154*9ef73392SGreg Roach            'json' => 'application/json',
155*9ef73392SGreg Roach            'png'  => 'image/png',
156*9ef73392SGreg Roach            'txt'  => 'text/plain',
157*9ef73392SGreg Roach        ];
158*9ef73392SGreg Roach
159*9ef73392SGreg Roach        $mime_type = $mime_types[$extension] ?? 'application/octet-stream';
160*9ef73392SGreg Roach
161*9ef73392SGreg Roach        $headers = [
162*9ef73392SGreg Roach            'Content-Type' => $mime_type,
163*9ef73392SGreg Roach        ];
164*9ef73392SGreg Roach
165*9ef73392SGreg Roach        $response = new Response($content, Response::HTTP_OK, $headers);
166*9ef73392SGreg Roach
167*9ef73392SGreg Roach        return $response
168*9ef73392SGreg Roach            ->setExpires($expiry_date);
169*9ef73392SGreg Roach    }
17049a243cbSGreg Roach}
171