1 <?php
2
3 4 5 6 7 8
9 class rex_article_content_base
10 {
11 public $warning;
12 public $info;
13 public $debug;
14
15 public $template_id;
16 public $template_attributes;
17
18 protected $category_id;
19 protected $article_id;
20 protected $slice_id;
21 protected $getSlice;
22 protected $mode;
23 protected $function;
24
25 protected $ctype;
26 protected $clang;
27
28 protected $eval;
29
30 protected $slice_revision;
31
32 protected $ARTICLE;
33
34 public function __construct($article_id = null, $clang = null)
35 {
36 $this->article_id = 0;
37 $this->template_id = 0;
38 $this->ctype = -1;
39 $this->slice_id = 0;
40 $this->getSlice = 0;
41
42 $this->mode = 'view';
43 $this->eval = false;
44
45 $this->slice_revision = 0;
46
47 $this->debug = false;
48
49 if ($clang !== null) {
50 $this->setCLang($clang);
51 } else {
52 $this->setClang(rex_clang::getCurrentId());
53 }
54
55
56 rex_extension::registerPoint(new rex_extension_point('ART_INIT', '', [
57 'article' => $this,
58 'article_id' => $article_id,
59 'clang' => $this->clang,
60 ]));
61
62 if ($article_id !== null) {
63 $this->setArticleId($article_id);
64 }
65 }
66
67 protected function getSqlInstance()
68 {
69 if (!is_object($this->ARTICLE)) {
70 $this->ARTICLE = rex_sql::factory();
71 if ($this->debug) {
72 $this->ARTICLE->setDebug();
73 }
74 }
75 return $this->ARTICLE;
76 }
77
78 public function setSliceRevision($sr)
79 {
80 $this->slice_revision = (int) $sr;
81 }
82
83
84 public function setSliceId($value)
85 {
86 $this->slice_id = $value;
87 }
88
89 public function setClang($value)
90 {
91 if (!rex_clang::exists($value)) {
92 $value = rex_clang::getCurrentId();
93 }
94 $this->clang = $value;
95 }
96
97 public function getArticleId()
98 {
99 return $this->article_id;
100 }
101
102 public function getClangId()
103 {
104 return $this->clang;
105 }
106
107 108 109
110 public function getClang()
111 {
112 return $this->clang;
113 }
114
115 public function setArticleId($article_id)
116 {
117 $article_id = (int) $article_id;
118 $this->article_id = $article_id;
119
120
121 $sql = $this->getSqlInstance();
122 $sql->setQuery('SELECT * FROM ' . rex::getTablePrefix() . 'article WHERE ' . rex::getTablePrefix() . 'article.id=? AND clang_id=?', [$article_id, $this->clang]);
123
124 if ($sql->getRows() == 1) {
125 $this->template_id = $this->getValue('template_id');
126 $this->category_id = $this->getValue('category_id');
127 return true;
128 }
129
130 $this->article_id = 0;
131 $this->template_id = 0;
132 $this->category_id = 0;
133 return false;
134 }
135
136 public function setTemplateId($template_id)
137 {
138 $this->template_id = $template_id;
139 }
140
141 public function getTemplateId()
142 {
143 return $this->template_id;
144 }
145
146 public function setMode($mode)
147 {
148 $this->mode = $mode;
149 }
150
151 public function setFunction($function)
152 {
153 $this->function = $function;
154 }
155
156 public function setEval($value)
157 {
158 if ($value) {
159 $this->eval = true;
160 } else {
161 $this->eval = false;
162 }
163 }
164
165 protected function correctValue($value)
166 {
167 if ($value == 'category_id') {
168 if ($this->getValue('startarticle') != 1) {
169 $value = 'parent_id';
170 } else {
171 $value = 'id';
172 }
173 } elseif ($value == 'article_id') {
174 $value = 'id';
175 }
176
177 return $value;
178 }
179
180 protected function _getValue($value)
181 {
182 $value = $this->correctValue($value);
183
184 return $this->getSqlInstance()->getValue($value);
185 }
186
187 public function getValue($value)
188 {
189
190
191
192 foreach (['', 'art_', 'cat_'] as $prefix) {
193 $val = $prefix . $value;
194 if ($this->hasValue($val)) {
195 return $this->_getValue($val);
196 }
197 }
198 return '[' . $value . ' not found]';
199 }
200
201 public function hasValue($value)
202 {
203 return $this->getSqlInstance()->hasValue($this->correctValue($value));
204 }
205
206 207 208 209 210 211 212 213
214 protected function outputSlice(rex_sql $artDataSql, $moduleIdToAdd)
215 {
216 $output = rex_extension::registerPoint(new rex_extension_point(
217 'SLICE_OUTPUT',
218 $artDataSql->getValue(rex::getTablePrefix() . 'module.output'),
219 [
220 'article_id' => $this->article_id,
221 'clang' => $this->clang,
222 'slice_data' => $artDataSql,
223 ]
224 ));
225 $output = $this->replaceVars($artDataSql, $output);
226
227 return $this->getStreamOutput('module/' . $artDataSql->getValue(rex::getTablePrefix() . 'module.id') . '/output', $output);
228 }
229
230 231 232 233 234 235 236
237 public function getSlice($sliceId)
238 {
239 $oldEval = $this->eval;
240 $this->setEval(true);
241
242 $this->getSlice = $sliceId;
243 $sliceContent = $this->getArticle();
244 $this->getSlice = 0;
245
246 $this->setEval($oldEval);
247 return $this->replaceLinks($sliceContent);
248 }
249
250 251 252 253 254 255 256
257 public function getArticle($curctype = -1)
258 {
259 $this->ctype = $curctype;
260
261 if ($this->article_id == 0 && $this->getSlice == 0) {
262 return rex_i18n::msg('no_article_available');
263 }
264
265 $articleLimit = '';
266 if ($this->article_id != 0) {
267 $articleLimit = ' AND ' . rex::getTablePrefix() . 'article_slice.article_id=' . (int) $this->article_id;
268 }
269
270 $sliceLimit = '';
271 if ($this->getSlice != 0) {
272 $sliceLimit = ' AND ' . rex::getTablePrefix() . "article_slice.id = '" . ((int) $this->getSlice) . "' ";
273 }
274
275
276 ob_start();
277 ob_implicit_flush(0);
278 $module_id = rex_request('module_id', 'int');
279
280
281 $query = 'SELECT ' . rex::getTablePrefix() . 'module.id, ' . rex::getTablePrefix() . 'module.name, ' . rex::getTablePrefix() . 'module.output, ' . rex::getTablePrefix() . 'module.input, ' . rex::getTablePrefix() . 'article_slice.*, ' . rex::getTablePrefix() . 'article.parent_id
282 FROM
283 ' . rex::getTablePrefix() . 'article_slice
284 LEFT JOIN ' . rex::getTablePrefix() . 'module ON ' . rex::getTablePrefix() . 'article_slice.module_id=' . rex::getTablePrefix() . 'module.id
285 LEFT JOIN ' . rex::getTablePrefix() . 'article ON ' . rex::getTablePrefix() . 'article_slice.article_id=' . rex::getTablePrefix() . 'article.id
286 WHERE
287 ' . rex::getTablePrefix() . "article_slice.clang_id='" . $this->clang . "' AND
288 " . rex::getTablePrefix() . "article.clang_id='" . $this->clang . "' AND
289 " . rex::getTablePrefix() . "article_slice.revision='" . $this->slice_revision . "'
290 " . $articleLimit . '
291 ' . $sliceLimit . '
292 ORDER BY ' . rex::getTablePrefix() . 'article_slice.priority';
293
294 $query = rex_extension::registerPoint(new rex_extension_point(
295 'ART_SLICES_QUERY',
296 $query,
297 ['article' => $this]
298 ));
299
300 $artDataSql = rex_sql::factory();
301 $artDataSql->setDebug($this->debug);
302 $artDataSql->setQuery($query);
303
304
305 $articleContent = '';
306 $articleContent = $this->preArticle($articleContent, $module_id);
307
308
309
310 $prevCtype = null;
311 $artDataSql->reset();
312 $rows = $artDataSql->getRows();
313 for ($i = 0; $i < $rows; ++$i) {
314 $sliceId = $artDataSql->getValue(rex::getTablePrefix() . 'article_slice.id');
315 $sliceCtypeId = $artDataSql->getValue(rex::getTablePrefix() . 'article_slice.ctype_id');
316 $sliceModuleId = $artDataSql->getValue(rex::getTablePrefix() . 'module.id');
317
318
319 if ($this->mode != 'edit' && !$this->eval) {
320 if (0 == $i) {
321 $articleContent = "<?php if (\$this->ctype == '" . $sliceCtypeId . "' || (\$this->ctype == '-1')) { \n";
322 } elseif (isset($prevCtype) && $sliceCtypeId != $prevCtype) {
323
324 $articleContent .= "\n } if(\$this->ctype == '" . $sliceCtypeId . "' || \$this->ctype == '-1'){ \n";
325 }
326 }
327
328
329 $slice_content = $this->outputSlice(
330 $artDataSql,
331 $module_id
332 );
333
334
335
336 $slice_content = rex_extension::registerPoint(new rex_extension_point(
337 'SLICE_SHOW',
338 $slice_content,
339 [
340 'article_id' => $this->article_id,
341 'clang' => $this->clang,
342 'ctype' => $sliceCtypeId,
343 'module_id' => $sliceModuleId,
344 'slice_id' => $sliceId,
345 'function' => $this->function,
346 'function_slice_id' => $this->slice_id,
347 'sql' => $artDataSql,
348 ]
349 ));
350
351
352 if ($this->ctype == -1 || $this->ctype == $sliceCtypeId) {
353 $articleContent .= $slice_content;
354 }
355
356 $prevCtype = $sliceCtypeId;
357
358 $artDataSql->flushValues();
359 $artDataSql->next();
360 }
361
362
363 if ($this->mode != 'edit' && !$this->eval && $i > 0) {
364 $articleContent .= "\n } ?>";
365 }
366
367
368 $articleContent = $this->postArticle($articleContent, $module_id);
369
370
371 echo $articleContent;
372
373
374 $CONTENT = ob_get_clean();
375
376 return $CONTENT;
377 }
378
379 380 381 382 383 384 385 386
387 protected function preArticle($articleContent, $module_id)
388 {
389
390 return $articleContent;
391 }
392
393 394 395 396 397 398 399 400
401 protected function postArticle($articleContent, $module_id)
402 {
403
404 return $articleContent;
405 }
406
407
408 public function getArticleTemplate()
409 {
410 if ($this->template_id != 0 && $this->article_id != 0) {
411 ob_start();
412 ob_implicit_flush(0);
413
414 $TEMPLATE = new rex_template($this->template_id);
415 $tplContent = $this->replaceCommonVars($TEMPLATE->getTemplate());
416 require rex_stream::factory('template/' . $this->template_id, $tplContent);
417
418 $CONTENT = ob_get_clean();
419
420 $CONTENT = $this->replaceLinks($CONTENT);
421 } else {
422 $CONTENT = 'no template';
423 }
424
425 return $CONTENT;
426 }
427
428 protected function getStreamOutput($path, $content)
429 {
430 if (!$this->eval) {
431 $key = 'EOD_' . strtoupper(sha1(time()));
432 return "require rex_stream::factory('$path', \n<<<'$key'\n$content\n$key\n);\n";
433 }
434
435 ob_start();
436 ob_implicit_flush(0);
437
438 $__stream = rex_stream::factory($path, $content);
439
440 $sandbox = function () use ($__stream) {
441 require $__stream;
442 };
443 $sandbox();
444
445 $CONTENT = ob_get_clean();
446
447 return $CONTENT;
448 }
449
450
451 protected function replaceVars(rex_sql $sql, $content)
452 {
453 $content = $this->replaceCommonVars($content);
454 $content = $this->replaceObjectVars($sql, $content);
455 $content = str_replace(
456 [
457 'REX_MODULE_ID',
458 'REX_SLICE_ID',
459 'REX_CTYPE_ID',
460 ],
461 [
462 (int) $sql->getValue('module_id'),
463 (int) $sql->getValue(rex::getTable('article_slice') . '.id'),
464 (int) $sql->getValue('ctype_id'),
465 ],
466 $content
467 );
468 return $content;
469 }
470
471
472 protected function replaceObjectVars(rex_sql $sql, $content)
473 {
474 $sliceId = $sql->getValue(rex::getTablePrefix() . 'article_slice.id');
475
476 if ($this->mode == 'edit') {
477 $env = rex_var::ENV_BACKEND;
478 if (($this->function == 'add' && $sliceId == null) || ($this->function == 'edit' && $sliceId == $this->slice_id)) {
479 $env = $env | rex_var::ENV_INPUT;
480 }
481 } else {
482 $env = rex_var::ENV_FRONTEND;
483 }
484 $content = rex_var::parse($content, $env, 'module', $sql);
485
486 return $content;
487 }
488
489
490 public function replaceCommonVars($content, $template_id = null)
491 {
492 static $user_id = null;
493 static $user_login = null;
494
495
496 if ($user_id === null) {
497 if (rex::getUser()) {
498 $user_id = rex::getUser()->getId();
499 $user_login = rex::getUser()->getLogin();
500 } else {
501 $user_id = '';
502 $user_login = '';
503 }
504 }
505
506 if (!$template_id) {
507 $template_id = $this->getTemplateId();
508 }
509
510 static $search = [
511 'REX_ARTICLE_ID',
512 'REX_CATEGORY_ID',
513 'REX_CLANG_ID',
514 'REX_TEMPLATE_ID',
515 'REX_USER_ID',
516 'REX_USER_LOGIN',
517 ];
518
519 $replace = [
520 $this->article_id,
521 $this->category_id,
522 $this->clang,
523 $template_id,
524 $user_id,
525 $user_login,
526 ];
527
528 return str_replace($search, $replace, $content);
529 }
530
531 protected function replaceLinks($content)
532 {
533 return preg_replace_callback(
534 '@redaxo://(\d+)(?:-(\d+))?/?@i',
535 function ($matches) {
536 return rex_getUrl($matches[1], isset($matches[2]) ? $matches[2] : (int) $this->clang);
537 },
538 $content
539 );
540 }
541 }
542