Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
MediaWikiTwigLoader
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 6
110
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getSource
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
20
 getCacheKey
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isFresh
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getSourceContext
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 exists
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * MediaWiki and Twig templating. It's... beautiful?
4 *
5 * -- License --
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * http://www.gnu.org/copyleft/gpl.html
20 *
21 * @file
22 */
23
24use Twig\Loader\LoaderInterface;
25
26/**
27 * Provides methods for Twig templates to integrate with MediaWiki.
28 *
29 * Twig Templates can in fact be localized! If the original file name is a.b; then this class will
30 * look for files named a.lang.b where lang is every language code in the current languages fallback
31 * list. It will also of course use the original a.b file if no localized file exists.
32 */
33class MediaWikiTwigLoader implements LoaderInterface {
34
35    /** @var string */
36    private $mTwigTemplatePath;
37
38    /** @var IContextSource */
39    private $mContext;
40
41    /**
42     * @param string $twigTemplatePath
43     * @param IContextSource $context
44     */
45    public function __construct( $twigTemplatePath, IContextSource $context ) {
46        $this->mTwigTemplatePath = $twigTemplatePath;
47        $this->mContext = $context;
48    }
49
50    /**
51     * Simple function; it returns a filesystem Twig template. The trick here is that the twig
52     * template can be localized. A localization
53     *
54     * @param string $name
55     *
56     * @return bool|mixed|string
57     * @throws MWException if the template $name can not be found
58     */
59    public function getSource( $name ) {
60        $lang = $this->mContext->getLanguage();
61
62        // This is supposedly a file in the filesystem. We want to look for the language
63        // variant first, followed by all the fallbacks, only then falling back to the original
64        // title.
65        $parts = explode( '.', $name );
66        $langVariants = [ $lang->getCode() ];
67        $langVariants = array_merge( $langVariants, $lang->getFallbackLanguages() );
68
69        $paths = [];
70        foreach ( $langVariants as $langCode ) {
71            $localParts = $parts;
72            array_splice( $localParts, -1, 0, $langCode );
73            $paths[] = $this->mTwigTemplatePath . '/' . implode( '.', $localParts );
74        }
75        $paths[] = $this->mTwigTemplatePath . '/' . $name;
76
77        // Obtain any of the files in the $paths array
78        foreach ( $paths as $path ) {
79            if ( file_exists( $path ) ) {
80                return file_get_contents( $path );
81            }
82        }
83
84        // If we're here, it means that we couldn't find an appropriate template. Throw the
85        // generic error response.
86        throw new MWException( "Twig template '$name' could not be found to load." );
87    }
88
89    /**
90     * Obtains the cache key name. Really just the name of the page with the language code appended
91     * @param string $name
92     *
93     * @return string
94     */
95    public function getCacheKey( string $name ): string {
96        return $name . '-' . $this->mContext->getLanguage()->getCode();
97    }
98
99    /**
100     * Will force a refresh after $wgTwigCacheExpiry seconds
101     * @param string $name
102     * @param int $time
103     *
104     * @return bool
105     */
106    public function isFresh( string $name, int $time ): bool {
107        global $wgTwigCacheExpiry;
108        return ( time() < ( $time + $wgTwigCacheExpiry ) );
109    }
110
111    /**
112     * @inheritDoc
113     */
114    public function getSourceContext( string $name ): \Twig\Source {
115        return new Twig\Source( $this->getSource( $name ), $name, $this->mTwigTemplatePath );
116    }
117
118    /**
119     * @inheritDoc
120     */
121    public function exists( string $name ) {
122        try {
123            $this->getSource( $name );
124        } catch ( MWException $e ) {
125            return false;
126        }
127        return true;
128    }
129}