Issues (281)

Branch: master

src/Frontend/Core/Engine/Model.php (1 issue)

1
<?php
2
3
namespace Frontend\Core\Engine;
4
5
use InvalidArgumentException;
6
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
7
8
/**
9
 * In this file we store all generic functions that we will be using in the frontend.
10
 */
11
class Model extends \Common\Core\Model
12
{
13
    /**
14
     * Visitor id from tracking cookie
15
     *
16
     * @var string|null
17
     */
18
    private static $visitorId;
19
20
    /**
21
     * Add parameters to an URL
22
     *
23
     * @param string $url The URL to append the parameters too.
24
     * @param array $parameters The parameters as key-value-pairs.
25
     * @param string $separator Defaults to &
26
     *
27
     * @return string
28
     */
29
    public static function addUrlParameters(string $url, array $parameters, string $separator = '&'): string
30
    {
31
        if (empty($parameters)) {
32
            return $url;
33
        }
34
35
        $chunks = explode('#', $url, 2);
36
        $hash = '';
37
        if (isset($chunks[1])) {
38
            $url = $chunks[0];
39
            $hash = '#' . $chunks[1];
40
        }
41
42
        // build query string
43
        $queryString = http_build_query($parameters, null, $separator, PHP_QUERY_RFC3986);
44
        if (mb_strpos($url, '?') !== false) {
45
            return $url . $separator . $queryString . $hash;
46
        }
47
48
        return $url . '?' . $queryString . $hash;
49
    }
50
51
    /**
52
     * Get plain text for a given text
53
     *
54
     * @param string $text The text to convert.
55
     * @param bool $includeAHrefs Should the url be appended after the link-text?
56
     * @param bool $includeImgAlts Should the alt tag be inserted for images?
57
     *
58
     * @return string
59
     */
60
    public static function convertToPlainText(string $text, bool $includeAHrefs = true, $includeImgAlts = true): string
61
    {
62
        // remove tabs, line feeds and carriage returns
63
        $text = str_replace(["\t", "\n", "\r"], '', $text);
64
65
        // remove the head-, style- and script-tags and all their contents
66
        $text = preg_replace('|\<head[^>]*\>(.*\n*)\</head\>|isU', '', $text);
67
        $text = preg_replace('|\<style[^>]*\>(.*\n*)\</style\>|isU', '', $text);
68
        $text = preg_replace('|\<script[^>]*\>(.*\n*)\</script\>|isU', '', $text);
69
70
        // put back some new lines where needed
71
        $text = preg_replace(
72
            '#(\<(h1|h2|h3|h4|h5|h6|p|ul|ol)[^\>]*\>.*\</(h1|h2|h3|h4|h5|h6|p|ul|ol)\>)#isU',
73
            "\n$1",
74
            $text
75
        );
76
77
        // replace br tags with newlines
78
        $text = preg_replace('#(\<br[^\>]*\>)#isU', "\n", $text);
79
80
        // replace links with the inner html of the link with the url between ()
81
        // eg.: <a href="http://site.domain.com">My site</a> => My site (http://site.domain.com)
82
        if ($includeAHrefs) {
83
            $text = preg_replace('|<a.*href="(.*)".*>(.*)</a>|isU', '$2 ($1)', $text);
84
        }
85
86
        // replace images with their alternative content
87
        // eg. <img src="path/to/the/image.jpg" alt="My image" /> => My image
88
        if ($includeImgAlts) {
89
            $text = preg_replace('|\<img[^>]*alt="(.*)".*/\>|isU', '$1', $text);
90
        }
91
92
        // decode html entities
93
        $text = html_entity_decode($text, ENT_QUOTES, 'ISO-8859-15');
94
95
        // remove space characters at the beginning and end of each line and clear lines with nothing but spaces
96
        $text = preg_replace('/^\s*|\s*$|^\s*$/m', '', $text);
97
98
        // strip tags
99
        $text = strip_tags($text, '<h1><h2><h3><h4><h5><h6><p><li>');
100
101
        // format heading, paragraphs and list items
102
        $text = preg_replace('|\<h[123456]([^\>]*)\>(.*)\</h[123456]\>|isU', "\n** $2 **\n", $text);
103
        $text = preg_replace('|\<p([^\>]*)\>(.*)\</p\>|isU', "$2\n", $text);
104
        $text = preg_replace('|\<li([^\>]*)\>\n*(.*)\n*\</li\>|isU', "- $2\n", $text);
105
106
        // replace 3 and more line breaks in a row by 2 line breaks
107
        $text = preg_replace('/\n{3,}/', "\n\n", $text);
108
109
        // use php constant for new lines
110
        $text = str_replace("\n", PHP_EOL, $text);
111
112
        // trim line breaks at the beginning and ending of the text
113
        $text = trim($text, PHP_EOL);
114
115
        // return the plain text
116
        return $text;
117
    }
118
119
    /**
120
     * Get all data for a page
121
     *
122
     * @param int $pageId The pageId wherefore the data will be retrieved.
123
     *
124
     * @return array
125
     */
126 26
    public static function getPage(int $pageId): array
127
    {
128
        // get data
129 26
        $revisionId = (int) self::getContainer()->get('database')->getVar(
130 26
            'SELECT p.revision_id
131
             FROM pages AS p
132
             WHERE p.id = ? AND p.status = ? AND p.language = ?
133
             LIMIT 1',
134 26
            [$pageId, 'active', LANGUAGE]
135
        );
136
137
        // No page found
138 26
        if ($revisionId === 0) {
139
            return [];
140
        }
141
142 26
        return self::getPageRevision($revisionId, false);
143
    }
144
145
    /**
146
     * Get a revision for a page
147
     *
148
     * @param int $revisionId The revisionID.
149
     * @param bool $allowHidden is used by the getPage method to prevent hidden records
150
     *
151
     * @return array
152
     */
153 26
    public static function getPageRevision(int $revisionId, bool $allowHidden = true): array
154
    {
155 26
        $pageRevision = (array) self::getContainer()->get('database')->getRecord(
156 26
            'SELECT p.id, p.parent_id, p.revision_id, p.template_id, p.title, p.navigation_title,
157
                 p.navigation_title_overwrite, p.data, p.hidden,
158
                 m.title AS meta_title, m.title_overwrite AS meta_title_overwrite,
159
                 m.keywords AS meta_keywords, m.keywords_overwrite AS meta_keywords_overwrite,
160
                 m.description AS meta_description, m.description_overwrite AS meta_description_overwrite,
161
                 m.custom AS meta_custom,
162
                 m.url, m.url_overwrite,
163
                 m.data AS meta_data, m.seo_follow AS meta_seo_follow, m.seo_index AS meta_seo_index,
164
                 t.path AS template_path, t.data AS template_data
165
             FROM pages AS p
166
             INNER JOIN meta AS m ON p.meta_id = m.id
167
             INNER JOIN themes_templates AS t ON p.template_id = t.id
168
             WHERE p.revision_id = ? AND p.language = ?
169
             LIMIT 1',
170 26
            [$revisionId, LANGUAGE]
171
        );
172
173 26
        if (empty($pageRevision)) {
174
            return [];
175
        }
176
177 26
        if (!$allowHidden && (int) $pageRevision['id'] !== self::ERROR_PAGE_ID && $pageRevision['hidden']) {
178
            throw new NotFoundHttpException('The requested page revision is not available');
179
        }
180
181 26
        $pageRevision = self::unserializeArrayContent($pageRevision, 'data');
182 26
        $pageRevision = self::unserializeArrayContent($pageRevision, 'meta_data');
183 26
        $pageRevision = self::unserializeArrayContent($pageRevision, 'template_data');
184 26
        $pageRevision['positions'] = self::getPositionsForRevision($pageRevision['revision_id'], $allowHidden);
185
186 26
        return $pageRevision;
187
    }
188
189
    /**
190
     * @param int $revisionId
191
     * @param bool $allowHidden
192
     *
193
     * @return array
194
     */
195 26
    private static function getPositionsForRevision(int $revisionId, bool $allowHidden = false): array
196
    {
197 26
        $positions = [];
198 26
        $where = 'pb.revision_id = ?';
199 26
        $parameters = [false, $revisionId];
200
201 26
        if (!$allowHidden) {
202 26
            $where .= ' AND p.status = ? AND pb.visible = ?';
203 26
            $parameters[] = 'active';
204 26
            $parameters[] = true;
205
        }
206
207
        // get blocks
208 26
        $blocks = (array) self::getContainer()->get('database')->getRecords(
209
            'SELECT pe.id AS extra_id, pb.html, pb.position,
210
             pe.module AS extra_module, pe.type AS extra_type, pe.action AS extra_action, pe.data AS extra_data
211
             FROM pages_blocks AS pb
212
             INNER JOIN pages AS p ON p.revision_id = pb.revision_id
213
             LEFT OUTER JOIN modules_extras AS pe ON pb.extra_id = pe.id AND pe.hidden = ?
214 26
             WHERE ' . $where . '
215
             ORDER BY pb.position, pb.sequence',
216 26
            $parameters
217
        );
218
219
        // loop blocks
220 26
        foreach ($blocks as $block) {
221 26
            $positions[$block['position']][] = self::unserializeArrayContent($block, 'data');
222
        }
223
224 26
        return $positions;
225
    }
226
227
    /**
228
     * Get the visitor's id (using a tracking cookie)
229
     * @deprecated remove this in Fork 6, this should not be part of Fork.
230
     *      It should be implemented by the developer, and respect a visitors
231
     *      privacy preferences.
232
     *
233
     * @return string
234
     */
235 26
    public static function getVisitorId(): string
236
    {
237
        // check if tracking id is fetched already
238 26
        if (self::$visitorId !== null) {
239 26
            return self::$visitorId;
240
        }
241 26
        $cookie = self::getContainer()->get('fork.cookie');
242
243
        // get/init tracking identifier
244 26
        self::$visitorId = ($cookie->has('track') && $cookie->get('track', '') !== '')
245
            ? $cookie->get('track')
246 26
            : md5(uniqid('', true) . self::getSession()->getId());
247
248 26
        if ($cookie->hasAllowedCookies() || !self::get('fork.settings')->get('Core', 'show_cookie_bar', false)) {
249 26
            $cookie->set('track', self::$visitorId, 86400 * 365);
250
        }
251
252 26
        return self::getVisitorId();
0 ignored issues
show
Deprecated Code introduced by
The function Frontend\Core\Engine\Model::getVisitorId() has been deprecated: remove this in Fork 6, this should not be part of Fork. It should be implemented by the developer, and respect a visitors privacy preferences. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

252
        return /** @scrutinizer ignore-deprecated */ self::getVisitorId();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
253
    }
254
255
    /**
256
     * General method to check if something is spam
257
     *
258
     * @param string $content The content that was submitted.
259
     * @param string $permaLink The permanent location of the entry the comment was submitted to.
260
     * @param string $author Commenter's name.
261
     * @param string $email Commenter's email address.
262
     * @param string $url Commenter's URL.
263
     * @param string $type May be blank, comment, trackback, pingback, or a made up value like "registration".
264
     *
265
     * @throws \Exception
266
     *
267
     * @return bool|string Will return a boolean, except when we can't decide the status
268
     *                          (unknown will be returned in that case)
269
     */
270
    public static function isSpam(
271
        string $content,
272
        string $permaLink,
273
        string $author = null,
274
        string $email = null,
275
        string $url = null,
276
        string $type = 'comment'
277
    ) {
278
        try {
279
            $akismet = self::getAkismet();
280
        } catch (InvalidArgumentException $invalidArgumentException) {
281
            return false;
282
        }
283
284
        // try it, to decide if the item is spam
285
        try {
286
            // check with Akismet if the item is spam
287
            return $akismet->isSpam($content, $author, $email, $url, $permaLink, $type);
288
        } catch (\Exception $e) {
289
            // in debug mode we want to see exceptions, otherwise the fallback will be triggered
290
            if (self::getContainer()->getParameter('kernel.debug')) {
291
                throw $e;
292
            }
293
294
            // return unknown status
295
            return 'unknown';
296
        }
297
    }
298
299 26
    private static function unserializeArrayContent(array $array, string $key): array
300
    {
301 26
        if (isset($array[$key]) && $array[$key] !== '') {
302 26
            $array[$key] = unserialize($array[$key], ['allowed_classes' => false]);
303
304 26
            return $array;
305
        }
306
307 26
        return $array;
308
    }
309
}
310