1 <?php
2
3 4 5 6 7 8 9 10
11
12 namespace Icybee\Modules\Pages;
13
14 use ICanBoogie\ActiveRecord;
15 use ICanBoogie\Event;
16 use ICanBoogie\FileCache;
17 use ICanBoogie\HTTP\Dispatcher;
18 use ICanBoogie\HTTP\Request;
19 use ICanBoogie\HTTP\Response;
20
21 use Brickrouge\Element;
22
23 use Icybee\Modules\Files\File;
24 use Icybee\Modules\Sites\Site;
25
26 class Hooks
27 {
28 29 30 31 32 33
34 static public function on_http_dispatcher_alter(Dispatcher\AlterEvent $event, Dispatcher $target)
35 {
36
37
38 $target['pages'] = function(Request $request)
39 {
40 global $core;
41
42 require_once \ICanBoogie\DOCUMENT_ROOT . 'user-startup.php';
43
44 $controller = new PageController();
45 $response = $controller($request);
46
47 if (!$response)
48 {
49 return;
50 }
51
52 if (!($response instanceof Response))
53 {
54 $response = new Response($response);
55 }
56
57 $response->cache_control = 'private, no-cache, no-store, must-revalidate';
58
59 return $response;
60 };
61 }
62
63 64 65 66 67 68 69
70 static public function on_file_move(File\MoveEvent $event, File $target)
71 {
72 global $core;
73
74 $core->models['pages/contents']->execute
75 (
76 'UPDATE {self} SET content = REPLACE(content, ?, ?)', array($event->from, $event->to)
77 );
78 }
79
80 81 82 83 84 85 86 87 88 89
90 static public function on_page_move(Page\MoveEvent $event, Page $target)
91 {
92 global $core;
93
94 try
95 {
96 $model = $core->models['pages/contents'];
97 }
98 catch (\Exception $e) { return; }
99
100 $old = $event->from;
101 $new = $event->to;
102
103 if (!$old)
104 {
105 return;
106 }
107
108 foreach ($model->where('content LIKE ?', '%' . $old . '%') as $record)
109 {
110 $content = $record->content;
111 $content = preg_replace('~=\"' . preg_quote($old, '~') . '(\"|\/)~', '="' . $new . '$1', $content);
112
113 if ($content == $record->content)
114 {
115 continue;
116 }
117
118 $model->execute
119 (
120 'UPDATE {self} SET content = ? WHERE pageid = ? AND contentid = ?', array
121 (
122 $content, $record->pageid, $record->contentid
123 )
124 );
125 }
126 }
127
128 129 130 131
132 static public function invalidate_cache()
133 {
134 global $core;
135
136 $cache = new FileCache
137 (
138 array
139 (
140 FileCache::T_REPOSITORY => $core->config['repository.cache'] . '/pages'
141 )
142 );
143
144 return $cache->clear();
145 }
146
147 148 149 150 151 152 153 154 155
156 static public function get_page(\ICanBoogie\Core $core)
157 {
158 return $core->request->context->page;
159 }
160
161 162 163 164 165 166 167
168 static public function get_home(Site $site)
169 {
170 global $core;
171
172 return $core->models['pages']->find_home($site->siteid);
173 }
174
175 static public function before_document_render_title(\Icybee\Document\BeforeRenderTitleEvent $event)
176 {
177 global $core;
178
179 $page = $core->request->context->page;
180
181 $event->separator = ' − ';
182 $event->title = $page->title . $event->separator . $page->site->title;
183 }
184
185 186 187
188
189 static public function markup_page_region(array $args, \Patron\Engine $patron, $template)
190 {
191 global $core;
192
193 $id = $args['id'];
194 $page = $core->request->context->page;
195 $element = new Element('div', array('id' => $id, 'class' => "region region-$id"));
196 $html = null;
197
198 new Page\RenderRegionEvent
199 (
200 $page, array
201 (
202 'id' => $id,
203 'page' => $page,
204 'element' => $element,
205 'html' => &$html
206 )
207 );
208
209 if (!$html)
210 {
211 return;
212 }
213
214 $element[Element::INNER_HTML] = $html;
215
216 return $element;
217 }
218
219 static public function markup_page_title(array $args, $engine, $template)
220 {
221 global $core;
222
223 $page = $core->request->context->page;
224 $title = $page->title;
225 $html = \ICanBoogie\escape($title);
226
227 new Page\RenderTitleEvent($page, array('title' => $title, 'html' => &$html));
228
229 return $template ? $engine($template, $html) : $html;
230 }
231
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
268 static public function markup_page_content(array $args, \Patron\Engine $patron, $template)
269 {
270 global $core;
271
272 $render = $args['render'];
273
274 if ($render === 'none')
275 {
276 return;
277 }
278
279 $page = $core->request->context->page;
280 $contentid = $args['id'];
281 $contents = array_key_exists($contentid, $page->contents) ? $page->contents[$contentid] : null;
282
283 if (!$contents && !empty($args['inherit']))
284 {
285 $node = $page->parent;
286
287 while ($node)
288 {
289 $node_contents = $node->contents;
290
291 if (empty($node_contents[$contentid]))
292 {
293 $node = $node->parent;
294
295 continue;
296 }
297
298 $contents = $node_contents[$contentid];
299
300 break;
301 }
302
303
304
305
306
307
308 if (!$contents)
309 {
310 $node_contents = $page->home->contents;
311
312 if (isset($node_contents[$contentid]))
313 {
314 $contents = $node_contents[$contentid];
315 }
316 }
317 }
318
319 $editor = null;
320 $rendered = null;
321
322 if (is_string($contents))
323 {
324 $rendered = $contents;
325 }
326 else if ($contents)
327 {
328 $editor = $contents->editor;
329 $rendered = $contents->render();
330 }
331
332 if (!$rendered)
333 {
334 return;
335 }
336
337 $element = new Element('div', [
338
339 'id' => 'content-' . $contentid,
340 'class' => 'editor-' . \ICanBoogie\normalize($editor)
341
342 ]);
343
344 $patron->context['self']['element'] = $element;
345
346 $rc = $template ? $patron($template, $rendered) : $rendered;
347
348 if (!$rc)
349 {
350 return;
351 }
352
353 if (preg_match('#\.html$#', $page->template) && empty($args['no-wrapper']))
354 {
355 $element[Element::INNER_HTML] = $rc;
356 $rc = $element;
357 }
358
359 $rc = self::handle_external_anchors($rc);
360
361 return $rc;
362 }
363
364 365 366 367 368
369 static protected function handle_external_anchors($html)
370 {
371 return preg_replace_callback
372 (
373 '#<a\s+[^>]+>#', function($matches)
374 {
375 $str = array_shift($matches);
376
377 preg_match_all('#([a-zA-Z0-9\-]+)\="([^"]+)#', $str, $matches, 0, PREG_SET_ORDER);
378
379 if (empty($matches[1]))
380 {
381 return $str;
382 }
383
384 $attributes = array_combine($matches[1], $matches[2]);
385
386 if (isset($attributes['href']))
387 {
388 if (preg_match('#^http(s)?://#', $attributes['href']))
389 {
390 $attributes['target'] = '_blank';
391 }
392 }
393
394 $str = '<a';
395
396 foreach ($attributes as $attribute => $value)
397 {
398 $str .= ' ' . $attribute . '="' . $value . '"';
399 }
400
401 $str .= '>';
402
403 return $str;
404 },
405
406 $html
407 );
408 }
409 }
410
411 namespace Icybee\Modules\Pages\Page;
412
413 use Icybee\Modules\Pages\Page;
414
415 class RenderTitleEvent extends \ICanBoogie\Event
416 {
417 418 419 420 421
422 public $title;
423
424 425 426 427 428
429 public $html;
430
431 432 433 434 435 436
437 public function __construct(Page $target, array $payload)
438 {
439 parent::__construct($target, 'render_title', $payload);
440 }
441 }
442
443 class RenderRegionEvent extends \ICanBoogie\Event
444 {
445 446 447 448 449
450 public $id;
451
452 453 454 455 456
457 public $page;
458
459 460 461 462 463
464 public $element;
465
466 467 468 469 470
471 public $html;
472
473 474 475 476 477 478
479 public function __construct(Page $target, array $payload)
480 {
481 parent::__construct($target, 'render_region', $payload);
482 }
483 }