1<?php
2/**
3 * Plugin google_cal: Inserts an Google Calendar iframe
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Kite <Kite@puzzlers.org>,  Christopher Smith <chris@jalakai.co.uk>
7 * @seealso    (http://wiki.splitbrain.org/plugin:iframe)
8 */
9
10if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
12require_once(DOKU_PLUGIN.'syntax.php');
13
14/**
15 * All DokuWiki plugins to extend the parser/rendering mechanism
16 * need to inherit from this class
17 */
18class syntax_plugin_google_cal extends DokuWiki_Syntax_Plugin {
19
20	const DEFAULT_HEIGHT = "600";
21	const DEFAULT_WIDTH = "98%";
22
23	function getInfo() {
24		return array(
25			'author1' => 'Kite',
26			'email1'  => 'kite@puzzlers.org',
27			'author2' => 'Christopher Smith',
28			'email2'  => 'chris@jalakai.co.uk',
29			'date'   => '2007-05-01',
30			'name'   => 'Google Calendar Plugin',
31			'desc'   => 'Adds a Google Calendar iframe syntax: {{googlecal>name@address[width=NN,height=NN,date=YYYY-MM-DD]|alternate text}}',
32			'url'    => 'http://wiki.splitbrain.org/plugin:google_cal',
33		);
34	}
35
36	function getType() { return 'substition'; }
37	function getPType(){ return 'block'; }
38	function getSort() { return 305; }
39	function connectTo($mode) {
40		$this->Lexer->addSpecialPattern('{{googlecal>[^}]+?}}', $mode, 'plugin_google_cal');
41	}
42
43	function handle($match, $state, $pos, Doku_Handler $handler) {
44		$matches=array();
45
46		if(preg_match('/{{googlecal>([^}]+?)}}/', $match, $matches)) { // Hook for future features
47			$options = array();
48
49			// Handle the simplified style of calendar tag
50			@list($opt, $alt) = explode('|', html_entity_decode($matches[1]), 2);
51
52			$options['alt'] = isset($alt) ? trim($alt) : '';
53
54			if (preg_match('/^(.+)\[(.*)\]$/', trim($opt), $matches)) {
55				$options['url'] = htmlspecialchars($matches[1]);
56
57				$entries = explode(',', $matches[2]);
58
59				foreach ($entries as $entry) {
60					$key_value = explode('=', $entry);
61
62					$options[trim($key_value[0])] = trim($key_value[1]);
63				}
64
65				if (!preg_match('/^\d+/', $options['width'])) { // A number followed by something
66					$options['width'] = syntax_plugin_google_cal::DEFAULT_WIDTH;
67				}
68
69				if (!preg_match('/^\d+$/', $options['height'])) { // Only numbers (in px) are supported
70					$options['height'] = syntax_plugin_google_cal::DEFAULT_HEIGHT;
71				}
72
73				if (preg_match('/^(\d{4,4})-(\d{1,2})-(\d{1,2})$/', $options['date'], $matches)) { // Should be in format yyyy-mm-dd
74					$options['date'] = sprintf('%04d%02d%02d', $matches[1], $matches[2], $matches[3]);
75					$options['date'] = htmlspecialchars($options['date'] . '/' . $options['date']);
76				} else {
77					$options['date'] = null;
78				}
79			} else { // default settings
80				$options['url'] = htmlspecialchars($opt);
81				$options['width'] = syntax_plugin_google_cal::DEFAULT_WIDTH;
82				$options['height'] = syntax_plugin_google_cal::DEFAULT_HEIGHT;
83			}
84
85			if (!$this->getConf('js_ok') && substr($url,0,11) == 'javascript:') {
86				return array('error', $this->getLang('gcal_No_JS'));
87			}
88
89			return array('wiki', &$options);
90		} else {
91			return array('error', $this->getLang('gcal_Bad_iFrame'));  // this is an error
92		} // matched {{googlecal>...
93	}
94
95	function render($mode, Doku_Renderer $renderer, $data) {
96		list($style, $options) = $data;
97		if($mode == 'xhtml') {
98			// Two styles: wiki and error
99			switch($style) {
100			case 'wiki':
101				$options['frameborder'] = 0;
102
103				$renderer->doc .=
104					'<iframe src="//www.google.com/calendar/embed?src=' . $options['url'] .
105					'&height=' . $options['height'] .
106					'&title=' . $options['alt'];
107
108				if (isset($options['date'])) {
109					$renderer->doc .= '&dates=' . $options['date'];
110				}
111
112				$renderer->doc .= '"';
113
114				foreach (array('alt', 'width', 'height', 'frameborder') as $attr_name) {
115					$renderer->doc .= ' ' . $attr_name . '="' . $options[$attr_name] . '"';
116				}
117
118				$renderer->doc .= "></iframe>\n";
119				break;
120			case 'error':
121				$renderer->doc .= '<div class="error">' . $options['url'] . '</div>';
122				break;
123			default:
124				$renderer->doc .= '<div class="error">' . $this->getLang('gcal_Invalid_mode') . '</div>';
125				break;
126			}
127			return true;
128		}
129		return false;
130	}
131}
132?>
133