Passed
Push — main ( 9e9016...17b057 )
by Marc
04:37
created

get_template_engine()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 29
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 6
eloc 23
c 2
b 0
f 0
nc 6
nop 0
dl 0
loc 29
rs 8.9297
1
<?php declare(strict_types=1);
2
3
use Doctrine\Instantiator\Exception\InvalidArgumentException;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, InvalidArgumentException. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
4
use html_go\exceptions\InternalException;
5
use html_go\i18n\I18n;
6
use html_go\indexing\IndexManager;
7
use html_go\markdown\MarkdownParser;
8
use html_go\markdown\ParsedownParser;
9
use html_go\model\Config;
10
use html_go\model\ModelFactory;
11
use html_go\templating\TemplateEngine;
12
use html_go\templating\TwigTemplateEngine;
13
14
/**
15
 * Returns an multi-dimensional array. The first level is the menu name, the
16
 * second level is an array of stdClass objects each representing a menu node.
17
 * @return array<mixed>
18
 */
19
function get_menu(): array {
20
    return get_index_manager()->getMenusIndex();
21
}
22
23
/**
24
 * Returns the page number from the query string (if there is one).
25
 * @return int Default value is one (1)
26
 */
27
function get_pagination_pagenumber(): int {
28
    $pageNum = 1;
29
    if (($page = get_query_parameter('page')) !== null && \ctype_digit($page)) {
30
        $pageNum = (int)$page;
31
    }
32
    return $pageNum;
33
}
34
35
/**
36
 * Returns a pagination page of tags.
37
 * @param int $pageNum The page number
38
 * @param int $perPage Items per page. Default is 0 (zero) which means return all
39
 * @return array<\stdClass>
40
 */
41
function get_tags(int $pageNum = 1, int $perPage = 0): array {
42
    $tags = get_index_manager()->getTagIndex();
43
    if ($perPage > 0) {
44
        $tags = \array_slice($tags, ($pageNum - 1) * $perPage, $perPage);
45
    }
46
    return get_model_list($tags);
47
}
48
49
/**
50
 * Returns a pagination page of categories.
51
 * @param int $pageNum The page number
52
 * @param int $perPage Items per page. Default is 0 (zero) which means return all
53
 * @return array<\stdClass> The resulting list of posts
54
 */
55
function get_categories(int $pageNum = 1, int $perPage = 0): array {
56
    $cats = get_index_manager()->getCategoriesIndex();
57
    if ($perPage > 0) {
58
        $cats = \array_slice($cats, ($pageNum - 1) * $perPage, $perPage);
59
    }
60
    return get_model_list($cats);
61
}
62
63
/**
64
 * Takes an array of index <code>Element</code> object and converts them to an array of
65
 * <code>stdClass</code> objects.
66
 * @param array<string, \stdClass> $indexList
67
 * @return array<\stdClass>
68
 */
69
function get_model_list(array $indexList): array {
70
    $list = [];
71
    $factory = get_model_factory();
72
    foreach ($indexList as $obj) {
73
        $list[] = $factory->createContentObject($obj);
74
    }
75
    return $list;
76
}
77
78
/**
79
 * Build and return the template context.
80
 * @param \stdClass $content
81
 * @return array<mixed>
82
 */
83
function get_template_context(\stdClass $content): array {
84
    $template = DEFAULT_TEMPLATE;
85
    if (isset($content->template)) {
86
        $template = $content->template;
87
    }
88
    return [
89
        'i18n' => get_i18n(),
90
        'content' => $content,
91
        TEMPLATE_TPLVAR_KEY => $template
92
    ];
93
}
94
95
/**
96
 * Return the <code>i18n</code> instance.
97
 * @return I18n
98
 */
99
function get_i18n(): I18n {
100
    static $object = null;
101
    if (empty($object)) {
102
        $object = new I18n(LANG_ROOT.DS.get_config()->getString(Config::KEY_LANG).'.messages.php');
103
    }
104
    return $object;
105
}
106
107
/**
108
 * Render the given template placing the given variables into the template context.
109
 * Note: template defined in the front matter of the content file takes precendence.
110
 * @param string $template Default is <code>null</code>
111
 * @param array<mixed> $vars
112
 * @return string
113
 */
114
function render(string $template = null, array $vars = []): string {
115
    $tpl = DEFAULT_TEMPLATE;
116
    if (!empty($template)) {
117
        $tpl = $template;
118
    }
119
    // Front matter from content file takes precendence
120
    if (isset($vars[TEMPLATE_TPLVAR_KEY])) {
121
        $tpl = $vars[TEMPLATE_TPLVAR_KEY];
122
    }
123
    return get_template_engine()->render($tpl, $vars);
124
}
125
126
/**
127
 * Helper function for 404 page.
128
 * @return string
129
 */
130
function not_found(): string {
131
    return render('404.html', ['i18n' => get_i18n()]);
132
}
133
134
/**
135
 * Get the configured template engine.
136
 * @return TemplateEngine
137
 */
138
function get_template_engine(): TemplateEngine {
139
    static $engine = null;
140
    if (empty($engine)) {
141
        $themeName = get_config()->getString(Config::KEY_THEME_NAME);
142
        $engineName = get_config()->getString(Config::KEY_TPL_ENGINE);
143
144
        switch($engineName) {
145
            case 'twig':
146
                $caching = false;
147
                if (get_config()->getBool(Config::KEY_TPL_CACHING)) {
148
                    $caching = TEMPLATE_CACHE_ROOT;
149
                }
150
                $strict = get_config()->getBool(Config::KEY_TPL_STRICT_VARS_TWIG);
151
                $options = [
152
                    'cache' => $caching,
153
                    'strict_variables' => $strict
154
                ];
155
                $templateDirs = [THEMES_ROOT.DS.$engineName.DS.$themeName];
156
                $engine = new TwigTemplateEngine($templateDirs, $options);
157
                break;
158
            case 'smarty':
159
                throw new InternalException("Implement template engine [$engineName]");
160
            case 'php':
161
                throw new InternalException("Implement template engine [$engineName]");
162
            default:
163
                throw new InvalidArgumentException("Unsupported template engine [$engineName]");
164
        }
165
    }
166
    return $engine;
167
}
168
169
/**
170
 * Returns the instance of the <code>IndexManager</code>.
171
 * @return IndexManager
172
 */
173
function get_index_manager(): IndexManager {
174
    static $manager = null;
175
    if ($manager === null) {
176
        $manager = new IndexManager(APP_ROOT);
177
    }
178
    return $manager;
179
}
180
181
/**
182
 * Return the instance of the <code>Config</code>.
183
 * @return Config
184
 */
185
function get_config(): Config {
186
    static $config = null;
187
    if (empty($config)) {
188
        $config = new Config(CONFIG_ROOT);
189
    }
190
    return $config;
191
}
192
193
/**
194
 * Returns the instance of the <code>ModelFactory</code>.
195
 * @return ModelFactory
196
 */
197
function get_model_factory(): ModelFactory {
198
    static $factory = null;
199
    if (empty($factory)) {
200
        $factory = new ModelFactory(get_config(), get_markdown_parser(), get_index_manager());
201
    }
202
    return $factory;
203
}
204
205
/**
206
 * Returns the instance of the <code>MarkdownParser</code>.
207
 * @return MarkdownParser
208
 */
209
function get_markdown_parser(): MarkdownParser {
210
    static $parser = null;
211
    if (empty($parser)) {
212
        $parser = new ParsedownParser();
213
    }
214
    return $parser;
215
}
216
217
/**
218
 * Get a <code>Content</code> object (if any) associated with the given slug.
219
 * @param string $slug
220
 * @param array<\stdClass>$listing
221
 * @return \stdClass|NULL if no content was found associated with the given slug <code>null</code> is returned.
222
 */
223
function get_content_object(string $slug, array $listing = []): ?\stdClass {
224
    $manager = get_index_manager();
225
    if ($manager->elementExists($slug) === false) {
226
        return null;
227
    }
228
    $content = get_model_factory()->createContentObject($manager->getElementFromSlugIndex($slug));
229
    if (!empty($listing)) {
230
        $content->listing = $listing;
231
    }
232
    $content->menus = get_menu();
233
    return $content;
234
}
235
236
/**
237
 * Returns a pagination page of posts.
238
 * @param int $pageNum The page number
239
 * @param int $perPage Items per page
240
 * @return array<\stdClass> The resulting list of posts
241
 */
242
function get_posts(int $pageNum = 1, int $perPage = 5): array {
243
    $posts = get_index_manager()->getPostsIndex();
244
    $posts = \array_slice($posts, ($pageNum - 1) * $perPage, $perPage);
245
    $list = [];
246
    $factory = get_model_factory();
247
    foreach ($posts as $post) {
248
        $list[] = $factory->createContentObject($post);
249
    }
250
    return $list;
251
}
252
253
/**
254
 * Checks if the given slug exists in the index manager (alias for <code>IndexManager::elementExists()</code>).
255
 * @param string $slug
256
 * @return bool
257
 */
258
function slug_exists(string $slug): bool {
259
    return get_index_manager()->elementExists($slug);
260
}
261