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
|
|||
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 |
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.