]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/GNUsocialTemplatePlugin.php
Merge branch '1.0.x' of git://gitorious.org/statusnet/mainline
[quix0rs-gnu-social.git] / plugins / GNUsocialTemplatePlugin.php
1 <?php
2 /**
3  * Plugin to render GNU social
4  *
5  * Captures rendered parts from the output buffer, passes them through a template file: tpl/social.php
6  * Adds an API method at index.php/template/update which lets you overwrite the template file
7  * Requires username/password and a single POST parameter called "template"
8  * The method is disabled unless the user is #1, the first user of the system
9  *
10  * @category  Plugin
11  * @package   StatusNet
12  * @author    Brian Hendrickson <brian@megapump.com>
13  * @author    Matt Lee <mattl@cnuk.org>
14  * @copyright 2009 Megapump, Inc.
15  * @copyright 2010 Free Software Foundation, Inc.
16  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
17  * @link      http://megapump.com/
18  */
19
20 if (!defined('STATUSNET')) {
21     exit(1);
22 }
23
24 define('TEMPLATEPLUGIN_VERSION', '0.1');
25
26 class TemplatePlugin extends Plugin {
27
28   var $blocks = array();
29
30   function __construct() {
31     parent::__construct();
32   }
33
34   // capture the RouterInitialized event
35   // and connect a new API method
36   // for updating the template
37   function onRouterInitialized( $m ) {
38     $m->connect( 'template/update', array(
39       'action'      => 'template',
40     ));
41   }
42
43   // <%styles%>
44   // <%scripts%>
45   // <%search%>
46   // <%feeds%>
47   // <%description%>
48   // <%head%>
49   function onStartShowHead( $act ) {
50     $this->clear_xmlWriter($act);
51     $act->extraHead();
52     $this->blocks['head'] = $act->xw->flush();
53     $act->showStylesheets();
54     $this->blocks['styles'] = $act->xw->flush();
55     $act->showScripts();
56     $this->blocks['scripts'] = $act->xw->flush();
57     $act->showFeeds();
58     $this->blocks['feeds'] = $act->xw->flush();
59     $act->showOpenSearch();
60     $this->blocks['search'] = $act->xw->flush();
61     $act->showDescription();
62     $this->blocks['description'] = $act->xw->flush();
63     return false;
64   }
65
66   // <%bodytext%>
67   function onStartShowContentBlock( $act ) {
68     $this->clear_xmlWriter($act);
69     return true;
70   }
71   function onEndShowContentBlock( $act ) {
72     $this->blocks['bodytext'] = $act->xw->flush();
73   }
74
75   // <%localnav%>
76   function onStartShowLocalNavBlock( $act ) {
77     $this->clear_xmlWriter($act);
78     return true;
79   }
80   function onEndShowLocalNavBlock( $act ) {
81     $this->blocks['localnav'] = $act->xw->flush();
82   }
83
84   // <%export%>
85   function onStartShowExportData( $act ) {
86     $this->clear_xmlWriter($act);
87     return true;
88   }
89   function onEndShowExportData( $act ) {
90     $this->blocks['export'] = $act->xw->flush();
91   }
92
93   // <%subscriptions%>
94   // <%subscribers%>
95   // <%groups%>
96   // <%statistics%>
97   // <%cloud%>
98   // <%groupmembers%>
99   // <%groupstatistics%>
100   // <%groupcloud%>
101   // <%popular%>
102   // <%groupsbyposts%>
103   // <%featuredusers%>
104   // <%groupsbymembers%>
105   function onStartShowSections( $act ) {
106     global $action;
107     $this->clear_xmlWriter($act);
108     switch ($action) {
109       case "showstream":
110         $act->showSubscriptions();
111         $this->blocks['subscriptions'] = $act->xw->flush();
112         $act->showSubscribers();
113         $this->blocks['subscribers'] = $act->xw->flush();
114         $act->showGroups();
115         $this->blocks['groups'] = $act->xw->flush();
116         $act->showStatistics();
117         $this->blocks['statistics'] = $act->xw->flush();
118         $cloud = new PersonalTagCloudSection($act, $act->user);
119         $cloud->show();
120         $this->blocks['cloud'] = $act->xw->flush();
121         break;
122       case "showgroup":
123         $act->showMembers();
124         $this->blocks['groupmembers'] = $act->xw->flush();
125         $act->showStatistics();
126         $this->blocks['groupstatistics'] = $act->xw->flush();
127         $cloud = new GroupTagCloudSection($act, $act->group);
128         $cloud->show();
129         $this->blocks['groupcloud'] = $act->xw->flush();
130         break;
131       case "public":
132         $pop = new PopularNoticeSection($act);
133         $pop->show();
134         $this->blocks['popular'] = $act->xw->flush();
135         $gbp = new GroupsByPostsSection($act);
136         $gbp->show();
137         $this->blocks['groupsbyposts'] = $act->xw->flush();
138         $feat = new FeaturedUsersSection($act);
139         $feat->show();
140         $this->blocks['featuredusers'] = $act->xw->flush();
141         break;
142       case "groups":
143         $gbp = new GroupsByPostsSection($act);
144         $gbp->show();
145         $this->blocks['groupsbyposts'] = $act->xw->flush();
146         $gbm = new GroupsByMembersSection($act);
147         $gbm->show();
148         $this->blocks['groupsbymembers'] = $act->xw->flush();
149         break;
150     }
151     return false;
152   }
153
154   // <%logo%>
155   // <%nav%>
156   // <%notice%>
157   // <%noticeform%>
158   function onStartShowHeader( $act ) {
159     $this->clear_xmlWriter($act);
160     $act->showLogo();
161     $this->blocks['logo'] = $act->xw->flush();
162     $act->showPrimaryNav();
163     $this->blocks['nav'] = $act->xw->flush();
164     $act->showSiteNotice();
165     $this->blocks['notice'] = $act->xw->flush();
166     if (common_logged_in()) {
167         $act->showNoticeForm();
168     } else {
169         $act->showAnonymousMessage();
170     }
171     $this->blocks['noticeform'] = $act->xw->flush();
172     return false;
173   }
174
175   // <%secondarynav%>
176   // <%licenses%>
177   function onStartShowFooter( $act ) {
178     $this->clear_xmlWriter($act);
179     $act->showSecondaryNav();
180     $this->blocks['secondarynav'] = $act->xw->flush();
181     $act->showLicenses();
182     $this->blocks['licenses'] = $act->xw->flush();
183     return false;
184   }
185
186   // capture the EndHTML event
187   // and include the template
188   function onEndEndHTML($act) {
189
190     global $action, $tags;
191
192     // set the action and title values
193     $vars = array(
194       'action'=>$action,
195       'title'=>$act->title(). " - ". common_config('site', 'name')
196     );
197
198     // use the PHP template
199     // unless statusnet config:
200     //   $config['template']['mode'] = 'html';
201     if (!(common_config('template', 'mode') == 'html')) {
202       $tpl_file = $this->templateFolder() . '/social.php';
203       $tags = array_merge($vars,$this->blocks);
204       include $tpl_file;
205       return;
206     }
207
208     $tpl_file = $this->templateFolder() . '/index.html';
209
210     // read the static template
211     $output = file_get_contents( $tpl_file );
212
213     $tags = array();
214
215     // get a list of the <%tags%> in the template
216     $pattern='/<%([a-z]+)%>/';
217
218     if ( 1 <= preg_match_all( $pattern, $output, $found ))
219       $tags[] = $found;
220
221     // for each found tag, set its value from the rendered blocks
222     foreach( $tags[0][1] as $pos=>$tag ) {
223       if (isset($this->blocks[$tag]))
224         $vars[$tag] = $this->blocks[$tag];
225
226       // didn't find a block for the tag
227       elseif (!isset($vars[$tag]))
228         $vars[$tag] = '';
229     }
230
231     // replace the tags in the template
232     foreach( $vars as $key=>$val )
233       $output = str_replace( '<%'.$key.'%>', $val, $output );
234
235     echo $output;
236
237     return true;
238
239   }
240   function templateFolder() {
241     return 'tpl';
242   }
243
244   // catching the StartShowHTML event to halt the rendering
245   function onStartShowHTML( $act ) {
246     $this->clear_xmlWriter($act);
247     return true;
248   }
249
250   // clear the xmlWriter
251   function clear_xmlWriter( $act ) {
252     $act->xw->openMemory();
253     $act->xw->setIndent(true);
254   }
255
256 }
257
258 /**
259  * Action for updating the template remotely
260  *
261  * "template/update" -- a POST method that requires a single
262  * parameter "template", containing the new template code
263  *
264  * @category Plugin
265  * @package  StatusNet
266  * @author   Brian Hendrickson <brian@megapump.com>
267  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
268  * @link     http://megapump.com/
269  *
270  */
271
272 class TemplateAction extends Action
273 {
274
275   function prepare($args) {
276     parent::prepare($args);
277     return true;
278   }
279
280   function handle($args) {
281
282     parent::handle($args);
283
284     if (!isset($_SERVER['PHP_AUTH_USER'])) {
285
286       // not authenticated, show login form
287       header('WWW-Authenticate: Basic realm="StatusNet API"');
288
289       // cancelled the browser login form
290       $this->clientError(_('Authentication error!'), $code = 401);
291
292     } else {
293
294       $nick = $_SERVER['PHP_AUTH_USER'];
295       $pass = $_SERVER['PHP_AUTH_PW'];
296
297       // check username and password
298       $user = common_check_user($nick,$pass);
299
300       if ($user) {
301
302         // verify that user is admin
303         if (!($user->id == 1))
304           $this->clientError(_('Only User #1 can update the template.'), $code = 401);
305
306         // open the old template
307         $tpl_file = $this->templateFolder() . '/index.html';
308         $fp = fopen( $tpl_file, 'w+' );
309
310         // overwrite with the new template
311         fwrite($fp, $this->arg('template'));
312         fclose($fp);
313
314         header('HTTP/1.1 200 OK');
315         header('Content-type: text/plain');
316         print "Template Updated!";
317
318       } else {
319
320         // bad username and password
321         $this->clientError(_('Authentication error!'), $code = 401);
322
323       }
324
325     }
326   }
327     function onPluginVersion(&$versions)
328     {
329         $versions[] = array('name' => 'Template',
330                             'version' => TEMPLATEPLUGIN_VERSION,
331                             'author' => 'Brian Hendrickson',
332                             'homepage' => 'http://status.net/wiki/Plugin:Template',
333                             'rawdescription' =>
334                             _m('Use an HTML template for Web output.'));
335         return true;
336     }
337
338 }
339
340 /**
341  * Function for retrieving a statusnet display section
342  *
343  * requires one parameter, the name of the section
344  * section names are listed in the comments of the TemplatePlugin class
345  *
346  * @category Plugin
347  * @package  StatusNet
348  * @author   Brian Hendrickson <brian@megapump.com>
349  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
350  * @link     http://megapump.com/
351  *
352  */
353
354 function section($tagname) {
355   global $tags;
356   if (isset($tags[$tagname]))
357     return $tags[$tagname];
358 }
359