Passed
Push — main ( 4422cf...af94f1 )
by Marc
09:29 queued 01:34
created

get_widgets()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 5
rs 10
1
<?php declare(strict_types=1);
2
3
use html_go\exceptions\InternalException;
4
use html_go\i18n\I18n;
5
use html_go\indexing\IndexManager;
6
use html_go\markdown\MarkdownParser;
7
use html_go\markdown\ParsedownParser;
8
use html_go\model\Config;
9
use html_go\model\ModelFactory;
10
use html_go\templating\TemplateEngine;
11
use html_go\templating\TwigTemplateEngine;
12
13
/**
14
 * Returns an multi-dimensional array. The first level is the menu name, the
15
 * second level is an array of stdClass objects each representing a menu node.
16
 * @return array<mixed>
17
 */
18
function get_menu(): array {
19
    return get_index_manager()->getMenusIndex();
20
}
21
22
/**
23
 * Returns the page number from the query string (if there is one).
24
 * @return int Default value is one (1)
25
 */
26
function get_pagination_pagenumber(): int {
27
    $pageNum = 1;
28
    if (($page = get_query_parameter('page')) !== null && \ctype_digit($page)) {
29
        $pageNum = (int)$page;
30
    }
31
    return $pageNum;
32
}
33
34
/**
35
 * Returns a pagination page of tags.
36
 * @param int $pageNum The page number
37
 * @param int $perPage Items per page. Default is 0 (zero) which means return all
38
 * @return array<\stdClass>
39
 */
40
function get_tags(int $pageNum = 1, int $perPage = 0): array {
41
    $tags = get_index_manager()->getTagIndex();
42
    if ($perPage > 0) {
43
        $tags = \array_slice($tags, ($pageNum - 1) * $perPage, $perPage);
44
    }
45
    return get_model_list($tags);
46
}
47
48
/**
49
 * Returns a pagination page of categories.
50
 * @param int $pageNum The page number
51
 * @param int $perPage Items per page. Default is 0 (zero) which means return all
52
 * @return array<\stdClass> The resulting list of posts
53
 */
54
function get_categories(int $pageNum = 1, int $perPage = 0): array {
55
    $cats = get_index_manager()->getCategoriesIndex();
56
    if ($perPage > 0) {
57
        $cats = \array_slice($cats, ($pageNum - 1) * $perPage, $perPage);
58
    }
59
    return get_model_list($cats);
60
}
61
62
/**
63
 * Takes an array of index <code>Element</code> object and converts them to an array of
64
 * <code>stdClass</code> objects.
65
 * @param array<string, \stdClass> $indexList
66
 * @return array<\stdClass>
67
 */
68
function get_model_list(array $indexList): array {
69
    $list = [];
70
    $factory = get_model_factory();
71
    foreach ($indexList as $obj) {
72
        $list[] = $factory->createContentObject($obj);
73
    }
74
    return $list;
75
}
76
77
/**
78
 * Build and return the template context.
79
 * @param \stdClass $content
80
 * @return array<mixed>
81
 */
82
function get_template_context(\stdClass $content): array {
83
    $template = DEFAULT_TEMPLATE;
84
    if (isset($content->template)) {
85
        $template = $content->template;
86
    }
87
    return [
88
        'widgets' => get_widgets(),
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 = SINGLE_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
            case 'php':
150
                throw new InternalException("Implement template engine [$engineName]");
151
            default:
152
                throw new \InvalidArgumentException("Unsupported template engine [$engineName]");
153
        }
154
    }
155
    return $engine;
156
}
157
158
/**
159
 * Build the twig template engine.
160
 * @param string $themeName The name of the configure theme
161
 * @return TemplateEngine
162
 */
163
function build_twig_template_engine(string $themeName): TemplateEngine {
164
    $caching = false;
165
    if (get_config()->getBool(Config::KEY_TPL_CACHING)) {
166
        $caching = TEMPLATE_CACHE_ROOT;
167
    }
168
    $strict = get_config()->getBool(Config::KEY_TPL_STRICT_VARS_TWIG);
169
    $options = [
170
        'cache' => $caching,
171
        'strict_variables' => $strict
172
    ];
173
    $templateDirs = [THEMES_ROOT.DS.'twig'.DS.$themeName];
174
    return new TwigTemplateEngine($templateDirs, $options);
175
}
176
177
/**
178
 * Returns the instance of the <code>IndexManager</code>.
179
 * @return IndexManager
180
 */
181
function get_index_manager(): IndexManager {
182
    static $manager = null;
183
    if ($manager === null) {
184
        $manager = new IndexManager(APP_ROOT);
185
    }
186
    return $manager;
187
}
188
189
/**
190
 * Return the instance of the <code>Config</code>.
191
 * @return Config
192
 */
193
function get_config(): Config {
194
    static $config = null;
195
    if (empty($config)) {
196
        $config = new Config(CONFIG_ROOT);
197
    }
198
    return $config;
199
}
200
201
/**
202
 * Returns the instance of the <code>ModelFactory</code>.
203
 * @return ModelFactory
204
 */
205
function get_model_factory(): ModelFactory {
206
    static $factory = null;
207
    if (empty($factory)) {
208
        $factory = new ModelFactory(get_config(), get_markdown_parser(), get_index_manager());
209
    }
210
    return $factory;
211
}
212
213
/**
214
 * Returns the instance of the <code>MarkdownParser</code>.
215
 * @return MarkdownParser
216
 */
217
function get_markdown_parser(): MarkdownParser {
218
    static $parser = null;
219
    if (empty($parser)) {
220
        $parser = new ParsedownParser();
221
    }
222
    return $parser;
223
}
224
225
/**
226
 * Get a <code>Content</code> object (if any) associated with the given slug.
227
 * @param string $slug
228
 * @param array<\stdClass>$listing
229
 * @return \stdClass|NULL if no content was found associated with the given slug <code>null</code> is returned.
230
 */
231
function get_content_object(string $slug, array $listing = []): ?\stdClass {
232
    $manager = get_index_manager();
233
    if ($manager->elementExists($slug) === false) {
234
        return null;
235
    }
236
    $content = get_model_factory()->createContentObject($manager->getElementFromSlugIndex($slug));
237
    if (!empty($listing)) {
238
        $content->list = $listing;
239
    }
240
    $content->menus = get_menu();
241
    return $content;
242
}
243
244
/**
245
 * Returns a pagination page of posts.
246
 * @param int $pageNum The page number
247
 * @param int $perPage Items per page
248
 * @return array<\stdClass> The resulting list of posts
249
 */
250
function get_posts(int $pageNum = 1, int $perPage = 5): array {
251
    $posts = get_index_manager()->getPostsIndex();
252
    $posts = \array_slice($posts, ($pageNum - 1) * $perPage, $perPage);
253
    $list = [];
254
    $factory = get_model_factory();
255
    foreach ($posts as $post) {
256
        $list[] = $factory->createContentObject($post);
257
    }
258
    return $list;
259
}
260
261
/**
262
 * Checks if the given slug exists in the index manager (alias for <code>IndexManager::elementExists()</code>).
263
 * @param string $slug
264
 * @return bool
265
 */
266
function slug_exists(string $slug): bool {
267
    return get_index_manager()->elementExists($slug);
268
}
269
270
/**
271
 * Returns a list of widgets
272
 * @return array<mixed>
273
 */
274
function get_widgets(): array {
275
    return [
276
        'recent_posts' => get_posts(),
277
        'category_list' => get_categories(),
278
        'tag_list' => get_tags()
279
    ];
280
}
281