Passed
Push — main ( 17b057...29100e )
by Marc
10:38
created

get_template_engine()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 19
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 5
eloc 15
c 3
b 0
f 0
nc 5
nop 0
dl 0
loc 19
rs 9.4555
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
                $engine = build_twig_template_engine($themeName);
147
                break;
148
            case 'smarty':
149
                throw new InternalException("Implement template engine [$engineName]");
150
            case 'php':
151
                throw new InternalException("Implement template engine [$engineName]");
152
            default:
153
                throw new InvalidArgumentException("Unsupported template engine [$engineName]");
154
        }
155
    }
156
    return $engine;
157
}
158
159
/**
160
 * Build the twig template engine.
161
 * @param string $themeName The name of the configure theme
162
 * @return TemplateEngine
163
 */
164
function build_twig_template_engine(string $themeName): TemplateEngine {
165
    $caching = false;
166
    if (get_config()->getBool(Config::KEY_TPL_CACHING)) {
167
        $caching = TEMPLATE_CACHE_ROOT;
168
    }
169
    $strict = get_config()->getBool(Config::KEY_TPL_STRICT_VARS_TWIG);
170
    $options = [
171
        'cache' => $caching,
172
        'strict_variables' => $strict
173
    ];
174
    $templateDirs = [THEMES_ROOT.DS.'twig'.DS.$themeName];
175
    return new TwigTemplateEngine($templateDirs, $options);
176
}
177
178
/**
179
 * Returns the instance of the <code>IndexManager</code>.
180
 * @return IndexManager
181
 */
182
function get_index_manager(): IndexManager {
183
    static $manager = null;
184
    if ($manager === null) {
185
        $manager = new IndexManager(APP_ROOT);
186
    }
187
    return $manager;
188
}
189
190
/**
191
 * Return the instance of the <code>Config</code>.
192
 * @return Config
193
 */
194
function get_config(): Config {
195
    static $config = null;
196
    if (empty($config)) {
197
        $config = new Config(CONFIG_ROOT);
198
    }
199
    return $config;
200
}
201
202
/**
203
 * Returns the instance of the <code>ModelFactory</code>.
204
 * @return ModelFactory
205
 */
206
function get_model_factory(): ModelFactory {
207
    static $factory = null;
208
    if (empty($factory)) {
209
        $factory = new ModelFactory(get_config(), get_markdown_parser(), get_index_manager());
210
    }
211
    return $factory;
212
}
213
214
/**
215
 * Returns the instance of the <code>MarkdownParser</code>.
216
 * @return MarkdownParser
217
 */
218
function get_markdown_parser(): MarkdownParser {
219
    static $parser = null;
220
    if (empty($parser)) {
221
        $parser = new ParsedownParser();
222
    }
223
    return $parser;
224
}
225
226
/**
227
 * Get a <code>Content</code> object (if any) associated with the given slug.
228
 * @param string $slug
229
 * @param array<\stdClass>$listing
230
 * @return \stdClass|NULL if no content was found associated with the given slug <code>null</code> is returned.
231
 */
232
function get_content_object(string $slug, array $listing = []): ?\stdClass {
233
    $manager = get_index_manager();
234
    if ($manager->elementExists($slug) === false) {
235
        return null;
236
    }
237
    $content = get_model_factory()->createContentObject($manager->getElementFromSlugIndex($slug));
238
    if (!empty($listing)) {
239
        $content->listing = $listing;
240
    }
241
    $content->menus = get_menu();
242
    return $content;
243
}
244
245
/**
246
 * Returns a pagination page of posts.
247
 * @param int $pageNum The page number
248
 * @param int $perPage Items per page
249
 * @return array<\stdClass> The resulting list of posts
250
 */
251
function get_posts(int $pageNum = 1, int $perPage = 5): array {
252
    $posts = get_index_manager()->getPostsIndex();
253
    $posts = \array_slice($posts, ($pageNum - 1) * $perPage, $perPage);
254
    $list = [];
255
    $factory = get_model_factory();
256
    foreach ($posts as $post) {
257
        $list[] = $factory->createContentObject($post);
258
    }
259
    return $list;
260
}
261
262
/**
263
 * Checks if the given slug exists in the index manager (alias for <code>IndexManager::elementExists()</code>).
264
 * @param string $slug
265
 * @return bool
266
 */
267
function slug_exists(string $slug): bool {
268
    return get_index_manager()->elementExists($slug);
269
}
270